Skip to content

Commit 27d981f

Browse files
committed
merge
2 parents 045de68 + ec10654 commit 27d981f

File tree

169 files changed

+6497
-3971
lines changed

Some content is hidden

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

169 files changed

+6497
-3971
lines changed

news/changelog-1.8.md

Lines changed: 32 additions & 3 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,6 +35,8 @@ 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.
3842
- 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 +47,13 @@ All changes included in 1.8:
4347

4448
### `typst`
4549

46-
- ([#12180](https://github.com/quarto-dev/quarto-cli/issues/12180): Typst schema / autocomplete for `logo` option has `path` and `alt`.
50+
- ([#12180](https://github.com/quarto-dev/quarto-cli/issues/12180)): Typst schema / autocomplete for `logo` option has `path` and `alt`.
4751
- ([#12554](https://github.com/quarto-dev/quarto-cli/pull/12554)): CSS properties `font-weight` and `font-style` are translated to Typst `text` properties.
4852
- ([#12695](https://github.com/quarto-dev/quarto-cli/issues/12695)): Resolve Typst `font-paths` that start with `/` relative to project root.
4953
- ([#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.
5054
- ([#12815](https://github.com/quarto-dev/quarto-cli/issues/12815)): Do not crash when floats have no content.
5155
- ([#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.
5257

5358
### `beamer`
5459

@@ -62,6 +67,7 @@ All changes included in 1.8:
6267

6368
### `website`
6469

70+
- ([#10284](https://github.com/quarto-dev/quarto-cli/issues/10284)): a11y - Fix keyboard navigation for tabset panels when using an HTML theme. Tabs now properly receive keyboard focus.
6571
- ([#12551](https://github.com/quarto-dev/quarto-cli/pull/12551)): Improve warning issued when `aliases` would overwrite an existing document.
6672
- ([#12616](https://github.com/quarto-dev/quarto-cli/issues/12616)): find SVG images in image discovery for listings.
6773
- ([#12693](https://github.com/quarto-dev/quarto-cli/issues/12693)): Prevent resource exhaustion on large websites by serializing `NotebookContext` information to file instead of the environment.
@@ -71,11 +77,15 @@ All changes included in 1.8:
7177

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

74-
## Lua Filters
80+
## Lua Filters and API
7581

82+
- ([#11750](https://github.com/quarto-dev/quarto-cli/pull/11750)): Extend filter path resolution to support `at`/`path` filters from extensions.
7683
- ([#12727](https://github.com/quarto-dev/quarto-cli/issues/12727)): Do not crash in the presence of malformed tabset contents.
7784
- ([#12806](https://github.com/quarto-dev/quarto-cli/pull/12806)): Use pandoc APIs to handle codepage conversion on Windows.
7885
- ([#12811](https://github.com/quarto-dev/quarto-cli/pull/12811)): Add support for YouTube Shorts in `video` shortcode.
86+
- ([#13112](https://github.com/quarto-dev/quarto-cli/pull/13112)): Add `quarto.format.format_identifier()` API entry.
87+
- ([#13128](https://github.com/quarto-dev/quarto-cli/issues/13128)): Avoid meta shortcode crash on bad input.
88+
- ([#13246](https://github.com/quarto-dev/quarto-cli/pull/13246)): Add `quarto.variables.get()` and `quarto.metadata.get()` APIs.
7989

8090
## Commands
8191

@@ -91,13 +101,19 @@ All changes included in 1.8:
91101

92102
- ([#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.
93103

104+
## Extensions
105+
106+
- ([#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.
107+
94108
## Engines
95109

110+
- ([#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.
111+
96112
### `jupyter`
97113

98114
- ([#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.
99115
- ([#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.
100-
- ([#13026](https://github.com/quarto-dev/quarto-cli/pulls/13026)): Use `jsdelivr` CDN for jupyter widgets dependencies.
116+
- ([#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.
101117

102118
### `knitr`
103119

@@ -107,10 +123,23 @@ All changes included in 1.8:
107123

108124
- ([#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.
109125

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

112132
- ([#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.
113133
- ([#12782](https://github.com/quarto-dev/quarto-cli/pull/12782)): fix bug on `safeRemoveDirSync`'s detection of safe directory boundaries.
114134
- ([#12853](https://github.com/quarto-dev/quarto-cli/issues/12853)): fix replaceAll() escaping issue with embedded notebooks containing `$` in their Markdown.
115135
- ([#12939](https://github.com/quarto-dev/quarto-cli/pull/12939)): Upgrade `mermaidjs` to 11.6.0.
136+
- ([#13031](https://github.com/quarto-dev/quarto-cli/pull/13031)): Add `.quarto_ipynb` files to `.gitignore` by default.
137+
- ([#13085](https://github.com/quarto-dev/quarto-cli/pull/13085)): Avoid `kbd` shortcode crashes on unknown OS keys.
138+
- ([#13164](https://github.com/quarto-dev/quarto-cli/pull/13164)): add `julia` to execute schema to allow autocomplete suggestions. (@mcanouil)
116139
- ([#13121](https://github.com/quarto-dev/quarto-cli/issues/13121)): Allow `contents` shortcode to find inline elements.
140+
141+
142+
## Quarto Internals
143+
144+
- ([#13155](https://github.com/quarto-dev/quarto-cli/pull/13155)): Process `pandoc-reader-FORMAT` raw blocks through `pandoc.read(FORMAT)`.
145+
- ([#13255](https://github.com/quarto-dev/quarto-cli/pull/13255)): Move some Lua code to use Pandoc's Lua API.

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/filters.ts

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -851,19 +851,28 @@ async function resolveFilterExtension(
851851
// Resolve any filters that are provided by an extension
852852
const results: (QuartoFilter | QuartoFilter[])[] = [];
853853
const getFilter = async (filter: QuartoFilter) => {
854-
// Look for extension names in the filter list and result them
854+
// Look for extension names in the filter list and resolve them
855855
// into the filters provided by the extension
856-
if (
857-
filter !== kQuartoFilterMarker && filter !== kQuartoCiteProcMarker &&
858-
typeof filter === "string"
859-
) {
856+
if (filter === kQuartoFilterMarker || filter === kQuartoCiteProcMarker) {
857+
return filter;
858+
}
859+
860+
let pathToResolve: string | null = null;
861+
862+
if (typeof filter === "string") {
863+
pathToResolve = filter;
864+
} else if (typeof filter === "object" && filter.path) {
865+
pathToResolve = filter.path;
866+
}
867+
868+
if (pathToResolve) {
860869
// The filter string points to an executable file which exists
861-
if (existsSync(filter) && !Deno.statSync(filter).isDirectory) {
870+
if (existsSync(pathToResolve) && !Deno.statSync(pathToResolve).isDirectory) {
862871
return filter;
863872
}
864873

865874
const extensions = await options.services.extension?.find(
866-
filter,
875+
pathToResolve,
867876
options.source,
868877
"filters",
869878
options.project?.config,
@@ -873,15 +882,35 @@ async function resolveFilterExtension(
873882
// Filter this list of extensions
874883
const filteredExtensions = filterExtensions(
875884
extensions || [],
876-
filter,
885+
pathToResolve,
877886
"filter",
878887
);
879888
// Return any contributed plugins
880889
if (filteredExtensions.length > 0) {
881890
// This matches an extension, use the contributed filters
882-
const filters = extensions[0].contributes.filters;
883-
if (filters) {
884-
return filters;
891+
const extensionFilters = extensions[0].contributes.filters;
892+
if (extensionFilters) {
893+
// After "path" resolution, "at" needs to be preserved
894+
if (typeof filter === "string") {
895+
return extensionFilters;
896+
} else if (isFilterEntryPoint(filter)) {
897+
return extensionFilters.map(extFilter => {
898+
if (typeof extFilter === "string") {
899+
return {
900+
type: extFilter.endsWith(".lua") ? "lua" : "json" as "lua" | "json",
901+
path: extFilter,
902+
at: filter.at
903+
};
904+
} else {
905+
return {
906+
...extFilter,
907+
at: filter.at
908+
};
909+
}
910+
});
911+
} else {
912+
return extensionFilters;
913+
}
885914
} else {
886915
return filter;
887916
}

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: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ import { InternalError } from "../lib/error.ts";
3232
import { join, relative } from "../../deno_ral/path.ts";
3333
import { warnOnce } from "../log.ts";
3434
import { isCssColorName } from "../css/color-names.ts";
35-
import { assert } from "testing/asserts";
35+
import {
36+
LogoLightDarkSpecifierPathOptional,
37+
LogoOptionsPathOptional,
38+
LogoSpecifier,
39+
LogoSpecifierPathOptional,
40+
} from "../../resources/types/schema-types.ts";
3641

3742
type ProcessedBrandData = {
3843
color: Record<string, string>;
@@ -240,11 +245,13 @@ export class Brand {
240245
resolvePath(entry: BrandLogoResource) {
241246
const pathPrefix = relative(this.projectDir, this.brandDir);
242247
if (typeof entry === "string") {
243-
return { path: join(pathPrefix, entry) };
248+
return { path: isExternalPath(entry) ? entry : join(pathPrefix, entry) };
244249
}
245250
return {
246251
...entry,
247-
path: join(pathPrefix, entry.path),
252+
path: isExternalPath(entry.path)
253+
? entry.path
254+
: join(pathPrefix, entry.path),
248255
};
249256
}
250257

@@ -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

0 commit comments

Comments
 (0)