mirror of
https://github.com/zadam/trilium.git
synced 2026-01-09 08:04:23 +01:00
feat(share): basic support for custom icon packs
This commit is contained in:
parent
c7bb5ff119
commit
b00cb52da5
@ -29,6 +29,7 @@ export interface IconPackManifest {
|
|||||||
|
|
||||||
interface ProcessResult {
|
interface ProcessResult {
|
||||||
manifest: IconPackManifest;
|
manifest: IconPackManifest;
|
||||||
|
manifestNoteId: string;
|
||||||
fontMime: string;
|
fontMime: string;
|
||||||
fontAttachmentId: string;
|
fontAttachmentId: string;
|
||||||
title: string;
|
title: string;
|
||||||
@ -38,6 +39,7 @@ interface ProcessResult {
|
|||||||
export function getIconPacks() {
|
export function getIconPacks() {
|
||||||
const defaultIconPack: ProcessResult = {
|
const defaultIconPack: ProcessResult = {
|
||||||
manifest: boxiconsManifest,
|
manifest: boxiconsManifest,
|
||||||
|
manifestNoteId: "builtin-boxicons-v2",
|
||||||
fontMime: "font/woff2",
|
fontMime: "font/woff2",
|
||||||
fontAttachmentId: "builtin-boxicons-v2",
|
fontAttachmentId: "builtin-boxicons-v2",
|
||||||
title: "Boxicons",
|
title: "Boxicons",
|
||||||
@ -94,6 +96,7 @@ export function processIconPack(iconPackNote: BNote): ProcessResult | undefined
|
|||||||
fontMime: attachment.mime,
|
fontMime: attachment.mime,
|
||||||
fontAttachmentId: attachment.attachmentId,
|
fontAttachmentId: attachment.attachmentId,
|
||||||
title: iconPackNote.title,
|
title: iconPackNote.title,
|
||||||
|
manifestNoteId: iconPackNote.noteId,
|
||||||
icon: iconPackNote.getIcon()
|
icon: iconPackNote.getIcon()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -114,19 +117,20 @@ export function determineBestFontAttachment(iconPackNote: BNote) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateCss({ manifest, fontAttachmentId, fontMime }: ProcessResult) {
|
export function generateCss({ manifest, fontAttachmentId, fontMime }: ProcessResult, isShare = false) {
|
||||||
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(`.${manifest.prefix}.${key}::before { content: '\\${mapping.glyph.charCodeAt(0).toString(16)}'; }`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const downloadBaseUrl = isShare ? '/share' : '';
|
||||||
return `\
|
return `\
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'trilium-icon-pack-${manifest.prefix}';
|
font-family: 'trilium-icon-pack-${manifest.prefix}';
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
src: url('/api/attachments/${fontAttachmentId}/download') format('${MIME_TO_CSS_FORMAT_MAPPINGS[fontMime]}');
|
src: url('${downloadBaseUrl}/api/attachments/${fontAttachmentId}/download') format('${MIME_TO_CSS_FORMAT_MAPPINGS[fontMime]}');
|
||||||
}
|
}
|
||||||
|
|
||||||
.${manifest.prefix} {
|
.${manifest.prefix} {
|
||||||
|
|||||||
@ -1,24 +1,26 @@
|
|||||||
import { parse, HTMLElement, TextNode, Options } from "node-html-parser";
|
import { sanitizeUrl } from "@braintree/sanitize-url";
|
||||||
import shaca from "./shaca/shaca.js";
|
|
||||||
import assetPath, { assetUrlFragment } from "../services/asset_path.js";
|
|
||||||
import shareRoot from "./share_root.js";
|
|
||||||
import escapeHtml from "escape-html";
|
|
||||||
import type SNote from "./shaca/entities/snote.js";
|
|
||||||
import BNote from "../becca/entities/bnote.js";
|
|
||||||
import type BBranch from "../becca/entities/bbranch.js";
|
|
||||||
import { t } from "i18next";
|
|
||||||
import SBranch from "./shaca/entities/sbranch.js";
|
|
||||||
import options from "../services/options.js";
|
|
||||||
import utils, { getResourceDir, isDev, safeExtractMessageAndStackFromError } from "../services/utils.js";
|
|
||||||
import ejs from "ejs";
|
|
||||||
import log from "../services/log.js";
|
|
||||||
import { join } from "path";
|
|
||||||
import { readFileSync } from "fs";
|
|
||||||
import { highlightAuto } from "@triliumnext/highlightjs";
|
import { highlightAuto } from "@triliumnext/highlightjs";
|
||||||
|
import ejs from "ejs";
|
||||||
|
import escapeHtml from "escape-html";
|
||||||
|
import { readFileSync } from "fs";
|
||||||
|
import { t } from "i18next";
|
||||||
|
import { HTMLElement, Options,parse, TextNode } from "node-html-parser";
|
||||||
|
import { join } from "path";
|
||||||
|
|
||||||
import becca from "../becca/becca.js";
|
import becca from "../becca/becca.js";
|
||||||
import BAttachment from '../becca/entities/battachment.js';
|
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 } 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";
|
||||||
import SAttachment from "./shaca/entities/sattachment.js";
|
import SAttachment from "./shaca/entities/sattachment.js";
|
||||||
import { sanitizeUrl } from "@braintree/sanitize-url";
|
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";
|
||||||
|
|
||||||
const shareAdjustedAssetPath = isDev ? assetPath : `../${assetPath}`;
|
const shareAdjustedAssetPath = isDev ? assetPath : `../${assetPath}`;
|
||||||
const templateCache: Map<string, string> = new Map();
|
const templateCache: Map<string, string> = new Map();
|
||||||
@ -54,7 +56,7 @@ function getSharedSubTreeRoot(note: SNote | BNote | undefined): Subroot {
|
|||||||
return {
|
return {
|
||||||
note,
|
note,
|
||||||
branch: parentBranch
|
branch: parentBranch
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentBranch.parentNoteId === shareRoot.SHARE_ROOT_NOTE_ID) {
|
if (parentBranch.parentNoteId === shareRoot.SHARE_ROOT_NOTE_ID) {
|
||||||
@ -124,6 +126,7 @@ export function renderNoteContent(note: SNote) {
|
|||||||
|
|
||||||
const customLogoId = note.getRelation("shareLogo")?.value;
|
const customLogoId = note.getRelation("shareLogo")?.value;
|
||||||
const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png` : `../${assetUrlFragment}/images/icon-color.svg`;
|
const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png` : `../${assetUrlFragment}/images/icon-color.svg`;
|
||||||
|
const iconPacks = getIconPacks().filter(p => !!shaca.notes[p.manifestNoteId]);
|
||||||
|
|
||||||
return renderNoteContentInternal(note, {
|
return renderNoteContentInternal(note, {
|
||||||
subRoot,
|
subRoot,
|
||||||
@ -133,7 +136,10 @@ export function renderNoteContent(note: SNote) {
|
|||||||
logoUrl,
|
logoUrl,
|
||||||
ancestors,
|
ancestors,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
faviconUrl: note.hasRelation("shareFavicon") ? `api/notes/${note.getRelationValue("shareFavicon")}/download` : `../favicon.ico`
|
faviconUrl: note.hasRelation("shareFavicon") ? `api/notes/${note.getRelationValue("shareFavicon")}/download` : `../favicon.ico`,
|
||||||
|
iconPackCss: iconPacks.map(p => generateCss(p, true))
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("\n\n"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +152,7 @@ interface RenderArgs {
|
|||||||
ancestors: string[];
|
ancestors: string[];
|
||||||
isStatic: boolean;
|
isStatic: boolean;
|
||||||
faviconUrl: string;
|
faviconUrl: string;
|
||||||
|
iconPackCss: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderNoteContentInternal(note: SNote | BNote, renderArgs: RenderArgs) {
|
function renderNoteContentInternal(note: SNote | BNote, renderArgs: RenderArgs) {
|
||||||
@ -281,7 +288,7 @@ function renderText(result: Result, note: SNote | BNote) {
|
|||||||
if (typeof result.content !== "string") return;
|
if (typeof result.content !== "string") return;
|
||||||
const parseOpts: Partial<Options> = {
|
const parseOpts: Partial<Options> = {
|
||||||
blockTextElements: {}
|
blockTextElements: {}
|
||||||
}
|
};
|
||||||
const document = parse(result.content || "", parseOpts);
|
const document = parse(result.content || "", parseOpts);
|
||||||
|
|
||||||
// Process include notes.
|
// Process include notes.
|
||||||
|
|||||||
@ -84,6 +84,9 @@
|
|||||||
<meta name="twitter:image" content="<%= openGraphImage %>">
|
<meta name="twitter:image" content="<%= openGraphImage %>">
|
||||||
<!-- Meta Tags Generated via https://opengraph.dev -->
|
<!-- Meta Tags Generated via https://opengraph.dev -->
|
||||||
<meta name="theme-color" content="<%= openGraphColor %>">
|
<meta name="theme-color" content="<%= openGraphColor %>">
|
||||||
|
<style id="trilium-icon-packs">
|
||||||
|
<%- iconPackCss %>
|
||||||
|
</style>
|
||||||
<%- renderSnippets("head:end") %>
|
<%- renderSnippets("head:end") %>
|
||||||
</head>
|
</head>
|
||||||
<%
|
<%
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user