refactor: use function findMatchingParser to reduce duplicate code (#1367)

* refactor: Use function findMatchingParser to reduce duplicate code

* chore: declare type Parser
This commit is contained in:
远浅 2023-03-17 20:46:07 +08:00 committed by GitHub
parent 4ee8cf08c6
commit 2ba0dbf50b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,67 +1,79 @@
import { matcher } from "./matcher"; import { matcher } from "./matcher";
import { blockElementParserList, inlineElementParserList } from "./parser"; 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 = ( export const marked = (
markdownStr: string, markdownStr: string,
blockParsers = blockElementParserList, blockParsers = blockElementParserList,
inlineParsers = inlineElementParserList inlineParsers = inlineElementParserList
): string | JSX.Element => { ): string | JSX.Element => {
for (const parser of blockParsers) { const matchedBlockParser = findMatchingParser(blockParsers, markdownStr);
const matchResult = matcher(markdownStr, parser.regexp); if (matchedBlockParser) {
if (!matchResult) { const matchResult = matcher(markdownStr, matchedBlockParser.regexp);
continue; if (matchResult) {
} const matchedStr = matchResult[0];
const matchedStr = matchResult[0]; const retainContent = markdownStr.slice(matchedStr.length);
const retainContent = markdownStr.slice(matchedStr.length);
if (parser.name === "br") { if (matchedBlockParser.name === "br") {
return (
<>
{parser.renderer(matchedStr)}
{marked(retainContent, blockParsers, inlineParsers)}
</>
);
} else {
if (retainContent === "") {
return parser.renderer(matchedStr);
} else if (retainContent.startsWith("\n")) {
return ( return (
<> <>
{parser.renderer(matchedStr)} {matchedBlockParser.renderer(matchedStr)}
{marked(retainContent.slice(1), blockParsers, inlineParsers)} {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; const matchedInlineParser = findMatchingParser(inlineParsers, markdownStr);
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;
}
}
if (matchedInlineParser) { if (matchedInlineParser) {
const matchResult = matcher(markdownStr, matchedInlineParser.regexp); const matchResult = matcher(markdownStr, matchedInlineParser.regexp);
if (matchResult) { if (matchResult) {
const matchedStr = matchResult[0]; const matchedStr = matchResult[0];
const matchedLength = matchedStr.length; const matchedLength = matchedStr.length;
const prefixStr = markdownStr.slice(0, matchedIndex); const mIndex = matchResult.index || 0;
const suffixStr = markdownStr.slice(matchedIndex + matchedLength); const prefixStr = markdownStr.slice(0, mIndex);
const suffixStr = markdownStr.slice(mIndex + matchedLength);
return ( return (
<> <>
{marked(prefixStr, [], inlineParsers)} {marked(prefixStr, [], inlineParsers)}
@ -83,70 +95,52 @@ interface MatchedNode {
export const getMatchedNodes = (markdownStr: string): MatchedNode[] => { export const getMatchedNodes = (markdownStr: string): MatchedNode[] => {
const matchedNodeList: MatchedNode[] = []; const matchedNodeList: MatchedNode[] = [];
const walkthough = (markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList): string => { const walkthrough = (markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList): string => {
for (const parser of blockParsers) { const matchedBlockParser = findMatchingParser(blockParsers, markdownStr);
const matchResult = matcher(markdownStr, parser.regexp); if (matchedBlockParser) {
if (!matchResult) { const matchResult = matcher(markdownStr, matchedBlockParser.regexp);
continue; if (matchResult) {
} const matchedStr = matchResult[0];
const matchedStr = matchResult[0]; const retainContent = markdownStr.slice(matchedStr.length);
const retainContent = markdownStr.slice(matchedStr.length); matchedNodeList.push({
matchedNodeList.push({ parserName: matchedBlockParser.name,
parserName: parser.name, matchedContent: matchedStr,
matchedContent: matchedStr, });
});
if (parser.name === "br") { if (matchedBlockParser.name === "br") {
return walkthough(retainContent, blockParsers, inlineParsers); return walkthrough(retainContent, blockParsers, inlineParsers);
} else { } else {
if (parser.name !== "code block") { if (matchedBlockParser.name !== "code block") {
walkthough(matchedStr, [], inlineParsers); walkthrough(matchedStr, [], inlineParsers);
}
if (retainContent.startsWith("\n")) {
return walkthrough(retainContent.slice(1), blockParsers, inlineParsers);
}
} }
if (retainContent.startsWith("\n")) { return "";
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;
} }
} }
const matchedInlineParser = findMatchingParser(inlineParsers, markdownStr);
if (matchedInlineParser) { if (matchedInlineParser) {
const matchResult = matcher(markdownStr, matchedInlineParser.regexp); const matchResult = matcher(markdownStr, matchedInlineParser.regexp);
if (matchResult) { if (matchResult) {
const matchedStr = matchResult[0]; const matchedStr = matchResult[0];
const matchedLength = matchedStr.length; const matchedLength = matchedStr.length;
const suffixStr = markdownStr.slice(matchedIndex + matchedLength); const mIndex = matchResult.index || 0;
const suffixStr = markdownStr.slice(mIndex + matchedLength);
matchedNodeList.push({ matchedNodeList.push({
parserName: matchedInlineParser.name, parserName: matchedInlineParser.name,
matchedContent: matchedStr, matchedContent: matchedStr,
}); });
return walkthough(suffixStr, [], inlineParsers); return walkthrough(suffixStr, [], inlineParsers);
} }
} }
return markdownStr; return markdownStr;
}; };
walkthough(markdownStr); walkthrough(markdownStr);
return matchedNodeList; return matchedNodeList;
}; };