feat: show source-qualified author names
This commit is contained in:
@@ -8,6 +8,10 @@
|
||||
|
||||
- Constrained remote Memos avatars to a fixed, cropped size so oversized source images cannot break dashboard or source-page layouts.
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed homepage author labels for Memos and Hub-to-Memos posts from duplicated source names to `@name@source-hostname` identities.
|
||||
|
||||
## [0.8.0] - 2026-07-19
|
||||
|
||||
### Added
|
||||
|
||||
@@ -2,10 +2,11 @@ import Link from "next/link";
|
||||
import { Attachments } from "./attachments";
|
||||
import { Markdown } from "./markdown";
|
||||
import { canonicalTags } from "@/lib/tags";
|
||||
import { postAuthorLabel } from "@/lib/display";
|
||||
|
||||
export type PublicPost = { id: number; source_id: number | null; origin: string; content: string; tags_json: string; attachments_json: string; created_at: string; remote_created_at?: string | null; username: string; name: string | null; remote_display_name?: string | null; source_base_url: string | null; comment_count: number; reaction_count: number };
|
||||
|
||||
export function PostCard({ post }: { post: PublicPost }) {
|
||||
let tags: string[] = []; try { tags = canonicalTags(JSON.parse(post.tags_json)); } catch { /* Ignore malformed legacy tags. */ }
|
||||
const publishedAt = post.remote_created_at || post.created_at; const author = post.origin === "memos" ? (post.remote_display_name || post.name || post.username) : (post.name || post.username); return <article className="card"><div className="space"><Link className="meta post-name-link" href={`/posts/${post.id}`}>@{author}{post.name ? ` · ${post.name}` : ""}</Link><span className="meta">{new Date(publishedAt).toLocaleString("zh-TW")}</span></div><Markdown content={post.content} tags={tags} compact /><Attachments json={post.attachments_json} sourceBaseUrl={post.source_base_url} compact /><div className="row">{tags.map((tag) => <Link className="tag" href={`/tags/${encodeURIComponent(tag)}`} key={tag}>#{tag}</Link>)}{post.source_id && <Link className="tag" href={`/sources/${post.source_id}`}>來源</Link>}<Link href={`/posts/${post.id}`}>閱讀全文 · 💬 {post.comment_count} 🙂 {post.reaction_count}</Link></div></article>;
|
||||
const publishedAt = post.remote_created_at || post.created_at; return <article className="card"><div className="space"><Link className="meta post-name-link" href={`/posts/${post.id}`}>{postAuthorLabel(post)}</Link><span className="meta">{new Date(publishedAt).toLocaleString("zh-TW")}</span></div><Markdown content={post.content} tags={tags} compact /><Attachments json={post.attachments_json} sourceBaseUrl={post.source_base_url} compact /><div className="row">{tags.map((tag) => <Link className="tag" href={`/tags/${encodeURIComponent(tag)}`} key={tag}>#{tag}</Link>)}{post.source_id && <Link className="tag" href={`/sources/${post.source_id}`}>來源</Link>}<Link href={`/posts/${post.id}`}>閱讀全文 · 💬 {post.comment_count} 🙂 {post.reaction_count}</Link></div></article>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
export type AuthorDisplay = {
|
||||
origin: string;
|
||||
username: string;
|
||||
name: string | null;
|
||||
remote_display_name?: string | null;
|
||||
source_base_url: string | null;
|
||||
};
|
||||
|
||||
export function postAuthorLabel(post: AuthorDisplay) {
|
||||
const linkedMemos = post.origin === "memos" || post.origin === "hub";
|
||||
const author = linkedMemos ? (post.remote_display_name || post.name || post.username) : (post.name || post.username);
|
||||
if (linkedMemos && post.source_base_url) {
|
||||
try { return `@${author}@${new URL(post.source_base_url).hostname}`; } catch { /* Keep a readable fallback for legacy malformed URLs. */ }
|
||||
}
|
||||
return `@${author}${post.name ? ` · ${post.name}` : ""}`;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
import { postAuthorLabel } from "../lib/display";
|
||||
|
||||
test("formats Memos authors as name at source hostname", () => {
|
||||
assert.equal(postAuthorLabel({ origin: "memos", username: "hub-user", name: "codex", remote_display_name: "codex", source_base_url: "https://memos.fishking.studio/path" }), "@codex@memos.fishking.studio");
|
||||
});
|
||||
|
||||
test("formats Hub posts linked to Memos with the same source identity", () => {
|
||||
assert.equal(postAuthorLabel({ origin: "hub", username: "codex", name: "codex", remote_display_name: "codex", source_base_url: "https://memos.fishking.studio" }), "@codex@memos.fishking.studio");
|
||||
});
|
||||
|
||||
test("keeps the existing label for non-Memos posts", () => {
|
||||
assert.equal(postAuthorLabel({ origin: "hub", username: "codex", name: "Hub", source_base_url: null }), "@Hub · Hub");
|
||||
});
|
||||
Reference in New Issue
Block a user