mirror of
https://github.com/usememos/memos.git
synced 2025-03-27 08:00:13 +01:00
feat: use gomark wasm in frontend
This commit is contained in:
parent
3158c4b8b5
commit
8ce6a32aac
web
public
src
components
MemoContent
Blockquote.tsxBold.tsxCodeBlock.tsx
MemoView.tsxPreviewMarkdownDialog.tsxShareMemoDialog.tsxEmbeddedContent
Heading.tsxOrderedList.tsxParagraph.tsxRenderer.tsxTable.tsxTaskList.tsxUnorderedList.tsxindex.tsxtypes
pages
types
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
import { Node } from "@/types/proto/api/v2/node";
|
import { Node } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
import { BaseProps } from "./types";
|
import { BaseProps } from "./types";
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Node } from "@/types/proto/api/v2/node";
|
import { Node } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -12,7 +12,7 @@ interface Props extends BaseProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
|
const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
|
||||||
const formatedLanguage = language.toLowerCase() || "plaintext";
|
const formatedLanguage = (language || "").toLowerCase() || "plaintext";
|
||||||
let highlightedCode = hljs.highlightAuto(content).value;
|
let highlightedCode = hljs.highlightAuto(content).value;
|
||||||
|
|
||||||
// Users can set Markdown code blocks as `__html` to render HTML directly.
|
// Users can set Markdown code blocks as `__html` to render HTML directly.
|
||||||
|
@ -42,7 +42,7 @@ const EmbeddedMemo = ({ resourceId, params: paramsStr }: Props) => {
|
|||||||
if (inlineMode) {
|
if (inlineMode) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<MemoContent nodes={memo.nodes} memoId={memo.id} embeddedMemos={context.embeddedMemos} />
|
<MemoContent memoId={memo.id} content={memo.content} embeddedMemos={context.embeddedMemos} />
|
||||||
<MemoResourceListView resources={memo.resources} />
|
<MemoResourceListView resources={memo.resources} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -56,7 +56,7 @@ const EmbeddedMemo = ({ resourceId, params: paramsStr }: Props) => {
|
|||||||
<Icon.ArrowUpRight className="w-5 h-auto opacity-80 text-gray-400" />
|
<Icon.ArrowUpRight className="w-5 h-auto opacity-80 text-gray-400" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<MemoContent nodes={memo.nodes} memoId={memo.id} embeddedMemos={context.embeddedMemos} />
|
<MemoContent memoId={memo.id} content={memo.content} embeddedMemos={context.embeddedMemos} />
|
||||||
<MemoResourceListView resources={memo.resources} />
|
<MemoResourceListView resources={memo.resources} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Node } from "@/types/proto/api/v2/node";
|
import { Node } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
import { BaseProps } from "./types";
|
import { BaseProps } from "./types";
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { repeat } from "lodash-es";
|
import { repeat } from "lodash-es";
|
||||||
import { Node } from "@/types/proto/api/v2/node";
|
import { Node } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
import { BaseProps } from "./types";
|
import { BaseProps } from "./types";
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Node } from "@/types/proto/api/v2/node";
|
import { Node } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
import { BaseProps } from "./types";
|
import { BaseProps } from "./types";
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import {
|
|||||||
TaskListNode,
|
TaskListNode,
|
||||||
TextNode,
|
TextNode,
|
||||||
UnorderedListNode,
|
UnorderedListNode,
|
||||||
} from "@/types/proto/api/v2/node";
|
} from "@/types/node";
|
||||||
import Blockquote from "./Blockquote";
|
import Blockquote from "./Blockquote";
|
||||||
import Bold from "./Bold";
|
import Bold from "./Bold";
|
||||||
import BoldItalic from "./BoldItalic";
|
import BoldItalic from "./BoldItalic";
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { TableNode_Row } from "@/types/proto/api/v2/node";
|
import { TableNode_Row } from "@/types/node";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
header: string[];
|
header: string[];
|
||||||
|
@ -3,7 +3,7 @@ import classNames from "classnames";
|
|||||||
import { repeat } from "lodash-es";
|
import { repeat } from "lodash-es";
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import { useMemoStore } from "@/store/v1";
|
import { useMemoStore } from "@/store/v1";
|
||||||
import { Node, NodeType } from "@/types/proto/api/v2/node";
|
import { Node, NodeType } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
import { RendererContext } from "./types";
|
import { RendererContext } from "./types";
|
||||||
|
|
||||||
@ -35,12 +35,13 @@ const TaskList: React.FC<Props> = ({ index, indent, complete, children }: Props)
|
|||||||
}
|
}
|
||||||
|
|
||||||
node.taskListNode!.complete = on;
|
node.taskListNode!.complete = on;
|
||||||
|
const content = window.restore(context.nodes);
|
||||||
await memoStore.updateMemo(
|
await memoStore.updateMemo(
|
||||||
{
|
{
|
||||||
id: context.memoId,
|
id: context.memoId,
|
||||||
nodes: context.nodes,
|
content,
|
||||||
},
|
},
|
||||||
["nodes"],
|
["content"],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { repeat } from "lodash-es";
|
import { repeat } from "lodash-es";
|
||||||
import { Node } from "@/types/proto/api/v2/node";
|
import { Node } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { memo, useRef } from "react";
|
import { memo, useRef } from "react";
|
||||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||||
import { useMemoStore } from "@/store/v1";
|
import { useMemoStore } from "@/store/v1";
|
||||||
import { Node, NodeType } from "@/types/proto/api/v2/node";
|
import { Node, NodeType } from "@/types/node";
|
||||||
import Renderer from "./Renderer";
|
import Renderer from "./Renderer";
|
||||||
import { RendererContext } from "./types";
|
import { RendererContext } from "./types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
nodes: Node[];
|
content: string;
|
||||||
memoId?: number;
|
memoId?: number;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
disableFilter?: boolean;
|
disableFilter?: boolean;
|
||||||
@ -18,10 +18,11 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MemoContent: React.FC<Props> = (props: Props) => {
|
const MemoContent: React.FC<Props> = (props: Props) => {
|
||||||
const { className, memoId, nodes, embeddedMemos, onClick } = props;
|
const { className, content, memoId, embeddedMemos, onClick } = props;
|
||||||
const currentUser = useCurrentUser();
|
const currentUser = useCurrentUser();
|
||||||
const memoStore = useMemoStore();
|
const memoStore = useMemoStore();
|
||||||
const memoContentContainerRef = useRef<HTMLDivElement>(null);
|
const memoContentContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const nodes = window.parse(content);
|
||||||
const allowEdit = !props.readonly && memoId && currentUser?.id === memoStore.getMemoById(memoId)?.creatorId;
|
const allowEdit = !props.readonly && memoId && currentUser?.id === memoStore.getMemoById(memoId)?.creatorId;
|
||||||
|
|
||||||
const handleMemoContentClick = async (e: React.MouseEvent) => {
|
const handleMemoContentClick = async (e: React.MouseEvent) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createContext } from "react";
|
import { createContext } from "react";
|
||||||
import { Node } from "@/types/proto/api/v2/node";
|
import { Node } from "@/types/node";
|
||||||
|
|
||||||
interface Context {
|
interface Context {
|
||||||
nodes: Node[];
|
nodes: Node[];
|
||||||
|
@ -257,7 +257,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MemoContent memoId={memo.id} nodes={memo.nodes} readonly={readonly} onClick={handleMemoContentClick} />
|
<MemoContent memoId={memo.id} content={memo.content} readonly={readonly} onClick={handleMemoContentClick} />
|
||||||
<MemoResourceListView resources={memo.resources} />
|
<MemoResourceListView resources={memo.resources} />
|
||||||
<MemoRelationListView memo={memo} relationList={referenceRelations} />
|
<MemoRelationListView memo={memo} relationList={referenceRelations} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import { IconButton } from "@mui/joy";
|
import { IconButton } from "@mui/joy";
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { memoServiceClient } from "@/grpcweb";
|
|
||||||
import { Node } from "@/types/proto/api/v2/node";
|
|
||||||
import { generateDialog } from "./Dialog";
|
import { generateDialog } from "./Dialog";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import MemoContent from "./MemoContent";
|
import MemoContent from "./MemoContent";
|
||||||
@ -11,17 +8,6 @@ interface Props extends DialogProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PreviewMarkdownDialog: React.FC<Props> = ({ content, destroy }: Props) => {
|
const PreviewMarkdownDialog: React.FC<Props> = ({ content, destroy }: Props) => {
|
||||||
const [nodes, setNodes] = useState<Node[]>([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
const { nodes } = await memoServiceClient.previewMemoContent({
|
|
||||||
content,
|
|
||||||
});
|
|
||||||
setNodes(nodes);
|
|
||||||
})();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleCloseBtnClick = () => {
|
const handleCloseBtnClick = () => {
|
||||||
destroy();
|
destroy();
|
||||||
};
|
};
|
||||||
@ -37,7 +23,7 @@ const PreviewMarkdownDialog: React.FC<Props> = ({ content, destroy }: Props) =>
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-start items-start max-w-full w-[32rem]">
|
<div className="flex flex-col justify-start items-start max-w-full w-[32rem]">
|
||||||
{content !== "" ? <MemoContent nodes={nodes} /> : <p className="text-gray-400 dark:text-gray-600">Nothing to preview</p>}
|
{content !== "" ? <MemoContent content={content} /> : <p className="text-gray-400 dark:text-gray-600">Nothing to preview</p>}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -113,7 +113,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
|
|||||||
>
|
>
|
||||||
<span className="w-full px-6 pt-5 pb-2 text-sm text-gray-500">{getDateTimeString(memo.displayTime)}</span>
|
<span className="w-full px-6 pt-5 pb-2 text-sm text-gray-500">{getDateTimeString(memo.displayTime)}</span>
|
||||||
<div className="w-full px-6 text-base pb-4">
|
<div className="w-full px-6 text-base pb-4">
|
||||||
<MemoContent memoId={memo.id} nodes={memo.nodes} readonly={true} disableFilter />
|
<MemoContent memoId={memo.id} content={memo.content} readonly={true} disableFilter />
|
||||||
<MemoResourceListView resources={memo.resources} />
|
<MemoResourceListView resources={memo.resources} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row justify-between items-center w-full bg-gray-100 dark:bg-zinc-900 py-4 px-6">
|
<div className="flex flex-row justify-between items-center w-full bg-gray-100 dark:bg-zinc-900 py-4 px-6">
|
||||||
|
@ -125,7 +125,7 @@ const Archived = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MemoContent memoId={memo.id} nodes={memo.nodes} readonly={true} />
|
<MemoContent memoId={memo.id} content={memo.content} readonly={true} />
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
@ -137,7 +137,7 @@ const MemoDetail = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<MemoContent memoId={memo.id} nodes={memo.nodes} readonly={readonly} />
|
<MemoContent memoId={memo.id} content={memo.content} readonly={readonly} />
|
||||||
<MemoResourceListView resources={memo.resources} />
|
<MemoResourceListView resources={memo.resources} />
|
||||||
<MemoRelationListView memo={memo} relationList={referenceRelations} />
|
<MemoRelationListView memo={memo} relationList={referenceRelations} />
|
||||||
<div className="w-full mt-3 flex flex-row justify-between items-center gap-2">
|
<div className="w-full mt-3 flex flex-row justify-between items-center gap-2">
|
||||||
|
10
web/src/types/global.d.ts
vendored
Normal file
10
web/src/types/global.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Node } from "./node";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
parse: (content: string) => Node[];
|
||||||
|
restore: (input: Node[]) => string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
2328
web/src/types/node.ts
Normal file
2328
web/src/types/node.ts
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user