diff --git a/backend/src/index.js b/backend/src/index.js index 84c7335..ca628d3 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -88,6 +88,12 @@ app.use(express.static(PUBLIC, { if (filePath.match(/\.(js|css)$/) && !filePath.includes('sw.js')) { res.setHeader('Cache-Control', 'public, max-age=31536000, immutable'); } + // index.html niemals cachen – auch nicht über express.static + if (filePath.endsWith('index.html')) { + res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate'); + res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); + } } })); @@ -95,6 +101,7 @@ app.use(express.static(PUBLIC, { app.get('*', (_req, res) => { res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate'); res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); res.sendFile(path.join(PUBLIC, 'index.html')); }); diff --git a/frontend/src/tools/devtools.jsx b/frontend/src/tools/devtools.jsx index 031288e..e99908b 100644 --- a/frontend/src/tools/devtools.jsx +++ b/frontend/src/tools/devtools.jsx @@ -1902,11 +1902,30 @@ function RegexBuilder({ toast, mobile }) { // Typografische Anführungszeichen und andere häufige Probleme beheben function sanitizeJson(raw) { - return raw - .replace(/[\u201C\u201D\u201E\u201F\u2018\u2019\u02BC]/g, '"') // „" "" usw → " - .replace(/[\u2018\u2019\u02BC\u0060]/g, '"') // ' ` → " - .replace(/,\s*([}\]])/g, '$1') // trailing commas - .replace(/([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1"$2":'); // unquoted keys + let s = raw + // Alle typografischen/deutschen Anführungszeichen → gerade " + .replace(/[\u201C\u201D\u201E\u201F\u00AB\u00BB\u2039\u203A]/g, '"') + // Einfache typografische → gerade " + .replace(/[\u2018\u2019\u02BC\u0060]/g, '"') + // Trailing commas vor } oder ] + .replace(/,\s*([}\]])/g, '$1') + // Unquoted keys: {key: ...} → {"key": ...} + .replace(/([{,]\s*)([a-zA-Z_\u00C0-\u024F][a-zA-Z0-9_\u00C0-\u024F]*)\s*:/g, '$1"$2":'); + + const trimmed = s.trim(); + + // Falls kein vollständiges JSON-Objekt/Array → versuche als Objekt-Fragment wrappen + // z.B. "Mitarbeiter": [...] → {"Mitarbeiter": [...]} + if (trimmed && !trimmed.startsWith('{') && !trimmed.startsWith('[') + && !trimmed.startsWith('"') && trimmed !== 'null' + && trimmed !== 'true' && trimmed !== 'false') { + s = '{' + trimmed + '}'; + } else if (trimmed && trimmed.startsWith('"') && trimmed.includes(':')) { + // Quoted key at root level: "key": value → {"key": value} + s = '{' + trimmed + '}'; + } + + return s; } // JSON → XML string @@ -2183,11 +2202,26 @@ function JsonTool({ toast, mobile }) { {/* Anleitung */}
-
SO FUNKTIONIERT ES
-
- JSON oder XML einfügen → der Baum unten zeigt die Struktur auf/zuklappbar.
- Pfeile ▸ anklicken zum Auf-/Zuklappen. Konvertierung in das andere Format erscheint automatisch.
- Tipp: Typografische Anführungszeichen „" werden automatisch korrigiert. +
SO FUNKTIONIERT ES
+
+ JSON oder XML einfügen → der Baum zeigt die Struktur auf/zuklappbar. Pfeile ▸ anklicken.
+ + Typografische Anführungszeichen „" werden automatisch korrigiert. Unvollständige Fragmente werden soweit möglich automatisch ergänzt. + +
+
+ {[ + ['Objekt { }','Zusammengehörige Felder eines Eintrags.\nBeispiel: eine Person mit Name und Alter.', + '{\n "name": "Max",\n "alter": 30\n}'], + ['Array [ ]','Eine Liste gleichartiger Einträge.\nBeispiel: mehrere Personen.', + '[\n {"name": "Max"},\n {"name": "Lisa"}\n]'], + ].map(([title,desc,ex])=>( +
+
{title}
+
{desc}
+
{ex}
+
+ ))}
@@ -2262,13 +2296,28 @@ function JsonTool({ toast, mobile }) { {/* Anleitung */}
-
SO FUNKTIONIERT DER BUILDER
-
- Klicke „+ Feld hinzufügen" um Felder zum Objekt oder zur Liste hinzuzufügen.
- Typen: Text = normaler Text · Zahl = Nummer · Ja/Nein = true/false · Leer = null
- Objekt {'{ }'} = verschachtelter Datensatz (z.B. Adresse mit Straße, PLZ) · - Liste [ ] = mehrere gleichartige Einträge (z.B. Mitarbeiterliste)
- Das fertige JSON/XML erscheint unten und kann kopiert werden. +
SO BAUST DU EINE STRUKTUR
+
+ Klicke „+ Feld hinzufügen" und wähle einen Typ. Felder können beliebig tief verschachtelt werden. +
+
+ {[ + ['Text (string)','#a8f0eb','Normaler Text.\nz.B. Name, Adresse, E-Mail','„Max Mustermann"'], + ['Zahl (number)','#ffe66d','Eine Zahl.\nz.B. Alter, Preis, Menge','42 oder 3.14'], + ['Ja/Nein (boolean)','#ff6b9d','Wahrheitswert.\nz.B. aktiv, sichtbar','true oder false'], + ['Objekt { }','#4ecdc4','Zusammengehörige Felder.\nz.B. eine Person mit Name + Alter','{ name, alter }'], + ['Liste [ ]','#ffe66d','Mehrere gleichartige Einträge.\nz.B. eine Mitarbeiterliste','[ {...}, {...} ]'], + ['Leer (null)','rgba(255,255,255,0.4)','Kein Wert vorhanden.\nz.B. optionales Feld','null'], + ].map(([title,color,desc,ex])=>( +
+
{title}
+
{desc}
+ {ex} +
+ ))} +
+
+ 💡 Beispiel „Mitarbeiterliste": Root-Objekt → Feld „Mitarbeiter" als Liste [ ] → in der Liste Einträge als Objekt {'{ }'} mit Feldern „vorname" und „nachname" als Text.