// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. import { html, render, TemplateResult } from 'lit-html' import { breakWordLit, isExternalHref, meta } from './helper' import { themePicker } from './theme' import { TocNode } from './toc' export type NavItem = { name: string href: URL } export type NavItemContainer = { name: string items: NavItem[] } /** * @returns active navbar items */ export async function renderNavbar(): Promise { const navbar = document.getElementById('navbar') if (!navbar) { return } const navItems = await loadNavItems() const activeItem = findActiveItem(navItems) const menuItem = item => { const current = (item === activeItem ? 'page' : false) const active = (item === activeItem ? 'active' : null) return html`` } const menu = html` ` function renderCore() { const icons = html`
${window.docfx.iconLinks?.map(i => html``)} ${themePicker(renderCore)} Sponsor
` render(html`${menu} ${icons}`, navbar) } renderCore() return activeItem ? [activeItem] : [] async function loadNavItems(): Promise<(NavItem | NavItemContainer)[]> { const navrel = meta('docfx:navrel') if (!navrel) { return [] } const navUrl = new URL(navrel.replace(/.html$/gi, '.json'), window.location.href) const { items } = await fetch(navUrl).then(res => res.json()) return items.map((a: NavItem | NavItemContainer) => { if ('items' in a) { return { name: a.name, items: a.items.map(i => ({ name: i.name, href: new URL(i.href, navUrl) })) } } return { name: a.name, href: new URL(a.href, navUrl) } }) } } export function renderBreadcrumb(breadcrumb: (NavItem | TocNode)[]) { const container = document.getElementById('breadcrumb') if (container) { render( html` `, container) } } export function renderInThisArticle() { const affix = document.getElementById('affix') const windowPathname = window.location.pathname if (windowPathname === '' || windowPathname === '/' || windowPathname === '/index.html') { return } if (affix) { render(document.body.getAttribute('data-yaml-mime') === 'ManagedReference' ? inThisArticleForManagedReference() : inThisArticleForConceptual(), affix) } } function inThisArticleForConceptual() { const headings = document.querySelectorAll('article h2') if (headings.length > 0) { return html`
In this article
` } } function inThisArticleForManagedReference(): TemplateResult { let headings = Array.from(document.querySelectorAll('article h2, article h3')) headings = headings.filter((h, i) => h.tagName === 'H3' || headings[i + 1]?.tagName === 'H3') if (headings.length > 0) { return html`
In this article
` } } function findActiveItem(items: (NavItem | NavItemContainer)[]): NavItem { const url = new URL(window.location.href) let activeItem: NavItem let maxPrefix = 0 for (const item of items.map(i => 'items' in i ? i.items : i).flat()) { if (isExternalHref(item.href)) { continue } const prefix = commonUrlPrefix(url, item.href) if (prefix > maxPrefix) { maxPrefix = prefix activeItem = item } } return activeItem } function commonUrlPrefix(url: URL, base: URL): number { const urlSegments = url.pathname.split('/') const baseSegments = base.pathname.split('/') let i = 0 while (i < urlSegments.length && i < baseSegments.length && urlSegments[i] === baseSegments[i]) { i++ } return i }