From f075eaf6c49db6d0fac366cf967f8ea568513833 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Fri, 6 Dec 2024 07:57:41 -0700 Subject: [PATCH 1/3] move fix to #10567 into website postprocessor --- src/command/render/pandoc.ts | 5 - src/project/types/website/website.ts | 344 +++++++++++++-------------- 2 files changed, 170 insertions(+), 179 deletions(-) diff --git a/src/command/render/pandoc.ts b/src/command/render/pandoc.ts index fcb8a47f0a3..6864b8fc75a 100644 --- a/src/command/render/pandoc.ts +++ b/src/command/render/pandoc.ts @@ -439,11 +439,6 @@ 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/project/types/website/website.ts b/src/project/types/website/website.ts index 2f8bc5063ee..be974a477da 100644 --- a/src/project/types/website/website.ts +++ b/src/project/types/website/website.ts @@ -89,6 +89,7 @@ import { projectDraftMode } from "./website-utils.ts"; import { kFieldCategories } from "./listing/website-listing-shared.ts"; import { pandocNativeStr } from "../../../core/pandoc/codegen.ts"; import { asArray } from "../../../core/array.ts"; +import { canonicalizeTitlePostprocessor } from "../../../format/html/format-html-title.ts"; export const kSiteTemplateDefault = "default"; export const kSiteTemplateBlog = "blog"; @@ -139,210 +140,205 @@ export const websiteProjectType: ProjectType = { format: Format, services: RenderServices, ): Promise => { - if (isHtmlFileOutput(format.pandoc)) { - // navigation extras for bootstrap enabled formats - const extras = formatHasBootstrap(format) - ? await websiteNavigationExtras( - project, - source, - flags, - format, - services.temp, - ) - : await websiteNoThemeExtras( - project, - source, - flags, - format, - services.temp, - ); + if (!isHtmlFileOutput(format.pandoc)) { + return Promise.resolve({}); + } - // add some title related variables - extras.pandoc = extras.pandoc || {}; - extras.metadata = extras.metadata || {}; - extras.metadataOverride = extras.metadataOverride || {}; + // navigation extras for bootstrap enabled formats + const extras = formatHasBootstrap(format) + ? await websiteNavigationExtras( + project, + source, + flags, + format, + services.temp, + ) + : await websiteNoThemeExtras( + project, + source, + flags, + format, + services.temp, + ); - // Resolve any giscus information - resolveFormatForGiscus(project, format); + // add some title related variables + extras.pandoc = extras.pandoc || {}; + extras.metadata = extras.metadata || {}; + extras.metadataOverride = extras.metadataOverride || {}; - // title prefix if the project has a title and this isn't the home page - const title = websiteTitle(project.config); - if (title) { - extras.pandoc = { - [kTitlePrefix]: title, - }; - } + // Resolve any giscus information + resolveFormatForGiscus(project, format); - // dependency for favicon if we have one - const favicon = websiteConfigString(kSiteFavicon, project.config); - if (favicon) { - const offset = projectOffset(project, source); - extras.html = extras.html || {}; - extras.html.dependencies = extras.html.dependencies || []; - extras.html.dependencies.push({ - name: kSiteFavicon, - links: [{ - rel: "icon", - href: offset + "/" + favicon, - type: contentType(favicon), - }], - }); - } + // title prefix if the project has a title and this isn't the home page + const title = websiteTitle(project.config); + if (title) { + extras.pandoc = { + [kTitlePrefix]: title, + }; + } - // pagetitle for home page if it has no title + // dependency for favicon if we have one + const favicon = websiteConfigString(kSiteFavicon, project.config); + if (favicon) { const offset = projectOffset(project, source); - const [_dir, stem] = dirAndStem(source); - const home = stem === "index" && offset === "."; - if ( - home && !format.metadata[kTitle] && !format.metadata[kPageTitle] && - title - ) { - extras.metadata[kPageTitle] = title; - } + extras.html = extras.html || {}; + extras.html.dependencies = extras.html.dependencies || []; + extras.html.dependencies.push({ + name: kSiteFavicon, + links: [{ + rel: "icon", + href: offset + "/" + favicon, + type: contentType(favicon), + }], + }); + } - // categories metadata needs to be escaped from Markdown processing to - // avoid +smart applying to it. Categories are expected to be non markdown. - // So we provide an override to ensure they are not processed. - if (format.metadata[kFieldCategories]) { - extras.metadataOverride[kFieldCategories] = asArray( - format.metadata[kFieldCategories], - ).map( - (category) => - pandocNativeStr(category as string).mappedString().value, - ); - } + // pagetitle for home page if it has no title + const offset = projectOffset(project, source); + const [_dir, stem] = dirAndStem(source); + const home = stem === "index" && offset === "."; + if ( + home && !format.metadata[kTitle] && !format.metadata[kPageTitle] && + title + ) { + extras.metadata[kPageTitle] = title; + } - // html metadata - extras.html = extras.html || {}; - extras.html[kHtmlPostprocessors] = extras.html[kHtmlPostprocessors] || []; - extras.html[kHtmlFinalizers] = extras.html[kHtmlFinalizers] || []; - extras.html[kMarkdownAfterBody] = extras.html[kMarkdownAfterBody] || []; - extras.html[kHtmlPostprocessors]?.push(...[ - htmlResourceResolverPostprocessor( - source, - project, - projectExtensionPathResolver( - project.config?.project[kProjectLibDir] || "", - project.dir, - ), - ), - ]); - extras.html[kHtmlPostprocessors].unshift(websiteDraftPostProcessor); + // categories metadata needs to be escaped from Markdown processing to + // avoid +smart applying to it. Categories are expected to be non markdown. + // So we provide an override to ensure they are not processed. + if (format.metadata[kFieldCategories]) { + extras.metadataOverride[kFieldCategories] = asArray( + format.metadata[kFieldCategories], + ).map( + (category) => pandocNativeStr(category as string).mappedString().value, + ); + } - // listings extras - const hasBootstrap = formatHasBootstrap(format); + // html metadata + extras.html = extras.html || {}; + extras.html[kHtmlPostprocessors] = extras.html[kHtmlPostprocessors] || []; + extras.html[kHtmlFinalizers] = extras.html[kHtmlFinalizers] || []; + extras.html[kMarkdownAfterBody] = extras.html[kMarkdownAfterBody] || []; - const htmlListingDependencies = await listingHtmlDependencies( + extras.html[kHtmlPostprocessors].push(...[ + htmlResourceResolverPostprocessor( source, project, - format, - services.temp, - extras, - ); - if (htmlListingDependencies) { - const listingPostProcessor = - htmlListingDependencies[kHtmlPostprocessors]; - if (listingPostProcessor) { - // Process listings early so if we inject content div, navigation and other - // elements will wrap around - extras.html[kHtmlPostprocessors]?.unshift(listingPostProcessor); - } + projectExtensionPathResolver( + project.config?.project[kProjectLibDir] || "", + project.dir, + ), + ), + // Fix H1 title inconsistency + canonicalizeTitlePostprocessor, + ]); + extras.html[kHtmlPostprocessors].unshift(websiteDraftPostProcessor); - const listingAfterBody = htmlListingDependencies[kMarkdownAfterBody]; - if (listingAfterBody) { - extras.html[kMarkdownAfterBody]?.push(listingAfterBody); - } - extras[kIncludeInHeader] = extras[kIncludeInHeader] || []; - extras[kIncludeInHeader]!.push( - ...htmlListingDependencies[kIncludeInHeader], - ); - extras.html[kSassBundles] = extras.html[kSassBundles] || []; - extras.html[kSassBundles]!.push( - ...htmlListingDependencies[kSassBundles], - ); + // listings extras + const hasBootstrap = formatHasBootstrap(format); - extras.html[kDependencies] = extras.html[kDependencies] || []; - extras.html[kDependencies]?.push( - ...htmlListingDependencies[kDependencies], - ); + const htmlListingDependencies = await listingHtmlDependencies( + source, + project, + format, + services.temp, + extras, + ); + if (htmlListingDependencies) { + const listingPostProcessor = htmlListingDependencies[kHtmlPostprocessors]; + if (listingPostProcessor) { + // Process listings early so if we inject content div, navigation and other + // elements will wrap around + extras.html[kHtmlPostprocessors]?.unshift(listingPostProcessor); } - if (hasBootstrap) { - // about extras - const aboutDependencies = await aboutHtmlDependencies( - source, - project, - format, - services.temp, - extras, - ); - if (aboutDependencies) { - const aboutPostProcessor = aboutDependencies[kHtmlPostprocessors]; - if (aboutPostProcessor) { - extras.html[kHtmlPostprocessors]?.push(aboutPostProcessor); - } - - extras.html[kSassBundles] = extras.html[kSassBundles] || []; - extras.html[kSassBundles]!.push( - ...aboutDependencies[kSassBundles], - ); - extras.html[kMarkdownAfterBody] = extras.html[kMarkdownAfterBody] || - []; - extras.html[kMarkdownAfterBody]!.push( - ...aboutDependencies[kMarkdownAfterBody], - ); - } + const listingAfterBody = htmlListingDependencies[kMarkdownAfterBody]; + if (listingAfterBody) { + extras.html[kMarkdownAfterBody]?.push(listingAfterBody); } - - // metadata html dependencies - const htmlMetadataDependencies = metadataHtmlDependencies( - source, - project, - format, - extras, - ); - extras.html[kHtmlPostprocessors]?.push( - htmlMetadataDependencies[kHtmlPostprocessors], + extras[kIncludeInHeader] = extras[kIncludeInHeader] || []; + extras[kIncludeInHeader]!.push( + ...htmlListingDependencies[kIncludeInHeader], ); - extras.html[kMarkdownAfterBody]?.push( - htmlMetadataDependencies[kMarkdownAfterBody], + extras.html[kSassBundles] = extras.html[kSassBundles] || []; + extras.html[kSassBundles]!.push( + ...htmlListingDependencies[kSassBundles], ); - // Add html analytics extras, if any - const analyticsDependency = websiteAnalyticsScriptFile( - project, - services.temp, + extras.html[kDependencies] = extras.html[kDependencies] || []; + extras.html[kDependencies]?.push( + ...htmlListingDependencies[kDependencies], ); - if (analyticsDependency) { - extras[kIncludeInHeader] = extras[kIncludeInHeader] || []; - extras[kIncludeInHeader]?.push(analyticsDependency); - } - const cookieDep = cookieConsentDependencies( + } + + if (hasBootstrap) { + // about extras + const aboutDependencies = await aboutHtmlDependencies( + source, project, format, services.temp, + extras, ); - if (cookieDep) { - // Inline script - extras[kIncludeInHeader] = extras[kIncludeInHeader] || []; - extras[kIncludeInHeader]?.push( - cookieDep.scriptFile, + if (aboutDependencies) { + const aboutPostProcessor = aboutDependencies[kHtmlPostprocessors]; + if (aboutPostProcessor) { + extras.html[kHtmlPostprocessors]?.push(aboutPostProcessor); + } + + extras.html[kSassBundles] = extras.html[kSassBundles] || []; + extras.html[kSassBundles]!.push( + ...aboutDependencies[kSassBundles], ); + extras.html[kMarkdownAfterBody].push( + ...aboutDependencies[kMarkdownAfterBody], + ); + } + } - // dependency - extras.html = extras.html || {}; - extras.html[kDependencies] = extras.html[kDependencies] || []; - extras.html[kDependencies]?.push(cookieDep.dependency); + // metadata html dependencies + const htmlMetadataDependencies = metadataHtmlDependencies( + source, + project, + format, + extras, + ); + extras.html[kHtmlPostprocessors].push( + htmlMetadataDependencies[kHtmlPostprocessors], + ); + extras.html[kMarkdownAfterBody].push( + htmlMetadataDependencies[kMarkdownAfterBody], + ); - extras.html[kHtmlPostprocessors] = extras.html[kHtmlPostprocessors] || - []; - extras.html[kHtmlPostprocessors]?.push(cookieDep.htmlPostProcessor); - } + // Add html analytics extras, if any + const analyticsDependency = websiteAnalyticsScriptFile( + project, + services.temp, + ); + if (analyticsDependency) { + extras[kIncludeInHeader] = extras[kIncludeInHeader] || []; + extras[kIncludeInHeader]?.push(analyticsDependency); + } + const cookieDep = cookieConsentDependencies( + project, + format, + services.temp, + ); + if (cookieDep) { + // Inline script + extras[kIncludeInHeader] = extras[kIncludeInHeader] || []; + extras[kIncludeInHeader]?.push( + cookieDep.scriptFile, + ); - return Promise.resolve(extras); - } else { - return Promise.resolve({}); + // dependency + extras.html[kDependencies] = extras.html[kDependencies] || []; + extras.html[kDependencies].push(cookieDep.dependency); + extras.html[kHtmlPostprocessors].push(cookieDep.htmlPostProcessor); } + + return Promise.resolve(extras); }, postRender: async ( From a63c82c3cf5275af8ef8223e6c90ac866e7f2507 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 9 Dec 2024 15:14:45 +0100 Subject: [PATCH 2/3] Remove unused import --- src/command/render/pandoc.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/command/render/pandoc.ts b/src/command/render/pandoc.ts index 6864b8fc75a..0228ea34483 100644 --- a/src/command/render/pandoc.ts +++ b/src/command/render/pandoc.ts @@ -201,7 +201,6 @@ import { MarkdownPipelineHandler, } from "../../core/markdown-pipeline.ts"; import { getEnv } from "../../../package/src/util/utils.ts"; -import { canonicalizeTitlePostprocessor } from "../../format/html/format-html-title.ts"; import { BrandFontBunny, BrandFontFile, From 5f071f244c57bd59ea45f103470e17673e55c5ab Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 9 Dec 2024 15:25:02 +0100 Subject: [PATCH 3/3] `canonicalizeTitlePostprocessor()` needs to be done before `websiteNavigationExtras()` --- src/project/types/website/website.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/project/types/website/website.ts b/src/project/types/website/website.ts index be974a477da..980eab5a370 100644 --- a/src/project/types/website/website.ts +++ b/src/project/types/website/website.ts @@ -230,10 +230,13 @@ export const websiteProjectType: ProjectType = { project.dir, ), ), + ]); + // add postprocessors that needs to be before other extras.html + extras.html[kHtmlPostprocessors].unshift( + websiteDraftPostProcessor, // Fix H1 title inconsistency canonicalizeTitlePostprocessor, - ]); - extras.html[kHtmlPostprocessors].unshift(websiteDraftPostProcessor); + ); // listings extras const hasBootstrap = formatHasBootstrap(format);