UNPKG

@podlite/toc

Version:

'Table of contents' plugin for Podlite markup language

114 lines (112 loc) 4.8 kB
import { getFromTree, getTextContentFromNode, mkTocItem, mkTocList, mkToc, getNodeId, makeAttrs, isNamedBlock, mkFomattingCodeL, mkNode, } from '@podlite/schema'; import { prepareDataForToc } from './helpers'; export const getContentForToc = (node) => { if (typeof node !== 'string' && 'type' in node) { if (node.type === 'block') { const conf = makeAttrs(node, {}); if (isNamedBlock(node.name)) { const caption = ((conf, nodeName) => { if (conf.exists('caption')) { return conf.getFirstValue('caption'); } else if (conf.exists('title')) { return conf.getFirstValue('title'); } else { // try to find content child node const [captionNode] = getFromTree(node, 'caption'); if (captionNode) { return getTextContentFromNode(captionNode); } } return `${nodeName} not have :caption`; })(conf, node.name); return caption; } if (node.name == 'image') { const caption = getTextContentFromNode(conf.getFirstValue('caption')); return caption || 'image not have caption'; } if (node.name == 'table') { const caption = getTextContentFromNode(conf.getFirstValue('caption')); return caption || 'table not have :caption'; } if (node.type === 'block' && node.name === 'item') { if (Array.isArray(node.content) && node.content.length > 0) { return getTextContentFromNode(node.content[0]); } } const caption = ((conf, nodeName) => { if (conf.exists('caption')) { return getTextContentFromNode(conf.getFirstValue('caption')); } else if (conf.exists('title')) { return getTextContentFromNode(conf.getFirstValue('title')); } else { // try to find content child node const [captionNode] = getFromTree(node, 'caption'); if (captionNode) { return getTextContentFromNode(captionNode); } return null; } })(conf, node.name); if (caption) { return caption; } return getTextContentFromNode(node); } } return 'Not supported toc element'; }; /* */ export const plugin = { toAstAfter: (writer, processor, fulltree) => { return (node, ctx) => { const content = getTextContentFromNode(node); const blocks = content .trim() .split(/(?:\s*,\s*|\s+)/) .filter(Boolean); if (blocks.length == 0) { blocks.push({ name: 'head' }); } const nodes = getFromTree(fulltree, ...blocks); const tocTree = prepareDataForToc(nodes); const createList = (items, level) => { const resultList = []; items.map(item => { const { level, node, content } = item; // create new node for each item const text = getContentForToc(node) || ' '; // ' ' needs to avoid lack of L<> //TODO: 1. getNodeId should use ctx of node, but using {} instead //TODO: 2. refactor linking for blocks const para = mkNode({ type: 'para', content: [mkFomattingCodeL({ meta: `#${getNodeId(node, {})}` }, [text])], }); const tocNode = para; resultList.push(mkTocItem(tocNode)); if (Array.isArray(content) && content.length > 0) { resultList.push(createList(content, level + 1)); } }); return mkTocList(resultList, level); }; const conf = makeAttrs(node, ctx); const tocTitle = conf.getFirstValue('caption') || conf.getFirstValue('title'); const makeToc = (tocTree, title) => { return mkToc(createList(tocTree.content, 1), title, node.location); }; return makeToc(tocTree, tocTitle); }; }, }; export const PluginRegister = { Toc: plugin, toc: plugin, }; export default plugin; //# sourceMappingURL=index.js.map