diff --git a/news/changelog-1.6.md b/news/changelog-1.6.md index da91c282f16..d7eca33aac7 100644 --- a/news/changelog-1.6.md +++ b/news/changelog-1.6.md @@ -86,6 +86,7 @@ All changes included in 1.6: - ([#2671](https://github.com/quarto-dev/quarto-cli/issues/2671)): Ensure that `--output-dir` works across filesystem boundaries. - ([#8517](https://github.com/quarto-dev/quarto-cli/issues/8571)), ([#10829](https://github.com/quarto-dev/quarto-cli/issues/10829)): Allow listing categories with non-alphanumeric characters such as apostrophes, etc. - ([#8932](https://github.com/quarto-dev/quarto-cli/issues/8932)): Escape render ids in markdown pipeline to allow special characters in sidebars/navbars, etc. +- ([#10567](https://github.com/quarto-dev/quarto-cli/issues/10567)): Generate breadcrumbs correctly for documents using a level-1 heading as the title. - ([#10616](https://github.com/quarto-dev/quarto-cli/issues/10268)): Add a `z-index` setting to the 'back to top' button to ensure it is always visible. ### Quarto Blog diff --git a/src/command/render/pandoc.ts b/src/command/render/pandoc.ts index c5a69079ef5..3e6108a310c 100644 --- a/src/command/render/pandoc.ts +++ b/src/command/render/pandoc.ts @@ -201,6 +201,7 @@ import { MarkdownPipelineHandler, } from "../../core/markdown-pipeline.ts"; import { getEnv } from "../../../package/src/util/utils.ts"; +import { canonicalizeTitlePostprocessor } from "../../format/html/format-html-title.ts"; // in case we are running multiple pandoc processes // we need to make sure we capture all of the trace files @@ -431,6 +432,11 @@ export async function runPandoc( // record postprocessors postprocessors.push(...(extras.postprocessors || [])); + // Fix H1 title inconsistency + if (isHtmlFileOutput(options.format.pandoc)) { + htmlPostprocessors.push(canonicalizeTitlePostprocessor); + } + // add a keep-source post processor if we need one if ( options.format?.render[kKeepSource] || formatHasCodeTools(options.format) diff --git a/src/format/html/format-html-title.ts b/src/format/html/format-html-title.ts index 07ea1c2f707..de6e53e2e06 100644 --- a/src/format/html/format-html-title.ts +++ b/src/format/html/format-html-title.ts @@ -8,11 +8,17 @@ import { existsSync } from "../../deno_ral/fs.ts"; import { dirname, isAbsolute, join } from "../../deno_ral/path.ts"; import { kDateFormat, kTocLocation } from "../../config/constants.ts"; import { Format, Metadata, PandocFlags } from "../../config/types.ts"; -import { Document } from "../../core/deno-dom.ts"; +import { Document, Element } from "../../core/deno-dom.ts"; import { formatResourcePath } from "../../core/resources.ts"; import { sassLayer } from "../../core/sass.ts"; import { TempContext } from "../../core/temp-types.ts"; import { MarkdownPipeline } from "../../core/markdown-pipeline.ts"; +import { + HtmlPostProcessResult, + PandocInputTraits, + RenderedFormat, +} from "../../command/render/types.ts"; +import { InternalError } from "../../core/lib/error.ts"; export const kTitleBlockStyle = "title-block-style"; const kTitleBlockBanner = "title-block-banner"; @@ -177,6 +183,69 @@ export function documentTitlePartial( } } +export async function canonicalizeTitlePostprocessor( + doc: Document, + _options: { + inputMetadata: Metadata; + inputTraits: PandocInputTraits; + renderedFormats: RenderedFormat[]; + quiet?: boolean; + }, +): Promise { + // https://github.com/quarto-dev/quarto-cli/issues/10567 + // this fix cannot happen in `processDocumentTitle` because + // that's too late in the postprocessing order + const titleBlock = doc.querySelector("header.quarto-title-block"); + + const main = doc.querySelector("main"); + // if no main element exists, this is likely a revealjs presentation + // which will generally have a title slide instead of a title block + // so we don't need to do anything + + if (!titleBlock && main) { + const header = doc.createElement("header"); + header.id = "title-block-header"; + header.classList.add("quarto-title-block"); + main.insertBefore(header, main.firstChild); + const h1s = Array.from(doc.querySelectorAll("h1")); + for (const h1n of h1s) { + const h1 = h1n as Element; + if (h1.classList.contains("quarto-secondary-nav-title")) { + continue; + } + + // Now we need to check whether this is a plausible title element. + if (h1.parentElement?.tagName === "SECTION") { + // If the parent element is a section, then we need to check if there's + // any content before the section. If there is, then this is not a title + if ( + h1.parentElement?.parentElement?.firstElementChild !== + h1.parentElement + ) { + continue; + } + } else { + // If the parent element is not a section, then we need to check if there's + // any content before the h1. If there is, then this is not a title + if (h1.parentElement?.firstElementChild !== h1) { + continue; + } + } + + const div = doc.createElement("div"); + div.classList.add("quarto-title-banner"); + h1.classList.add("title"); + header.appendChild(h1); + break; + } + } + + return { + resources: [], + supporting: [], + }; +} + export function processDocumentTitle( input: string, format: Format, diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/.gitignore b/tests/docs/smoke-all/2024/10/28/issue-10567/.gitignore new file mode 100644 index 00000000000..075b2542afb --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/.gitignore @@ -0,0 +1 @@ +/.quarto/ diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/_quarto.yml b/tests/docs/smoke-all/2024/10/28/issue-10567/_quarto.yml new file mode 100644 index 00000000000..c795fda82d5 --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/_quarto.yml @@ -0,0 +1,25 @@ +project: + type: website + +website: + title: "issue-10567" + sidebar: + - contents: + - section: "Tutorials" + contents: + - text: Tutorials bad + href: tutorials-bad.qmd + - text: Tutorials good + href: tutorials-good.qmd + navbar: + left: + - href: index.qmd + text: Home + - about.qmd + +format: + html: + theme: cosmo + css: styles.css + toc: true + diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/about.qmd b/tests/docs/smoke-all/2024/10/28/issue-10567/about.qmd new file mode 100644 index 00000000000..07c5e7f9d13 --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/about.qmd @@ -0,0 +1,5 @@ +--- +title: "About" +--- + +About this site diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/index.qmd b/tests/docs/smoke-all/2024/10/28/issue-10567/index.qmd new file mode 100644 index 00000000000..d40480b5106 --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/index.qmd @@ -0,0 +1,7 @@ +--- +title: "issue-10567" +--- + +This is a Quarto website. + +To learn more about Quarto websites visit . diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/revealjs.qmd b/tests/docs/smoke-all/2024/10/28/issue-10567/revealjs.qmd new file mode 100644 index 00000000000..29722e7f20d --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/revealjs.qmd @@ -0,0 +1,4 @@ +--- +title: hello +format: revealjs +--- \ No newline at end of file diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/styles.css b/tests/docs/smoke-all/2024/10/28/issue-10567/styles.css new file mode 100644 index 00000000000..2ddf50c7b42 --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/styles.css @@ -0,0 +1 @@ +/* css styles */ diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/tutorials-bad.qmd b/tests/docs/smoke-all/2024/10/28/issue-10567/tutorials-bad.qmd new file mode 100644 index 00000000000..93687501b59 --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/tutorials-bad.qmd @@ -0,0 +1,14 @@ +--- +# uncomment below to see breadcrumbs say "Tutorial sidebar title" +# title: Tutorial topmatter title +_quarto: + tests: + html: + ensureHtmlElements: + - ["header.quarto-title-block ol.breadcrumb"] + - [] +--- + +# Tutorial qmd first header (not working) + +abc diff --git a/tests/docs/smoke-all/2024/10/28/issue-10567/tutorials-good.qmd b/tests/docs/smoke-all/2024/10/28/issue-10567/tutorials-good.qmd new file mode 100644 index 00000000000..896c5ede42d --- /dev/null +++ b/tests/docs/smoke-all/2024/10/28/issue-10567/tutorials-good.qmd @@ -0,0 +1,11 @@ +--- +title: Tutorial topmatter title (working) +_quarto: + tests: + html: + ensureHtmlElements: + - ["header.quarto-title-block ol.breadcrumb"] + - [] +--- + +abc