Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
7d5f6034
Commit
7d5f6034
authored
Mar 04, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: update compact view
parent
f0a521f5
Changes
21
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
328 additions
and
400 deletions
+328
-400
user_service.proto
proto/api/v2/user_service.proto
+0
-2
README.md
proto/gen/api/v2/README.md
+0
-1
user_service.pb.go
proto/gen/api/v2/user_service.pb.go
+168
-179
README.md
proto/gen/store/README.md
+0
-2
user_setting.pb.go
proto/gen/store/user_setting.pb.go
+39
-62
user_setting.proto
proto/store/user_setting.proto
+0
-3
apidocs.swagger.yaml
server/route/api/v2/apidocs.swagger.yaml
+0
-6
user_service.go
server/route/api/v2/user_service.go
+0
-13
user_setting.go
store/db/mysql/user_setting.go
+0
-11
user_setting.go
store/db/postgres/user_setting.go
+0
-11
user_setting.go
store/db/sqlite/user_setting.go
+0
-11
gomark.wasm
web/src/assets/gomark.wasm
+0
-0
wasm_exec.js
web/src/assets/wasm_exec.js
+1
-0
CodeBlock.tsx
web/src/components/MemoContent/CodeBlock.tsx
+7
-4
Renderer.tsx
web/src/components/MemoContent/Renderer.tsx
+30
-31
TaskList.tsx
web/src/components/MemoContent/TaskList.tsx
+2
-2
index.tsx
web/src/components/MemoContent/index.tsx
+69
-28
MemoView.tsx
web/src/components/MemoView.tsx
+1
-23
SystemSection.tsx
web/src/components/Settings/SystemSection.tsx
+6
-6
node.ts
web/src/types/node.ts
+1
-1
tag.ts
web/src/utils/tag.ts
+4
-4
No files found.
proto/api/v2/user_service.proto
View file @
7d5f6034
...
@@ -161,8 +161,6 @@ message UserSetting {
...
@@ -161,8 +161,6 @@ message UserSetting {
string
memo_visibility
=
4
;
string
memo_visibility
=
4
;
// The telegram user id of the user.
// The telegram user id of the user.
string
telegram_user_id
=
5
;
string
telegram_user_id
=
5
;
// The compact view for a memo.
bool
compact_view
=
6
;
}
}
message
GetUserSettingRequest
{
message
GetUserSettingRequest
{
...
...
proto/gen/api/v2/README.md
View file @
7d5f6034
...
@@ -718,7 +718,6 @@ Used internally for obfuscating the page token.
...
@@ -718,7 +718,6 @@ Used internally for obfuscating the page token.
| appearance |
[
string
](
#string
)
| | The preferred appearance of the user. |
| appearance |
[
string
](
#string
)
| | The preferred appearance of the user. |
| memo_visibility |
[
string
](
#string
)
| | The default visibility of the memo. |
| memo_visibility |
[
string
](
#string
)
| | The default visibility of the memo. |
| telegram_user_id |
[
string
](
#string
)
| | The telegram user id of the user. |
| telegram_user_id |
[
string
](
#string
)
| | The telegram user id of the user. |
| compact_view |
[
bool
](
#bool
)
| | The compact view for a memo. |
...
...
proto/gen/api/v2/user_service.pb.go
View file @
7d5f6034
This diff is collapsed.
Click to expand it.
proto/gen/store/README.md
View file @
7d5f6034
...
@@ -289,7 +289,6 @@
...
@@ -289,7 +289,6 @@
| appearance |
[
string
](
#string
)
| | |
| appearance |
[
string
](
#string
)
| | |
| memo_visibility |
[
string
](
#string
)
| | |
| memo_visibility |
[
string
](
#string
)
| | |
| telegram_user_id |
[
string
](
#string
)
| | |
| telegram_user_id |
[
string
](
#string
)
| | |
| compact_view |
[
bool
](
#bool
)
| | |
...
@@ -311,7 +310,6 @@
...
@@ -311,7 +310,6 @@
| USER_SETTING_APPEARANCE | 3 | The appearance of the user. |
| USER_SETTING_APPEARANCE | 3 | The appearance of the user. |
| USER_SETTING_MEMO_VISIBILITY | 4 | The visibility of the memo. |
| USER_SETTING_MEMO_VISIBILITY | 4 | The visibility of the memo. |
| USER_SETTING_TELEGRAM_USER_ID | 5 | The telegram user id of the user. |
| USER_SETTING_TELEGRAM_USER_ID | 5 | The telegram user id of the user. |
| USER_SETTING_COMPACT_VIEW | 6 | The compact view for a memo. |
...
...
proto/gen/store/user_setting.pb.go
View file @
7d5f6034
This diff is collapsed.
Click to expand it.
proto/store/user_setting.proto
View file @
7d5f6034
...
@@ -16,8 +16,6 @@ enum UserSettingKey {
...
@@ -16,8 +16,6 @@ enum UserSettingKey {
USER_SETTING_MEMO_VISIBILITY
=
4
;
USER_SETTING_MEMO_VISIBILITY
=
4
;
// The telegram user id of the user.
// The telegram user id of the user.
USER_SETTING_TELEGRAM_USER_ID
=
5
;
USER_SETTING_TELEGRAM_USER_ID
=
5
;
// The compact view for a memo.
USER_SETTING_COMPACT_VIEW
=
6
;
}
}
message
UserSetting
{
message
UserSetting
{
...
@@ -29,7 +27,6 @@ message UserSetting {
...
@@ -29,7 +27,6 @@ message UserSetting {
string
appearance
=
5
;
string
appearance
=
5
;
string
memo_visibility
=
6
;
string
memo_visibility
=
6
;
string
telegram_user_id
=
7
;
string
telegram_user_id
=
7
;
bool
compact_view
=
8
;
}
}
}
}
...
...
server/route/api/v2/apidocs.swagger.yaml
View file @
7d5f6034
...
@@ -1437,9 +1437,6 @@ paths:
...
@@ -1437,9 +1437,6 @@ paths:
telegramUserId
:
telegramUserId
:
type
:
string
type
:
string
description
:
The telegram user id of the user.
description
:
The telegram user id of the user.
compactView
:
type
:
boolean
description
:
The compact view for a memo.
tags
:
tags
:
-
UserService
-
UserService
/api/v2/{user.name}
:
/api/v2/{user.name}
:
...
@@ -1626,9 +1623,6 @@ definitions:
...
@@ -1626,9 +1623,6 @@ definitions:
telegramUserId
:
telegramUserId
:
type
:
string
type
:
string
description
:
The telegram user id of the user.
description
:
The telegram user id of the user.
compactView
:
type
:
boolean
description
:
The compact view for a memo.
apiv2Webhook
:
apiv2Webhook
:
type
:
object
type
:
object
properties
:
properties
:
...
...
server/route/api/v2/user_service.go
View file @
7d5f6034
...
@@ -219,7 +219,6 @@ func getDefaultUserSetting() *apiv2pb.UserSetting {
...
@@ -219,7 +219,6 @@ func getDefaultUserSetting() *apiv2pb.UserSetting {
Locale
:
"en"
,
Locale
:
"en"
,
Appearance
:
"system"
,
Appearance
:
"system"
,
MemoVisibility
:
"PRIVATE"
,
MemoVisibility
:
"PRIVATE"
,
CompactView
:
false
,
}
}
}
}
...
@@ -245,8 +244,6 @@ func (s *APIV2Service) GetUserSetting(ctx context.Context, _ *apiv2pb.GetUserSet
...
@@ -245,8 +244,6 @@ func (s *APIV2Service) GetUserSetting(ctx context.Context, _ *apiv2pb.GetUserSet
userSettingMessage
.
MemoVisibility
=
setting
.
GetMemoVisibility
()
userSettingMessage
.
MemoVisibility
=
setting
.
GetMemoVisibility
()
}
else
if
setting
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
}
else
if
setting
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
userSettingMessage
.
TelegramUserId
=
setting
.
GetTelegramUserId
()
userSettingMessage
.
TelegramUserId
=
setting
.
GetTelegramUserId
()
}
else
if
setting
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
{
userSettingMessage
.
CompactView
=
setting
.
GetCompactView
()
}
}
}
}
return
&
apiv2pb
.
GetUserSettingResponse
{
return
&
apiv2pb
.
GetUserSettingResponse
{
...
@@ -305,16 +302,6 @@ func (s *APIV2Service) UpdateUserSetting(ctx context.Context, request *apiv2pb.U
...
@@ -305,16 +302,6 @@ func (s *APIV2Service) UpdateUserSetting(ctx context.Context, request *apiv2pb.U
});
err
!=
nil
{
});
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to upsert user setting: %v"
,
err
)
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to upsert user setting: %v"
,
err
)
}
}
}
else
if
field
==
"compact_view"
{
if
_
,
err
:=
s
.
Store
.
UpsertUserSetting
(
ctx
,
&
storepb
.
UserSetting
{
UserId
:
user
.
ID
,
Key
:
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
,
Value
:
&
storepb
.
UserSetting_CompactView
{
CompactView
:
request
.
Setting
.
CompactView
,
},
});
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to upsert user setting: %v"
,
err
)
}
}
else
{
}
else
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid update path: %s"
,
field
)
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid update path: %s"
,
field
)
}
}
...
...
store/db/mysql/user_setting.go
View file @
7d5f6034
...
@@ -3,7 +3,6 @@ package mysql
...
@@ -3,7 +3,6 @@ package mysql
import
(
import
(
"context"
"context"
"database/sql"
"database/sql"
"strconv"
"strings"
"strings"
"github.com/pkg/errors"
"github.com/pkg/errors"
...
@@ -30,8 +29,6 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting)
...
@@ -30,8 +29,6 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting)
valueString
=
upsert
.
GetMemoVisibility
()
valueString
=
upsert
.
GetMemoVisibility
()
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
valueString
=
upsert
.
GetTelegramUserId
()
valueString
=
upsert
.
GetTelegramUserId
()
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
{
valueString
=
strconv
.
FormatBool
(
upsert
.
GetCompactView
())
}
else
{
}
else
{
return
nil
,
errors
.
Errorf
(
"unknown user setting key: %s"
,
upsert
.
Key
.
String
())
return
nil
,
errors
.
Errorf
(
"unknown user setting key: %s"
,
upsert
.
Key
.
String
())
}
}
...
@@ -96,14 +93,6 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
...
@@ -96,14 +93,6 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
userSetting
.
Value
=
&
storepb
.
UserSetting_TelegramUserId
{
userSetting
.
Value
=
&
storepb
.
UserSetting_TelegramUserId
{
TelegramUserId
:
valueString
,
TelegramUserId
:
valueString
,
}
}
}
else
if
userSetting
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
{
compactView
,
err
:=
strconv
.
ParseBool
(
valueString
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"failed to parse compact view value: %s"
,
valueString
)
}
userSetting
.
Value
=
&
storepb
.
UserSetting_CompactView
{
CompactView
:
compactView
,
}
}
else
{
}
else
{
// Skip unknown user setting key.
// Skip unknown user setting key.
continue
continue
...
...
store/db/postgres/user_setting.go
View file @
7d5f6034
...
@@ -3,7 +3,6 @@ package postgres
...
@@ -3,7 +3,6 @@ package postgres
import
(
import
(
"context"
"context"
"database/sql"
"database/sql"
"strconv"
"strings"
"strings"
"github.com/pkg/errors"
"github.com/pkg/errors"
...
@@ -37,8 +36,6 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting)
...
@@ -37,8 +36,6 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting)
valueString
=
upsert
.
GetMemoVisibility
()
valueString
=
upsert
.
GetMemoVisibility
()
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
valueString
=
upsert
.
GetTelegramUserId
()
valueString
=
upsert
.
GetTelegramUserId
()
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
{
valueString
=
strconv
.
FormatBool
(
upsert
.
GetCompactView
())
}
else
{
}
else
{
return
nil
,
errors
.
Errorf
(
"unknown user setting key: %s"
,
upsert
.
Key
.
String
())
return
nil
,
errors
.
Errorf
(
"unknown user setting key: %s"
,
upsert
.
Key
.
String
())
}
}
...
@@ -109,14 +106,6 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
...
@@ -109,14 +106,6 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
userSetting
.
Value
=
&
storepb
.
UserSetting_TelegramUserId
{
userSetting
.
Value
=
&
storepb
.
UserSetting_TelegramUserId
{
TelegramUserId
:
valueString
,
TelegramUserId
:
valueString
,
}
}
}
else
if
userSetting
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
{
compactView
,
err
:=
strconv
.
ParseBool
(
valueString
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"failed to parse compact view value: %s"
,
valueString
)
}
userSetting
.
Value
=
&
storepb
.
UserSetting_CompactView
{
CompactView
:
compactView
,
}
}
else
{
}
else
{
// Skip unknown user setting key.
// Skip unknown user setting key.
continue
continue
...
...
store/db/sqlite/user_setting.go
View file @
7d5f6034
...
@@ -3,7 +3,6 @@ package sqlite
...
@@ -3,7 +3,6 @@ package sqlite
import
(
import
(
"context"
"context"
"database/sql"
"database/sql"
"strconv"
"strings"
"strings"
"github.com/pkg/errors"
"github.com/pkg/errors"
...
@@ -37,8 +36,6 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting)
...
@@ -37,8 +36,6 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting)
valueString
=
upsert
.
GetMemoVisibility
()
valueString
=
upsert
.
GetMemoVisibility
()
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_TELEGRAM_USER_ID
{
valueString
=
upsert
.
GetTelegramUserId
()
valueString
=
upsert
.
GetTelegramUserId
()
}
else
if
upsert
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
{
valueString
=
strconv
.
FormatBool
(
upsert
.
GetCompactView
())
}
else
{
}
else
{
return
nil
,
errors
.
Errorf
(
"unknown user setting key: %s"
,
upsert
.
Key
.
String
())
return
nil
,
errors
.
Errorf
(
"unknown user setting key: %s"
,
upsert
.
Key
.
String
())
}
}
...
@@ -109,14 +106,6 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
...
@@ -109,14 +106,6 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
userSetting
.
Value
=
&
storepb
.
UserSetting_TelegramUserId
{
userSetting
.
Value
=
&
storepb
.
UserSetting_TelegramUserId
{
TelegramUserId
:
valueString
,
TelegramUserId
:
valueString
,
}
}
}
else
if
userSetting
.
Key
==
storepb
.
UserSettingKey_USER_SETTING_COMPACT_VIEW
{
compactView
,
err
:=
strconv
.
ParseBool
(
valueString
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"failed to parse compact view value: %s"
,
valueString
)
}
userSetting
.
Value
=
&
storepb
.
UserSetting_CompactView
{
CompactView
:
compactView
,
}
}
else
{
}
else
{
// Skip unknown user setting key.
// Skip unknown user setting key.
continue
continue
...
...
web/src/assets/gomark.wasm
View file @
7d5f6034
No preview for this file type
web/src/assets/wasm_exec.js
View file @
7d5f6034
...
@@ -363,6 +363,7 @@
...
@@ -363,6 +363,7 @@
"syscall/js.finalizeRef"
:
(
v_ref
)
=>
{
"syscall/js.finalizeRef"
:
(
v_ref
)
=>
{
// Note: TinyGo does not support finalizers so this should never be
// Note: TinyGo does not support finalizers so this should never be
// called.
// called.
console
.
warn
(
"syscall/js.finalizeRef not implemented"
);
},
},
// func stringVal(value string) ref
// func stringVal(value string) ref
...
...
web/src/components/MemoContent/CodeBlock.tsx
View file @
7d5f6034
...
@@ -28,10 +28,13 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
...
@@ -28,10 +28,13 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
let
highlightedCode
=
content
;
let
highlightedCode
=
content
;
try
{
try
{
const
temp
=
hljs
.
highlight
(
content
,
{
const
lang
=
hljs
.
getLanguage
(
formatedLanguage
);
language
:
formatedLanguage
,
if
(
lang
)
{
}).
value
;
const
temp
=
hljs
.
highlight
(
content
,
{
highlightedCode
=
temp
;
language
:
formatedLanguage
,
}).
value
;
highlightedCode
=
temp
;
}
}
catch
(
error
)
{
}
catch
(
error
)
{
// Skip error and use default highlighted code.
// Skip error and use default highlighted code.
}
}
...
...
web/src/components/MemoContent/Renderer.tsx
View file @
7d5f6034
...
@@ -62,67 +62,66 @@ interface Props {
...
@@ -62,67 +62,66 @@ interface Props {
node
:
Node
;
node
:
Node
;
}
}
const
Renderer
:
React
.
FC
<
Props
>
=
({
index
,
node
:
rawNode
}:
Props
)
=>
{
const
Renderer
:
React
.
FC
<
Props
>
=
({
index
,
node
}:
Props
)
=>
{
const
{
type
,
node
}
=
rawNode
;
switch
(
node
.
type
)
{
switch
(
type
)
{
case
NodeType
.
LINE_BREAK
:
case
NodeType
.
LINE_BREAK
:
return
<
LineBreak
index=
{
index
}
/>;
return
<
LineBreak
index=
{
index
}
/>;
case
NodeType
.
PARAGRAPH
:
case
NodeType
.
PARAGRAPH
:
return
<
Paragraph
index=
{
index
}
{
...
(
node
as
ParagraphNode
)}
/>;
return
<
Paragraph
index=
{
index
}
{
...
(
node
.
value
as
ParagraphNode
)}
/>;
case
NodeType
.
CODE_BLOCK
:
case
NodeType
.
CODE_BLOCK
:
return
<
CodeBlock
index=
{
index
}
{
...
(
node
as
CodeBlockNode
)}
/>;
return
<
CodeBlock
index=
{
index
}
{
...
(
node
.
value
as
CodeBlockNode
)}
/>;
case
NodeType
.
HEADING
:
case
NodeType
.
HEADING
:
return
<
Heading
index=
{
index
}
{
...
(
node
as
HeadingNode
)}
/>;
return
<
Heading
index=
{
index
}
{
...
(
node
.
value
as
HeadingNode
)}
/>;
case
NodeType
.
HORIZONTAL_RULE
:
case
NodeType
.
HORIZONTAL_RULE
:
return
<
HorizontalRule
index=
{
index
}
{
...
(
node
as
HorizontalRuleNode
)}
/>;
return
<
HorizontalRule
index=
{
index
}
{
...
(
node
.
value
as
HorizontalRuleNode
)}
/>;
case
NodeType
.
BLOCKQUOTE
:
case
NodeType
.
BLOCKQUOTE
:
return
<
Blockquote
index=
{
index
}
{
...
(
node
as
BlockquoteNode
)}
/>;
return
<
Blockquote
index=
{
index
}
{
...
(
node
.
value
as
BlockquoteNode
)}
/>;
case
NodeType
.
ORDERED_LIST
:
case
NodeType
.
ORDERED_LIST
:
return
<
OrderedList
index=
{
index
}
{
...
(
node
as
OrderedListNode
)}
/>;
return
<
OrderedList
index=
{
index
}
{
...
(
node
.
value
as
OrderedListNode
)}
/>;
case
NodeType
.
UNORDERED_LIST
:
case
NodeType
.
UNORDERED_LIST
:
return
<
UnorderedList
{
...
(
node
as
UnorderedListNode
)}
/>;
return
<
UnorderedList
{
...
(
node
.
value
as
UnorderedListNode
)}
/>;
case
NodeType
.
TASK_LIST
:
case
NodeType
.
TASK_LIST
:
return
<
TaskList
index=
{
index
}
{
...
(
node
as
TaskListNode
)}
/>;
return
<
TaskList
index=
{
index
}
{
...
(
node
.
value
as
TaskListNode
)}
/>;
case
NodeType
.
MATH_BLOCK
:
case
NodeType
.
MATH_BLOCK
:
return
<
Math
{
...
(
node
as
MathNode
)}
block=
{
true
}
/>;
return
<
Math
{
...
(
node
.
value
as
MathNode
)}
block=
{
true
}
/>;
case
NodeType
.
TABLE
:
case
NodeType
.
TABLE
:
return
<
Table
{
...
(
node
as
TableNode
)}
/>;
return
<
Table
{
...
(
node
.
value
as
TableNode
)}
/>;
case
NodeType
.
EMBEDDED_CONTENT
:
case
NodeType
.
EMBEDDED_CONTENT
:
return
<
EmbeddedContent
{
...
(
node
as
EmbeddedContentNode
)}
/>;
return
<
EmbeddedContent
{
...
(
node
.
value
as
EmbeddedContentNode
)}
/>;
case
NodeType
.
TEXT
:
case
NodeType
.
TEXT
:
return
<
Text
{
...
(
node
as
TextNode
)}
/>;
return
<
Text
{
...
(
node
.
value
as
TextNode
)}
/>;
case
NodeType
.
BOLD
:
case
NodeType
.
BOLD
:
return
<
Bold
{
...
(
node
as
BoldNode
)}
/>;
return
<
Bold
{
...
(
node
.
value
as
BoldNode
)}
/>;
case
NodeType
.
ITALIC
:
case
NodeType
.
ITALIC
:
return
<
Italic
{
...
(
node
as
ItalicNode
)}
/>;
return
<
Italic
{
...
(
node
.
value
as
ItalicNode
)}
/>;
case
NodeType
.
BOLD_ITALIC
:
case
NodeType
.
BOLD_ITALIC
:
return
<
BoldItalic
{
...
(
node
as
BoldItalicNode
)}
/>;
return
<
BoldItalic
{
...
(
node
.
value
as
BoldItalicNode
)}
/>;
case
NodeType
.
CODE
:
case
NodeType
.
CODE
:
return
<
Code
{
...
(
node
as
CodeNode
)}
/>;
return
<
Code
{
...
(
node
.
value
as
CodeNode
)}
/>;
case
NodeType
.
IMAGE
:
case
NodeType
.
IMAGE
:
return
<
Image
{
...
(
node
as
ImageNode
)}
/>;
return
<
Image
{
...
(
node
.
value
as
ImageNode
)}
/>;
case
NodeType
.
LINK
:
case
NodeType
.
LINK
:
return
<
Link
{
...
(
node
as
LinkNode
)}
/>;
return
<
Link
{
...
(
node
.
value
as
LinkNode
)}
/>;
case
NodeType
.
AUTO_LINK
:
case
NodeType
.
AUTO_LINK
:
return
<
Link
{
...
(
node
as
AutoLinkNode
)}
/>;
return
<
Link
{
...
(
node
.
value
as
AutoLinkNode
)}
/>;
case
NodeType
.
TAG
:
case
NodeType
.
TAG
:
return
<
Tag
{
...
(
node
as
TagNode
)}
/>;
return
<
Tag
{
...
(
node
.
value
as
TagNode
)}
/>;
case
NodeType
.
STRIKETHROUGH
:
case
NodeType
.
STRIKETHROUGH
:
return
<
Strikethrough
{
...
(
node
as
StrikethroughNode
)}
/>;
return
<
Strikethrough
{
...
(
node
.
value
as
StrikethroughNode
)}
/>;
case
NodeType
.
MATH
:
case
NodeType
.
MATH
:
return
<
Math
{
...
(
node
as
MathNode
)}
/>;
return
<
Math
{
...
(
node
.
value
as
MathNode
)}
/>;
case
NodeType
.
HIGHLIGHT
:
case
NodeType
.
HIGHLIGHT
:
return
<
Highlight
{
...
(
node
as
HighlightNode
)}
/>;
return
<
Highlight
{
...
(
node
.
value
as
HighlightNode
)}
/>;
case
NodeType
.
ESCAPING_CHARACTER
:
case
NodeType
.
ESCAPING_CHARACTER
:
return
<
EscapingCharacter
{
...
(
node
as
EscapingCharacterNode
)}
/>;
return
<
EscapingCharacter
{
...
(
node
.
value
as
EscapingCharacterNode
)}
/>;
case
NodeType
.
SUBSCRIPT
:
case
NodeType
.
SUBSCRIPT
:
return
<
Subscript
{
...
(
node
as
SubscriptNode
)}
/>;
return
<
Subscript
{
...
(
node
.
value
as
SubscriptNode
)}
/>;
case
NodeType
.
SUPERSCRIPT
:
case
NodeType
.
SUPERSCRIPT
:
return
<
Superscript
{
...
(
node
as
SuperscriptNode
)}
/>;
return
<
Superscript
{
...
(
node
.
value
as
SuperscriptNode
)}
/>;
case
NodeType
.
REFERENCED_CONTENT
:
case
NodeType
.
REFERENCED_CONTENT
:
return
<
ReferencedContent
{
...
(
node
as
ReferencedContentNode
)}
/>;
return
<
ReferencedContent
{
...
(
node
.
value
as
ReferencedContentNode
)}
/>;
case
NodeType
.
SPOILER
:
case
NodeType
.
SPOILER
:
return
<
Spoiler
{
...
(
node
as
SpoilerNode
)}
/>;
return
<
Spoiler
{
...
(
node
.
value
as
SpoilerNode
)}
/>;
default
:
default
:
return
null
;
return
null
;
}
}
...
...
web/src/components/MemoContent/TaskList.tsx
View file @
7d5f6034
...
@@ -31,11 +31,11 @@ const TaskList: React.FC<Props> = ({ index, indent, complete, children }: Props)
...
@@ -31,11 +31,11 @@ const TaskList: React.FC<Props> = ({ index, indent, complete, children }: Props)
}
}
const
node
=
context
.
nodes
[
nodeIndex
];
const
node
=
context
.
nodes
[
nodeIndex
];
if
(
node
.
type
!==
NodeType
.
TASK_LIST
||
!
node
.
nod
e
)
{
if
(
node
.
type
!==
NodeType
.
TASK_LIST
||
!
node
.
valu
e
)
{
return
;
return
;
}
}
(
node
.
nod
e
as
TaskListNode
)
!
.
complete
=
on
;
(
node
.
valu
e
as
TaskListNode
)
!
.
complete
=
on
;
const
content
=
window
.
restore
(
context
.
nodes
);
const
content
=
window
.
restore
(
context
.
nodes
);
await
memoStore
.
updateMemo
(
await
memoStore
.
updateMemo
(
{
{
...
...
web/src/components/MemoContent/index.tsx
View file @
7d5f6034
import
{
memo
,
useRef
}
from
"react"
;
import
classNames
from
"classnames"
;
import
{
memo
,
useEffect
,
useRef
,
useState
}
from
"react"
;
import
{
Link
}
from
"react-router-dom"
;
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/node"
;
import
{
Node
,
NodeType
}
from
"@/types/node"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
Icon
from
"../Icon"
;
import
Renderer
from
"./Renderer"
;
import
Renderer
from
"./Renderer"
;
import
{
RendererContext
}
from
"./types"
;
import
{
RendererContext
}
from
"./types"
;
// MAX_DISPLAY_HEIGHT is the maximum height of the memo content to display in compact mode.
const
MAX_DISPLAY_HEIGHT
=
256
;
interface
Props
{
interface
Props
{
content
:
string
;
content
:
string
;
memoId
?:
number
;
memoId
?:
number
;
compact
?:
boolean
;
readonly
?:
boolean
;
readonly
?:
boolean
;
disableFilter
?:
boolean
;
disableFilter
?:
boolean
;
// embeddedMemos is a set of memo resource names that are embedded in the current memo.
// embeddedMemos is a set of memo resource names that are embedded in the current memo.
...
@@ -19,11 +27,28 @@ interface Props {
...
@@ -19,11 +27,28 @@ interface Props {
const
MemoContent
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
MemoContent
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
className
,
content
,
memoId
,
embeddedMemos
,
onClick
}
=
props
;
const
{
className
,
content
,
memoId
,
embeddedMemos
,
onClick
}
=
props
;
const
t
=
useTranslate
();
const
currentUser
=
useCurrentUser
();
const
currentUser
=
useCurrentUser
();
const
memoStore
=
useMemoStore
();
const
memoStore
=
useMemoStore
();
const
memoContentContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memoContentContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
[
showCompactMode
,
setShowCompactMode
]
=
useState
<
boolean
>
(
false
);
const
memo
=
memoId
?
memoStore
.
getMemoById
(
memoId
)
:
null
;
const
nodes
=
window
.
parse
(
content
);
const
nodes
=
window
.
parse
(
content
);
const
allowEdit
=
!
props
.
readonly
&&
memoId
&&
currentUser
?.
id
===
memoStore
.
getMemoById
(
memoId
)?.
creatorId
;
const
allowEdit
=
!
props
.
readonly
&&
memo
&&
currentUser
?.
id
===
memo
.
creatorId
;
// Initial compact mode.
useEffect
(()
=>
{
if
(
!
props
.
compact
)
{
return
;
}
if
(
!
memoContentContainerRef
.
current
)
{
return
;
}
if
((
memoContentContainerRef
.
current
as
HTMLDivElement
).
getBoundingClientRect
().
height
>
MAX_DISPLAY_HEIGHT
)
{
setShowCompactMode
(
true
);
}
},
[]);
const
handleMemoContentClick
=
async
(
e
:
React
.
MouseEvent
)
=>
{
const
handleMemoContentClick
=
async
(
e
:
React
.
MouseEvent
)
=>
{
if
(
onClick
)
{
if
(
onClick
)
{
...
@@ -35,34 +60,50 @@ const MemoContent: React.FC<Props> = (props: Props) => {
...
@@ -35,34 +60,50 @@ const MemoContent: React.FC<Props> = (props: Props) => {
let
skipNextLineBreakFlag
=
false
;
let
skipNextLineBreakFlag
=
false
;
return
(
return
(
<
RendererContext
.
Provider
<>
value=
{
{
<
RendererContext
.
Provider
nodes
,
value=
{
{
memoId
,
nodes
,
readonly
:
!
allowEdit
,
memoId
,
disableFilter
:
props
.
disableFilter
,
readonly
:
!
allowEdit
,
embeddedMemos
:
embeddedMemos
||
new
Set
(),
disableFilter
:
props
.
disableFilter
,
}
}
embeddedMemos
:
embeddedMemos
||
new
Set
(),
>
}
}
<
div
className=
{
`w-full flex flex-col justify-start items-start text-gray-800 dark:text-gray-300 ${className || ""}`
}
>
>
<
div
<
div
className=
{
`w-full flex flex-col justify-start items-start text-gray-800 dark:text-gray-300 ${className || ""}`
}
>
ref=
{
memoContentContainerRef
}
<
div
className=
"w-full max-w-full word-break text-base leading-6 space-y-1 whitespace-pre-wrap"
ref=
{
memoContentContainerRef
}
onClick=
{
handleMemoContentClick
}
className=
{
classNames
(
>
"w-full max-w-full word-break text-base leading-6 space-y-1 whitespace-pre-wrap"
,
{
nodes
.
map
((
node
,
index
)
=>
{
showCompactMode
&&
"line-clamp-6"
,
if
(
prevNode
?.
type
!==
NodeType
.
LINE_BREAK
&&
node
.
type
===
NodeType
.
LINE_BREAK
&&
skipNextLineBreakFlag
)
{
)
}
skipNextLineBreakFlag
=
false
;
onClick=
{
handleMemoContentClick
}
return
null
;
>
}
{
nodes
.
map
((
node
,
index
)
=>
{
if
(
prevNode
?.
type
!==
NodeType
.
LINE_BREAK
&&
node
.
type
===
NodeType
.
LINE_BREAK
&&
skipNextLineBreakFlag
)
{
skipNextLineBreakFlag
=
false
;
return
null
;
}
prevNode
=
node
;
prevNode
=
node
;
skipNextLineBreakFlag
=
true
;
skipNextLineBreakFlag
=
true
;
return
<
Renderer
key=
{
`${node.type}-${index}`
}
index=
{
String
(
index
)
}
node=
{
node
}
/>;
return
<
Renderer
key=
{
`${node.type}-${index}`
}
index=
{
String
(
index
)
}
node=
{
node
}
/>;
})
}
})
}
</
div
>
</
div
>
</
RendererContext
.
Provider
>
{
memo
&&
showCompactMode
&&
(
<
div
className=
"w-full mt-2"
>
<
Link
className=
"w-auto inline-flex flex-row justify-start items-center text-sm text-blue-600 dark:text-blue-400 hover:underline"
to=
{
`/m/${memo.name}`
}
>
<
span
>
{
t
(
"memo.show-more"
)
}
</
span
>
<
Icon
.
ChevronRight
className=
"w-4 h-auto"
/>
</
Link
>
</
div
>
</
div
>
</
div
>
)
}
</
RendererContext
.
Provider
>
</>
);
);
};
};
...
...
web/src/components/MemoView.tsx
View file @
7d5f6034
...
@@ -42,7 +42,6 @@ const MemoView: React.FC<Props> = (props: Props) => {
...
@@ -42,7 +42,6 @@ const MemoView: React.FC<Props> = (props: Props) => {
const
[
displayTime
,
setDisplayTime
]
=
useState
<
string
>
(
getRelativeTimeString
(
getTimeStampByDate
(
memo
.
displayTime
)));
const
[
displayTime
,
setDisplayTime
]
=
useState
<
string
>
(
getRelativeTimeString
(
getTimeStampByDate
(
memo
.
displayTime
)));
const
[
creator
,
setCreator
]
=
useState
(
userStore
.
getUserByUsername
(
extractUsernameFromName
(
memo
.
creator
)));
const
[
creator
,
setCreator
]
=
useState
(
userStore
.
getUserByUsername
(
extractUsernameFromName
(
memo
.
creator
)));
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
[
showCompactMode
,
setShowCompactMode
]
=
useState
(
false
);
const
referencedMemos
=
memo
.
relations
.
filter
((
relation
)
=>
relation
.
type
===
MemoRelation_Type
.
REFERENCE
);
const
referencedMemos
=
memo
.
relations
.
filter
((
relation
)
=>
relation
.
type
===
MemoRelation_Type
.
REFERENCE
);
const
commentAmount
=
memo
.
relations
.
filter
((
relation
)
=>
relation
.
type
===
MemoRelation_Type
.
COMMENT
).
length
;
const
commentAmount
=
memo
.
relations
.
filter
((
relation
)
=>
relation
.
type
===
MemoRelation_Type
.
COMMENT
).
length
;
const
readonly
=
memo
.
creator
!==
user
?.
name
;
const
readonly
=
memo
.
creator
!==
user
?.
name
;
...
@@ -55,16 +54,6 @@ const MemoView: React.FC<Props> = (props: Props) => {
...
@@ -55,16 +54,6 @@ const MemoView: React.FC<Props> = (props: Props) => {
})();
})();
},
[]);
},
[]);
// Initial compact mode.
useEffect
(()
=>
{
if
(
!
memoContainerRef
.
current
)
{
return
;
}
if
((
memoContainerRef
.
current
as
HTMLDivElement
).
getBoundingClientRect
().
height
>
512
)
{
setShowCompactMode
(
true
);
}
},
[]);
// Update display time string.
// Update display time string.
useEffect
(()
=>
{
useEffect
(()
=>
{
let
intervalFlag
:
any
=
-
1
;
let
intervalFlag
:
any
=
-
1
;
...
@@ -163,24 +152,13 @@ const MemoView: React.FC<Props> = (props: Props) => {
...
@@ -163,24 +152,13 @@ const MemoView: React.FC<Props> = (props: Props) => {
</
div
>
</
div
>
</
div
>
</
div
>
<
MemoContent
<
MemoContent
className=
{
showCompactMode
?
"!line-clamp-6"
:
""
}
key=
{
`${memo.id}-${memo.updateTime}`
}
key=
{
`${memo.id}-${memo.updateTime}`
}
memoId=
{
memo
.
id
}
memoId=
{
memo
.
id
}
content=
{
memo
.
content
}
content=
{
memo
.
content
}
readonly=
{
readonly
}
readonly=
{
readonly
}
onClick=
{
handleMemoContentClick
}
onClick=
{
handleMemoContentClick
}
compact=
{
true
}
/>
/>
{
showCompactMode
&&
(
<
div
className=
"w-full mt-2"
>
<
Link
className=
"w-auto flex flex-row justify-start items-center text-sm text-blue-600 dark:text-blue-400 hover:underline"
to=
{
`/m/${memo.name}`
}
>
<
span
>
{
t
(
"memo.show-more"
)
}
</
span
>
<
Icon
.
ChevronRight
className=
"w-4 h-auto"
/>
</
Link
>
</
div
>
)
}
<
MemoResourceListView
resources=
{
memo
.
resources
}
/>
<
MemoResourceListView
resources=
{
memo
.
resources
}
/>
<
MemoRelationListView
memo=
{
memo
}
relations=
{
referencedMemos
}
/>
<
MemoRelationListView
memo=
{
memo
}
relations=
{
referencedMemos
}
/>
<
MemoReactionistView
memo=
{
memo
}
reactions=
{
memo
.
reactions
}
/>
<
MemoReactionistView
memo=
{
memo
}
reactions=
{
memo
.
reactions
}
/>
...
...
web/src/components/Settings/SystemSection.tsx
View file @
7d5f6034
...
@@ -216,7 +216,7 @@ const SystemSection = () => {
...
@@ -216,7 +216,7 @@ const SystemSection = () => {
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
p
className=
"font-medium text-gray-700 dark:text-gray-500"
>
{
t
(
"common.basic"
)
}
</
p
>
<
p
className=
"font-medium text-gray-700 dark:text-gray-500"
>
{
t
(
"common.basic"
)
}
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"normal-text"
>
<
div
>
{
t
(
"setting.system-section.server-name"
)
}
:
<
span
className=
"font-mono font-bold"
>
{
systemStatus
.
customizedProfile
.
name
}
</
span
>
{
t
(
"setting.system-section.server-name"
)
}
:
<
span
className=
"font-mono font-bold"
>
{
systemStatus
.
customizedProfile
.
name
}
</
span
>
</
div
>
</
div
>
<
Button
onClick=
{
handleUpdateCustomizedProfileButtonClick
}
>
{
t
(
"common.edit"
)
}
</
Button
>
<
Button
onClick=
{
handleUpdateCustomizedProfileButtonClick
}
>
{
t
(
"common.edit"
)
}
</
Button
>
...
@@ -267,7 +267,7 @@ const SystemSection = () => {
...
@@ -267,7 +267,7 @@ const SystemSection = () => {
</
div
>
</
div
>
<
div
className=
"space-y-2 border rounded-md py-2 px-3 dark:border-zinc-700"
>
<
div
className=
"space-y-2 border rounded-md py-2 px-3 dark:border-zinc-700"
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.system-section.additional-style"
)
}
</
span
>
<
span
>
{
t
(
"setting.system-section.additional-style"
)
}
</
span
>
<
Button
variant=
"outlined"
color=
"neutral"
onClick=
{
handleSaveAdditionalStyle
}
>
<
Button
variant=
"outlined"
color=
"neutral"
onClick=
{
handleSaveAdditionalStyle
}
>
{
t
(
"common.save"
)
}
{
t
(
"common.save"
)
}
</
Button
>
</
Button
>
...
@@ -285,7 +285,7 @@ const SystemSection = () => {
...
@@ -285,7 +285,7 @@ const SystemSection = () => {
onChange=
{
(
event
)
=>
handleAdditionalStyleChanged
(
event
.
target
.
value
)
}
onChange=
{
(
event
)
=>
handleAdditionalStyleChanged
(
event
.
target
.
value
)
}
/>
/>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.system-section.additional-script"
)
}
</
span
>
<
span
>
{
t
(
"setting.system-section.additional-script"
)
}
</
span
>
<
Button
variant=
"outlined"
color=
"neutral"
onClick=
{
handleSaveAdditionalScript
}
>
<
Button
variant=
"outlined"
color=
"neutral"
onClick=
{
handleSaveAdditionalScript
}
>
{
t
(
"common.save"
)
}
{
t
(
"common.save"
)
}
</
Button
>
</
Button
>
...
@@ -317,16 +317,16 @@ const SystemSection = () => {
...
@@ -317,16 +317,16 @@ const SystemSection = () => {
<
Divider
className=
"!my-3"
/>
<
Divider
className=
"!my-3"
/>
<
p
className=
"font-medium text-gray-700 dark:text-gray-500"
>
Others
</
p
>
<
p
className=
"font-medium text-gray-700 dark:text-gray-500"
>
Others
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.system-section.disable-public-memos"
)
}
</
span
>
<
span
>
{
t
(
"setting.system-section.disable-public-memos"
)
}
</
span
>
<
Switch
checked=
{
state
.
disablePublicMemos
}
onChange=
{
(
event
)
=>
handleDisablePublicMemosChanged
(
event
.
target
.
checked
)
}
/>
<
Switch
checked=
{
state
.
disablePublicMemos
}
onChange=
{
(
event
)
=>
handleDisablePublicMemosChanged
(
event
.
target
.
checked
)
}
/>
</
div
>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.system-section.display-with-updated-time"
)
}
</
span
>
<
span
>
{
t
(
"setting.system-section.display-with-updated-time"
)
}
</
span
>
<
Switch
checked=
{
state
.
memoDisplayWithUpdatedTs
}
onChange=
{
(
event
)
=>
handleMemoDisplayWithUpdatedTs
(
event
.
target
.
checked
)
}
/>
<
Switch
checked=
{
state
.
memoDisplayWithUpdatedTs
}
onChange=
{
(
event
)
=>
handleMemoDisplayWithUpdatedTs
(
event
.
target
.
checked
)
}
/>
</
div
>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"flex flex-row items-center"
>
<
div
className=
"flex flex-row items-center"
>
<
span
className=
"
text-sm
mr-1"
>
{
t
(
"setting.system-section.max-upload-size"
)
}
</
span
>
<
span
className=
"mr-1"
>
{
t
(
"setting.system-section.max-upload-size"
)
}
</
span
>
<
Tooltip
title=
{
t
(
"setting.system-section.max-upload-size-hint"
)
}
placement=
"top"
>
<
Tooltip
title=
{
t
(
"setting.system-section.max-upload-size-hint"
)
}
placement=
"top"
>
<
Icon
.
HelpCircle
className=
"w-4 h-auto"
/>
<
Icon
.
HelpCircle
className=
"w-4 h-auto"
/>
</
Tooltip
>
</
Tooltip
>
...
...
web/src/types/node.ts
View file @
7d5f6034
...
@@ -32,7 +32,7 @@ export enum NodeType {
...
@@ -32,7 +32,7 @@ export enum NodeType {
export
interface
Node
{
export
interface
Node
{
type
:
NodeType
;
type
:
NodeType
;
nod
e
:
valu
e
:
|
LineBreakNode
|
LineBreakNode
|
ParagraphNode
|
ParagraphNode
|
CodeBlockNode
|
CodeBlockNode
...
...
web/src/utils/tag.ts
View file @
7d5f6034
import
{
Node
}
from
"@/types/node"
;
import
{
Node
,
TagNode
}
from
"@/types/node"
;
export
const
TAG_REG
=
/#
([^\s
#,
]
+
)
/
;
export
const
TAG_REG
=
/#
([^\s
#,
]
+
)
/
;
...
@@ -15,7 +15,7 @@ export const extractTagsFromContent = (content: string) => {
...
@@ -15,7 +15,7 @@ export const extractTagsFromContent = (content: string) => {
handle
(
node
);
handle
(
node
);
if
(
node
.
type
===
"PARAGRAPH"
||
node
.
type
===
"ORDERED_LIST"
||
node
.
type
===
"UNORDERED_LIST"
)
{
if
(
node
.
type
===
"PARAGRAPH"
||
node
.
type
===
"ORDERED_LIST"
||
node
.
type
===
"UNORDERED_LIST"
)
{
const
children
=
(
node
.
nod
e
as
any
).
children
;
const
children
=
(
node
.
valu
e
as
any
).
children
;
if
(
Array
.
isArray
(
children
))
{
if
(
Array
.
isArray
(
children
))
{
traverse
(
children
,
handle
);
traverse
(
children
,
handle
);
}
}
...
@@ -24,8 +24,8 @@ export const extractTagsFromContent = (content: string) => {
...
@@ -24,8 +24,8 @@ export const extractTagsFromContent = (content: string) => {
};
};
traverse
(
nodes
,
(
node
)
=>
{
traverse
(
nodes
,
(
node
)
=>
{
if
(
node
.
type
===
"TAG"
&&
node
.
nod
e
)
{
if
(
node
.
type
===
"TAG"
&&
node
.
valu
e
)
{
tags
.
add
((
node
.
node
as
any
).
content
);
tags
.
add
((
node
.
value
as
TagNode
).
content
);
}
}
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment