feat: implement table renderer

This commit is contained in:
Steven 2024-01-18 10:49:28 +08:00
parent aecffe3402
commit 05c0aeb789
6 changed files with 653 additions and 366 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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

View file

@ -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:

View 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;