Skip to content

Commit 79588b7

Browse files
authored
Merge branch 'main' into feature/lua-format-id
2 parents fea10ef + bff4e40 commit 79588b7

152 files changed

Lines changed: 6561 additions & 3912 deletions

File tree

Some content is hidden

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

.github/workflows/test-smokes.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ jobs:
235235
readarray -t my_array < <(echo '${{ inputs.buckets }}' | jq -rc '.[]')
236236
for file in "${my_array[@]}"; do
237237
echo ">>> ./run-tests.sh ${file}"
238-
./run-tests.sh $file
238+
shopt -s globstar && ./run-tests.sh $file
239239
status=$?
240240
[ $status -eq 0 ] && echo ">>> No error in this test file" || haserror=1
241241
done

news/changelog-1.8.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ All changes included in 1.8:
2020
- ([#726](https://github.com/quarto-dev/quarto-cli/issues/726)): a11y - Provide `.screen-reader-only` callout type when callout text doesn't naturally include the type.
2121
- ([#5538](https://github.com/quarto-dev/quarto-cli/issues/5538)): Fix code-copy button style so that scrolling behaves properly.
2222
- ([#5879](https://github.com/quarto-dev/quarto-cli/issues/5879)): Improve font rendering of `kbd` shortcode on macOS. `kbd` will now also be stricter in converting keyboard shortcuts to macOS icons.
23+
- ([#8568](https://github.com/quarto-dev/quarto-cli/issues/8568)) Default inline code background color to the code block background color if not specified; foreground color is `$pre-color` in dark mode and (remains) purple in light mode.
2324
- ([#10983](https://github.com/quarto-dev/quarto-cli/issues/10983)): Fix spacing inconsistency between paras and first section headings.
2425
- ([#12259](https://github.com/quarto-dev/quarto-cli/issues/12259)): Fix conflict between `html-math-method: katex` and crossref popups (author: @benkeks).
2526
- ([#12341](https://github.com/quarto-dev/quarto-cli/issues/12341)): Enable light and dark logos for html formats (sidebar, navbar, dashboard).
27+
- ([#12643](https://github.com/quarto-dev/quarto-cli/issues/12643)): Ensure brand.yml logos using urls are rendered correctly by passing them through when resolving brand `processedData`, and not processing them as paths.
2628
- ([#12734](https://github.com/quarto-dev/quarto-cli/issues/12734)): `highlight-style` now correctly supports setting a different `light` and `dark`.
2729
- ([#12747](https://github.com/quarto-dev/quarto-cli/issues/12747)): Ensure `th` elements are properly restored when Quarto's HTML table processing is happening.
2830
- ([#12766](https://github.com/quarto-dev/quarto-cli/issues/12766)): Use consistent equation numbering display for `html-math-method` and `html-math-method.method` for MathJax and KaTeX (author: @mcanouil)
@@ -33,19 +35,25 @@ All changes included in 1.8:
3335

3436
### `revealjs`
3537

38+
- ([#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.
39+
- ([#12550](https://github.com/quarto-dev/quarto-cli/issues/12550)): Revealjs supports `brand-mode`, allowing to select either the light or the dark brand.
3640
- ([#12598](https://github.com/quarto-dev/quarto-cli/pull/12598)): Ensure `.fragment` on an image with caption applies to whole figure.
3741
- ([#12716](https://github.com/quarto-dev/quarto-cli/issues/12716)): Correctly resolve `"brand"` set in `theme` configuration for document in subdirectory from project root.
42+
- 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.
3843

3944
### `docx`
4045

4146
- ([#8392](https://github.com/quarto-dev/quarto-cli/issues/8392)): Fix `docx` generation issues in tables
4247

4348
### `typst`
4449

50+
- ([#12180](https://github.com/quarto-dev/quarto-cli/issues/12180)): Typst schema / autocomplete for `logo` option has `path` and `alt`.
4551
- ([#12554](https://github.com/quarto-dev/quarto-cli/pull/12554)): CSS properties `font-weight` and `font-style` are translated to Typst `text` properties.
4652
- ([#12695](https://github.com/quarto-dev/quarto-cli/issues/12695)): Resolve Typst `font-paths` that start with `/` relative to project root.
4753
- ([#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.
4854
- ([#12815](https://github.com/quarto-dev/quarto-cli/issues/12815)): Do not crash when floats have no content.
55+
- ([#13119](https://github.com/quarto-dev/quarto-cli/pull/13119)): Expose `brand.logo` metadata as Typst dictionaries.
56+
- ([#13133](https://github.com/quarto-dev/quarto-cli/pull/13133)): Allow customization of light and dark logos at document level, consistent with other formats.
4957

5058
### `beamer`
5159

@@ -68,12 +76,14 @@ All changes included in 1.8:
6876

6977
- ([#12615](https://github.com/quarto-dev/quarto-cli/pull/12615)): Adds `algorithm` to theorem environments. (author: @jeremy9959)
7078

71-
## Lua Filters
79+
## Lua Filters and API
7280

7381
- ([#12727](https://github.com/quarto-dev/quarto-cli/issues/12727)): Do not crash in the presence of malformed tabset contents.
7482
- ([#12806](https://github.com/quarto-dev/quarto-cli/pull/12806)): Use pandoc APIs to handle codepage conversion on Windows.
7583
- ([#12811](https://github.com/quarto-dev/quarto-cli/pull/12811)): Add support for YouTube Shorts in `video` shortcode.
7684
- ([#13112](https://github.com/quarto-dev/quarto-cli/pull/13112)): Add `quarto.format.format_identifier()` API entry.
85+
- ([#13128](https://github.com/quarto-dev/quarto-cli/issues/13128)): Avoid meta shortcode crash on bad input.
86+
- ([#13246](https://github.com/quarto-dev/quarto-cli/pull/13246)): Add `quarto.variables.get()` and `quarto.metadata.get()` APIs.
7787

7888
## Commands
7989

@@ -89,13 +99,19 @@ All changes included in 1.8:
8999

90100
- ([#12965](https://github.com/quarto-dev/quarto-cli/issues/12965)): Prevent automatic opening of new editor sessions when creating projects in Posit Workbench context. The `--open` flag is now ignored in this environment to avoid issues with Workbench session management.
91101

102+
## Extensions
103+
104+
- ([#12559](https://github.com/quarto-dev/quarto-cli/issues/12559)): New extension type: `brand` for distributing [brand.yml](https://posit-dev.github.io/brand-yml/) configurations with associated assets.
105+
92106
## Engines
93107

108+
- ([#13171](https://github.com/quarto-dev/quarto-cli/pull/13171/)): Provide execution information to all engines uniformly via QUARTO_EXECUTE_INFO environment variable. It points to a file on disk containing a JSON object describing the execution environment for code cells to use.
109+
94110
### `jupyter`
95111

96112
- ([#12753](https://github.com/quarto-dev/quarto-cli/issues/12753)): Support change in IPython 9+ and import `set_matplotlib_formats` from `matplotlib_inline.backend_inline` in the internal `setup.py` script used to initialize rendering with Jupyter engine.
97113
- ([#12839](https://github.com/quarto-dev/quarto-cli/issues/12839)): Support for `plotly.py` 6+ which now loads plotly.js using a cdn in script as a module.
98-
- ([#13026](https://github.com/quarto-dev/quarto-cli/pulls/13026)): Use `jsdelivr` CDN for jupyter widgets dependencies.
114+
- ([#13026](https://github.com/quarto-dev/quarto-cli/pull/13026), [#13151](https://github.com/quarto-dev/quarto-cli/pull/13151)), [#13184](https://github.com/quarto-dev/quarto-cli/pull/13184): Use `jsdelivr` CDN for jupyter widgets dependencies.
99115

100116
### `knitr`
101117

@@ -105,9 +121,18 @@ All changes included in 1.8:
105121

106122
- ([#12870](https://github.com/quarto-dev/quarto-cli/pull/12870)): Update `julia` engine from `0.17.0` to `0.17.3` to improve `juliaup` detection on Windows systems and correctly set `Base.source_path()` output to match REPL and script usage.
107123

124+
## Languages
125+
126+
- ([#13098](https://github.com/quarto-dev/quarto-cli/pull/13098)): Fox a minor inappropriate phrasing in the Chinese localization of `environment-proof-title` (@sun123xyz).
127+
108128
## Other fixes and improvements
109129

110130
- ([#11321](https://github.com/quarto-dev/quarto-cli/issues/11321)): Follow [recommendation from LaTeX project](https://latex-project.org/news/latex2e-news/ltnews40.pdf) and use `lualatex` instead of `xelatex` as the default PDF engine.
111131
- ([#12782](https://github.com/quarto-dev/quarto-cli/pull/12782)): fix bug on `safeRemoveDirSync`'s detection of safe directory boundaries.
112132
- ([#12853](https://github.com/quarto-dev/quarto-cli/issues/12853)): fix replaceAll() escaping issue with embedded notebooks containing `$` in their Markdown.
113133
- ([#12939](https://github.com/quarto-dev/quarto-cli/pull/12939)): Upgrade `mermaidjs` to 11.6.0.
134+
- ([#13164](https://github.com/quarto-dev/quarto-cli/pull/13164)): add `julia` to execute schema to allow autocomplete suggestions. (@mcanouil)
135+
136+
## Quarto Internals
137+
138+
- ([#13155](https://github.com/quarto-dev/quarto-cli/pull/13155)): Process `pandoc-reader-FORMAT` raw blocks through `pandoc.read(FORMAT)`

src/command/create/artifacts/extension.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const kExtensionTypes: Array<string | ExtensionType> = [
4141
{ name: "journal format", value: "journal", openfiles: ["template.qmd"] },
4242
{ name: "custom format", value: "format", openfiles: ["template.qmd"] },
4343
{ name: "metadata", value: "metadata", openfiles: [] },
44+
{ name: "brand", value: "brand", openfiles: [] },
4445
];
4546

4647
const kExtensionSubtypes: Record<string, string[]> = {

src/command/render/project.ts

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
} from "../../deno_ral/fs.ts";
1515
import { dirname, isAbsolute, join, relative } from "../../deno_ral/path.ts";
1616
import { info, warning } from "../../deno_ral/log.ts";
17-
import { mergeProjectMetadata } from "../../config/metadata.ts";
1817

1918
import * as colors from "fmt/colors";
2019

@@ -80,7 +79,6 @@ import { Format } from "../../config/types.ts";
8079
import { fileExecutionEngine } from "../../execute/engine.ts";
8180
import { projectContextForDirectory } from "../../project/project-context.ts";
8281
import { ProjectType } from "../../project/types/types.ts";
83-
import { Zod } from "../../resources/types/zod/schema-types.ts";
8482

8583
const noMutationValidations = (
8684
projType: ProjectType,
@@ -242,37 +240,11 @@ const getProjectRenderScripts = async (
242240
return { preRenderScripts, postRenderScripts };
243241
};
244242

245-
const mergeExtensionMetadata = async (
246-
context: ProjectContext,
247-
pOptions: RenderOptions,
248-
) => {
249-
// this will mutate context.config.project to merge
250-
// in any project metadata from extensions
251-
if (context.config) {
252-
const extensions = await pOptions.services.extension.extensions(
253-
undefined,
254-
context.config,
255-
context.isSingleFile ? undefined : context.dir,
256-
{ builtIn: false },
257-
);
258-
const projectMetadata = extensions.filter((extension) =>
259-
extension.contributes.metadata?.project
260-
).map((extension) => {
261-
return Zod.ProjectConfig.parse(extension.contributes.metadata!.project);
262-
});
263-
context.config.project = mergeProjectMetadata(
264-
context.config.project,
265-
...projectMetadata,
266-
);
267-
}
268-
};
269-
270243
export async function renderProject(
271244
context: ProjectContext,
272245
pOptions: RenderOptions,
273246
pFiles?: string[],
274247
): Promise<RenderResult> {
275-
await mergeExtensionMetadata(context, pOptions);
276248
const { preRenderScripts, postRenderScripts } = await getProjectRenderScripts(
277249
context,
278250
);

src/core/brand/brand.ts

Lines changed: 80 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
BrandColorLightDark,
1111
BrandFont,
1212
BrandLogoExplicitResource,
13+
BrandLogoResource,
1314
BrandLogoSingle,
1415
BrandLogoUnified,
1516
BrandNamedLogo,
@@ -31,7 +32,12 @@ import { InternalError } from "../lib/error.ts";
3132
import { join, relative } from "../../deno_ral/path.ts";
3233
import { warnOnce } from "../log.ts";
3334
import { isCssColorName } from "../css/color-names.ts";
34-
import { assert } from "testing/asserts";
35+
import {
36+
LogoLightDarkSpecifierPathOptional,
37+
LogoOptionsPathOptional,
38+
LogoSpecifier,
39+
LogoSpecifierPathOptional,
40+
} from "../../resources/types/schema-types.ts";
3541

3642
type ProcessedBrandData = {
3743
color: Record<string, string>;
@@ -143,11 +149,7 @@ export class Brand {
143149
}
144150
}
145151
for (const [key, value] of Object.entries(data.logo?.images ?? {})) {
146-
if (typeof value === "string") {
147-
logo.images[key] = { path: value };
148-
} else {
149-
logo.images[key] = value;
150-
}
152+
logo.images[key] = this.resolvePath(value);
151153
}
152154

153155
return {
@@ -240,21 +242,26 @@ export class Brand {
240242
return fonts ?? [];
241243
}
242244

243-
getLogoResource(name: string): BrandLogoExplicitResource {
244-
const entry = this.data.logo?.images?.[name];
245-
if (!entry) {
246-
return { path: name };
247-
}
245+
resolvePath(entry: BrandLogoResource) {
248246
const pathPrefix = relative(this.projectDir, this.brandDir);
249247
if (typeof entry === "string") {
250-
return { path: join(pathPrefix, entry) };
248+
return { path: isExternalPath(entry) ? entry : join(pathPrefix, entry) };
251249
}
252250
return {
253251
...entry,
254-
path: join(pathPrefix, entry.path),
252+
path: isExternalPath(entry.path)
253+
? entry.path
254+
: join(pathPrefix, entry.path),
255255
};
256256
}
257257

258+
getLogoResource(name: string): BrandLogoExplicitResource {
259+
const entry = this.data.logo?.images?.[name];
260+
if (!entry) {
261+
return { path: name };
262+
}
263+
return this.resolvePath(entry);
264+
}
258265
getLogo(name: BrandNamedLogo): BrandLogoExplicitResource | undefined {
259266
const entry = this.data.logo?.[name];
260267
if (!entry) {
@@ -264,6 +271,10 @@ export class Brand {
264271
}
265272
}
266273

274+
function isExternalPath(path: string) {
275+
return /^\w+:/.test(path);
276+
}
277+
267278
export type LightDarkBrand = {
268279
light?: Brand;
269280
dark?: Brand;
@@ -379,6 +390,62 @@ export function resolveLogo(
379390
};
380391
}
381392

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

src/core/jupyter/widgets.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export function includesForJupyterWidgetDependencies(
101101
const head: string[] = [];
102102
if (haveJavascriptWidgets || haveJupyterWidgets) {
103103
head.push(
104-
'<script src="https://cdn.jsdelivr.net/npm/[email protected]/require.min.js" integrity="sha384-c9c+LnTbwQ3aujuU7ULEPVvgLs+Fn6fJUvIGTsuu1ZcCf11fiEubah0ttpca4ntM" crossorigin="anonymous"></script>',
104+
'<script src="https://cdn.jsdelivr.net/npm/[email protected]/require.min.js" integrity="sha384-c9c+LnTbwQ3aujuU7ULEPVvgLs+Fn6fJUvIGTsuu1ZcCf11fiEubah0ttpca4ntM sha384-6V1/AdqZRWk1KAlWbKBlGhN7VG4iE/yAZcO6NZPMF8od0vukrvr0tg4qY6NSrItx" crossorigin="anonymous"></script>',
105105
);
106106
head.push(
107107
'<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js" integrity="sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2" crossorigin="anonymous" data-relocate-top="true"></script>',

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(

0 commit comments

Comments
 (0)