// Die reinen Update-Regeln (§ 6.8) — getrennt von update.ts, damit die // Tests sie ohne Electron laden können. export const STANDARD_UPDATE_URL = 'https://git.tobisniceshomelab.ddnsfree.com/Hitonabi/rippy/releases/download/aktuell' /** Prüft die Update-Adresse: NUR https:// ist zulässig (§ 6.8 Regel 1) — * ohne Code-Signing (Entscheid 5) ist der Transportweg die einzige * Absicherung; eine http://-Adresse wird ABGELEHNT, nicht still * akzeptiert. */ export function updateUrlPruefen(url: string): { ok: boolean; grund: string } { const sauber = url.trim() if (sauber.length === 0) return { ok: true, grund: '' } // Standard gilt if (sauber.startsWith('https://')) return { ok: true, grund: '' } return { ok: false, grund: 'Die Update-Adresse muss mit https:// beginnen — ohne Signatur ist der sichere Transportweg die einzige Absicherung (KONZEPT § 6.8).', } } /** So viel Änderungstext zeigt das Fenster höchstens — der Rest wird * abgeschnitten, damit eine ausufernde Datei die Karte nicht sprengt. */ export const NEUERUNGEN_HOECHSTENS = 4000 /** Die Änderungsnotizen aus `latest.yml` in reinen Text. * * `UpdateInfo.releaseNotes` ist laut builder-util-runtime * `string | Array | null` — bei uns ein String * (electron-builder legt den Inhalt von `bau/release-notes.md` hinein), * bei mehreren übersprungenen Versionen eine Liste. Beides muss hier * ankommen können, sonst steht im Fenster „[object Object]". * * HTML-Marken fliegen raus: Der Text kommt von einem Server, und auch * wenn React ihn ohnehin nur als Text setzt, wird hier nichts * weitergereicht, was wie Auszeichnung aussieht. */ export function neuerungenText(roh: unknown): string { const saubern = (t: string): string => t .replace(/<[^>]*>/g, ' ') .split('\n') .map((zeile) => zeile.replace(/[ \t]+$/, '')) .join('\n') .replace(/\n{3,}/g, '\n\n') .trim() if (typeof roh === 'string') return saubern(roh).slice(0, NEUERUNGEN_HOECHSTENS) if (Array.isArray(roh)) { const teile: string[] = [] for (const eintrag of roh) { if (eintrag === null || typeof eintrag !== 'object') continue const e = eintrag as { version?: unknown; note?: unknown } const version = typeof e.version === 'string' ? e.version : '' const notiz = typeof e.note === 'string' ? saubern(e.note) : '' if (notiz.length === 0) continue teile.push(version.length > 0 ? `${version}\n${notiz}` : notiz) } return teile.join('\n\n').slice(0, NEUERUNGEN_HOECHSTENS) } return '' }