From 704eae72c988d67e2e897cff686b8ddcad9b08b1 Mon Sep 17 00:00:00 2001 From: Corvid Agent <95454608+corvid-agent@users.noreply.github.com> Date: Tue, 5 May 2026 08:37:06 -0700 Subject: [PATCH] redesign: clean precision UI with new typography and color system New design system: Syne display font, Plus Jakarta Sans body, warm zinc neutrals with sparse cyan accent. Removed all decorative noise (glows, dot patterns, gradient sweeps). Added markdown rendering for README modal and Cmd+K command palette for quick navigation. Bumped to v0.6.0. Co-Authored-By: Claude Opus 4.6 --- docs/index.html | 2 +- package.json | 2 +- plugin.toml | 2 +- public/app.js | 779 +++++++++++++-------- public/index.html | 91 +-- public/style.css | 1683 ++++++++++++++++++++++----------------------- 6 files changed, 1367 insertions(+), 1192 deletions(-) diff --git a/docs/index.html b/docs/index.html index ccad282..f4ca165 100644 --- a/docs/index.html +++ b/docs/index.html @@ -51,7 +51,7 @@

fledge-plugin-hub

Local web dashboard for browsing and managing fledge templates, plugins, lanes, and config

✓ official - v0.5.0 + v0.6.0 TypeScript
diff --git a/package.json b/package.json index 3a625bf..f5d0772 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fledge-plugin-hub", - "version": "0.5.0", + "version": "0.6.0", "description": "Local web dashboard for browsing and managing fledge templates, plugins, lanes, and config", "type": "module", "scripts": { diff --git a/plugin.toml b/plugin.toml index 21a1ed7..2c8f19d 100644 --- a/plugin.toml +++ b/plugin.toml @@ -1,6 +1,6 @@ [plugin] name = "fledge-plugin-hub" -version = "0.5.0" +version = "0.6.0" description = "Local web dashboard for browsing and managing fledge templates, plugins, lanes, and config" author = "CorvidLabs" diff --git a/public/app.js b/public/app.js index 0bf2bef..a1917d2 100644 --- a/public/app.js +++ b/public/app.js @@ -1,6 +1,8 @@ const $ = (sel) => document.querySelector(sel); const $$ = (sel) => document.querySelectorAll(sel); +// --- API --- + async function api(path, opts) { try { const res = await fetch(`/api${path}`, opts); @@ -18,24 +20,10 @@ async function postJSON(path, body) { }); } -function navigate(page) { - $$(".page").forEach((p) => p.classList.remove("active")); - $$(".nav-link").forEach((l) => l.classList.remove("active")); - $(`#page-${page}`)?.classList.add("active"); - $(`.nav-link[data-page="${page}"]`)?.classList.add("active"); - loaders[page]?.(); -} +// --- Helpers --- function html(el, content) { el.innerHTML = content; } -function renderError(msg) { - return `
${escape(msg)}
`; -} - -function renderEmpty(msg) { - return `
${msg}
`; -} - function escape(s) { if (s == null) return ""; const d = document.createElement("div"); @@ -43,24 +31,9 @@ function escape(s) { return d.innerHTML; } -function trustBadge(source, tier) { - const t = (tier || "").toLowerCase(); - if (t === "official") return 'official'; - if (t === "team") return 'team'; - if (t === "unverified") return 'community'; - if (!source) return ""; - return source.toLowerCase().startsWith("corvidlabs/") - ? 'official' - : 'community'; -} - -function typeBadge(topics) { - if (!topics) return ""; - if (topics.includes("fledge-plugin")) - return 'plugin'; - if (topics.includes("fledge-template")) - return 'template'; - return ""; +function truncate(s, n) { + s = String(s ?? ""); + return s.length > n ? s.slice(0, n) + "…" : s; } function timeAgo(dateStr) { @@ -68,22 +41,100 @@ function timeAgo(dateStr) { const diff = Date.now() - new Date(dateStr).getTime(); const days = Math.floor(diff / 86400000); if (days < 1) return "today"; - if (days === 1) return "1 day ago"; - if (days < 30) return `${days} days ago`; + if (days === 1) return "1d ago"; + if (days < 30) return `${days}d ago`; const months = Math.floor(days / 30); - if (months === 1) return "1 month ago"; - if (months < 12) return `${months} months ago`; + if (months < 12) return `${months}mo ago`; return `${Math.floor(months / 12)}y ago`; } +function renderError(msg) { + return `
${escape(msg)}
`; +} + +function renderEmpty(msg) { + return `
${msg}
`; +} + +// --- Markdown renderer --- + +function renderMarkdown(raw) { + if (!raw) return ""; + let text = raw; + + // Fenced code blocks + text = text.replace(/```(\w*)\n([\s\S]*?)```/g, (_, lang, code) => + `
${escape(code.trim())}
` + ); + + // Inline code (protect from further processing) + const codeMap = []; + text = text.replace(/`([^`]+)`/g, (_, code) => { + const id = `\x00CODE${codeMap.length}\x00`; + codeMap.push(`${escape(code)}`); + return id; + }); + + // Headings + text = text.replace(/^####\s+(.+)$/gm, "

$1

"); + text = text.replace(/^###\s+(.+)$/gm, "

$1

"); + text = text.replace(/^##\s+(.+)$/gm, "

$1

"); + text = text.replace(/^#\s+(.+)$/gm, "

$1

"); + + // Bold / italic + text = text.replace(/\*\*(.+?)\*\*/g, "$1"); + text = text.replace(/(?$1"); + + // Links + text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, + '$1' + ); + + // Images (render as links since we're in a modal) + text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, + '[$1]' + ); + + // Horizontal rules + text = text.replace(/^---+$/gm, "
"); + + // Blockquotes + text = text.replace(/^>\s*(.+)$/gm, "
$1
"); + + // List items + text = text.replace(/^[-*]\s+(.+)$/gm, "
  • $1
  • "); + + // Wrap consecutive
  • in