tiny update

This commit is contained in:
KingKDot
2026-08-24 09:35:03 -05:00
parent fcc6cc53be
commit 0921e39333
131 changed files with 9948 additions and 1076 deletions
@@ -10,7 +10,7 @@ export async function loadPluginNavItems(activeMap) {
if (!plugins || !Array.isArray(plugins)) return;
const navPlugins = plugins.filter(
(p) => p.navbar && p.enabled
(p) => p && typeof p === "object" && p.navbar && p.enabled
);
if (navPlugins.length === 0) return;
@@ -28,11 +28,17 @@ export async function loadPluginNavItems(activeMap) {
if (!childContainer) return;
const itemsHtml = navPlugins.map((p) => {
const linkId = `plugin-nav-${p.id}`;
activeMap[`/plugins/${p.id}`] = linkId;
const pluginId = String(p.id || "").trim();
if (
!/^[A-Za-z0-9_-][A-Za-z0-9._-]{0,127}$/.test(pluginId) ||
pluginId.includes("..") ||
pluginId.endsWith(".")
) return "";
const linkId = `plugin-nav-${pluginId}`;
activeMap[`/plugins/${pluginId}`] = linkId;
const childObj = {
href: `/plugins/${p.id}`,
href: `/plugins/${pluginId}`,
label: p.navbar.label || p.name,
icon: p.navbar.icon || "fa-cube",
iconColor: "text-slate-300",
+39 -8
View File
@@ -81,16 +81,45 @@ export const NAV_GROUPS = [
TOPBAR — dropdown menus
────────────────────────────────────────────── */
function escapeNavHtml(value) {
return String(value ?? "")
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
function safeNavHref(value) {
const href = String(value ?? "").trim();
if (!href.startsWith("/") || href.startsWith("//") || /[\u0000-\u001f\u007f]/.test(href)) {
return "#";
}
return escapeNavHtml(href);
}
function safeNavId(value) {
return String(value ?? "").replace(/[^A-Za-z0-9_.:-]/g, "-").slice(0, 192);
}
function safeNavClassList(value) {
return String(value ?? "")
.split(/\s+/)
.filter((token) => /^[A-Za-z0-9_-]+$/.test(token))
.join(" ");
}
export function dropdownItem(child) {
const hiddenCls = child.hidden ? " hidden" : "";
const prefetchAttr = child.turboPrefetch === false ? ' data-turbo-prefetch="false"' : "";
const badgeHtml = child.hasBadge
? `<span id="enrollment-badge" class="nav-dd-badge hidden"></span>`
: "";
return `<a href="${child.href}" id="${child.linkId}"${prefetchAttr}
class="nav-dd-item${hiddenCls}" data-link-id="${child.linkId}">
<i class="fa-solid ${child.icon} ${child.iconColor} nav-dd-item-icon"></i>
<span>${child.label}</span>
const linkId = safeNavId(child.linkId);
return `<a href="${safeNavHref(child.href)}" id="${linkId}"${prefetchAttr}
class="nav-dd-item${hiddenCls}" data-link-id="${linkId}">
<i class="fa-solid ${safeNavClassList(child.icon)} ${safeNavClassList(child.iconColor)} nav-dd-item-icon"></i>
<span>${escapeNavHtml(child.label)}</span>
${badgeHtml}
</a>`;
}
@@ -241,10 +270,12 @@ export function sidebarChild(child) {
const badgeHtml = child.hasBadge
? `<span id="enrollment-badge" class="sb-badge hidden"></span>`
: "";
return `<a href="${child.href}" id="${child.linkId}"
class="sb-link sb-link-child${hiddenCls}" data-link-id="${child.linkId}" title="${child.label}">
<i class="fa-solid ${child.icon} ${child.iconColor} sb-icon"></i>
<span class="sb-text">${child.label}</span>
const linkId = safeNavId(child.linkId);
const label = escapeNavHtml(child.label);
return `<a href="${safeNavHref(child.href)}" id="${linkId}"
class="sb-link sb-link-child${hiddenCls}" data-link-id="${linkId}" title="${label}">
<i class="fa-solid ${safeNavClassList(child.icon)} ${safeNavClassList(child.iconColor)} sb-icon"></i>
<span class="sb-text">${label}</span>
${badgeHtml}
</a>`;
}