From 069b84daf9b99b095b8ebf8d9dddbe07d5de26b0 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 2 Sep 2026 13:17:04 +0800 Subject: [PATCH] fix(settings): render changelog entries as markdown --- .../components/settings/ChangelogPanel.vue | 13 +++++++----- .../src/lib/__tests__/ai/aiMarkdown.spec.ts | 20 ++++++++++++++++++- apps/desktop/src/lib/ai/aiMarkdown.ts | 8 ++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/apps/desktop/src/components/settings/ChangelogPanel.vue b/apps/desktop/src/components/settings/ChangelogPanel.vue index d52358eb9f..aba18982cf 100644 --- a/apps/desktop/src/components/settings/ChangelogPanel.vue +++ b/apps/desktop/src/components/settings/ChangelogPanel.vue @@ -7,7 +7,8 @@ import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { currentLocale } from "@/i18n"; import { isTauriRuntime } from "@/lib/backend/tauriRuntime"; -import { changelogLangFromLocale, changelogReleaseUrl, changelogWebsiteUrl, createLatestRequestGuard, fetchChangelog, type ChangelogLang, type ChangelogRelease } from "@/lib/app/changelog"; +import { formatAiInlineMarkdownFragment, handleAiMarkdownLinkClick } from "@/lib/ai/aiMarkdown"; +import { changelogLangFromLocale, changelogReleaseUrl, changelogWebsiteUrl, createLatestRequestGuard, fetchChangelog, type ChangelogItem, type ChangelogLang, type ChangelogRelease } from "@/lib/app/changelog"; const PAGE_SIZE = 5; @@ -80,6 +81,11 @@ function openExternalUrl(url: string) { } } +function formatChangelogItemHtml(item: ChangelogItem): string { + const title = formatAiInlineMarkdownFragment(item.title); + return item.desc ? `${title} — ${formatAiInlineMarkdownFragment(item.desc)}` : title; +} + function isExpanded(tag: string) { return expandedTags.value.has(tag); } @@ -193,10 +199,7 @@ watch(changelogLang, (lang) => { diff --git a/apps/desktop/src/lib/__tests__/ai/aiMarkdown.spec.ts b/apps/desktop/src/lib/__tests__/ai/aiMarkdown.spec.ts index 212cf10fee..b03a3f7575 100644 --- a/apps/desktop/src/lib/__tests__/ai/aiMarkdown.spec.ts +++ b/apps/desktop/src/lib/__tests__/ai/aiMarkdown.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { aiMarkdownLinkUrlFromClick, formatAiInlineMarkdown, handleAiMarkdownLinkClick, normalizeAiMarkdownLink } from "@/lib/ai/aiMarkdown"; +import { aiMarkdownLinkUrlFromClick, formatAiInlineMarkdown, formatAiInlineMarkdownFragment, handleAiMarkdownLinkClick, normalizeAiMarkdownLink } from "@/lib/ai/aiMarkdown"; describe("formatAiInlineMarkdown", () => { it("renders http links for external browser handling", () => { @@ -26,6 +26,24 @@ describe("formatAiInlineMarkdown", () => { }); }); +describe("formatAiInlineMarkdownFragment", () => { + it("renders single-line content without a block paragraph wrapper", () => { + const html = formatAiInlineMarkdownFragment("Title — see [PR #1](https://example.com/pull/1) and `code`."); + + expect(html).not.toContain("

"); + expect(html).toContain('href="https://example.com/pull/1"'); + expect(html).toContain(" { + const html = formatAiInlineMarkdownFragment(""); + + expect(html).toContain("<script>alert(1)</script>"); + expect(html).not.toContain("