Compare commits

..

5 Commits

3 changed files with 26 additions and 2 deletions

6
app.py
View File

@@ -284,6 +284,12 @@ def service_worker():
# Service Worker muss auf Top-Level liegen # Service Worker muss auf Top-Level liegen
log_page_view("service_worker", request.headers.get('User-Agent')) log_page_view("service_worker", request.headers.get('User-Agent'))
return send_from_directory(Path(__file__).parent / 'static', 'sw.js', mimetype='application/javascript') return send_from_directory(Path(__file__).parent / 'static', 'sw.js', mimetype='application/javascript')
@app.route('/screenshot.png')
def screenshot_image():
"""Liefert das OpenGraph/Twitter Vorschaubild aus dem Projektstamm."""
log_page_view("screenshot", request.headers.get('User-Agent'))
return send_from_directory(Path(__file__).parent, 'screenshot.png', mimetype='image/png')
@app.route('/login', methods=['GET', 'POST']) @app.route('/login', methods=['GET', 'POST'])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -11,9 +11,14 @@
<meta property="og:title" content="WordleCheater (DE)" /> <meta property="og:title" content="WordleCheater (DE)" />
<meta property="og:description" content="Finde deutsche 5BuchstabenWörter mit Positions- und Buchstabenfiltern. Quellen: OpenThesaurus & wordfreq." /> <meta property="og:description" content="Finde deutsche 5BuchstabenWörter mit Positions- und Buchstabenfiltern. Quellen: OpenThesaurus & wordfreq." />
<meta property="og:url" content="{{ request.url_root }}" /> <meta property="og:url" content="{{ request.url_root }}" />
<meta property="og:site_name" content="WordleCheater (DE)" />
<meta property="og:locale" content="de_DE" />
<meta property="og:image" content="{{ url_for('screenshot_image', _external=True) }}" />
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="WordleCheater (DE)" /> <meta name="twitter:title" content="WordleCheater (DE)" />
<meta name="twitter:description" content="Finde deutsche 5BuchstabenWörter mit Positions- und Buchstabenfiltern. Quellen: OpenThesaurus & wordfreq." /> <meta name="twitter:description" content="Finde deutsche 5BuchstabenWörter mit Positions- und Buchstabenfiltern. Quellen: OpenThesaurus & wordfreq." />
<meta name="twitter:image" content="{{ url_for('screenshot_image', _external=True) }}" />
<link rel="alternate" hreflang="de" href="{{ request.url_root }}" />
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='favicon.svg') }}" /> <link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='favicon.svg') }}" />
<link rel="manifest" href="/manifest.webmanifest" /> <link rel="manifest" href="/manifest.webmanifest" />
<meta name="theme-color" content="#0b1220" /> <meta name="theme-color" content="#0b1220" />
@@ -28,6 +33,19 @@
} catch (e) {} } catch (e) {}
})(); })();
</script> </script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
"name": "WordleCheater (DE)",
"url": "{{ request.url_root }}",
"applicationCategory": "UtilitiesApplication",
"operatingSystem": "Web",
"description": "Finde deutsche 5BuchstabenWörter anhand bekannter Buchstaben und Positionen. Quellen: OpenThesaurus & wordfreq.",
"inLanguage": "de",
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "EUR" }
}
</script>
<style> <style>
:root { --bg:#ffffff; --text:#111827; --muted:#6b7280; --badge-bg:#e5e7eb; --badge-text:#111827; --border:#e5e7eb; --skip-bg:#111827; --skip-text:#ffffff; --button-bg:#111827; --button-text:#ffffff; --input-bg:#ffffff; --input-text:#111827; --error:#b91c1c; } :root { --bg:#ffffff; --text:#111827; --muted:#6b7280; --badge-bg:#e5e7eb; --badge-text:#111827; --border:#e5e7eb; --skip-bg:#111827; --skip-text:#ffffff; --button-bg:#111827; --button-text:#ffffff; --input-bg:#ffffff; --input-text:#111827; --error:#b91c1c; }
[data-theme="dark"] { --bg:#0b1220; --text:#e5e7eb; --muted:#9ca3af; --badge-bg:#374151; --badge-text:#f9fafb; --border:#334155; --skip-bg:#e5e7eb; --skip-text:#111827; --button-bg:#e5e7eb; --button-text:#111827; --input-bg:#111827; --input-text:#e5e7eb; --error:#ef4444; } [data-theme="dark"] { --bg:#0b1220; --text:#e5e7eb; --muted:#9ca3af; --badge-bg:#374151; --badge-text:#f9fafb; --border:#334155; --skip-bg:#e5e7eb; --skip-text:#111827; --button-bg:#e5e7eb; --button-text:#111827; --input-bg:#111827; --input-text:#e5e7eb; --error:#ef4444; }
@@ -98,7 +116,7 @@
<input id="pos4" name="pos4" maxlength="1" aria-label="Position 4" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[3] }}" /> <input id="pos4" name="pos4" maxlength="1" aria-label="Position 4" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[3] }}" />
<input id="pos5" name="pos5" maxlength="1" aria-label="Position 5" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[4] }}" /> <input id="pos5" name="pos5" maxlength="1" aria-label="Position 5" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[4] }}" />
</div> </div>
<p id="pos-hint" class="hint">Je Feld genau ein Buchstabe. Umlaute (ä, ö, ü) und ß sind erlaubt.</p> <p id="pos-hint" class="hint">Je Feld ein Buchstabe. Ziehe einen Buchstaben heraus, wenn du ihn löschen möchtest.</p>
</fieldset> </fieldset>
<label for="includes-input-one">Weitere enthaltene Buchstaben (beliebige Reihenfolge)</label> <label for="includes-input-one">Weitere enthaltene Buchstaben (beliebige Reihenfolge)</label>
@@ -108,7 +126,7 @@
<input type="hidden" id="includes" name="includes" value="{{ includes }}" /> <input type="hidden" id="includes" name="includes" value="{{ includes }}" />
</div> </div>
<ul id="includes-list" class="word-list" aria-live="polite"></ul> <ul id="includes-list" class="word-list" aria-live="polite"></ul>
<p id="includes-hint" class="hint">Gib einen Buchstaben ein und füge ihn mit „+“ zur Liste hinzu.</p> <p id="includes-hint" class="hint">Gib einen Buchstaben ein und füge ihn mit „+“ zur Liste hinzu. Ziehe ihn auf ein Positionsfeld, wenn er dort passen würde.</p>
<label for="excludes-input-one">Ausgeschlossene Buchstaben</label> <label for="excludes-input-one">Ausgeschlossene Buchstaben</label>
<div class="inline-controls" aria-describedby="excludes-hint"> <div class="inline-controls" aria-describedby="excludes-hint">