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
7 changes: 6 additions & 1 deletion news/changelog-1.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ All changes included in 1.9:

## Formats

### All Formats

- ([#13878](https://github.com/quarto-dev/quarto-cli/issues/13878)): Add `syntax-highlighting` option replacing the deprecated `highlight-style` in Pandoc 3.8. It supports style names (e.g., `tango`, `github`), custom `.theme` files, `none` to disable highlighting, or `idiomatic` for native format highlighting. The `highlight-style` option remains supported but is deprecated.

### `gfm`

- ([#13421](https://github.com/quarto-dev/quarto-cli/issues/13421)): Do not word-wrap titles in header.
Expand Down Expand Up @@ -56,7 +60,8 @@ All changes included in 1.9:
- ([#13870](https://github.com/quarto-dev/quarto-cli/issues/13870)): Add support for `alt` attribute on cross-referenced equations for improved accessibility. (author: @mcanouil)
- ([#13950](https://github.com/quarto-dev/quarto-cli/pull/13950)): Replace ctheorems with theorion package for theorem environments. Add `theorem-appearance` option to control styling: `simple` (default, classic LaTeX style), `fancy` (colored boxes with brand colors), `clouds` (rounded backgrounds), or `rainbow` (colored start border and colored title).
- ([#13954](https://github.com/quarto-dev/quarto-cli/issues/13954)): Add support for Typst book projects via format extensions. Quarto now bundles the `orange-book` extension which provides a textbook-style format with chapter numbering, cross-references, and professional styling. Book projects with `format: typst` automatically use this extension.
- ([#13978])(https://github.com/quarto-dev/quarto-cli/pull/13978)): Keep term and description together in definition lists to avoid breaking across pages. (author: @mcanouil)
- ([#13978](https://github.com/quarto-dev/quarto-cli/pull/13978)): Keep term and description together in definition lists to avoid breaking across pages. (author: @mcanouil)
- ([#13878](https://github.com/quarto-dev/quarto-cli/issues/13878)): Typst now uses Pandoc's skylighting for syntax highlighting by default (consistent with other formats). Use `syntax-highlighting: idiomatic` to opt-in to Typst's native syntax highlighting instead.

### `pdf`

Expand Down
51 changes: 37 additions & 14 deletions src/command/render/pandoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { basename, dirname, isAbsolute, join } from "../../deno_ral/path.ts";

import { info } from "../../deno_ral/log.ts";
import { info, warning } from "../../deno_ral/log.ts";

import { ensureDir, existsSync, expandGlobSync } from "../../deno_ral/fs.ts";

Expand Down Expand Up @@ -99,6 +99,7 @@ import {
kFormatResources,
kFrom,
kHighlightStyle,
kSyntaxHighlighting,
kHtmlMathMethod,
kIncludeAfterBody,
kIncludeBeforeBody,
Expand Down Expand Up @@ -699,15 +700,18 @@ export async function runPandoc(
printAllDefaults = mergeConfigs(extras.pandoc, printAllDefaults);

// Special case - theme is resolved on extras and should override allDefaults
if (extras.pandoc[kHighlightStyle] === null) {
delete printAllDefaults[kHighlightStyle];
allDefaults[kHighlightStyle] = null;
} else if (extras.pandoc[kHighlightStyle]) {
delete printAllDefaults[kHighlightStyle];
allDefaults[kHighlightStyle] = extras.pandoc[kHighlightStyle];
// Clean up deprecated kHighlightStyle if user used old name
delete printAllDefaults[kHighlightStyle];
delete allDefaults[kHighlightStyle];
if (extras.pandoc[kSyntaxHighlighting] === null) {
delete printAllDefaults[kSyntaxHighlighting];
allDefaults[kSyntaxHighlighting] = null;
} else if (extras.pandoc[kSyntaxHighlighting]) {
delete printAllDefaults[kSyntaxHighlighting];
allDefaults[kSyntaxHighlighting] = extras.pandoc[kSyntaxHighlighting];
} else {
delete printAllDefaults[kHighlightStyle];
delete allDefaults[kHighlightStyle];
delete printAllDefaults[kSyntaxHighlighting];
delete allDefaults[kSyntaxHighlighting];
}
}

Expand Down Expand Up @@ -1756,16 +1760,35 @@ function resolveTextHighlightStyle(
} as FormatExtras;

// Get the user selected theme or choose a default
const highlightTheme = pandoc[kHighlightStyle] || kDefaultHighlightStyle;
// Check both syntax-highlighting (new) and highlight-style (deprecated alias)
const highlightTheme = pandoc[kSyntaxHighlighting] ||
pandoc[kHighlightStyle] ||
kDefaultHighlightStyle;
const textHighlightingMode = extras.html?.[kTextHighlightingMode];

if (highlightTheme === "none") {
// Disable highlighting - pass "none" string (not null, which Pandoc 3.8+ rejects)
extras.pandoc = extras.pandoc || {};
extras.pandoc[kHighlightStyle] = "none";
extras.pandoc[kSyntaxHighlighting] = "none";
return extras;
}

if (highlightTheme === "idiomatic") {
if (isRevealjsOutput(pandoc)) {
// reveal.js idiomatic mode doesn't produce working highlighting
// Fall through to default skylighting instead
warning(
"syntax-highlighting: idiomatic is not supported for reveal.js. Using default highlighting.",
);
} else {
// Use native format highlighting (typst native, LaTeX listings)
// Pass through to Pandoc 3.8+ which handles this natively
extras.pandoc = extras.pandoc || {};
extras.pandoc[kSyntaxHighlighting] = "idiomatic";
return extras;
}
}

// create the possible name matches based upon the dark vs. light
// and find a matching theme file
// Themes from
Expand All @@ -1775,7 +1798,7 @@ function resolveTextHighlightStyle(
case "dark":
// Set light or dark mode as appropriate
extras.pandoc = extras.pandoc || {};
extras.pandoc[kHighlightStyle] = textHighlightThemePath(
extras.pandoc[kSyntaxHighlighting] = textHighlightThemePath(
inputDir,
highlightTheme,
textHighlightingMode,
Expand All @@ -1787,7 +1810,7 @@ function resolveTextHighlightStyle(
// Clear the highlighting
if (extras.pandoc) {
extras.pandoc = extras.pandoc || {};
extras.pandoc[kHighlightStyle] = textHighlightThemePath(
extras.pandoc[kSyntaxHighlighting] = textHighlightThemePath(
inputDir,
"none",
);
Expand All @@ -1797,7 +1820,7 @@ function resolveTextHighlightStyle(
default:
// Set the the light (default) highlighting mode
extras.pandoc = extras.pandoc || {};
extras.pandoc[kHighlightStyle] =
extras.pandoc[kSyntaxHighlighting] =
textHighlightThemePath(inputDir, highlightTheme, "light") ||
highlightTheme;
break;
Expand Down
4 changes: 4 additions & 0 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,10 @@ export const kNumberDepth = "number-depth";
export const kTopLevelDivision = "top-level-division";
export const kPaperSize = "papersize";
export const kLogFile = "log-file";
// TODO: Deprecate kHighlightStyle in favor of kSyntaxHighlighting
// Kept for backward compatibility with older documents using highlight-style
export const kHighlightStyle = "highlight-style";
export const kSyntaxHighlighting = "syntax-highlighting";
export const kDefaultImageExtension = "default-image-extension";
export const kLogo = "logo";
export const kLinkColor = "linkcolor";
Expand Down Expand Up @@ -709,6 +712,7 @@ export const kPandocDefaultsKeys = [
"ascii",
kDefaultImageExtension,
kHighlightStyle,
kSyntaxHighlighting,
kSyntaxDefinitions,
kSyntaxDefinition,
kListings,
Expand Down
2 changes: 2 additions & 0 deletions src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ import {
kFreeze,
kGladtex,
kHighlightStyle,
kSyntaxHighlighting,
kHtmlMathMethod,
kHtmlPreTagProcessing,
kHtmlTableProcessing,
Expand Down Expand Up @@ -594,6 +595,7 @@ export interface FormatPandoc {
[kNumberSections]?: boolean;
[kNumberOffset]?: number[];
[kHighlightStyle]?: string | Record<string, string> | null;
[kSyntaxHighlighting]?: string | Record<string, string> | null;
[kSectionDivs]?: boolean;
[kHtmlMathMethod]?: string | { method: string; url: string };
[kTopLevelDivision]?: string;
Expand Down
4 changes: 2 additions & 2 deletions src/preview/preview-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ async function textPreviewHtml(file: string, req: Request) {
const cmd = [pandocBinaryPath()];
cmd.push("--to", "html");
cmd.push(
"--highlight-style",
"--syntax-highlighting",
textHighlightThemePath("atom-one", darkMode ? "dark" : "light")!,
);
cmd.push("--standalone");
Expand Down Expand Up @@ -239,7 +239,7 @@ async function gfmPreview(file: string, request: Request) {
cmd.push("--lua-filter");
cmd.push(filter);
if (highlightPath) {
cmd.push("--highlight-style");
cmd.push("--syntax-highlighting");
cmd.push(highlightPath);
}
// Github renders math with MathJax now, so our preview mode does the same
Expand Down
38 changes: 20 additions & 18 deletions src/quarto-core/text-highlighting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { join } from "../deno_ral/path.ts";

import { kDefaultHighlightStyle } from "../command/render/constants.ts";
import { kHighlightStyle } from "../config/constants.ts";
import { kHighlightStyle, kSyntaxHighlighting } from "../config/constants.ts";
import { FormatPandoc } from "../config/types.ts";

import { existsSync } from "../deno_ral/fs.ts";
Expand All @@ -22,6 +22,15 @@ export interface ThemeDescriptor {
const kDarkSuffix = "dark";
const kLightSuffix = "light";

// Resolve highlight theme from syntax-highlighting (new) or highlight-style (deprecated)
export function getHighlightTheme(
pandoc: FormatPandoc,
): string | Record<string, string> {
return pandoc[kSyntaxHighlighting] ||
pandoc[kHighlightStyle] ||
kDefaultHighlightStyle;
}

export function textHighlightThemePath(
inputDir: string,
theme: string | Record<string, string>,
Expand Down Expand Up @@ -69,30 +78,23 @@ export function readHighlightingTheme(
pandoc: FormatPandoc,
style: "dark" | "light" | "default",
): ThemeDescriptor | undefined {
const theme = pandoc[kHighlightStyle] || kDefaultHighlightStyle;
if (theme) {
const themeRaw = readTheme(inputDir, theme, style);
if (themeRaw) {
return {
json: JSON.parse(themeRaw),
isAdaptive: isAdaptiveTheme(theme),
};
} else {
return undefined;
}
} else {
return undefined;
const theme = getHighlightTheme(pandoc);
const themeRaw = readTheme(inputDir, theme, style);
if (themeRaw) {
return {
json: JSON.parse(themeRaw),
isAdaptive: isAdaptiveTheme(theme),
};
}
return undefined;
}

export function hasAdaptiveTheme(pandoc: FormatPandoc) {
const theme = pandoc[kHighlightStyle] || kDefaultHighlightStyle;
return theme && isAdaptiveTheme(theme);
return isAdaptiveTheme(getHighlightTheme(pandoc));
}

export function hasTextHighlighting(pandoc: FormatPandoc): boolean {
const theme = pandoc[kHighlightStyle];
return theme !== null;
return getHighlightTheme(pandoc) !== "none";
}

export function isAdaptiveTheme(theme: string | Record<string, string>) {
Expand Down
57 changes: 48 additions & 9 deletions src/resources/editor/tools/vs-code.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13685,13 +13685,14 @@ var require_yaml_intelligence_resources = __commonJS({
}
},
{
name: "highlight-style",
name: "syntax-highlighting",
tags: {
formats: [
"$html-all",
"docx",
"ms",
"$pdf-all"
"$pdf-all",
"typst"
]
},
schema: {
Expand Down Expand Up @@ -13720,6 +13721,7 @@ var require_yaml_intelligence_resources = __commonJS({
"github",
"gruvbox",
"haddock",
"idiomatic",
"kate",
"monochrome",
"monokai",
Expand All @@ -13740,7 +13742,38 @@ var require_yaml_intelligence_resources = __commonJS({
},
description: {
short: "Specifies the coloring style to be used in highlighted source code.",
long: "Specifies the coloring style to be used in highlighted source code.\n\nInstead of a *STYLE* name, a JSON file with extension\n` .theme` may be supplied. This will be parsed as a KDE\nsyntax highlighting theme and (if valid) used as the\nhighlighting style.\n"
long: "Specifies the coloring style to be used in highlighted source code.\n\nValid values:\n\n- `none`: Disables syntax highlighting for code blocks.\n- `idiomatic`: Uses the format's native syntax highlighter\n (e.g., Typst's built-in highlighting, LaTeX `listings` package,\n or reveal.js highlight.js plugin).\n- A style name (e.g., `pygments`, `tango`, `github`): Uses\n Pandoc's skylighting with the specified theme.\n- A path to a `.theme` file: Uses a custom KDE syntax\n highlighting theme.\n\nFor adaptive light/dark themes, specify an object with `light`\nand `dark` properties pointing to theme files.\n"
}
},
{
name: "highlight-style",
hidden: true,
tags: {
formats: [
"$html-all",
"docx",
"ms",
"$pdf-all",
"typst"
]
},
schema: {
anyOf: [
{
object: {
closed: true,
properties: {
light: "path",
dark: "path"
}
}
},
"string"
]
},
description: {
short: "Deprecated: use `syntax-highlighting` instead.",
long: "Deprecated: use `syntax-highlighting` instead.\n\nSpecifies the coloring style to be used in highlighted source code.\n"
}
},
{
Expand All @@ -13750,7 +13783,8 @@ var require_yaml_intelligence_resources = __commonJS({
"$html-all",
"docx",
"ms",
"$pdf-all"
"$pdf-all",
"typst"
]
},
schema: "path",
Expand All @@ -13764,7 +13798,8 @@ var require_yaml_intelligence_resources = __commonJS({
"$html-all",
"docx",
"ms",
"$pdf-all"
"$pdf-all",
"typst"
]
},
schema: {
Expand Down Expand Up @@ -23195,7 +23230,11 @@ var require_yaml_intelligence_resources = __commonJS({
},
{
short: "Specifies the coloring style to be used in highlighted source\ncode.",
long: "Specifies the coloring style to be used in highlighted source\ncode.\nInstead of a <em>STYLE</em> name, a JSON file with extension\n<code>.theme</code> may be supplied. This will be parsed as a KDE syntax\nhighlighting theme and (if valid) used as the highlighting style."
long: "Specifies the coloring style to be used in highlighted source\ncode.\nValid values:"
},
{
short: "Deprecated: use <code>syntax-highlighting</code> instead.",
long: "Deprecated: use <code>syntax-highlighting</code> instead.\nSpecifies the coloring style to be used in highlighted source\ncode."
},
"KDE language syntax definition file (XML)",
"KDE language syntax definition files (XML)",
Expand Down Expand Up @@ -25266,12 +25305,12 @@ var require_yaml_intelligence_resources = __commonJS({
mermaid: "%%"
},
"handlers/mermaid/schema.yml": {
_internalId: 220795,
_internalId: 221789,
type: "object",
description: "be an object",
properties: {
"mermaid-format": {
_internalId: 220787,
_internalId: 221781,
type: "enum",
enum: [
"png",
Expand All @@ -25287,7 +25326,7 @@ var require_yaml_intelligence_resources = __commonJS({
exhaustiveCompletions: true
},
theme: {
_internalId: 220794,
_internalId: 221788,
type: "anyOf",
anyOf: [
{
Expand Down

Large diffs are not rendered by default.

Loading
Loading