diff --git a/apps/client/src/widgets/note_icon.tsx b/apps/client/src/widgets/note_icon.tsx index ea81aae70..00ef7e78b 100644 --- a/apps/client/src/widgets/note_icon.tsx +++ b/apps/client/src/widgets/note_icon.tsx @@ -73,10 +73,10 @@ function NoteIconList({ note, dropdownRef }: { async function loadIcons() { // Filter by text and/or category. let icons: IconData["icons"] = [ - ...glob.iconRegistry.sources.map(s => s.icons.map((i) => ({ + ...glob.iconRegistry.sources.flatMap(s => s.icons.map((i) => ({ ...i, iconPack: s.name, - }))).flat() + }))) ]; const processedSearch = search?.trim()?.toLowerCase(); if (processedSearch || filterByPrefix !== null) { diff --git a/apps/server/src/services/icon_packs.spec.ts b/apps/server/src/services/icon_packs.spec.ts index 43757dcc2..831032323 100644 --- a/apps/server/src/services/icon_packs.spec.ts +++ b/apps/server/src/services/icon_packs.spec.ts @@ -82,6 +82,21 @@ describe("Mapping attachments", () => { expect(attachment?.mime).toStrictEqual("font/ttf"); }); + it("ignores when no right attachment is found", () => { + const iconPackNote = buildNote({ + type: "text", + attachments: [ + { + role: "file", + title: "Font", + mime: "font/otf" + } + ] + }); + const attachment = determineBestFontAttachment(iconPackNote); + expect(attachment).toBeNull(); + }); + it("prefers woff2", () => { const iconPackNote = buildNote({ type: "text", @@ -149,7 +164,7 @@ describe("CSS generation", () => { }); }); -describe("Icon registery", () => { +describe("Icon registry", () => { it("generates the registry", () => { const iconPack = processIconPack(buildNote({ title: "Boxicons v2", @@ -177,7 +192,7 @@ describe("Icon registery", () => { }); }); - it("ignores incorrect manifest", () => { + it("ignores manifest with wrong icon structure", () => { const iconPack = processIconPack(buildNote({ type: "text", content: JSON.stringify({ @@ -195,4 +210,14 @@ describe("Icon registery", () => { const registry = generateIconRegistry([ iconPack! ]); expect(registry.sources).toHaveLength(0); }); + + it("ignores manifest with corrupt JSON", () => { + const iconPack = processIconPack(buildNote({ + type: "text", + content: "{ this is not valid JSON }", + attachments: [ defaultAttachment ], + "#iconPack": "bx" + })); + expect(iconPack).toBeFalsy(); + }); }); diff --git a/apps/server/src/services/icon_packs.ts b/apps/server/src/services/icon_packs.ts index cbaa2a875..adddbf935 100644 --- a/apps/server/src/services/icon_packs.ts +++ b/apps/server/src/services/icon_packs.ts @@ -119,6 +119,12 @@ export function processIconPack(iconPackNote: BNote): ProcessedIconPack | undefi return; } + // Ensure prefix is alphanumeric only, dashes and underscores. + if (!/^[a-zA-Z0-9-_]+$/.test(prefix)) { + log.error(`Icon pack has invalid 'iconPack' prefix (only alphanumeric characters, dashes and underscores are allowed): ${iconPackNote.title} (${iconPackNote.noteId})`); + return; + } + return { prefix, manifest,