Teilen gibt einen fertigen Discord-Beitrag -- und die zwei Seiten bekommen ein Gesicht
Filipe: "beim teilen wird auch nur der link geteilt, und ich will dass
wenn ich es teile im discord der agentur, dass ein banner und ein
kompletter fertiger text fuer die creator entsteht und nicht einfach
der link kopiert wird damit die leute drauf gehen. das ist kake."
Und: "perfektionier die zwei events kategorien. ich will es noch viel
krasser und spezieller."
EIN LINK IN EINEM DISCORD-KANAL IST EINE AUFFORDERUNG. Wer ihn nicht
anklickt -- und das sind die meisten -- weiss nicht, dass es die
Kampagne gibt. Was in Discord steht, muss die Kampagne SEIN. Der
Teilen-Knopf legt deshalb einen fertigen Beitrag in die Zwischenablage:
Titel als Ueberschrift, Zeitraum, Einleitung, die Aufgaben als Liste,
die Geschenke mit Coinpreis, "Gut zu wissen" aus Rangliste, Zeitplan
und Teilnahme. Er steht zusaetzlich sichtbar unter der Kachel, mit
Zeichenzaehler und zweitem Kopierknopf -- was man nicht gesehen hat,
fuegt man blind ein.
ZWEI DINGE SIND DABEI NICHT BELIEBIG:
- Der Link steht GANZ AM ENDE. Discord setzt die Bannervorschau
UNTER die Nachricht; steht er oben, schiebt das Banner den Text
aus dem Blick.
- Der Link steht NACKT da. Spitze Klammern unterdruecken die
Vorschau -- und damit genau das Banner, um das es geht.
2000 ZEICHEN, UND NICHT EINS MEHR. Gekuerzt wird auf dem Server, in
fester Reihenfolge und an Abschnittsgrenzen: erst "Gut zu wissen",
dann die Einleitung auf zwei Saetze, dann die Geschenke. Titel,
Zeitraum, Aufgaben und Link bleiben IMMER. Gemessen gegen sieben
Laengen und einen 1500-Zeichen-Titel als Haertefall.
Gebaut wird der Beitrag aus `teilenDaten()` -- derselben Funktion, aus
der auch die offene Seite entsteht. Zwei Aufbauten fuer dasselbe Event
wuerden irgendwann Verschiedenes sagen, und niemand koennte entscheiden,
welcher recht hat.
DIE ZWEI SEITEN: ein gezeichnetes Wappen in der Farbe der Spalte, ein
Kopf mit Lichtkante und Verlauf, der beim Scrollen oben stehen bleibt,
und eine Lagezeile ("2 laufen - 1 kommt - 3 vorbei"). Gezaehlt mit
derselben Regel, die die Gruppen darunter bildet; was null ist,
erscheint nicht. Augenschonend bleibt es ueber Form und Tiefe, nicht
ueber Leuchtkraft.
NEBENBEFUND, BEHOBEN: Der Einlesekasten war durch Seitenwahl und
Bildweg auf 521 px gewachsen -- auf 412 px mehr als ein halber
Telefonbildschirm, bevor man die erste Kachel sieht. Er klappt jetzt zu
(82 px) und merkt sich die Wahl; ein Druck, und er bleibt offen.
BERICHTIGT, WEIL GEMESSEN:
- Der Bindestrich wurde entwertet: "4\-woechige", "Ahorn\-Welt". In
Discord ist "-" nur am Zeilenanfang eine Aufzaehlung.
- Das Klappschild hatte nur eine Handy-Regel und sonst kein
Aussehen -- auf 1400 px ein nackter Knopf mit 27 px statt 48.
- bild-kampagne mass elementFromPoint ausserhalb des
Sichtfensters und meldete "etwas liegt auf dem Knopf", wo nichts
lag; und r(null) liess den ganzen Lauf abstuerzen, statt die
Zusicherung rot zu machen.
- EINE GEGENPROBE WAR BLIND: DISCORD_MAX von 2000 auf 99999 zu
setzen liess die Pruefung gruen -- der Testbeitrag ist 1230
Zeichen lang, die Grenze wurde also nie geprueft. Jetzt mit einem
Beitrag, der ohne Kuerzung sicher zu lang waere.
GEPRUEFT: 190 (Route und Teilen, +8), 183 (Kachel, +13), 69 Messungen
(Bild, +2), 67 (Agentur), 43 (Bildleser), struktur, css-klassen,
zeichen, deutsche-texte, tippziele. Sechs Gegenproben: Link nur noch
Link, Link oben statt unten, Grenze weg, Lagezeile weg, Kopf klebt
nicht, Kasten wieder offen -- alle sechs werden bemerkt, alle Dateien
byte-gleich wiederhergestellt.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -1423,6 +1423,127 @@ melde("\n=== 4c. Die Seitenwahl ===");
|
||||
ok(links.includes("Oktober Event") && links.includes("Glow Up Struktur"),
|
||||
`ohne Wahl entscheidet weiterhin die Herkunft (links: ${JSON.stringify(links)})`);
|
||||
|
||||
/* ---- DIE ZWEI SEITEN, KRASSER (08.10.2026) ----------------
|
||||
|
||||
Filipe: „perfektionier die zwei events kategorien. ich will es
|
||||
noch viel krasser und spezieller.“
|
||||
|
||||
Gemessen wird, was dabei herauskommen SOLL, und zwar so, dass ein
|
||||
leerer Kasten nicht durchrutscht: Jede Zusicherung trägt die Zahl
|
||||
der untersuchten Dinge in ihrer Bedingung. */
|
||||
const seiten = await seite.evaluate(() => {
|
||||
const lies = (w) => {
|
||||
const s = getComputedStyle(w);
|
||||
return {
|
||||
breite: Math.round(w.getBoundingClientRect().width),
|
||||
hoehe: Math.round(w.getBoundingClientRect().height),
|
||||
rand: s.borderTopWidth,
|
||||
grund: s.backgroundImage.slice(0, 40),
|
||||
klebt: s.position,
|
||||
};
|
||||
};
|
||||
return [...document.querySelectorAll(".kv-seite")].map((s) => {
|
||||
const w = s.querySelector(".kv-seite__wappen");
|
||||
const k = s.querySelector(".kv-seite__kopf");
|
||||
return {
|
||||
seite: s.dataset.seite,
|
||||
ton: getComputedStyle(s).getPropertyValue("--kv-ton").trim(),
|
||||
wappen: w ? lies(w) : null,
|
||||
kopf: k ? lies(k) : null,
|
||||
lage: [...s.querySelectorAll(".kv-seite__lageteil")].map((x) => ({
|
||||
stand: x.dataset.stand || null,
|
||||
wort: x.textContent.trim(),
|
||||
farbe: getComputedStyle(x).color,
|
||||
})),
|
||||
};
|
||||
});
|
||||
});
|
||||
melde(" -- Seiten: " + JSON.stringify(seiten));
|
||||
|
||||
ok(seiten.length === 2, `zwei Seiten (${seiten.length})`);
|
||||
|
||||
/* ---- Das Wappen ------------------------------------------- */
|
||||
const wappen = seiten.map((s) => s.wappen).filter(Boolean);
|
||||
ok(wappen.length === 2, `jede Seite trägt ein Wappen (${wappen.length})`);
|
||||
/* ES WIRD WIRKLICH GEZEICHNET. Ein Element mit 0 px ist kein
|
||||
Abzeichen, und ein Verlauf, der nicht ankommt, auch
|
||||
nicht — genau dieser Fehlgriff (Merkmal gesetzt, nichts zu sehen)
|
||||
hat am 07.10.2026 einen Farbpunkt 10 statt 22 px breit gemacht. */
|
||||
ok(wappen.every((w) => w.breite >= 24 && w.hoehe >= 24),
|
||||
`und es ist groß genug: ${JSON.stringify(wappen.map((w) => `${w.breite}x${w.hoehe}`))}`);
|
||||
ok(wappen.every((w) => /gradient/.test(w.grund)),
|
||||
"und wirklich gezeichnet, nicht nur vorhanden");
|
||||
|
||||
/* ---- Der Kopf klebt ---------------------------------------- */
|
||||
/* Bei fünf Gruppen und einem Dutzend Kacheln je Spalte ist „auf
|
||||
welcher Seite bin ich gerade“ eine echte Frage. */
|
||||
ok(seiten.every((s) => s.kopf && s.kopf.klebt === "sticky"),
|
||||
`der Spaltenkopf bleibt beim Scrollen oben (${
|
||||
JSON.stringify(seiten.map((s) => s.kopf?.klebt))})`);
|
||||
|
||||
/* ---- Die Lage der Seite ------------------------------------ */
|
||||
const alleTeile = seiten.flatMap((s) => s.lage);
|
||||
ok(alleTeile.length >= 2,
|
||||
`die Spalten sagen, was los ist (${alleTeile.length} Angaben: ${
|
||||
JSON.stringify(alleTeile.map((x) => x.wort))})`);
|
||||
/* KEINE NULL. „0 laufen“ ist keine Auskunft, sondern Füllmaterial —
|
||||
und drei Nullen lassen eine leere Spalte voll aussehen. */
|
||||
ok(!alleTeile.some((x) => /^0 /.test(x.wort)),
|
||||
"und nennen nie eine Null");
|
||||
/* DIE ZAHLEN STIMMEN MIT DEN GRUPPEN DARUNTER ÜBEREIN. Eine zweite
|
||||
Zählung könnte etwas anderes sagen als die Überschriften zwei
|
||||
Zentimeter weiter unten. */
|
||||
const summeLage = alleTeile
|
||||
.map((x) => Number((x.wort.match(/^(\d+)/) || [])[1] || 0))
|
||||
.reduce((a, b) => a + b, 0);
|
||||
ok(summeLage === 5,
|
||||
`und zählen alle 5 Events (Summe ${summeLage})`);
|
||||
/* Verschiedene Zustände, verschiedene Töne — sonst wäre die
|
||||
Einfärbung Zierde ohne Aussage. */
|
||||
const toene = new Set(alleTeile.filter((x) => x.stand).map((x) => x.farbe));
|
||||
ok(toene.size >= 2,
|
||||
`und verschiedene Zustände sehen verschieden aus (${toene.size} Töne)`);
|
||||
|
||||
/* ---- DER KASTEN STEHT ZU, UND DAS IST DER ZWECK (08.10.2026) --
|
||||
|
||||
Gemessen auf 412 px war er auf 521 px gewachsen -- mehr als ein
|
||||
halber Telefonbildschirm, bevor man die erste Kachel sieht. Er
|
||||
ist ein Werkzeug, nicht der Inhalt der Seite.
|
||||
|
||||
ZUERST WIRD GEMESSEN, DASS ER ZU IST, dann wird er
|
||||
aufgemacht. Ohne den ersten Teil waere „er laesst sich
|
||||
aufklappen" auch bei einem Kasten gruen, der nie zugeht. */
|
||||
const zuerstZu = await seite.evaluate(() => {
|
||||
const form = document.getElementById("kampagne-form");
|
||||
const schild = document.getElementById("kampagne-schild");
|
||||
return {
|
||||
formVerborgen: form?.hidden === true,
|
||||
gedrueckt: schild?.getAttribute("aria-expanded"),
|
||||
schildHoehe: schild ? Math.round(schild.getBoundingClientRect().height) : null,
|
||||
kastenHoehe: Math.round(
|
||||
document.getElementById("kampagneholen")?.getBoundingClientRect().height ?? 0),
|
||||
wort: schild?.querySelector(".kampagneholen__schildwort")?.textContent.trim() || null,
|
||||
};
|
||||
});
|
||||
melde(" -- Kasten zu: " + JSON.stringify(zuerstZu));
|
||||
ok(zuerstZu.formVerborgen === true && zuerstZu.gedrueckt === "false",
|
||||
`der Einlesekasten steht von sich aus zu (hidden=${zuerstZu.formVerborgen}, `
|
||||
+ `aria-expanded=${zuerstZu.gedrueckt})`);
|
||||
/* UND ER BRAUCHT DANN FAST KEINEN PLATZ. Die Zahl steht in der
|
||||
Bedingung, nicht nur im Meldetext: Ein zugeklappter Kasten, der
|
||||
trotzdem 500 px hoch ist, waere kein zugeklappter Kasten. */
|
||||
ok(zuerstZu.kastenHoehe <= 110,
|
||||
`und nimmt zugeklappt nur ${zuerstZu.kastenHoehe} px (hoechstens 110)`);
|
||||
/* 44 px Tippziel -- dieselbe Vorgabe wie ueberall im Haus. */
|
||||
ok(zuerstZu.schildHoehe >= 44,
|
||||
`sein Schild ist ${zuerstZu.schildHoehe} px hoch (mindestens 44)`);
|
||||
ok(/Kampagne aus einer Einladung/.test(zuerstZu.wort || ""),
|
||||
`und sagt, was dahinter steckt: ${JSON.stringify(zuerstZu.wort)}`);
|
||||
|
||||
/* EIN DRUCK MACHT IHN AUF. */
|
||||
await seite.click("#kampagne-schild");
|
||||
await seite.waitForTimeout(250);
|
||||
|
||||
/* ---- Die Auswahl im Kasten -------------------------------- */
|
||||
const wahl = await seite.evaluate(() => {
|
||||
const f = document.querySelector(".kampagneholen__wahl");
|
||||
|
||||
Reference in New Issue
Block a user