@docgeni/template
Version:
Docgeni - Angular Template Components
1 lines • 261 kB
Source Map (JSON)
{"version":3,"file":"docgeni-template.mjs","sources":["../../../packages/template/src/built-in/built-in-component.ts","../../../packages/template/src/built-in/label/label.component.ts","../../../packages/template/src/built-in/label/label.component.html","../../../packages/template/src/built-in/alert/alert.component.ts","../../../packages/template/src/built-in/alert/alert.component.html","../../../packages/template/src/built-in/built-in-components.ts","../../../packages/template/src/built-in/loader.ts","../../../packages/template/src/built-in/built-in.module.ts","../../../packages/template/src/built-in/index.ts","../../../packages/template/src/interfaces/config.ts","../../../packages/template/src/utils/language-compare.ts","../../../packages/template/src/services/global-context.ts","../../../packages/template/src/services/navigation.service.ts","../../../packages/template/src/services/channel.resolver.ts","../../../packages/template/src/services/example-loader.ts","../../../packages/template/src/services/page-title.service.ts","../../../packages/template/src/shared/icon/svgs.ts","../../../packages/template/src/shared/icon/icon.component.ts","../../../packages/template/src/shared/icon/icon.component.html","../../../packages/template/src/utils/color-metadata.ts","../../../packages/template/src/shared/label/label.component.ts","../../../packages/template/src/shared/label/label.component.html","../../../packages/template/src/services/toc.service.ts","../../../packages/template/src/shared/toc/toc.component.ts","../../../packages/template/src/shared/toc/toc.component.html","../../../packages/template/src/shared/locales-selector/locales-selector.component.ts","../../../packages/template/src/shared/locales-selector/locales-selector.component.html","../../../packages/template/src/shared/logo/logo.component.ts","../../../packages/template/src/shared/logo/logo.component.html","../../../packages/template/src/services/search.service.ts","../../../packages/template/src/shared/pipes/translate.pipe.ts","../../../packages/template/src/shared/pipes/highlight.pipe.ts","../../../packages/template/src/shared/search/search.component.ts","../../../packages/template/src/shared/search/search.component.html","../../../packages/template/src/shared/pipes/mode.pipe.ts","../../../packages/template/src/shared/sidebar/sidebar.component.ts","../../../packages/template/src/shared/sidebar/sidebar.component.html","../../../packages/template/src/pages/channel/channel.component.ts","../../../packages/template/src/pages/channel/channel.component.html","../../../packages/template/src/shared/footer/footer.component.ts","../../../packages/template/src/shared/footer/footer.component.html","../../../packages/template/src/shared/doc-header/doc-header.component.ts","../../../packages/template/src/shared/doc-header/doc-header.component.html","../../../packages/template/src/utils.ts","../../../packages/template/src/services/example.service.ts","../../../packages/template/src/services/stackblitz-example.service.ts","../../../packages/template/src/shared/example-renderer/example-renderer.component.ts","../../../packages/template/src/shared/example-renderer/example-renderer.component.html","../../../packages/template/src/shared/content-renderer.ts","../../../packages/template/src/shared/copier/copier.service.ts","../../../packages/template/src/shared/copy/copy.component.ts","../../../packages/template/src/shared/copy/copy.component.html","../../../packages/template/src/shared/source-code/source-code.component.ts","../../../packages/template/src/shared/source-code/source-code.component.html","../../../packages/template/src/shared/example-viewer/example-viewer.component.ts","../../../packages/template/src/shared/example-viewer/example-viewer.component.html","../../../packages/template/src/services/dom-portal-outlet.ts","../../../packages/template/src/shared/content-viewer/content-viewer.component.ts","../../../packages/template/src/shared/doc-meta/doc-meta.component.ts","../../../packages/template/src/shared/doc-meta/doc-meta.component.html","../../../packages/template/src/shared/doc-pages-links/doc-pages-links.component.ts","../../../packages/template/src/shared/doc-pages-links/doc-pages-links.component.html","../../../packages/template/src/pages/component-viewer/component-viewer.component.ts","../../../packages/template/src/pages/component-viewer/component-viewer.component.html","../../../packages/template/src/shared/pipes/assets-content-path.pipe.ts","../../../packages/template/src/shared/pipes/nav.pipe.ts","../../../packages/template/src/pages/doc-viewer/doc-viewer.component.ts","../../../packages/template/src/pages/doc-viewer/doc-viewer.component.html","../../../packages/template/src/pages/component-viewer/overview/component-overview.component.ts","../../../packages/template/src/pages/component-viewer/overview/component-overview.component.html","../../../packages/template/src/shared/pipes/ng-kind.pipe.ts","../../../packages/template/src/shared/pipes/property-name.pipe.ts","../../../packages/template/src/pages/component-viewer/api/component-api.component.ts","../../../packages/template/src/pages/component-viewer/api/component-api.component.html","../../../packages/template/src/pages/component-viewer/examples/component-examples.component.ts","../../../packages/template/src/pages/component-viewer/examples/component-examples.component.html","../../../packages/template/src/shared/pipes/hero.pipe.ts","../../../packages/template/src/pages/home/home.component.ts","../../../packages/template/src/pages/home/home.component.html","../../../packages/template/src/pages/example/example.component.ts","../../../packages/template/src/pages/example/example.component.html","../../../packages/template/src/interfaces/index.ts","../../../packages/template/src/shared/themes-selector/themes-selector.component.ts","../../../packages/template/src/shared/themes-selector/themes-selector.component.html","../../../packages/template/src/shared/navbar/navbar.component.ts","../../../packages/template/src/shared/navbar/navbar.component.html","../../../packages/template/src/pages/root/root.component.ts","../../../packages/template/src/pages/root/root.component.html","../../../packages/template/src/services/router-reset.service.ts","../../../packages/template/src/initializer.ts","../../../packages/template/src/shared/shared.module.ts","../../../packages/template/src/pages/pages.module.ts","../../../packages/template/src/module.ts","../../../packages/template/src/routes.ts","../../../packages/template/src/public-api.ts","../../../packages/template/src/docgeni-template.ts"],"sourcesContent":["import { Directive, ElementRef, Type } from '@angular/core';\n\n@Directive()\nexport abstract class DocgeniBuiltInComponent {\n private classes: string[] = [];\n\n get hostElement(): HTMLElement {\n return this.elementRef.nativeElement;\n }\n\n constructor(protected elementRef: ElementRef) {}\n\n setAttribute(qualifiedName: string, value: string) {\n (this as any)[qualifiedName] = value;\n this.hostElement.setAttribute(qualifiedName, value);\n }\n\n updateHostClass(classes: string[]) {\n if (this.classes) {\n this.classes.forEach((className) => {\n if (!this.classes.includes(className)) {\n this.removeClass(className);\n }\n });\n }\n const newClasses: string[] = [];\n classes.forEach((className) => {\n if (className) {\n newClasses.push(className);\n if (!this.classes.includes(className)) {\n this.addClass(className);\n }\n }\n });\n this.classes = newClasses;\n return this;\n }\n\n addClass(className: string) {\n this.hostElement.classList.add(className);\n }\n\n removeClass(className: string) {\n this.hostElement.classList.remove(className);\n }\n}\n\nexport interface BuiltInComponentDef {\n selector: string;\n component: Type<unknown>;\n}\n","import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit } from '@angular/core';\nimport { DocgeniBuiltInComponent } from '../built-in-component';\n\nexport type DocgeniLabelType = 'primary' | 'danger' | 'warning' | 'info' | '';\n\n@Component({\n selector: 'label',\n templateUrl: './label.component.html',\n host: {\n class: 'dg-label',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false,\n})\nexport class DocgeniLabelComponent extends DocgeniBuiltInComponent implements OnInit {\n private internalType: DocgeniLabelType = 'primary';\n\n get type(): DocgeniLabelType {\n return this.internalType;\n }\n\n @Input() set type(value: DocgeniLabelType) {\n this.internalType = value;\n this.updateHostClass([`dg-label-${this.type}`]);\n }\n\n constructor(elementRef: ElementRef<unknown>) {\n super(elementRef);\n }\n\n ngOnInit(): void {\n this.updateHostClass([`dg-label-${this.type}`]);\n }\n}\n\nexport default {\n selector: 'label',\n component: DocgeniLabelComponent,\n};\n","<ng-content></ng-content>\n","import { Component, ElementRef, Input, OnInit, ChangeDetectionStrategy } from '@angular/core';\nimport { DocgeniBuiltInComponent } from '../built-in-component';\n\nexport type DocgeniAlertType = 'primary' | 'info' | 'success' | 'warning' | 'danger';\n\n@Component({\n selector: 'alert',\n templateUrl: './alert.component.html',\n host: {\n class: 'dg-alert',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false,\n})\nexport class DocgeniAlertComponent extends DocgeniBuiltInComponent implements OnInit {\n private internalType: DocgeniAlertType = 'info';\n\n get type(): DocgeniAlertType {\n return this.internalType;\n }\n\n @Input() set type(value: DocgeniAlertType) {\n this.internalType = value;\n this.updateHostClass([`dg-alert-${this.type}`]);\n }\n\n constructor(elementRef: ElementRef<unknown>) {\n super(elementRef);\n }\n\n ngOnInit(): void {\n this.updateHostClass([`dg-alert-${this.type}`]);\n }\n}\n\nexport default {\n selector: 'alert',\n component: DocgeniAlertComponent,\n};\n","<ng-content></ng-content>\n","import { BuiltInComponentDef } from './built-in-component';\n\nlet builtInComponents: BuiltInComponentDef[];\nexport function setBuiltInComponents(components: BuiltInComponentDef[]) {\n builtInComponents = components || [];\n}\n\nexport function getBuiltInComponents(): BuiltInComponentDef[] {\n return builtInComponents;\n}\n\nexport function addBuiltInComponents(components: BuiltInComponentDef[]) {\n builtInComponents = builtInComponents ? builtInComponents.concat(components) : components;\n}\n","import { setBuiltInComponents } from './built-in-components';\nimport label from './label/label.component';\nimport alert from './alert/alert.component';\n\nexport function loadBuiltInComponents() {\n setBuiltInComponents([label, alert]);\n}\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { DocgeniLabelComponent } from './label/label.component';\nimport { DocgeniAlertComponent } from './alert/alert.component';\nimport { loadBuiltInComponents } from './loader';\n\n@NgModule({\n declarations: [DocgeniLabelComponent, DocgeniAlertComponent],\n imports: [CommonModule],\n exports: [],\n providers: [],\n})\nexport class DocgeniBuiltInModule {\n constructor() {\n loadBuiltInComponents();\n }\n}\n","import label from './label/label.component';\nimport alert from './alert/alert.component';\nexport * from './built-in.module';\nexport * from './built-in-component';\nexport * from './built-in-components';\n\nexport const BUILT_IN_COMPONENTS = [label, alert];\n","import { DocgeniLibrary } from './library';\nimport { Locale } from './locale';\nimport { DocItemToc } from './navigation-item';\n\nexport interface HeroAction {\n text: string;\n link: string;\n btnType?: string;\n btnShape?: 'round' | 'square';\n}\n\nexport interface HomeDocMeta {\n title: string;\n hero: {\n title: string;\n description: string;\n banner: string | string[];\n actions: HeroAction;\n backgroundColor?: string;\n };\n features: {\n icon: string;\n title: string;\n description: string;\n }[];\n contentPath: string;\n}\n\nexport type DocgeniMode = 'full' | 'lite';\n\nexport enum DocgeniTheme {\n light = 'light',\n dark = 'dark',\n system = 'system',\n}\n\nexport interface DocgeniNavItem {\n /** Title for nav item **/\n title: string;\n /** Route path for nav item **/\n path: string;\n /** Whether is external link **/\n isExternal?: boolean;\n /** Lib name for libs **/\n lib?: string;\n /** Locales **/\n locales?: {\n [key: string]: {\n title: string;\n };\n };\n}\n\nexport interface DocgeniAlgoliaConfig {\n appId?: string;\n\n apiKey: string;\n\n indexName: string;\n}\n\nexport interface DocgeniSitemapConfig {\n host?: string;\n}\n\nexport interface DocgeniConfig {\n /** Title of documentation, e.g: Docgeni **/\n title?: string;\n /** Description of documentation **/\n description?: string;\n /** Mode of documentation, full mode contains nav, home page, lite mode only contains menu and doc viewers **/\n mode?: DocgeniMode;\n /** Theme, angular navbar style and default style **/\n theme?: 'default' | 'angular';\n /** Base href of documentation, default is / **/\n baseHref?: string;\n /** Logo url*/\n logoUrl?: string;\n /** Public dir, default is .docgeni/public **/\n publicDir?: string;\n /** Repo url*/\n repoUrl?: string;\n /** Docs dir, default is 'docs' **/\n docsDir?: string;\n /** Site default dir .docgeni/site **/\n siteDir?: string;\n /** Site default dir .docgeni/components **/\n componentsDir?: string;\n /** Site output dir, default is dist/docgeni-site **/\n outputDir?: string;\n /** Angular demo site name in angular.json **/\n siteProjectName?: string;\n /** Angular libraries **/\n libs?: DocgeniLibrary[];\n /** Navigations for menu and nav **/\n navs?: DocgeniNavItem[];\n /** Locales **/\n locales?: Locale[];\n /** Default locale **/\n defaultLocale?: string;\n /** Enable themes */\n switchTheme?: boolean;\n /** footer content **/\n footer?: string;\n /** algolia config */\n algolia?: DocgeniAlgoliaConfig;\n /** default toc, default is content **/\n toc?: DocItemToc;\n /** sitemap config */\n sitemap?: DocgeniSitemapConfig;\n /** Progress */\n progress?: boolean;\n}\n\n// For Angular Template\nexport interface DocgeniSiteConfig {\n /** Title of documentation, e.g: Docgeni **/\n title: string;\n /** Heading of documentation, e.g: Doc Generator, default is same as title **/\n heading?: string;\n /** Description of documentation **/\n description?: string;\n /** Mode of documentation, full mode contains nav, home page, lite mode only contains menu and doc viewers **/\n mode?: 'full' | 'lite';\n /** Theme, angular navbar style and default style **/\n theme?: 'default' | 'angular';\n /** Base href of documentation, default is / **/\n baseHref?: string;\n /** Heads of documentation*/\n heads?: [];\n /** Logo url*/\n logoUrl?: string;\n /** Repo url*/\n repoUrl?: string;\n /** Home meta **/\n homeMeta?: HomeDocMeta;\n /** Locales **/\n locales?: Locale[];\n /** Default locale **/\n defaultLocale?: string;\n /** Enable themes */\n switchTheme?: boolean;\n /** footer content **/\n footer?: string;\n /** algolia config */\n algolia?: DocgeniAlgoliaConfig;\n}\n","export function languageCompare(language1: string, language2: string) {\n return language1.toLocaleLowerCase().replace(/_/g, '-') === language2.toLocaleLowerCase().replace(/_/g, '-');\n}\n","import { Injectable, Inject, InjectionToken, Signal, computed, WritableSignal, signal } from '@angular/core';\nimport { DocgeniSiteConfig, NavigationItem, DocgeniMode, HomeDocMeta, CategoryItem, DocgeniTheme } from '../interfaces/public-api';\nimport { HttpClient } from '@angular/common/http';\nimport { languageCompare } from '../utils/language-compare';\nimport { DOCUMENT, Location } from '@angular/common';\n\nexport const CONFIG_TOKEN = new InjectionToken('DOC_SITE_CONFIG');\n\nexport const DEFAULT_CONFIG: DocgeniSiteConfig = {\n title: 'Docgeni',\n description: '',\n};\n\nconst DOCGENI_LOCALE_KEY = 'docgeni-locale';\nconst DOCGENI_MODE_KEY = 'docgeni-mode';\nconst DOCGENI_THEME_KEY = 'docgeni-theme';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class GlobalContext {\n locale!: string;\n\n navs!: NavigationItem[];\n\n docItems!: NavigationItem[];\n\n homeMeta!: HomeDocMeta;\n\n owner!: string;\n\n repo!: string;\n\n theme: WritableSignal<DocgeniTheme> = signal(DocgeniTheme.light);\n\n isDarkTheme: Signal<boolean> = computed(() => {\n return (\n (this.theme() === DocgeniTheme.system && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ||\n this.theme() === DocgeniTheme.dark\n );\n });\n\n get isDefaultLocale() {\n return this.locale === this.config.defaultLocale;\n }\n\n constructor(\n @Inject(CONFIG_TOKEN) public config: DocgeniSiteConfig,\n private http: HttpClient,\n @Inject(DOCUMENT) private document: any,\n private location: Location,\n ) {\n this.setup();\n }\n\n private getLocaleKey(): string {\n const localeKeyFromUrl = this.getLocalKeyFromUrl();\n if (localeKeyFromUrl) {\n return localeKeyFromUrl;\n } else {\n const cacheLocale = window.localStorage.getItem(DOCGENI_LOCALE_KEY) || window.navigator.language || '';\n const locale = (this.config.locales || []).find((locale) => {\n return languageCompare(locale.key, cacheLocale);\n });\n if (locale) {\n return locale.key;\n } else {\n return this.config.defaultLocale as string;\n }\n }\n }\n\n private setup() {\n this.setLocale(this.getLocaleKey());\n this.setTheme(this.getTheme());\n\n const cacheMode = window.localStorage.getItem(DOCGENI_MODE_KEY);\n if (cacheMode && ['lite', 'full'].includes(cacheMode)) {\n this.config.mode = cacheMode as DocgeniMode;\n }\n\n document.body.classList.add(`dg-mode-${this.config.mode}`, `dg-navbar-theme-${this.config.theme}`);\n if (this.config.repoUrl) {\n const pattern = /https:\\/\\/github.com\\/([^\\/]*)\\/([^\\/]*)/.exec(this.config.repoUrl);\n if (pattern && pattern.length === 3) {\n this.owner = pattern[1];\n this.repo = pattern[2];\n }\n }\n }\n\n public getLocalKeyFromUrl() {\n const localeFromUrl = (this.config.locales || []).find((locale) => {\n return this.location.path().startsWith(`/${locale.key}`);\n });\n return localeFromUrl && localeFromUrl.key;\n }\n\n public setLocale(locale: string) {\n this.locale = locale;\n window.localStorage.setItem(DOCGENI_LOCALE_KEY, locale);\n }\n\n private getTheme(): DocgeniTheme {\n const cacheTheme = window.localStorage.getItem(DOCGENI_THEME_KEY) as DocgeniTheme;\n if (cacheTheme && [DocgeniTheme.light, DocgeniTheme.dark, DocgeniTheme.system].includes(cacheTheme)) {\n return cacheTheme;\n } else {\n return DocgeniTheme.light;\n }\n }\n\n public setTheme(theme: DocgeniTheme) {\n this.theme.set(theme);\n window.localStorage.setItem(DOCGENI_THEME_KEY, theme);\n\n if (this.isDarkTheme()) {\n document.documentElement.setAttribute('theme', DocgeniTheme.dark);\n document.documentElement.style.setProperty('color-scheme', 'dark');\n } else {\n document.documentElement.removeAttribute('theme');\n document.documentElement.style.removeProperty('color-scheme');\n }\n }\n\n getNowTimestamp() {\n return new Date().getTime();\n }\n\n initialize() {\n return new Promise((resolve, reject) => {\n this.http\n .get<{\n navs: NavigationItem[];\n docs: NavigationItem[];\n homeMeta: HomeDocMeta;\n }>(`assets/content/navigations-${this.locale}.json?t=${this.getNowTimestamp()}`)\n .subscribe({\n next: (response: { navs: NavigationItem[]; docs: NavigationItem[]; homeMeta: HomeDocMeta }) => {\n this.homeMeta = response.homeMeta;\n this.navs = response.navs;\n this.docItems = this.sortDocItems(this.navs);\n resolve(response);\n },\n error: (error) => {\n reject(error);\n },\n });\n });\n }\n\n getAssetsContentPath(path: string) {\n return path.startsWith('/') ? `assets/content${path}` : `assets/content/${path}`;\n }\n\n sortDocItems(navs: NavigationItem[]) {\n navs = navs.slice();\n const list: NavigationItem[] = [];\n while (navs.length) {\n const item = navs.shift();\n if (item) {\n if (item.items) {\n item.items.forEach((child: CategoryItem) => {\n child.ancestors = child.ancestors || [];\n child.ancestors.push(...(item.ancestors || []), item);\n });\n navs.unshift(...(item.items as NavigationItem[]));\n } else if (!item.hidden) {\n list.push(item);\n }\n }\n }\n return list;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { NavigationItem, DocItem, ChannelItem, CategoryItem } from '../interfaces/public-api';\nimport { GlobalContext } from './global-context';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class NavigationService {\n channel$ = new BehaviorSubject<ChannelItem | null>(null);\n\n docItem$ = new BehaviorSubject<NavigationItem | null>(null);\n docPages$ = new BehaviorSubject<{ pre: NavigationItem; next: NavigationItem } | null>(null);\n /** Responsive layout, sidebar default is hide */\n showSidebar = false;\n get channel() {\n return this.channel$.value;\n }\n\n get docItem() {\n return this.docItem$.value;\n }\n\n get navs() {\n return this.global.navs;\n }\n\n get docItems() {\n return this.global.docItems;\n }\n\n constructor(private global: GlobalContext) {}\n\n getChannels(): ChannelItem[] {\n return this.navs as ChannelItem[];\n }\n\n getChannel(path: string): ChannelItem {\n return this.navs.find((nav) => {\n return nav.path === path;\n }) as ChannelItem;\n }\n\n getDocItemByPath(path: string) {\n let index: number;\n if (this.channel) {\n // 类库频道\n if (this.channel.lib) {\n index = this.docItems.findIndex((docItem) => {\n return docItem.path === path && docItem.channelPath === this.channel!.path && !!docItem.importSpecifier;\n });\n } else {\n index = this.docItems.findIndex((docItem) => {\n return docItem.path === path && docItem.channelPath === this.channel!.path;\n });\n }\n } else {\n index = this.docItems.findIndex((docItem) => {\n return docItem.path === path && (this.global.config.mode === 'lite' ? true : !docItem.channelPath);\n });\n }\n if (index > -1) {\n const preDocItem = index ? this.docItems[index - 1] : undefined;\n const nextDocItem = this.docItems.length - 1 === index ? undefined : this.docItems[index + 1];\n this.docPages$.next({\n pre: preDocItem!,\n next: nextDocItem!,\n });\n }\n return this.docItems[index];\n }\n\n selectChannelByPath(path: string) {\n const channel = this.getChannel(path);\n this.channel$.next(channel);\n return channel;\n }\n\n clearChannel() {\n this.channel$.next(null);\n }\n\n selectDocItem(path: string) {\n const docItem = this.getDocItemByPath(path);\n this.docItem$.next(docItem);\n }\n\n getChannelFirstDocItem() {\n if (this.channel && this.channel.items) {\n return this.searchFirstDocItem(this.channel.items as NavigationItem[]);\n }\n return null;\n }\n\n searchFirstDocItem(items: NavigationItem[] = this.navs) {\n let docItem: DocItem;\n for (const nav of items) {\n if (this.isDocItem(nav)) {\n docItem = nav;\n } else {\n docItem = this.getNavFirstDocItem(nav as NavigationItem);\n }\n if (docItem) {\n break;\n }\n }\n return docItem!;\n }\n\n getNavFirstDocItem(nav: NavigationItem) {\n let docItem: DocItem;\n for (const item of nav.items!) {\n if (item && this.isCategoryItem(item)) {\n docItem = this.getNavFirstDocItem(item as NavigationItem);\n } else {\n docItem = item as DocItem;\n }\n if (docItem) {\n break;\n }\n }\n return docItem!;\n }\n\n toggleSidebar() {\n this.showSidebar = !this.showSidebar;\n }\n\n resetShowSidebar() {\n this.showSidebar = false;\n }\n\n private isCategoryItem(category: CategoryItem | DocItem): category is CategoryItem {\n return (category as any).items;\n }\n\n private isDocItem(item: any): item is DocItem {\n return !item.items;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { ActivatedRouteSnapshot } from '@angular/router';\nimport { Observable } from 'rxjs';\nimport { NavigationService } from './navigation.service';\nimport { ChannelItem } from '../interfaces/public-api';\n\n@Injectable({ providedIn: 'root' })\nexport class ChannelResolver {\n constructor(private navigationService: NavigationService) {}\n\n resolve(route: ActivatedRouteSnapshot): Observable<ChannelItem> | Promise<ChannelItem> | ChannelItem {\n const path = route.paramMap.get('channel');\n const channel = this.navigationService.getChannel(path!);\n return channel;\n }\n}\n","import { Injectable, Type } from '@angular/core';\nimport { LiveExample } from '../interfaces/public-api';\n\nexport interface ExampleLoadResult {\n moduleType: Type<any>;\n componentType: Type<any>;\n example: LiveExample;\n}\n@Injectable()\nexport abstract class ExampleLoader {\n enableIvy!: boolean;\n abstract load(exampleName: string): Promise<ExampleLoadResult>;\n}\n","import { Injectable } from '@angular/core';\nimport { Title } from '@angular/platform-browser';\nimport { GlobalContext } from './global-context';\n\n@Injectable({ providedIn: 'root' })\nexport class PageTitleService {\n private innerTitle = '';\n\n get title(): string {\n return this.innerTitle;\n }\n\n set title(title: string) {\n this.innerTitle = title;\n if (title !== '') {\n title = `${title} - ${this.globalContext.config.title}`;\n } else {\n title = this.globalContext.config.title;\n }\n this.bodyTitle.setTitle(title);\n }\n\n constructor(\n private bodyTitle: Title,\n private globalContext: GlobalContext,\n ) {}\n}\n","const github = `<svg focusable=\"false\" viewBox=\"0 0 51.8 50.4\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\">\n<path\n d=\"M25.9,0.2C11.8,0.2,0.3,11.7,0.3,25.8c0,11.3,7.3,20.9,17.5,24.3c1.3,0.2,1.7-0.6,1.7-1.2c0-0.6,0-2.6,0-4.8c-7.1,1.5-8.6-3-8.6-3c-1.2-3-2.8-3.7-2.8-3.7c-2.3-1.6,0.2-1.6,0.2-1.6c2.6,0.2,3.9,2.6,3.9,2.6c2.3,3.9,6,2.8,7.5,2.1c0.2-1.7,0.9-2.8,1.6-3.4c-5.7-0.6-11.7-2.8-11.7-12.7c0-2.8,1-5.1,2.6-6.9c-0.3-0.7-1.1-3.3,0.3-6.8c0,0,2.1-0.7,7,2.6c2-0.6,4.2-0.9,6.4-0.9c2.2,0,4.4,0.3,6.4,0.9c4.9-3.3,7-2.6,7-2.6c1.4,3.5,0.5,6.1,0.3,6.8c1.6,1.8,2.6,4.1,2.6,6.9c0,9.8-6,12-11.7,12.6c0.9,0.8,1.7,2.4,1.7,4.7c0,3.4,0,6.2,0,7c0,0.7,0.5,1.5,1.8,1.2c10.2-3.4,17.5-13,17.5-24.3C51.5,11.7,40.1,0.2,25.9,0.2z\"\n></path>\n</svg>`;\n\nconst code = `<svg\nviewBox=\"0 0 16 16\"\nxmlns=\"http://www.w3.org/2000/svg\"\nfit=\"\"\nheight=\"1em\"\nwidth=\"1em\"\npreserveAspectRatio=\"xMidYMid meet\"\nfocusable=\"false\"\n>\n<g fill-rule=\"evenodd\">\n <path d=\"M.003 8.306l4.302 4.304.849-.848L.852 7.458z\"></path>\n <path d=\"M0 8.308l.847.85 4.31-4.296-.847-.85zM10.8 4.861l4.309 4.296.848-.85-4.309-4.296z\"></path>\n <path d=\"M10.804 11.762l.849.848 4.302-4.304-.85-.848zM8.526 4L6.1 12.582l1.241.006 2.435-8.565z\"></path>\n</g>\n</svg>`;\n\nconst external = `<svg\nfit=\"\"\nfocusable=\"false\"\nheight=\"100%\"\npreserveAspectRatio=\"xMidYMid meet\"\nviewBox=\"0 0 24 24\"\nwidth=\"100%\"\nxmlns=\"http://www.w3.org/2000/svg\"\n>\n<path d=\"M0 0h24v24H0z\" fill=\"none\"></path>\n<path\n d=\"M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z\"\n></path>\n</svg>`;\n\nconst copy = `<svg\nviewBox=\"0 0 16 16\"\nxmlns=\"http://www.w3.org/2000/svg\"\nfit=\"\"\nheight=\"1em\"\nwidth=\"1em\"\npreserveAspectRatio=\"xMidYMid meet\"\nfocusable=\"false\"\n>\n<path\n d=\"M7.6 8.2V7h4.174v1.2H7.6zm0 3V10h4.174v1.2H7.6zm-4.4-10v10.074H2L2.003 2c0-1.088.895-2 1.997-2h7.585v1.2H3.2zM5 2h9a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1zm.2 1.2v11.6h8.6V3.2H5.2z\"\n></path>\n</svg>`;\n\nconst check = `\n<svg\n viewBox=\"0 0 16 16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fit=\"\"\n height=\"1em\"\n width=\"1em\"\n preserveAspectRatio=\"xMidYMid meet\"\n focusable=\"false\"\n>\n <path d=\"M6.012 11.201L1.313 6.832l-.817.879 5.54 5.15 9.304-9.163-.842-.855z\"></path>\n</svg>`;\n\nconst list = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" id=\"align-justify\">\n<g id=\"ageditor/align-justify\" stroke-width=\"1\" fill-rule=\"evenodd\">\n <path d=\"M0 1h16v1.2H0V1zm0 6.4h16v1.2H0V7.4zm0 6.4h16V15H0v-1.2z\" id=\"ag合并形状\"></path>\n</g>\n</svg>`;\nconst arrowLeft = `<svg width=\"1em\" height=\"1em\" viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <!-- Generator: Sketch 55.2 (78181) - https://sketchapp.com -->\n <title>navigation/arrow-left</title>\n <desc>Created with Sketch.</desc>\n <g id=\"navigation/arrow-left\" stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n <path d=\"M7.4,4.14955232 L4.4383,7.3151 C4.2123,7.5571 3.8323,7.5691 3.5903,7.3431 C3.3483,7.1161 3.3353,6.7371 3.5623,6.4951 L7.53151194,2.2516372 C7.55538364,2.21814642 7.58305703,2.18659454 7.6145,2.1576 C7.8585,1.9336 8.2375,1.9496 8.4615,2.1946 L12.4315,6.5176 C12.6565,6.7616 12.6395,7.1416 12.3955,7.3656 C12.1515,7.5896 11.7725,7.5736 11.5475,7.3296 L8.6,4.11846621 L8.6,13.2666667 C8.6,13.6712222 8.331,14 8,14 C7.668,14 7.4,13.6712222 7.4,13.2666667 L7.4,4.14955232 Z\" id=\"形状结合\" transform=\"translate(7.995013, 7.999832) rotate(-90.000000) translate(-7.995013, -7.999832) \"></path>\n </g>\n</svg>`;\nconst arrowRight = `<svg width=\"1em\" height=\"1em\" viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <!-- Generator: Sketch 55.2 (78181) - https://sketchapp.com -->\n <title>navigation/arrow-right</title>\n <desc>Created with Sketch.</desc>\n <g id=\"navigation/arrow-right\" stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n <path d=\"M7.4,4.14955232 L4.4383,7.3151 C4.2123,7.5571 3.8323,7.5691 3.5903,7.3431 C3.3483,7.1161 3.3353,6.7371 3.5623,6.4951 L7.53151194,2.2516372 C7.55538364,2.21814642 7.58305703,2.18659454 7.6145,2.1576 C7.8585,1.9336 8.2375,1.9496 8.4615,2.1946 L12.4315,6.5176 C12.6565,6.7616 12.6395,7.1416 12.3955,7.3656 C12.1515,7.5896 11.7725,7.5736 11.5475,7.3296 L8.6,4.11846621 L8.6,13.2666667 C8.6,13.6712222 8.331,14 8,14 C7.668,14 7.4,13.6712222 7.4,13.2666667 L7.4,4.14955232 Z\" id=\"形状结合\" transform=\"translate(7.995013, 7.999832) rotate(90.000000) translate(-7.995013, -7.999832) \"></path>\n </g>\n</svg>`;\nconst angleRight = `<svg width=\"16px\" height=\"16px\" viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <!-- Generator: Sketch 55.2 (78181) - https://sketchapp.com -->\n <title>navigation/angle-right</title>\n <desc>Created with Sketch.</desc>\n <g id=\"navigation/angle-right\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <path d=\"M7.97815,11.49765 L7.9728,11.503 L2.2998,5.831 L3.1298,5 L7.97807731,9.84827731 L12.8255,5 L13.6565,5.831 L7.9835,11.503 L7.97815,11.49765 Z\" id=\"形状结合\" fill=\"#888888\" transform=\"translate(7.978150, 8.251500) scale(-1, -1) rotate(-270.000000) translate(-7.978150, -8.251500) \"></path>\n </g>\n</svg>`;\nconst search = `<svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fit=\"\" height=\"1em\" width=\"1em\" preserveAspectRatio=\"xMidYMid meet\" focusable=\"false\"><g id=\"oonormal/search\" stroke-width=\"1\" fill-rule=\"evenodd\"><path d=\"M6.751 12.303A5.557 5.557 0 0 1 1.2 6.751C1.2 3.691 3.69 1.2 6.751 1.2a5.558 5.558 0 0 1 5.551 5.551 5.557 5.557 0 0 1-5.551 5.552M6.751 0a6.751 6.751 0 1 0 4.309 11.949l3.855 3.855a.6.6 0 1 0 .849-.849l-3.854-3.853A6.751 6.751 0 0 0 6.751 0\" id=\"ooFill-1\"></path></g></svg>`;\nconst empty = `<svg width=\"148px\" height=\"134px\" viewBox=\"0 0 148 134\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" class=\"ng-star-inserted\"><defs><filter x=\"0.0%\" y=\"0.0%\" width=\"100.0%\" height=\"100.0%\" filterUnits=\"objectBoundingBox\" id=\"filter-1\"><feGaussianBlur stdDeviation=\"0\" in=\"SourceGraphic\"></feGaussianBlur></filter></defs><g id=\"148x134\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\"><g id=\"编组-6\" transform=\"translate(1.000000, 1.000000)\"><ellipse id=\"椭圆形\" fill=\"#EDEEF2\" opacity=\"0.3\" filter=\"url(#filter-1)\" cx=\"73.0800017\" cy=\"115.920003\" rx=\"73.0800017\" ry=\"16.8000004\"></ellipse><g id=\"编组-5\" transform=\"translate(15.120000, 0.000000)\"><polygon id=\"矩形\" fill=\"#E2E4E9\" points=\"19.2789848 49.5600011 99.1200023 48.7200011 117.600003 75.9297673 117.600003 92.313049 0 92.313049 0 75.0356267\"></polygon><path d=\"M23.5200005,0 L94.0800002,0 C97.7913538,2.06413823e-16 100.8,3.00864655 100.8,6.72000015 L100.8,99.1200023 L100.8,99.1200023 L16.8000004,99.1200023 L16.8000004,6.72000015 C16.8000004,3.00864655 19.8086469,1.56994302e-15 23.5200005,0 Z\" id=\"矩形\" fill=\"#F9FAFB\"></path><path d=\"M30.9200007,12.4400003 L86.6800019,12.4400003 C88.5356787,12.4400003 90.040002,13.9443236 90.040002,15.8000004 L90.040002,42.000001 C90.040002,43.8556778 88.5356787,45.360001 86.6800019,45.360001 L30.9200007,45.360001 C29.0643239,45.360001 27.5600006,43.8556778 27.5600006,42.000001 L27.5600006,15.8000004 C27.5600006,13.9443236 29.0643239,12.4400003 30.9200007,12.4400003 Z\" id=\"矩形\" fill=\"#E8EAEE\"></path><text id=\"</null>\" font-family=\"PingFangSC-Medium, PingFang SC\" font-size=\"15.1200003\" font-weight=\"400\" fill=\"#BCBECD\"><tspan x=\"33.6000008\" y=\"32.8000004\"></null></tspan></text><rect id=\"矩形\" fill=\"#E8EAEE\" x=\"27.5600006\" y=\"52.0800012\" width=\"61.4800014\" height=\"5.04000011\" rx=\"2.52000006\"></rect><rect id=\"矩形备份\" fill=\"#E8EAEE\" x=\"27.5600006\" y=\"63.8400014\" width=\"61.4800014\" height=\"5.04000011\" rx=\"2.52000006\"></rect><path d=\"M0,75.6000017 L29.280235,75.6000017 C32.0637502,75.6000017 34.3202352,77.8564866 34.3202352,80.6400018 L34.3202352,86.2591426 C34.3202352,89.0426578 36.5767201,91.2991427 39.3602353,91.2991427 L78.4136737,91.2991427 C81.1971889,91.2991427 83.4536738,89.0426578 83.4536738,86.2591426 L83.4536738,80.6400018 C83.4536738,77.8564866 85.7101587,75.6000017 88.4936739,75.6000017 L117.600003,75.6000017 L117.600003,75.6000017 L117.600003,110.880003 C117.600003,115.519195 113.839194,119.280003 109.200002,119.280003 L8.40000019,119.280003 C3.76080819,119.280003 -6.53729019e-15,115.519195 0,110.880003 L0,75.6000017 L0,75.6000017 Z\" id=\"矩形\" fill=\"#EDEFF2\"></path></g></g></g></svg>`;\nconst stackBlitz = `<svg viewBox=\"0 0 28 28\" aria-hidden=\"true\" class=\"StackBlitzLogo-module-boltIcon-3IWaX\" width=\"28\" height=\"28\"><path d=\"M12.747 16.273h-7.46L18.925 1.5l-3.671 10.227h7.46L9.075 26.5l3.671-10.227z\"></path></svg>`;\n\nconst lightTheme = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" viewBox=\"0 0 48 48\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"24\" cy=\"24\" r=\"9\" fill=\"currentColor\" stroke=\"none\"/><path fill=\"currentColor\" stroke=\"none\" d=\"M21 5.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-5ZM21 37.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-5ZM42.5 21a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-5a.5.5 0 0 1 .5-.5h5ZM10.5 21a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-5a.5.5 0 0 1 .5-.5h5ZM39.203 34.96a.5.5 0 0 1 0 .707l-3.536 3.536a.5.5 0 0 1-.707 0l-3.535-3.536a.5.5 0 0 1 0-.707l3.535-3.535a.5.5 0 0 1 .707 0l3.536 3.535ZM16.575 12.333a.5.5 0 0 1 0 .707l-3.535 3.535a.5.5 0 0 1-.707 0L8.797 13.04a.5.5 0 0 1 0-.707l3.536-3.536a.5.5 0 0 1 .707 0l3.535 3.536ZM13.04 39.203a.5.5 0 0 1-.707 0l-3.536-3.536a.5.5 0 0 1 0-.707l3.536-3.535a.5.5 0 0 1 .707 0l3.536 3.535a.5.5 0 0 1 0 .707l-3.536 3.536ZM35.668 16.575a.5.5 0 0 1-.708 0l-3.535-3.535a.5.5 0 0 1 0-.707l3.535-3.536a.5.5 0 0 1 .708 0l3.535 3.536a.5.5 0 0 1 0 .707l-3.535 3.535Z\"/></svg>`;\nconst darkTheme = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" viewBox=\"0 0 48 48\" aria-hidden=\"true\" focusable=\"false\"><path fill=\"currentColor\" stroke=\"none\" d=\"M42.108 29.769c.124-.387-.258-.736-.645-.613A17.99 17.99 0 0 1 36 30c-9.941 0-18-8.059-18-18 0-1.904.296-3.74.844-5.463.123-.387-.226-.768-.613-.645C10.558 8.334 5 15.518 5 24c0 10.493 8.507 19 19 19 8.482 0 15.666-5.558 18.108-13.231Z\"/></svg>`;\nconst systemTheme = `<svg fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" viewBox=\"0 0 48 48\" width=\"1em\" height=\"1em\"><path d=\"M24 32v8m0 0h-9m9 0h9M7 32h34a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1v22a1 1 0 0 0 1 1Z\"></path></svg>`;\n\nconst locale = `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M2 5C2 3.34315 3.34315 2 5 2H7C8.65685 2 10 3.34315 10 5V11H8V8.5H4V11H2V5ZM4 6.5H8V5C8 4.44772 7.55228 4 7 4H5C4.44772 4 4 4.44772 4 5V6.5ZM12 3.5H18C19.6569 3.5 21 4.84315 21 6.5V9H19V6.5C19 5.94772 18.5523 5.5 18 5.5H12V3.5ZM18 11.5V13H22V15H20.9381C20.7182 16.7638 19.9241 18.3492 18.7488 19.5634C19.4441 19.845 20.2041 20 21 20H22V22H21C19.5425 22 18.1765 21.6102 17.0001 20.9297C15.8234 21.6104 14.4572 22 13 22H12V20H13C13.7962 20 14.5562 19.8449 15.2514 19.5633C14.6487 18.9407 14.1463 18.2205 13.7704 17.4291L13.3413 16.5258L15.1478 15.6676L15.5769 16.5709C15.9219 17.2971 16.4081 17.9427 16.9999 18.4723C17.9921 17.5843 18.687 16.371 18.917 15H12V13H16V11.5H18ZM6 13V19C6 19.5523 6.44772 20 7 20H9.5V22H7C5.34315 22 4 20.6569 4 19V13H6Z\" fill=\"currentColor\"/>\n</svg>`;\n\nexport const BUILTIN_SVGS: Record<string, string> = {\n github,\n code,\n external,\n copy,\n check,\n list,\n arrowLeft,\n arrowRight,\n angleRight,\n search,\n empty,\n stackBlitz,\n locale,\n lightTheme,\n darkTheme,\n systemTheme,\n};\n","import { Component, OnInit, Input, AfterViewInit, ElementRef, HostBinding } from '@angular/core';\nimport { BUILTIN_SVGS } from './svgs';\nimport { DomSanitizer } from '@angular/platform-browser';\n\n@Component({\n selector: 'dg-icon',\n templateUrl: './icon.component.html',\n standalone: false,\n})\nexport class IconComponent implements OnInit, AfterViewInit {\n @HostBinding('class.dg-icon') isIcon = true;\n\n @Input() set iconName(name: string) {\n this.setSvg(name);\n }\n\n constructor(\n private elementRef: ElementRef<HTMLElement>,\n private domSanitizer: DomSanitizer,\n ) {}\n\n ngOnInit(): void {}\n\n ngAfterViewInit() {}\n\n setSvg(name: string) {\n const svg = BUILTIN_SVGS[name];\n if (svg) {\n this.elementRef.nativeElement.innerHTML = svg;\n } else {\n this.elementRef.nativeElement.innerHTML = '';\n }\n }\n}\n","<ng-content></ng-content>\n","export function colorMetadata(color: string) {\n let obj: { r?: number; g?: number; b?: number };\n if (color.startsWith('#')) {\n obj = hexColorMetadata(color);\n } else if (color.startsWith('rgb')) {\n obj = rgbColorMetadata(color);\n } else {\n throw new Error('unsupported color format ' + color);\n }\n return obj;\n}\n\nfunction hexColorMetadata(color: string) {\n const rgx = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\n const hex = color.replace(rgx, (m: any, r: any, g: any, b: any) => r + r + g + g + b + b);\n const rgb = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return rgb ? { r: parseInt(rgb[1], 16), g: parseInt(rgb[2], 16), b: parseInt(rgb[3], 16) } : {};\n}\n\nfunction rgbColorMetadata(color: string) {\n const result = /rgb\\(([0-9]{1,3})\\s*[,\\s]\\s*([0-9]{1,3})\\s*[,\\s]\\s*([0-9]{1,3})\\)/i.exec(color);\n return result\n ? {\n r: parseInt(result[1], 10),\n g: parseInt(result[2], 10),\n b: parseInt(result[3], 10),\n }\n : {};\n}\n","import { Component, OnInit, Input, HostBinding, ElementRef, Renderer2 } from '@angular/core';\nimport { colorMetadata } from '../../utils/color-metadata';\n\ntype LabelType = 'primary' | 'danger' | 'warning' | 'info' | '';\nconst LABEL_LIST = ['primary', 'danger', 'warning', 'info'];\n\n@Component({\n selector: 'dg-label',\n templateUrl: './label.component.html',\n standalone: false,\n})\nexport class LabelComponent implements OnInit {\n @HostBinding(`class`) classList!: string[];\n\n @Input() set labelType(value: LabelType) {\n if (LABEL_LIST.includes(value)) {\n this.classList = ['dg-label', `dg-label-${value}`];\n } else {\n this.classList = ['dg-label'];\n this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', this.getBackgroundColor(value));\n this.renderer.setStyle(this.elementRef.nativeElement, 'color', value);\n }\n }\n\n constructor(\n private elementRef: ElementRef,\n private renderer: Renderer2,\n ) {}\n\n ngOnInit(): void {}\n\n private getBackgroundColor(color: string) {\n const { r, g, b } = colorMetadata(color);\n return `rgba(${r},${g},${b},0.20)`;\n }\n}\n","<ng-content></ng-content>\n","import { DOCUMENT, ViewportScroller } from '@angular/common';\nimport { Inject, Injectable } from '@angular/core';\nimport { fromEvent, Observable, BehaviorSubject, Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { GlobalContext } from './global-context';\n\nexport interface TocLink {\n /* id of the section*/\n id: string;\n\n /* header type h1/h2/h3/h4 */\n type: string;\n\n /* If the anchor is in view of the page */\n active: boolean;\n\n /* name of the anchor */\n name: string;\n\n /* top offset px of the anchor */\n top: number;\n\n /** level of the section */\n level?: number;\n\n element?: HTMLHeadingElement;\n}\n\nlet OFFSET = 0;\n\n@Injectable({\n providedIn: 'root',\n})\nexport class TocService {\n private linksSubject$ = new BehaviorSubject<TocLink[]>([]);\n private activeLinkSubject$ = new BehaviorSubject<TocLink | null>(null);\n private destroyed$ = new Subject<TocLink[] | null>();\n private scrollContainer!: HTMLElement & Window;\n public highestLevel!: number;\n public get links$(): Observable<TocLink[]> {\n return this.linksSubject$.asObservable();\n }\n\n public get links() {\n return this.linksSubject$.value;\n }\n\n public get activeLink$(): Observable<TocLink> {\n return this.activeLinkSubject$.asObservable() as Observable<TocLink>;\n }\n\n constructor(\n @Inject(DOCUMENT) private document: any,\n global: GlobalContext,\n private viewportScroller: ViewportScroller,\n ) {\n if (global.config.mode === 'lite') {\n OFFSET = 0;\n }\n this.viewportScroller.setOffset([0, OFFSET]);\n }\n\n reset() {\n this.linksSubject$.next([]);\n this.activeLinkSubject$.next(null);\n this.highestLevel = 0;\n this.destroyed$.next(null);\n this.destroyed$.complete();\n }\n\n generateToc(docViewerContent: HTMLElement, scrollContainer = '.dg-scroll-container') {\n const headers = Array.from<HTMLHeadingElement>(docViewerContent.querySelectorAll('h1, h2, h3, h4, dg-examples'));\n const links: TocLink[] = [];\n headers.forEach((header) => {\n if (header.tagName === 'DG-EXAMPLES') {\n const allExamples = header.querySelectorAll('example');\n const headerLevel = 2;\n allExamples.forEach((example) => {\n links.push({\n name: example.getAttribute('title') as string,\n type: 'h2',\n top: example.getBoundingClientRect().top,\n id: example.getAttribute('name') as string,\n active: false,\n level: headerLevel,\n element: example as HTMLHeadingElement,\n });\n });\n return;\n }\n // remove the 'TocLink' icon name from the inner text\n const name = header.innerText.trim().replace(/^TocLink/, '');\n const { top } = header.getBoundingClientRect();\n const headerLevel = parseInt(header.tagName[1], 10);\n links.push({\n name,\n type: header.tagName.toLowerCase(),\n top,\n id: header.id,\n active: false,\n level: headerLevel,\n element: header,\n });\n this.highestLevel = this.highestLevel && headerLevel > this.highestLevel ? this.highestLevel : headerLevel;\n });\n this.initializeScrollContainer(scrollContainer);\n this.linksSubject$.next(links);\n }\n\n initializeScrollContainer(scrollContainerSelector: string) {\n this.scrollContainer = scrollContainerSelector ? this.document.querySelectorAll(scrollContainerSelector)[0] : window;\n\n Promise.resolve().then(() => {\n if (this.scrollContainer) {\n fromEvent(this.scrollContainer, 'scroll')\n .pipe(takeUntil(this.destroyed$), debounceTime(10))\n .subscribe(() => this.onScroll());\n }\n this.onScroll();\n });\n }\n\n onScroll() {\n const scrollOffset = this.getScrollOffset();\n let activeItem: TocLink;\n if (scrollOffset! <= OFFSET + 1) {\n activeItem = this.links[0];\n } else {\n const itemOffset = this.links.find((link) => {\n return link.element!.offsetTop >= scrollOffset!;\n });\n if (itemOffset) {\n activeItem = itemOffset;\n } else {\n activeItem = this.links[this.links.length - 1];\n }\n }\n\n this.activeLinkSubject$.next(activeItem || null);\n }\n\n scrollToAnchor(urlFragment: string) {\n if (this.scrollContainer) {\n if (this.scrollContainer === this.document.window) {\n this.viewportScroller.scrollToAnchor(urlFragment);\n } else {\n const link = this.links.find((link) => {\n return link.id === urlFragment;\n });\n if (link) {\n this.scrollContainer.scrollTop = link.element!.offsetTop - 10;\n }\n }\n }\n }\n\n private getScrollOffset(): number {\n if (this.scrollContainer) {\n if (typeof this.scrollContainer.scrollTop !== 'undefined') {\n return this.scrollContainer.scrollTop + OFFSET;\n } else if (typeof this.scrollContainer.pageYOffset !== 'undefined') {\n return this.scrollContainer.pageYOffset + OFFSET;\n }\n return 0;\n } else {\n return 0;\n }\n }\n}\n","import { Component, Input, OnDestroy, OnInit, HostBinding } from '@angular/core';\nimport { Locatio