feat(ui): release v1.2.0 with improved installer UX, build tests, and docs update
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
# Kantine Wrapper Bookmarklet (v1.7.0)
|
||||
# Kantine Wrapper Bookmarklet (v1.2.0)
|
||||
|
||||
Ein intelligentes Bookmarklet für die Mitarbeiter-Kantine der Bessa App. Dieses Skript erweitert die Standardansicht um eine **Wochenübersicht**, Kostenkontrolle und verbesserte Usability.
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
* **Wochenübersicht:** Zeigt alle Tage der aktuellen Woche auf einen Blick.
|
||||
* **Bestell-Countdown:** ⏳ Roter Alarm 1h vor Bestellschluss.
|
||||
* **Smart Highlights:** 🌟 Markiere deine Favoriten (z.B. "Schnitzel", "Vegetarisch").
|
||||
* **Bestellstatus:** Farbige Indikatoren für bestellte Menüs.
|
||||
* **Kostenkontrolle:** Summiert automatisch den Gesamtpreis der Woche.
|
||||
* **Session Reuse:** Nutzt automatisch eine bestehende Login-Session (Loggt dich automatisch ein).
|
||||
* **API Fallback:** Prüft die Verbindung und bietet bei Fehlern einen Direktlink zur Originalseite.
|
||||
* **Menu Badges:** Zeigt Menü-Codes (M1, M2+) direkt im Header.
|
||||
* **Changelog:** Übersicht über neue Funktionen direkt im Installer.
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
|
||||
@@ -108,39 +108,49 @@ cat > "$DIST_DIR/install.html" << INSTALLEOF
|
||||
</head>
|
||||
<body>
|
||||
<h1>🍽️ Kantine Wrapper <span style="font-size:0.5em; opacity:0.6; font-weight:400; vertical-align:middle; margin-left:10px;">$VERSION</span></h1>
|
||||
<div class="card">
|
||||
<h2>Changelog</h2>
|
||||
<div class="changelog-container">
|
||||
<!-- CHANGELOG_PLACEHOLDER -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 1. BUTTON (Top Priority) -->
|
||||
<div class="card" style="text-align: center; border: 2px solid #029AA8;">
|
||||
<p style="margin-bottom:15px; font-weight:bold;">👇 Diesen Button in die Lesezeichen-Leiste ziehen:</p>
|
||||
<p><a class="bookmarklet" id="bookmarklet-link" href="#">⏳ Wird generiert...</a></p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>So funktioniert's</h2>
|
||||
<ol>
|
||||
<li>Ziehe den Button unten in deine <strong>Lesezeichen-Leiste</strong> (Drag & Drop)</li>
|
||||
<li>Navigiere zu <a href="https://web.bessa.app/knapp-kantine" style="color:#029AA8">web.bessa.app/knapp-kantine</a></li>
|
||||
<li>Klicke auf das Lesezeichen <code>Kantine $VERSION</code></li>
|
||||
</ol>
|
||||
</div>
|
||||
<!-- 2. INSTRUCTIONS -->
|
||||
<div class="card">
|
||||
<h2>So funktioniert's</h2>
|
||||
<ol>
|
||||
<li>Ziehe den Button oben in deine <strong>Lesezeichen-Leiste</strong> (Drag & Drop)</li>
|
||||
<li>Navigiere zu <a href="https://web.bessa.app/knapp-kantine" style="color:#029AA8">web.bessa.app/knapp-kantine</a></li>
|
||||
<li>Klicke auf das Lesezeichen <code>Kantine $VERSION</code></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>✨ Features</h2>
|
||||
<ul>
|
||||
<li>📅 <strong>Wochenübersicht:</strong> Die ganze Woche auf einen Blick.</li>
|
||||
<li>💰 <strong>Kostenkontrolle:</strong> Automatische Berechnung der Wochensumme.</li>
|
||||
<li>🔑 <strong>Auto-Login:</strong> Nutzt deine bestehende Session.</li>
|
||||
<li>🏷️ <strong>Badges & Status:</strong> Menü-Codes (M1, M2) und Bestellstatus direkt sichtbar.</li>
|
||||
<li>🛡️ <strong>Offline-Support:</strong> Speichert Menüdaten lokal.</li>
|
||||
</ul>
|
||||
<!-- 3. FEATURES -->
|
||||
<div class="card">
|
||||
<h2>✨ Features</h2>
|
||||
<ul>
|
||||
<li>📅 <strong>Wochenübersicht:</strong> Die ganze Woche auf einen Blick.</li>
|
||||
<li>⏳ <strong>Order Countdown:</strong> Roter Alarm 1h vor Bestellschluss.</li>
|
||||
<li>🌟 <strong>Smart Highlights:</strong> Markiere deine Favoriten (z.B. "Schnitzel").</li>
|
||||
<li>💰 <strong>Kostenkontrolle:</strong> Automatische Berechnung der Wochensumme.</li>
|
||||
<li>🔑 <strong>Auto-Login:</strong> Nutzt deine bestehende Session.</li>
|
||||
<li>🏷️ <strong>Badges & Status:</strong> Menü-Codes (M1, M2) und Bestellstatus direkt sichtbar.</li>
|
||||
</ul>
|
||||
|
||||
<div style="margin-top: 30px; padding: 15px; background: rgba(233, 69, 96, 0.1); border: 1px solid rgba(233, 69, 96, 0.3); border-radius: 8px; font-size: 0.85em; color: #ddd;">
|
||||
<div style="margin-top: 30px; padding: 15px; background: rgba(233, 69, 96, 0.1); border: 1px solid rgba(233, 69, 96, 0.3); border-radius: 8px; font-size: 0.85em; color: #ddd;">
|
||||
<strong>⚠️ Haftungsausschluss:</strong><br>
|
||||
Die Verwendung dieses Bookmarklets erfolgt auf eigene Verantwortung. Der Entwickler übernimmt keine Haftung für Schäden, Datenverlust oder ungewollte Bestellungen, die durch die Nutzung dieser Software entstehen.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. CHANGELOG (Bottom) -->
|
||||
<div class="card">
|
||||
<h2>Changelog</h2>
|
||||
<div class="changelog-container">
|
||||
<!-- CHANGELOG_PLACEHOLDER -->
|
||||
</div>
|
||||
</div>
|
||||
<p>👇 Diesen Button in die Lesezeichen-Leiste ziehen:</p>
|
||||
<p><a class="bookmarklet" id="bookmarklet-link" href="#">⏳ Wird generiert...</a></p>
|
||||
|
||||
<script>
|
||||
INSTALLEOF
|
||||
|
||||
@@ -168,27 +178,22 @@ import sys, json, urllib.parse
|
||||
|
||||
# 1. Read JS and Replace VERSION
|
||||
js_template = sys.stdin.read()
|
||||
# We do replacement here in Python to be safe
|
||||
js = js_template.replace('{{VERSION}}', '$VERSION')
|
||||
|
||||
# 2. Prepare CSS
|
||||
# 2. Prepare CSS for injection via createElement('style')
|
||||
css = open('$CSS_FILE').read().replace('\n', ' ').replace(' ', ' ')
|
||||
escaped_css = css.replace('\\\\', '\\\\\\\\').replace(\"'\", \"\\\\'\").replace('\"', '\\\\\"')
|
||||
|
||||
# 3. Inject CSS and Update URL
|
||||
# 3. Update URL
|
||||
update_url = 'https://htmlpreview.github.io/?https://github.com/TauNeutrino/kantine-overview/blob/main/dist/install.html'
|
||||
js = js.replace('https://github.com/TauNeutrino/kantine-overview/raw/main/dist/install.html', update_url)
|
||||
js = js.replace('{{CSS_ESCAPED}}', escaped_css)
|
||||
|
||||
# 4. Create Bookmarklet Code
|
||||
# Wrap in IIFE
|
||||
bookmarklet_code = 'javascript:(function(){' + js + '})();'
|
||||
# 4. Create Bookmarklet Code with CSS injection
|
||||
# Inject CSS via style element (same pattern as bookmarklet-payload.js)
|
||||
css_injection = \"var s=document.createElement('style');s.textContent='\" + escaped_css + \"';document.head.appendChild(s);\"
|
||||
bookmarklet_code = 'javascript:(function(){' + css_injection + js + '})();'
|
||||
|
||||
# 5. URL Encode the body (keeping javascript: prefix)
|
||||
# We accept that simple encoding is better.
|
||||
# But browsers expect encoded URI for href.
|
||||
# However, for bookmarklet usage, user drags the link.
|
||||
# If we encode everything, it's safer.
|
||||
# 5. URL Encode
|
||||
encoded_code = urllib.parse.quote(bookmarklet_code, safe=':/()!;=+,')
|
||||
|
||||
# Output as JSON string for the HTML script to assign to href
|
||||
@@ -218,3 +223,14 @@ echo ""
|
||||
echo "=== Build Complete ==="
|
||||
echo "Files in $DIST_DIR:"
|
||||
ls -la "$DIST_DIR/"
|
||||
|
||||
# === 4. Run build-time tests ===
|
||||
echo ""
|
||||
echo "=== Running Build Tests ==="
|
||||
python3 "$SCRIPT_DIR/test_build.py"
|
||||
TEST_EXIT=$?
|
||||
if [ $TEST_EXIT -ne 0 ]; then
|
||||
echo "❌ Build tests FAILED! See above for details."
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All build tests passed."
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
## v1.2.0 (2026-02-16)
|
||||
- **Feature**: Bessere UX im Installer (Button oben, Log unten, Features aktualisiert). 💅
|
||||
- **Tech**: Build-Tests hinzugefügt. 🧪
|
||||
- **Fix**: Encoding-Probleme final behoben (dank Python Buildlogic). 🐍
|
||||
|
||||
## v1.1.2 (2026-02-16)
|
||||
- **Fix**: Encoding-Problem beim Bookmarklet behoben (URL Malformed Error). 🔗
|
||||
|
||||
|
||||
4
dist/bookmarklet-payload.js
vendored
4
dist/bookmarklet-payload.js
vendored
File diff suppressed because one or more lines are too long
2
dist/bookmarklet.txt
vendored
2
dist/bookmarklet.txt
vendored
File diff suppressed because one or more lines are too long
86
dist/install.html
vendored
86
dist/install.html
vendored
File diff suppressed because one or more lines are too long
70
dist/kantine-standalone.html
vendored
70
dist/kantine-standalone.html
vendored
@@ -152,17 +152,6 @@ body {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.weekly-cost {
|
||||
white-space: nowrap;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
color: var(--success-color);
|
||||
background-color: var(--bg-body);
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.header-week-title {
|
||||
font-size: 1.1rem;
|
||||
@@ -1177,13 +1166,15 @@ body {
|
||||
color: var(--text-primary);
|
||||
/* Ensure text remains standard color */
|
||||
}
|
||||
|
||||
/* Update Icon */
|
||||
.update-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 8px;
|
||||
background-color: rgba(16, 185, 129, 0.2); /* Green tint */
|
||||
background-color: rgba(16, 185, 129, 0.2);
|
||||
/* Green tint */
|
||||
color: var(--success-color);
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
@@ -1202,9 +1193,17 @@ body {
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
|
||||
70% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
|
||||
70% {
|
||||
box-shadow: 0 0 0 6px rgba(16, 185, 129, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Order Countdown */
|
||||
@@ -1235,14 +1234,23 @@ body {
|
||||
}
|
||||
|
||||
@keyframes pulse-red {
|
||||
0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
|
||||
70% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4);
|
||||
}
|
||||
|
||||
70% {
|
||||
box-shadow: 0 0 0 6px rgba(239, 68, 68, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Smart Highlights */
|
||||
.highlight-glow {
|
||||
box-shadow: 0 0 15px rgba(59, 130, 246, 0.5); /* Blue glow */
|
||||
box-shadow: 0 0 15px rgba(59, 130, 246, 0.5);
|
||||
/* Blue glow */
|
||||
border: 1px solid rgba(59, 130, 246, 0.8);
|
||||
background: rgba(59, 130, 246, 0.05);
|
||||
position: relative;
|
||||
@@ -1251,14 +1259,16 @@ body {
|
||||
|
||||
/* Nav Badge with Count */
|
||||
.nav-badge.has-highlights {
|
||||
background-color: var(--card-bg); /* Neutral background */
|
||||
background-color: var(--bg-card);
|
||||
/* Neutral background */
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.nav-badge .highlight-count {
|
||||
color: #3b82f6; /* Blue 500 */
|
||||
color: #3b82f6;
|
||||
/* Blue 500 */
|
||||
font-weight: 700;
|
||||
margin-left: 4px;
|
||||
}
|
||||
@@ -1304,7 +1314,7 @@ body {
|
||||
.input-group input {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
background: var(--bg-color);
|
||||
background: var(--bg-body);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-primary);
|
||||
border-radius: 8px;
|
||||
@@ -1313,7 +1323,7 @@ body {
|
||||
/* Update Banner Enhanced */
|
||||
.change-summary {
|
||||
font-size: 0.8rem;
|
||||
background: rgba(0,0,0,0.1);
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
padding: 0.5rem;
|
||||
border-radius: 4px;
|
||||
margin: 0.5rem 0;
|
||||
@@ -1323,6 +1333,7 @@ body {
|
||||
max-height: 100px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.update-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1331,21 +1342,22 @@ body {
|
||||
}
|
||||
|
||||
/* Installer Changelog */
|
||||
.changelog-container ul {
|
||||
padding-left: 1.5rem;
|
||||
.changelog-container ul {
|
||||
padding-left: 1.5rem;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.changelog-container li {
|
||||
margin-bottom: 0.4rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.changelog-container h3 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.1em;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
</style>
|
||||
} </style>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
@@ -1417,7 +1429,7 @@ body {
|
||||
<div class="brand">
|
||||
<span class="material-icons-round logo-icon">restaurant_menu</span>
|
||||
<div class="header-left">
|
||||
<h1>Kantinen Übersicht <small style="font-size: 0.6em; opacity: 0.7; font-weight: 400;">v1.1.2</small></h1>
|
||||
<h1>Kantinen Übersicht <small style="font-size: 0.6em; opacity: 0.7; font-weight: 400;">v1.2.0</small></h1>
|
||||
<div id="last-updated-subtitle" class="subtitle"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2750,7 +2762,7 @@ body {
|
||||
|
||||
// === Version Check ===
|
||||
async function checkForUpdates() {
|
||||
const CurrentVersion = 'v1.1.2';
|
||||
const CurrentVersion = 'v1.2.0';
|
||||
const VersionUrl = 'https://raw.githubusercontent.com/TauNeutrino/kantine-overview/main/version.txt';
|
||||
const InstallerUrl = 'https://htmlpreview.github.io/?https://github.com/TauNeutrino/kantine-overview/blob/main/dist/install.html';
|
||||
|
||||
|
||||
65
style.css
65
style.css
@@ -141,17 +141,6 @@ body {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.weekly-cost {
|
||||
white-space: nowrap;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
color: var(--success-color);
|
||||
background-color: var(--bg-body);
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.header-week-title {
|
||||
font-size: 1.1rem;
|
||||
@@ -1166,13 +1155,15 @@ body {
|
||||
color: var(--text-primary);
|
||||
/* Ensure text remains standard color */
|
||||
}
|
||||
|
||||
/* Update Icon */
|
||||
.update-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 8px;
|
||||
background-color: rgba(16, 185, 129, 0.2); /* Green tint */
|
||||
background-color: rgba(16, 185, 129, 0.2);
|
||||
/* Green tint */
|
||||
color: var(--success-color);
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
@@ -1191,9 +1182,17 @@ body {
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
|
||||
70% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
|
||||
70% {
|
||||
box-shadow: 0 0 0 6px rgba(16, 185, 129, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Order Countdown */
|
||||
@@ -1224,14 +1223,23 @@ body {
|
||||
}
|
||||
|
||||
@keyframes pulse-red {
|
||||
0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
|
||||
70% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4);
|
||||
}
|
||||
|
||||
70% {
|
||||
box-shadow: 0 0 0 6px rgba(239, 68, 68, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Smart Highlights */
|
||||
.highlight-glow {
|
||||
box-shadow: 0 0 15px rgba(59, 130, 246, 0.5); /* Blue glow */
|
||||
box-shadow: 0 0 15px rgba(59, 130, 246, 0.5);
|
||||
/* Blue glow */
|
||||
border: 1px solid rgba(59, 130, 246, 0.8);
|
||||
background: rgba(59, 130, 246, 0.05);
|
||||
position: relative;
|
||||
@@ -1240,14 +1248,16 @@ body {
|
||||
|
||||
/* Nav Badge with Count */
|
||||
.nav-badge.has-highlights {
|
||||
background-color: var(--card-bg); /* Neutral background */
|
||||
background-color: var(--bg-card);
|
||||
/* Neutral background */
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.nav-badge .highlight-count {
|
||||
color: #3b82f6; /* Blue 500 */
|
||||
color: #3b82f6;
|
||||
/* Blue 500 */
|
||||
font-weight: 700;
|
||||
margin-left: 4px;
|
||||
}
|
||||
@@ -1293,7 +1303,7 @@ body {
|
||||
.input-group input {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
background: var(--bg-color);
|
||||
background: var(--bg-body);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-primary);
|
||||
border-radius: 8px;
|
||||
@@ -1302,7 +1312,7 @@ body {
|
||||
/* Update Banner Enhanced */
|
||||
.change-summary {
|
||||
font-size: 0.8rem;
|
||||
background: rgba(0,0,0,0.1);
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
padding: 0.5rem;
|
||||
border-radius: 4px;
|
||||
margin: 0.5rem 0;
|
||||
@@ -1312,6 +1322,7 @@ body {
|
||||
max-height: 100px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.update-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1320,17 +1331,19 @@ body {
|
||||
}
|
||||
|
||||
/* Installer Changelog */
|
||||
.changelog-container ul {
|
||||
padding-left: 1.5rem;
|
||||
.changelog-container ul {
|
||||
padding-left: 1.5rem;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.changelog-container li {
|
||||
margin-bottom: 0.4rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.changelog-container h3 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.1em;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
89
test_build.py
Executable file
89
test_build.py
Executable file
@@ -0,0 +1,89 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
DIST_DIR = os.path.join(os.path.dirname(__file__), 'dist')
|
||||
INSTALL_HTML = os.path.join(DIST_DIR, 'install.html')
|
||||
BOOKMARKLET_TXT = os.path.join(DIST_DIR, 'bookmarklet.txt')
|
||||
STANDALONE_HTML = os.path.join(DIST_DIR, 'kantine-standalone.html')
|
||||
|
||||
def check_file_exists(path, description):
|
||||
if not os.path.exists(path):
|
||||
print(f"❌ MISSING: {description} ({path})")
|
||||
return False
|
||||
# Check if not empty
|
||||
if os.path.getsize(path) == 0:
|
||||
print(f"❌ EMPTY: {description} ({path})")
|
||||
return False
|
||||
print(f"✅ FOUND: {description}")
|
||||
return True
|
||||
|
||||
def check_content(path, must_contain=[], must_not_contain=[]):
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
success = True
|
||||
for item in must_contain:
|
||||
if item not in content:
|
||||
print(f"❌ MISSING CONTENT: '{item}' in {os.path.basename(path)}")
|
||||
success = False
|
||||
|
||||
for item in must_not_contain:
|
||||
if item in content:
|
||||
print(f"❌ FORBIDDEN CONTENT: '{item}' in {os.path.basename(path)}")
|
||||
success = False
|
||||
|
||||
if success:
|
||||
print(f"✅ CONTENT VERIFIED: {os.path.basename(path)}")
|
||||
return success
|
||||
|
||||
def main():
|
||||
print("=== Running Build Tests ===")
|
||||
|
||||
# 1. Existence Check
|
||||
if not all([
|
||||
check_file_exists(INSTALL_HTML, "Installer HTML"),
|
||||
check_file_exists(BOOKMARKLET_TXT, "Bookmarklet Text"),
|
||||
check_file_exists(STANDALONE_HTML, "Standalone HTML")
|
||||
]):
|
||||
sys.exit(1)
|
||||
|
||||
# 2. Bookmarklet Logic Check
|
||||
# Must have the CSS injection fix from the external AI
|
||||
# Must have correct versioning
|
||||
# Must be properly URL encoded (checking for common issues)
|
||||
|
||||
# Read bookmarklet code (decoded mostly by being in txt? No, txt is usually the raw URL)
|
||||
with open(BOOKMARKLET_TXT, 'r') as f:
|
||||
bm_code = f.read().strip()
|
||||
|
||||
if not bm_code.startswith("javascript:"):
|
||||
print("❌ Bookmarklet does not start with 'javascript:'")
|
||||
sys.exit(1)
|
||||
|
||||
# Check for placeholder leftovers
|
||||
if not check_content(BOOKMARKLET_TXT,
|
||||
must_contain=["document.createElement('style')", "M1", "M2"],
|
||||
must_not_contain=["{{VERSION}}", "{{CSS_ESCAPED}}"]):
|
||||
sys.exit(1)
|
||||
|
||||
# Check for CSS injection specific logic
|
||||
if "document.head.appendChild(s)" not in bm_code and "appendChild(s)" not in bm_code: # URL encoded might mask this, strictly checking decoded would be better but simple check first
|
||||
# Actually bm_code is URL encoded. We should decode it to verify logic.
|
||||
import urllib.parse
|
||||
decoded = urllib.parse.unquote(bm_code)
|
||||
if "document.createElement('style')" not in decoded:
|
||||
print("❌ CSS Injection logic missing in bookmarklet")
|
||||
sys.exit(1)
|
||||
print("✅ CSS Injection logic confirmed")
|
||||
|
||||
# 3. Installer Check
|
||||
if not check_content(INSTALL_HTML,
|
||||
must_contain=["Kantine Wrapper", "So funktioniert's", "changelog-container"],
|
||||
must_not_contain=["CHANGELOG_HTML_PLACEHOLDER"]): # If we used that
|
||||
sys.exit(1)
|
||||
|
||||
print("🎉 ALL TESTS PASSED")
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1 +1 @@
|
||||
v1.1.2
|
||||
v1.2.0
|
||||
|
||||
Reference in New Issue
Block a user