Add Gruvbox share theme + blog system for Trilium (anonymized)
Blog generator, publish manager, share scripts, theme CSS, highlight.js bundles, font, favicon, templates and generated-reference outputs, plus an English installation guide.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user