import { parseNote, Pair } from "./frontmatter"; import { buildPost } from "./buildPost"; import { pageFilename } 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; export type PublishEventsListener = (on: 'beforeClone' | 'beforeWrite' | 'beforePush') => void; export interface PublishResult { postPath: string; imageCount: number; unresolved: string[]; } export async function publish( input: PublishInput, settings: JekyllPublishSettings, git: GitClient, imageResolver: ImageResolver, onProgress?: PublishEventsListener ): Promise { 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 imageResolver(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 notePath = `${settings.publishDir}/${pageFilename({ date: input.date, slug: input.slug })}`; const files: GitFile[] = [{ repoPath: notePath, data: postText }]; for (const item of plan) { const r = resolved.find((x) => x.linktext === item.linktext)!; files.push({ repoPath: item.repoPath, data: r.data }); } onProgress?.('beforeClone'); await git.syncClone({ url: settings.remoteUrl, branch: settings.branch }); onProgress?.('beforeWrite'); await git.writeFiles(files); onProgress?.('beforePush'); await git.commitAndPush({ message: input.commitMessage, branch: settings.branch, authorName: settings.authorName || undefined, authorEmail: settings.authorEmail || undefined, }); return { postPath: notePath, imageCount: plan.length, unresolved }; }