From 2ba0dbf50b523a3663b12ae230ac5818bd3dee9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BF=9C=E6=B5=85?= <370732889@qq.com> Date: Fri, 17 Mar 2023 20:46:07 +0800 Subject: [PATCH] refactor: use function findMatchingParser to reduce duplicate code (#1367) * refactor: Use function findMatchingParser to reduce duplicate code * chore: declare type Parser --- web/src/labs/marked/index.tsx | 166 ++++++++++++++++------------------ 1 file changed, 80 insertions(+), 86 deletions(-) diff --git a/web/src/labs/marked/index.tsx b/web/src/labs/marked/index.tsx index 749f19a2..db80b63b 100644 --- a/web/src/labs/marked/index.tsx +++ b/web/src/labs/marked/index.tsx @@ -1,67 +1,79 @@ import { matcher } from "./matcher"; import { blockElementParserList, inlineElementParserList } from "./parser"; +type Parser = { + name: string; + regexp: RegExp; + renderer: (rawStr: string) => JSX.Element | string; +}; + +const findMatchingParser = (parsers: Parser[], markdownStr: string): Parser | undefined => { + let matchedParser = undefined; + let matchedIndex = -1; + + for (const parser of parsers) { + const matchResult = matcher(markdownStr, parser.regexp); + if (!matchResult) { + continue; + } + + if (parser.name === "plain text" && matchedParser !== undefined) { + continue; + } + + const startIndex = matchResult.index as number; + if (matchedParser === undefined || matchedIndex > startIndex) { + matchedParser = parser; + matchedIndex = startIndex; + } + } + + return matchedParser; +}; + export const marked = ( markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList ): string | JSX.Element => { - for (const parser of blockParsers) { - const matchResult = matcher(markdownStr, parser.regexp); - if (!matchResult) { - continue; - } - const matchedStr = matchResult[0]; - const retainContent = markdownStr.slice(matchedStr.length); + const matchedBlockParser = findMatchingParser(blockParsers, markdownStr); + if (matchedBlockParser) { + const matchResult = matcher(markdownStr, matchedBlockParser.regexp); + if (matchResult) { + const matchedStr = matchResult[0]; + const retainContent = markdownStr.slice(matchedStr.length); - if (parser.name === "br") { - return ( - <> - {parser.renderer(matchedStr)} - {marked(retainContent, blockParsers, inlineParsers)} - - ); - } else { - if (retainContent === "") { - return parser.renderer(matchedStr); - } else if (retainContent.startsWith("\n")) { + if (matchedBlockParser.name === "br") { return ( <> - {parser.renderer(matchedStr)} - {marked(retainContent.slice(1), blockParsers, inlineParsers)} + {matchedBlockParser.renderer(matchedStr)} + {marked(retainContent, blockParsers, inlineParsers)} ); + } else { + if (retainContent === "") { + return matchedBlockParser.renderer(matchedStr); + } else if (retainContent.startsWith("\n")) { + return ( + <> + {matchedBlockParser.renderer(matchedStr)} + {marked(retainContent.slice(1), blockParsers, inlineParsers)} + + ); + } } } } - let matchedInlineParser = undefined; - let matchedIndex = -1; - - for (const parser of inlineParsers) { - const matchResult = matcher(markdownStr, parser.regexp); - if (!matchResult) { - continue; - } - - if (parser.name === "plain text" && matchedInlineParser !== undefined) { - continue; - } - - const startIndex = matchResult.index as number; - if (matchedInlineParser === undefined || matchedIndex > startIndex) { - matchedInlineParser = parser; - matchedIndex = startIndex; - } - } - + const matchedInlineParser = findMatchingParser(inlineParsers, markdownStr); if (matchedInlineParser) { const matchResult = matcher(markdownStr, matchedInlineParser.regexp); if (matchResult) { const matchedStr = matchResult[0]; const matchedLength = matchedStr.length; - const prefixStr = markdownStr.slice(0, matchedIndex); - const suffixStr = markdownStr.slice(matchedIndex + matchedLength); + const mIndex = matchResult.index || 0; + const prefixStr = markdownStr.slice(0, mIndex); + const suffixStr = markdownStr.slice(mIndex + matchedLength); return ( <> {marked(prefixStr, [], inlineParsers)} @@ -83,70 +95,52 @@ interface MatchedNode { export const getMatchedNodes = (markdownStr: string): MatchedNode[] => { const matchedNodeList: MatchedNode[] = []; - const walkthough = (markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList): string => { - for (const parser of blockParsers) { - const matchResult = matcher(markdownStr, parser.regexp); - if (!matchResult) { - continue; - } - const matchedStr = matchResult[0]; - const retainContent = markdownStr.slice(matchedStr.length); - matchedNodeList.push({ - parserName: parser.name, - matchedContent: matchedStr, - }); + const walkthrough = (markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList): string => { + const matchedBlockParser = findMatchingParser(blockParsers, markdownStr); + if (matchedBlockParser) { + const matchResult = matcher(markdownStr, matchedBlockParser.regexp); + if (matchResult) { + const matchedStr = matchResult[0]; + const retainContent = markdownStr.slice(matchedStr.length); + matchedNodeList.push({ + parserName: matchedBlockParser.name, + matchedContent: matchedStr, + }); - if (parser.name === "br") { - return walkthough(retainContent, blockParsers, inlineParsers); - } else { - if (parser.name !== "code block") { - walkthough(matchedStr, [], inlineParsers); + if (matchedBlockParser.name === "br") { + return walkthrough(retainContent, blockParsers, inlineParsers); + } else { + if (matchedBlockParser.name !== "code block") { + walkthrough(matchedStr, [], inlineParsers); + } + if (retainContent.startsWith("\n")) { + return walkthrough(retainContent.slice(1), blockParsers, inlineParsers); + } } - if (retainContent.startsWith("\n")) { - return walkthough(retainContent.slice(1), blockParsers, inlineParsers); - } - } - return ""; - } - - let matchedInlineParser = undefined; - let matchedIndex = -1; - - for (const parser of inlineParsers) { - const matchResult = matcher(markdownStr, parser.regexp); - if (!matchResult) { - continue; - } - - if (parser.name === "plain text" && matchedInlineParser !== undefined) { - continue; - } - - const startIndex = matchResult.index as number; - if (matchedInlineParser === undefined || matchedIndex > startIndex) { - matchedInlineParser = parser; - matchedIndex = startIndex; + return ""; } } + const matchedInlineParser = findMatchingParser(inlineParsers, markdownStr); if (matchedInlineParser) { const matchResult = matcher(markdownStr, matchedInlineParser.regexp); if (matchResult) { const matchedStr = matchResult[0]; const matchedLength = matchedStr.length; - const suffixStr = markdownStr.slice(matchedIndex + matchedLength); + const mIndex = matchResult.index || 0; + const suffixStr = markdownStr.slice(mIndex + matchedLength); matchedNodeList.push({ parserName: matchedInlineParser.name, matchedContent: matchedStr, }); - return walkthough(suffixStr, [], inlineParsers); + return walkthrough(suffixStr, [], inlineParsers); } } return markdownStr; }; - walkthough(markdownStr); + walkthrough(markdownStr); return matchedNodeList; };