UNPKG

@gouvfr/dsfr-roller

Version:

Le module `dsfr-roller` permet de publier le site de documentation du Système de Design de l’État - DSFR

100 lines (83 loc) 2.68 kB
import { Renderable } from '../../core/renderable.js'; import { Summary } from '../../component/components/summary.js'; const filterHeadings = (list, depths = [2]) => { if (!list || list.length === 0) return undefined; let heading = list[0]; if (!depths.includes(heading.depth)) return undefined; for (heading of list) { if (Array.isArray(heading.list)) { heading.list = filterHeadings(heading.list, depths); } } return list; } class TOC extends Renderable { constructor (data, nodes) { super(data); this._hasToc = data.toc !== undefined; this._nodes = nodes; } async render () { if (!this._hasToc) { return ''; } const headings = this._nodes.filter(node => node.type === 'heading').map (heading => { return { depth: heading.depth, href: `#${heading.normalizedId}`, label: heading.text, }; }); let depths = headings.map(heading => heading.depth).filter((depth, index, array) => array.indexOf(depth) === index).sort((a, b) => a - b); let depth = depths[0]; const lists = []; let mainList = []; let list = mainList; let previous; for (const heading of headings) { switch (true) { case heading.depth === depth: list.push(heading); break; case heading.depth < depth: while (lists.length > 0 && list[0].depth > heading.depth) { list = lists.pop(); } if (list[0].depth === heading.depth) { list.push(heading); depth = heading.depth; } else { list = [heading]; lists.push(list); if (previous) previous.list = list; depth = heading.depth; } break; case heading.depth > depth: lists.push(list); list = [heading]; if (previous) previous.list = list; depth = heading.depth; break; } previous = heading; } while (mainList?.length === 1) mainList = mainList[0].list; if (!mainList || mainList?.length === 0) return ''; switch (typeof this._data.toc) { case 'string': depths = this._data.toc.split(',').map(depth => parseInt(depth.trim(), 10)).filter(depth => !isNaN(depth)); mainList = filterHeadings(mainList, depths); break; case 'number': mainList = filterHeadings(mainList, [this._data.toc]); break; } const summary = new Summary({ title: this.data?.fragments?.summary?.title, list: mainList }); return `<div class="fr-mb-6v" > ${await summary.render()} </div>`; } } export { TOC };