feat: publish orchestrator wiring transforms to GitClient

Co-Authored-By: Claude
This commit is contained in:
2026-06-19 02:12:58 +00:00
parent d0aafa1aa0
commit 62ae955044
2 changed files with 137 additions and 0 deletions

72
src/publish.ts Normal file
View File

@@ -0,0 +1,72 @@
import { parseNote, Pair } from "./frontmatter";
import { buildPost } from "./buildPost";
import { postFilename } from "./slug";
import { findImageRefs, planImages, Strategy } from "./images";
import { GitClient, GitFile } from "./git";
import { JekyllPublishSettings } from "./settings";
export interface PublishInput {
noteText: string;
frontmatterPairs: Pair[];
slug: string;
date: string;
strategy: Strategy;
commitMessage: string;
}
export type ImageResolver = (linktext: string) => Promise<Buffer | null>;
export interface PublishResult {
postPath: string;
imageCount: number;
unresolved: string[];
}
export async function publish(
input: PublishInput,
settings: JekyllPublishSettings,
git: GitClient,
resolveImage: ImageResolver
): Promise<PublishResult> {
if (!settings.remoteUrl.trim()) throw new Error("No git remote URL configured");
const { body } = parseNote(input.noteText);
const refs = findImageRefs(body);
const resolved: { linktext: string; data: Buffer }[] = [];
const unresolved: string[] = [];
for (const ref of refs) {
if (resolved.some((r) => r.linktext === ref.linktext)) continue;
const data = await resolveImage(ref.linktext);
if (data) resolved.push({ linktext: ref.linktext, data });
else unresolved.push(ref.linktext);
}
const usableRefs = refs.filter((r) => resolved.some((x) => x.linktext === r.linktext));
const { rewrittenBody, plan } = planImages(usableRefs, {
slug: input.slug,
strategy: input.strategy,
imagesDir: settings.imagesDir,
body,
});
const postText = buildPost({ frontmatterPairs: input.frontmatterPairs, body: rewrittenBody });
const postPath = `${settings.postsDir}/${postFilename({ date: input.date, slug: input.slug })}`;
const files: GitFile[] = [{ repoPath: postPath, data: postText }];
for (const item of plan) {
const r = resolved.find((x) => x.linktext === item.linktext)!;
files.push({ repoPath: item.repoPath, data: r.data });
}
await git.syncClone({ url: settings.remoteUrl, branch: settings.branch });
await git.writeFiles(files);
await git.commitAndPush({
message: input.commitMessage,
branch: settings.branch,
authorName: settings.authorName || undefined,
authorEmail: settings.authorEmail || undefined,
});
return { postPath, imageCount: plan.length, unresolved };
}