mirror of
https://github.com/zadam/trilium.git
synced 2026-01-12 09:34:26 +01:00
chore(core): integrate icon_packs service
This commit is contained in:
parent
22590596da
commit
f05fda871c
@ -7,7 +7,7 @@ import assetPath from "../services/asset_path.js";
|
||||
import attributeService from "../services/attributes.js";
|
||||
import config from "../services/config.js";
|
||||
import { getCurrentLocale } from "../services/i18n.js";
|
||||
import { generateCss, generateIconRegistry, getIconPacks, MIME_TO_EXTENSION_MAPPINGS } from "../services/icon_packs.js";
|
||||
import { icon_packs as iconPackService } from "@triliumnext/core";
|
||||
import log from "../services/log.js";
|
||||
import optionService from "../services/options.js";
|
||||
import protectedSessionService from "../services/protected_session.js";
|
||||
@ -30,7 +30,7 @@ export function bootstrap(req: Request, res: Response) {
|
||||
const theme = options.theme;
|
||||
const themeNote = attributeService.getNoteWithLabel("appTheme", theme);
|
||||
const nativeTitleBarVisible = options.nativeTitleBarVisible === "true";
|
||||
const iconPacks = getIconPacks();
|
||||
const iconPacks = iconPackService.getIconPacks();
|
||||
const currentLocale = getCurrentLocale();
|
||||
|
||||
res.send({
|
||||
@ -62,12 +62,12 @@ export function bootstrap(req: Request, res: Response) {
|
||||
currentLocale,
|
||||
isRtl: !!currentLocale.rtl,
|
||||
iconPackCss: iconPacks
|
||||
.map(p => generateCss(p, p.builtin
|
||||
? `${assetPath}/fonts/${p.fontAttachmentId}.${MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`
|
||||
.map(p => iconPackService.generateCss(p, p.builtin
|
||||
? `${assetPath}/fonts/${p.fontAttachmentId}.${iconPackService.MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`
|
||||
: `api/attachments/download/${p.fontAttachmentId}`))
|
||||
.filter(Boolean)
|
||||
.join("\n\n"),
|
||||
iconRegistry: generateIconRegistry(iconPacks),
|
||||
iconRegistry: iconPackService.generateIconRegistry(iconPacks),
|
||||
TRILIUM_SAFE_MODE: !!process.env.TRILIUM_SAFE_MODE
|
||||
});
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import type BBranch from "../../../becca/entities/bbranch.js";
|
||||
import type BNote from "../../../becca/entities/bnote.js";
|
||||
import { getClientDir, getShareThemeAssetDir } from "../../../routes/assets";
|
||||
import { getDefaultTemplatePath, readTemplate, renderNoteForExport } from "../../../share/content_renderer";
|
||||
import { getIconPacks, MIME_TO_EXTENSION_MAPPINGS, ProcessedIconPack } from "../../icon_packs";
|
||||
import { icon_packs as iconPackService } from "@triliumnext/core";
|
||||
import log from "../../log";
|
||||
import NoteMeta, { NoteMetaFile } from "../../meta/note_meta";
|
||||
import { RESOURCE_DIR } from "../../resource_dir";
|
||||
@ -31,7 +31,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
|
||||
private indexMeta: NoteMeta | null = null;
|
||||
private searchIndex: Map<string, SearchIndexEntry> = new Map();
|
||||
private rootMeta: NoteMeta | null = null;
|
||||
private iconPacks: ProcessedIconPack[] = [];
|
||||
private iconPacks: iconPackService.ProcessedIconPack[] = [];
|
||||
|
||||
prepareMeta(metaFile: NoteMetaFile): void {
|
||||
const assets = [
|
||||
@ -56,7 +56,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
|
||||
dataFileName: "index.html"
|
||||
};
|
||||
this.rootMeta = metaFile.files[0];
|
||||
this.iconPacks = getIconPacks();
|
||||
this.iconPacks = iconPackService.getIconPacks();
|
||||
|
||||
metaFile.files.push(this.indexMeta);
|
||||
}
|
||||
@ -165,7 +165,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
|
||||
|
||||
// Inject the custom fonts.
|
||||
for (const iconPack of this.iconPacks) {
|
||||
const extension = MIME_TO_EXTENSION_MAPPINGS[iconPack.fontMime];
|
||||
const extension = iconPackService.MIME_TO_EXTENSION_MAPPINGS[iconPack.fontMime];
|
||||
let fontData: Uint8Array | undefined;
|
||||
if (iconPack.builtin) {
|
||||
fontData = readFileSync(join(getClientDir(), "fonts", `${iconPack.fontAttachmentId}.${extension}`));
|
||||
|
||||
@ -343,10 +343,6 @@ export function processStringOrBuffer(data: string | Buffer | null) {
|
||||
}
|
||||
}
|
||||
|
||||
export function safeExtractMessageAndStackFromError(err: unknown): [errMessage: string, errStack: string | undefined] {
|
||||
return (err instanceof Error) ? [err.message, err.stack] as const : ["Unknown Error", undefined] as const;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes URL by removing trailing slashes and fixing double slashes.
|
||||
* Preserves the protocol (http://, https://) but removes trailing slashes from the rest.
|
||||
@ -453,9 +449,14 @@ function slugify(text: string) {
|
||||
.replace(/(^-|-$)+/g, ""); // trim dashes
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
export const escapeHtml = coreUtils.escapeHtml;
|
||||
/** @deprecated */
|
||||
export const unescapeHtml = coreUtils.unescapeHtml;
|
||||
/** @deprecated */
|
||||
export const randomSecureToken = coreUtils.randomSecureToken;
|
||||
/** @deprecated */
|
||||
export const safeExtractMessageAndStackFromError = coreUtils.safeExtractMessageAndStackFromError;
|
||||
|
||||
export default {
|
||||
compareVersions,
|
||||
|
||||
@ -12,7 +12,6 @@ import BAttachment from '../becca/entities/battachment.js';
|
||||
import type BBranch from "../becca/entities/bbranch.js";
|
||||
import BNote from "../becca/entities/bnote.js";
|
||||
import assetPath, { assetUrlFragment } from "../services/asset_path.js";
|
||||
import { generateCss, getIconPacks, MIME_TO_EXTENSION_MAPPINGS, ProcessedIconPack } from "../services/icon_packs.js";
|
||||
import log from "../services/log.js";
|
||||
import options from "../services/options.js";
|
||||
import utils, { getResourceDir, isDev, safeExtractMessageAndStackFromError } from "../services/utils.js";
|
||||
@ -21,6 +20,7 @@ import SBranch from "./shaca/entities/sbranch.js";
|
||||
import type SNote from "./shaca/entities/snote.js";
|
||||
import shaca from "./shaca/shaca.js";
|
||||
import shareRoot from "./share_root.js";
|
||||
import { icon_packs as iconPackService } from "@triliumnext/core";
|
||||
|
||||
const shareAdjustedAssetPath = isDev ? assetPath : `../${assetPath}`;
|
||||
const templateCache: Map<string, string> = new Map();
|
||||
@ -69,7 +69,7 @@ function getSharedSubTreeRoot(note: SNote | BNote | undefined): Subroot {
|
||||
return getSharedSubTreeRoot(parentBranch.getParentNote());
|
||||
}
|
||||
|
||||
export function renderNoteForExport(note: BNote, parentBranch: BBranch, basePath: string, ancestors: string[], iconPacks: ProcessedIconPack[]) {
|
||||
export function renderNoteForExport(note: BNote, parentBranch: BBranch, basePath: string, ancestors: string[], iconPacks: iconPackService.ProcessedIconPack[]) {
|
||||
const subRoot: Subroot = {
|
||||
branch: parentBranch,
|
||||
note: parentBranch.getNote()
|
||||
@ -95,7 +95,7 @@ export function renderNoteForExport(note: BNote, parentBranch: BBranch, basePath
|
||||
faviconUrl: `${basePath}favicon.ico`,
|
||||
ancestors,
|
||||
isStatic: true,
|
||||
iconPackCss: iconPacks.map(p => generateCss(p, `${basePath}assets/icon-pack-${p.prefix.toLowerCase()}.${MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`))
|
||||
iconPackCss: iconPacks.map(p => iconPackService.generateCss(p, `${basePath}assets/icon-pack-${p.prefix.toLowerCase()}.${iconPackService.MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`))
|
||||
.filter(Boolean)
|
||||
.join("\n\n"),
|
||||
iconPackSupportedPrefixes: iconPacks.map(p => p.prefix)
|
||||
@ -136,7 +136,7 @@ export function renderNoteContent(note: SNote) {
|
||||
|
||||
const customLogoId = note.getRelation("shareLogo")?.value;
|
||||
const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png` : `../${assetUrlFragment}/images/icon-color.svg`;
|
||||
const iconPacks = getIconPacks().filter(p => p.builtin || !!shaca.notes[p.manifestNoteId]);
|
||||
const iconPacks = iconPackService.getIconPacks().filter(p => p.builtin || !!shaca.notes[p.manifestNoteId]);
|
||||
|
||||
return renderNoteContentInternal(note, {
|
||||
subRoot,
|
||||
@ -147,8 +147,8 @@ export function renderNoteContent(note: SNote) {
|
||||
ancestors,
|
||||
isStatic: false,
|
||||
faviconUrl: note.hasRelation("shareFavicon") ? `api/notes/${note.getRelationValue("shareFavicon")}/download` : `../favicon.ico`,
|
||||
iconPackCss: iconPacks.map(p => generateCss(p, p.builtin
|
||||
? `/share/assets/fonts/${p.fontAttachmentId}.${MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`
|
||||
iconPackCss: iconPacks.map(p => iconPackService.generateCss(p, p.builtin
|
||||
? `/share/assets/fonts/${p.fontAttachmentId}.${iconPackService.MIME_TO_EXTENSION_MAPPINGS[p.fontMime]}`
|
||||
: `/share/api/attachments/${p.fontAttachmentId}/download`
|
||||
))
|
||||
.filter(Boolean)
|
||||
|
||||
@ -20,6 +20,7 @@ export { default as app_info } from "./services/app_info";
|
||||
export { default as keyboard_actions } from "./services/keyboard_actions";
|
||||
export { default as entity_changes } from "./services/entity_changes";
|
||||
export { default as hidden_subtree } from "./services/hidden_subtree";
|
||||
export * as icon_packs from "./services/icon_packs";
|
||||
export { getContext, type ExecutionContext } from "./services/context";
|
||||
export * as cls from "./services/context";
|
||||
export * from "./errors";
|
||||
|
||||
@ -3,9 +3,9 @@ import { IconRegistry } from "@triliumnext/commons";
|
||||
import type BAttachment from "../becca/entities/battachment";
|
||||
import type BNote from "../becca/entities/bnote";
|
||||
import boxiconsManifest from "./icon_pack_boxicons-v2.json" with { type: "json" };
|
||||
import log from "./log";
|
||||
import { getLog } from "./log";
|
||||
import search from "./search/services/search";
|
||||
import { safeExtractMessageAndStackFromError } from "./utils";
|
||||
import { safeExtractMessageAndStackFromError } from "./utils/index";
|
||||
|
||||
const PREFERRED_MIME_TYPE = [
|
||||
"font/woff2",
|
||||
@ -64,7 +64,7 @@ export function getIconPacks() {
|
||||
if (!iconPack) return false;
|
||||
|
||||
if (iconPack.prefix === "bx" || usedPrefixes.has(iconPack.prefix)) {
|
||||
log.info(`Skipping icon pack with duplicate prefix '${iconPack.prefix}': ${iconPack.title} (${iconPack.manifestNoteId})`);
|
||||
getLog().info(`Skipping icon pack with duplicate prefix '${iconPack.prefix}': ${iconPack.title} (${iconPack.manifestNoteId})`);
|
||||
return false;
|
||||
}
|
||||
usedPrefixes.add(iconPack.prefix);
|
||||
@ -103,25 +103,25 @@ export function generateIconRegistry(iconPacks: ProcessedIconPack[]): IconRegist
|
||||
export function processIconPack(iconPackNote: BNote): ProcessedIconPack | undefined {
|
||||
const manifest = iconPackNote.getJsonContentSafely() as IconPackManifest;
|
||||
if (!manifest) {
|
||||
log.error(`Icon pack is missing JSON manifest (or has syntax errors): ${iconPackNote.title} (${iconPackNote.noteId})`);
|
||||
getLog().error(`Icon pack is missing JSON manifest (or has syntax errors): ${iconPackNote.title} (${iconPackNote.noteId})`);
|
||||
return;
|
||||
}
|
||||
|
||||
const attachment = determineBestFontAttachment(iconPackNote);
|
||||
if (!attachment || !attachment.attachmentId) {
|
||||
log.error(`Icon pack is missing WOFF/WOFF2/TTF attachment: ${iconPackNote.title} (${iconPackNote.noteId})`);
|
||||
getLog().error(`Icon pack is missing WOFF/WOFF2/TTF attachment: ${iconPackNote.title} (${iconPackNote.noteId})`);
|
||||
return;
|
||||
}
|
||||
|
||||
const prefix = iconPackNote.getLabelValue("iconPack");
|
||||
if (!prefix) {
|
||||
log.error(`Icon pack is missing 'iconPack' label defining its prefix: ${iconPackNote.title} (${iconPackNote.noteId})`);
|
||||
getLog().error(`Icon pack is missing 'iconPack' label defining its prefix: ${iconPackNote.title} (${iconPackNote.noteId})`);
|
||||
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})`);
|
||||
getLog().error(`Icon pack has invalid 'iconPack' prefix (only alphanumeric characters, dashes and underscores are allowed): ${iconPackNote.title} (${iconPackNote.noteId})`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -185,7 +185,7 @@ export function generateCss({ manifest, fontMime, builtin, fontAttachmentId, pre
|
||||
${iconDeclarations.join("\n")}
|
||||
`;
|
||||
} catch (e) {
|
||||
log.error(safeExtractMessageAndStackFromError(e));
|
||||
getLog().error(safeExtractMessageAndStackFromError(e));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ export default {
|
||||
console.warn("Ignore search ", note.title);
|
||||
},
|
||||
|
||||
searchNotes(searchString: string, opts: {}): BNote[] {
|
||||
searchNotes(searchString: string, opts?: {}): BNote[] {
|
||||
console.warn("Ignore search", searchString);
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -126,3 +126,7 @@ export const unescapeHtml = unescape;
|
||||
export function randomSecureToken(bytes = 32) {
|
||||
return encodeBase64(getCrypto().randomBytes(32));
|
||||
}
|
||||
|
||||
export function safeExtractMessageAndStackFromError(err: unknown): [errMessage: string, errStack: string | undefined] {
|
||||
return (err instanceof Error) ? [err.message, err.stack] as const : ["Unknown Error", undefined] as const;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user