From 9ea13716963046c32de8272e59c4b58cd2e41e44 Mon Sep 17 00:00:00 2001 From: Cedric Date: Sat, 3 Oct 2026 15:39:15 +0200 Subject: [PATCH] Compact density and built-in Iosevka font for denser log display Settings > Interface > Log display gets a Density switch (Normal/Compact) that tightens row padding and line height, and the font list gets Iosevka, a narrow SIL OFL monospace font served from web/fonts (Latin subset, 13 KB per weight) so it works offline, unlike the Bunny Fonts ones. Co-Authored-By: Claude Opus 5.5 (1M context) --- README.fr.md | 19 ++++--- README.md | 15 +++-- web/app.js | 40 ++++++++++--- web/fonts/OFL-Iosevka.txt | 110 ++++++++++++++++++++++++++++++++++++ web/fonts/iosevka-400.woff2 | Bin 0 -> 13184 bytes web/fonts/iosevka-700.woff2 | Bin 0 -> 13152 bytes web/index.html | 5 ++ web/style.css | 13 ++++- 8 files changed, 179 insertions(+), 23 deletions(-) create mode 100644 web/fonts/OFL-Iosevka.txt create mode 100644 web/fonts/iosevka-400.woff2 create mode 100644 web/fonts/iosevka-700.woff2 diff --git a/README.fr.md b/README.fr.md index bd300f9..febd70e 100644 --- a/README.fr.md +++ b/README.fr.md @@ -243,14 +243,17 @@ couleur, est mémorisé par navigateur. - **Interface** - *Thème* : Système (suit la préférence de l'ordinateur ou du téléphone), Clair ou Sombre. Le bouton soleil/lune de l'en-tête bascule entre clair et sombre. - - *Affichage des logs* : taille du texte (très petite, petite, moyenne, grande) et police : - la police monospace du système, ou l'une des 12 polices libres conçues pour le texte dense - (JetBrains Mono, Fira Code, Source Code Pro, IBM Plex Mono, Cascadia Code, Roboto Mono, - Ubuntu Mono, Inconsolata, Red Hat Mono, Noto Sans Mono, Victor Mono, DM Mono). Elles sont - chargées par le navigateur depuis [Bunny Fonts](https://fonts.bunny.net), un service - européen de polices respectueux de la vie privée ; sans accès à internet, la police du - système est utilisée. Les ligatures sont désactivées pour que `->` ou `!=` s'affichent tels - quels. + - *Affichage des logs* : taille du texte (très petite, petite, moyenne, grande), densité + (normale, ou compacte pour afficher environ 50 % de lignes en plus à l'écran) et police : + la police monospace du système, [Iosevka](https://github.com/be5invis/Iosevka) (étroite, + donc plus de texte par ligne ; servie par LogStream lui-même, fonctionne hors ligne), ou + l'une des 12 polices libres conçues pour le texte dense (JetBrains Mono, Fira Code, Source + Code Pro, IBM Plex Mono, Cascadia Code, Roboto Mono, Ubuntu Mono, Inconsolata, Red Hat Mono, + Noto Sans Mono, Victor Mono, DM Mono). Ces 12 polices sont chargées par le navigateur depuis + [Bunny Fonts](https://fonts.bunny.net), un service européen de polices respectueux de la vie + privée ; sans accès à internet, la police du système est utilisée. Les ligatures sont + désactivées pour que `->` ou `!=` s'affichent tels quels. Le réglage le plus dense est Très + petite + Compacte + Iosevka. - **Données** : « Supprimer tous les logs » efface définitivement tous les logs stockés (il faut taper `PURGE` pour confirmer). Les tags et les paramètres sont conservés. VictoriaLogs doit être lancé avec `-delete.enable` (déjà présent dans `docker-compose.yml`) ; mettez diff --git a/README.md b/README.md index edcf628..bb4f266 100644 --- a/README.md +++ b/README.md @@ -222,12 +222,15 @@ remembered per browser. - **Interface** - *Theme*: System (follows the computer/phone preference), Light or Dark. The sun/moon button in the header switches between light and dark. - - *Log display*: font size (tiny, small, medium, large) and font: the system monospace - font, or one of 12 free fonts made for dense text (JetBrains Mono, Fira Code, Source - Code Pro, IBM Plex Mono, Cascadia Code, Roboto Mono, Ubuntu Mono, Inconsolata, Red Hat - Mono, Noto Sans Mono, Victor Mono, DM Mono). They are loaded by the browser from - [Bunny Fonts](https://fonts.bunny.net), a privacy-friendly European font service; without - internet access, the system font is used. Ligatures are disabled so `->` or `!=` show as typed. + - *Log display*: font size (tiny, small, medium, large), density (normal, or compact to + fit about 50% more lines on screen) and font: the system monospace font, + [Iosevka](https://github.com/be5invis/Iosevka) (narrow, so more text fits on each line; + served by LogStream itself, works offline), or one of 12 free fonts made for dense text + (JetBrains Mono, Fira Code, Source Code Pro, IBM Plex Mono, Cascadia Code, Roboto Mono, + Ubuntu Mono, Inconsolata, Red Hat Mono, Noto Sans Mono, Victor Mono, DM Mono). These 12 are + loaded by the browser from [Bunny Fonts](https://fonts.bunny.net), a privacy-friendly + European font service; without internet access, the system font is used. Ligatures are + disabled so `->` or `!=` show as typed. The densest setting is Tiny + Compact + Iosevka. - **Data**: "Delete all logs" permanently erases every stored log (you must type `PURGE` to confirm). Tags and settings are kept. VictoriaLogs needs `-delete.enable` (already set in `docker-compose.yml`); set `ALLOW_PURGE=false` to disable the feature. diff --git a/web/app.js b/web/app.js index 45314a1..9243ee7 100644 --- a/web/app.js +++ b/web/app.js @@ -120,8 +120,9 @@ const I18N = { themeHelp: 'System follows the light/dark preference of your computer or phone.', logDisplay: 'Log display', fontSize: 'Font size', sizeTiny: 'Tiny', sizeSmall: 'Small', sizeMedium: 'Medium', sizeLarge: 'Large', - fontLabel: 'Font', fontSystem: 'System monospace (no download)', - fontHelp: 'Free fonts (SIL Open Font License) loaded by your browser from Bunny Fonts, a privacy-friendly European font service. Without internet access, the system font is used.', + density: 'Density', densityNormal: 'Normal', densityCompact: 'Compact', + fontLabel: 'Font', fontSystem: 'System monospace (no download)', fontBuiltin: 'built in, narrow', + fontHelp: 'Free fonts (SIL Open Font License). Iosevka is served by LogStream itself and works offline; it is narrow, so more text fits on each line. The others are loaded by your browser from Bunny Fonts, a privacy-friendly European font service; without internet access, the system font is used.', previewMsgs: ['error: link down on eth1, carrier lost', 'warning: disk /dev/sda temperature 58°C', 'backup finished: ok (12.4 GB in 00:14:32)'], dangerZone: 'Danger zone', purgeHelp: 'Permanently delete every stored log to start from scratch. Color tags and settings are kept.', @@ -273,8 +274,9 @@ const I18N = { themeHelp: 'Système suit la préférence clair/sombre de votre ordinateur ou de votre téléphone.', logDisplay: 'Affichage des logs', fontSize: 'Taille du texte', sizeTiny: 'Très petite', sizeSmall: 'Petite', sizeMedium: 'Moyenne', sizeLarge: 'Grande', - fontLabel: 'Police', fontSystem: 'Monospace du système (aucun téléchargement)', - fontHelp: 'Polices libres (licence SIL Open Font) chargées par votre navigateur depuis Bunny Fonts, un service européen respectueux de la vie privée. Sans accès à internet, la police du système est utilisée.', + density: 'Densité', densityNormal: 'Normale', densityCompact: 'Compacte', + fontLabel: 'Police', fontSystem: 'Monospace du système (aucun téléchargement)', fontBuiltin: 'intégrée, étroite', + fontHelp: 'Polices libres (licence SIL Open Font). Iosevka est servie par LogStream lui-même et fonctionne hors ligne ; elle est étroite, donc chaque ligne affiche plus de texte. Les autres sont chargées par votre navigateur depuis Bunny Fonts, un service européen respectueux de la vie privée ; sans accès à internet, la police du système est utilisée.', previewMsgs: ['error: link down on eth1, carrier lost', 'warning: disk /dev/sda temperature 58°C', 'backup finished: ok (12.4 GB in 00:14:32)'], dangerZone: 'Zone de danger', purgeHelp: 'Supprime définitivement tous les logs stockés pour repartir de zéro. Les tags de couleur et les réglages sont conservés.', @@ -537,9 +539,11 @@ $('#themeSwitch').addEventListener('click', (ev) => { /* ================= Log font and size ================= */ -// Free monospace fonts, served by Bunny Fonts (https://fonts.bunny.net). +// Free monospace fonts, served by Bunny Fonts (https://fonts.bunny.net), except the +// built-in ones (web/fonts, declared in style.css), which also work offline. const LOG_FONTS = [ { id: 'system' }, + { id: 'iosevka', family: 'Iosevka', builtin: true }, { id: 'jetbrains-mono', family: 'JetBrains Mono' }, { id: 'fira-code', family: 'Fira Code' }, { id: 'source-code-pro', family: 'Source Code Pro' }, @@ -554,7 +558,8 @@ const LOG_FONTS = [ { id: 'dm-mono', family: 'DM Mono', weights: '400,500' }, ]; const LOG_SIZES = { tiny: '10.5px', small: '11.5px', medium: '12.5px', large: '14px' }; -const ui = { font: 'system', size: 'medium' }; +const LOG_DENSITIES = ['normal', 'compact']; +const ui = { font: 'system', size: 'medium', density: 'normal' }; function applyLogFont(id) { const f = LOG_FONTS.find((x) => x.id === id) || LOG_FONTS[0]; @@ -564,6 +569,10 @@ function applyLogFont(id) { root.removeProperty('--log-font'); return; } + if (f.builtin) { + root.setProperty('--log-font', `'${f.family}', var(--mono)`); + return; + } const href = `https://fonts.bunny.net/css?family=${f.id}:${f.weights || '400,700'}&display=swap`; let link = document.getElementById('logFontCss'); if (!link) { @@ -579,13 +588,22 @@ function applyLogSize(id) { document.documentElement.style.setProperty('--log-size', LOG_SIZES[ui.size]); } +function applyLogDensity(id) { + ui.density = LOG_DENSITIES.includes(id) ? id : 'normal'; + document.documentElement.dataset.density = ui.density; +} + function renderInterface() { renderThemeSwitch(); for (const b of document.querySelectorAll('#sizeSwitch [data-size]')) { b.setAttribute('aria-checked', String(b.dataset.size === ui.size)); } + for (const b of document.querySelectorAll('#densitySwitch [data-density]')) { + b.setAttribute('aria-checked', String(b.dataset.density === ui.density)); + } const sel = $('#fontSelect'); - sel.innerHTML = LOG_FONTS.map((f) => ``).join(''); + const fontName = (f) => (!f.family ? t('fontSystem') : f.builtin ? `${f.family} (${t('fontBuiltin')})` : f.family); + sel.innerHTML = LOG_FONTS.map((f) => ``).join(''); sel.value = ui.font; renderFontPreview(); renderHistoSettings(); @@ -609,6 +627,13 @@ $('#sizeSwitch').addEventListener('click', (ev) => { store.set('logSize', ui.size); renderInterface(); }); +$('#densitySwitch').addEventListener('click', (ev) => { + const b = ev.target.closest('[data-density]'); + if (!b) return; + applyLogDensity(b.dataset.density); + store.set('logDensity', ui.density); + renderInterface(); +}); $('#fontSelect').addEventListener('change', (ev) => { applyLogFont(ev.target.value); store.set('logFont', ui.font); @@ -2190,6 +2215,7 @@ $('#settingsDlg').addEventListener('click', (ev) => { if (ev.target === ev.curre } applyLogFont(store.get('logFont', 'system')); applyLogSize(store.get('logSize', 'medium')); +applyLogDensity(store.get('logDensity', 'normal')); applyLang(); $('#range').value = store.get('range', '1h'); if (!$('#range').value) $('#range').value = '1h'; diff --git a/web/fonts/OFL-Iosevka.txt b/web/fonts/OFL-Iosevka.txt new file mode 100644 index 0000000..b2a7b6a --- /dev/null +++ b/web/fonts/OFL-Iosevka.txt @@ -0,0 +1,110 @@ +Copyright (c) 2015-2023, Renzhi Li (aka. Belleve Invis, belleve@typeof.net) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +-------------------------- + + +SIL Open Font License v1.1 +==================================================== + + +Preamble +---------- + +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + + +Definitions +------------- + +`"Font Software"` refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +`"Reserved Font Name"` refers to any names specified as such after the +copyright statement(s). + +`"Original Version"` refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +`"Modified Version"` refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +`"Author"` refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + + +Permission & Conditions +------------------------ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1. Neither the Font Software nor any of its individual components, + in Original or Modified Versions, may be sold by itself. + +2. Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + +3. No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the corresponding + Copyright Holder. This restriction only applies to the primary font name as + presented to the users. + +4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + +5. The Font Software, modified or unmodified, in part or in whole, + must be distributed entirely under this license, and must not be + distributed under any other license. The requirement for fonts to + remain under this license does not apply to any document created + using the Font Software. + + + +Termination +----------- + +This license becomes null and void if any of the above conditions are +not met. + + + DISCLAIMER + + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/web/fonts/iosevka-400.woff2 b/web/fonts/iosevka-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..80d83abb3c5c753cbbead64a3a3b3a783c2732a6 GIT binary patch literal 13184 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 literal 0 HcmV?d00001 diff --git a/web/fonts/iosevka-700.woff2 b/web/fonts/iosevka-700.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..cf34747049c0d1b94a2adb1b993ad8b57d8add4e GIT binary patch literal 13152 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 G0096&_hvEx literal 0 HcmV?d00001 diff --git a/web/index.html b/web/index.html index 89116ed..f4b0ed4 100644 --- a/web/index.html +++ b/web/index.html @@ -282,6 +282,11 @@ + Density +
+ + +
diff --git a/web/style.css b/web/style.css index 3035f8f..87a8982 100644 --- a/web/style.css +++ b/web/style.css @@ -1,3 +1,8 @@ +/* Iosevka (SIL OFL, web/fonts/OFL-Iosevka.txt): a narrow monospace font served by LogStream + itself, so it also works offline. Latin subset only; other scripts fall back to --mono. */ +@font-face { font-family: "Iosevka"; src: url("fonts/iosevka-400.woff2") format("woff2"); font-weight: 400 500; font-display: swap; } +@font-face { font-family: "Iosevka"; src: url("fonts/iosevka-700.woff2") format("woff2"); font-weight: 600 800; font-display: swap; } + /* ---------- Theme: everything goes through these variables ---------- */ :root { --bg: #f6f7f9; @@ -342,6 +347,9 @@ body.col-resizing, body.col-resizing * { cursor: col-resize !important; user-sel cursor: pointer; } .row:last-child { border-bottom: 0; } +/* Settings > Interface > Density: compact fits about 50% more lines on screen */ +:root[data-density="compact"] .row { padding-top: 1px; padding-bottom: 1px; line-height: 1.25; } +:root[data-density="compact"] .row .sev { padding-top: 0; padding-bottom: 0; line-height: 1.3; } .row:hover { background: var(--row-hover); } .row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; } .row.new { animation: flash 1.2s ease-out; } @@ -678,8 +686,9 @@ input.switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2 } .set-nav button span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; } .set-panels { padding: 0 16px 18px; } - #sizeSwitch { display: flex; } - #sizeSwitch button { flex: 1; padding: 0 4px; white-space: nowrap; font-size: 12px; } + #sizeSwitch, #densitySwitch { display: flex; } + #sizeSwitch button, #densitySwitch button { flex: 1; padding: 0 4px; white-space: nowrap; font-size: 12px; } + :root[data-density="compact"] .row { padding-top: 3px; padding-bottom: 3px; } .field-grid select { margin-bottom: 6px; } .status { padding: 6px 16px; } .tag-row { grid-template-columns: auto 38px 1fr 36px; }