Skip to content

Commit

Permalink
refactor: return jsx element instead of string in marked (#910)
Browse files Browse the repository at this point in the history
* refactor: return jsx element instead of string in marked

* chore: update
  • Loading branch information
boojack committed Jan 6, 2023
1 parent 491859b commit 0f8ce3d
Show file tree
Hide file tree
Showing 42 changed files with 417 additions and 637 deletions.
3 changes: 2 additions & 1 deletion web/src/components/CreateTagDialog.tsx
Expand Up @@ -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";
Expand All @@ -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;
}
Expand Down
7 changes: 1 addition & 6 deletions web/src/components/Memo.tsx
Expand Up @@ -15,7 +15,6 @@ import "../less/memo.less";

interface Props {
memo: Memo;
highlightWord?: string;
}

export const getFormatedMemoTimeStr = (time: number, locale = "en"): string => {
Expand All @@ -27,7 +26,7 @@ export const getFormatedMemoTimeStr = (time: number, locale = "en"): string => {
};

const Memo: React.FC<Props> = (props: Props) => {
const { memo, highlightWord } = props;
const { memo } = props;
const { t, i18n } = useTranslation();
const navigate = useNavigate();
const editorStore = useEditorStore();
Expand Down Expand Up @@ -143,9 +142,6 @@ const Memo: React.FC<Props> = (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"));
}
};

Expand Down Expand Up @@ -228,7 +224,6 @@ const Memo: React.FC<Props> = (props: Props) => {
</div>
<MemoContent
content={memo.content}
highlightWord={highlightWord}
onMemoContentClick={handleMemoContentClick}
onMemoContentDoubleClick={handleMemoContentDoubleClick}
/>
Expand Down
17 changes: 7 additions & 10 deletions web/src/components/MemoContent.tsx
Expand Up @@ -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";

Expand All @@ -12,7 +11,6 @@ export interface DisplayConfig {

interface Props {
content: string;
highlightWord?: string;
className?: string;
displayConfig?: Partial<DisplayConfig>;
onMemoContentClick?: (e: React.MouseEvent) => void;
Expand All @@ -30,14 +28,14 @@ const defaultDisplayConfig: DisplayConfig = {
};

const MemoContent: React.FC<Props> = (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<State>({
expandButtonStatus: -1,
Expand Down Expand Up @@ -97,10 +95,9 @@ const MemoContent: React.FC<Props> = (props: Props) => {
className={`memo-content-text ${state.expandButtonStatus === 0 ? "expanded" : ""}`}
onClick={handleMemoContentClick}
onDoubleClick={handleMemoContentDoubleClick}
dangerouslySetInnerHTML={{
__html: highlightWithWord(marked(state.expandButtonStatus === 0 ? foldedContent : content), highlightWord),
}}
></div>
>
{marked(state.expandButtonStatus === 0 ? foldedContent : content)}
</div>
{state.expandButtonStatus !== -1 && (
<div className="expand-btn-container">
<span className={`btn ${state.expandButtonStatus === 0 ? "expand-btn" : "fold-btn"}`} onClick={handleExpandBtnClick}>
Expand Down
4 changes: 1 addition & 3 deletions web/src/components/MemoList.tsx
Expand Up @@ -19,7 +19,6 @@ const MemoList = () => {
const memoDisplayTsOption = userStore.state.user?.setting.memoDisplayTsOption;
const { memos, isFetching } = memoStore.state;
const [isComplete, setIsComplete] = useState<boolean>(false);
const [highlightWord, setHighlightWord] = useState<string | undefined>("");

const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId, visibility } = query ?? {};
const shortcut = shortcutId ? shortcutStore.getShortcutById(shortcutId) : null;
Expand Down Expand Up @@ -107,7 +106,6 @@ const MemoList = () => {
if (pageWrapper) {
pageWrapper.scrollTo(0, 0);
}
setHighlightWord(query?.text);
}, [query]);

useEffect(() => {
Expand Down Expand Up @@ -136,7 +134,7 @@ const MemoList = () => {
return (
<div className="memo-list-container">
{sortedMemos.map((memo) => (
<Memo key={`${memo.id}-${memo.displayTs}`} memo={memo} highlightWord={highlightWord} />
<Memo key={`${memo.id}-${memo.displayTs}`} memo={memo} />
))}
{isFetching ? (
<div className="status-text-container fetching-tip">
Expand Down
24 changes: 0 additions & 24 deletions web/src/labs/highlighter/index.ts

This file was deleted.

44 changes: 33 additions & 11 deletions web/src/labs/marked/index.ts → web/src/labs/marked/index.tsx
@@ -1,21 +1,36 @@
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;
}
const matchedStr = matchResult[0];
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)}
</>
);
}
}
}
Expand All @@ -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;
}
Expand All @@ -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 {
Expand All @@ -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;
}
Expand All @@ -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);
}
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down

0 comments on commit 0f8ce3d

Please sign in to comment.