@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
JavaScript
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 };