chore(icon_packs): integrate prefix as part of the attribute instead of manifest

This commit is contained in:
Elian Doran 2025-12-28 09:56:08 +02:00
parent 99bdd2e433
commit 1570ea77d8
No known key found for this signature in database
4 changed files with 24 additions and 17 deletions

View File

@ -153,7 +153,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
} }
if (!fontData) continue; if (!fontData) continue;
const fontFileName = `assets/icon-pack-${iconPack.manifest.prefix.toLowerCase()}.${extension}`; const fontFileName = `assets/icon-pack-${iconPack.prefix.toLowerCase()}.${extension}`;
this.archive.append(fontData, { name: fontFileName }); this.archive.append(fontData, { name: fontFileName });
} }
} }

View File

@ -1,5 +1,4 @@
{ {
"prefix": "bx",
"icons": { "icons": {
"bx-child": { "bx-child": {
"glyph": "", "glyph": "",

View File

@ -26,7 +26,6 @@ export const MIME_TO_EXTENSION_MAPPINGS: Record<string, string> = {
}; };
export interface IconPackManifest { export interface IconPackManifest {
prefix: string;
icons: Record<string, { icons: Record<string, {
glyph: string, glyph: string,
terms: string[]; terms: string[];
@ -34,6 +33,7 @@ export interface IconPackManifest {
} }
export interface ProcessedIconPack { export interface ProcessedIconPack {
prefix: string;
manifest: IconPackManifest; manifest: IconPackManifest;
manifestNoteId: string; manifestNoteId: string;
fontMime: string; fontMime: string;
@ -46,6 +46,7 @@ export interface ProcessedIconPack {
export function getIconPacks() { export function getIconPacks() {
const defaultIconPack: ProcessedIconPack = { const defaultIconPack: ProcessedIconPack = {
prefix: "bx",
manifest: boxiconsManifest, manifest: boxiconsManifest,
manifestNoteId: "boxicons", manifestNoteId: "boxicons",
fontMime: "font/woff2", fontMime: "font/woff2",
@ -55,18 +56,18 @@ export function getIconPacks() {
builtin: true builtin: true
}; };
const usedPrefixes = new Set<string>([defaultIconPack.manifest.prefix]); const usedPrefixes = new Set<string>([defaultIconPack.prefix]);
const customIconPacks = search.searchNotes("#iconPack") const customIconPacks = search.searchNotes("#iconPack")
.filter(note => !note.isProtected) .filter(note => !note.isProtected)
.map(iconPackNote => processIconPack(iconPackNote)) .map(iconPackNote => processIconPack(iconPackNote))
.filter(iconPack => { .filter(iconPack => {
if (!iconPack) return false; if (!iconPack) return false;
if (iconPack.manifest.prefix === "bx" || usedPrefixes.has(iconPack.manifest.prefix)) { if (iconPack.prefix === "bx" || usedPrefixes.has(iconPack.prefix)) {
log.info(`Skipping icon pack with duplicate prefix '${iconPack.manifest.prefix}': ${iconPack.title} (${iconPack.manifestNoteId})`); log.info(`Skipping icon pack with duplicate prefix '${iconPack.prefix}': ${iconPack.title} (${iconPack.manifestNoteId})`);
return false; return false;
} }
usedPrefixes.add(iconPack.manifest.prefix); usedPrefixes.add(iconPack.prefix);
return true; return true;
}) as ProcessedIconPack[]; }) as ProcessedIconPack[];
@ -79,17 +80,17 @@ export function getIconPacks() {
export function generateIconRegistry(iconPacks: ProcessedIconPack[]): IconRegistry { export function generateIconRegistry(iconPacks: ProcessedIconPack[]): IconRegistry {
const sources: IconRegistry["sources"] = []; const sources: IconRegistry["sources"] = [];
for (const { manifest, title, icon } of iconPacks) { for (const { manifest, title, icon, prefix } of iconPacks) {
const icons: IconRegistry["sources"][number]["icons"] = Object.entries(manifest.icons) const icons: IconRegistry["sources"][number]["icons"] = Object.entries(manifest.icons)
.map(( [id, { terms }] ) => { .map(( [id, { terms }] ) => {
if (!id || !terms) return null; if (!id || !terms) return null;
return { id: `${manifest.prefix} ${id}`, terms }; return { id: `${prefix} ${id}`, terms };
}) })
.filter(Boolean) as IconRegistry["sources"][number]["icons"]; .filter(Boolean) as IconRegistry["sources"][number]["icons"];
if (!icons.length) continue; if (!icons.length) continue;
sources.push({ sources.push({
prefix: manifest.prefix, prefix,
name: title, name: title,
icon, icon,
icons icons
@ -112,7 +113,14 @@ export function processIconPack(iconPackNote: BNote): ProcessedIconPack | undefi
return; return;
} }
const prefix = iconPackNote.getLabelValue("iconPack");
if (!prefix) {
log.error(`Icon pack is missing 'iconPack' label defining its prefix: ${iconPackNote.title} (${iconPackNote.noteId})`);
return;
}
return { return {
prefix,
manifest, manifest,
fontMime: attachment.mime, fontMime: attachment.mime,
fontAttachmentId: attachment.attachmentId, fontAttachmentId: attachment.attachmentId,
@ -139,14 +147,14 @@ export function determineBestFontAttachment(iconPackNote: BNote) {
return null; return null;
} }
export function generateCss({ manifest, fontMime, builtin, fontAttachmentId }: ProcessedIconPack, fontUrl: string) { export function generateCss({ manifest, fontMime, builtin, fontAttachmentId, prefix }: ProcessedIconPack, fontUrl: string) {
try { try {
const iconDeclarations: string[] = []; const iconDeclarations: string[] = [];
for (const [ key, mapping ] of Object.entries(manifest.icons)) { for (const [ key, mapping ] of Object.entries(manifest.icons)) {
iconDeclarations.push(`.${manifest.prefix}.${key}::before { content: '\\${mapping.glyph.charCodeAt(0).toString(16)}'; }`); iconDeclarations.push(`.${prefix}.${key}::before { content: '\\${mapping.glyph.charCodeAt(0).toString(16)}'; }`);
} }
const fontFamily = builtin ? fontAttachmentId : `trilium-icon-pack-${manifest.prefix}`; const fontFamily = builtin ? fontAttachmentId : `trilium-icon-pack-${prefix}`;
return `\ return `\
@font-face { @font-face {
font-family: '${fontFamily}'; font-family: '${fontFamily}';
@ -155,7 +163,7 @@ export function generateCss({ manifest, fontMime, builtin, fontAttachmentId }: P
src: url('${fontUrl}') format('${MIME_TO_CSS_FORMAT_MAPPINGS[fontMime]}'); src: url('${fontUrl}') format('${MIME_TO_CSS_FORMAT_MAPPINGS[fontMime]}');
} }
.${manifest.prefix} { .${prefix} {
font-family: '${fontFamily}' !important; font-family: '${fontFamily}' !important;
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;

View File

@ -89,10 +89,10 @@ export function renderNoteForExport(note: BNote, parentBranch: BBranch, basePath
faviconUrl: `${basePath}favicon.ico`, faviconUrl: `${basePath}favicon.ico`,
ancestors, ancestors,
isStatic: true, isStatic: true,
iconPackCss: iconPacks.map(p => generateCss(p, `${basePath}assets/icon-pack-${p.manifest.prefix.toLowerCase()}.${MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`)) iconPackCss: iconPacks.map(p => generateCss(p, `${basePath}assets/icon-pack-${p.prefix.toLowerCase()}.${MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`))
.filter(Boolean) .filter(Boolean)
.join("\n\n"), .join("\n\n"),
iconPackSupportedPrefixes: iconPacks.map(p => p.manifest.prefix) iconPackSupportedPrefixes: iconPacks.map(p => p.prefix)
}); });
} }
@ -147,7 +147,7 @@ export function renderNoteContent(note: SNote) {
)) ))
.filter(Boolean) .filter(Boolean)
.join("\n\n"), .join("\n\n"),
iconPackSupportedPrefixes: iconPacks.map(p => p.manifest.prefix) iconPackSupportedPrefixes: iconPacks.map(p => p.prefix)
}); });
} }