diff --git a/cwd-api/src/api/admin/updateComment.ts b/cwd-api/src/api/admin/updateComment.ts index 6ba43053..e4b43a8c 100644 --- a/cwd-api/src/api/admin/updateComment.ts +++ b/cwd-api/src/api/admin/updateComment.ts @@ -1,8 +1,8 @@ import { Context } from 'hono'; import { Bindings } from '../../bindings'; import { checkContent } from '../public/postComment'; -import { marked } from 'marked'; import xss from 'xss'; +import { parseMarkdown } from '../../utils/markdown'; export const updateComment = async (c: Context<{ Bindings: Bindings }>) => { let body: any; @@ -112,7 +112,7 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => { return c.json({ message: '评论内容不能为空' }, 400); } - const html = await marked.parse(cleanedContent, { async: true }); + const html = await parseMarkdown(cleanedContent); const contentHtml = xss(html, { whiteList: { ...xss.whiteList, @@ -138,4 +138,3 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => { message: `Comment updated, id: ${id}.` }); }; - diff --git a/cwd-api/src/api/public/postComment.ts b/cwd-api/src/api/public/postComment.ts index 30dc980b..610a6811 100644 --- a/cwd-api/src/api/public/postComment.ts +++ b/cwd-api/src/api/public/postComment.ts @@ -1,8 +1,8 @@ import { Context } from 'hono'; import { UAParser } from 'ua-parser-js'; -import { marked } from 'marked'; import xss from 'xss'; import { Bindings } from '../../bindings'; +import { parseMarkdown } from '../../utils/markdown'; import { sendCommentNotification, sendCommentReplyNotification, @@ -134,7 +134,7 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => { const name = checkContent(rawName); // Markdown 渲染与 XSS 过滤 - const html = await marked.parse(cleanedContent, { async: true }); + const html = await parseMarkdown(cleanedContent); const contentHtml = xss(html, { whiteList: { ...xss.whiteList, diff --git a/cwd-api/src/utils/markdown.spec.ts b/cwd-api/src/utils/markdown.spec.ts new file mode 100644 index 00000000..0c39ba44 --- /dev/null +++ b/cwd-api/src/utils/markdown.spec.ts @@ -0,0 +1,8 @@ +import { describe, expect, it } from 'vitest'; +import { parseMarkdown } from './markdown'; + +describe('parseMarkdown', () => { + it('renders a single newline as a line break', async () => { + await expect(parseMarkdown('first line\nsecond line')).resolves.toBe('

first line
second line

\n'); + }); +}); diff --git a/cwd-api/src/utils/markdown.ts b/cwd-api/src/utils/markdown.ts new file mode 100644 index 00000000..7b4de451 --- /dev/null +++ b/cwd-api/src/utils/markdown.ts @@ -0,0 +1,11 @@ +import { marked } from 'marked'; + +/** + * Parse comment Markdown with the same line-break behavior as the widget preview. + */ +export const parseMarkdown = async (content: string): Promise => + marked.parse(content, { + async: true, + gfm: true, + breaks: true, + });