UNPKG

@mieweb/wikigdrive

Version:

Google Drive to MarkDown synchronization

215 lines (174 loc) 6.51 kB
import {MarkdownNodes, MarkdownTagNode} from '../MarkdownNodes.ts'; import {walkRecursiveSync} from '../markdownNodesUtils.ts'; import {getEndMacro, getMarkdownEndMacro, isBeginMacro, isMarkdownBeginMacro} from '../macroUtils.ts'; function isPreBeginMacro(innerTxt: string) { return innerTxt.startsWith('{{% pre ') && innerTxt.endsWith(' %}}'); } function isPreEndMacro(innerTxt: string) { return innerTxt.startsWith('{{% /pre ') && innerTxt.endsWith(' %}}'); } function getMatching(startText: string) { if (startText === '{{rawhtml}}') { return '{{/rawhtml}}'; } if (isMarkdownBeginMacro(startText)) { return getMarkdownEndMacro(startText); } if (isBeginMacro(startText)) { return getEndMacro(startText); } return ''; } function cleanupLines(chunk: MarkdownTagNode) { while (chunk.children.length > 0) { const child = chunk.children[0]; if (child.isTag && ['EMPTY_LINE/', 'EOL/'].includes(child.tag)) { chunk.children.splice(0, 1); continue; } break; } for (let idx = chunk.children.length - 1; idx >= 1; idx--) { const child = chunk.children[idx]; const prevChild = chunk.children[idx - 1]; if (child.isTag && child.tag === 'EOL/') { if (prevChild.isTag && prevChild.tag === 'EOL/') { child.tag = 'EMPTY_LINE/'; continue; } } break; } while (chunk.children.length > 0) { const child = chunk.children[chunk.children.length - 1]; if (child.isTag && ['EMPTY_LINE/'].includes(child.tag)) { chunk.children.splice(chunk.children.length - 1, 1); continue; } break; } } export function postProcessPreMacros(markdownChunks: MarkdownNodes) { let inHtml = false; walkRecursiveSync(markdownChunks.body, (chunk, ctx: { nodeIdx: number }) => { if (chunk.isTag && chunk.tag === 'HTML_MODE/') { inHtml = true; return; } if (inHtml) { return; } if (chunk && chunk.isTag && ['P'].includes(chunk.tag)) { let firstChildIdx = -1; let startText = ''; for (let idx = 0; idx < chunk.children.length; idx++) { const child = chunk.children[idx]; if (firstChildIdx === -1) { if (child.isTag === false && (child.text === '{{rawhtml}}' || isMarkdownBeginMacro(child.text))) { startText = child.text; firstChildIdx = idx; } continue; } if (child.isTag && chunk.tag === 'HTML_MODE/') { firstChildIdx = -1; continue; } if (firstChildIdx > -1 && child.isTag === false && child.text === getMatching(startText)) { const afterFirst = chunk.children[firstChildIdx + 1]; if (afterFirst.isTag && afterFirst.tag === 'EOL/') { firstChildIdx++; } const lastChildIdx = idx; const rawMode = markdownChunks.createNode('RAW_MODE/'); rawMode.comment = 'postProcessPreMacros.ts: enter raw mode after: ' + startText; const children = chunk.children.splice(firstChildIdx + 1, lastChildIdx - firstChildIdx - 1, rawMode); rawMode.children.splice(0, 0, ...children); idx -= children.length; firstChildIdx = -1; cleanupLines(rawMode); } } } if (chunk && chunk.isTag && ['P'].includes(chunk.tag)) { let firstChildIdx = -1; let startText = ''; for (let idx = 0; idx < chunk.children.length; idx++) { const child = chunk.children[idx]; if (firstChildIdx === -1) { if (child.isTag === false && isBeginMacro(child.text)) { startText = child.text; firstChildIdx = idx; } continue; } if (child.isTag && chunk.tag === 'HTML_MODE/') { firstChildIdx = -1; continue; } if (firstChildIdx > -1 && child.isTag === false && child.text === getMatching(startText)) { const afterFirst = chunk.children[firstChildIdx + 1]; if (afterFirst.isTag && ['EOL/', 'BR/'].includes(afterFirst.tag)) { afterFirst.tag = 'EOL/'; firstChildIdx++; } const lastChildIdx = idx; const macroMode = markdownChunks.createNode('MACRO_MODE/'); macroMode.comment = 'postProcessPreMacros.ts: enter macro mode after: ' + startText; const children = chunk.children.splice(firstChildIdx + 1, lastChildIdx - firstChildIdx - 1, macroMode); macroMode.children.splice(0, 0, ...children); idx -= children.length; firstChildIdx = -1; walkRecursiveSync(macroMode, chunk => { if (chunk.isTag && chunk.tag === 'BR/') { chunk.tag = 'EOL/'; chunk.comment = 'postProcessPreMacros.ts: Converted BR/ to EOL/ inside macro'; } }); cleanupLines(macroMode); } } } if (chunk && chunk.isTag && chunk.tag === 'PRE') { let firstChildIdx = -1; for (let idx = 0; idx < chunk.children.length; idx++) { const child = chunk.children[idx]; if (child.isTag && ['EOL/', 'BR/', 'EMPTY_LINE/'].includes(child.tag)) { continue; } firstChildIdx = idx; break; } let lastChildIdx = -1; for (let idx = chunk.children.length - 1; idx >= 0; idx--) { const child = chunk.children[idx]; if (child.isTag && ['EOL/', 'BR/', 'EMPTY_LINE/'].includes(child.tag)) { continue; } lastChildIdx = idx; break; } if (firstChildIdx === -1 || lastChildIdx === -1) { return; } const firstChild = chunk.children[firstChildIdx]; const lastChild = chunk.children[lastChildIdx]; if (firstChild.isTag === false && isPreBeginMacro(firstChild.text) && lastChild.isTag === false && isPreEndMacro(lastChild.text)) { const afterFirst = chunk.children[firstChildIdx + 1]; if (afterFirst.isTag && afterFirst.tag === 'EOL/') { firstChildIdx++; } const after = chunk.children.splice(lastChildIdx, chunk.children.length - lastChildIdx); const before = chunk.children.splice(0, firstChildIdx + 1); chunk.parent.children.splice(ctx.nodeIdx + 1, 0, ...after); chunk.parent.children.splice(ctx.nodeIdx, 0, ...before); } } }, {}, (chunk) => { if (chunk.isTag && chunk.tag === 'HTML_MODE/') { inHtml = false; return; } }); }