This commit is contained in:
0
assets/images/blogs/2026-05-08-time-to-100m-pic.webp
Normal file → Executable file
0
assets/images/blogs/2026-05-08-time-to-100m-pic.webp
Normal file → Executable file
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
@@ -704,7 +704,7 @@ APP_HTML = r"""<!doctype html>
|
||||
button { border: 1px solid var(--line); background: #fff; color: var(--ink); min-height: 38px; padding: 0 12px; border-radius: 6px; cursor: pointer; }
|
||||
button.primary { background: var(--accent); color: white; border-color: var(--accent); }
|
||||
button.icon { min-width: 38px; padding: 0 10px; font-weight: 700; }
|
||||
.app { min-height: 100vh; display: grid; grid-template-columns: minmax(260px, 360px) 1fr; }
|
||||
.app { min-height: 100vh; display: grid; grid-template-columns: minmax(300px, 420px) 1fr; }
|
||||
aside { border-right: 1px solid var(--line); background: #eee8dc; padding: 18px; overflow: auto; max-height: 100vh; }
|
||||
main { padding: 20px clamp(18px, 3vw, 42px); overflow: auto; max-height: 100vh; }
|
||||
.topbar { display: flex; align-items: center; gap: 10px; justify-content: space-between; margin-bottom: 16px; }
|
||||
@@ -716,10 +716,23 @@ APP_HTML = r"""<!doctype html>
|
||||
.status.fail { border-color: #a12a2a; }
|
||||
.quick-link { display: inline-block; color: var(--accent); font-size: 13px; margin: -6px 0 14px; }
|
||||
.filters { display: grid; gap: 8px; margin-bottom: 14px; }
|
||||
.page-list { display: grid; gap: 7px; }
|
||||
.page-item { width: 100%; text-align: left; min-height: auto; padding: 9px 10px; background: var(--panel); }
|
||||
.page-list { display: grid; gap: 3px; }
|
||||
.tree-dir { margin: 1px 0; }
|
||||
.tree-dir summary { list-style: none; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: center; min-height: 34px; padding: 6px 8px; border-radius: 6px; cursor: pointer; color: var(--ink); }
|
||||
.tree-dir summary::-webkit-details-marker { display: none; }
|
||||
.tree-dir summary:hover, .page-item:hover { background: rgba(255, 253, 248, 0.78); }
|
||||
.tree-dir summary::before { content: ">"; display: inline-block; width: 14px; color: var(--muted); }
|
||||
.tree-dir[open] > summary::before { content: "v"; }
|
||||
.tree-label { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
|
||||
.tree-label strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
|
||||
.tree-label span { color: var(--muted); font-size: 12px; white-space: nowrap; }
|
||||
.tree-children { display: grid; gap: 2px; margin-left: 15px; padding-left: 10px; border-left: 1px solid var(--line); }
|
||||
.tree-add { min-height: 28px; padding: 0 8px; font-size: 12px; color: var(--accent); background: transparent; }
|
||||
.page-item { width: 100%; text-align: left; min-height: auto; padding: 8px 10px; background: transparent; }
|
||||
.page-item.active { border-color: var(--accent); background: var(--panel); }
|
||||
.page-item strong { display: block; font-size: 14px; margin-bottom: 2px; overflow-wrap: anywhere; }
|
||||
.page-item span { display: block; color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }
|
||||
.page-item .filename { color: var(--ink); }
|
||||
form { display: grid; gap: 14px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
|
||||
.toolbar { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; border: 1px solid var(--line); background: var(--panel); border-radius: 6px; padding: 7px; }
|
||||
@@ -924,19 +937,111 @@ APP_HTML = r"""<!doctype html>
|
||||
const matches = state.pages
|
||||
.filter((page) => (!type || page.pageType === type))
|
||||
.filter((page) => `${page.title} ${page.path} ${page.tags.join(" ")}`.toLowerCase().includes(query))
|
||||
.slice(0, 120);
|
||||
.sort((a, b) => a.path.localeCompare(b.path));
|
||||
if (!matches.length) {
|
||||
pagesBox.innerHTML = `<div class="queue-item"><span>No files matched.</span></div>`;
|
||||
renderStatus();
|
||||
return;
|
||||
}
|
||||
matches.forEach((page) => {
|
||||
const tree = buildPageTree(matches);
|
||||
renderTree(tree, pagesBox, query !== "");
|
||||
renderStatus();
|
||||
}
|
||||
|
||||
function buildPageTree(pages) {
|
||||
const root = { dirs: new Map(), pages: [], path: "" };
|
||||
pages.forEach((page) => {
|
||||
const parts = page.path.split("/");
|
||||
const filename = parts.pop();
|
||||
let node = root;
|
||||
let dirPath = "";
|
||||
parts.forEach((part) => {
|
||||
dirPath = dirPath ? `${dirPath}/${part}` : part;
|
||||
if (!node.dirs.has(part)) node.dirs.set(part, { dirs: new Map(), pages: [], path: dirPath });
|
||||
node = node.dirs.get(part);
|
||||
});
|
||||
node.pages.push({ ...page, filename });
|
||||
});
|
||||
return root;
|
||||
}
|
||||
|
||||
function renderTree(node, container, expandAll = false) {
|
||||
[...node.dirs.entries()]
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.forEach(([name, child]) => container.appendChild(renderDirectory(name, child, expandAll)));
|
||||
node.pages
|
||||
.sort((a, b) => a.filename.localeCompare(b.filename))
|
||||
.forEach((page) => container.appendChild(renderPageButton(page)));
|
||||
}
|
||||
|
||||
function renderDirectory(name, node, expandAll) {
|
||||
const details = document.createElement("details");
|
||||
details.className = "tree-dir";
|
||||
details.open = expandAll || node.path.split("/").length <= 2 || containsCurrentPath(node);
|
||||
|
||||
const summary = document.createElement("summary");
|
||||
const label = document.createElement("span");
|
||||
label.className = "tree-label";
|
||||
label.innerHTML = `<strong>${html(name)}</strong><span>${countPages(node)} files</span>`;
|
||||
const add = document.createElement("button");
|
||||
add.type = "button";
|
||||
add.className = "tree-add";
|
||||
add.textContent = "New";
|
||||
add.title = `New file in ${node.path}`;
|
||||
add.onclick = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
newPageInDirectory(node.path);
|
||||
};
|
||||
summary.append(label, add);
|
||||
|
||||
const children = document.createElement("div");
|
||||
children.className = "tree-children";
|
||||
renderTree(node, children, expandAll);
|
||||
details.append(summary, children);
|
||||
return details;
|
||||
}
|
||||
|
||||
function renderPageButton(page) {
|
||||
const btn = document.createElement("button");
|
||||
btn.type = "button";
|
||||
btn.className = "page-item";
|
||||
btn.innerHTML = `<strong>${html(page.title)}</strong><span>${html(page.path)}</span><span class="tags">${page.tags.map((tag) => `<span class="tag">${html(tag)}</span>`).join("")}</span>`;
|
||||
btn.className = `page-item${page.path === state.currentPath ? " active" : ""}`;
|
||||
btn.innerHTML = `<strong>${html(page.title)}</strong><span class="filename">${html(page.filename || page.path)}</span><span>${html(page.path)}</span>${page.tags.length ? `<span class="tags">${page.tags.map((tag) => `<span class="tag">${html(tag)}</span>`).join("")}</span>` : ""}`;
|
||||
btn.onclick = () => loadPage(page.path);
|
||||
pagesBox.appendChild(btn);
|
||||
});
|
||||
renderStatus();
|
||||
return btn;
|
||||
}
|
||||
|
||||
function countPages(node) {
|
||||
let count = node.pages.length;
|
||||
node.dirs.forEach((child) => { count += countPages(child); });
|
||||
return count;
|
||||
}
|
||||
|
||||
function containsCurrentPath(node) {
|
||||
return Boolean(state.currentPath && (state.currentPath.startsWith(`${node.path}/`) || node.pages.some((page) => page.path === state.currentPath)));
|
||||
}
|
||||
|
||||
function newPageInDirectory(dirPath) {
|
||||
const pageType = pageTypeForDirectory(dirPath);
|
||||
setForm({ pageType, date: currentOrgDate(), comments: true });
|
||||
editor.section.value = pageType === "post" ? postSectionForDirectory(dirPath) : "";
|
||||
editor.targetPath.value = `${dirPath}/`;
|
||||
state.pathManual = true;
|
||||
updateEditorMode();
|
||||
saveMessage.textContent = `New file will be created in ${dirPath}.`;
|
||||
editor.title.focus();
|
||||
}
|
||||
|
||||
function pageTypeForDirectory(dirPath) {
|
||||
if (dirPath === "lima" || dirPath.startsWith("lima/")) return "lima";
|
||||
if (dirPath === "posts" || dirPath.startsWith("posts/")) return "post";
|
||||
if (dirPath === "blogs" || dirPath.startsWith("blogs/")) return "blog";
|
||||
return "page";
|
||||
}
|
||||
|
||||
function postSectionForDirectory(dirPath) {
|
||||
if (!dirPath.startsWith("posts/")) return "";
|
||||
return dirPath.slice("posts/".length);
|
||||
}
|
||||
|
||||
function html(value) {
|
||||
@@ -1034,6 +1139,7 @@ APP_HTML = r"""<!doctype html>
|
||||
updateEditorMode();
|
||||
updateSuggestedPath();
|
||||
updateMarkdownPreview();
|
||||
if (state.pages.length) renderPages();
|
||||
saveMessage.textContent = "";
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
See the categories: @@html:<a href="../home/categories.html">Categories</a>@@
|
||||
|
||||
* Posts:
|
||||
- [[file:career/career-list.org][Career List]] @@html:<span class="post-date">08-05-2026 12:09</span>@@
|
||||
- [[file:career/career-list.org][Career List]] @@html:<span class="post-date">08-05-2026 12:27</span>@@
|
||||
- [[file:posts-list.sync-conflict-20260417-233432-VT6366A.org][Posts List]] @@html:<span class="post-date">14-04-2026 16:36</span>@@
|
||||
- [[file:career/ha-dr.org][High Availability, Disaster Recovery and Business Continuity]] @@html:<span class="post-date">11-03-2026 17:18</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@
|
||||
- [[file:career/javascript.org][Understands the Javascript language]] @@html:<span class="post-date">11-03-2026 16:52</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@
|
||||
|
||||
Reference in New Issue
Block a user