Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/command/render/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { existsSync } from "fs/mod.ts";

import {
kBibliography,
kBrand,
kCitationLocation,
kCiteMethod,
kClearCellOptions,
Expand Down Expand Up @@ -192,6 +193,7 @@ export async function filterParamsJson(
[kIsShinyPython]: isShinyPython,
[kShinyPythonExec]: isShinyPython ? await pythonExec() : undefined,
[kExecutionEngine]: options.executionEngine,
[kBrand]: options.format.render[kBrand],
};
return JSON.stringify(params);
}
Expand Down
8 changes: 6 additions & 2 deletions src/command/render/render-contexts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* render-contexts.ts
*
* Copyright (C) 2021-2023 Posit Software, PBC
* Copyright (C) 2021-2024 Posit Software, PBC
*/

import { Format, FormatExecute, Metadata } from "../../config/types.ts";
Expand Down Expand Up @@ -89,6 +89,7 @@ import {
} from "../../core/pandoc/pandoc-formats.ts";
import { ExtensionContext } from "../../extension/types.ts";
import { NotebookContext } from "../../render/notebook/notebook-types.ts";
import { Brand } from "../../resources/types/schema-types.ts";

export async function resolveFormatsFromMetadata(
metadata: Metadata,
Expand Down Expand Up @@ -394,7 +395,7 @@ async function resolveFormats(
engine: ExecutionEngine,
options: RenderOptions,
_notebookContext: NotebookContext,
project?: ProjectContext,
project: ProjectContext,
enforceProjectFormats: boolean = true,
): Promise<Record<string, { format: Format; active: boolean }>> {
// input level metadata
Expand Down Expand Up @@ -598,6 +599,9 @@ async function resolveFormats(
);
};

// resolve brand in project and forward it to format
mergedFormats[format].render.brand = await project.resolveBrand();

// ensure that we have a valid forma
const formatIsValid = isValidFormat(
formatDesc,
Expand Down
1 change: 1 addition & 0 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const kPreferHtml = "prefer-html";
export const kSelfContainedMath = "self-contained-math";
export const kBiblioConfig = "biblio-config";
export const kBodyClasses = "body-classes";
export const kBrand = "brand";

export const kLatexAutoMk = "latex-auto-mk";
export const kLatexAutoInstall = "latex-auto-install";
Expand Down
3 changes: 3 additions & 0 deletions src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
kBackToTop,
kBaseFormat,
kBodyClasses,
kBrand,
kCache,
kCalloutCautionCaption,
kCalloutImportantCaption,
Expand Down Expand Up @@ -246,6 +247,7 @@ import {
import { HtmlPostProcessor, RenderServices } from "../command/render/types.ts";
import { QuartoFilterSpec } from "../command/render/types.ts";
import { ProjectContext } from "../project/types.ts";
import { Brand } from "../resources/types/schema-types.ts";

export const kDependencies = "dependencies";
export const kSassBundles = "sass-bundles";
Expand Down Expand Up @@ -493,6 +495,7 @@ export interface FormatRender {
[kValidateYaml]?: boolean;
[kCanonicalUrl]?: boolean | string;
[kBodyClasses]?: string;
[kBrand]?: Brand;
}

export interface FormatExecute {
Expand Down
4 changes: 4 additions & 0 deletions src/project/project-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import {
ignoreFieldsForProjectType,
normalizeFormatYaml,
projectConfigFile,
projectResolveBrand,
projectResolveFullMarkdownForFile,
projectVarsFile,
} from "./project-shared.ts";
Expand Down Expand Up @@ -254,6 +255,7 @@ export async function projectContext(
}

const result: ProjectContext = {
resolveBrand: async () => projectResolveBrand(result),
resolveFullMarkdownForFile: (
engine: ExecutionEngine | undefined,
file: string,
Expand Down Expand Up @@ -333,6 +335,7 @@ export async function projectContext(
} else {
debug(`projectContext: Found Quarto project in ${dir}`);
const result: ProjectContext = {
resolveBrand: async () => projectResolveBrand(result),
resolveFullMarkdownForFile: (
engine: ExecutionEngine | undefined,
file: string,
Expand Down Expand Up @@ -390,6 +393,7 @@ export async function projectContext(
configResolvers.shift();
} else if (force) {
const context: ProjectContext = {
resolveBrand: async () => projectResolveBrand(context),
resolveFullMarkdownForFile: (
engine: ExecutionEngine | undefined,
file: string,
Expand Down
22 changes: 22 additions & 0 deletions src/project/project-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ import { mappedIndexToLineCol } from "../core/lib/mapped-text.ts";
import { normalizeNewlines } from "../core/lib/text.ts";
import { DirectiveCell } from "../core/lib/break-quarto-md-types.ts";
import { QuartoJSONSchema } from "../core/yaml.ts";
import { refSchema } from "../core/lib/yaml-schema/common.ts";
import { Brand } from "../resources/types/schema-types.ts";

export function projectExcludeDirs(context: ProjectContext): string[] {
const outputDir = projectOutputDir(context);
Expand Down Expand Up @@ -484,3 +486,23 @@ const ensureFileInformationCache = (project: ProjectContext, file: string) => {
}
return project.fileInformationCache.get(file)!;
};

export async function projectResolveBrand(project: ProjectContext) {
if (project.brandCache) {
return project.brandCache.brand;
}
project.brandCache = {};
for (const brandFile of ["_brand.yml", "_brand.yaml"]) {
const brandPath = join(project.dir, brandFile);
if (!existsSync(brandPath)) {
continue;
}
const brand = await readAndValidateYamlFromFile(
brandPath,
refSchema("brand", "Format-independent brand configuration."),
"Brand validation failed for " + brandPath + ".",
) as Brand;
project.brandCache.brand = brand;
}
return project.brandCache.brand;
}
5 changes: 5 additions & 0 deletions src/project/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ExecutionEngine, ExecutionTarget } from "../execute/types.ts";
import { InspectedMdCell } from "../quarto-core/inspect-types.ts";
import { NotebookContext } from "../render/notebook/notebook-types.ts";
import {
Brand,
NavigationItem as NavItem,
NavigationItemObject,
NavigationItemObject as SidebarTool,
Expand Down Expand Up @@ -66,6 +67,10 @@ export interface ProjectContext {

fileInformationCache: Map<string, FileInformation>;

// This is a cache of _brand.yml for a project
brandCache?: { brand?: Brand };
resolveBrand: () => Promise<Brand | undefined>;

// expands markdown for a file
// input file doesn't have to be markdown; it can be, for example, a knitr spin file
// output file is always markdown, though, and it is cached in the project
Expand Down
6 changes: 5 additions & 1 deletion src/project/types/single-file/single-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import { renderFormats } from "../../../command/render/render-contexts.ts";
import { RenderFlags } from "../../../command/render/types.ts";
import { MappedString } from "../../../core/mapped-text.ts";
import { fileExecutionEngineAndTarget } from "../../../execute/engine.ts";
import { projectResolveFullMarkdownForFile } from "../../project-shared.ts";
import {
projectResolveBrand,
projectResolveFullMarkdownForFile,
} from "../../project-shared.ts";
import { ExecutionEngine } from "../../../execute/types.ts";

export function singleFileProjectContext(
Expand All @@ -30,6 +33,7 @@ export function singleFileProjectContext(
const environmentMemoizer = makeProjectEnvironmentMemoizer(notebookContext);

const result: ProjectContext = {
resolveBrand: () => projectResolveBrand(result),
dir: normalizePath(dirname(source)),
engines: [],
files: {
Expand Down
Loading