From eaf89aa2f2b3726e599a65ef56347c035cea9ca9 Mon Sep 17 00:00:00 2001 From: boojack Date: Tue, 4 Oct 2022 10:44:16 +0800 Subject: [PATCH] feat: update marked parsers (#260) * chore: remove external match functions * chore: update parsers --- web/src/labs/marked/index.ts | 44 ++++++++++++++++++--- web/src/labs/marked/marked.test.ts | 24 +++++++++++ web/src/labs/marked/parser/Bold.ts | 24 ++++++----- web/src/labs/marked/parser/CodeBlock.ts | 11 ------ web/src/labs/marked/parser/DoneList.ts | 13 +----- web/src/labs/marked/parser/Emphasis.ts | 24 ++++++----- web/src/labs/marked/parser/Image.ts | 11 ------ web/src/labs/marked/parser/InlineCode.ts | 11 ------ web/src/labs/marked/parser/Link.ts | 11 ------ web/src/labs/marked/parser/Mark.ts | 11 ------ web/src/labs/marked/parser/OrderedList.ts | 13 +----- web/src/labs/marked/parser/Paragraph.ts | 13 +----- web/src/labs/marked/parser/PlainLink.ts | 11 ------ web/src/labs/marked/parser/Tag.ts | 11 ------ web/src/labs/marked/parser/TodoList.ts | 13 +----- web/src/labs/marked/parser/UnorderedList.ts | 13 +----- web/src/labs/marked/parser/index.ts | 7 +--- web/src/less/memo-content.less | 4 +- 18 files changed, 92 insertions(+), 177 deletions(-) diff --git a/web/src/labs/marked/index.ts b/web/src/labs/marked/index.ts index f2f58acf..bafa9194 100644 --- a/web/src/labs/marked/index.ts +++ b/web/src/labs/marked/index.ts @@ -1,18 +1,50 @@ -import { parserList } from "./parser"; +import { blockElementParserList, inlineElementParserList } from "./parser"; -export const marked = (markdownStr: string, parsers = parserList) => { - for (const parser of parsers) { +const match = (rawStr: string, regex: RegExp): number => { + const matchResult = rawStr.match(regex); + if (!matchResult) { + return 0; + } + + const matchStr = matchResult[0]; + return matchStr.length; +}; + +export const marked = (markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList): string => { + for (const parser of blockParsers) { const startIndex = markdownStr.search(parser.regex); - const matchedLength = parser.match(markdownStr); + const matchedLength = match(markdownStr, parser.regex); if (startIndex > -1 && matchedLength > 0) { const prefixStr = markdownStr.slice(0, startIndex); const matchedStr = markdownStr.slice(startIndex, startIndex + matchedLength); const suffixStr = markdownStr.slice(startIndex + matchedLength); - markdownStr = marked(prefixStr, parsers) + parser.renderer(matchedStr) + marked(suffixStr, parsers); - break; + return marked(prefixStr, blockParsers, inlineParsers) + parser.renderer(matchedStr) + marked(suffixStr, blockParsers, inlineParsers); } } + let matchedInlineParser = undefined; + let matchedIndex = -1; + + for (const parser of inlineElementParserList) { + const startIndex = markdownStr.search(parser.regex); + const matchedLength = match(markdownStr, parser.regex); + + if (startIndex > -1 && matchedLength > 0) { + if (!matchedInlineParser || matchedIndex > startIndex) { + matchedIndex = startIndex; + matchedInlineParser = parser; + } + } + } + + if (matchedInlineParser) { + const matchedLength = match(markdownStr, matchedInlineParser.regex); + const prefixStr = markdownStr.slice(0, matchedIndex); + const matchedStr = markdownStr.slice(matchedIndex, matchedIndex + matchedLength); + const suffixStr = markdownStr.slice(matchedIndex + matchedLength); + return prefixStr + matchedInlineParser.renderer(matchedStr) + marked(suffixStr, [], inlineParsers); + } + return markdownStr; }; diff --git a/web/src/labs/marked/marked.test.ts b/web/src/labs/marked/marked.test.ts index b7ebcc36..ecb79071 100644 --- a/web/src/labs/marked/marked.test.ts +++ b/web/src/labs/marked/marked.test.ts @@ -94,6 +94,30 @@ console.log("hello world!") }, ]; + for (const t of tests) { + expect(marked(t.markdown)).toBe(t.want); + } + }); + test("parse bold and em text", () => { + const tests = [ + { + markdown: `Important: **Minecraft**`, + want: `

Important: Minecraft

`, + }, + { + markdown: `Em: *Minecraft*`, + want: `

Em: Minecraft

`, + }, + { + markdown: `Important: ***Minecraft/123***`, + want: `

Important: Minecraft/123

`, + }, + { + markdown: `Important: ***[baidu](https://baidu.com)***`, + want: `

Important: baidu

`, + }, + ]; + for (const t of tests) { expect(marked(t.markdown)).toBe(t.want); } diff --git a/web/src/labs/marked/parser/Bold.ts b/web/src/labs/marked/parser/Bold.ts index 3f0c531c..31fdf433 100644 --- a/web/src/labs/marked/parser/Bold.ts +++ b/web/src/labs/marked/parser/Bold.ts @@ -1,23 +1,21 @@ -export const BOLD_REG = /\*\*([\S ]+?)\*\*/; +import { marked } from ".."; +import Emphasis from "./Emphasis"; +import Link from "./Link"; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(BOLD_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; +export const BOLD_REG = /\*\*([\S ]+)\*\*/; const renderer = (rawStr: string): string => { - const parsedStr = rawStr.replace(BOLD_REG, "$1"); - return parsedStr; + const matchResult = rawStr.match(BOLD_REG); + if (!matchResult) { + return rawStr; + } + + const parsedContent = marked(matchResult[1], [], [Emphasis, Link]); + return `${parsedContent}`; }; export default { name: "bold", regex: BOLD_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/CodeBlock.ts b/web/src/labs/marked/parser/CodeBlock.ts index 4f5f731b..28cb1580 100644 --- a/web/src/labs/marked/parser/CodeBlock.ts +++ b/web/src/labs/marked/parser/CodeBlock.ts @@ -1,15 +1,5 @@ export const CODE_BLOCK_REG = /^```(\S*?)\s([\s\S]*?)```(\n?)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(CODE_BLOCK_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const parsedStr = rawStr.replace(CODE_BLOCK_REG, "
\n$2
$3"); return parsedStr; @@ -18,6 +8,5 @@ const renderer = (rawStr: string): string => { export default { name: "code block", regex: CODE_BLOCK_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/DoneList.ts b/web/src/labs/marked/parser/DoneList.ts index 10f3783c..88a3eeb5 100644 --- a/web/src/labs/marked/parser/DoneList.ts +++ b/web/src/labs/marked/parser/DoneList.ts @@ -3,29 +3,18 @@ import { marked } from ".."; export const DONE_LIST_REG = /^- \[x\] ([\S ]+)(\n?)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(DONE_LIST_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const matchResult = rawStr.match(DONE_LIST_REG); if (!matchResult) { return rawStr; } - const parsedContent = marked(matchResult[1], inlineElementParserList); + const parsedContent = marked(matchResult[1], [], inlineElementParserList); return `

${parsedContent}

${matchResult[2]}`; }; export default { name: "done list", regex: DONE_LIST_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/Emphasis.ts b/web/src/labs/marked/parser/Emphasis.ts index d749dcd1..810ee736 100644 --- a/web/src/labs/marked/parser/Emphasis.ts +++ b/web/src/labs/marked/parser/Emphasis.ts @@ -1,23 +1,21 @@ -export const EMPHASIS_REG = /\*([\S ]+?)\*/; +import { marked } from ".."; +import Bold from "./Bold"; +import Link from "./Link"; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(EMPHASIS_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; +export const EMPHASIS_REG = /\*([\S ]+)\*/; const renderer = (rawStr: string): string => { - const parsedStr = rawStr.replace(EMPHASIS_REG, "$1"); - return parsedStr; + const matchResult = rawStr.match(EMPHASIS_REG); + if (!matchResult) { + return rawStr; + } + + const parsedContent = marked(matchResult[1], [], [Bold, Link]); + return `${parsedContent}`; }; export default { name: "emphasis", regex: EMPHASIS_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/Image.ts b/web/src/labs/marked/parser/Image.ts index 30959835..208b80a0 100644 --- a/web/src/labs/marked/parser/Image.ts +++ b/web/src/labs/marked/parser/Image.ts @@ -1,15 +1,5 @@ export const IMAGE_REG = /!\[.*?\]\((.+?)\)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(IMAGE_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const parsedStr = rawStr.replace(IMAGE_REG, ""); return parsedStr; @@ -18,6 +8,5 @@ const renderer = (rawStr: string): string => { export default { name: "image", regex: IMAGE_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/InlineCode.ts b/web/src/labs/marked/parser/InlineCode.ts index 2593c8ce..d6270423 100644 --- a/web/src/labs/marked/parser/InlineCode.ts +++ b/web/src/labs/marked/parser/InlineCode.ts @@ -1,15 +1,5 @@ export const INLINE_CODE_REG = /`([\S ]+?)`/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(INLINE_CODE_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const parsedStr = rawStr.replace(INLINE_CODE_REG, "$1"); return parsedStr; @@ -18,6 +8,5 @@ const renderer = (rawStr: string): string => { export default { name: "inline code", regex: INLINE_CODE_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/Link.ts b/web/src/labs/marked/parser/Link.ts index a0599d82..7429488b 100644 --- a/web/src/labs/marked/parser/Link.ts +++ b/web/src/labs/marked/parser/Link.ts @@ -1,15 +1,5 @@ export const LINK_REG = /\[(.*?)\]\((.+?)\)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(LINK_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const parsedStr = rawStr.replace(LINK_REG, "$1"); return parsedStr; @@ -18,6 +8,5 @@ const renderer = (rawStr: string): string => { export default { name: "link", regex: LINK_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/Mark.ts b/web/src/labs/marked/parser/Mark.ts index 9dbd3a4b..893eb4ce 100644 --- a/web/src/labs/marked/parser/Mark.ts +++ b/web/src/labs/marked/parser/Mark.ts @@ -1,15 +1,5 @@ export const MARK_REG = /@\[([\S ]+?)\]\((\S+?)\)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(MARK_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const parsedStr = rawStr.replace(MARK_REG, "$1"); return parsedStr; @@ -18,6 +8,5 @@ const renderer = (rawStr: string): string => { export default { name: "mark", regex: MARK_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/OrderedList.ts b/web/src/labs/marked/parser/OrderedList.ts index fe42ff9d..8b27097d 100644 --- a/web/src/labs/marked/parser/OrderedList.ts +++ b/web/src/labs/marked/parser/OrderedList.ts @@ -3,29 +3,18 @@ import { marked } from ".."; export const ORDERED_LIST_REG = /^(\d+)\. ([\S ]+)(\n?)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(ORDERED_LIST_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const matchResult = rawStr.match(ORDERED_LIST_REG); if (!matchResult) { return rawStr; } - const parsedContent = marked(matchResult[2], inlineElementParserList); + const parsedContent = marked(matchResult[2], [], inlineElementParserList); return `

${matchResult[1]}.${parsedContent}

${matchResult[3]}`; }; export default { name: "ordered list", regex: ORDERED_LIST_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/Paragraph.ts b/web/src/labs/marked/parser/Paragraph.ts index d85558b0..67626057 100644 --- a/web/src/labs/marked/parser/Paragraph.ts +++ b/web/src/labs/marked/parser/Paragraph.ts @@ -3,29 +3,18 @@ import { marked } from ".."; export const PARAGRAPH_REG = /^([\S ]*)(\n?)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(PARAGRAPH_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const matchResult = rawStr.match(PARAGRAPH_REG); if (!matchResult) { return rawStr; } - const parsedContent = marked(matchResult[1], inlineElementParserList); + const parsedContent = marked(matchResult[1], [], inlineElementParserList); return `

${parsedContent}

${matchResult[2]}`; }; export default { name: "ordered list", regex: PARAGRAPH_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/PlainLink.ts b/web/src/labs/marked/parser/PlainLink.ts index b30f0d47..f1ae6e84 100644 --- a/web/src/labs/marked/parser/PlainLink.ts +++ b/web/src/labs/marked/parser/PlainLink.ts @@ -1,15 +1,5 @@ export const PLAIN_LINK_REG = /(https?:\/\/[^ ]+)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(PLAIN_LINK_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const parsedStr = rawStr.replace(PLAIN_LINK_REG, "$1"); return parsedStr; @@ -18,6 +8,5 @@ const renderer = (rawStr: string): string => { export default { name: "plain link", regex: PLAIN_LINK_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/Tag.ts b/web/src/labs/marked/parser/Tag.ts index a117d053..5d9262ac 100644 --- a/web/src/labs/marked/parser/Tag.ts +++ b/web/src/labs/marked/parser/Tag.ts @@ -1,15 +1,5 @@ export const TAG_REG = /[^\s]?#([^\s#]+?) /; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(TAG_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const parsedStr = rawStr.replace(TAG_REG, "#$1 "); return parsedStr; @@ -18,6 +8,5 @@ const renderer = (rawStr: string): string => { export default { name: "tag", regex: TAG_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/TodoList.ts b/web/src/labs/marked/parser/TodoList.ts index 541b2abb..f817c5e4 100644 --- a/web/src/labs/marked/parser/TodoList.ts +++ b/web/src/labs/marked/parser/TodoList.ts @@ -3,29 +3,18 @@ import { marked } from ".."; export const TODO_LIST_REG = /^- \[ \] ([\S ]+)(\n?)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(TODO_LIST_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const matchResult = rawStr.match(TODO_LIST_REG); if (!matchResult) { return rawStr; } - const parsedContent = marked(matchResult[1], inlineElementParserList); + const parsedContent = marked(matchResult[1], [], inlineElementParserList); return `

${parsedContent}

${matchResult[2]}`; }; export default { name: "todo list", regex: TODO_LIST_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/UnorderedList.ts b/web/src/labs/marked/parser/UnorderedList.ts index 59f87cb8..9b075360 100644 --- a/web/src/labs/marked/parser/UnorderedList.ts +++ b/web/src/labs/marked/parser/UnorderedList.ts @@ -3,29 +3,18 @@ import { marked } from ".."; export const UNORDERED_LIST_REG = /^[*-] ([\S ]+)(\n?)/; -const match = (rawStr: string): number => { - const matchResult = rawStr.match(UNORDERED_LIST_REG); - if (!matchResult) { - return 0; - } - - const matchStr = matchResult[0]; - return matchStr.length; -}; - const renderer = (rawStr: string): string => { const matchResult = rawStr.match(UNORDERED_LIST_REG); if (!matchResult) { return rawStr; } - const parsedContent = marked(matchResult[1], inlineElementParserList); + const parsedContent = marked(matchResult[1], [], inlineElementParserList); return `

${parsedContent}

${matchResult[2]}`; }; export default { name: "unordered list", regex: UNORDERED_LIST_REG, - match, renderer, }; diff --git a/web/src/labs/marked/parser/index.ts b/web/src/labs/marked/parser/index.ts index 27a9ef1b..3dedfd89 100644 --- a/web/src/labs/marked/parser/index.ts +++ b/web/src/labs/marked/parser/index.ts @@ -16,17 +16,12 @@ import InlineCode from "./InlineCode"; export { CODE_BLOCK_REG } from "./CodeBlock"; export { TODO_LIST_REG } from "./TodoList"; export { DONE_LIST_REG } from "./DoneList"; -export { ORDERED_LIST_REG } from "./OrderedList"; -export { UNORDERED_LIST_REG } from "./UnorderedList"; -export { PARAGRAPH_REG } from "./Paragraph"; export { TAG_REG } from "./Tag"; export { IMAGE_REG } from "./Image"; export { LINK_REG } from "./Link"; export { MARK_REG } from "./Mark"; -export { BOLD_REG } from "./Bold"; -export { EMPHASIS_REG } from "./Emphasis"; // The order determines the order of execution. export const blockElementParserList = [CodeBlock, TodoList, DoneList, OrderedList, UnorderedList, Paragraph]; -export const inlineElementParserList = [Image, Mark, Link, Bold, Emphasis, InlineCode, PlainLink, Tag]; +export const inlineElementParserList = [Image, Mark, Bold, Emphasis, Link, InlineCode, PlainLink, Tag]; export const parserList = [...blockElementParserList, ...inlineElementParserList]; diff --git a/web/src/less/memo-content.less b/web/src/less/memo-content.less index 810318d3..b862c162 100644 --- a/web/src/less/memo-content.less +++ b/web/src/less/memo-content.less @@ -19,7 +19,7 @@ } .img { - @apply float-left max-w-full w-full; + @apply float-left max-w-full; } .tag-span { @@ -52,7 +52,7 @@ } code { - @apply bg-gray-100 px-1 rounded text-sm leading-6 inline-block; + @apply bg-gray-100 px-1 rounded text-sm font-mono leading-6 inline-block; } }