mirror of
https://github.com/usememos/memos.git
synced 2025-03-15 18:20:09 +01:00
feat: implement table renderer
This commit is contained in:
parent
aecffe3402
commit
05c0aeb789
@ -63,6 +63,8 @@ func convertFromASTNode(rawNode ast.Node) *apiv2pb.Node {
|
||||
node.Node = &apiv2pb.Node_TaskListNode{TaskListNode: &apiv2pb.TaskListNode{Symbol: n.Symbol, Indent: int32(n.Indent), Complete: n.Complete, Children: children}}
|
||||
case *ast.MathBlock:
|
||||
node.Node = &apiv2pb.Node_MathBlockNode{MathBlockNode: &apiv2pb.MathBlockNode{Content: n.Content}}
|
||||
case *ast.Table:
|
||||
node.Node = &apiv2pb.Node_TableNode{TableNode: convertTableFromASTNode(n)}
|
||||
case *ast.Text:
|
||||
node.Node = &apiv2pb.Node_TextNode{TextNode: &apiv2pb.TextNode{Content: n.Content}}
|
||||
case *ast.Bold:
|
||||
@ -134,6 +136,8 @@ func convertToASTNode(node *apiv2pb.Node) ast.Node {
|
||||
return &ast.TaskList{Symbol: n.TaskListNode.Symbol, Indent: int(n.TaskListNode.Indent), Complete: n.TaskListNode.Complete, Children: children}
|
||||
case *apiv2pb.Node_MathBlockNode:
|
||||
return &ast.MathBlock{Content: n.MathBlockNode.Content}
|
||||
case *apiv2pb.Node_TableNode:
|
||||
return convertTableToASTNode(node)
|
||||
case *apiv2pb.Node_TextNode:
|
||||
return &ast.Text{Content: n.TextNode.Content}
|
||||
case *apiv2pb.Node_BoldNode:
|
||||
@ -166,6 +170,32 @@ func convertToASTNode(node *apiv2pb.Node) ast.Node {
|
||||
}
|
||||
}
|
||||
|
||||
func convertTableToASTNode(node *apiv2pb.Node) *ast.Table {
|
||||
table := &ast.Table{
|
||||
Header: node.GetTableNode().Header,
|
||||
}
|
||||
for _, d := range node.GetTableNode().Delimiter {
|
||||
table.Delimiter = append(table.Delimiter, int(d))
|
||||
}
|
||||
for _, row := range node.GetTableNode().Rows {
|
||||
table.Rows = append(table.Rows, row.Cells)
|
||||
}
|
||||
return table
|
||||
}
|
||||
|
||||
func convertTableFromASTNode(node *ast.Table) *apiv2pb.TableNode {
|
||||
table := &apiv2pb.TableNode{
|
||||
Header: node.Header,
|
||||
}
|
||||
for _, d := range node.Delimiter {
|
||||
table.Delimiter = append(table.Delimiter, int32(d))
|
||||
}
|
||||
for _, row := range node.Rows {
|
||||
table.Rows = append(table.Rows, &apiv2pb.TableNode_Row{Cells: row})
|
||||
}
|
||||
return table
|
||||
}
|
||||
|
||||
func traverseASTNodes(nodes []ast.Node, fn func(ast.Node)) {
|
||||
for _, node := range nodes {
|
||||
fn(node)
|
||||
|
@ -35,19 +35,20 @@ enum NodeType {
|
||||
UNORDERED_LIST = 8;
|
||||
TASK_LIST = 9;
|
||||
MATH_BLOCK = 10;
|
||||
TEXT = 11;
|
||||
BOLD = 12;
|
||||
ITALIC = 13;
|
||||
BOLD_ITALIC = 14;
|
||||
CODE = 15;
|
||||
IMAGE = 16;
|
||||
LINK = 17;
|
||||
AUTO_LINK = 18;
|
||||
TAG = 19;
|
||||
STRIKETHROUGH = 20;
|
||||
ESCAPING_CHARACTER = 21;
|
||||
MATH = 22;
|
||||
HIGHLIGHT = 23;
|
||||
TABLE = 11;
|
||||
TEXT = 12;
|
||||
BOLD = 13;
|
||||
ITALIC = 14;
|
||||
BOLD_ITALIC = 15;
|
||||
CODE = 16;
|
||||
IMAGE = 17;
|
||||
LINK = 18;
|
||||
AUTO_LINK = 19;
|
||||
TAG = 20;
|
||||
STRIKETHROUGH = 21;
|
||||
ESCAPING_CHARACTER = 22;
|
||||
MATH = 23;
|
||||
HIGHLIGHT = 24;
|
||||
}
|
||||
|
||||
message Node {
|
||||
@ -63,19 +64,20 @@ message Node {
|
||||
UnorderedListNode unordered_list_node = 9;
|
||||
TaskListNode task_list_node = 10;
|
||||
MathBlockNode math_block_node = 11;
|
||||
TextNode text_node = 12;
|
||||
BoldNode bold_node = 13;
|
||||
ItalicNode italic_node = 14;
|
||||
BoldItalicNode bold_italic_node = 15;
|
||||
CodeNode code_node = 16;
|
||||
ImageNode image_node = 17;
|
||||
LinkNode link_node = 18;
|
||||
AutoLinkNode auto_link_node = 19;
|
||||
TagNode tag_node = 20;
|
||||
StrikethroughNode strikethrough_node = 21;
|
||||
EscapingCharacterNode escaping_character_node = 22;
|
||||
MathNode math_node = 23;
|
||||
HighlightNode highlight_node = 24;
|
||||
TableNode table_node = 12;
|
||||
TextNode text_node = 13;
|
||||
BoldNode bold_node = 14;
|
||||
ItalicNode italic_node = 15;
|
||||
BoldItalicNode bold_italic_node = 16;
|
||||
CodeNode code_node = 17;
|
||||
ImageNode image_node = 18;
|
||||
LinkNode link_node = 19;
|
||||
AutoLinkNode auto_link_node = 20;
|
||||
TagNode tag_node = 21;
|
||||
StrikethroughNode strikethrough_node = 22;
|
||||
EscapingCharacterNode escaping_character_node = 23;
|
||||
MathNode math_node = 24;
|
||||
HighlightNode highlight_node = 25;
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,6 +128,16 @@ message MathBlockNode {
|
||||
string content = 1;
|
||||
}
|
||||
|
||||
message TableNode {
|
||||
repeated string header = 1;
|
||||
repeated int32 delimiter = 2;
|
||||
|
||||
message Row {
|
||||
repeated string cells = 1;
|
||||
}
|
||||
repeated Row rows = 3;
|
||||
}
|
||||
|
||||
message TextNode {
|
||||
string content = 1;
|
||||
}
|
||||
|
@ -88,6 +88,8 @@
|
||||
- [ParseMarkdownRequest](#memos-api-v2-ParseMarkdownRequest)
|
||||
- [ParseMarkdownResponse](#memos-api-v2-ParseMarkdownResponse)
|
||||
- [StrikethroughNode](#memos-api-v2-StrikethroughNode)
|
||||
- [TableNode](#memos-api-v2-TableNode)
|
||||
- [TableNode.Row](#memos-api-v2-TableNode-Row)
|
||||
- [TagNode](#memos-api-v2-TagNode)
|
||||
- [TaskListNode](#memos-api-v2-TaskListNode)
|
||||
- [TextNode](#memos-api-v2-TextNode)
|
||||
@ -1222,6 +1224,7 @@
|
||||
| unordered_list_node | [UnorderedListNode](#memos-api-v2-UnorderedListNode) | | |
|
||||
| task_list_node | [TaskListNode](#memos-api-v2-TaskListNode) | | |
|
||||
| math_block_node | [MathBlockNode](#memos-api-v2-MathBlockNode) | | |
|
||||
| table_node | [TableNode](#memos-api-v2-TableNode) | | |
|
||||
| text_node | [TextNode](#memos-api-v2-TextNode) | | |
|
||||
| bold_node | [BoldNode](#memos-api-v2-BoldNode) | | |
|
||||
| italic_node | [ItalicNode](#memos-api-v2-ItalicNode) | | |
|
||||
@ -1318,6 +1321,38 @@
|
||||
|
||||
|
||||
|
||||
<a name="memos-api-v2-TableNode"></a>
|
||||
|
||||
### TableNode
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| header | [string](#string) | repeated | |
|
||||
| delimiter | [int32](#int32) | repeated | |
|
||||
| rows | [TableNode.Row](#memos-api-v2-TableNode-Row) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="memos-api-v2-TableNode-Row"></a>
|
||||
|
||||
### TableNode.Row
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| cells | [string](#string) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="memos-api-v2-TagNode"></a>
|
||||
|
||||
### TagNode
|
||||
@ -1403,19 +1438,20 @@
|
||||
| UNORDERED_LIST | 8 | |
|
||||
| TASK_LIST | 9 | |
|
||||
| MATH_BLOCK | 10 | |
|
||||
| TEXT | 11 | |
|
||||
| BOLD | 12 | |
|
||||
| ITALIC | 13 | |
|
||||
| BOLD_ITALIC | 14 | |
|
||||
| CODE | 15 | |
|
||||
| IMAGE | 16 | |
|
||||
| LINK | 17 | |
|
||||
| AUTO_LINK | 18 | |
|
||||
| TAG | 19 | |
|
||||
| STRIKETHROUGH | 20 | |
|
||||
| ESCAPING_CHARACTER | 21 | |
|
||||
| MATH | 22 | |
|
||||
| HIGHLIGHT | 23 | |
|
||||
| TABLE | 11 | |
|
||||
| TEXT | 12 | |
|
||||
| BOLD | 13 | |
|
||||
| ITALIC | 14 | |
|
||||
| BOLD_ITALIC | 15 | |
|
||||
| CODE | 16 | |
|
||||
| IMAGE | 17 | |
|
||||
| LINK | 18 | |
|
||||
| AUTO_LINK | 19 | |
|
||||
| TAG | 20 | |
|
||||
| STRIKETHROUGH | 21 | |
|
||||
| ESCAPING_CHARACTER | 22 | |
|
||||
| MATH | 23 | |
|
||||
| HIGHLIGHT | 24 | |
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@ import {
|
||||
OrderedListNode,
|
||||
ParagraphNode,
|
||||
StrikethroughNode,
|
||||
TableNode,
|
||||
TagNode,
|
||||
TaskListNode,
|
||||
TextNode,
|
||||
@ -40,6 +41,7 @@ import Math from "./Math";
|
||||
import OrderedList from "./OrderedList";
|
||||
import Paragraph from "./Paragraph";
|
||||
import Strikethrough from "./Strikethrough";
|
||||
import Table from "./Table";
|
||||
import Tag from "./Tag";
|
||||
import TaskList from "./TaskList";
|
||||
import Text from "./Text";
|
||||
@ -72,6 +74,8 @@ const Renderer: React.FC<Props> = ({ index, node }: Props) => {
|
||||
return <TaskList index={index} {...(node.taskListNode as TaskListNode)} />;
|
||||
case NodeType.MATH_BLOCK:
|
||||
return <Math {...(node.mathBlockNode as MathNode)} block={true} />;
|
||||
case NodeType.TABLE:
|
||||
return <Table {...(node.tableNode as TableNode)} />;
|
||||
case NodeType.TEXT:
|
||||
return <Text {...(node.textNode as TextNode)} />;
|
||||
case NodeType.BOLD:
|
||||
|
35
web/src/components/MemoContent/Table.tsx
Normal file
35
web/src/components/MemoContent/Table.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { TableNode_Row } from "@/types/proto/api/v2/markdown_service";
|
||||
|
||||
interface Props {
|
||||
header: string[];
|
||||
rows: TableNode_Row[];
|
||||
}
|
||||
|
||||
const Table = ({ header, rows }: Props) => {
|
||||
return (
|
||||
<table className="w-auto max-w-full border border-gray-300 dark:border-zinc-600 divide-y divide-gray-300 dark:divide-zinc-600">
|
||||
<thead className="text-sm font-semibold leading-5 text-left text-gray-900 dark:text-gray-400">
|
||||
<tr className="divide-x divide-gray-300 dark:divide-zinc-600">
|
||||
{header.map((h, i) => (
|
||||
<th key={i} className="py-1 px-2">
|
||||
{h}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-300 dark:divide-zinc-600 text-sm leading-5 text-left text-gray-900 dark:text-gray-400">
|
||||
{rows.map((row, i) => (
|
||||
<tr key={i} className="divide-x divide-gray-300 dark:divide-zinc-600">
|
||||
{row.cells.map((r, j) => (
|
||||
<td key={j} className="py-1 px-2">
|
||||
{r}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
||||
|
||||
export default Table;
|
Loading…
x
Reference in New Issue
Block a user