feat: impl list renderer

This commit is contained in:
Steven 2024-09-17 19:03:10 +08:00
parent 759f7c6171
commit fbe0251eed
15 changed files with 1274 additions and 985 deletions

View file

@ -300,12 +300,16 @@ paths:
type: integer
format: int32
- name: pageToken
description: "A page token, received from a previous `ListMemos` call.\r\nProvide this to retrieve the subsequent page."
description: |-
A page token, received from a previous `ListMemos` call.
Provide this to retrieve the subsequent page.
in: query
required: false
type: string
- name: filter
description: "Filter is used to filter memos returned in the list.\r\nFormat: \"creator == 'users/{uid}' && visibilities == ['PUBLIC', 'PROTECTED']\""
description: |-
Filter is used to filter memos returned in the list.
Format: "creator == 'users/{uid}' && visibilities == ['PUBLIC', 'PROTECTED']"
in: query
required: false
type: string
@ -480,7 +484,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: filter
description: "Filter is used to filter users returned in the list.\r\nFormat: \"username == 'frank'\""
description: |-
Filter is used to filter users returned in the list.
Format: "username == 'frank'"
in: query
required: false
type: string
@ -641,7 +647,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The resource name of the workspace setting.\r\nFormat: settings/{setting}"
description: |-
The resource name of the workspace setting.
Format: settings/{setting}
in: path
required: true
type: string
@ -663,7 +671,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: setting.name
description: "name is the name of the setting.\r\nFormat: settings/{setting}"
description: |-
name is the name of the setting.
Format: settings/{setting}
in: path
required: true
type: string
@ -699,7 +709,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: identityProvider.name
description: "The name of the identityProvider.\r\nFormat: identityProviders/{id}"
description: |-
The name of the identityProvider.
Format: identityProviders/{id}
in: path
required: true
type: string
@ -737,7 +749,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: inbox.name
description: "The name of the inbox.\r\nFormat: inboxes/{id}"
description: |-
The name of the inbox.
Format: inboxes/{id}
in: path
required: true
type: string
@ -781,7 +795,10 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: memo.name
description: "The name of the memo.\r\nFormat: memos/{id}\r\nid is the system generated id."
description: |-
The name of the memo.
Format: memos/{id}
id is the system generated id.
in: path
required: true
type: string
@ -799,7 +816,9 @@ paths:
$ref: '#/definitions/v1RowStatus'
creator:
type: string
title: "The name of the creator.\r\nFormat: users/{id}"
title: |-
The name of the creator.
Format: users/{id}
createTime:
type: string
format: date-time
@ -852,7 +871,9 @@ paths:
readOnly: true
parent:
type: string
title: "The name of the parent memo.\r\nFormat: memos/{id}"
title: |-
The name of the parent memo.
Format: memos/{id}
readOnly: true
snippet:
type: string
@ -874,7 +895,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_1
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -896,7 +919,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_1
description: "The name of the identityProvider to delete.\r\nFormat: identityProviders/{id}"
description: |-
The name of the identityProvider to delete.
Format: identityProviders/{id}
in: path
required: true
type: string
@ -918,7 +943,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_2
description: "The name of the identityProvider to get.\r\nFormat: identityProviders/{id}"
description: |-
The name of the identityProvider to get.
Format: identityProviders/{id}
in: path
required: true
type: string
@ -940,7 +967,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_2
description: "The name of the inbox to delete.\r\nFormat: inboxes/{id}"
description: |-
The name of the inbox to delete.
Format: inboxes/{id}
in: path
required: true
type: string
@ -962,7 +991,10 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_3
description: "The name of the resource.\r\nFormat: resources/{id}\r\nid is the system generated unique identifier."
description: |-
The name of the resource.
Format: resources/{id}
id is the system generated unique identifier.
in: path
required: true
type: string
@ -984,7 +1016,10 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_3
description: "The name of the resource.\r\nFormat: resources/{id}\r\nid is the system generated unique identifier."
description: |-
The name of the resource.
Format: resources/{id}
id is the system generated unique identifier.
in: path
required: true
type: string
@ -1006,7 +1041,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_4
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1028,7 +1065,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name_4
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1050,7 +1089,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the activity.\r\nFormat: activities/{id}"
description: |-
The name of the activity.
Format: activities/{id}
in: path
required: true
type: string
@ -1072,7 +1113,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1094,7 +1137,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1115,7 +1160,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1143,7 +1190,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1170,7 +1219,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1191,7 +1242,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1218,7 +1271,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}. Use \"memos/-\" to list all properties."
description: |-
The name of the memo.
Format: memos/{id}. Use "memos/-" to list all properties.
in: path
required: true
type: string
@ -1241,7 +1296,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}. Use \"memos/-\" to rebuild all memos."
description: |-
The name of the memo.
Format: memos/{id}. Use "memos/-" to rebuild all memos.
in: path
required: true
type: string
@ -1268,7 +1325,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1289,7 +1348,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1316,7 +1377,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1338,7 +1401,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1365,7 +1430,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1387,7 +1454,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the memo.\r\nFormat: memos/{id}"
description: |-
The name of the memo.
Format: memos/{id}
in: path
required: true
type: string
@ -1414,7 +1483,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1436,13 +1507,17 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: parent
description: "The parent, who owns the tags.\r\nFormat: memos/{id}. Use \"memos/-\" to list all tags."
description: |-
The parent, who owns the tags.
Format: memos/{id}. Use "memos/-" to list all tags.
in: path
required: true
type: string
pattern: memos/[^/]+
- name: filter
description: "Filter is used to filter memos.\r\nFormat: \"creator == 'users/{uid}' && visibilities == ['PUBLIC', 'PROTECTED']\""
description: |-
Filter is used to filter memos.
Format: "creator == 'users/{uid}' && visibilities == ['PUBLIC', 'PROTECTED']"
in: query
required: false
type: string
@ -1464,7 +1539,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: parent
description: "The parent, who owns the tags.\r\nFormat: memos/{id}. Use \"memos/-\" to delete all tags."
description: |-
The parent, who owns the tags.
Format: memos/{id}. Use "memos/-" to delete all tags.
in: path
required: true
type: string
@ -1495,7 +1572,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: parent
description: "The parent, who owns the tags.\r\nFormat: memos/{id}. Use \"memos/-\" to rename all tags."
description: |-
The parent, who owns the tags.
Format: memos/{id}. Use "memos/-" to rename all tags.
in: path
required: true
type: string
@ -1522,7 +1601,10 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: resource.name
description: "The name of the resource.\r\nFormat: resources/{id}\r\nid is the system generated unique identifier."
description: |-
The name of the resource.
Format: resources/{id}
id is the system generated unique identifier.
in: path
required: true
type: string
@ -1554,7 +1636,9 @@ paths:
format: int64
memo:
type: string
title: "The related memo.\r\nFormat: memos/{id}"
title: |-
The related memo.
Format: memos/{id}
tags:
- ResourceService
/api/v1/{setting.name}:
@ -1572,7 +1656,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: setting.name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1609,7 +1695,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: user.name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1663,7 +1751,9 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the user.\r\nFormat: users/{id}"
description: |-
The name of the user.
Format: users/{id}
in: path
required: true
type: string
@ -1696,7 +1786,10 @@ paths:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: name
description: "The name of the resource.\r\nFormat: resources/{id}\r\nid is the system generated unique identifier."
description: |-
The name of the resource.
Format: resources/{id}
id is the system generated unique identifier.
in: path
required: true
type: string
@ -1883,7 +1976,9 @@ definitions:
properties:
name:
type: string
title: "The name of the identityProvider.\r\nFormat: identityProviders/{id}"
title: |-
The name of the identityProvider.
Format: identityProviders/{id}
type:
$ref: '#/definitions/apiv1IdentityProviderType'
title:
@ -1927,7 +2022,9 @@ definitions:
properties:
name:
type: string
title: "The name of the user.\r\nFormat: users/{id}"
title: |-
The name of the user.
Format: users/{id}
locale:
type: string
description: The preferred locale of the user.
@ -1971,7 +2068,10 @@ definitions:
weekStartDayOffset:
type: integer
format: int32
description: "week_start_day_offset is the week start day offset from Sunday.\r\n0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday\r\nDefault is Sunday."
description: |-
week_start_day_offset is the week start day offset from Sunday.
0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday
Default is Sunday.
disallowChangeUsername:
type: boolean
description: disallow_change_username disallows changing username.
@ -2008,7 +2108,9 @@ definitions:
properties:
name:
type: string
title: "name is the name of the setting.\r\nFormat: settings/{setting}"
title: |-
name is the name of the setting.
Format: settings/{setting}
generalSetting:
$ref: '#/definitions/apiv1WorkspaceGeneralSetting'
storageSetting:
@ -2023,7 +2125,9 @@ definitions:
description: storage_type is the storage type.
filepathTemplate:
type: string
title: "The template of file path.\r\ne.g. assets/{timestamp}_{filename}"
title: |-
The template of file path.
e.g. assets/{timestamp}_{filename}
uploadSizeLimitMb:
type: string
format: int64
@ -2182,7 +2286,9 @@ definitions:
properties:
name:
type: string
title: "The name of the activity.\r\nFormat: activities/{id}"
title: |-
The name of the activity.
Format: activities/{id}
creatorId:
type: integer
format: int32
@ -2313,7 +2419,9 @@ definitions:
properties:
name:
type: string
title: "The name of the inbox.\r\nFormat: inboxes/{id}"
title: |-
The name of the inbox.
Format: inboxes/{id}
sender:
type: string
title: 'Format: users/{id}'
@ -2433,7 +2541,10 @@ definitions:
additionalProperties:
type: integer
format: int32
description: "tag_amounts is the amount of tags.\r\nkey is the tag name. e.g. \"tag1\".\r\nvalue is the amount of the tag."
description: |-
tag_amounts is the amount of tags.
key is the tag name. e.g. "tag1".
value is the amount of the tag.
v1ListMemosResponse:
type: object
properties:
@ -2444,7 +2555,17 @@ definitions:
$ref: '#/definitions/v1Memo'
nextPageToken:
type: string
description: "A token, which can be sent as `page_token` to retrieve the next page.\r\nIf this field is omitted, there are no subsequent pages."
description: |-
A token, which can be sent as `page_token` to retrieve the next page.
If this field is omitted, there are no subsequent pages.
v1ListNode:
type: object
properties:
children:
type: array
items:
type: object
$ref: '#/definitions/v1Node'
v1ListResourcesResponse:
type: object
properties:
@ -2492,7 +2613,10 @@ definitions:
properties:
name:
type: string
description: "The name of the memo.\r\nFormat: memos/{id}\r\nid is the system generated id."
description: |-
The name of the memo.
Format: memos/{id}
id is the system generated id.
uid:
type: string
description: The user defined id of the memo.
@ -2500,7 +2624,9 @@ definitions:
$ref: '#/definitions/v1RowStatus'
creator:
type: string
title: "The name of the creator.\r\nFormat: users/{id}"
title: |-
The name of the creator.
Format: users/{id}
createTime:
type: string
format: date-time
@ -2553,7 +2679,9 @@ definitions:
readOnly: true
parent:
type: string
title: "The name of the parent memo.\r\nFormat: memos/{id}"
title: |-
The name of the parent memo.
Format: memos/{id}
readOnly: true
snippet:
type: string
@ -2578,7 +2706,9 @@ definitions:
properties:
name:
type: string
title: "The name of the memo property.\r\nFormat: memos/{id}/properties/{property_id}"
title: |-
The name of the memo property.
Format: memos/{id}/properties/{property_id}
property:
$ref: '#/definitions/v1MemoProperty'
readOnly: true
@ -2591,10 +2721,14 @@ definitions:
properties:
memo:
type: string
title: "The name of memo.\r\nFormat: \"memos/{uid}\""
title: |-
The name of memo.
Format: "memos/{uid}"
relatedMemo:
type: string
title: "The name of related memo.\r\nFormat: \"memos/{uid}\""
title: |-
The name of related memo.
Format: "memos/{uid}"
type:
$ref: '#/definitions/v1MemoRelationType'
v1MemoRelationType:
@ -2611,6 +2745,7 @@ definitions:
$ref: '#/definitions/v1NodeType'
lineBreakNode:
$ref: '#/definitions/v1LineBreakNode'
description: Block nodes.
paragraphNode:
$ref: '#/definitions/v1ParagraphNode'
codeBlockNode:
@ -2621,12 +2756,14 @@ definitions:
$ref: '#/definitions/v1HorizontalRuleNode'
blockquoteNode:
$ref: '#/definitions/v1BlockquoteNode'
orderedListNode:
$ref: '#/definitions/v1OrderedListNode'
unorderedListNode:
$ref: '#/definitions/v1UnorderedListNode'
taskListNode:
$ref: '#/definitions/v1TaskListNode'
listNode:
$ref: '#/definitions/v1ListNode'
orderedListItemNode:
$ref: '#/definitions/v1OrderedListItemNode'
unorderedListItemNode:
$ref: '#/definitions/v1UnorderedListItemNode'
taskListItemNode:
$ref: '#/definitions/v1TaskListItemNode'
mathBlockNode:
$ref: '#/definitions/v1MathBlockNode'
tableNode:
@ -2635,6 +2772,7 @@ definitions:
$ref: '#/definitions/v1EmbeddedContentNode'
textNode:
$ref: '#/definitions/v1TextNode'
description: Inline nodes.
boldNode:
$ref: '#/definitions/v1BoldNode'
italicNode:
@ -2679,9 +2817,10 @@ definitions:
- HEADING
- HORIZONTAL_RULE
- BLOCKQUOTE
- ORDERED_LIST
- UNORDERED_LIST
- TASK_LIST
- LIST
- ORDERED_LIST_ITEM
- UNORDERED_LIST_ITEM
- TASK_LIST_ITEM
- MATH_BLOCK
- TABLE
- EMBEDDED_CONTENT
@ -2704,7 +2843,10 @@ definitions:
- SPOILER
- HTML_ELEMENT
default: NODE_UNSPECIFIED
v1OrderedListNode:
description: |2-
- LINE_BREAK: Block nodes.
- TEXT: Inline nodes.
v1OrderedListItemNode:
type: object
properties:
number:
@ -2746,7 +2888,9 @@ definitions:
format: int32
creator:
type: string
title: "The name of the creator.\r\nFormat: users/{id}"
title: |-
The name of the creator.
Format: users/{id}
contentId:
type: string
reactionType:
@ -2780,7 +2924,10 @@ definitions:
properties:
name:
type: string
description: "The name of the resource.\r\nFormat: resources/{id}\r\nid is the system generated unique identifier."
description: |-
The name of the resource.
Format: resources/{id}
id is the system generated unique identifier.
uid:
type: string
description: The user defined id of the resource.
@ -2802,7 +2949,9 @@ definitions:
format: int64
memo:
type: string
title: "The related memo.\r\nFormat: memos/{id}"
title: |-
The related memo.
Format: memos/{id}
v1RestoreMarkdownNodesRequest:
type: object
properties:
@ -2886,7 +3035,7 @@ definitions:
properties:
content:
type: string
v1TaskListNode:
v1TaskListItemNode:
type: object
properties:
symbol:
@ -2906,7 +3055,7 @@ definitions:
properties:
content:
type: string
v1UnorderedListNode:
v1UnorderedListItemNode:
type: object
properties:
symbol:
@ -2924,7 +3073,9 @@ definitions:
properties:
name:
type: string
title: "The name of the user.\r\nFormat: users/{id}"
title: |-
The name of the user.
Format: users/{id}
id:
type: integer
format: int32
@ -2998,7 +3149,9 @@ definitions:
properties:
owner:
type: string
title: "The name of instance owner.\r\nFormat: \"users/{id}\""
title: |-
The name of instance owner.
Format: "users/{id}"
version:
type: string
title: version is the current version of instance

2
go.mod
View file

@ -25,7 +25,7 @@ require (
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
github.com/usememos/gomark v0.0.0-20240714122951-35ed01b21822
github.com/usememos/gomark v0.0.0-20240917110103-3ccacc410d19
golang.org/x/crypto v0.25.0
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8
golang.org/x/mod v0.20.0

4
go.sum
View file

@ -439,8 +439,8 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/usememos/gomark v0.0.0-20240714122951-35ed01b21822 h1:4DQs0DJGaXLq+1eP6QfMkvcunyTVJ5OR7LK1cOm2imE=
github.com/usememos/gomark v0.0.0-20240714122951-35ed01b21822/go.mod h1:7CZRoYFQyyljzplOTeyODFR26O+wr0BbnpTWVLGfKJA=
github.com/usememos/gomark v0.0.0-20240917110103-3ccacc410d19 h1:LFNLNBuUxqyYqh8yZrPyuk0n72rRGHqGWfoGBmoysMk=
github.com/usememos/gomark v0.0.0-20240917110103-3ccacc410d19/go.mod h1:7CZRoYFQyyljzplOTeyODFR26O+wr0BbnpTWVLGfKJA=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=

View file

@ -70,71 +70,81 @@ message LinkMetadata {
enum NodeType {
NODE_UNSPECIFIED = 0;
// Block nodes.
LINE_BREAK = 1;
PARAGRAPH = 2;
CODE_BLOCK = 3;
HEADING = 4;
HORIZONTAL_RULE = 5;
BLOCKQUOTE = 6;
ORDERED_LIST = 7;
UNORDERED_LIST = 8;
TASK_LIST = 9;
MATH_BLOCK = 10;
TABLE = 11;
EMBEDDED_CONTENT = 12;
TEXT = 13;
BOLD = 14;
ITALIC = 15;
BOLD_ITALIC = 16;
CODE = 17;
IMAGE = 18;
LINK = 19;
AUTO_LINK = 20;
TAG = 21;
STRIKETHROUGH = 22;
ESCAPING_CHARACTER = 23;
MATH = 24;
HIGHLIGHT = 25;
SUBSCRIPT = 26;
SUPERSCRIPT = 27;
REFERENCED_CONTENT = 28;
SPOILER = 29;
HTML_ELEMENT = 30;
LIST = 7;
ORDERED_LIST_ITEM = 8;
UNORDERED_LIST_ITEM = 9;
TASK_LIST_ITEM = 10;
MATH_BLOCK = 11;
TABLE = 12;
EMBEDDED_CONTENT = 13;
// Inline nodes.
TEXT = 51;
BOLD = 52;
ITALIC = 53;
BOLD_ITALIC = 54;
CODE = 55;
IMAGE = 56;
LINK = 57;
AUTO_LINK = 58;
TAG = 59;
STRIKETHROUGH = 60;
ESCAPING_CHARACTER = 61;
MATH = 62;
HIGHLIGHT = 63;
SUBSCRIPT = 64;
SUPERSCRIPT = 65;
REFERENCED_CONTENT = 66;
SPOILER = 67;
HTML_ELEMENT = 68;
}
message Node {
NodeType type = 1;
oneof node {
LineBreakNode line_break_node = 2;
ParagraphNode paragraph_node = 3;
CodeBlockNode code_block_node = 4;
HeadingNode heading_node = 5;
HorizontalRuleNode horizontal_rule_node = 6;
BlockquoteNode blockquote_node = 7;
OrderedListNode ordered_list_node = 8;
UnorderedListNode unordered_list_node = 9;
TaskListNode task_list_node = 10;
MathBlockNode math_block_node = 11;
TableNode table_node = 12;
EmbeddedContentNode embedded_content_node = 13;
TextNode text_node = 14;
BoldNode bold_node = 15;
ItalicNode italic_node = 16;
BoldItalicNode bold_italic_node = 17;
CodeNode code_node = 18;
ImageNode image_node = 19;
LinkNode link_node = 20;
AutoLinkNode auto_link_node = 21;
TagNode tag_node = 22;
StrikethroughNode strikethrough_node = 23;
EscapingCharacterNode escaping_character_node = 24;
MathNode math_node = 25;
HighlightNode highlight_node = 26;
SubscriptNode subscript_node = 27;
SuperscriptNode superscript_node = 28;
ReferencedContentNode referenced_content_node = 29;
SpoilerNode spoiler_node = 30;
HTMLElementNode html_element_node = 31;
// Block nodes.
LineBreakNode line_break_node = 11;
ParagraphNode paragraph_node = 12;
CodeBlockNode code_block_node = 13;
HeadingNode heading_node = 14;
HorizontalRuleNode horizontal_rule_node = 15;
BlockquoteNode blockquote_node = 16;
ListNode list_node = 17;
OrderedListItemNode ordered_list_item_node = 18;
UnorderedListItemNode unordered_list_item_node = 19;
TaskListItemNode task_list_item_node = 20;
MathBlockNode math_block_node = 21;
TableNode table_node = 22;
EmbeddedContentNode embedded_content_node = 23;
// Inline nodes.
TextNode text_node = 51;
BoldNode bold_node = 52;
ItalicNode italic_node = 53;
BoldItalicNode bold_italic_node = 54;
CodeNode code_node = 55;
ImageNode image_node = 56;
LinkNode link_node = 57;
AutoLinkNode auto_link_node = 58;
TagNode tag_node = 59;
StrikethroughNode strikethrough_node = 60;
EscapingCharacterNode escaping_character_node = 61;
MathNode math_node = 62;
HighlightNode highlight_node = 63;
SubscriptNode subscript_node = 64;
SuperscriptNode superscript_node = 65;
ReferencedContentNode referenced_content_node = 66;
SpoilerNode spoiler_node = 67;
HTMLElementNode html_element_node = 68;
}
}
@ -162,19 +172,23 @@ message BlockquoteNode {
repeated Node children = 1;
}
message OrderedListNode {
message ListNode {
repeated Node children = 1;
}
message OrderedListItemNode {
string number = 1;
int32 indent = 2;
repeated Node children = 3;
}
message UnorderedListNode {
message UnorderedListItemNode {
string symbol = 1;
int32 indent = 2;
repeated Node children = 3;
}
message TaskListNode {
message TaskListItemNode {
string symbol = 1;
int32 indent = 2;
bool complete = 3;

File diff suppressed because it is too large Load diff

View file

@ -75,15 +75,18 @@ func convertFromASTNode(rawNode ast.Node) *v1pb.Node {
case *ast.Blockquote:
children := convertFromASTNodes(n.Children)
node.Node = &v1pb.Node_BlockquoteNode{BlockquoteNode: &v1pb.BlockquoteNode{Children: children}}
case *ast.OrderedList:
case *ast.List:
children := convertFromASTNodes(n.Children)
node.Node = &v1pb.Node_OrderedListNode{OrderedListNode: &v1pb.OrderedListNode{Number: n.Number, Indent: int32(n.Indent), Children: children}}
case *ast.UnorderedList:
node.Node = &v1pb.Node_ListNode{ListNode: &v1pb.ListNode{Children: children}}
case *ast.OrderedListItem:
children := convertFromASTNodes(n.Children)
node.Node = &v1pb.Node_UnorderedListNode{UnorderedListNode: &v1pb.UnorderedListNode{Symbol: n.Symbol, Indent: int32(n.Indent), Children: children}}
case *ast.TaskList:
node.Node = &v1pb.Node_OrderedListItemNode{OrderedListItemNode: &v1pb.OrderedListItemNode{Number: n.Number, Indent: int32(n.Indent), Children: children}}
case *ast.UnorderedListItem:
children := convertFromASTNodes(n.Children)
node.Node = &v1pb.Node_TaskListNode{TaskListNode: &v1pb.TaskListNode{Symbol: n.Symbol, Indent: int32(n.Indent), Complete: n.Complete, Children: children}}
node.Node = &v1pb.Node_UnorderedListItemNode{UnorderedListItemNode: &v1pb.UnorderedListItemNode{Symbol: n.Symbol, Indent: int32(n.Indent), Children: children}}
case *ast.TaskListItem:
children := convertFromASTNodes(n.Children)
node.Node = &v1pb.Node_TaskListItemNode{TaskListItemNode: &v1pb.TaskListItemNode{Symbol: n.Symbol, Indent: int32(n.Indent), Complete: n.Complete, Children: children}}
case *ast.MathBlock:
node.Node = &v1pb.Node_MathBlockNode{MathBlockNode: &v1pb.MathBlockNode{Content: n.Content}}
case *ast.Table:
@ -170,15 +173,18 @@ func convertToASTNode(node *v1pb.Node) ast.Node {
case *v1pb.Node_BlockquoteNode:
children := convertToASTNodes(n.BlockquoteNode.Children)
return &ast.Blockquote{Children: children}
case *v1pb.Node_OrderedListNode:
children := convertToASTNodes(n.OrderedListNode.Children)
return &ast.OrderedList{Number: n.OrderedListNode.Number, Indent: int(n.OrderedListNode.Indent), Children: children}
case *v1pb.Node_UnorderedListNode:
children := convertToASTNodes(n.UnorderedListNode.Children)
return &ast.UnorderedList{Symbol: n.UnorderedListNode.Symbol, Indent: int(n.UnorderedListNode.Indent), Children: children}
case *v1pb.Node_TaskListNode:
children := convertToASTNodes(n.TaskListNode.Children)
return &ast.TaskList{Symbol: n.TaskListNode.Symbol, Indent: int(n.TaskListNode.Indent), Complete: n.TaskListNode.Complete, Children: children}
case *v1pb.Node_ListNode:
children := convertToASTNodes(n.ListNode.Children)
return &ast.List{Children: children}
case *v1pb.Node_OrderedListItemNode:
children := convertToASTNodes(n.OrderedListItemNode.Children)
return &ast.OrderedListItem{Number: n.OrderedListItemNode.Number, Indent: int(n.OrderedListItemNode.Indent), Children: children}
case *v1pb.Node_UnorderedListItemNode:
children := convertToASTNodes(n.UnorderedListItemNode.Children)
return &ast.UnorderedListItem{Symbol: n.UnorderedListItemNode.Symbol, Indent: int(n.UnorderedListItemNode.Indent), Children: children}
case *v1pb.Node_TaskListItemNode:
children := convertToASTNodes(n.TaskListItemNode.Children)
return &ast.TaskListItem{Symbol: n.TaskListItemNode.Symbol, Indent: int(n.TaskListItemNode.Indent), Complete: n.TaskListItemNode.Complete, Children: children}
case *v1pb.Node_MathBlockNode:
return &ast.MathBlock{Content: n.MathBlockNode.Content}
case *v1pb.Node_TableNode:

View file

@ -86,7 +86,7 @@ func GetMemoPropertyFromContent(content string) (*storepb.MemoPayload_Property,
}
case *ast.Link, *ast.AutoLink:
property.HasLink = true
case *ast.TaskList:
case *ast.TaskListItem:
property.HasTaskList = true
if !n.Complete {
property.HasIncompleteTasks = true
@ -108,11 +108,13 @@ func TraverseASTNodes(nodes []ast.Node, fn func(ast.Node)) {
TraverseASTNodes(n.Children, fn)
case *ast.Blockquote:
TraverseASTNodes(n.Children, fn)
case *ast.OrderedList:
case *ast.List:
TraverseASTNodes(n.Children, fn)
case *ast.UnorderedList:
case *ast.OrderedListItem:
TraverseASTNodes(n.Children, fn)
case *ast.TaskList:
case *ast.UnorderedListItem:
TraverseASTNodes(n.Children, fn)
case *ast.TaskListItem:
TraverseASTNodes(n.Children, fn)
case *ast.Bold:
TraverseASTNodes(n.Children, fn)

View file

@ -0,0 +1,29 @@
import { Node, NodeType } from "@/types/proto/api/v1/markdown_service";
import Renderer from "./Renderer";
interface Props {
index: string;
children: Node[];
}
const List: React.FC<Props> = ({ children }: Props) => {
let prevNode: Node | null = null;
let skipNextLineBreakFlag = false;
return (
<dl>
{children.map((child, index) => {
if (prevNode?.type !== NodeType.LINE_BREAK && child.type === NodeType.LINE_BREAK && skipNextLineBreakFlag) {
skipNextLineBreakFlag = false;
return null;
}
prevNode = child;
skipNextLineBreakFlag = true;
return <Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />;
})}
</dl>
);
};
export default List;

View file

@ -1,36 +0,0 @@
import { repeat } from "lodash-es";
import { Node } from "@/types/proto/api/v1/markdown_service";
import Renderer from "./Renderer";
import { BaseProps } from "./types";
interface Props extends BaseProps {
number: string;
indent: number;
children: Node[];
}
const OrderedList: React.FC<Props> = ({ number, indent, children }: Props) => {
return (
<ol>
<li className="w-full flex flex-row">
{indent > 0 && (
<div className="block font-mono shrink-0">
<span>{repeat(" ", indent)}</span>
</div>
)}
<div className="w-auto grid grid-cols-[24px_1fr] gap-1">
<div className="w-7 h-6 flex justify-center items-center">
<span className="opacity-80">{number}.</span>
</div>
<div>
{children.map((child, index) => (
<Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />
))}
</div>
</div>
</li>
</ol>
);
};
export default OrderedList;

View file

@ -0,0 +1,34 @@
import { repeat } from "lodash-es";
import { Node } from "@/types/proto/api/v1/markdown_service";
import Renderer from "./Renderer";
import { BaseProps } from "./types";
interface Props extends BaseProps {
number: string;
indent: number;
children: Node[];
}
const OrderedListItem: React.FC<Props> = ({ number, indent, children }: Props) => {
return (
<li className="w-full flex flex-row">
{indent > 0 && (
<div className="block font-mono shrink-0">
<span>{repeat(" ", indent)}</span>
</div>
)}
<div className="w-auto grid grid-cols-[24px_1fr] gap-1">
<div className="w-7 h-6 flex justify-center items-center">
<span className="opacity-80">{number}.</span>
</div>
<div>
{children.map((child, index) => (
<Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />
))}
</div>
</div>
</li>
);
};
export default OrderedListItem;

View file

@ -14,11 +14,12 @@ import {
ImageNode,
ItalicNode,
LinkNode,
ListNode,
MathBlockNode,
MathNode,
Node,
NodeType,
OrderedListNode,
OrderedListItemNode,
ParagraphNode,
ReferencedContentNode,
SpoilerNode,
@ -27,9 +28,9 @@ import {
SuperscriptNode,
TableNode,
TagNode,
TaskListNode,
TaskListItemNode,
TextNode,
UnorderedListNode,
UnorderedListItemNode,
} from "@/types/proto/api/v1/markdown_service";
import Blockquote from "./Blockquote";
import Bold from "./Bold";
@ -46,8 +47,9 @@ import Image from "./Image";
import Italic from "./Italic";
import LineBreak from "./LineBreak";
import Link from "./Link";
import List from "./List";
import Math from "./Math";
import OrderedList from "./OrderedList";
import OrderedListItem from "./OrderedListItem";
import Paragraph from "./Paragraph";
import ReferencedContent from "./ReferencedContent";
import Spoiler from "./Spoiler";
@ -56,9 +58,9 @@ import Subscript from "./Subscript";
import Superscript from "./Superscript";
import Table from "./Table";
import Tag from "./Tag";
import TaskList from "./TaskList";
import TaskListItem from "./TaskListItem";
import Text from "./Text";
import UnorderedList from "./UnorderedList";
import UnorderedListItem from "./UnorderedListItem";
interface Props {
index: string;
@ -79,12 +81,14 @@ const Renderer: React.FC<Props> = ({ index, node }: Props) => {
return <HorizontalRule index={index} {...(node.horizontalRuleNode as HorizontalRuleNode)} />;
case NodeType.BLOCKQUOTE:
return <Blockquote index={index} {...(node.blockquoteNode as BlockquoteNode)} />;
case NodeType.ORDERED_LIST:
return <OrderedList index={index} {...(node.orderedListNode as OrderedListNode)} />;
case NodeType.UNORDERED_LIST:
return <UnorderedList {...(node.unorderedListNode as UnorderedListNode)} />;
case NodeType.TASK_LIST:
return <TaskList index={index} {...(node.taskListNode as TaskListNode)} />;
case NodeType.LIST:
return <List index={index} {...(node.listNode as ListNode)} />;
case NodeType.ORDERED_LIST_ITEM:
return <OrderedListItem index={index} {...(node.orderedListItemNode as OrderedListItemNode)} />;
case NodeType.UNORDERED_LIST_ITEM:
return <UnorderedListItem {...(node.unorderedListItemNode as UnorderedListItemNode)} />;
case NodeType.TASK_LIST_ITEM:
return <TaskListItem index={index} node={node} {...(node.taskListItemNode as TaskListItemNode)} />;
case NodeType.MATH_BLOCK:
return <Math {...(node.mathBlockNode as MathBlockNode)} block={true} />;
case NodeType.TABLE:

View file

@ -1,73 +0,0 @@
import { Checkbox } from "@mui/joy";
import clsx from "clsx";
import { repeat } from "lodash-es";
import { useContext, useState } from "react";
import { markdownServiceClient } from "@/grpcweb";
import { useMemoStore } from "@/store/v1";
import { Node, NodeType, TaskListNode } from "@/types/proto/api/v1/markdown_service";
import Renderer from "./Renderer";
import { RendererContext } from "./types";
interface Props {
index: string;
symbol: string;
indent: number;
complete: boolean;
children: Node[];
}
const TaskList: React.FC<Props> = ({ index, indent, complete, children }: Props) => {
const context = useContext(RendererContext);
const memoStore = useMemoStore();
const [checked] = useState(complete);
const handleCheckboxChange = async (on: boolean) => {
if (context.readonly || !context.memoName) {
return;
}
const nodeIndex = Number(index);
if (isNaN(nodeIndex)) {
return;
}
const node = context.nodes[nodeIndex];
if (node.type !== NodeType.TASK_LIST) {
return;
}
(node.taskListNode as TaskListNode)!.complete = on;
const { markdown } = await markdownServiceClient.restoreMarkdownNodes({ nodes: context.nodes });
await memoStore.updateMemo(
{
name: context.memoName,
content: markdown,
},
["content"],
);
};
return (
<ul>
<li className="w-full flex flex-row">
{indent > 0 && (
<div className="block font-mono shrink-0">
<span>{repeat(" ", indent)}</span>
</div>
)}
<div className="w-auto grid grid-cols-[24px_1fr] gap-1">
<div className="w-7 h-6 flex justify-center items-center">
<Checkbox size="sm" checked={checked} disabled={context.readonly} onChange={(e) => handleCheckboxChange(e.target.checked)} />
</div>
<div className={clsx(complete && "line-through opacity-80")}>
{children.map((child, index) => (
<Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />
))}
</div>
</div>
</li>
</ul>
);
};
export default TaskList;

View file

@ -0,0 +1,62 @@
import { Checkbox } from "@mui/joy";
import clsx from "clsx";
import { repeat } from "lodash-es";
import { useContext, useState } from "react";
import { markdownServiceClient } from "@/grpcweb";
import { useMemoStore } from "@/store/v1";
import { Node, TaskListItemNode } from "@/types/proto/api/v1/markdown_service";
import Renderer from "./Renderer";
import { RendererContext } from "./types";
interface Props {
node: Node;
index: string;
symbol: string;
indent: number;
complete: boolean;
children: Node[];
}
const TaskListItem: React.FC<Props> = ({ node, indent, complete, children }: Props) => {
const context = useContext(RendererContext);
const memoStore = useMemoStore();
const [checked] = useState(complete);
const handleCheckboxChange = async (on: boolean) => {
if (context.readonly || !context.memoName) {
return;
}
(node.taskListItemNode as TaskListItemNode)!.complete = on;
const { markdown } = await markdownServiceClient.restoreMarkdownNodes({ nodes: context.nodes });
await memoStore.updateMemo(
{
name: context.memoName,
content: markdown,
},
["content"],
);
};
return (
<li className="w-full flex flex-row">
{indent > 0 && (
<div className="block font-mono shrink-0">
<span>{repeat(" ", indent)}</span>
</div>
)}
<div className="w-auto grid grid-cols-[24px_1fr] gap-1">
<div className="w-7 h-6 flex justify-center items-center">
<Checkbox size="sm" checked={checked} disabled={context.readonly} onChange={(e) => handleCheckboxChange(e.target.checked)} />
</div>
<div className={clsx(complete && "line-through opacity-80")}>
{children.map((child, index) => (
<Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />
))}
</div>
</div>
</li>
);
};
export default TaskListItem;

View file

@ -1,35 +0,0 @@
import { repeat } from "lodash-es";
import { Node } from "@/types/proto/api/v1/markdown_service";
import Renderer from "./Renderer";
interface Props {
symbol: string;
indent: number;
children: Node[];
}
const UnorderedList: React.FC<Props> = ({ indent, children }: Props) => {
return (
<ul>
<li className="w-full flex flex-row">
{indent > 0 && (
<div className="block font-mono shrink-0">
<span>{repeat(" ", indent)}</span>
</div>
)}
<div className="w-auto grid grid-cols-[24px_1fr] gap-1">
<div className="w-7 h-6 flex justify-center items-center">
<span className="opacity-80"></span>
</div>
<div>
{children.map((child, index) => (
<Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />
))}
</div>
</div>
</li>
</ul>
);
};
export default UnorderedList;

View file

@ -0,0 +1,33 @@
import { repeat } from "lodash-es";
import { Node } from "@/types/proto/api/v1/markdown_service";
import Renderer from "./Renderer";
interface Props {
symbol: string;
indent: number;
children: Node[];
}
const UnorderedListItem: React.FC<Props> = ({ indent, children }: Props) => {
return (
<li className="w-full flex flex-row">
{indent > 0 && (
<div className="block font-mono shrink-0">
<span>{repeat(" ", indent)}</span>
</div>
)}
<div className="w-auto grid grid-cols-[24px_1fr] gap-1">
<div className="w-7 h-6 flex justify-center items-center">
<span className="opacity-80"></span>
</div>
<div>
{children.map((child, index) => (
<Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />
))}
</div>
</div>
</li>
);
};
export default UnorderedListItem;