| |
| |
| |
| |
|
|
| import { Lexer } from "marked"; |
|
|
| |
| |
| |
| |
| export function parseMarkdownIntoBlocks(markdown: string): string[] { |
| |
| |
| |
| |
| const hasFootnoteReference = /\[\^[^\]\s]{1,200}\](?!:)/.test(markdown); |
| const hasFootnoteDefinition = /\[\^[^\]\s]{1,200}\]:/.test(markdown); |
|
|
| |
| |
| if (hasFootnoteReference || hasFootnoteDefinition) { |
| return [markdown]; |
| } |
|
|
| const tokens = Lexer.lex(markdown, { gfm: true }); |
|
|
| |
| const mergedBlocks: string[] = []; |
| const htmlStack: string[] = []; |
|
|
| for (let i = 0; i < tokens.length; i++) { |
| const token = tokens[i]; |
| const currentBlock = token.raw; |
|
|
| |
| if (htmlStack.length > 0) { |
| |
| mergedBlocks[mergedBlocks.length - 1] += currentBlock; |
|
|
| |
| if (token.type === "html") { |
| const closingTagMatch = currentBlock.match(/<\/(\w+)>/); |
| if (closingTagMatch) { |
| const closingTag = closingTagMatch[1]; |
| |
| if (htmlStack[htmlStack.length - 1] === closingTag) { |
| htmlStack.pop(); |
| } |
| } |
| } |
| continue; |
| } |
|
|
| |
| if (token.type === "html" && token.block) { |
| const openingTagMatch = currentBlock.match(/<(\w+)[\s>]/); |
| if (openingTagMatch) { |
| const tagName = openingTagMatch[1]; |
| |
| const hasClosingTag = currentBlock.includes(`</${tagName}>`); |
| if (!hasClosingTag) { |
| |
| htmlStack.push(tagName); |
| } |
| } |
| } |
|
|
| |
| |
| if (currentBlock.trim() === "$$" && mergedBlocks.length > 0) { |
| const previousBlock = mergedBlocks.at(-1); |
|
|
| if (!previousBlock) { |
| mergedBlocks.push(currentBlock); |
| continue; |
| } |
|
|
| |
| const prevStartsWith$$ = previousBlock.trimStart().startsWith("$$"); |
| const prevDollarCount = (previousBlock.match(/\$\$/g) || []).length; |
|
|
| |
| if (prevStartsWith$$ && prevDollarCount % 2 === 1) { |
| mergedBlocks[mergedBlocks.length - 1] = previousBlock + currentBlock; |
| continue; |
| } |
| } |
|
|
| |
| if (mergedBlocks.length > 0 && currentBlock.trimEnd().endsWith("$$")) { |
| const previousBlock = mergedBlocks.at(-1); |
|
|
| if (!previousBlock) { |
| mergedBlocks.push(currentBlock); |
| continue; |
| } |
|
|
| const prevStartsWith$$ = previousBlock.trimStart().startsWith("$$"); |
| const prevDollarCount = (previousBlock.match(/\$\$/g) || []).length; |
| const currDollarCount = (currentBlock.match(/\$\$/g) || []).length; |
|
|
| |
| |
| if ( |
| prevStartsWith$$ && |
| prevDollarCount % 2 === 1 && |
| !currentBlock.trimStart().startsWith("$$") && |
| currDollarCount === 1 |
| ) { |
| mergedBlocks[mergedBlocks.length - 1] = previousBlock + currentBlock; |
| continue; |
| } |
| } |
|
|
| mergedBlocks.push(currentBlock); |
| } |
|
|
| return mergedBlocks; |
| } |
|
|