Menu
Public repository / 054e5cda0171bd13facff3c16a38f2048a1052cc
AkurAI-Mail / scripts/gen-icons.ts
Latest change 054e5cda0171bd13facff3c16a38f2048a1052cc - OLI-249: compose, settings, admin console and sign-in on the framework; SvelteKit removed by Ólafur Búi Ólafsson
// One-off generator: inline SVG icon data for the icons the mail UI uses, taken from lucide-svelte's shipped components.
export {};
const names = "Archive ArrowLeft Bell Bold Bot Check ChevronDown ChevronLeft ChevronRight CircleHelp Clock Clock3 Download FilePen FileText Flag FolderInput Forward Inbox Italic Keyboard Link2 List ListOrdered Mail MessageCircle MoreHorizontal Paperclip PenLine Plus Quote RefreshCcw RefreshCw Reply ReplyAll Search SearchCheck Send ServerCog Settings2 ShieldAlert SlidersHorizontal Star Trash2 TriangleAlert UserPlus WifiOff X".split(" ");
const kebab = (n: string) => n.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Za-z])([0-9])/g, "$1-$2").toLowerCase();
let out = `// icons.js — inline SVG icons for AkurAI Mail (no build step, no runtime dependency).
// Path data from Lucide (https://lucide.dev), ISC License, Copyright (c) Lucide Icons and Contributors;
// icons derived from Feather are MIT, Copyright (c) 2013-present Cole Bemis. Generated by scripts/gen-icons.ts.
const SVG_NS = "http://www.w3.org/2000/svg";
/** @type {Record<string, [string, Record<string, string>][]>} */
export const ICONS = {
`;
for (const n of names) {
// Icons lucide has renamed since the UI was written keep their old names here.
const RENAMED: Record<string, string> = { MoreHorizontal: "ellipsis", CircleHelp: "circle-question-mark" };
const file = `node_modules/lucide-svelte/dist/icons/${RENAMED[n] ?? kebab(n)}.svelte`;
const src = await Bun.file(file).text();
const m = /const iconNode = (\[.*\]);/.exec(src);
if (!m) throw new Error(`no iconNode in ${file}`);
out += ` ${n}: ${m[1]},\n`;
}
out += `};
/**
* An inline SVG element for icon \`name\` (a key of ICONS).
* @param {string} name
* @param {{ size?: number, strokeWidth?: number, fill?: string, class?: string, label?: string }} [options]
* @returns {SVGSVGElement}
*/
export function icon(name, { size = 24, strokeWidth = 2, fill = "none", class: className = "", label = "" } = {}) {
// Accepts PascalCase keys and lucide's kebab-case names ("message-circle").
const key = name.includes("-") || name[0] !== name[0].toUpperCase() ? name.replace(/(^|-)([a-z0-9])/g, (_, _sep, c) => c.toUpperCase()) : name;
const nodes = ICONS[key];
if (!nodes) throw new Error(\`unknown icon \${name}\`);
const svg = document.createElementNS(SVG_NS, "svg");
const attrs = { xmlns: SVG_NS, width: String(size), height: String(size), viewBox: "0 0 24 24", fill, stroke: "currentColor", "stroke-width": String(strokeWidth), "stroke-linecap": "round", "stroke-linejoin": "round", class: \`icon icon-\${name} \${className}\`.trim() };
for (const [key, value] of Object.entries(attrs)) svg.setAttribute(key, value);
if (label) svg.setAttribute("aria-label", label); else svg.setAttribute("aria-hidden", "true");
for (const [tag, props] of nodes) {
const child = document.createElementNS(SVG_NS, tag);
for (const [key, value] of Object.entries(props)) child.setAttribute(key, value);
svg.appendChild(child);
}
return svg;
}
`;
await Bun.write("src/framework/icons.js", out);
console.log("wrote", names.length, "icons");