fix(community): Pixelgrenze beim Anzeigen, exakter Tag-Filter, unsichtbare Zeichen
- Gemeinsamer Helfer loadGalleryImageChecked/checkGalleryImage (gallery.ts): lädt das Bild über new Image(), lehnt über 4 Megapixel oder nicht dekodierbare Dateien ab und liefert eine fertige Object-URL (der Aufrufer gibt sie frei). Raster -> „Keine Vorschau“ (auch bei <img>-Fehler), Hero -> Beispielmotiv, Detailseite -> „Das Bild konnte nicht geladen werden.“ Verspätet eintreffende URLs werden sofort freigegeben. - Tag-Filter sucht ",<tag>," (der Server speichert ",a,b,"): „gold“ trifft nicht mehr „marigold“. - Veröffentlichen-Dialog lehnt dieselben unsichtbaren Zeichen ab wie die API (C1, Nullbreite, Bidi, BOM). - Das Limit der API (429 „schon 20 Karten veröffentlicht“) gilt als eindeutige Ablehnung: die hochgeladenen Dateien werden aufgeräumt. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5500495443
commit
c62075f2d4
12 files changed
+435
-66
No files matched your search
@@ -151,6 +151,42 @@ describe('Veröffentlichen-Dialog: Prüfung vor dem Senden', () => {
|
||||
await invalid({ title: 'a\tb' }, 'Der Titel enthält ungültige Zeichen.', 'title');
|
||||
});
|
||||
|
||||
// Dasselbe Muster wie deploy/api/app.js: C1-Steuerzeichen, Nullbreiten-, Bidi-Zeichen und BOM sind unsichtbar oder ordnen Text um.
|
||||
it.each([
|
||||
['Nullbreiten-Leerzeichen', 'a\u200bb'],
|
||||
['Rechts-nach-links-Überschreibung', 'foto\u202egnp.exe'],
|
||||
['Isolate', 'a\u2066b'],
|
||||
['Wortverbinder', 'a\u2060b'],
|
||||
['C1-Steuerzeichen', 'a\u0085b'],
|
||||
['BOM mitten im Titel', 'a\ufeffb'],
|
||||
])('unsichtbare Zeichen werden abgelehnt: %s (Titel)', async (_name, title) => {
|
||||
await invalid({ title }, 'Der Titel enthält ungültige Zeichen.', 'title');
|
||||
});
|
||||
|
||||
it('ein Titel nur aus unsichtbaren Zeichen gilt als ungültig', async () => {
|
||||
await invalid({ title: '\u200b\u200d' }, 'Der Titel enthält ungültige Zeichen.', 'title');
|
||||
});
|
||||
|
||||
it('unsichtbare Zeichen in Herausgeber, Tags und Anzeigename', async () => {
|
||||
await invalid({ issuer: 'Bank\u200f' }, 'Herausgeber / Bank enthält ungültige Zeichen.', 'issuer');
|
||||
});
|
||||
|
||||
it('unsichtbares Zeichen in einem Tag', async () => {
|
||||
await invalid({ tags: 'visa, gol\u200bd' }, 'Tags enthalten ungültige Zeichen.', 'tags');
|
||||
});
|
||||
|
||||
it('unsichtbares Zeichen im Anzeigenamen', async () => {
|
||||
await invalid({ displayName: 'Ken\u2060so' }, 'Der Anzeigename enthält ungültige Zeichen.', 'displayName');
|
||||
});
|
||||
|
||||
it('normale Sonderzeichen (Umlaute, Emoji, Bindestrich, Zeilenabstand durch Leerzeichen) bleiben erlaubt', async () => {
|
||||
submit.mockResolvedValue({ id: 'g1' });
|
||||
const outcome = open();
|
||||
fill({ title: 'Größe 😀 – Möwe', issuer: 'Café-Bank', displayName: 'Zoë', tags: 'grün, ✨' });
|
||||
send();
|
||||
await expect(outcome).resolves.toBe('published');
|
||||
});
|
||||
|
||||
it('Grenzen sind inklusive: 60/40/30 Zeichen und fünf Tags gehen durch; doppelte und leere Tags zählen nicht', async () => {
|
||||
submit.mockResolvedValue({ id: 'g1' });
|
||||
const outcome = open();
|
||||
|
||||
Reference in new issue
Block a user