Update comment tags and hashtag payload
This commit is contained in:
@@ -250,6 +250,17 @@ export interface PostCommentResponse {
|
|||||||
export const postComment = async (commentData: PostCommentRequest): Promise<PostCommentResponse> => {
|
export const postComment = async (commentData: PostCommentRequest): Promise<PostCommentResponse> => {
|
||||||
try {
|
try {
|
||||||
const identity = await get_id_token();
|
const identity = await get_id_token();
|
||||||
|
const hashtopic: string[] = [];
|
||||||
|
const regex = /#\S+/g;
|
||||||
|
const matches = commentData.content.match(regex);
|
||||||
|
if (matches) {
|
||||||
|
matches.forEach(tag => {
|
||||||
|
const cleanTag = tag.substring(1);
|
||||||
|
if (!hashtopic.includes(cleanTag)) {
|
||||||
|
hashtopic.push(cleanTag);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
const response = await fetch('/api/comment', {
|
const response = await fetch('/api/comment', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -257,6 +268,7 @@ export const postComment = async (commentData: PostCommentRequest): Promise<Post
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
...commentData,
|
...commentData,
|
||||||
|
hashtopic,
|
||||||
identity,
|
identity,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import { Dismiss24Regular, ArrowReply24Regular } from '@fluentui/react-icons';
|
|||||||
import { getComments, postComment } from '../api';
|
import { getComments, postComment } from '../api';
|
||||||
import type { Comment as CommentType } from '../api';
|
import type { Comment as CommentType } from '../api';
|
||||||
import { useLayout } from '../context/LayoutContext';
|
import { useLayout } from '../context/LayoutContext';
|
||||||
|
import ReactMarkdown from 'react-markdown';
|
||||||
|
import remarkGfm from 'remark-gfm';
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
container: {
|
container: {
|
||||||
@@ -85,8 +87,43 @@ const useStyles = makeStyles({
|
|||||||
height: '40px',
|
height: '40px',
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
},
|
},
|
||||||
|
tag: {
|
||||||
|
color: tokens.colorBrandForeground1,
|
||||||
|
textDecoration: 'none',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 自定义 remark 插件,用于高亮 #tag
|
||||||
|
const remarkTagPlugin = () => {
|
||||||
|
return (tree: any) => {
|
||||||
|
const transformNode = (node: any, inLink = false) => {
|
||||||
|
if (node.type === 'link') inLink = true;
|
||||||
|
|
||||||
|
if (node.children) {
|
||||||
|
node.children = node.children.flatMap((child: any) => {
|
||||||
|
if (child.type === 'text' && !inLink) {
|
||||||
|
const parts = child.value.split(/(#\S+)/g);
|
||||||
|
return parts.map((part: string) => {
|
||||||
|
if (part.match(/^#\S+$/)) {
|
||||||
|
return {
|
||||||
|
type: 'link',
|
||||||
|
url: 'tag:' + part,
|
||||||
|
children: [{ type: 'text', value: part }]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (part === "") return [];
|
||||||
|
return { type: 'text', value: part };
|
||||||
|
}).flat();
|
||||||
|
}
|
||||||
|
return transformNode(child, inLink);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
transformNode(tree);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
interface CommentSectionProps {
|
interface CommentSectionProps {
|
||||||
postId: number;
|
postId: number;
|
||||||
}
|
}
|
||||||
@@ -188,7 +225,21 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId }) => {
|
|||||||
<div className={styles.commentHeader}>
|
<div className={styles.commentHeader}>
|
||||||
<Text className={styles.nickname}>{comment.nickname}</Text>
|
<Text className={styles.nickname}>{comment.nickname}</Text>
|
||||||
</div>
|
</div>
|
||||||
<Text>{comment.content}</Text>
|
<div style={{ whiteSpace: 'pre-wrap' }}>
|
||||||
|
<ReactMarkdown
|
||||||
|
remarkPlugins={[remarkGfm, remarkTagPlugin]}
|
||||||
|
components={{
|
||||||
|
a: ({ node, ...props }) => {
|
||||||
|
if (props.href && props.href.startsWith('tag:')) {
|
||||||
|
return <span className={styles.tag}>{props.children}</span>;
|
||||||
|
}
|
||||||
|
return <a {...props} />;
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{comment.content}
|
||||||
|
</ReactMarkdown>
|
||||||
|
</div>
|
||||||
<div className={styles.commentFooter}>
|
<div className={styles.commentFooter}>
|
||||||
<Tooltip content="回复" relationship="label">
|
<Tooltip content="回复" relationship="label">
|
||||||
<div
|
<div
|
||||||
|
|||||||
Reference in New Issue
Block a user