const BLOG_ROOT_ID = "__BLOG_ROOT_ID__"; const UNPUBLISHED_ROOT_ID = "__UNPUBLISHED_ROOT_ID__"; const BLOG_GENERATOR_ID = "__BLOG_GENERATOR_ID__"; const entity = api.originEntity; if (!entity) return; function findOrCreateChild(parentId, title, iconClass) { const parent = api.getNote(parentId); let child = parent.getChildNotes().find(n => n.title === title); if (!child) { const created = api.createTextNote(parentId, title, ""); child = created.note ? created.note : created; if (iconClass) child.setLabel("iconClass", iconClass); child.save(); return { noteId: child.noteId, created: true }; } if (child.hasLabel("blogCategory") && iconClass && child.getLabelValue("iconClass") !== iconClass) { child.setLabel("iconClass", iconClass); child.save(); } return { noteId: child.noteId, created: false }; } function mirrorPath(note, sourceRootId, targetRootId) { const chain = []; let current = note; let guard = 0; while (current && guard++ < 20) { const parents = current.getParentNotes().filter(p => p.noteId === sourceRootId || p.hasAncestor(sourceRootId)); if (parents.length === 0) break; const parent = parents[0]; if (parent.noteId === sourceRootId) break; chain.unshift(parent); current = parent; } let target = targetRootId; const createdIds = []; for (const folder of chain) { const res = findOrCreateChild(target, folder.title, folder.getLabelValue("iconClass")); if (res.created) createdIds.push(res.noteId); target = res.noteId; } return { target, createdIds }; } function blogParentsOf(note) { return note.getParentNotes().filter(p => p.noteId === BLOG_ROOT_ID || p.hasAncestor(BLOG_ROOT_ID)); } function runGenerator() { const gen = api.getNote(BLOG_GENERATOR_ID); if (gen) gen.executeScript(); } function slugify(s) { return String(s).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""); } function ensureAlias(note) { if (note.getLabelValue("shareAlias")) return; const base = slugify(note.title) || "post"; let alias = base; let i = 2; while (api.getNotesWithLabel("shareAlias", alias).some(n => n.noteId !== note.noteId)) { alias = base + "-" + i++; } note.setLabel("shareAlias", alias); note.save(); api.log("blog_publish_manager: assigned shareAlias '" + alias + "' to '" + note.title + "'"); } if (entity.type === "label" && entity.name === "publish") { const note = api.getNote(entity.noteId); if (!note) return; const isPublished = note.getLabelValue("publish") === "true"; if (isPublished) ensureAlias(note); const underBlog = note.hasAncestor(BLOG_ROOT_ID); const underUnpublished = note.hasAncestor(UNPUBLISHED_ROOT_ID); if (isPublished && underUnpublished && !underBlog) { const res = mirrorPath(note, UNPUBLISHED_ROOT_ID, BLOG_ROOT_ID); api.ensureNoteIsPresentInParent(note.noteId, res.target); for (const id of res.createdIds) { api.getNote(id).setLabel("blogCategory", ""); } api.log("blog_publish_manager: cloned note '" + note.title + "' to blog"); runGenerator(); } else if (!isPublished && underBlog) { if (underUnpublished) { for (const p of blogParentsOf(note)) { api.ensureNoteIsAbsentFromParent(note.noteId, p.noteId); } api.log("blog_publish_manager: removed clone of '" + note.title + "' from blog"); } else { const res = mirrorPath(note, BLOG_ROOT_ID, UNPUBLISHED_ROOT_ID); api.ensureNoteIsPresentInParent(note.noteId, res.target); for (const p of blogParentsOf(note)) { api.ensureNoteIsAbsentFromParent(note.noteId, p.noteId); } api.log("blog_publish_manager: moved note '" + note.title + "' back to unpublished"); } runGenerator(); } }