/** * Auxiliary module to provide code api documentation. * * * Once 'backend' data has been generated, customization of the output is using a layer running in the * browser. For now, the customization is essentially defined using css through the {@link Configuration.css} attribute. * Its purpose is to link {@link Semantic.role} attribute to display options. * * For instance, * this * is the default css file of the {@link configurationTsTypedoc}. * * @module CodeApi */ export * from './attribute.view' export * from './type.view' export * from './code.view' export * from './configurations' export * from './documentation.view' export * from './models' export * from './module.view' export * from './utils' import { combineLatest, map, Observable } from 'rxjs' import { ModuleView } from './module.view' import { AnyVirtualDOM } from '@youwol/rx-vdom' import { Configuration } from './configurations' import { request$, raiseHTTPErrors } from '@youwol/http-primitives' import { Module, Project } from './models' import { install } from '@youwol/webpm-client' import type { Decoration, Navigation, Router, Views } from '../index' import type { installNotebookModule } from '../../index' import type { parseMd } from '../markdown' export class Dependencies { public static parseMd: typeof parseMd = undefined public static Views: typeof Views = undefined public static installNotebookModule: typeof installNotebookModule = undefined public static headingPrefixId: string } export const tocConvertor = (heading: HTMLHeadingElement): AnyVirtualDOM => { const classes = heading.firstChild ? (heading.firstChild as HTMLElement).classList?.value : '' return { tag: 'div' as const, innerText: heading.firstChild['innerText'] || heading.innerText, class: `${classes} fv-hover-text-focus`, } } export function fetchModuleDoc({ modulePath, basePath, configuration, project, }: { modulePath: string basePath: string configuration: Configuration project: Project }): Observable { const assetPath = `${basePath}/${modulePath}.json` return combineLatest([ request$(new Request(assetPath)).pipe(raiseHTTPErrors()), install({ css: [configuration.css(project)], }), ]).pipe(map(([mdle]) => mdle)) } export const docNode: ({ project, configuration, }: { project: Project configuration: Configuration }) => Navigation = ({ project, configuration }) => ({ name: 'API', tableOfContent: (d: { html: HTMLElement; router: Router }) => Dependencies.Views.tocView({ ...d, domConvertor: tocConvertor }), html: () => ({ tag: 'div', innerText: 'The modules of the project', }), '/api': { name: project.name, tableOfContent: (d: { html: HTMLElement; router: Router }) => Dependencies.Views.tocView({ ...d, domConvertor: tocConvertor }), html: ({ router }) => fetchModuleDoc({ modulePath: project.name, basePath: project.docBasePath, configuration, project, }).pipe( map((module: Module) => { return new ModuleView({ module, router, configuration, project, }) }), ), '...': ({ path, router }: { path: string; router: Router }) => docNavigation({ modulePath: path, router, project, configuration, }), }, }) export const docNavigation = ({ modulePath, router, project, configuration, }: { modulePath: string router: Router project: Project configuration: Configuration }) => { if (modulePath === '') { modulePath = project.name } if (!modulePath.startsWith(project.name)) { modulePath = `${project.name}/${modulePath}` } return fetchModuleDoc({ modulePath, basePath: project.docBasePath, configuration, project, }).pipe( map((module) => { return { children: module.children?.length > 0 ? module.children.map((m) => ({ name: m.name, leaf: m.isLeaf, id: m.name, decoration: { icon: { tag: 'i' as const, class: 'mkapi-semantic-flag mkapi-role-module', }, }, })) : [], html: () => new ModuleView({ module, router, configuration, project }), tableOfContent: (d: { html: HTMLElement; router: Router }) => Dependencies.Views.tocView({ ...d, domConvertor: tocConvertor, }), } }), ) } export function codeApiEntryNode(params: { name: string decoration: Decoration docBasePath: string entryModule: string configuration: Configuration }) { const project = { name: params.entryModule, docBasePath: params.docBasePath, } const configuration = params.configuration return { name: params.name, decoration: params.decoration, html: ({ router }) => { return fetchModuleDoc({ modulePath: project.name, basePath: project.docBasePath, configuration, project, }).pipe( map((module) => { return new ModuleView({ module, router, configuration, project, }) }), ) }, tableOfContent: Dependencies.Views.tocView, '...': ({ router, path }) => docNavigation({ modulePath: path, router, project, configuration, }), } }