59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { fromPromise } from "xstate";
|
|
import { TFile, Vault } from "obsidian";
|
|
import { format, parse } from "@formkit/tempo";
|
|
import { ContentNode, Lifelog } from "./query.ts";
|
|
|
|
interface WriteInput {
|
|
vault: Vault;
|
|
lifelog: Lifelog;
|
|
rootDir: string;
|
|
}
|
|
|
|
// We could just use the markdown output, but the heading levels
|
|
// are one unit too high, and we don't need the timestamp links
|
|
function formatContentBlock(content: ContentNode): string {
|
|
let markdown = "";
|
|
|
|
if (content.type.startsWith("heading")) {
|
|
const [, level] = content.type.split("heading");
|
|
const levelNum = Number(level);
|
|
|
|
markdown += `${"#".repeat(levelNum + 1)} ${content.content}`;
|
|
} else if (content.type === "blockquote") {
|
|
markdown += `> ${content.speakerName}: ${content.content}`;
|
|
}
|
|
|
|
for (const node of content?.children ?? []) {
|
|
markdown += `\n\n${formatContentBlock(node)}`;
|
|
}
|
|
|
|
return markdown;
|
|
}
|
|
|
|
export const writeLifelog = fromPromise(
|
|
async ({ input }: { input: WriteInput }) => {
|
|
const { vault, lifelog, rootDir } = input;
|
|
const start = parse(lifelog.startTime);
|
|
const markdown = lifelog.contents.reduce((str, content) => {
|
|
return str + `\n\n${formatContentBlock(content)}`;
|
|
}, "");
|
|
|
|
const folder = `${rootDir}/${format(start, "YYYY-MM")}`;
|
|
const file = `${format(start, "DD")}.md`;
|
|
|
|
const dir = vault.getAbstractFileByPath(folder);
|
|
if (dir === null) {
|
|
await vault.createFolder(folder);
|
|
}
|
|
|
|
const abstract = vault.getAbstractFileByPath(`${folder}/${file}`);
|
|
if (abstract instanceof TFile) {
|
|
await vault.append(abstract, markdown);
|
|
} else {
|
|
const page = `# ${format(start, "YYYY-MM-DD")}\n\n${markdown}`;
|
|
await vault.create(`${folder}/${file}`, page);
|
|
}
|
|
|
|
return parse(lifelog.endTime);
|
|
},
|
|
);
|