UNPKG

@mieweb/wikigdrive

Version:

Google Drive to MarkDown synchronization

88 lines (78 loc) 2.89 kB
import slugify from 'slugify'; import {extractText, walkRecursiveAsync, walkRecursiveSync} from '../markdownNodesUtils.ts'; import {MarkdownNodes, MarkdownTextNode} from '../MarkdownNodes.ts'; export async function rewriteHeaders(markdownChunks: MarkdownNodes): Promise<{ headersMap: {[key: string]: string}, invisibleBookmarks: {[key: string]: number} }> { const headersMap = {}; const invisibleBookmarks = {}; let inPre = false; await walkRecursiveAsync(markdownChunks.body, async (chunk, ctx: { nodeIdx: number }) => { if (chunk.isTag && 'PRE' === chunk.tag) { inPre = true; } if (inPre) { if (chunk.isTag) { for (let j = chunk.children.length - 1; j >= 0; j--) { const child = chunk.children[j]; if (child.isTag && child.tag === 'BOOKMARK/') { chunk.children.splice(j, 1); break; } } } } if (chunk.isTag && ['H1', 'H2', 'H3', 'H4'].includes(chunk.tag)) { const innerTxt = extractText(chunk); const slug = slugify(innerTxt.trim(), { replacement: '-', lower: true, remove: /[#*+~.,^()'"!:@]/g }); if (chunk.children.length === 1) { const child = chunk.children[0]; if (child.isTag && child.tag === 'BOOKMARK/') { chunk.parent.children.splice(ctx.nodeIdx, 1, child); return; } } for (let j = 0; j < chunk.children.length - 1; j++) { const child = chunk.children[j]; if (child.isTag && child.tag === 'BOOKMARK/') { const toMove = chunk.children.splice(j, 1); if (slug && !headersMap['#' + child.payload.id]) { headersMap['#' + child.payload.id] = '#' + slug; } else { chunk.children.splice(chunk.children.length, 0, ...toMove); } break; } } } }, {}, async (chunk) => { if (chunk.isTag && 'PRE' === chunk.tag) { inPre = false; } }); await walkRecursiveAsync(markdownChunks.body, async (chunk, ctx: { nodeIdx: number }) => { if (chunk.isTag && 'BOOKMARK/' === chunk.tag) { if (!headersMap['#' + chunk.payload.id]) { invisibleBookmarks['#' + chunk.payload.id] = 1; } if (chunk.parent.children.length < 2) { return; } const space: MarkdownTextNode = { isTag: false, text: ' ', comment: 'rewriteHeaders.ts: space before anchor' }; chunk.parent.children.splice(ctx.nodeIdx, 0, space); return { nodeIdx: ctx.nodeIdx + 1 }; } }); if (Object.keys(headersMap).length > 0) { walkRecursiveSync(markdownChunks.body, (chunk) => { if (chunk.isTag === true && chunk.payload?.href) { if (headersMap[chunk.payload.href]) { chunk.payload.href = headersMap[chunk.payload.href]; } } }); } return { headersMap, invisibleBookmarks }; }