Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 1bf5096d17eb06612adce750ed4b85c7b15f8359
parent f911fb85f95e590fc807d9f049bb1434d7678218
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Sun,  4 Oct 2026 20:13:50 -0400

common: the post viewer's capture panel shows the article's title and a link to article.md

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Mcommon/components/PostModal.test.ts | 14++++++++++++++
Mcommon/components/PostModal.tsx | 24+++++++++++++++++++++---
Mcommon/jobs/jobKinds.ts | 9+++++----
3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/common/components/PostModal.test.ts b/common/components/PostModal.test.ts @@ -55,6 +55,20 @@ test("without media or a shot (a deleted post's record): nothing at all", () => assert.equal(render({ ...BASE, state: "deleted" }), ""); }); +test("an article: its title and a link to its markdown; a failed one says how, with no link", () => { + const html = render({ + ...BASE, + shot: { src: "/s.png" }, + article: { state: "captured", title: "A Long <Read>", md: { src: "/capture/demo/1/article.md" } }, + }); + assert.match(html, /data-post-capture-article=""[^>]*>Article: A Long &lt;Read&gt;/); + assert.match(html, /<a href="\/capture\/demo\/1\/article\.md"[^>]*>article\.md<\/a>/); + + const failed = render({ ...BASE, article: { state: "login-wall" } }); + assert.match(failed, /Article: untitled \(login-wall\)/); + assert.doesNotMatch(failed, /article\.md/); +}); + test("media kinds by extension", () => { assert.equal(captureMediaKind("a.JPG"), "image"); assert.equal(captureMediaKind("a.webp"), "image"); diff --git a/common/components/PostModal.tsx b/common/components/PostModal.tsx @@ -46,6 +46,9 @@ export type PostCaptureView = { sensitive?: boolean; shot?: { src: string }; media: { src: string; name: string }[]; + // The X Article the post links to, when the capture opened it: its title, + // how that went, and its markdown when saved. + article?: { state: string; title?: string; md?: { src: string } }; }; export type PostModalProps = { @@ -265,16 +268,31 @@ export function captureMediaKind(name: string): "image" | "video" | "other" { return "other"; } -// The captured screenshot and media of one post. Nothing when the capture -// holds neither (a deleted post's record, say). +// The captured screenshot and media of one post, and a line for its article. +// Nothing when the capture holds none of them (a deleted post's record, say). export function PostCapturePanel({ capture }: { capture: PostCaptureView }) { - if (!capture.shot && capture.media.length === 0) return null; + const { article } = capture; + if (!capture.shot && capture.media.length === 0 && !article) return null; return ( <section data-post-capture="" className="mt-3 flex flex-col gap-2"> <h3 className="text-xs uppercase tracking-wide text-muted-foreground"> Captured {formatWhen(capture.capturedAt)} {capture.sensitive ? " · behind a sensitive-media cover" : ""} </h3> + {article && ( + <p data-post-capture-article="" className="text-xs text-muted-foreground"> + Article: {article.title ?? "untitled"} + {article.state !== "captured" ? ` (${article.state})` : ""} + {article.md && ( + <> + {" · "} + <a href={article.md.src} className="text-primary underline"> + article.md + </a> + </> + )} + </p> + )} {capture.shot && ( <img src={capture.shot.src} diff --git a/common/jobs/jobKinds.ts b/common/jobs/jobKinds.ts @@ -523,10 +523,11 @@ const JOB_KINDS: Record<string, JobKindMeta> = { replayable: true, queueKeyStrategy: "platform", }, - // A screenshot and the attached media of specific archived posts, into the - // channel's `posts-media/` (controller/capturePosts.ts). On the PLATFORM - // queue, like fetch-posts: each post is a page load and a download against - // the same source, so it serialises with the fetch and shares its backoff. + // A screenshot and the attached media of specific archived posts (and the X + // Article a post links to), into the channel's `posts-media/` + // (controller/capturePosts.ts). On the PLATFORM queue, like fetch-posts: + // each post is a page load and a download against the same source, so it + // serialises with the fetch and shares its backoff. // Drainable (it stops between posts) and replayable (the ids are in the // spec; posts already captured are skipped on a re-run). "capture-posts": {