UNPKG

@podlite/toc

Version:

'Table of contents' plugin for Podlite markup language

124 lines 4.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTocPod = exports.prepareDataForToc = void 0; const schema_1 = require("@podlite/schema"); const prepareDataForToc = (data) => { const isSemanticBlock = node => { const name = node.name || ''; const isTypeBlock = (node.type || '') === 'block'; return isTypeBlock && name === name.toUpperCase(); }; const reduceLevel = arr => { return arr.reduce((i, c) => { return (i.includes(c) ? [...i] : [...i, c]).sort((a, b) => a - b); }, []); }; const normalizeLevels = data => { const namesLevels = {}; for (const node of data) { if (isSemanticBlock(node)) { const level = 1; node.level = level; namesLevels['head'] = reduceLevel([...(namesLevels['head'] || []), 1]); } else { // TODO: eliminate string level (=item) // default level is 1 for all items namesLevels[node.name] = reduceLevel([...(namesLevels[node.name] || []), parseInt(node.level, 10) || 1]); } } return namesLevels; }; const levelsMap = normalizeLevels(data); const tocTree = [[-1, { item: 'toc', level: 0, node: {} }]]; /** // find nearest by level const tocTree = [ [ -1, { item: 'toc', level:0 } ], [ 0, { item: 'head', level:1 } ], [ 1, { item: 'head2', level:2 } ], [ 0, { item: 'head', level:1 } ], [ 3, { item: 'item2', level:3 } ], ]; const sq = getIndexByLevel(tocTree, 4) */ const getRootIndexByLevel = (tocTree, level) => { return (tocTree.length - tocTree .slice() .reverse() .findIndex(e => e[1].level < level) - 1); }; let currentLevel = 1; // prepare normilized data for (let i = 0; i < data.length; i++) { const item = data[i]; // deafult level is 1 for all items const normalizedLevel = levelsMap[item.name].findIndex(l => l === parseInt(item.level || 1)) + 1; switch (item.name) { case 'head': { const parent = getRootIndexByLevel(tocTree, normalizedLevel); tocTree.push([parent, { item: item.name, level: normalizedLevel, node: item }]); if (currentLevel != normalizedLevel) { currentLevel = normalizedLevel; } } break; default: { const newlevel = currentLevel + normalizedLevel; const parent = getRootIndexByLevel(tocTree, newlevel); tocTree.push([parent, { item: item.name, level: newlevel, node: item }]); } break; } } //Turns given flat arr into a tree and returns root.. //(Assumes that no child is declared before parent) function makeTree(arr) { //Array with all the children elements set correctly.. var treeArr = new Array(arr.length); for (var i = 0, len = arr.length; i < len; i++) { var arrI = arr[i]; var newNode = (treeArr[i] = { type: arrI[1].item, level: arrI[1].level, node: arrI[1].node, content: [], }); var parentI = arrI[0]; if (parentI > -1) { //i.e. not the root.. treeArr[parentI].content.push(newNode); } } return treeArr[0]; //return the root.. } return makeTree(tocTree); }; exports.prepareDataForToc = prepareDataForToc; const getTocPod = (tocTree, tocTitle = 'Table of contents') => { let blocks = []; const rules = { ':toc': (node, _, visiter) => { blocks.push(`=head1 ${tocTitle}`); visiter(node.content); }, ':head': (node, ctx, visiter) => { const id = (0, schema_1.getNodeId)(node.node, ctx); blocks.push(`=item${node.level} L<${(0, schema_1.getTextContentFromNode)(node.node).trim()} ${id ? `|#${id}` : ''}>`); visiter(node.content); }, ':item': (node, _, visiter) => { blocks.push(`=item${node.level} ${(0, schema_1.getTextContentFromNode)(node.node).trim()}`); visiter(node.content); }, }; const transformer = (0, schema_1.makeTransformer)(rules); const res = transformer(tocTree, {}); return blocks.join('\n'); }; exports.getTocPod = getTocPod; //# sourceMappingURL=helpers.js.map