diff --git a/public/analyse-cards.js b/public/analyse-cards.js index 054d473..49bfed3 100644 --- a/public/analyse-cards.js +++ b/public/analyse-cards.js @@ -19,10 +19,9 @@ Fehler section.an-card.an-error[role=alert] > p + button.an-btn#an-retry */ import { esc } from './fn-util.js' -import { fmtNum, fmtDuration, periodLabel, shortDay, dayLabel, compareFrom, delta, contactRate, refName, summarize, chartModel, barRows, countryName, flagEmoji, DEVICE_LABELS } from './analyse-view.js' +import { fmtNum, fmtDuration, periodLabel, shortDay, dayLabel, compareFrom, delta, contactRate, refName, summarize, chartModel, barRows, countryName, flagEmoji, DEVICE_LABELS, bannerColor } from './analyse-view.js' const RANGES = [7, 30, 90] -const HEX_RE = /^#[0-9a-f]{6}$/i const isNum = (v) => typeof v === 'number' && Number.isFinite(v) const num = (v) => (Number.isFinite(Number(v)) ? Number(v) : 0) const round = (n) => Math.round(n * 10) / 10 @@ -250,7 +249,7 @@ const hrefOk = (url) => typeof url === 'string' && /^(\/(?!\/)|https?:\/\/)/i.te export function settingsHtml(project) { const a = project?.analyse || {} - const color = HEX_RE.test(a.accentColor || '') ? a.accentColor.toLowerCase() : '#111111' + const color = bannerColor(a.accentColor) // wie auf der Website: zu helle Farbe => #111111 const since = a.activatedAt ? new Date(a.activatedAt) : null const status = `Analyse aktiv${since && !Number.isNaN(since.getTime()) ? ` seit ${BERLIN_DATE.format(since)}` : ''}` const rows = [ diff --git a/test/analyseCards.test.js b/test/analyseCards.test.js index 2e412da..00a24bd 100644 --- a/test/analyseCards.test.js +++ b/test/analyseCards.test.js @@ -303,6 +303,10 @@ test('settingsHtml: aktiv seit TT.MM.JJJJ, Farbfeld, Fassung, Links AVV und Leis const bad = settingsHtml(project({ analyse: { state: 'active', accentColor: 'red;">', avvVersion: '2026-10-02', legal: {}, activatedAt: null } })) assert.match(bad, /background:#111111/); assert.doesNotMatch(bad, /|seit| klein // gefährliche Link-Ziele und Namen const evil = settingsHtml(project({ analyse: { state: 'active', accentColor: '#fff', avvVersion: '', legal: { avv: 'javascript:alert(1)', lb: '/x"onmouseover="y' }, activatedAt: 'kaputt' } })) assert.doesNotMatch(evil, /javascript:||onmouseover="y/); assert.doesNotMatch(evil, /NaN|undefined|null|Invalid/)