Commit fdb1779a authored by Steven's avatar Steven

chore: implement referenced content renderer

parent a316e239
......@@ -98,6 +98,8 @@ func convertFromASTNode(rawNode ast.Node) *apiv2pb.Node {
node.Node = &apiv2pb.Node_SubscriptNode{SubscriptNode: &apiv2pb.SubscriptNode{Content: n.Content}}
case *ast.Superscript:
node.Node = &apiv2pb.Node_SuperscriptNode{SuperscriptNode: &apiv2pb.SuperscriptNode{Content: n.Content}}
case *ast.ReferencedContent:
node.Node = &apiv2pb.Node_ReferencedContentNode{ReferencedContentNode: &apiv2pb.ReferencedContentNode{ResourceName: n.ResourceName, Params: n.Params}}
default:
node.Node = &apiv2pb.Node_TextNode{TextNode: &apiv2pb.TextNode{}}
}
......@@ -177,6 +179,8 @@ func convertToASTNode(node *apiv2pb.Node) ast.Node {
return &ast.Subscript{Content: n.SubscriptNode.Content}
case *apiv2pb.Node_SuperscriptNode:
return &ast.Superscript{Content: n.SuperscriptNode.Content}
case *apiv2pb.Node_ReferencedContentNode:
return &ast.ReferencedContent{ResourceName: n.ReferencedContentNode.ResourceName, Params: n.ReferencedContentNode.Params}
default:
return &ast.Text{}
}
......
......@@ -52,6 +52,7 @@ enum NodeType {
HIGHLIGHT = 25;
SUBSCRIPT = 26;
SUPERSCRIPT = 27;
REFERENCED_CONTENT = 28;
}
message Node {
......@@ -84,6 +85,7 @@ message Node {
HighlightNode highlight_node = 26;
SubscriptNode subscript_node = 27;
SuperscriptNode superscript_node = 28;
ReferencedContentNode referenced_content_node = 29;
}
}
......@@ -214,3 +216,8 @@ message SubscriptNode {
message SuperscriptNode {
string content = 1;
}
message ReferencedContentNode {
string resource_name = 1;
string params = 2;
}
......@@ -88,6 +88,7 @@
- [ParagraphNode](#memos-api-v2-ParagraphNode)
- [ParseMarkdownRequest](#memos-api-v2-ParseMarkdownRequest)
- [ParseMarkdownResponse](#memos-api-v2-ParseMarkdownResponse)
- [ReferencedContentNode](#memos-api-v2-ReferencedContentNode)
- [StrikethroughNode](#memos-api-v2-StrikethroughNode)
- [SubscriptNode](#memos-api-v2-SubscriptNode)
- [SuperscriptNode](#memos-api-v2-SuperscriptNode)
......@@ -1266,6 +1267,7 @@
| highlight_node | [HighlightNode](#memos-api-v2-HighlightNode) | | |
| subscript_node | [SubscriptNode](#memos-api-v2-SubscriptNode) | | |
| superscript_node | [SuperscriptNode](#memos-api-v2-SuperscriptNode) | | |
| referenced_content_node | [ReferencedContentNode](#memos-api-v2-ReferencedContentNode) | | |
......@@ -1334,6 +1336,22 @@
<a name="memos-api-v2-ReferencedContentNode"></a>
### ReferencedContentNode
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| resource_name | [string](#string) | | |
| params | [string](#string) | | |
<a name="memos-api-v2-StrikethroughNode"></a>
### StrikethroughNode
......@@ -1513,6 +1531,7 @@
| HIGHLIGHT | 25 | |
| SUBSCRIPT | 26 | |
| SUPERSCRIPT | 27 | |
| REFERENCED_CONTENT | 28 | |
......
This diff is collapsed.
interface Props {
message: string;
}
const Error = ({ message }: Props) => {
return <p className="font-mono text-sm text-red-600 dark:text-red-700">{message}</p>;
};
export default Error;
import { useContext, useEffect } from "react";
import useLoading from "@/hooks/useLoading";
import useNavigateTo from "@/hooks/useNavigateTo";
import { useMemoStore } from "@/store/v1";
import { RendererContext } from "../types";
import Error from "./Error";
interface Props {
resourceId: string;
params: string;
}
const ReferencedMemo = ({ resourceId }: Props) => {
const context = useContext(RendererContext);
const navigateTo = useNavigateTo();
const loadingState = useLoading();
const memoStore = useMemoStore();
const memo = memoStore.getMemoByName(resourceId);
const resourceName = `memos/${resourceId}`;
useEffect(() => {
memoStore.getOrFetchMemoByName(resourceId).finally(() => loadingState.setFinish());
}, [resourceId]);
if (loadingState.isLoading) {
return null;
}
if (!memo) {
return <Error message={`Memo not found: ${resourceId}`} />;
}
if (memo.id === context.memoId || context.embeddedMemos.has(resourceName)) {
return <Error message={`Nested Rendering Error: ![[${resourceName}]]`} />;
}
const displayContent = memo.content.length > 12 ? `${memo.content.slice(0, 12)}...` : memo.content;
const handleGotoMemoDetailPage = () => {
navigateTo(`/m/${memo.name}`);
};
// Add the memo to the set of embedded memos. This is used to prevent infinite loops when a memo embeds itself.
context.embeddedMemos.add(resourceName);
return (
<span
className="text-blue-600 whitespace-nowrap dark:text-blue-400 cursor-pointer underline break-all hover:opacity-80 decoration-1"
onClick={handleGotoMemoDetailPage}
>
{displayContent}
</span>
);
};
export default ReferencedMemo;
import Error from "./Error";
import ReferencedMemo from "./ReferencedMemo";
interface Props {
resourceName: string;
params: string;
}
const extractResourceTypeAndId = (resourceName: string) => {
const [resourceType, resourceId] = resourceName.split("/");
return { resourceType, resourceId };
};
const ReferencedContent = ({ resourceName, params }: Props) => {
const { resourceType, resourceId } = extractResourceTypeAndId(resourceName);
if (resourceType === "memos") {
return <ReferencedMemo resourceId={resourceId} params={params} />;
}
return <Error message={`Unknown resource: ${resourceName}`} />;
};
export default ReferencedContent;
......@@ -18,6 +18,7 @@ import {
NodeType,
OrderedListNode,
ParagraphNode,
ReferencedContentNode,
StrikethroughNode,
SubscriptNode,
SuperscriptNode,
......@@ -44,6 +45,7 @@ import Link from "./Link";
import Math from "./Math";
import OrderedList from "./OrderedList";
import Paragraph from "./Paragraph";
import ReferencedContent from "./ReferencedContent";
import Strikethrough from "./Strikethrough";
import Subscript from "./Subscript";
import Superscript from "./Superscript";
......@@ -114,6 +116,8 @@ const Renderer: React.FC<Props> = ({ index, node }: Props) => {
return <Subscript {...(node.subscriptNode as SubscriptNode)} />;
case NodeType.SUPERSCRIPT:
return <Superscript {...(node.superscriptNode as SuperscriptNode)} />;
case NodeType.REFERENCED_CONTENT:
return <ReferencedContent {...(node.referencedContentNode as ReferencedContentNode)} />;
default:
return null;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment