From ba6730f428d7246020e82ecadf2c89b6490fe0c1 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Mon, 7 Oct 2024 08:22:01 -0700 Subject: [PATCH 1/2] brand,html - forward logo information to sidebars --- .../types/website/website-navigation.ts | 30 ++++++++++--------- src/project/types/website/website-search.ts | 22 +++++++------- src/project/types/website/website-shared.ts | 18 ++++++++++- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/project/types/website/website-navigation.ts b/src/project/types/website/website-navigation.ts index 788434a95f..26574ac823 100644 --- a/src/project/types/website/website-navigation.ts +++ b/src/project/types/website/website-navigation.ts @@ -164,7 +164,7 @@ export async function initWebsiteNavigation(project: ProjectContext) { pageMargin, bodyDecorators, announcement, - } = websiteNavigationConfig( + } = await websiteNavigationConfig( project, ); if ( @@ -258,7 +258,7 @@ export async function websiteNavigationExtras( // determine dependencies (always include baseline nav dependency) const dependencies: FormatDependency[] = [ - websiteNavigationDependency(project), + await websiteNavigationDependency(project), ]; // the contents of anything before the head @@ -267,11 +267,13 @@ export async function websiteNavigationExtras( // Determine any sass bundles const sassBundles: SassBundle[] = [websiteNavigationSassBundle()]; - const searchDep = websiteSearchDependency(project, source); + const searchDep = await websiteSearchDependency(project, source); if (searchDep) { dependencies.push(...searchDep); sassBundles.push(websiteSearchSassBundle()); - includeInHeader.push(websiteSearchIncludeInHeader(project, format, temp)); + includeInHeader.push( + await websiteSearchIncludeInHeader(project, format, temp), + ); } // Inject dashboard dependencies so they are present if necessary @@ -997,7 +999,7 @@ async function sidebarsEjsData(project: ProjectContext, sidebars: Sidebar[]) { for (let i = 0; i < sidebars.length; i++) { ejsSidebars.push(await sidebarEjsData(project, sidebars[i])); } - return Promise.resolve(ejsSidebars); + return ejsSidebars; } async function sidebarEjsData(project: ProjectContext, sidebar: Sidebar) { @@ -1009,10 +1011,10 @@ async function sidebarEjsData(project: ProjectContext, sidebar: Sidebar) { } // ensure title and search are present - sidebar.title = sidebarTitle(sidebar, project) as string | undefined; + sidebar.title = await sidebarTitle(sidebar, project) as string | undefined; sidebar.logo = resolveLogo(sidebar.logo); - const searchOpts = searchOptions(project); + const searchOpts = await searchOptions(project); sidebar.search = sidebar.search !== undefined ? sidebar.search : searchOpts && searchOpts.location === "sidebar" @@ -1227,7 +1229,7 @@ async function navbarEjsData( ): Promise { const collapse = navbar.collapse !== undefined ? !!navbar.collapse : true; - const searchOpts = searchOptions(project); + const searchOpts = await searchOptions(project); const data: Navbar = { ...navbar, search: searchOpts && searchOpts.location === "navbar" @@ -1472,8 +1474,8 @@ function looksLikeShortCode(href: string) { return href.startsWith("{{<") && href.endsWith(">}}"); } -function sidebarTitle(sidebar: Sidebar, project: ProjectContext) { - const { navbar } = websiteNavigationConfig(project); +async function sidebarTitle(sidebar: Sidebar, project: ProjectContext) { + const { navbar } = await websiteNavigationConfig(project); if (sidebar.title) { // Title was explicitly set return sidebar.title; @@ -1499,8 +1501,8 @@ function resolveLogo(logo?: string) { } } -function websiteHeadroom(project: ProjectContext) { - const { navbar, sidebars } = websiteNavigationConfig(project); +async function websiteHeadroom(project: ProjectContext) { + const { navbar, sidebars } = await websiteNavigationConfig(project); if (navbar || sidebars?.length) { const navbarPinned = navbar?.pinned === true; const anySidebarPinned = sidebars && @@ -1525,9 +1527,9 @@ function websiteNavigationSassBundle() { }; } -function websiteNavigationDependency(project: ProjectContext) { +async function websiteNavigationDependency(project: ProjectContext) { const scripts = [navigationDependency("quarto-nav.js")]; - if (websiteHeadroom(project)) { + if (await websiteHeadroom(project)) { scripts.push(navigationDependency("headroom.min.js")); } return { diff --git a/src/project/types/website/website-search.ts b/src/project/types/website/website-search.ts index 254d72c384..10890f2ea6 100644 --- a/src/project/types/website/website-search.ts +++ b/src/project/types/website/website-search.ts @@ -407,13 +407,13 @@ export async function updateSearchIndex( const kDefaultCollapse = 3; -export function searchOptions( +export async function searchOptions( project: ProjectContext, -): SearchOptions | undefined { +): Promise { const searchMetadata = websiteConfigMetadata(kSearch, project.config); // The location of the search input - const location = searchInputLocation(project); + const location = await searchInputLocation(project); if (searchMetadata) { // Sort out collapsing (by default, show 2 sections per document) @@ -545,9 +545,9 @@ function algoliaOptions( } } -export function searchInputLocation( +export async function searchInputLocation( project: ProjectContext, -): SearchInputLocation { +): Promise { const searchConfig = websiteConfigMetadata(kSearch, project.config); if (searchConfig && searchConfig[kLocation]) { switch (searchConfig[kLocation]) { @@ -558,7 +558,7 @@ export function searchInputLocation( return "navbar"; } } else { - const { navbar } = websiteNavigationConfig(project); + const { navbar } = await websiteNavigationConfig(project); if (navbar) { return "navbar"; } else { @@ -581,7 +581,7 @@ export function websiteSearchSassBundle() { }; } -export function websiteSearchIncludeInHeader( +export async function websiteSearchIncludeInHeader( project: ProjectContext, format: Format, temp: TempContext, @@ -589,7 +589,7 @@ export function websiteSearchIncludeInHeader( // Generates a script tag that contains the options for configuring search // which is ready in quarto-search.js const websiteSearchScript = temp.createFile({ suffix: "-search.html" }); - const options = searchOptions(project) || {} as SearchOptions; + const options = await searchOptions(project) || {} as SearchOptions; options[kLanguageDefaults] = {} as FormatLanguage; Object.keys(format.language).forEach((key) => { if (key.startsWith("search-")) { @@ -615,14 +615,14 @@ export function websiteSearchIncludeInHeader( return websiteSearchScript; } -export function websiteSearchDependency( +export async function websiteSearchDependency( project: ProjectContext, source: string, -): FormatDependency[] { +): Promise { const searchDependencies: FormatDependency[] = []; const resources: DependencyFile[] = []; - const options = searchOptions(project); + const options = await searchOptions(project); if (options) { const sourceRelative = relative(project.dir, source); const offset = projectOffset(project, source); diff --git a/src/project/types/website/website-shared.ts b/src/project/types/website/website-shared.ts index 11bc953718..204a5faec2 100644 --- a/src/project/types/website/website-shared.ts +++ b/src/project/types/website/website-shared.ts @@ -114,7 +114,7 @@ export function inputFileHref(href: string) { return pathWithForwardSlashes(htmlHref); } -export function websiteNavigationConfig(project: ProjectContext) { +export async function websiteNavigationConfig(project: ProjectContext) { // read navbar let navbar = websiteConfig(kSiteNavbar, project.config) as | Navbar @@ -164,6 +164,22 @@ export function websiteNavigationConfig(project: ProjectContext) { } } + const projectBrand = await project.resolveBrand(); + if ( + projectBrand && sidebars && sidebars[0] && projectBrand.processedData.logo + ) { + if (sidebars[0].logo === undefined) { + const logo = projectBrand.processedData.logo.medium ?? + projectBrand.processedData.logo.small ?? + projectBrand.processedData.logo.large; + if (typeof logo === "string") { + sidebars[0].logo = logo; + } else if (typeof logo === "object") { + sidebars[0].logo = logo.light; // TODO: This needs smarts to work on light+dark themes + } + } + } + // if there is more than one sidebar then propagate options from the // first sidebar to the others if (sidebars && sidebars.length > 1) { From 572c90b4e2f07b45f8ed93024d3574e4ebb588d4 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Mon, 7 Oct 2024 13:19:26 -0700 Subject: [PATCH 2/2] brand,html - forward logo to navbar --- src/project/types/website/website-shared.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/project/types/website/website-shared.ts b/src/project/types/website/website-shared.ts index 204a5faec2..6fff5d2196 100644 --- a/src/project/types/website/website-shared.ts +++ b/src/project/types/website/website-shared.ts @@ -166,7 +166,7 @@ export async function websiteNavigationConfig(project: ProjectContext) { const projectBrand = await project.resolveBrand(); if ( - projectBrand && sidebars && sidebars[0] && projectBrand.processedData.logo + projectBrand?.processedData.logo && sidebars?.[0] ) { if (sidebars[0].logo === undefined) { const logo = projectBrand.processedData.logo.medium ?? @@ -180,6 +180,19 @@ export async function websiteNavigationConfig(project: ProjectContext) { } } + if ( + projectBrand?.processedData && navbar + ) { + const logo = projectBrand.processedData.logo.small ?? + projectBrand.processedData.logo.medium ?? + projectBrand.processedData.logo.large; + if (typeof logo === "string") { + navbar.logo = logo; + } else if (typeof logo === "object") { + navbar.logo = logo.light; // TODO: This needs smarts to work on light+dark themes + } + } + // if there is more than one sidebar then propagate options from the // first sidebar to the others if (sidebars && sidebars.length > 1) {