Skip to content
Open
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.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ All changes included in 1.9:
- ([#11929](https://github.com/quarto-dev/quarto-cli/issues/11929)): Import all `brand.typography.fonts` in CSS, whether or not fonts are referenced by typography elements.
- ([#13413](https://github.com/quarto-dev/quarto-cli/issues/13413)): Fix uncentered play button in `video` shortcodes from cross-reference divs. (author: @bruvellu)
- ([#13508](https://github.com/quarto-dev/quarto-cli/issues/13508)): Add `aria-label` support to `video` shortcode for improved accessibility.
- ([#13685](https://github.com/quarto-dev/quarto-cli/issues/13685)): Fix remote font URLs in brand extensions being incorrectly joined with the extension path, resulting in broken font imports.

### `typst`

Expand Down
7 changes: 6 additions & 1 deletion src/core/sass/brand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ const googleFontImportString = (description: BrandFontGoogle) => {
}:${styleString}wght@${weights}&display=${display}');`;
};

const isExternalPath = (path: string) => /^\w+:/.test(path);

const fileFontImportString = (brand: Brand, description: BrandFontFile) => {
const pathPrefix = relative(brand.projectDir, brand.brandDir);
const parts = [];
Expand All @@ -162,9 +164,12 @@ const fileFontImportString = (brand: Brand, description: BrandFontFile) => {
weight = file.weight;
style = file.style;
}
const fontUrl = isExternalPath(path)
? path
: join(pathPrefix, path).replace(/\\/g, "/");
parts.push(`@font-face {
font-family: '${description.family}';
src: url('${join(pathPrefix, path).replace(/\\/g, "/")}');
src: url('${fontUrl}');
font-weight: ${weight || "normal"};
font-style: ${style || "normal"};
}\n`);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/.quarto/
**/*.quarto_ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: My Brand
author: Quarto
version: 1.0.0
quarto-required: ">=99.9.0"
contributes:
metadata:
project:
brand: mybrand.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
typography:
fonts:
- family: Noto Sans
source: file
files:
- path: https://notofonts.github.io/latin-greek-cyrillic/fonts/NotoSans/unhinted/ttf/NotoSans-Regular.ttf
base:
family: Noto Sans
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project:
type: default
format:
html:
theme: brand
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Remote Font Extension Test
_quarto:
tests:
html:
ensureCssRegexMatches:
- ['src:url\("https://notofonts\.github\.io/']
- ['_extensions/my-brand/https:']
---

# Remote Font Test

This document tests that remote font URLs in brand extensions are handled correctly (issue #13685).

{{< lipsum 1 >}}
2 changes: 2 additions & 0 deletions tests/smoke/smoke-all.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { breakQuartoMd } from "../../src/core/lib/break-quarto-md.ts";
import { parse } from "../../src/core/yaml.ts";
import { cleanoutput } from "./render/render.ts";
import {
ensureCssRegexMatches,
ensureEpubFileRegexMatches,
ensureDocxRegexMatches,
ensureDocxXpath,
Expand Down Expand Up @@ -171,6 +172,7 @@ function resolveTestSpecs(
const result = [];
// deno-lint-ignore no-explicit-any
const verifyMap: Record<string, any> = {
ensureCssRegexMatches,
ensureEpubFileRegexMatches,
ensureHtmlElements,
ensureHtmlElementContents,
Expand Down
47 changes: 47 additions & 0 deletions tests/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,53 @@ export const ensureFileRegexMatches = (
return(verifyFileRegexMatches(regexChecker)(file, matchesUntyped, noMatchesUntyped));
};

// Use this function to Regex match text in CSS files in the supporting files directory
export const ensureCssRegexMatches = (
file: string,
matchesUntyped: (string | RegExp)[],
noMatchesUntyped?: (string | RegExp)[],
): Verify => {
const asRegexp = (m: string | RegExp) => {
if (typeof m === "string") {
return new RegExp(m, "m");
}
return m;
};
const matches = matchesUntyped.map(asRegexp);
const noMatches = noMatchesUntyped?.map(asRegexp);

return {
name: `Inspecting CSS files for Regex matches`,
verify: async (_output: ExecuteOutput[]) => {
// Find support directory from file path
const [dir, stem] = dirAndStem(file);
const supportDir = join(dir, stem + "_files");

// Find all CSS files recursively and combine their content
let combinedContent = "";
for (const entry of walkSync(supportDir, { exts: [".css"] })) {
combinedContent += await Deno.readTextFile(entry.path) + "\n";
}

matches.forEach((regex) => {
assert(
regex.test(combinedContent),
`Required CSS match ${String(regex)} is missing.`,
);
});

if (noMatches) {
noMatches.forEach((regex) => {
assert(
!regex.test(combinedContent),
`Illegal CSS match ${String(regex)} was found.`,
);
});
}
},
};
};

// Use this function to Regex match text in the intermediate kept file
// FIXME: do this properly without resorting on file having keep-*
export const verifyKeepFileRegexMatches = (
Expand Down
Loading