Skip to content

Commit 2c47b1b

Browse files
committed
Merge branch 'main' into fix/theorem-vertical-space
2 parents 5b3a9d8 + fdfdd31 commit 2c47b1b

39 files changed

+893
-105
lines changed

.github/workflows/test-smokes.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ jobs:
7878
- uses: ./.github/workflows/actions/quarto-dev
7979

8080
- name: Install Tinytex
81+
env:
82+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8183
run: |
8284
quarto install tinytex
8385

news/changelog-1.3.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
- Replace default style for date picker component in OJS ([#2863](https://github.com/quarto-dev/quarto-cli/issues/2863)).
107107
- `quarto check` now supports `quarto check versions` for checking binary dependency versions in the case of custom binaries ([#3602](https://github.com/quarto-dev/quarto-cli/issues/3602)).
108108
- the API for shortcode handlers in lua now accepts a fourth parameter `raw_args` which hold the unparsed arguments in a table ([#3833](https://github.com/quarto-dev/quarto-cli/issues/3833)).
109+
- remove scaffolding div from conditional content in final output ([#3847](https://github.com/quarto-dev/quarto-cli/issues/3847)).
109110

110111
## Pandoc filter changes
111112

src/config/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const kFormatResources = "format-resources";
4040

4141
export const kFormatLinks = "format-links";
4242
export const kNotebookLinks = "notebook-links";
43+
export const kNotebookPreview = "notebook-preview";
4344

4445
export const kKeepHidden = "keep-hidden";
4546

@@ -168,6 +169,7 @@ export const kRenderDefaultsKeys = [
168169
kFormatResources,
169170
kFormatLinks,
170171
kNotebookLinks,
172+
kNotebookPreview,
171173
];
172174

173175
// language fields

src/config/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ import {
131131
kMergeIncludes,
132132
kMermaidFormat,
133133
kNotebookLinks,
134+
kNotebookPreview,
134135
kNumberOffset,
135136
kNumberSections,
136137
kOutput,
@@ -403,6 +404,7 @@ export interface FormatRender {
403404
[kFormatResources]?: string[];
404405
[kFormatLinks]?: boolean | string[];
405406
[kNotebookLinks]?: boolean | "inline" | "global";
407+
[kNotebookPreview]?: boolean;
406408
}
407409

408410
export interface FormatExecute {

src/core/jupyter/jupyter-embed.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import {
4444
import { globalTempContext } from "../temp.ts";
4545
import { isAbsolute } from "path/mod.ts";
4646
import { partitionMarkdown } from "../pandoc/pandoc-partition.ts";
47+
import { safeExistsSync } from "../path.ts";
48+
import { basename } from "../../vendor/deno.land/[email protected]/path/win32.ts";
4749

4850
export interface JupyterNotebookAddress {
4951
path: string;
@@ -173,18 +175,26 @@ export async function replaceNotebookPlaceholders(
173175
// Compute appropriate includes based upon the note
174176
// dependendencies
175177
const notebookIncludes = () => {
176-
const notebook = jupyterFromFile(resolveNbPath(input, nbAddress.path));
177-
const dependencies = isHtmlOutput(context.format.pandoc)
178-
? extractJupyterWidgetDependencies(notebook)
179-
: undefined;
180-
if (dependencies) {
181-
const tempDir = globalTempContext().createDir();
182-
return includesForJupyterWidgetDependencies(
183-
[dependencies],
184-
tempDir,
185-
);
178+
const nbPath = resolveNbPath(input, nbAddress.path);
179+
if (safeExistsSync(nbPath)) {
180+
const notebook = jupyterFromFile(nbPath);
181+
const dependencies = isHtmlOutput(context.format.pandoc)
182+
? extractJupyterWidgetDependencies(notebook)
183+
: undefined;
184+
if (dependencies) {
185+
const tempDir = globalTempContext().createDir();
186+
return includesForJupyterWidgetDependencies(
187+
[dependencies],
188+
tempDir,
189+
);
190+
} else {
191+
return undefined;
192+
}
186193
} else {
187-
return undefined;
194+
const notebookName = basename(nbPath);
195+
throw new Error(
196+
`Unable to embed content from notebook '${notebookName}'\nThe file ${nbPath} doesn't exist or cannot be read.`,
197+
);
188198
}
189199
};
190200
includes = notebookIncludes();

src/format/html/format-html-bootstrap.ts

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
*/
77

8-
import { Document, Element, Node } from "../../core/deno-dom.ts";
8+
import { Document, Element } from "../../core/deno-dom.ts";
99
import { join } from "path/mod.ts";
1010

1111
import { renderEjs } from "../../core/ejs.ts";
@@ -20,12 +20,16 @@ import {
2020
kIncludeInHeader,
2121
kLinkCitations,
2222
kNotebookLinks,
23+
kNotebookPreview,
24+
kOutputFile,
2325
kQuartoTemplateParams,
2426
kRelatedFormatsTitle,
2527
kRelatedNotebooksTitle,
2628
kSectionDivs,
2729
kSourceNotebookPrefix,
2830
kTargetFormat,
31+
kTemplate,
32+
kTheme,
2933
kTocDepth,
3034
kTocLocation,
3135
} from "../../config/constants.ts";
@@ -82,6 +86,10 @@ import {
8286
} from "../../config/format.ts";
8387
import * as ld from "../../core/lodash.ts";
8488
import { basename } from "path/mod.ts";
89+
import { render, renderServices } from "../../command/render/render-shared.ts";
90+
import { info } from "log/mod.ts";
91+
import { dirname } from "../../vendor/deno.land/[email protected]/path/win32.ts";
92+
import { renderHtmlPreview } from "./format-html-embed.ts";
8593

8694
export function formatPageLayout(format: Format) {
8795
return format.metadata[kPageLayout] as string || kPageLayoutArticle;
@@ -329,7 +337,7 @@ function bootstrapHtmlPostprocessor(
329337

330338
// Look for included / embedded notebooks and include those
331339
if (format.render[kNotebookLinks] !== false) {
332-
processNotebookEmbeds(doc, format, resources);
340+
await processNotebookEmbeds(doc, format, resources);
333341
}
334342

335343
// default treatment for computational tables
@@ -538,7 +546,7 @@ function processAlternateFormatLinks(
538546
}
539547
}
540548

541-
function processNotebookEmbeds(
549+
async function processNotebookEmbeds(
542550
doc: Document,
543551
format: Format,
544552
resources: string[],
@@ -547,24 +555,43 @@ function processNotebookEmbeds(
547555
format.render[kNotebookLinks] === true;
548556
const global = format.render[kNotebookLinks] === "global" ||
549557
format.render[kNotebookLinks] === true;
558+
const notebookPreview = format.render[kNotebookPreview] ?? true;
550559

551560
const notebookDivNodes = doc.querySelectorAll("[data-notebook]");
552561
if (notebookDivNodes.length > 0) {
553-
const nbPaths: { path: string; title: string; filename: string }[] = [];
562+
const nbPaths: { path: string; title: string; filename?: string }[] = [];
554563
let count = 1;
555-
notebookDivNodes.forEach((nbDivNode) => {
564+
const services = renderServices();
565+
566+
for (const nbDivNode of notebookDivNodes) {
556567
const nbDivEl = nbDivNode as Element;
557568
nbDivEl.classList.add("quarto-notebook");
558569
const notebookPath = nbDivEl.getAttribute("data-notebook");
559570
if (notebookPath) {
560571
const title = nbDivEl.getAttribute("data-notebook-title");
572+
const nbDir = dirname(notebookPath);
561573
const filename = basename(notebookPath);
562574

563-
const nbPath = {
564-
path: notebookPath,
565-
title: title || filename,
566-
filename,
575+
const notePreview = async () => {
576+
if (notebookPreview) {
577+
const htmlPreview = await renderHtmlPreview(
578+
notebookPath,
579+
format,
580+
services,
581+
);
582+
return {
583+
title: htmlPreview.title,
584+
path: htmlPreview.path,
585+
};
586+
} else {
587+
return {
588+
path: join(nbDir, filename),
589+
title: title || filename,
590+
filename,
591+
};
592+
}
567593
};
594+
const nbPath = await notePreview();
568595
nbPaths.push(nbPath);
569596

570597
// Add a decoration to this div node
@@ -575,7 +602,9 @@ function processNotebookEmbeds(
575602
nbLinkEl.classList.add("quarto-notebook-link");
576603
nbLinkEl.setAttribute("id", `${id}`);
577604
nbLinkEl.setAttribute("href", nbPath.path);
578-
nbLinkEl.setAttribute("download", nbPath.filename);
605+
if (nbPath.filename) {
606+
nbLinkEl.setAttribute("download", nbPath.filename);
607+
}
579608
nbLinkEl.appendChild(
580609
doc.createTextNode(
581610
`${format.language[kSourceNotebookPrefix]}: ${nbPath.title}`,
@@ -597,7 +626,7 @@ function processNotebookEmbeds(
597626
}
598627
}
599628
}
600-
});
629+
}
601630

602631
if (global) {
603632
const containerEl = doc.createElement("div");
@@ -618,7 +647,9 @@ function processNotebookEmbeds(
618647

619648
const link = doc.createElement("a");
620649
link.setAttribute("href", nbPath.path);
621-
link.setAttribute("download", nbPath.filename);
650+
if (nbPath.filename) {
651+
link.setAttribute("download", nbPath.filename);
652+
}
622653

623654
const icon = doc.createElement("i");
624655
icon.classList.add("bi");
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* format-html-embed.ts
3+
*
4+
* Copyright (C) 2020-2022 Posit Software, PBC
5+
*
6+
*/
7+
import { formatResourcePath } from "../../core/resources.ts";
8+
import { renderEjs } from "../../core/ejs.ts";
9+
10+
import { kOutputFile, kTemplate, kTheme } from "../../config/constants.ts";
11+
import { Format } from "../../config/types.ts";
12+
13+
import { RenderServices } from "../../command/render/types.ts";
14+
import { render } from "../../command/render/render-shared.ts";
15+
16+
import { basename, dirname, join } from "path/mod.ts";
17+
18+
export interface HtmlPreview {
19+
title: string;
20+
path: string;
21+
}
22+
23+
export async function renderHtmlPreview(
24+
path: string,
25+
format: Format,
26+
services: RenderServices,
27+
): Promise<HtmlPreview> {
28+
const filename = basename(path);
29+
const title = filename;
30+
31+
// Use the special `embed` template for this render
32+
const embedHtmlEjs = formatResourcePath(
33+
"html",
34+
join("embed", "template.ejs.html"),
35+
);
36+
const embedTemplate = renderEjs(embedHtmlEjs, {
37+
title,
38+
path,
39+
filename,
40+
});
41+
const templatePath = services.temp.createFile({ suffix: "html" });
42+
Deno.writeTextFileSync(templatePath, embedTemplate);
43+
44+
// Rebder the notebook and update the path
45+
const nbPreviewFile = `${filename}.html`;
46+
await render(path, {
47+
services,
48+
flags: {
49+
metadata: {
50+
[kTheme]: format.metadata[kTheme],
51+
[kOutputFile]: nbPreviewFile,
52+
[kTemplate]: templatePath,
53+
},
54+
quiet: false,
55+
},
56+
});
57+
58+
return {
59+
title,
60+
path: join(dirname(path), nbPreviewFile),
61+
};
62+
}

src/format/html/format-html-title.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,14 @@ export function documentTitleIncludeInHeader(
8888

8989
if (variables.length > 0) {
9090
const styles = `<style>
91-
.quarto-title-block .quarto-title-banner {
91+
.quarto-title-block .quarto-title-banner,
92+
.quarto-title-block .quarto-title-banner h1,
93+
.quarto-title-block .quarto-title-banner h2,
94+
.quarto-title-block .quarto-title-banner h3,
95+
.quarto-title-block .quarto-title-banner h4,
96+
.quarto-title-block .quarto-title-banner h5,
97+
.quarto-title-block .quarto-title-banner h6
98+
{
9299
${variables.join("\n")}
93100
}
94101
</style>`;

src/format/html/format-html.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
kLinkExternalIcon,
2929
kLinkExternalNewwindow,
3030
kNotebookLinks,
31+
kNotebookPreview,
3132
kTheme,
3233
} from "../../config/constants.ts";
3334

@@ -89,7 +90,6 @@ import {
8990
} from "../../core/giscus.ts";
9091
import { metadataPostProcessor } from "./format-html-meta.ts";
9192
import { kHtmlEmptyPostProcessResult } from "../../command/render/constants.ts";
92-
import { coerce } from "https://deno.land/x/[email protected]/mod.ts";
9393

9494
export function htmlFormat(
9595
figwidth: number,
@@ -100,6 +100,7 @@ export function htmlFormat(
100100
{
101101
render: {
102102
[kNotebookLinks]: true,
103+
[kNotebookPreview]: true,
103104
[kFormatLinks]: true,
104105
},
105106
resolveFormat: (format: Format) => {

src/format/reveal/format-reveal.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ export function revealjsFormat() {
189189
figResponsive: false,
190190
}, // tippy options
191191
{
192-
theme: "quarto-reveal",
193192
parent: "section.slide",
194193
config: {
195194
offset: [0, 0],

0 commit comments

Comments
 (0)