Allow custom favicon URL. Closes #3365

This commit is contained in:
Mike Cao 2025-04-25 13:59:23 -07:00
parent ffa8d8dd88
commit 02f0df3a2e
3 changed files with 14 additions and 10 deletions

View file

@ -1,5 +1,9 @@
/* eslint-disable @typescript-eslint/no-var-requires */ import dotenv from 'dotenv';
require('dotenv').config(); import { createRequire } from 'module';
dotenv.config();
const require = createRequire(import.meta.url);
const pkg = require('./package.json'); const pkg = require('./package.json');
const TRACKER_SCRIPT = '/script.js'; const TRACKER_SCRIPT = '/script.js';
@ -12,6 +16,7 @@ const corsMaxAge = process.env.CORS_MAX_AGE;
const defaultLocale = process.env.DEFAULT_LOCALE; const defaultLocale = process.env.DEFAULT_LOCALE;
const disableLogin = process.env.DISABLE_LOGIN; const disableLogin = process.env.DISABLE_LOGIN;
const disableUI = process.env.DISABLE_UI; const disableUI = process.env.DISABLE_UI;
const faviconURL = process.env.FAVICON_URL;
const forceSSL = process.env.FORCE_SSL; const forceSSL = process.env.FORCE_SSL;
const frameAncestors = process.env.ALLOWED_FRAME_URLS; const frameAncestors = process.env.ALLOWED_FRAME_URLS;
const privateMode = process.env.PRIVATE_MODE; const privateMode = process.env.PRIVATE_MODE;
@ -180,17 +185,17 @@ if (cloudMode && cloudUrl) {
} }
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const config = { export default {
reactStrictMode: false, reactStrictMode: false,
env: { env: {
basePath, basePath,
cloudMode, cloudMode,
cloudUrl, cloudUrl,
configUrl: '/config',
currentVersion: pkg.version, currentVersion: pkg.version,
defaultLocale, defaultLocale,
disableLogin, disableLogin,
disableUI, disableUI,
faviconURL,
privateMode, privateMode,
}, },
basePath, basePath,
@ -237,5 +242,3 @@ const config = {
return [...redirects]; return [...redirects];
}, },
}; };
module.exports = config;

View file

@ -1,4 +1,4 @@
import { GROUPED_DOMAINS } from '@/lib/constants'; import { FAVICON_URL, GROUPED_DOMAINS } from '@/lib/constants';
function getHostName(url: string) { function getHostName(url: string) {
const match = url.match(/^(?:https?:\/\/)?(?:[^@\n]+@)?([^:/\n?=]+)/im); const match = url.match(/^(?:https?:\/\/)?(?:[^@\n]+@)?([^:/\n?=]+)/im);
@ -10,10 +10,10 @@ export function Favicon({ domain, ...props }) {
return null; return null;
} }
const url = process.env.faviconURL || FAVICON_URL;
const hostName = domain ? getHostName(domain) : null; const hostName = domain ? getHostName(domain) : null;
const src = hostName const domainName = GROUPED_DOMAINS[hostName]?.domain || hostName;
? `https://icons.duckduckgo.com/ip3/${GROUPED_DOMAINS[hostName]?.domain || hostName}.ico` const src = hostName ? url.replace(/\{\{\s*domain\s*}}/, domainName) : null;
: null;
return hostName ? <img src={src} width={16} height={16} alt="" {...props} /> : null; return hostName ? <img src={src} width={16} height={16} alt="" {...props} /> : null;
} }

View file

@ -12,6 +12,7 @@ export const HOMEPAGE_URL = 'https://umami.is';
export const REPO_URL = 'https://github.com/umami-software/umami'; export const REPO_URL = 'https://github.com/umami-software/umami';
export const UPDATES_URL = 'https://api.umami.is/v1/updates'; export const UPDATES_URL = 'https://api.umami.is/v1/updates';
export const TELEMETRY_PIXEL = 'https://i.umami.is/a.png'; export const TELEMETRY_PIXEL = 'https://i.umami.is/a.png';
export const FAVICON_URL = 'https://icons.duckduckgo.com/ip3/{{domain}}.ico';
export const DEFAULT_LOCALE = process.env.defaultLocale || 'en-US'; export const DEFAULT_LOCALE = process.env.defaultLocale || 'en-US';
export const DEFAULT_THEME = 'light'; export const DEFAULT_THEME = 'light';