Skip to content

Commit 1d912df

Browse files
authored
Merge branch 'main' into fix/language-es
2 parents a212b12 + 908cde5 commit 1d912df

File tree

47 files changed

+620
-70
lines changed

Some content is hidden

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

47 files changed

+620
-70
lines changed

news/changelog-1.8.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ All changes included in 1.8:
2323
- ([#10983](https://github.com/quarto-dev/quarto-cli/issues/10983)): Fix spacing inconsistency between paras and first section headings.
2424
- ([#12259](https://github.com/quarto-dev/quarto-cli/issues/12259)): Fix conflict between `html-math-method: katex` and crossref popups (author: @benkeks).
2525
- ([#12341](https://github.com/quarto-dev/quarto-cli/issues/12341)): Enable light and dark logos for html formats (sidebar, navbar, dashboard).
26+
- ([#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.
2627
- ([#12734](https://github.com/quarto-dev/quarto-cli/issues/12734)): `highlight-style` now correctly supports setting a different `light` and `dark`.
2728
- ([#12747](https://github.com/quarto-dev/quarto-cli/issues/12747)): Ensure `th` elements are properly restored when Quarto's HTML table processing is happening.
2829
- ([#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)
@@ -95,6 +96,10 @@ All changes included in 1.8:
9596

9697
- ([#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.
9798

99+
## Extensions
100+
101+
- ([#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.
102+
98103
## Engines
99104

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

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: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ 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";
3635
import {
3736
LogoLightDarkSpecifierPathOptional,
3837
LogoOptionsPathOptional,
@@ -246,11 +245,13 @@ export class Brand {
246245
resolvePath(entry: BrandLogoResource) {
247246
const pathPrefix = relative(this.projectDir, this.brandDir);
248247
if (typeof entry === "string") {
249-
return { path: join(pathPrefix, entry) };
248+
return { path: isExternalPath(entry) ? entry : join(pathPrefix, entry) };
250249
}
251250
return {
252251
...entry,
253-
path: join(pathPrefix, entry.path),
252+
path: isExternalPath(entry.path)
253+
? entry.path
254+
: join(pathPrefix, entry.path),
254255
};
255256
}
256257

@@ -270,6 +271,10 @@ export class Brand {
270271
}
271272
}
272273

274+
function isExternalPath(path: string) {
275+
return /^\w+:/.test(path);
276+
}
277+
273278
export type LightDarkBrand = {
274279
light?: Brand;
275280
dark?: Brand;

src/extension/extension.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from "../project/types.ts";
1818

1919
import {
20+
basename,
2021
dirname,
2122
isAbsolute,
2223
join,
@@ -158,10 +159,13 @@ export function projectExtensionPathResolver(
158159
return (href: string, projectOffset: string) => {
159160
const projectRelativeHref = relative(projectOffset, href);
160161

161-
if (projectRelativeHref.startsWith("_extensions/")) {
162+
if (
163+
projectRelativeHref.startsWith("_extensions/") ||
164+
projectRelativeHref.startsWith("_extensions\\")
165+
) {
162166
const projectTargetHref = projectRelativeHref.replace(
163-
/^_extensions\//,
164-
`${libDir}/quarto-contrib/quarto-project/`,
167+
/^_extensions/,
168+
`${libDir}/quarto-contrib/quarto-project`,
165169
);
166170

167171
copyResourceFile(
@@ -791,7 +795,7 @@ async function readExtension(
791795
const metadata = contributes?.metadata as Record<string, unknown> | undefined;
792796

793797
// resolve metadata/project pre- and post-render scripts to their full path
794-
for (const key of ["pre-render", "post-render"]) {
798+
for (const key of ["pre-render", "post-render", "brand"]) {
795799
for (const object of [metadata, project]) {
796800
if (!object?.project || typeof object.project !== "object") {
797801
continue;
@@ -808,8 +812,21 @@ async function readExtension(
808812
[],
809813
);
810814
if (resolved.include.length > 0) {
811-
(object.project as Record<string, unknown>)[key] = resolved
812-
.include;
815+
if (key === "brand") {
816+
let projectDir = extensionDir, last;
817+
do {
818+
last = basename(projectDir);
819+
projectDir = dirname(projectDir);
820+
} while (projectDir && last !== "_extensions");
821+
if (projectDir) {
822+
(object.project as Record<string, unknown>)[key] = relative(
823+
projectDir,
824+
resolved.include[0],
825+
);
826+
}
827+
} else {
828+
(object.project as Record<string, unknown>)[key] = resolved.include;
829+
}
813830
}
814831
}
815832
}

src/project/project-context.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,32 @@ import { createTempContext } from "../core/temp.ts";
107107

108108
import { onCleanup } from "../core/cleanup.ts";
109109
import { once } from "../core/once.ts";
110+
import { Zod } from "../resources/types/zod/schema-types.ts";
111+
112+
const mergeExtensionMetadata = async (
113+
context: ProjectContext,
114+
pOptions: RenderOptions,
115+
) => {
116+
// this will mutate context.config.project to merge
117+
// in any project metadata from extensions
118+
if (context.config) {
119+
const extensions = await pOptions.services.extension.extensions(
120+
undefined,
121+
context.config,
122+
context.isSingleFile ? undefined : context.dir,
123+
{ builtIn: false },
124+
);
125+
const projectMetadata = extensions.filter((extension) =>
126+
extension.contributes.metadata?.project
127+
).map((extension) => {
128+
return Zod.ProjectConfig.parse(extension.contributes.metadata!.project);
129+
});
130+
context.config.project = mergeProjectMetadata(
131+
context.config.project,
132+
...projectMetadata,
133+
);
134+
}
135+
};
110136

111137
export async function projectContext(
112138
path: string,
@@ -145,6 +171,16 @@ export async function projectContext(
145171
}
146172
};
147173

174+
const returnResult = async (
175+
context: ProjectContext,
176+
) => {
177+
if (renderOptions) {
178+
await mergeExtensionMetadata(context, renderOptions);
179+
}
180+
onCleanup(context.cleanup);
181+
return context;
182+
};
183+
148184
while (true) {
149185
// use the current resolver
150186
const resolver = configResolvers[0];
@@ -362,8 +398,7 @@ export async function projectContext(
362398
config: configFiles,
363399
configResources: projectConfigResources(dir, projectConfig, type),
364400
};
365-
onCleanup(result.cleanup);
366-
return result;
401+
return await returnResult(result);
367402
} else {
368403
debug(`projectContext: Found Quarto project in ${dir}`);
369404
const temp = createTempContext({
@@ -431,8 +466,7 @@ export async function projectContext(
431466
config: configFiles,
432467
configResources: projectConfigResources(dir, projectConfig),
433468
};
434-
onCleanup(result.cleanup);
435-
return result;
469+
return await returnResult(result);
436470
}
437471
} else {
438472
const nextDir = dirname(dir);
@@ -511,8 +545,7 @@ export async function projectContext(
511545
context.files.input = [input];
512546
}
513547
debug(`projectContext: Found Quarto project in ${originalDir}`);
514-
onCleanup(context.cleanup);
515-
return context;
548+
return await returnResult(context);
516549
} else {
517550
return undefined;
518551
}

src/project/project-shared.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,14 @@ export async function projectResolveBrand(
560560
let fileNames = ["_brand.yml", "_brand.yaml"].map((file) =>
561561
join(project.dir, file)
562562
);
563-
const brand = project?.config?.brand as boolean | string | {
564-
light?: string;
565-
dark?: string;
566-
};
563+
const brand = (project?.config?.brand ??
564+
project?.config?.project.brand) as
565+
| boolean
566+
| string
567+
| {
568+
light?: string;
569+
dark?: string;
570+
};
567571
if (brand === false) {
568572
project.brandCache.brand = undefined;
569573
return project.brandCache.brand;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.html
2+
*.pdf
3+
*_files/
4+
/.quarto/
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# <%= title %> Extension For Quarto
2+
3+
_TODO_: Add a short description of your extension.
4+
5+
## Installing
6+
7+
_TODO_: Replace the `<github-organization>` with your GitHub organization.
8+
9+
```bash
10+
quarto add <github-organization>/<%= filesafename %>
11+
```
12+
13+
This will install the extension under the `_extensions` subdirectory.
14+
If you're using version control, you will want to check in this directory.
15+
16+
## Using
17+
18+
This extension installs a [brand.yml](https://posit-dev.github.io/brand-yml/) configuration for _your organization name_.
19+
20+
## Example
21+
22+
Here is the source code for a minimal example: [example.qmd](example.qmd).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
title: <%= title %>
2+
author: <%= author %>
3+
version: <%= version %>
4+
quarto-required: ">=<%= quartoversion %>"
5+
contributes:
6+
metadata:
7+
project:
8+
brand: brand.yml

0 commit comments

Comments
 (0)