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,14 @@
|
||||
<script>
|
||||
(function () {
|
||||
document.addEventListener("click", function (e) {
|
||||
if (e.defaultPrevented) return;
|
||||
var card = e.target.closest(".blog-post");
|
||||
if (!card) return;
|
||||
if (e.target.closest("a")) return;
|
||||
var link = card.querySelector(".blog-post-title a");
|
||||
if (!link) return;
|
||||
e.preventDefault();
|
||||
window.location.href = link.getAttribute("href");
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,45 @@
|
||||
<script>
|
||||
(function () {
|
||||
var pane = document.getElementById("left-pane");
|
||||
if (!pane) return;
|
||||
|
||||
var items = [];
|
||||
var menu = document.getElementById("menu");
|
||||
if (menu) {
|
||||
var links = menu.querySelectorAll('a[href="./aboutme"], a[href="./impressum"]');
|
||||
links.forEach(function (a) {
|
||||
var li = a.closest("li");
|
||||
if (li) items.push(li);
|
||||
});
|
||||
}
|
||||
|
||||
var rssLink = '<a class="bmc-link" href="./feed"><i class="tn-icon bx bx-rss"></i><span>RSS Feed</span></a>';
|
||||
|
||||
var nav = document.createElement("nav");
|
||||
nav.id = "bmc-links";
|
||||
var inner = "";
|
||||
items.forEach(function (li) {
|
||||
var a = li.querySelector("a");
|
||||
if (a) {
|
||||
var icon = a.querySelector(".tn-icon");
|
||||
var iconHtml = icon ? icon.outerHTML : "";
|
||||
var text = (a.querySelector("span") || a).textContent.trim();
|
||||
if (text === "Impressum") {
|
||||
inner += rssLink;
|
||||
}
|
||||
inner += '<a class="bmc-link" href="' + a.getAttribute("href") + '">' + iconHtml + '<span>' + text + '</span></a>';
|
||||
}
|
||||
li.remove();
|
||||
});
|
||||
nav.innerHTML = inner;
|
||||
pane.appendChild(nav);
|
||||
|
||||
var wrap = document.createElement("div");
|
||||
wrap.id = "bmc-wrap";
|
||||
wrap.innerHTML =
|
||||
'<a class="bmc-btn" href="https://www.buymeacoffee.com/YOUR-USERNAME" target="_blank" rel="noopener noreferrer">' +
|
||||
'<span class="bmc-emoji">\u2615</span><span class="bmc-text">Buy me a coffee</span></a>' +
|
||||
'<div class="bmc-copyright">\u00a9 ' + new Date().getFullYear() + ' Your Name \u00b7 Powered by <a class="bmc-powered" href="https://triliumnotes.org"><svg class="powered-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" aria-hidden="true"><style> .st0{fill:#95C980;} .st1{fill:#72B755;} .st2{fill:#4FA52B;} .st3{fill:#EE8C89;} .st4{fill:#E96562;} .st5{fill:#E33F3B;} .st6{fill:#EFB075;} .st7{fill:#E99547;} .st8{fill:#E47B19;} </style><g><path class="st0" d="m202.9 112.7c-22.5 16.1-54.5 12.8-74.9 6.3l14.8-11.8 14.1-11.3 49.1-39.3-51.2 35.9-14.3 10-14.9 10.5c0.7-21.2 7-49.9 28.6-65.4 1.8-1.3 3.9-2.6 6.1-3.8 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.4 2.8-4.9 5.4-7.4 7.8-3.4 3.5-6.8 6.4-10.1 8.8z"/><path class="st1" d="m213.1 104c-22.2 12.6-51.4 9.3-70.3 3.2l14.1-11.3 49.1-39.3-51.2 35.9-14.3 10c0.5-18.1 4.9-42.1 19.7-58.6 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.3 2.8-4.8 5.4-7.2 7.8z"/><path class="st2" d="m220.5 96.2c-21.1 8.6-46.6 5.3-63.7-0.2l49.2-39.4-51.2 35.9c0.3-15.8 3.5-36.6 14.3-52.8 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.8 66z"/><path class="st3" d="m106.7 179c-5.8-21 5.2-43.8 15.5-57.2l4.8 14.2 4.5 13.4 15.9 47-12.8-47.6-3.6-13.2-3.7-13.9c15.5 6.2 35.1 18.6 40.7 38.8 0.5 1.7 0.9 3.6 1.2 5.5 0.4 2.4 0.6 5 0.7 7.7 0.9 23.1-7.1 54.9-15.9 65.7-12-4.3-29.3-24-39.7-42.8-1.4-2.6-2.7-5.1-3.8-7.6-1.6-3.5-2.9-6.8-3.8-10z"/><path class="st4" d="m110.4 188.9c-3.4-19.8 6.9-40.5 16.6-52.9l4.5 13.4 15.9 47-12.8-47.6-3.6-13.2c13.3 5.2 29.9 15 38.1 30.4 0.4 2.4 0.6 5 0.7 7.7 0.9 23.1-7.1 54.9-15.9 65.7-12-4.3-29.3-24-39.7-42.8-1.4-2.6-2.7-5.2-3.8-7.7z"/><path class="st5" d="m114.2 196.5c-0.7-18 8.6-35.9 17.3-47.1l15.9 47-12.8-47.6c11.6 4.4 26.1 12.4 35.2 24.8 0.9 23.1-7.1 54.9-15.9 65.7-12-4.3-29.3-24-39.7-42.8z"/><path class="st6" d="m86.3 59.1c21.7 10.9 32.4 36.6 35.8 54.9l-15.2-6.6-14.5-6.3-50.6-22 48.8 24.9 13.6 6.9 14.3 7.3c-16.6 7.9-41.3 14.5-62.1 4.1-1.8-0.9-3.6-1.9-5.4-3.2-2.3-1.5-4.5-3.2-6.8-5.1-19.9-16.4-40.3-46.4-42.7-61.5 12.4-6.5 41.5-5.8 64.8-0.3 3.2 0.8 6.2 1.6 9.1 2.5 4 1.3 7.6 2.8 10.9 4.4z"/><path class="st7" d="m75.4 54.8c18.9 12 28.4 35.6 31.6 52.6l-14.5-6.3-50.6-22 48.7 24.9 13.6 6.9c-14.1 6.8-34.5 13-53.3 8.2-2.3-1.5-4.5-3.2-6.8-5.1-19.8-16.4-40.2-46.4-42.6-61.5 12.4-6.5 41.5-5.8 64.8-0.3 3.1 0.8 6.2 1.6 9.1 2.6z"/><path class="st8" d="m66.3 52.2c15.3 12.8 23.3 33.6 26.1 48.9l-50.6-22 48.8 24.9c-12.2 6-29.6 11.8-46.5 10-19.8-16.4-40.2-46.4-42.6-61.5 12.4-6.5 41.5-5.8 64.8-0.3z"/></g></svg> Trilium</a></div>';
|
||||
pane.appendChild(wrap);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,45 @@
|
||||
<script>
|
||||
(function () {
|
||||
function codeText(code) {
|
||||
var ln = code.querySelectorAll(".hljs-ln .hljs-ln-code");
|
||||
if (ln.length) {
|
||||
var parts = [];
|
||||
for (var i = 0; i < ln.length; i++) parts.push(ln[i].textContent);
|
||||
return parts.join("\n");
|
||||
}
|
||||
return code.textContent;
|
||||
}
|
||||
|
||||
document.querySelectorAll("#content pre").forEach(function (pre) {
|
||||
if (pre.classList.contains("code-processed")) return;
|
||||
var code = pre.querySelector("code");
|
||||
if (!code) return;
|
||||
pre.classList.add("code-processed");
|
||||
|
||||
var btn = document.createElement("button");
|
||||
btn.className = "code-copy-btn";
|
||||
btn.type = "button";
|
||||
btn.textContent = "Copy";
|
||||
btn.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
var text = codeText(code);
|
||||
function copied() {
|
||||
btn.textContent = "Copied!";
|
||||
setTimeout(function () { btn.textContent = "Copy"; }, 1500);
|
||||
}
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(copied);
|
||||
} else {
|
||||
var ta = document.createElement("textarea");
|
||||
ta.value = text;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(ta);
|
||||
copied();
|
||||
}
|
||||
});
|
||||
pre.appendChild(btn);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,32 @@
|
||||
<script>
|
||||
(function () {
|
||||
var codes = document.querySelectorAll("#content pre code:not(.language-mermaid)");
|
||||
if (!codes.length) return;
|
||||
|
||||
function apply() {
|
||||
if (!window.hljs) return;
|
||||
codes.forEach(function (c) {
|
||||
c.classList.add("hljs");
|
||||
hljs.highlightElement(c);
|
||||
if (window.hljs.lineNumbersBlock) {
|
||||
hljs.lineNumbersBlock(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadPlugin() {
|
||||
if (window.hljs && window.hljs.lineNumbersBlock) { apply(); return; }
|
||||
var s = document.createElement("script");
|
||||
s.src = "api/notes/__HLJS_LN_ID__/download";
|
||||
s.onload = apply;
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
|
||||
if (window.hljs) { loadPlugin(); return; }
|
||||
|
||||
var s = document.createElement("script");
|
||||
s.src = "api/notes/__HLJS_ID__/download";
|
||||
s.onload = loadPlugin;
|
||||
document.head.appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,10 @@
|
||||
<style>
|
||||
html.theme-dark #content h1 {
|
||||
background-color: rgba(184, 187, 38, 0.80) !important;
|
||||
border-bottom-color: rgba(184, 187, 38, 0.95) !important;
|
||||
}
|
||||
html.theme-light #content h1 {
|
||||
background-color: rgba(184, 187, 38, 0.55) !important;
|
||||
border-bottom-color: rgba(184, 187, 38, 0.8) !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,14 @@
|
||||
<script>
|
||||
(function () {
|
||||
document.addEventListener("click", function (e) {
|
||||
if (e.defaultPrevented) return;
|
||||
var row = e.target.closest(".blog-garden-table tbody tr");
|
||||
if (!row) return;
|
||||
if (e.target.closest("a")) return;
|
||||
var link = row.querySelector("a");
|
||||
if (!link) return;
|
||||
e.preventDefault();
|
||||
window.location.href = link.getAttribute("href");
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1 @@
|
||||
<style>#content h1#title { display: none; }</style>
|
||||
@@ -0,0 +1,10 @@
|
||||
<script>
|
||||
(function () {
|
||||
var logo = document.getElementById("header-logo");
|
||||
if (!logo) return;
|
||||
var h = logo.getAttribute("href");
|
||||
if (h && h.indexOf("__BLOG_ROOT_ID__") !== -1) {
|
||||
logo.setAttribute("href", "./blog");
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,407 @@
|
||||
<script>
|
||||
(function () {
|
||||
var content = document.getElementById("content");
|
||||
if (!content) return;
|
||||
var m = document.body.className.match(/type-([\w-]+)/);
|
||||
var type = m ? m[1] : "";
|
||||
var widgetTypes = ["mermaid", "canvas", "mindMap", "webView", "relationMap", "spreadsheet", "search", "geo"];
|
||||
if (widgetTypes.indexOf(type) === -1) return;
|
||||
if (content.querySelector("svg, iframe, canvas, .excalidraw, .mindmap, .mermaid")) return;
|
||||
|
||||
var clone = content.cloneNode(true);
|
||||
clone.querySelectorAll("script, style, nav, a, .blog-prevnext, .reading-time").forEach(function (el) { el.remove(); });
|
||||
var raw = (clone.textContent || "").trim();
|
||||
if (!raw) return;
|
||||
|
||||
function makePre(text) {
|
||||
var pre = document.createElement("pre");
|
||||
pre.className = "note-fallback";
|
||||
var code = document.createElement("code");
|
||||
code.className = "language-json";
|
||||
code.textContent = text;
|
||||
pre.appendChild(code);
|
||||
applyHighlight(code);
|
||||
return pre;
|
||||
}
|
||||
|
||||
var hljsLoading = false;
|
||||
function applyHighlight(codeEl) {
|
||||
if (window.hljs) {
|
||||
codeEl.classList.add("hljs");
|
||||
try { hljs.highlightElement(codeEl); } catch (e) {}
|
||||
if (window.hljs.lineNumbersBlock) {
|
||||
try { hljs.lineNumbersBlock(codeEl); } catch (e) {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (hljsLoading) {
|
||||
setTimeout(function () { applyHighlight(codeEl); }, 200);
|
||||
return;
|
||||
}
|
||||
hljsLoading = true;
|
||||
var s = document.createElement("script");
|
||||
s.src = "api/notes/__HLJS_ID__/download";
|
||||
s.onload = function () {
|
||||
if (window.hljs && window.hljs.lineNumbersBlock) { applyHighlight(codeEl); return; }
|
||||
var p = document.createElement("script");
|
||||
p.src = "api/notes/__HLJS_LN_ID__/download";
|
||||
p.onload = function () { applyHighlight(codeEl); };
|
||||
document.head.appendChild(p);
|
||||
};
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
|
||||
if (type === "mermaid") {
|
||||
content.querySelectorAll("img, hr").forEach(function (el) { el.remove(); });
|
||||
var nativePre = content.querySelector("pre");
|
||||
if (!nativePre) return;
|
||||
var src = nativePre.textContent;
|
||||
if (!src.trim()) return;
|
||||
var nativeDetails = nativePre.closest("details");
|
||||
|
||||
var wrapper = document.createElement("div");
|
||||
wrapper.className = "mermaid-render";
|
||||
var diagram = document.createElement("div");
|
||||
diagram.className = "mermaid-diagram";
|
||||
var details = document.createElement("details");
|
||||
details.className = "mermaid-source";
|
||||
var summary = document.createElement("summary");
|
||||
summary.textContent = "Source";
|
||||
var pre = document.createElement("pre");
|
||||
var code = document.createElement("code");
|
||||
code.textContent = src;
|
||||
pre.appendChild(code);
|
||||
addCopyButton(pre, src);
|
||||
details.appendChild(summary);
|
||||
details.appendChild(pre);
|
||||
wrapper.appendChild(diagram);
|
||||
wrapper.appendChild(details);
|
||||
(nativeDetails || nativePre).replaceWith(wrapper);
|
||||
applyHighlight(code);
|
||||
|
||||
var MMD_DARK = {
|
||||
background: "transparent",
|
||||
textColor: "#ebdbb2",
|
||||
titleColor: "#fbf1c7",
|
||||
lineColor: "#a89984",
|
||||
edgeLabelBackground: "#3c3836",
|
||||
nodeTextColor: "#fbf1c7",
|
||||
primaryColor: "#458588", primaryTextColor: "#fbf1c7", primaryBorderColor: "#458588",
|
||||
secondaryColor: "#b8bb26", secondaryTextColor: "#1d2021", secondaryBorderColor: "#b8bb26",
|
||||
tertiaryColor: "#d3869b", tertiaryTextColor: "#1d2021", tertiaryBorderColor: "#d3869b"
|
||||
};
|
||||
var MMD_LIGHT = {
|
||||
background: "transparent",
|
||||
textColor: "#3c3836",
|
||||
titleColor: "#282828",
|
||||
lineColor: "#928374",
|
||||
edgeLabelBackground: "#ebdbb2",
|
||||
nodeTextColor: "#1d2021",
|
||||
primaryColor: "#83a598", primaryTextColor: "#1d2021", primaryBorderColor: "#076678",
|
||||
secondaryColor: "#98971a", secondaryTextColor: "#fbf1c7", secondaryBorderColor: "#79740e",
|
||||
tertiaryColor: "#b16286", tertiaryTextColor: "#fbf1c7", tertiaryBorderColor: "#8f3f71"
|
||||
};
|
||||
function mermaidConfig() {
|
||||
var light = document.documentElement.classList.contains("theme-light");
|
||||
return { startOnLoad: false, theme: "base", themeVariables: light ? MMD_LIGHT : MMD_DARK };
|
||||
}
|
||||
function renderMermaid() {
|
||||
import("/assets/mermaid.core-BUJU3YJZ.js").then(function (mod) {
|
||||
var mermaid = mod.default;
|
||||
mermaid.initialize(mermaidConfig());
|
||||
return mermaid.render("mm-" + Date.now(), src);
|
||||
}).then(function (res) {
|
||||
diagram.innerHTML = res.svg;
|
||||
diagram.querySelectorAll(".node rect, .cluster rect").forEach(function (r) {
|
||||
var rad = Math.min(8, Math.min(parseFloat(r.getAttribute("width") || 50), parseFloat(r.getAttribute("height") || 50)) * 0.15);
|
||||
r.setAttribute("rx", rad);
|
||||
r.setAttribute("ry", rad);
|
||||
});
|
||||
}).catch(function () {
|
||||
diagram.textContent = src;
|
||||
});
|
||||
}
|
||||
renderMermaid();
|
||||
var themeInput = document.querySelector(".theme-selection input");
|
||||
if (themeInput) {
|
||||
themeInput.addEventListener("change", renderMermaid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === "webView") {
|
||||
var p = document.createElement("p");
|
||||
p.className = "note-fallback note-fallback-link";
|
||||
p.innerHTML = "Embedded page: <a href=\"" + raw + "\" target=\"_blank\" rel=\"noopener noreferrer\">" + raw + "</a>";
|
||||
content.appendChild(p);
|
||||
return;
|
||||
}
|
||||
|
||||
var NS = "http://www.w3.org/2000/svg";
|
||||
function svgEl(name, attrs) {
|
||||
var n = document.createElementNS(NS, name);
|
||||
for (var k in attrs) n.setAttribute(k, attrs[k]);
|
||||
return n;
|
||||
}
|
||||
|
||||
function fallbackCopy(text, done) {
|
||||
var ta = document.createElement("textarea");
|
||||
ta.value = text;
|
||||
ta.style.position = "fixed";
|
||||
ta.style.opacity = "0";
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
try { document.execCommand("copy"); } catch (e) {}
|
||||
document.body.removeChild(ta);
|
||||
done();
|
||||
}
|
||||
function addCopyButton(pre, text) {
|
||||
var btn = document.createElement("button");
|
||||
btn.className = "code-copy-btn";
|
||||
btn.type = "button";
|
||||
btn.textContent = "Copy";
|
||||
btn.addEventListener("click", function () {
|
||||
var done = function () {
|
||||
btn.textContent = "Copied";
|
||||
setTimeout(function () { btn.textContent = "Copy"; }, 1500);
|
||||
};
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(done, function () { fallbackCopy(text, done); });
|
||||
} else {
|
||||
fallbackCopy(text, done);
|
||||
}
|
||||
});
|
||||
pre.appendChild(btn);
|
||||
}
|
||||
function makeSourceDetails(text) {
|
||||
var details = document.createElement("details");
|
||||
details.className = "mermaid-source";
|
||||
var summary = document.createElement("summary");
|
||||
summary.textContent = "Source";
|
||||
var pre = document.createElement("pre");
|
||||
var code = document.createElement("code");
|
||||
code.className = "language-json";
|
||||
code.textContent = text;
|
||||
pre.appendChild(code);
|
||||
addCopyButton(pre, text);
|
||||
details.appendChild(summary);
|
||||
details.appendChild(pre);
|
||||
applyHighlight(code);
|
||||
return details;
|
||||
}
|
||||
|
||||
/* ---------- MindMap (MindElixir data) ---------- */
|
||||
var MIND_DARK = [
|
||||
{ bg: "#458588", bd: "#3a6b70", text: "#fbf1c7" },
|
||||
{ bg: "#b8bb26", bd: "#98971a", text: "#1d2021" },
|
||||
{ bg: "#d3869b", bd: "#b16286", text: "#1d2021" },
|
||||
{ bg: "#8ec07c", bd: "#689d6a", text: "#1d2021" },
|
||||
{ bg: "#fe8019", bd: "#d65d0e", text: "#1d2021" }
|
||||
];
|
||||
var MIND_LIGHT = [
|
||||
{ bg: "#83a598", bd: "#458588", text: "#1d2021" },
|
||||
{ bg: "#98971a", bd: "#79740e", text: "#fbf1c7" },
|
||||
{ bg: "#b16286", bd: "#8f3f71", text: "#fbf1c7" },
|
||||
{ bg: "#427b58", bd: "#3a6350", text: "#fbf1c7" },
|
||||
{ bg: "#af3a03", bd: "#8f3003", text: "#fbf1c7" }
|
||||
];
|
||||
function mindPalette() {
|
||||
return document.documentElement.classList.contains("theme-light") ? MIND_LIGHT : MIND_DARK;
|
||||
}
|
||||
function mindEdgeColor() {
|
||||
return document.documentElement.classList.contains("theme-light") ? "#928374" : "#a89984";
|
||||
}
|
||||
function mindSize(topic, fontSize) {
|
||||
var lines = String(topic || "").split("\n");
|
||||
var w = 0;
|
||||
for (var i = 0; i < lines.length; i++) w = Math.max(w, lines[i].length * fontSize * 0.62);
|
||||
return { w: Math.max(w + 24, 56), h: Math.max(lines.length * (fontSize + 6) + 10, 32) };
|
||||
}
|
||||
function mindSubHeight(n, depth) {
|
||||
n.depth = depth;
|
||||
var fs = depth === 0 ? 16 : 14;
|
||||
n.box = mindSize(n.topic, fs);
|
||||
if (n.children && n.children.length) {
|
||||
var sum = 0;
|
||||
for (var i = 0; i < n.children.length; i++) sum += mindSubHeight(n.children[i], depth + 1);
|
||||
n.childSpan = sum + (n.children.length - 1) * 18;
|
||||
n.total = Math.max(n.box.h, n.childSpan);
|
||||
} else {
|
||||
n.total = n.box.h;
|
||||
}
|
||||
return n.total;
|
||||
}
|
||||
function mindPlace(n, x, side, yTop) {
|
||||
n.x = x - n.box.w / 2;
|
||||
n.y = yTop + (n.total - n.box.h) / 2;
|
||||
if (!n.children || !n.children.length) return;
|
||||
var cursor = yTop;
|
||||
for (var i = 0; i < n.children.length; i++) {
|
||||
var c = n.children[i];
|
||||
var childSide = side === 0 ? (i % 2 === 0 ? -1 : 1) : side;
|
||||
var childX = x + childSide * (n.box.w / 2 + 46 + c.box.w / 2);
|
||||
mindPlace(c, childX, childSide, cursor);
|
||||
cursor += c.total + 18;
|
||||
}
|
||||
}
|
||||
function renderMindMap(nodeData) {
|
||||
var wrap = document.createElement("div");
|
||||
wrap.className = "mindmap-render";
|
||||
var root = nodeData;
|
||||
mindSubHeight(root, 0);
|
||||
mindPlace(root, 0, 0, -root.total / 2);
|
||||
var minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9;
|
||||
(function walk(n) {
|
||||
minX = Math.min(minX, n.x); maxX = Math.max(maxX, n.x + n.box.w);
|
||||
minY = Math.min(minY, n.y); maxY = Math.max(maxY, n.y + n.box.h);
|
||||
if (n.children) n.children.forEach(walk);
|
||||
})(root);
|
||||
var pad = 34;
|
||||
var MIND = mindPalette();
|
||||
var EDGE = mindEdgeColor();
|
||||
var W = maxX - minX + pad * 2, H = maxY - minY + pad * 2;
|
||||
var svg = svgEl("svg", { class: "mindmap-svg", viewBox: (minX - pad) + " " + (minY - pad) + " " + W + " " + H, width: W, height: H });
|
||||
function draw(n) {
|
||||
var col = MIND[Math.min(n.depth, MIND.length - 1)];
|
||||
var g = svgEl("g");
|
||||
g.appendChild(svgEl("rect", { x: n.x, y: n.y, width: n.box.w, height: n.box.h, rx: 8, fill: col.bg, stroke: col.bd, "stroke-width": 1.5 }));
|
||||
var lines = String(n.topic || "").split("\n");
|
||||
var fs = n.depth === 0 ? 16 : 14;
|
||||
var lh = fs + 5;
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var t = svgEl("text", { x: n.x + n.box.w / 2, y: n.y + n.box.h / 2 - ((lines.length - 1) * lh) / 2 + i * lh, "text-anchor": "middle", "dominant-baseline": "central", "font-size": fs, fill: col.text, "font-family": "sans-serif" });
|
||||
t.textContent = lines[i];
|
||||
g.appendChild(t);
|
||||
}
|
||||
svg.appendChild(g);
|
||||
if (n.children) n.children.forEach(function (c) {
|
||||
var sy = n.y + n.box.h / 2, ey = c.y + c.box.h / 2;
|
||||
var sx = c.x > n.x ? n.x + n.box.w : n.x;
|
||||
var ex = c.x > n.x ? c.x : c.x + c.box.w;
|
||||
var dir = ex >= sx ? 1 : -1;
|
||||
var dx = Math.max(26, Math.min(56, Math.abs(ex - sx) * 0.4));
|
||||
var lead = dx * 0.5;
|
||||
svg.appendChild(svgEl("path", {
|
||||
d: "M " + sx + " " + sy +
|
||||
" L " + (sx + dir * lead) + " " + sy +
|
||||
" C " + (sx + dir * dx) + " " + sy + " " + (ex - dir * dx) + " " + ey + " " + (ex - dir * lead) + " " + ey +
|
||||
" L " + ex + " " + ey,
|
||||
fill: "none", stroke: EDGE, "stroke-width": 2.5,
|
||||
"stroke-linecap": "round", "stroke-linejoin": "round"
|
||||
}));
|
||||
draw(c);
|
||||
});
|
||||
}
|
||||
draw(root);
|
||||
wrap.appendChild(svg);
|
||||
return wrap;
|
||||
}
|
||||
|
||||
/* ---------- Canvas (Excalidraw) ---------- */
|
||||
function renderExcalidraw(elements) {
|
||||
var wrap = document.createElement("div");
|
||||
wrap.className = "excalidraw-render";
|
||||
var els = elements.filter(function (e) { return e && !e.isDeleted; });
|
||||
if (!els.length) { wrap.textContent = "Empty canvas"; return wrap; }
|
||||
var pad = 40;
|
||||
var minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9;
|
||||
els.forEach(function (e) {
|
||||
minX = Math.min(minX, e.x); minY = Math.min(minY, e.y);
|
||||
maxX = Math.max(maxX, e.x + e.width); maxY = Math.max(maxY, e.y + e.height);
|
||||
});
|
||||
var W = maxX - minX + pad * 2, H = maxY - minY + pad * 2;
|
||||
var svg = svgEl("svg", { class: "excalidraw-svg", viewBox: (minX - pad) + " " + (minY - pad) + " " + W + " " + H, width: W, height: H });
|
||||
els.forEach(function (e) {
|
||||
var g = svgEl("g");
|
||||
if (e.angle) g.setAttribute("transform", "rotate(" + (e.angle * 180 / Math.PI) + " " + (e.x + e.width / 2) + " " + (e.y + e.height / 2) + ")");
|
||||
if (typeof e.opacity === "number" && e.opacity < 100) g.setAttribute("opacity", e.opacity / 100);
|
||||
var sc = e.strokeColor || "#282828", bg = e.backgroundColor || "transparent", sw = Math.max(1, e.strokeWidth || 2);
|
||||
var filled = bg && bg !== "transparent";
|
||||
var fillOp = e.fillStyle === "solid" ? 1 : 0.35;
|
||||
function strokeShape(shape) {
|
||||
if (filled) { shape.setAttribute("fill", bg); shape.setAttribute("fill-opacity", fillOp); }
|
||||
else shape.setAttribute("fill", "none");
|
||||
shape.setAttribute("stroke", sc); shape.setAttribute("stroke-width", sw);
|
||||
g.appendChild(shape);
|
||||
}
|
||||
if (e.type === "rectangle") {
|
||||
strokeShape(svgEl("rect", { x: e.x, y: e.y, width: e.width, height: e.height, rx: Math.min(8, Math.min(e.width, e.height) * 0.08) }));
|
||||
} else if (e.type === "ellipse") {
|
||||
strokeShape(svgEl("ellipse", { cx: e.x + e.width / 2, cy: e.y + e.height / 2, rx: e.width / 2, ry: e.height / 2 }));
|
||||
} else if (e.type === "diamond") {
|
||||
var cx = e.x + e.width / 2, cy = e.y + e.height / 2;
|
||||
strokeShape(svgEl("polygon", { points: cx + "," + e.y + " " + (e.x + e.width) + "," + cy + " " + cx + "," + (e.y + e.height) + " " + e.x + "," + cy }));
|
||||
} else if (e.type === "line" || e.type === "arrow") {
|
||||
var pts = e.points || [];
|
||||
if (!pts.length) return;
|
||||
var coords = pts.map(function (pt) { return (e.x + pt[0]) + "," + (e.y + pt[1]); }).join(" ");
|
||||
strokeShape(svgEl("polyline", { points: coords }));
|
||||
if (e.type === "arrow" && pts.length > 1) {
|
||||
var last = pts[pts.length - 1], prev = pts[pts.length - 2];
|
||||
var ang = Math.atan2(last[1] - prev[1], last[0] - prev[0]);
|
||||
var ax = e.x + last[0], ay = e.y + last[1], al = 9 + sw;
|
||||
g.appendChild(svgEl("polygon", { points: (ax + Math.cos(ang) * al) + "," + (ay + Math.sin(ang) * al) + " " + (ax + Math.cos(ang + 2.6) * al * 0.6) + "," + (ay + Math.sin(ang + 2.6) * al * 0.6) + " " + (ax + Math.cos(ang - 2.6) * al * 0.6) + "," + (ay + Math.sin(ang - 2.6) * al * 0.6), fill: sc, stroke: sc }));
|
||||
}
|
||||
} else if (e.type === "freedraw") {
|
||||
var fpts = e.points || [];
|
||||
if (!fpts.length) return;
|
||||
strokeShape(svgEl("path", { d: "M " + fpts.map(function (pt) { return (e.x + pt[0]) + "," + (e.y + pt[1]); }).join(" L "), "stroke-linecap": "round", "stroke-linejoin": "round" }));
|
||||
} else if (e.type === "text") {
|
||||
var fs = e.fontSize || 20;
|
||||
var ff = e.fontFamily === 2 ? "sans-serif" : (e.fontFamily === 3 ? "monospace" : "'Comic Sans MS','Comic Sans',cursive");
|
||||
var ta = e.textAlign === "left" ? "start" : (e.textAlign === "right" ? "end" : "middle");
|
||||
var x = ta === "middle" ? e.x + e.width / 2 : e.x;
|
||||
var y = e.verticalAlign === "top" ? e.y + fs * 0.8 : e.y + e.height / 2 + fs * 0.35;
|
||||
var lines = String(e.text || "").split("\n");
|
||||
var t = svgEl("text", { x: x, y: y, "font-size": fs, fill: sc, "font-family": ff, "text-anchor": ta });
|
||||
for (var li = 0; li < lines.length; li++) {
|
||||
var ts = document.createElementNS(NS, "tspan");
|
||||
ts.setAttribute("x", x);
|
||||
ts.setAttribute("dy", li === 0 ? 0 : fs * 1.2);
|
||||
ts.textContent = lines[li];
|
||||
t.appendChild(ts);
|
||||
}
|
||||
g.appendChild(t);
|
||||
}
|
||||
svg.appendChild(g);
|
||||
});
|
||||
wrap.appendChild(svg);
|
||||
return wrap;
|
||||
}
|
||||
|
||||
/* content per Download-Endpoint holen */
|
||||
var noteId = document.body.getAttribute("data-note-id");
|
||||
var box = document.createElement("div");
|
||||
var prevnext = content.querySelector(".blog-prevnext");
|
||||
if (prevnext) { content.insertBefore(box, prevnext); }
|
||||
else { content.appendChild(box); }
|
||||
|
||||
function renderWidget() {
|
||||
fetch("api/notes/" + noteId + "/download")
|
||||
.then(function (r) { return r.text(); })
|
||||
.then(function (text) {
|
||||
var pretty = text, data = null;
|
||||
try { data = JSON.parse(text); pretty = JSON.stringify(data, null, 2); } catch (e) {}
|
||||
box.innerHTML = "";
|
||||
var rendered = null;
|
||||
if (data && type === "mindMap" && data.nodeData) rendered = renderMindMap(data.nodeData);
|
||||
else if (data && type === "canvas" && Array.isArray(data.elements)) rendered = renderExcalidraw(data.elements);
|
||||
if (rendered) {
|
||||
rendered.appendChild(makeSourceDetails(pretty));
|
||||
box.appendChild(rendered);
|
||||
} else {
|
||||
box.appendChild(makePre(pretty));
|
||||
box.appendChild(makeSourceDetails(pretty));
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
box.textContent = "Content not available.";
|
||||
});
|
||||
}
|
||||
renderWidget();
|
||||
var widgetThemeInput = document.querySelector(".theme-selection input");
|
||||
if (widgetThemeInput) {
|
||||
widgetThemeInput.addEventListener("change", renderWidget);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,33 @@
|
||||
<script>
|
||||
(function () {
|
||||
var data = window.blogData;
|
||||
if (!data || !data.articles || !data.articles.length) return;
|
||||
var id = document.body.getAttribute("data-note-id");
|
||||
var list = data.articles;
|
||||
var idx = -1;
|
||||
for (var i = 0; i < list.length; i++) { if (list[i].id === id) { idx = i; break; } }
|
||||
if (idx < 0) return;
|
||||
var builtin = document.querySelector("#content-footer .navigation");
|
||||
if (builtin) builtin.style.display = "none";
|
||||
var content = document.getElementById("content");
|
||||
if (!content) return;
|
||||
var prev = idx + 1 < list.length ? list[idx + 1] : null;
|
||||
var next = idx > 0 ? list[idx - 1] : null;
|
||||
if (!prev && !next) return;
|
||||
var box = document.createElement("nav");
|
||||
box.className = "blog-prevnext";
|
||||
var inner = "";
|
||||
if (prev) {
|
||||
inner += '<a class="blog-pn prev" href="' + prev.url + '"><span class="blog-pn-label">Previous</span><span class="blog-pn-title">' + prev.title + '</span></a>';
|
||||
} else {
|
||||
inner += '<span class="blog-pn empty"></span>';
|
||||
}
|
||||
if (next) {
|
||||
inner += '<a class="blog-pn next" href="' + next.url + '"><span class="blog-pn-label">Next</span><span class="blog-pn-title">' + next.title + '</span></a>';
|
||||
} else {
|
||||
inner += '<span class="blog-pn empty"></span>';
|
||||
}
|
||||
box.innerHTML = inner;
|
||||
content.appendChild(box);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,18 @@
|
||||
<script>
|
||||
(function () {
|
||||
var content = document.getElementById("content");
|
||||
if (!content) return;
|
||||
if (!document.body.classList.contains("type-text")) return;
|
||||
if (content.querySelector(".blog-post") || content.querySelector(".blog-garden-table") || content.querySelector(".blog-subcategories") || content.querySelector(".blog-search")) return;
|
||||
var clone = content.cloneNode(true);
|
||||
clone.querySelectorAll("script, style, pre, code, nav, a, .blog-prevnext").forEach(function (el) { el.remove(); });
|
||||
var words = (clone.textContent || "").trim().split(/\s+/).filter(Boolean).length;
|
||||
var mins = Math.max(1, Math.round(words / 200));
|
||||
var title = document.getElementById("title");
|
||||
if (!title) return;
|
||||
var p = document.createElement("div");
|
||||
p.className = "reading-time";
|
||||
p.textContent = mins + " min read";
|
||||
title.parentNode.insertBefore(p, title.nextSibling);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,48 @@
|
||||
<script>
|
||||
(function () {
|
||||
var old = document.querySelector(".search-item .search-input");
|
||||
if (!old) return;
|
||||
var box = old.closest(".search-item") || old.parentNode;
|
||||
|
||||
var input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.className = "blog-search-header-input";
|
||||
input.placeholder = old.placeholder || "Search...";
|
||||
old.replaceWith(input);
|
||||
|
||||
var overlay = document.createElement("div");
|
||||
overlay.className = "blog-search-overlay";
|
||||
box.appendChild(overlay);
|
||||
|
||||
function render(q) {
|
||||
q = (q || "").toLowerCase().trim();
|
||||
if (!q) { overlay.innerHTML = ""; overlay.classList.remove("open"); return; }
|
||||
var articles = (window.blogData && window.blogData.articles) || [];
|
||||
var hits = articles.filter(function (a) {
|
||||
var hay = (a.title + " " + (a.summary || "") + " " + (a.tags || []).join(" ")).toLowerCase();
|
||||
return hay.indexOf(q) !== -1;
|
||||
});
|
||||
if (!hits.length) {
|
||||
overlay.innerHTML = '<div class="blog-search-none">No results.</div>';
|
||||
} else {
|
||||
overlay.innerHTML = hits.slice(0, 8).map(function (a) {
|
||||
return '<a class="blog-search-overlay-hit" href="' + a.url + '"><span class="t">' + a.title + '</span>' +
|
||||
(a.summary ? '<span class="s">' + a.summary + '</span>' : '') + '</a>';
|
||||
}).join("");
|
||||
}
|
||||
overlay.classList.add("open");
|
||||
}
|
||||
|
||||
var t;
|
||||
input.addEventListener("input", function () {
|
||||
clearTimeout(t);
|
||||
t = setTimeout(function () { render(input.value); }, 150);
|
||||
});
|
||||
input.addEventListener("focus", function () { if (input.value.trim()) render(input.value); });
|
||||
input.addEventListener("blur", function () { setTimeout(function () { overlay.classList.remove("open"); }, 150); });
|
||||
input.addEventListener("keydown", function (e) { if (e.key === "Escape") { overlay.classList.remove("open"); } });
|
||||
document.addEventListener("click", function (e) {
|
||||
if (!box.contains(e.target)) overlay.classList.remove("open");
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,27 @@
|
||||
<script>
|
||||
(function () {
|
||||
function clearColHover(table) {
|
||||
table.querySelectorAll(".col-hover").forEach(function (el) {
|
||||
el.classList.remove("col-hover");
|
||||
});
|
||||
}
|
||||
document.addEventListener("mouseover", function (e) {
|
||||
var cell = e.target.closest("td, th");
|
||||
if (!cell) return;
|
||||
var table = cell.closest("table");
|
||||
if (!table) return;
|
||||
clearColHover(table);
|
||||
var idx = cell.cellIndex;
|
||||
table.querySelectorAll("tr").forEach(function (tr) {
|
||||
var c = tr.children[idx];
|
||||
if (c) c.classList.add("col-hover");
|
||||
});
|
||||
});
|
||||
document.addEventListener("mouseout", function (e) {
|
||||
var table = e.target.closest("table");
|
||||
if (table && !table.contains(e.relatedTarget)) {
|
||||
clearColHover(table);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,39 @@
|
||||
<script>
|
||||
(function () {
|
||||
var states = window.blogStates || {};
|
||||
var id = document.body.getAttribute("data-note-id");
|
||||
if (!id || !states[id]) return;
|
||||
var state = states[id];
|
||||
var s = String(state).toLowerCase();
|
||||
document.body.classList.add("is-garden");
|
||||
function inject() {
|
||||
var title = document.getElementById("title");
|
||||
if (!title) return;
|
||||
var icons = {
|
||||
"seed": "bx bxs-coffee-bean",
|
||||
"seedling": "bx bxs-coffee-bean",
|
||||
"sprout": "bx bxs-leaf",
|
||||
"sprouting": "bx bxs-leaf",
|
||||
"bud": "bx bxs-leaf",
|
||||
"evergreen": "bx bxs-tree-alt",
|
||||
"draft": "bx bx-edit",
|
||||
"review": "bx bx-search-alt"
|
||||
};
|
||||
var growth = ["seed", "seedling", "sprout", "sprouting", "bud", "evergreen"];
|
||||
var cls;
|
||||
if (growth.indexOf(s) >= 0) cls = "state-growth";
|
||||
else if (s === "draft") cls = "state-draft";
|
||||
else if (s === "review") cls = "state-review";
|
||||
else cls = "state-unknown";
|
||||
var badge = document.createElement("span");
|
||||
badge.className = "note-state " + cls;
|
||||
badge.innerHTML = '<i class="' + (icons[s] || "bx bxs-circle") + '"></i>' + state;
|
||||
title.appendChild(badge);
|
||||
}
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", inject);
|
||||
} else {
|
||||
inject();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user