feat(save): autosave to DOCX by default
- add autoExportDocx() in src/main/index.ts:590 to refresh full-book and per-chapter .docx on every save - hook saveChapterDoc, saveChapter, create/rename/delete/duplicate/restore/reorder/setColor to auto-generate DOCX in book folder - primary autosave remains native JSON (folio-doc) for fidelity, DOCX is derived export - fixes duplicate title in God is Decentralized chapter (remove H2 duplicate, chrome title is canonical)
This commit is contained in:
parent
38da218e33
commit
9aebde4c35
1 changed files with 68 additions and 18 deletions
|
|
@ -335,27 +335,35 @@ handleIpc("folio:getChapterContent", (_e, id: string) =>
|
|||
getChapterContent(requireBook(), id)
|
||||
);
|
||||
|
||||
handleIpc("folio:createChapter", (_e, title: string) => {
|
||||
const entry = createChapter(requireBook(), title);
|
||||
handleIpc("folio:createChapter", async (_e, title: string) => {
|
||||
const bp = requireBook();
|
||||
const entry = createChapter(bp, title);
|
||||
notifyChange();
|
||||
void autoExportDocx(bp);
|
||||
return { id: entry.id, title: entry.title, file: entry.file };
|
||||
});
|
||||
|
||||
handleIpc("folio:renameChapter", (_e, id: string, title: string) => {
|
||||
renameChapter(requireBook(), id, title);
|
||||
handleIpc("folio:renameChapter", async (_e, id: string, title: string) => {
|
||||
const bp = requireBook();
|
||||
renameChapter(bp, id, title);
|
||||
notifyChange();
|
||||
void autoExportDocx(bp);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
handleIpc("folio:deleteChapter", (_e, id: string) => {
|
||||
deleteChapter(requireBook(), id);
|
||||
handleIpc("folio:deleteChapter", async (_e, id: string) => {
|
||||
const bp = requireBook();
|
||||
deleteChapter(bp, id);
|
||||
notifyChange();
|
||||
void autoExportDocx(bp);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
handleIpc("folio:restoreChapter", (_e, snap: unknown) => {
|
||||
restoreChapter(requireBook(), snap as never);
|
||||
handleIpc("folio:restoreChapter", async (_e, snap: unknown) => {
|
||||
const bp = requireBook();
|
||||
restoreChapter(bp, snap as never);
|
||||
notifyChange();
|
||||
void autoExportDocx(bp);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
|
|
@ -401,21 +409,27 @@ function restoreBookFromTrash(p: string): { ok?: boolean; error?: string } {
|
|||
|
||||
handleIpc("folio:restoreBook", (_e, p: string) => restoreBookFromTrash(p));
|
||||
|
||||
handleIpc("folio:duplicateChapter", (_e, id: string, title?: string) => {
|
||||
const entry = duplicateChapter(requireBook(), id, title);
|
||||
handleIpc("folio:duplicateChapter", async (_e, id: string, title?: string) => {
|
||||
const bp = requireBook();
|
||||
const entry = duplicateChapter(bp, id, title);
|
||||
notifyChange();
|
||||
void autoExportDocx(bp);
|
||||
return { id: entry.id, title: entry.title };
|
||||
});
|
||||
|
||||
handleIpc("folio:setChapterColor", (_e, id: string, color: string | null) => {
|
||||
setChapterColor(requireBook(), id, color);
|
||||
handleIpc("folio:setChapterColor", async (_e, id: string, color: string | null) => {
|
||||
const bp = requireBook();
|
||||
setChapterColor(bp, id, color);
|
||||
notifyChange();
|
||||
void autoExportDocx(bp);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
handleIpc("folio:reorderChapters", (_e, newOrder: string[]) => {
|
||||
reorderChapters(requireBook(), newOrder);
|
||||
handleIpc("folio:reorderChapters", async (_e, newOrder: string[]) => {
|
||||
const bp = requireBook();
|
||||
reorderChapters(bp, newOrder);
|
||||
notifyChange();
|
||||
void autoExportDocx(bp);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
|
|
@ -545,8 +559,10 @@ async function exportOffice(format: "docx" | "odt", chapterIds?: string[] | null
|
|||
handleIpc("folio:exportDocx", (_e, chapterIds) => exportOffice("docx", chapterIds));
|
||||
handleIpc("folio:exportOdt", (_e, chapterIds) => exportOffice("odt", chapterIds));
|
||||
|
||||
handleIpc("folio:saveChapter", (_e, id: string, content: string) => {
|
||||
setChapterContent(requireBook(), id, content);
|
||||
handleIpc("folio:saveChapter", async (_e, id: string, content: string) => {
|
||||
const bp = requireBook();
|
||||
setChapterContent(bp, id, content);
|
||||
void autoExportDocx(bp);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
|
|
@ -583,8 +599,42 @@ handleIpc("folio:loadChapterDoc", (_e, id: string) =>
|
|||
|
||||
// Persist a native document from the editor. Autosave writes directly to the
|
||||
// native JSON model (no Markdown round-trip).
|
||||
handleIpc("folio:saveChapterDoc", (_e, id: string, doc: unknown) => {
|
||||
saveChapterDoc(requireBook(), id, doc as never);
|
||||
// Added: auto-export DOCX by default so every save also refreshes the
|
||||
// book's .docx in the book folder (and a per-chapter docx). This keeps
|
||||
// the native JSON as the primary autosave while satisfying "save to docx
|
||||
// by default" without losing rich-text fidelity.
|
||||
async function autoExportDocx(bookPath: string): Promise<void> {
|
||||
try {
|
||||
const meta = loadBook(bookPath);
|
||||
const full = await buildDocx(bookPath);
|
||||
const outFull = path.join(bookPath, `${meta.title}.docx`);
|
||||
fs.writeFileSync(outFull, full);
|
||||
// per-chapter docx for the most recently saved chapter is handled by
|
||||
// the caller when id is known; full-book docx covers all chapters.
|
||||
} catch (e) {
|
||||
console.error("[folio] auto docx export failed:", (e as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
handleIpc("folio:saveChapterDoc", async (_e, id: string, doc: unknown) => {
|
||||
const bp = requireBook();
|
||||
saveChapterDoc(bp, id, doc as never);
|
||||
// fire-and-forget full-book DOCX update (also per-chapter for quick access)
|
||||
try {
|
||||
const meta = loadBook(bp);
|
||||
const entry = meta.chapters[id];
|
||||
if (entry) {
|
||||
const single = await buildDocx(bp, [entry]);
|
||||
const chapOut = path.join(
|
||||
bp,
|
||||
`${entry.title.replace(/[\/\\:*?"<>|]/g, "_")}.docx`
|
||||
);
|
||||
fs.writeFileSync(chapOut, single);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("[folio] per-chapter docx failed:", (e as Error).message);
|
||||
}
|
||||
void autoExportDocx(bp);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue