From 0f8ce3dd1696722f951d7195ad1f88b39a5d15d7 Mon Sep 17 00:00:00 2001 From: boojack Date: Sat, 7 Jan 2023 00:13:49 +0800 Subject: [PATCH] refactor: return jsx element instead of string in marked (#910) * refactor: return jsx element instead of string in marked * chore: update --- web/src/components/CreateTagDialog.tsx | 3 +- web/src/components/Memo.tsx | 7 +- web/src/components/MemoContent.tsx | 17 +- web/src/components/MemoList.tsx | 4 +- web/src/labs/highlighter/index.ts | 24 --- web/src/labs/marked/{index.ts => index.tsx} | 44 +++-- web/src/labs/marked/marked.test.ts | 174 ------------------ web/src/labs/marked/matcher.ts | 4 + web/src/labs/marked/parser/Blockquote.ts | 24 --- web/src/labs/marked/parser/Blockquote.tsx | 19 ++ web/src/labs/marked/parser/Bold.ts | 27 --- web/src/labs/marked/parser/Bold.tsx | 22 +++ .../{BoldEmphasis.ts => BoldEmphasis.tsx} | 19 +- web/src/labs/marked/parser/Br.ts | 17 -- web/src/labs/marked/parser/Br.tsx | 16 ++ web/src/labs/marked/parser/CodeBlock.ts | 37 ---- web/src/labs/marked/parser/CodeBlock.tsx | 51 +++++ web/src/labs/marked/parser/DoneList.ts | 26 --- web/src/labs/marked/parser/DoneList.tsx | 28 +++ .../parser/{Emphasis.ts => Emphasis.tsx} | 15 +- web/src/labs/marked/parser/Heading.ts | 25 --- web/src/labs/marked/parser/Heading.tsx | 29 +++ web/src/labs/marked/parser/HorizontalRules.ts | 18 -- .../labs/marked/parser/HorizontalRules.tsx | 12 ++ .../marked/parser/{Image.ts => Image.tsx} | 15 +- web/src/labs/marked/parser/InlineCode.ts | 24 --- web/src/labs/marked/parser/InlineCode.tsx | 19 ++ .../labs/marked/parser/{Link.ts => Link.tsx} | 19 +- web/src/labs/marked/parser/OrderedList.ts | 26 --- web/src/labs/marked/parser/OrderedList.tsx | 26 +++ .../parser/{Paragraph.ts => Paragraph.tsx} | 12 +- web/src/labs/marked/parser/PlainLink.ts | 24 --- web/src/labs/marked/parser/PlainLink.tsx | 23 +++ .../parser/{PlainText.ts => PlainText.tsx} | 11 +- web/src/labs/marked/parser/Strikethrough.ts | 24 --- web/src/labs/marked/parser/Strikethrough.tsx | 19 ++ web/src/labs/marked/parser/Tag.ts | 27 --- web/src/labs/marked/parser/Tag.tsx | 19 ++ web/src/labs/marked/parser/TodoList.ts | 26 --- web/src/labs/marked/parser/TodoList.tsx | 26 +++ web/src/labs/marked/parser/UnorderedList.ts | 26 --- web/src/labs/marked/parser/UnorderedList.tsx | 26 +++ 42 files changed, 417 insertions(+), 637 deletions(-) delete mode 100644 web/src/labs/highlighter/index.ts rename web/src/labs/marked/{index.ts => index.tsx} (72%) delete mode 100644 web/src/labs/marked/marked.test.ts create mode 100644 web/src/labs/marked/matcher.ts delete mode 100644 web/src/labs/marked/parser/Blockquote.ts create mode 100644 web/src/labs/marked/parser/Blockquote.tsx delete mode 100644 web/src/labs/marked/parser/Bold.ts create mode 100644 web/src/labs/marked/parser/Bold.tsx rename web/src/labs/marked/parser/{BoldEmphasis.ts => BoldEmphasis.tsx} (52%) delete mode 100644 web/src/labs/marked/parser/Br.ts create mode 100644 web/src/labs/marked/parser/Br.tsx delete mode 100644 web/src/labs/marked/parser/CodeBlock.ts create mode 100644 web/src/labs/marked/parser/CodeBlock.tsx delete mode 100644 web/src/labs/marked/parser/DoneList.ts create mode 100644 web/src/labs/marked/parser/DoneList.tsx rename web/src/labs/marked/parser/{Emphasis.ts => Emphasis.tsx} (53%) delete mode 100644 web/src/labs/marked/parser/Heading.ts create mode 100644 web/src/labs/marked/parser/Heading.tsx delete mode 100644 web/src/labs/marked/parser/HorizontalRules.ts create mode 100644 web/src/labs/marked/parser/HorizontalRules.tsx rename web/src/labs/marked/parser/{Image.ts => Image.tsx} (51%) delete mode 100644 web/src/labs/marked/parser/InlineCode.ts create mode 100644 web/src/labs/marked/parser/InlineCode.tsx rename web/src/labs/marked/parser/{Link.ts => Link.tsx} (59%) delete mode 100644 web/src/labs/marked/parser/OrderedList.ts create mode 100644 web/src/labs/marked/parser/OrderedList.tsx rename web/src/labs/marked/parser/{Paragraph.ts => Paragraph.tsx} (51%) delete mode 100644 web/src/labs/marked/parser/PlainLink.ts create mode 100644 web/src/labs/marked/parser/PlainLink.tsx rename web/src/labs/marked/parser/{PlainText.ts => PlainText.tsx} (58%) delete mode 100644 web/src/labs/marked/parser/Strikethrough.ts create mode 100644 web/src/labs/marked/parser/Strikethrough.tsx delete mode 100644 web/src/labs/marked/parser/Tag.ts create mode 100644 web/src/labs/marked/parser/Tag.tsx delete mode 100644 web/src/labs/marked/parser/TodoList.ts create mode 100644 web/src/labs/marked/parser/TodoList.tsx delete mode 100644 web/src/labs/marked/parser/UnorderedList.ts create mode 100644 web/src/labs/marked/parser/UnorderedList.tsx diff --git a/web/src/components/CreateTagDialog.tsx b/web/src/components/CreateTagDialog.tsx index ea2ab6858adc5..3dc57e6381bf2 100644 --- a/web/src/components/CreateTagDialog.tsx +++ b/web/src/components/CreateTagDialog.tsx @@ -2,6 +2,7 @@ import { TextField } from "@mui/joy"; import React, { useEffect, useState } from "react"; import { useTagStore } from "../store/module"; import { getTagSuggestionList } from "../helpers/api"; +import { matcher } from "../labs/marked/matcher"; import Tag from "../labs/marked/parser/Tag"; import Icon from "./Icon"; import toastHelper from "./Toast"; @@ -10,7 +11,7 @@ import { generateDialog } from "./Dialog"; type Props = DialogProps; const validateTagName = (tagName: string): boolean => { - const matchResult = Tag.matcher(`#${tagName}`); + const matchResult = matcher(`#${tagName}`, Tag.regexp); if (!matchResult || matchResult[1] !== tagName) { return false; } diff --git a/web/src/components/Memo.tsx b/web/src/components/Memo.tsx index bd2468d36b2dd..499785da09052 100644 --- a/web/src/components/Memo.tsx +++ b/web/src/components/Memo.tsx @@ -15,7 +15,6 @@ import "../less/memo.less"; interface Props { memo: Memo; - highlightWord?: string; } export const getFormatedMemoTimeStr = (time: number, locale = "en"): string => { @@ -27,7 +26,7 @@ export const getFormatedMemoTimeStr = (time: number, locale = "en"): string => { }; const Memo: React.FC = (props: Props) => { - const { memo, highlightWord } = props; + const { memo } = props; const { t, i18n } = useTranslation(); const navigate = useNavigate(); const editorStore = useEditorStore(); @@ -143,9 +142,6 @@ const Memo: React.FC = (props: Props) => { if (imgUrl) { showPreviewImageDialog([imgUrl], 0); } - } else if (targetEl.tagName === "BUTTON" && targetEl.className === "codeblock-copy-btn") { - copy(targetEl.parentElement?.children[1].textContent ?? ""); - toastHelper.success(t("message.succeed-copy-code")); } }; @@ -228,7 +224,6 @@ const Memo: React.FC = (props: Props) => { diff --git a/web/src/components/MemoContent.tsx b/web/src/components/MemoContent.tsx index a486eb03856dd..20bd038575be7 100644 --- a/web/src/components/MemoContent.tsx +++ b/web/src/components/MemoContent.tsx @@ -2,7 +2,6 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useUserStore } from "../store/module"; import { marked } from "../labs/marked"; -import { highlightWithWord } from "../labs/highlighter"; import Icon from "./Icon"; import "../less/memo-content.less"; @@ -12,7 +11,6 @@ export interface DisplayConfig { interface Props { content: string; - highlightWord?: string; className?: string; displayConfig?: Partial; onMemoContentClick?: (e: React.MouseEvent) => void; @@ -30,14 +28,14 @@ const defaultDisplayConfig: DisplayConfig = { }; const MemoContent: React.FC = (props: Props) => { - const { className, content, highlightWord, onMemoContentClick, onMemoContentDoubleClick } = props; + const { className, content, onMemoContentClick, onMemoContentDoubleClick } = props; + const { t } = useTranslation(); + const userStore = useUserStore(); + const user = userStore.state.user; const foldedContent = useMemo(() => { const firstHorizontalRuleIndex = content.search(/^---$|^\*\*\*$|^___$/m); return firstHorizontalRuleIndex !== -1 ? content.slice(0, firstHorizontalRuleIndex) : content; }, [content]); - const { t } = useTranslation(); - const userStore = useUserStore(); - const user = userStore.state.user; const [state, setState] = useState({ expandButtonStatus: -1, @@ -97,10 +95,9 @@ const MemoContent: React.FC = (props: Props) => { className={`memo-content-text ${state.expandButtonStatus === 0 ? "expanded" : ""}`} onClick={handleMemoContentClick} onDoubleClick={handleMemoContentDoubleClick} - dangerouslySetInnerHTML={{ - __html: highlightWithWord(marked(state.expandButtonStatus === 0 ? foldedContent : content), highlightWord), - }} - > + > + {marked(state.expandButtonStatus === 0 ? foldedContent : content)} + {state.expandButtonStatus !== -1 && (
diff --git a/web/src/components/MemoList.tsx b/web/src/components/MemoList.tsx index 55c7a00eb736c..cf66fbde7a243 100644 --- a/web/src/components/MemoList.tsx +++ b/web/src/components/MemoList.tsx @@ -19,7 +19,6 @@ const MemoList = () => { const memoDisplayTsOption = userStore.state.user?.setting.memoDisplayTsOption; const { memos, isFetching } = memoStore.state; const [isComplete, setIsComplete] = useState(false); - const [highlightWord, setHighlightWord] = useState(""); const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId, visibility } = query ?? {}; const shortcut = shortcutId ? shortcutStore.getShortcutById(shortcutId) : null; @@ -107,7 +106,6 @@ const MemoList = () => { if (pageWrapper) { pageWrapper.scrollTo(0, 0); } - setHighlightWord(query?.text); }, [query]); useEffect(() => { @@ -136,7 +134,7 @@ const MemoList = () => { return (
{sortedMemos.map((memo) => ( - + ))} {isFetching ? (
diff --git a/web/src/labs/highlighter/index.ts b/web/src/labs/highlighter/index.ts deleted file mode 100644 index d18e6cb159594..0000000000000 --- a/web/src/labs/highlighter/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { escape } from "lodash"; - -const walkthroughNodeWithKeyword = (node: HTMLElement, keyword: string) => { - if (node.nodeType === 3) { - const span = document.createElement("span"); - span.innerHTML = node.nodeValue?.replace(new RegExp(keyword, "g"), `${keyword}`) ?? ""; - node.parentNode?.insertBefore(span, node); - node.parentNode?.removeChild(node); - } - for (const child of Array.from(node.childNodes)) { - walkthroughNodeWithKeyword(child, keyword); - } - return node.innerHTML; -}; - -export const highlightWithWord = (html: string, keyword?: string): string => { - if (!keyword) { - return html; - } - keyword = escape(keyword); - const wrap = document.createElement("div"); - wrap.innerHTML = escape(html); - return walkthroughNodeWithKeyword(wrap, keyword); -}; diff --git a/web/src/labs/marked/index.ts b/web/src/labs/marked/index.tsx similarity index 72% rename from web/src/labs/marked/index.ts rename to web/src/labs/marked/index.tsx index 0d3d083ad5a25..bbae6c49ba753 100644 --- a/web/src/labs/marked/index.ts +++ b/web/src/labs/marked/index.tsx @@ -1,8 +1,13 @@ +import { matcher } from "./matcher"; import { blockElementParserList, inlineElementParserList } from "./parser"; -export const marked = (markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList): string => { +export const marked = ( + markdownStr: string, + blockParsers = blockElementParserList, + inlineParsers = inlineElementParserList +): string | JSX.Element => { for (const parser of blockParsers) { - const matchResult = parser.matcher(markdownStr); + const matchResult = matcher(markdownStr, parser.regexp); if (!matchResult) { continue; } @@ -10,12 +15,22 @@ export const marked = (markdownStr: string, blockParsers = blockElementParserLis const retainContent = markdownStr.slice(matchedStr.length); if (parser.name === "br") { - return parser.renderer(matchedStr) + marked(retainContent, blockParsers, inlineParsers); + return ( + <> + {parser.renderer(matchedStr)} + {marked(retainContent, blockParsers, inlineParsers)} + + ); } else { if (retainContent === "") { return parser.renderer(matchedStr); } else if (retainContent.startsWith("\n")) { - return parser.renderer(matchedStr) + marked(retainContent.slice(1), blockParsers, inlineParsers); + return ( + <> + {parser.renderer(matchedStr)} + {marked(retainContent.slice(1), blockParsers, inlineParsers)} + + ); } } } @@ -24,7 +39,7 @@ export const marked = (markdownStr: string, blockParsers = blockElementParserLis let matchedIndex = -1; for (const parser of inlineParsers) { - const matchResult = parser.matcher(markdownStr); + const matchResult = matcher(markdownStr, parser.regexp); if (!matchResult) { continue; } @@ -41,17 +56,23 @@ export const marked = (markdownStr: string, blockParsers = blockElementParserLis } if (matchedInlineParser) { - const matchResult = matchedInlineParser.matcher(markdownStr); + 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); - return marked(prefixStr, [], inlineParsers) + matchedInlineParser.renderer(matchedStr) + marked(suffixStr, [], inlineParsers); + return ( + <> + {marked(prefixStr, [], inlineParsers)} + {matchedInlineParser.renderer(matchedStr)} + {marked(suffixStr, [], inlineParsers)} + + ); } } - return markdownStr; + return <>{markdownStr}; }; interface MatchedNode { @@ -64,7 +85,7 @@ export const getMatchedNodes = (markdownStr: string): MatchedNode[] => { const walkthough = (markdownStr: string, blockParsers = blockElementParserList, inlineParsers = inlineElementParserList): string => { for (const parser of blockParsers) { - const matchResult = parser.matcher(markdownStr); + const matchResult = matcher(markdownStr, parser.regexp); if (!matchResult) { continue; } @@ -79,6 +100,7 @@ export const getMatchedNodes = (markdownStr: string): MatchedNode[] => { return walkthough(retainContent, blockParsers, inlineParsers); } else { if (retainContent.startsWith("\n")) { + walkthough(matchedStr, [], inlineParsers); return walkthough(retainContent.slice(1), blockParsers, inlineParsers); } } @@ -88,7 +110,7 @@ export const getMatchedNodes = (markdownStr: string): MatchedNode[] => { let matchedIndex = -1; for (const parser of inlineParsers) { - const matchResult = parser.matcher(markdownStr); + const matchResult = matcher(markdownStr, parser.regexp); if (!matchResult) { continue; } @@ -105,7 +127,7 @@ export const getMatchedNodes = (markdownStr: string): MatchedNode[] => { } if (matchedInlineParser) { - const matchResult = matchedInlineParser.matcher(markdownStr); + const matchResult = matcher(markdownStr, matchedInlineParser.regexp); if (matchResult) { const matchedStr = matchResult[0]; const matchedLength = matchedStr.length; diff --git a/web/src/labs/marked/marked.test.ts b/web/src/labs/marked/marked.test.ts deleted file mode 100644 index 8ef893da03885..0000000000000 --- a/web/src/labs/marked/marked.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -/* eslint-disable no-irregular-whitespace */ -import { describe, expect, test } from "@jest/globals"; -import { unescape } from "lodash-es"; -import { marked } from "."; - -describe("test marked parser", () => { - test("horizontal rule", () => { - const tests = [ - { - markdown: `--- -This is some text after the horizontal rule. -___ -This is some text after the horizontal rule. -*** -This is some text after the horizontal rule.`, - want: `

This is some text after the horizontal rule.


This is some text after the horizontal rule.


This is some text after the horizontal rule.

`, - }, - ]; - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse code block", () => { - const tests = [ - { - markdown: `\`\`\` -hello world! -\`\`\``, - want: `
hello world!
-
`, - }, - { - markdown: `test code block - -\`\`\`js -console.log("hello world!") -\`\`\``, - want: `

test code block


console.log("hello world!")
-
`, - }, - ]; - - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse todo list block", () => { - const tests = [ - { - markdown: `My task: -- [ ] finish my homework -- [x] yahaha`, - want: `

My task:

finish my homework

yahaha

`, - }, - ]; - - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse list block", () => { - const tests = [ - { - markdown: `This is a list -* list 123 -1. 123123`, - want: `

This is a list

list 123

1.123123

`, - }, - ]; - - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse inline element", () => { - const tests = [ - { - markdown: `Link: [baidu](https://baidu.com#1231)`, - want: `

Link: baidu

`, - }, - ]; - - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse inline code within inline element", () => { - const tests = [ - { - markdown: `Link: [\`baidu\`](https://baidu.com)`, - want: `

Link: baidu

`, - }, - ]; - - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse plain link", () => { - const tests = [ - { - markdown: `Link:https://baidu.com#1231`, - want: `

Link:https://baidu.com#1231

`, - }, - ]; - - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse inline code", () => { - const tests = [ - { - markdown: `Code: \`console.log("Hello world!")\``, - want: `

Code: console.log("Hello world!")

`, - }, - ]; - - for (const t of tests) { - expect(unescape(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(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse full width space", () => { - const tests = [ - { - markdown: `  line1 -  line2`, - want: `

  line1

  line2

`, - }, - ]; - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); - test("parse heading", () => { - const tests = [ - { - markdown: `# 123 `, - want: `

123

`, - }, - { - markdown: `## 123 `, - want: `

123

`, - }, - ]; - for (const t of tests) { - expect(unescape(marked(t.markdown))).toBe(t.want); - } - }); -}); diff --git a/web/src/labs/marked/matcher.ts b/web/src/labs/marked/matcher.ts new file mode 100644 index 0000000000000..475d809e9fc3d --- /dev/null +++ b/web/src/labs/marked/matcher.ts @@ -0,0 +1,4 @@ +export const matcher = (rawStr: string, regexp: RegExp) => { + const matchResult = rawStr.match(regexp); + return matchResult; +}; diff --git a/web/src/labs/marked/parser/Blockquote.ts b/web/src/labs/marked/parser/Blockquote.ts deleted file mode 100644 index 3e1a47a442dc2..0000000000000 --- a/web/src/labs/marked/parser/Blockquote.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { escape } from "lodash"; - -export const BLOCKQUOTE_REG = /^> ([^\n]+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(BLOCKQUOTE_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - return `
${escape(matchResult[1])}
`; -}; - -export default { - name: "blockquote", - regex: BLOCKQUOTE_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/Blockquote.tsx b/web/src/labs/marked/parser/Blockquote.tsx new file mode 100644 index 0000000000000..da4d02c7e19a1 --- /dev/null +++ b/web/src/labs/marked/parser/Blockquote.tsx @@ -0,0 +1,19 @@ +import { escape } from "lodash"; +import { matcher } from "../matcher"; + +export const BLOCKQUOTE_REG = /^> ([^\n]+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, BLOCKQUOTE_REG); + if (!matchResult) { + return <>{rawStr}; + } + + return
{escape(matchResult[1])}
; +}; + +export default { + name: "blockquote", + regexp: BLOCKQUOTE_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/Bold.ts b/web/src/labs/marked/parser/Bold.ts deleted file mode 100644 index af8b8756e36c3..0000000000000 --- a/web/src/labs/marked/parser/Bold.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { marked } from ".."; -import Link from "./Link"; -import PlainText from "./PlainText"; - -export const BOLD_REG = /\*\*(.+?)\*\*/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(BOLD_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - const parsedContent = marked(matchResult[1], [], [Link, PlainText]); - return `${parsedContent}`; -}; - -export default { - name: "bold", - regex: BOLD_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/Bold.tsx b/web/src/labs/marked/parser/Bold.tsx new file mode 100644 index 0000000000000..259eb0f86fc96 --- /dev/null +++ b/web/src/labs/marked/parser/Bold.tsx @@ -0,0 +1,22 @@ +import { marked } from ".."; +import { matcher } from "../matcher"; +import Link from "./Link"; +import PlainText from "./PlainText"; + +export const BOLD_REG = /\*\*(.+?)\*\*/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, BOLD_REG); + if (!matchResult) { + return <>{rawStr}; + } + + const parsedContent = marked(matchResult[1], [], [Link, PlainText]); + return {parsedContent}; +}; + +export default { + name: "bold", + regexp: BOLD_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/BoldEmphasis.ts b/web/src/labs/marked/parser/BoldEmphasis.tsx similarity index 52% rename from web/src/labs/marked/parser/BoldEmphasis.ts rename to web/src/labs/marked/parser/BoldEmphasis.tsx index 450589b24ad99..66b6eea4dd4a1 100644 --- a/web/src/labs/marked/parser/BoldEmphasis.ts +++ b/web/src/labs/marked/parser/BoldEmphasis.tsx @@ -1,27 +1,26 @@ import { marked } from ".."; +import { matcher } from "../matcher"; import Link from "./Link"; import PlainText from "./PlainText"; export const BOLD_EMPHASIS_REG = /\*\*\*(.+?)\*\*\*/; -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(BOLD_EMPHASIS_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, BOLD_EMPHASIS_REG); if (!matchResult) { return rawStr; } const parsedContent = marked(matchResult[1], [], [Link, PlainText]); - return `${parsedContent}`; + return ( + + ${parsedContent} + + ); }; export default { name: "bold emphasis", - regex: BOLD_EMPHASIS_REG, - matcher, + regexp: BOLD_EMPHASIS_REG, renderer, }; diff --git a/web/src/labs/marked/parser/Br.ts b/web/src/labs/marked/parser/Br.ts deleted file mode 100644 index 0882474f80c7c..0000000000000 --- a/web/src/labs/marked/parser/Br.ts +++ /dev/null @@ -1,17 +0,0 @@ -export const BR_REG = /^(\n+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(BR_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - return rawStr.replaceAll("\n", "
"); -}; - -export default { - name: "br", - regex: BR_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/Br.tsx b/web/src/labs/marked/parser/Br.tsx new file mode 100644 index 0000000000000..9bd80ba8c47c6 --- /dev/null +++ b/web/src/labs/marked/parser/Br.tsx @@ -0,0 +1,16 @@ +export const BR_REG = /^(\n+)/; + +const renderer = (rawStr: string) => { + const length = rawStr.split("\n").length - 1; + const brList = []; + for (let i = 0; i < length; i++) { + brList.push(
); + } + return <>{...brList}; +}; + +export default { + name: "br", + regexp: BR_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/CodeBlock.ts b/web/src/labs/marked/parser/CodeBlock.ts deleted file mode 100644 index cb55617de8053..0000000000000 --- a/web/src/labs/marked/parser/CodeBlock.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { escape } from "lodash-es"; -import hljs from "highlight.js"; - -export const CODE_BLOCK_REG = /^```(\S*?)\s([\s\S]*?)```/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(CODE_BLOCK_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - const language = escape(matchResult[1]) || "plaintext"; - let highlightedCode = hljs.highlightAuto(matchResult[2]).value; - - try { - const temp = hljs.highlight(matchResult[2], { - language, - }).value; - highlightedCode = temp; - } catch (error) { - // do nth - } - - return `
${highlightedCode}
`; -}; - -export default { - name: "code block", - regex: CODE_BLOCK_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/CodeBlock.tsx b/web/src/labs/marked/parser/CodeBlock.tsx new file mode 100644 index 0000000000000..e3c4be4575113 --- /dev/null +++ b/web/src/labs/marked/parser/CodeBlock.tsx @@ -0,0 +1,51 @@ +import copy from "copy-to-clipboard"; +import { escape } from "lodash-es"; +import hljs from "highlight.js"; +import { useTranslation } from "react-i18next"; +import { matcher } from "../matcher"; +import toastHelper from "../../../components/Toast"; + +export const CODE_BLOCK_REG = /^```(\S*?)\s([\s\S]*?)```/; + +const renderer = (rawStr: string) => { + const { t } = useTranslation(); + const matchResult = matcher(rawStr, CODE_BLOCK_REG); + if (!matchResult) { + return <>{rawStr}; + } + + const language = escape(matchResult[1]) || "plaintext"; + let highlightedCode = hljs.highlightAuto(matchResult[2]).value; + + try { + const temp = hljs.highlight(matchResult[2], { + language, + }).value; + highlightedCode = temp; + } catch (error) { + // do nth + } + + const handleCopyButtonClick = () => { + copy(matchResult[2]); + toastHelper.success(t("message.succeed-copy-code")); + }; + + return ( +
+      
+      {highlightedCode}
+    
+ ); +}; + +export default { + name: "code block", + regexp: CODE_BLOCK_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/DoneList.ts b/web/src/labs/marked/parser/DoneList.ts deleted file mode 100644 index 5faee636c5f26..0000000000000 --- a/web/src/labs/marked/parser/DoneList.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { inlineElementParserList } from "."; -import { marked } from ".."; - -export const DONE_LIST_REG = /^- \[[xX]\] ([^\n]+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(DONE_LIST_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - const parsedContent = marked(matchResult[1], [], inlineElementParserList); - return `

${parsedContent}

`; -}; - -export default { - name: "done list", - regex: DONE_LIST_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/DoneList.tsx b/web/src/labs/marked/parser/DoneList.tsx new file mode 100644 index 0000000000000..b3b1c10b04e05 --- /dev/null +++ b/web/src/labs/marked/parser/DoneList.tsx @@ -0,0 +1,28 @@ +import { inlineElementParserList } from "."; +import { marked } from ".."; +import { matcher } from "../matcher"; + +export const DONE_LIST_REG = /^- \[[xX]\] ([^\n]+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, DONE_LIST_REG); + if (!matchResult) { + return rawStr; + } + + const parsedContent = marked(matchResult[1], [], inlineElementParserList); + return ( +

+ + ✓ + + {parsedContent} +

+ ); +}; + +export default { + name: "done list", + regexp: DONE_LIST_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/Emphasis.ts b/web/src/labs/marked/parser/Emphasis.tsx similarity index 53% rename from web/src/labs/marked/parser/Emphasis.ts rename to web/src/labs/marked/parser/Emphasis.tsx index b8f91260fc3f6..20c2ece1661b2 100644 --- a/web/src/labs/marked/parser/Emphasis.ts +++ b/web/src/labs/marked/parser/Emphasis.tsx @@ -1,27 +1,22 @@ import { marked } from ".."; +import { matcher } from "../matcher"; import Link from "./Link"; import PlainText from "./PlainText"; export const EMPHASIS_REG = /\*(.+?)\*/; -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(EMPHASIS_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, EMPHASIS_REG); if (!matchResult) { return rawStr; } const parsedContent = marked(matchResult[1], [], [Link, PlainText]); - return `${parsedContent}`; + return {parsedContent}; }; export default { name: "emphasis", - regex: EMPHASIS_REG, - matcher, + regexp: EMPHASIS_REG, renderer, }; diff --git a/web/src/labs/marked/parser/Heading.ts b/web/src/labs/marked/parser/Heading.ts deleted file mode 100644 index 9f5dd2de20f6e..0000000000000 --- a/web/src/labs/marked/parser/Heading.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { escape } from "lodash"; - -export const HEADING_REG = /^(#+) ([^\n]+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(HEADING_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - const level = matchResult[1].length; - return `${escape(matchResult[2])}`; -}; - -export default { - name: "heading", - regex: HEADING_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/Heading.tsx b/web/src/labs/marked/parser/Heading.tsx new file mode 100644 index 0000000000000..82308e4b7adbd --- /dev/null +++ b/web/src/labs/marked/parser/Heading.tsx @@ -0,0 +1,29 @@ +import { escape } from "lodash"; +import { matcher } from "../matcher"; + +export const HEADING_REG = /^(#+) ([^\n]+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, HEADING_REG); + if (!matchResult) { + return rawStr; + } + + const level = matchResult[1].length; + if (level === 1) { + return

{escape(matchResult[2])}

; + } else if (level === 2) { + return

{escape(matchResult[2])}

; + } else if (level === 3) { + return

{escape(matchResult[2])}

; + } else if (level === 4) { + return

{escape(matchResult[2])}

; + } + return
{escape(matchResult[2])}
; +}; + +export default { + name: "heading", + regexp: HEADING_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/HorizontalRules.ts b/web/src/labs/marked/parser/HorizontalRules.ts deleted file mode 100644 index a52a519bdbe21..0000000000000 --- a/web/src/labs/marked/parser/HorizontalRules.ts +++ /dev/null @@ -1,18 +0,0 @@ -export const HORIZONTAL_RULES_REG = /^_{3}|^-{3}|^\*{3}/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(HORIZONTAL_RULES_REG); - return matchResult; -}; - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export const renderer = (rawStr: string): string => { - return `
`; -}; - -export default { - name: "horizontal rules", - regex: HORIZONTAL_RULES_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/HorizontalRules.tsx b/web/src/labs/marked/parser/HorizontalRules.tsx new file mode 100644 index 0000000000000..e8f14864d8e4a --- /dev/null +++ b/web/src/labs/marked/parser/HorizontalRules.tsx @@ -0,0 +1,12 @@ +export const HORIZONTAL_RULES_REG = /^_{3}|^-{3}|^\*{3}/; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const renderer = (rawStr: string) => { + return
; +}; + +export default { + name: "horizontal rules", + regexp: HORIZONTAL_RULES_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/Image.ts b/web/src/labs/marked/parser/Image.tsx similarity index 51% rename from web/src/labs/marked/parser/Image.ts rename to web/src/labs/marked/parser/Image.tsx index b3afc50a12121..81052a3edbf54 100644 --- a/web/src/labs/marked/parser/Image.ts +++ b/web/src/labs/marked/parser/Image.tsx @@ -1,26 +1,21 @@ import { escape } from "lodash-es"; import { absolutifyLink } from "../../../helpers/utils"; +import { matcher } from "../matcher"; export const IMAGE_REG = /!\[.*?\]\((.+?)\)/; -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(IMAGE_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, IMAGE_REG); if (!matchResult) { return rawStr; } const imageUrl = absolutifyLink(escape(matchResult[1])); - return ``; + return ; }; export default { name: "image", - regex: IMAGE_REG, - matcher, + regexp: IMAGE_REG, renderer, }; diff --git a/web/src/labs/marked/parser/InlineCode.ts b/web/src/labs/marked/parser/InlineCode.ts deleted file mode 100644 index 7de2a1f9d7515..0000000000000 --- a/web/src/labs/marked/parser/InlineCode.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { escape } from "lodash-es"; - -export const INLINE_CODE_REG = /`(.+?)`/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(INLINE_CODE_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - return `${escape(matchResult[1])}`; -}; - -export default { - name: "inline code", - regex: INLINE_CODE_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/InlineCode.tsx b/web/src/labs/marked/parser/InlineCode.tsx new file mode 100644 index 0000000000000..0c7c90d3f83c8 --- /dev/null +++ b/web/src/labs/marked/parser/InlineCode.tsx @@ -0,0 +1,19 @@ +import { escape } from "lodash-es"; +import { matcher } from "../matcher"; + +export const INLINE_CODE_REG = /`(.+?)`/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, INLINE_CODE_REG); + if (!matchResult) { + return rawStr; + } + + return {escape(matchResult[1])}; +}; + +export default { + name: "inline code", + regexp: INLINE_CODE_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/Link.ts b/web/src/labs/marked/parser/Link.tsx similarity index 59% rename from web/src/labs/marked/parser/Link.ts rename to web/src/labs/marked/parser/Link.tsx index 89c4ae65e12c3..3ff7ada09c173 100644 --- a/web/src/labs/marked/parser/Link.ts +++ b/web/src/labs/marked/parser/Link.tsx @@ -5,26 +5,25 @@ import { marked } from ".."; import InlineCode from "./InlineCode"; import BoldEmphasis from "./BoldEmphasis"; import PlainText from "./PlainText"; +import { matcher } from "../matcher"; export const LINK_REG = /\[(.*?)\]\((.+?)\)+/; -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(LINK_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, LINK_REG); if (!matchResult) { return rawStr; } const parsedContent = marked(matchResult[1], [], [InlineCode, BoldEmphasis, Emphasis, Bold, PlainText]); - return `${parsedContent}`; + return ( + + {parsedContent} + + ); }; export default { name: "link", - regex: LINK_REG, - matcher, + regexp: LINK_REG, renderer, }; diff --git a/web/src/labs/marked/parser/OrderedList.ts b/web/src/labs/marked/parser/OrderedList.ts deleted file mode 100644 index 3f7f3fb7bbf62..0000000000000 --- a/web/src/labs/marked/parser/OrderedList.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { inlineElementParserList } from "."; -import { marked } from ".."; - -export const ORDERED_LIST_REG = /^(\d+)\. (.+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(ORDERED_LIST_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - const parsedContent = marked(matchResult[2], [], inlineElementParserList); - return `

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

`; -}; - -export default { - name: "ordered list", - regex: ORDERED_LIST_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/OrderedList.tsx b/web/src/labs/marked/parser/OrderedList.tsx new file mode 100644 index 0000000000000..ebe0dc99305ff --- /dev/null +++ b/web/src/labs/marked/parser/OrderedList.tsx @@ -0,0 +1,26 @@ +import { inlineElementParserList } from "."; +import { marked } from ".."; +import { matcher } from "../matcher"; + +export const ORDERED_LIST_REG = /^(\d+)\. (.+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, ORDERED_LIST_REG); + if (!matchResult) { + return rawStr; + } + + const parsedContent = marked(matchResult[2], [], inlineElementParserList); + return ( +

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

+ ); +}; + +export default { + name: "ordered list", + regexp: ORDERED_LIST_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/Paragraph.ts b/web/src/labs/marked/parser/Paragraph.tsx similarity index 51% rename from web/src/labs/marked/parser/Paragraph.ts rename to web/src/labs/marked/parser/Paragraph.tsx index bc22d8ca2f097..60cb69d6d5979 100644 --- a/web/src/labs/marked/parser/Paragraph.ts +++ b/web/src/labs/marked/parser/Paragraph.tsx @@ -3,19 +3,13 @@ import { marked } from ".."; export const PARAGRAPH_REG = /^([^\n]+)/; -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(PARAGRAPH_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { +const renderer = (rawStr: string) => { const parsedContent = marked(rawStr, [], inlineElementParserList); - return `

${parsedContent}

`; + return

{parsedContent}

; }; export default { name: "paragraph", - regex: PARAGRAPH_REG, - matcher, + regexp: PARAGRAPH_REG, renderer, }; diff --git a/web/src/labs/marked/parser/PlainLink.ts b/web/src/labs/marked/parser/PlainLink.ts deleted file mode 100644 index 3af201ad89864..0000000000000 --- a/web/src/labs/marked/parser/PlainLink.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { escape } from "lodash-es"; - -export const PLAIN_LINK_REG = /(https?:\/\/[^ ]+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(PLAIN_LINK_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - return `${escape(matchResult[1])}`; -}; - -export default { - name: "plain link", - regex: PLAIN_LINK_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/PlainLink.tsx b/web/src/labs/marked/parser/PlainLink.tsx new file mode 100644 index 0000000000000..f420fbe47ab8d --- /dev/null +++ b/web/src/labs/marked/parser/PlainLink.tsx @@ -0,0 +1,23 @@ +import { escape } from "lodash-es"; +import { matcher } from "../matcher"; + +export const PLAIN_LINK_REG = /(https?:\/\/[^ ]+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, PLAIN_LINK_REG); + if (!matchResult) { + return rawStr; + } + + return ( + + {escape(matchResult[1])} + + ); +}; + +export default { + name: "plain link", + regexp: PLAIN_LINK_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/PlainText.ts b/web/src/labs/marked/parser/PlainText.tsx similarity index 58% rename from web/src/labs/marked/parser/PlainText.ts rename to web/src/labs/marked/parser/PlainText.tsx index 507c979fe2de6..498c7b50a485a 100644 --- a/web/src/labs/marked/parser/PlainText.ts +++ b/web/src/labs/marked/parser/PlainText.tsx @@ -1,14 +1,10 @@ import { escape } from "lodash-es"; +import { matcher } from "../matcher"; export const PLAIN_TEXT_REG = /(.+)/; -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(PLAIN_TEXT_REG); - return matchResult; -}; - const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); + const matchResult = matcher(rawStr, PLAIN_TEXT_REG); if (!matchResult) { return rawStr; } @@ -18,7 +14,6 @@ const renderer = (rawStr: string): string => { export default { name: "plain text", - regex: PLAIN_TEXT_REG, - matcher, + regexp: PLAIN_TEXT_REG, renderer, }; diff --git a/web/src/labs/marked/parser/Strikethrough.ts b/web/src/labs/marked/parser/Strikethrough.ts deleted file mode 100644 index 7dc189766a500..0000000000000 --- a/web/src/labs/marked/parser/Strikethrough.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { escape } from "lodash"; - -export const STRIKETHROUGH_REG = /~~(.+?)~~/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(STRIKETHROUGH_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - return `${escape(matchResult[1])}`; -}; - -export default { - name: "Strikethrough", - regex: STRIKETHROUGH_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/Strikethrough.tsx b/web/src/labs/marked/parser/Strikethrough.tsx new file mode 100644 index 0000000000000..5b0cb98b44ca9 --- /dev/null +++ b/web/src/labs/marked/parser/Strikethrough.tsx @@ -0,0 +1,19 @@ +import { escape } from "lodash"; +import { matcher } from "../matcher"; + +export const STRIKETHROUGH_REG = /~~(.+?)~~/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, STRIKETHROUGH_REG); + if (!matchResult) { + return rawStr; + } + + return {escape(matchResult[1])}; +}; + +export default { + name: "Strikethrough", + regexp: STRIKETHROUGH_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/Tag.ts b/web/src/labs/marked/parser/Tag.ts deleted file mode 100644 index a0fc5fffdee73..0000000000000 --- a/web/src/labs/marked/parser/Tag.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { escape } from "lodash-es"; - -export const TAG_REG = /#([^\s#]+)/; - -export const matcher = (rawStr: string) => { - const matchResult = rawStr.match(TAG_REG); - if (matchResult) { - return matchResult; - } - return null; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - return `#${escape(matchResult[1])}`; -}; - -export default { - name: "tag", - regex: TAG_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/Tag.tsx b/web/src/labs/marked/parser/Tag.tsx new file mode 100644 index 0000000000000..b7f1b5fb28b28 --- /dev/null +++ b/web/src/labs/marked/parser/Tag.tsx @@ -0,0 +1,19 @@ +import { escape } from "lodash-es"; +import { matcher } from "../matcher"; + +export const TAG_REG = /#([^\s#]+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, TAG_REG); + if (!matchResult) { + return rawStr; + } + + return #{escape(matchResult[1])}; +}; + +export default { + name: "tag", + regexp: TAG_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/TodoList.ts b/web/src/labs/marked/parser/TodoList.ts deleted file mode 100644 index 4d552ff30fb09..0000000000000 --- a/web/src/labs/marked/parser/TodoList.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { inlineElementParserList } from "."; -import { marked } from ".."; - -export const TODO_LIST_REG = /^- \[ \] ([^\n]+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(TODO_LIST_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - const parsedContent = marked(matchResult[1], [], inlineElementParserList); - return `

${parsedContent}

`; -}; - -export default { - name: "todo list", - regex: TODO_LIST_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/TodoList.tsx b/web/src/labs/marked/parser/TodoList.tsx new file mode 100644 index 0000000000000..10aa4ffbacb3d --- /dev/null +++ b/web/src/labs/marked/parser/TodoList.tsx @@ -0,0 +1,26 @@ +import { inlineElementParserList } from "."; +import { marked } from ".."; +import { matcher } from "../matcher"; + +export const TODO_LIST_REG = /^- \[ \] ([^\n]+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, TODO_LIST_REG); + if (!matchResult) { + return rawStr; + } + + const parsedContent = marked(matchResult[1], [], inlineElementParserList); + return ( +

+ + {parsedContent} +

+ ); +}; + +export default { + name: "todo list", + regexp: TODO_LIST_REG, + renderer, +}; diff --git a/web/src/labs/marked/parser/UnorderedList.ts b/web/src/labs/marked/parser/UnorderedList.ts deleted file mode 100644 index 29039828cef65..0000000000000 --- a/web/src/labs/marked/parser/UnorderedList.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { inlineElementParserList } from "."; -import { marked } from ".."; - -export const UNORDERED_LIST_REG = /^[*-] ([^\n]+)/; - -const matcher = (rawStr: string) => { - const matchResult = rawStr.match(UNORDERED_LIST_REG); - return matchResult; -}; - -const renderer = (rawStr: string): string => { - const matchResult = matcher(rawStr); - if (!matchResult) { - return rawStr; - } - - const parsedContent = marked(matchResult[1], [], inlineElementParserList); - return `

${parsedContent}

`; -}; - -export default { - name: "unordered list", - regex: UNORDERED_LIST_REG, - matcher, - renderer, -}; diff --git a/web/src/labs/marked/parser/UnorderedList.tsx b/web/src/labs/marked/parser/UnorderedList.tsx new file mode 100644 index 0000000000000..595d6e1e170c7 --- /dev/null +++ b/web/src/labs/marked/parser/UnorderedList.tsx @@ -0,0 +1,26 @@ +import { inlineElementParserList } from "."; +import { marked } from ".."; +import { matcher } from "../matcher"; + +export const UNORDERED_LIST_REG = /^[*-] ([^\n]+)/; + +const renderer = (rawStr: string) => { + const matchResult = matcher(rawStr, UNORDERED_LIST_REG); + if (!matchResult) { + return rawStr; + } + + const parsedContent = marked(matchResult[1], [], inlineElementParserList); + return ( +

+ + ${parsedContent} +

+ ); +}; + +export default { + name: "unordered list", + regexp: UNORDERED_LIST_REG, + renderer, +};