diff --git a/server/pruef-fingermass.mjs b/server/pruef-fingermass.mjs index 223420b6..a9330c44 100644 --- a/server/pruef-fingermass.mjs +++ b/server/pruef-fingermass.mjs @@ -46,38 +46,79 @@ const ORDNER = new URL(".", import.meta.url).pathname.replace(/^\/([A-Za-z]:)/, werden. Wird sie kleiner, gehoert sie hier angepasst — die Pruefung sagt es dann selbst. - EIN GREP HATTE 18 GEZAEHLT. Zwei davon waren Zahlen in - Kommentaren („gemessen bei 412 px"), keine Fenster. Deshalb liest - diese Pruefung nur die Stelle, die ein Fenster AUFMACHT, und - blendet Kommentare vorher aus. Die erste Zahl, die eine Wache - liefert, ist selten die richtige — auch hier war die genauere - Lesart um zwei kleiner. */ -const GRUNDLINIE = 16; + DREI ANLAEUFE, DREI ZAHLEN. Ein grep ueber die Dateien fand 18; + zwei davon waren Zahlen in Kommentaren („gemessen bei 412 px"), + keine Fenster. Die erste Fassung dieser Wache zaehlte dann DATEIEN + und kam auf 16 — aber `pruef-kalender.mjs` allein hat sieben + Fenster, davon drei schmale, und ein einziges `hasTouch` irgendwo + in der Datei haette alle drei freigesprochen. Gezaehlt wird + deshalb je FENSTER. + + Die geschaerfte Fassung fand dann prompt zwei Dateien, welche die + grobe freigesprochen hatte — `pruef-chat-optik` und + `pruef-handy-teamdogi`, beide mit EINEM Finger und einem blinden + Fenster daneben. Beim Nachmessen war die erste ein Fehlalarm (ihr + `setViewportSize` sitzt auf einer Seite, die den Finger schon + hat), die zweite ein echter Fund und sofort repariert. + + Die erste Zahl, die eine Wache liefert, ist selten die richtige. */ +const GRUNDLINIE = 17; /* Ab wann ist ein Fenster ein Telefon? 860 ist die Grenze, die im Haus schon in mess-reaktion und mess-chat-optik steht. Darueber hat ein Geraet mit hoher Wahrscheinlichkeit einen Zeiger. */ -const SCHMAL = /(?:width|breite)\s*[:=]\s*(\d{3})\b/g; +const SCHMAL = 860; const MISST = /getBoundingClientRect|offsetWidth|offsetHeight|clientWidth|clientHeight|scrollWidth|scrollHeight|boundingBox/; +const ohneKommentare = (text) => text + .replace(/\/\*[\s\S]*?\*\//g, " ") + .replace(/^\s*\/\/.*$/gm, " "); + /* NUR DIE STELLE, DIE EIN FENSTER AUFMACHT — nicht jede Zahl im Text. `width: 412` in einem Kommentar ueber eine Messung von - gestern ist keine Messung. */ -const fensterBreiten = (text) => { + gestern ist keine Messung. + + UND JE FENSTER, NICHT JE DATEI. Eine Wache, die eine Datei als + Ganzes abhakt, uebersieht genau die Mischung, die im Haus die + Regel ist: ein Fenster mit Finger, drei ohne. */ +export const fensterStellen = (text) => { const raus = []; - const ohneKommentar = text.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/^\s*\/\/.*$/gm, " "); - for (const m of ohneKommentar.matchAll(/(?:newContext|setViewportSize|viewport)\s*[({][^)}]{0,200}/g)) { - for (const z of m[0].matchAll(SCHMAL)) raus.push(Number(z[1])); + const rein = ohneKommentare(text); + for (const m of rein.matchAll(/newContext\s*\(\s*\{[\s\S]{0,400}?\}\s*\)/g)) { + const br = [...m[0].matchAll(/width\s*:\s*(\d{3,4})\b/g)].map((z) => Number(z[1])); + if (!br.length) continue; + raus.push({ schmal: br.some((x) => x <= SCHMAL), finger: /hasTouch/.test(m[0]) }); + } + /* `setViewportSize` KANN `hasTouch` nicht nachtragen — es gehoert + zum Kontext und ist beim Anlegen entschieden. + + ABER ES KANN IHN AUCH NICHT WEGNEHMEN. Die erste Fassung zaehlte + jede solche Stelle als blind und meldete daraufhin + `pruef-chat-optik.mjs` — zu Unrecht: Deren Kontext traegt + `hasTouch: breite < 900`, und wer danach nur die Groesse + aendert, behaelt den Finger. Ein Fehlalarm, gefunden beim + Nachmessen des ersten Laufs. + + Gezaehlt wird die Stelle deshalb nur, wenn in der ganzen Datei + KEIN einziges `hasTouch` steht — dann stammt die Seite sicher + aus einem fingerlosen Kontext. Wo ich raten muesste, zaehle ich + nicht: Eine Wache, die im Zweifel meldet, wird weggeklickt. */ + if (!/hasTouch/.test(rein)) { + for (const m of rein.matchAll(/setViewportSize\s*\(\s*\{[^}]{0,150}\}/g)) { + const br = [...m[0].matchAll(/width\s*:\s*(\d{3,4})\b/g)].map((z) => Number(z[1])); + if (!br.length) continue; + raus.push({ schmal: br.some((x) => x <= SCHMAL), finger: false }); + } } return raus; }; -export const fingerlos = (text) => { - const breiten = fensterBreiten(text); - if (!breiten.some((b) => b <= 860)) return false; - if (/hasTouch/.test(text)) return false; - return MISST.test(text); -}; +/* Ein Fenster ist nur dann ein Befund, wenn die Datei ueberhaupt + MISST. Wer bei 390 px nachsieht, ob ein Text dasteht, braucht + keinen Finger. */ +export const blindeStellen = (text) => (MISST.test(text) + ? fensterStellen(text).filter((f) => f.schmal && !f.finger).length : 0); +export const fingerlos = (text) => blindeStellen(text) > 0; console.log("\n=== 1. Wer misst am Telefon ohne Finger? ==="); const dateien = readdirSync(ORDNER) @@ -92,56 +133,78 @@ if (dateien.length < 50) { } const funde = []; -let mitFinger = 0, amTelefon = 0; +let blind = 0, mitFinger = 0, amTelefon = 0; for (const name of dateien) { const text = readFileSync(join(ORDNER, name), "utf8"); - const breiten = fensterBreiten(text); - if (!breiten.some((b) => b <= 860)) continue; + const schmale = fensterStellen(text).filter((f) => f.schmal); + if (!schmale.length) continue; amTelefon++; - if (/hasTouch/.test(text)) { mitFinger++; continue; } - if (MISST.test(text)) funde.push(name); + mitFinger += schmale.filter((f) => f.finger).length; + const b = blindeStellen(text); + if (b) { blind += b; funde.push(`${name} (${b})`); } } -console.log(` ${amTelefon} Dateien oeffnen ein Telefonformat, ${mitFinger} davon mit Finger.`); -if (funde.length) console.log(" ohne Finger und mit Massband: " + funde.join(", ")); +console.log(` ${amTelefon} Dateien oeffnen ein Telefonformat, ` + + `${mitFinger} dieser Fenster haben einen Finger.`); +if (funde.length) console.log(" blinde Fenster mit Massband: " + funde.join(", ")); ok(amTelefon > 20, `${amTelefon} Dateien messen am Telefon — die Suche findet ueberhaupt etwas`); -if (funde.length > GRUNDLINIE) { - ok(false, `${funde.length} Messungen ohne Finger — das sind ${funde.length - GRUNDLINIE} MEHR ` - + `als die Grundlinie ${GRUNDLINIE}. Neu dazugekommen ist eine Messung, die auf ` - + "412 px eine Seite vermisst, die es auf keinem Telefon gibt. `hasTouch: true` " - + "gehoert in den newContext-Aufruf — setViewportSize kann es nicht nachtragen."); -} else if (funde.length < GRUNDLINIE) { - ok(false, `Nur noch ${funde.length} Messungen ohne Finger — die Grundlinie steht auf ` - + `${GRUNDLINIE}. Bitte in pruef-fingermass.mjs auf ${funde.length} senken, sonst deckt ` - + "sie Platz fuer die naechste."); +if (blind > GRUNDLINIE) { + ok(false, `${blind} blinde Fenster — das sind ${blind - GRUNDLINIE} MEHR als die ` + + `Grundlinie ${GRUNDLINIE}. Neu dazugekommen ist eine Messung, die auf einem ` + + "Telefonformat eine Seite vermisst, die es auf keinem Telefon gibt. " + + "`hasTouch: true` gehoert in den newContext-Aufruf — setViewportSize kann es " + + "nicht nachtragen."); +} else if (blind < GRUNDLINIE) { + ok(false, `Nur noch ${blind} blinde Fenster — die Grundlinie steht auf ${GRUNDLINIE}. ` + + `Bitte in pruef-fingermass.mjs auf ${blind} senken, sonst deckt sie Platz fuer ` + + "die naechste."); } else { - ok(true, `${funde.length} Messungen ohne Finger — unveraendert zur Grundlinie ${GRUNDLINIE}`); + ok(true, `${blind} blinde Fenster mit Massband — unveraendert zur Grundlinie ${GRUNDLINIE}`); } console.log("\n=== 2. Gegenprobe: kann sie auch NICHT IN ORDNUNG sagen? ==="); const faelle = [ ["der Fall vom 29.09. (schmal, misst, kein Finger)", 'const s = await b.newContext({ viewport: { width: 412, height: 900 } });\n' - + 'el.getBoundingClientRect()', true], + + 'el.getBoundingClientRect()', 1], ["mit Finger", 'const s = await b.newContext({ viewport: { width: 412, height: 900 }, hasTouch: true });\n' - + 'el.getBoundingClientRect()', false], + + 'el.getBoundingClientRect()', 0], ["nur ein Laptopfenster", 'const s = await b.newContext({ viewport: { width: 1280, height: 900 } });\n' - + 'el.getBoundingClientRect()', false], + + 'el.getBoundingClientRect()', 0], ["schmal, misst aber nichts", 'const s = await b.newContext({ viewport: { width: 390, height: 844 } });\n' - + 'await p.textContent("h1")', false], + + 'await p.textContent("h1")', 0], ["eine Breite, die nur im Kommentar steht", '/* gemessen bei width: 412 -- drei Zeilen */\n' + 'const s = await b.newContext({ viewport: { width: 1440, height: 900 } });\n' - + 'el.getBoundingClientRect()', false], + + 'el.getBoundingClientRect()', 0], ["setViewportSize statt newContext — kann hasTouch gar nicht setzen", - 'await p.setViewportSize({ width: 390, height: 844 });\nel.offsetWidth', true], + 'await p.setViewportSize({ width: 390, height: 844 });\nel.offsetWidth', 1], + /* DER FEHLALARM AUS DEM ERSTEN LAUF: Wer einen Finger-Kontext + anlegt und danach nur die Groesse aendert, behaelt den Finger. */ + ["Groesse aendern an einer Seite, die schon einen Finger hat", + 'const c = await b.newContext({ viewport: { width: 900, height: 900 },\n' + + ' hasTouch: breite < 900 });\n' + + 'await p.setViewportSize({ width: 390, height: 844 });\nel.offsetWidth', 0], + /* DER FALL, AN DEM DIE ERSTE FASSUNG SCHEITERTE: Ein Finger in der + Datei, drei blinde Fenster daneben. Sie sprach die ganze Datei + frei. */ + ["ein Finger spricht nicht die ganze Datei frei", + 'const a = await b.newContext({ viewport: { width: 390, height: 844 }, hasTouch: true });\n' + + 'const c = await b.newContext({ viewport: { width: 412, height: 900 } });\n' + + 'el.getBoundingClientRect()', 1], + ["zwei blinde Fenster sind zwei Befunde, nicht einer", + 'const a = await b.newContext({ viewport: { width: 390, height: 844 } });\n' + + 'const c = await b.newContext({ viewport: { width: 412, height: 900 } });\n' + + 'el.getBoundingClientRect()', 2], ]; -const daneben = faelle.filter(([, text, soll]) => fingerlos(text) !== soll).map(([n]) => n); +const daneben = faelle + .filter(([, text, soll]) => blindeStellen(text) !== soll) + .map(([n, text, soll]) => `${n} (${blindeStellen(text)} statt ${soll})`); ok(daneben.length === 0, daneben.length ? `Gegenprobe daneben bei: ${daneben.join(", ")}` : `Gegenprobe: alle ${faelle.length} Faelle richtig eingeordnet`); diff --git a/server/pruef-handy-teamdogi.mjs b/server/pruef-handy-teamdogi.mjs index c5a77c12..229a97c6 100644 --- a/server/pruef-handy-teamdogi.mjs +++ b/server/pruef-handy-teamdogi.mjs @@ -731,7 +731,12 @@ for (const [breite, hoehe, geraet] of BREITEN) { ===================================================================== */ melde("\n --- Gegenprobe (beide Fehler MÜSSEN gefunden werden) ---"); { - const kontext = await browser.newContext({ viewport: { width: 390, height: 844 }, ignoreHTTPSErrors: true }); + /* MIT FINGER (29.09.2026). Der zweite Kontext dieser Datei hatte + keinen -- der erste schon. Ohne `hasTouch` meldet der Browser + `pointer: fine`, und keine Regel aus `@media (pointer: coarse)` + greift; dort stehen die 44-Pixel-Beruehrziele. */ + const kontext = await browser.newContext({ viewport: { width: 390, height: 844 }, + hasTouch: true, isMobile: true, ignoreHTTPSErrors: true }); const seite = await kontext.newPage(); await seite.goto(BASIS + "/workspace/", { waitUntil: "load" }); await seite.waitForTimeout(600); diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 496474f0..6a604ee4 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,8 +16,8 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +