From c7383f3a774845a8519c9fc749b0d56d4a0c0d28 Mon Sep 17 00:00:00 2001 From: Kendrick Bollens Date: Tue, 23 Jun 2026 11:29:56 +0200 Subject: [PATCH] =?UTF-8?q?Release=20v2.3.5=20=E2=80=94=20Signatur-Sync:?= =?UTF-8?q?=20Web-Editor-Edits=20werden=20korrekt=20=C3=BCbernommen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull-Lookup für Signatur-Header war case-sensitiv gegen eine lowercase headerMap → Groß-/Leerzeichen-Namen wurden nie gefunden, Plugin fiel auf die lokale TB-Signatur zurück und revertierte beim Push die Web-Editor- Änderung. Jetzt: case-insensitive Lookup, kanonischer sigSlug (= Web-Editor- Format, lowercase-bindestrich) zum Lesen+Schreiben, Legacy-Format nur noch lesend, bei mehreren Treffern gewinnt der neueste Commit. Keine git-seitigen Breaking Changes — alte Plugin-Versionen (Groß-Dateien) bleiben kompatibel. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/gitea-sync.js | 49 +++++++++++++++++++++++++++++++++----- manifest.json | 2 +- templates-reply-hotel.xpi | Bin 449951 -> 451493 bytes updates.json | 10 ++++++++ 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/lib/gitea-sync.js b/lib/gitea-sync.js index 45aceb7..7bd5a55 100644 --- a/lib/gitea-sync.js +++ b/lib/gitea-sync.js @@ -400,6 +400,19 @@ class SyncManager { return { success: true, pushed }; } + // Kanonischer Signatur-Slug, identisch zum Web-Editor (slugifyHeaderName): + // toFilename(...) + lowercase + Leerzeichen→Bindestrich. So lesen/schreiben + // Web-Editor und Plugin DIESELBE Datei (z.B. ".kendrick-bollens.html"). + get sigSlug() { + return SyncManager.toFilename(this.config.authorName || '') + .toLowerCase() + .replace(/\s+/g, '-'); + } + + // Altes Plugin-Format (Groß-/Kleinschreibung + Leerzeichen, z.B. + // ".Kendrick Bollens.html"). Nur noch für Lese-Fallback, damit Dateien von + // Clients mit alter Plugin-Version weiterhin angewandt werden. Nicht mehr + // schreiben — sonst entstehen wieder Doppel-Dateien. get authorSlug() { return SyncManager.toFilename(this.config.authorName || ''); } @@ -567,11 +580,30 @@ class SyncManager { if (source.startsWith('=')) continue; - // Try personal header: email.authorslug.html - let targetFile = null; + // Personal-Header suchen. headerMap-Keys sind lowercase, daher + // Kandidaten ebenfalls lowercase nachschlagen (behebt den Bug, + // dass Groß-Namen NIE gefunden wurden → Plugin fiel auf die lokale + // Signatur zurück und revertierte beim Push die Web-Editor-Änderung). + // Kandidaten: + // • kanonisches Web-Editor-Format (lowercase-bindestrich) + // • altes Plugin-Format (Groß/Leerzeichen) von Clients mit alter Version + // Bei mehreren Treffern gewinnt der NEUESTE Commit — so verdeckt eine + // veraltete Datei keine frische Web-Editor-Änderung, egal welche der + // beiden Dateien zuletzt im Web-Editor bearbeitet wurde. + const candidates = []; + if (this.sigSlug) { + const f = headerMap[`${email}.${this.sigSlug}.html`.toLowerCase()]; + if (f) candidates.push(f); + } if (this.authorSlug) { - const personalName = `${email}.${this.authorSlug}.html`; - targetFile = headerMap[personalName] || null; + const f = headerMap[`${email}.${this.authorSlug}.html`.toLowerCase()]; + if (f && !candidates.includes(f)) candidates.push(f); + } + let targetFile = null; + let targetTime = -1; + for (const f of candidates) { + const t = Date.parse(f.last_author_date || f.last_committer_date || '') || 0; + if (t >= targetTime) { targetFile = f; targetTime = t; } } let header = null; @@ -634,7 +666,7 @@ class SyncManager { async pushSignatures() { if (!this.isConfigured) throw new Error('Sync nicht konfiguriert'); if (!this.config.authorName) throw new Error('Bitte Name eintragen (für Commit-Zuordnung)'); - if (!this.authorSlug) throw new Error('Name fehlt für Dateiname'); + if (!this.sigSlug) throw new Error('Name fehlt für Dateiname'); const sourceResult = await browser.storage.local.get('sig_source_map'); const sourceMap = sourceResult.sig_source_map || {}; @@ -655,7 +687,12 @@ class SyncManager { const header = SyncManager.extractHeader(identity.signature); if (!header.trim()) continue; - const filename = `${email}.${this.authorSlug}.html`; + // Ins kanonische Web-Editor-Format schreiben (lowercase-bindestrich), + // damit Plugin und Web-Editor dieselbe Datei pflegen. Alte + // Groß-Dateien bleiben unangetastet (keine Breaking Changes für + // Clients mit alter Plugin-Version), werden aber nicht mehr neu + // geschrieben. + const filename = `${email}.${this.sigSlug}.html`; const filepath = `signatures/headers/${filename}`; const commitMsg = `Signatur-Header ${identity.email} - von ${this.config.authorName}`; diff --git a/manifest.json b/manifest.json index 7ab97d6..f5a42c9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "HPS Vorlagen & Signaturen", - "version": "2.3.4", + "version": "2.3.5", "description": "Vorlagen- und Signaturverwaltung für Hotel Park Soltau mit Git-Sync", "browser_specific_settings": { "gecko": { diff --git a/templates-reply-hotel.xpi b/templates-reply-hotel.xpi index 2b7b0082bb67ee3c28d32eea616456f6d8c079b0..c3fcee4f400daa8a022af2574929eab28923aee3 100644 GIT binary patch delta 10398 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