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
1 change: 1 addition & 0 deletions news/changelog-1.11.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ All changes included in 1.11:

- ([#14772](https://github.com/quarto-dev/quarto-cli/issues/14772)): Custom `language` keys now reach templates through `$quarto.language.<key>$`. A key that Quarto does not ship passed schema validation and was merged over the defaults, then discarded before templates saw it, so it expanded to an empty string with no warning. (author: @mcanouil)
- ([#14882](https://github.com/quarto-dev/quarto-cli/issues/14882)): Fix brand font families with a word starting with a digit, such as `Source Sans 3`, not applying in `html` and `revealjs` output. The same names in `mainfont` now also apply in `revealjs`. (author: @Masad791)
- ([#14891](https://github.com/quarto-dev/quarto-cli/issues/14891)): Fix a brand file that holds only comments, such as a commented-out `_brand.yml` template, stopping the render with `YAML value is missing`. It now prints a warning and is ignored. (author: @Masad791)

### `dashboard`

Expand Down
30 changes: 27 additions & 3 deletions src/project/project-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

import { existsSync, safeRemoveSync } from "../deno_ral/fs.ts";
import { warnOnce } from "../core/log.ts";
import {
dirname,
isAbsolute,
Expand Down Expand Up @@ -553,7 +554,26 @@ export async function projectResolveBrand(
project: ProjectContext,
fileName?: string,
): Promise<LightDarkBrandDarkFlag | undefined> {
async function loadSingleBrand(brandPath: string): Promise<Brand> {
// A brand file holding only comments (e.g. a commented-out template) has no
// YAML value and would fail validation, so warn and treat it as absent.
function isEmptyBrandFile(brandPath: string): boolean {
let empty = false;
try {
empty = parse(Deno.readTextFileSync(brandPath)) == null;
} catch {
// invalid YAML: let validation report it
}
if (empty) {
warnOnce(`Brand file ${brandPath} has no content and will be ignored.`);
}
return empty;
}
async function loadSingleBrand(
brandPath: string,
): Promise<Brand | undefined> {
if (isEmptyBrandFile(brandPath)) {
return undefined;
}
const brand = await readAndValidateYamlFromFile(
brandPath,
refSchema("brand-single", "Format-independent brand configuration."),
Expand All @@ -563,7 +583,10 @@ export async function projectResolveBrand(
}
async function loadUnifiedBrand(
brandPath: string,
): Promise<LightDarkBrandDarkFlag> {
): Promise<LightDarkBrandDarkFlag | undefined> {
if (isEmptyBrandFile(brandPath)) {
return undefined;
}
const brand = await readAndValidateYamlFromFile(
brandPath,
refSchema("brand-unified", "Format-independent brand configuration."),
Expand Down Expand Up @@ -662,7 +685,8 @@ export async function projectResolveBrand(
if (!existsSync(brandPath)) {
continue;
}
project.brandCache.brand = await loadUnifiedBrand(brandPath);
project.brandCache.brand = (await loadUnifiedBrand(brandPath)) ??
project.brandCache.brand;
}
return project.brandCache.brand;
} else {
Expand Down
5 changes: 5 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-14891/_brand.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# A brand file that only holds comments, e.g. a commented-out template.
# color:
# primary: "#447099"
# typography:
# base: Inter
13 changes: 13 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-14891/index.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: "Comment-only _brand.yml"
format: html
_quarto:
tests:
html:
noErrors: true
printsMessage:
level: WARN
regex: '_brand\.yml has no content and will be ignored'
---

A `_brand.yml` holding only comments should warn and be ignored, not stop the render.
Loading