add preview to posts

This commit is contained in:
liyunze 2026-09-02 21:57:04 +08:00
parent b499a5fb61
commit 503c44ac17
9 changed files with 59 additions and 0 deletions

View file

@ -1,10 +1,12 @@
<script lang="ts">
import { previewMarkdown } from "$lib/markdown";
import { unitPath } from "$lib/paths";
import VoteStack from "./VoteStack.svelte";
let {
href,
title,
content,
unitCode,
meta,
voteCount = 0,
@ -14,6 +16,7 @@
}: {
href: string;
title: string;
content?: string;
unitCode?: string;
meta: string;
voteCount?: number;
@ -40,6 +43,11 @@
>
{title}
</a>
{#if content?.trim()}
<p class="text-muted mt-1 line-clamp-2 text-sm leading-relaxed">
{previewMarkdown(content)}
</p>
{/if}
<p class="kicker mt-1.5">{meta}</p>
</div>
</article>

14
src/lib/markdown.spec.ts Normal file
View file

@ -0,0 +1,14 @@
import { describe, expect, it } from "vitest";
import { previewMarkdown } from "./markdown";
describe("previewMarkdown", () => {
it("returns readable text without markdown formatting", () => {
expect(previewMarkdown("# Heading\n\nA **bold** [link](https://example.com).")).toBe(
"Heading A bold link.",
);
});
it("includes code and truncates long previews", () => {
expect(previewMarkdown("Use `const value = 1` here.", 18)).toBe("Use const value =…");
});
});

View file

@ -9,3 +9,30 @@ const md = new MarkdownIt({
export function renderMarkdown(source: string): string {
return md.render(source ?? "");
}
export function previewMarkdown(source: string, maxLength = 180): string {
const text = md
.parse(source ?? "", {})
.map((token) => {
console.log(token);
if (token.type === "inline") {
return (token.children ?? [])
.filter((child) => child.type !== "image")
.map((child) =>
child.type === "softbreak" || child.type === "hardbreak"
? " "
: child.content,
)
.join("");
}
if (token.type === "fence" || token.type === "code_block") return token.content;
return "";
})
.join(" ")
.replace(/\s+/g, " ")
.trim();
if (text.length <= maxLength) return text;
return `${text.slice(0, Math.max(0, maxLength - 1)).trimEnd()}`;
}

View file

@ -82,6 +82,7 @@
<FeedRow
href={postPath(note.unit!.code, note._id)}
title={note.title}
content={note.content}
unitCode={note.unit
? note.unit.code + (note.unit.code2 ? ` / ${note.unit.code2}` : "")
: undefined}

View file

@ -89,6 +89,7 @@
<FeedRow
href={postPath(question.unit!.code, question._id)}
title={question.title}
content={question.content}
unitCode={question.unit
? question.unit.code + (question.unit.code2 ? ` / ${question.unit.code2}` : "")
: undefined}

View file

@ -54,6 +54,7 @@
<FeedRow
href={postPath(result.unit!.code, result._id)}
title={result.title}
content={result.content}
unitCode={result.unit
? result.unit.code + (result.unit.code2 ? ` / ${result.unit.code2}` : "")
: undefined}
@ -69,6 +70,7 @@
<FeedRow
href={postPath(result.unit!.code, result._id)}
title={result.title}
content={result.content}
unitCode={result.unit
? result.unit.code + (result.unit.code2 ? ` / ${result.unit.code2}` : "")
: undefined}

View file

@ -48,6 +48,7 @@
<FeedRow
href={postPath(note.unit!.code, note._id)}
title={note.title}
content={note.content}
unitCode={note.unit
? note.unit.code + (note.unit.code2 ? ` / ${note.unit.code2}` : "")
: undefined}
@ -67,6 +68,7 @@
<FeedRow
href={postPath(question.unit!.code, question._id)}
title={question.title}
content={question.content}
unitCode={question.unit
? question.unit.code +
(question.unit.code2 ? ` / ${question.unit.code2}` : "")

View file

@ -94,6 +94,7 @@
<FeedRow
href={postPath(selectedUnit.code, note._id)}
title={note.title}
content={note.content}
unitCode={selectedUnit.code +
(selectedUnit.code2 ? ` / ${selectedUnit.code2}` : "")}
meta="{note.authorName} · {timeAgo(
@ -114,6 +115,7 @@
<FeedRow
href={postPath(selectedUnit.code, question._id)}
title={question.title}
content={question.content}
unitCode={selectedUnit.code +
(selectedUnit.code2 ? ` / ${selectedUnit.code2}` : "")}
meta="{question.authorName} · {timeAgo(

View file

@ -51,6 +51,7 @@
<FeedRow
href={postPath(unit.code, note._id)}
title={note.title}
content={note.content}
unitCode={unit.code + (unit.code2 ? ` / ${unit.code2}` : "")}
meta="{note.authorName} · {timeAgo(
note.createdAt,
@ -68,6 +69,7 @@
<FeedRow
href={postPath(unit.code, question._id)}
title={question.title}
content={question.content}
unitCode={unit.code + (unit.code2 ? ` / ${unit.code2}` : "")}
meta="{question.authorName} · {timeAgo(
question.createdAt,