UNPKG

solidity-docgen

Version:

Documentation generator for Solidity smart contracts.

88 lines (74 loc) 2.57 kB
import Handlebars, { RuntimeOptions } from 'handlebars'; import { Site, Page, DocItemWithContext, DOC_ITEM_CONTEXT } from './site'; import { Templates } from './templates'; import { itemType } from './utils/item-type'; import fs from 'fs'; export interface RenderedPage { id: string; contents: string; } interface TemplateOptions { data: { site: Site; }; } export function render(site: Site, templates: Templates, collapseNewlines?: boolean): RenderedPage[] { const renderPage = buildRenderer(templates); const renderedPages: RenderedPage[] = []; for (const page of site.pages) { let contents = renderPage(page, { data: { site } }); if (collapseNewlines) { contents = contents.replace(/\n{3,}/g, '\n\n'); } renderedPages.push({ id: page.id, contents, }); } return renderedPages; } export const itemPartialName = (item: DocItemWithContext) => itemType(item).replace(/ /g, '-').toLowerCase(); function itemPartial(item: DocItemWithContext, options?: RuntimeOptions) { if (!item.__item_context) { throw new Error(`Partial 'item' used in unsupported context (not a doc item)`); } const partial = options?.partials?.[itemPartialName(item)]; if (!partial) { throw new Error(`Missing partial '${itemPartialName(item)}'`); } return partial(item, options); } function readmeHelper(H: typeof Handlebars, path: string, opts: RuntimeOptions) { const items: DocItemWithContext[] = opts.data.root.items; const renderedItems = Object.fromEntries( items.map(item => [ item.name, new H.SafeString( H.compile('{{>item}}')(item, opts), ), ]), ); return new H.SafeString( H.compile(fs.readFileSync(path, 'utf8'))(renderedItems, opts), ); } function buildRenderer(templates: Templates): (page: Page, options: TemplateOptions) => string { const pageTemplate = templates.partials?.page; if (pageTemplate === undefined) { throw new Error(`Missing 'page' template`); } const H = Handlebars.create(); for (const [name, getBody] of Object.entries(templates.partials ?? {})) { let partial: HandlebarsTemplateDelegate | undefined; H.registerPartial(name, (...args) => { partial ??= H.compile(getBody()); return partial(...args); }); } H.registerHelper('readme', (path: string, opts: RuntimeOptions) => readmeHelper(H, path, opts)); for (const [name, fn] of Object.entries(templates.helpers ?? {})) { H.registerHelper(name, fn); } H.registerPartial('item', itemPartial); return H.compile('{{>page}}'); }