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> => {
|
||||
try {
|
||||
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', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -257,6 +268,7 @@ export const postComment = async (commentData: PostCommentRequest): Promise<Post
|
||||
},
|
||||
body: JSON.stringify({
|
||||
...commentData,
|
||||
hashtopic,
|
||||
identity,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -16,6 +16,8 @@ import { Dismiss24Regular, ArrowReply24Regular } from '@fluentui/react-icons';
|
||||
import { getComments, postComment } from '../api';
|
||||
import type { Comment as CommentType } from '../api';
|
||||
import { useLayout } from '../context/LayoutContext';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
container: {
|
||||
@@ -85,8 +87,43 @@ const useStyles = makeStyles({
|
||||
height: '40px',
|
||||
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 {
|
||||
postId: number;
|
||||
}
|
||||
@@ -188,7 +225,21 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId }) => {
|
||||
<div className={styles.commentHeader}>
|
||||
<Text className={styles.nickname}>{comment.nickname}</Text>
|
||||
</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}>
|
||||
<Tooltip content="回复" relationship="label">
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user