78 lines
2.5 KiB
TypeScript
78 lines
2.5 KiB
TypeScript
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<Buffer | null>;
|
|
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<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 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 };
|
|
}
|