Compare commits

...

17 Commits

Author SHA1 Message Date
Kantine Wrapper
6b8ac5ca1d chore: update build artifacts for v1.6.8 2026-03-06 10:01:16 +01:00
Kantine Wrapper
2964eba88b chore: dist files update 2026-03-06 10:01:09 +01:00
Kantine Wrapper
089e5375b4 chore: update build artifacts for v1.6.8 2026-03-06 09:55:54 +01:00
Kantine Wrapper
e514f42dbe feat: minify bookmarklet javascript via terser 2026-03-06 09:55:54 +01:00
Kantine Wrapper
f7a9b061ea chore: update build artifacts for v1.6.7 2026-03-06 09:39:33 +01:00
Kantine Wrapper
fe75347682 chore: update dist files 2026-03-06 09:39:26 +01:00
Kantine Wrapper
5c5255058c chore: increase logo image size in the header 2026-03-06 09:38:20 +01:00
Kantine Wrapper
e16398ef74 chore: update build artifacts for v1.6.7 2026-03-06 08:54:48 +01:00
Kantine Wrapper
6a57e2716f chore: footer text erweitert 2026-03-06 08:54:33 +01:00
Kantine Wrapper
d383808f4f chore: update build artifacts for v1.6.7 2026-03-06 08:46:46 +01:00
Kantine Wrapper
498b400033 style: scale header logo to 40x40px 2026-03-06 08:46:46 +01:00
Kantine Wrapper
884a17e7d3 chore: update build artifacts for v1.6.6 2026-03-06 08:41:06 +01:00
Kantine Wrapper
ad660799ec style: flatten past ordered items 2026-03-06 08:41:06 +01:00
Kantine Wrapper
a5fe50bbf0 chore: update build artifacts for v1.6.5 2026-03-06 08:39:09 +01:00
Kantine Wrapper
a98faec51e chore: release v1.6.5 2026-03-06 08:39:09 +01:00
Kantine Wrapper
212bf3b015 chore: update build artifacts for v1.6.4 2026-03-06 08:38:24 +01:00
Kantine Wrapper
f29ecd4b79 style: remove past ordered borders and swap header icon 2026-03-06 08:38:17 +01:00
12 changed files with 112 additions and 112 deletions

View File

@@ -28,13 +28,13 @@ if [ ! -f "$JS_FILE" ]; then echo "ERROR: $JS_FILE not found"; exit 1; fi
# Generate favicon.png from favicon_base.png if base exists
FAVICON_BASE="$SCRIPT_DIR/favicon_base.png"
if [ -f "$FAVICON_BASE" ]; then
echo "Generating 32x32 favicon.png from favicon_base.png..."
echo "Generating 40x40 favicon.png from favicon_base.png..."
python3 -c "
import sys
from PIL import Image
try:
img = Image.open('$FAVICON_BASE')
img_resized = img.resize((32, 32), Image.Resampling.LANCZOS)
img_resized = img.resize((40, 40), Image.Resampling.LANCZOS)
img_resized.save('$FAVICON_FILE')
except Exception as e:
print('Favicon generation error:', e)
@@ -99,15 +99,20 @@ echo "✅ Standalone HTML: $DIST_DIR/kantine-standalone.html"
# Escape CSS for embedding in JS string
CSS_ESCAPED=$(echo "$CSS_CONTENT" | sed "s/'/\\\\'/g" | tr '\n' ' ' | sed 's/ */ /g')
# Build bookmarklet payload
# Create a minified version for the injected bookmarklet payloads
echo "Minifying JS with Terser..."
TEMP_JS=$(mktemp)
echo "$JS_CONTENT" > "$TEMP_JS"
JS_MINIFIED=$(npx -y terser "$TEMP_JS" --compress --mangle)
rm -f "$TEMP_JS"
cat > "$DIST_DIR/bookmarklet-payload.js" << PAYLOADEOF
(function(){
javascript:(function(){
if(window.__KANTINE_LOADED){alert('Kantine Wrapper already loaded!');return;}
var s=document.createElement('style');
s.textContent='${CSS_ESCAPED}';
document.head.appendChild(s);
var s=document.createElement('style');s.textContent='${CSS_ESCAPED}';document.head.appendChild(s);
// Inject JS logic
var sc=document.createElement('script');
sc.textContent=$(echo "$JS_CONTENT" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo "$JS_CONTENT" | sed 's/\\/\\\\/g' | sed "s/'/\\\\'/g" | sed 's/"/\\\\"/g' | tr '\n' ' ' | sed 's/^/"/' | sed 's/$/"/');
sc.textContent=$(echo "$JS_MINIFIED" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo "$JS_MINIFIED" | sed 's/\\/\\\\/g' | sed "s/'/\\\\'/g" | sed 's/"/\\\\"/g' | tr '\n' ' ' | sed 's/^/"/' | sed 's/$/"/');
document.head.appendChild(sc);
})();
PAYLOADEOF
@@ -161,7 +166,7 @@ cat > "$DIST_DIR/install.html" << INSTALLEOF
<div style="text-align: center; margin-bottom: 30px;">
<h1 style="margin-bottom: 5px; display: flex; align-items: center; justify-content: center; gap: 10px;">
<img src="$FAVICON_URL" alt="Logo" style="width: 38px; height: 38px;">
<img src="$FAVICON_URL" alt="Logo" style="width: 40px; height: 40px;">
Kantine Wrapper
<span style="font-size:0.5em; opacity:0.6; font-weight:400; margin-left:5px;">$VERSION</span>
</h1>
@@ -239,12 +244,11 @@ fi
# Embed the bookmarklet URL inline
echo "document.getElementById('bookmarklet-link').href = " >> "$DIST_DIR/install.html"
echo "$JS_CONTENT" | python3 -c "
echo "$JS_MINIFIED" | python3 -c "
import sys, json, urllib.parse
# 1. Read JS and Replace VERSION + Favicon
js_template = sys.stdin.read()
js = js_template.replace('{{VERSION}}', '$VERSION').replace('{{FAVICON_DATA_URI}}', '$FAVICON_URL')
js = sys.stdin.read()
# 2. Prepare CSS for injection via createElement('style')
css = open('$CSS_FILE').read().replace('\n', ' ').replace(' ', ' ')
@@ -303,26 +307,30 @@ ls -la "$DIST_DIR/"
# === 4. Run build-time tests ===
echo ""
echo "=== Running Logic Tests ==="
node "$SCRIPT_DIR/test_logic.js"
timeout 15s node "$SCRIPT_DIR/test_logic.js"
LOGIC_EXIT=$?
if [ $LOGIC_EXIT -ne 0 ]; then
echo "❌ Logic tests FAILED! See above for details."
echo "❌ Logic tests FAILED or TIMED OUT (Exit: $LOGIC_EXIT)! See above for details."
exit 1
fi
echo "=== Running DOM Interaction Tests ==="
node "$SCRIPT_DIR/tests/test_dom.js"
timeout 15s node "$SCRIPT_DIR/tests/test_dom.js"
DOM_EXIT=$?
if [ $DOM_EXIT -ne 0 ]; then
echo "❌ DOM UI tests FAILED! Regressions detected."
echo "❌ DOM UI tests FAILED or TIMED OUT (Exit: $DOM_EXIT)! Regressions detected."
# Ensure playwright processes are killed if they leak
pkill -f playwright || true
pkill -f "node.*test_dom" || true
exit 1
fi
echo "=== Running Build Tests ==="
python3 "$SCRIPT_DIR/test_build.py"
timeout 15s python3 "$SCRIPT_DIR/test_build.py"
TEST_EXIT=$?
if [ $TEST_EXIT -ne 0 ]; then
echo "❌ Build tests FAILED! See above for details."
echo "❌ Build tests FAILED or TIMED OUT (Exit: $TEST_EXIT)! See above for details."
exit 1
fi
echo "✅ All build tests passed."

View File

@@ -1,3 +1,17 @@
## v1.6.8 (2026-03-06)
-**Performance**: Das JavaScript für das Kantinen-Bookmarklet wird nun beim Build-Prozess (via Terser) minimiert, was die Länge der injizierten URL spürbar reduziert.
## v1.6.7 (2026-03-06)
- 🎨 **Style**: Das neue Header-Logo (`favicon_base.png`) wird nun konsequent auf 40x40px generiert und gerendert.
## v1.6.6 (2026-03-06)
- 🎨 **Style**: Den Schatten und den hervorstehenden Karten-Effekt für bestellte Menüs an vergangenen Tagen komplett entfernt - verbleiben nun visuell flach und unaufdringlich wie nicht-bestellte Menüs.
## v1.6.5 (2026-03-06)
-**Feature**: Das `restaurant_menu` Icon im Header wurde durch das neue `favicon_base.png` Logo ersetzt, passend zur Textgröße skaliert.
- 🎨 **Style**: Violette Umrahmung (Bestellt-Markierung) an vergangenen Tagen entfernt, um den Fokus auf aktuelle und zukünftige Bestellungen zu lenken.
- 🎨 **Style**: Der Glow-Effekt für am heutigen Tag bestellte Menüs wurde intensiviert.
## v1.6.4 (2026-03-05)
-**Feature**: Sprach-Lexikon (DE/EN) massiv erweitert um österreichische Begriffe (Nockerl, Fleckerl, Topfen, Mohn, Most etc.) und gängige Tippfehler aus dem Bessa-System (trukey, coffe, oveb etc.).
- 🧹 **Cleanup**: Sprach-Lexikon dedupliziert und alphabetisch sortiert für bessere Performance und Wartbarkeit.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

34
dist/install.html vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,29 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
<!-- Fork (left, with gap to triangle) -->
<g transform="translate(2, 10)">
<!-- Tines -->
<rect x="1" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
<rect x="4.6" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
<rect x="8.2" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
<!-- Connector -->
<rect x="1" y="14" width="9" height="3.5" rx="1.5" fill="#333"/>
<!-- Handle -->
<rect x="3.5" y="16.5" width="4" height="24" rx="2" fill="#333"/>
</g>
<!-- Triangle (center, equilateral aspect ratio ~1:0.866) -->
<!-- Equilateral: base=28, height=24.25 => keeps proper ratio -->
<polygon points="32,8 47,48 17,48" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
<!-- Knife (right, with gap to triangle) -->
<g transform="translate(50, 10)">
<!-- Blade (slight curve) -->
<path d="M3,0 C3,0 3,0 3,0 L3,17 L10,14 C10,6 7,0 3,0 Z" fill="#333"/>
<!-- Spine -->
<rect x="1.5" y="0" width="2" height="18" rx="1" fill="#333"/>
<!-- Bolster -->
<rect x="1.5" y="16.5" width="8.5" height="3.5" rx="1.2" fill="#333"/>
<!-- Handle -->
<rect x="3.5" y="19" width="4" height="22" rx="2" fill="#333"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -80,7 +80,7 @@
<header class="app-header">
<div class="header-content">
<div class="brand">
<span class="material-icons-round logo-icon">restaurant_menu</span>
<img src="{{FAVICON_DATA_URI}}" alt="Logo" class="logo-img" style="height: 2em; width: 2em; object-fit: contain;">
<div class="header-left">
<h1>Kantinen Übersicht <small class="version-tag" style="font-size: 0.6em; opacity: 0.7; font-weight: 400; cursor: pointer;" title="Klick für Versionsmenü">{{VERSION}}</small></h1>
<div id="last-updated-subtitle" class="subtitle"></div>
@@ -268,7 +268,7 @@
</main>
<footer class="app-footer">
<p>Jetzt Bessa Einfach! &bull; Knapp-Kantine Wrapper &bull; <span id="current-year">${new Date().getFullYear()}</span> by Kaufis-Kitchen</p>
<p>Jetzt Bessa Einfach! &bull; Knapp-Kantine Wrapper &bull; <span id="current-year">${new Date().getFullYear()}</span> by Kaufi 😃👍 mit Hilfe von KI 🤖</p>
</footer>
</div>`;
}

View File

@@ -875,42 +875,31 @@ body {
filter: grayscale(0.4);
}
/* Enhancements for ordered items */
.menu-card.past-day .menu-item.ordered {
/* No opacity/filter here - fully visible */
background: var(--bg-card);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
border: 1px solid #8b5cf6;
border-radius: 8px;
padding: 1rem;
margin: 0 -1rem 1.5rem -1rem;
position: relative;
z-index: 10;
}
/* Past ordered items get no special frame or shadow, but remain visually distinct by staying fully opaque (via the :not(.ordered) selector above) */
.menu-item.today-ordered {
border: 2px solid #8b5cf6;
box-shadow: 0 0 20px rgba(139, 92, 246, 0.4);
box-shadow: 0 0 30px rgba(139, 92, 246, 0.6);
border-radius: 8px;
padding: 1rem;
margin: 0 -1rem 1.5rem -1rem;
background: var(--bg-card);
position: relative;
z-index: 5;
animation: pulse-glow 3s infinite;
animation: pulse-glow-strong 3s infinite;
}
@keyframes pulse-glow {
@keyframes pulse-glow-strong {
0% {
box-shadow: 0 0 15px rgba(139, 92, 246, 0.3);
box-shadow: 0 0 20px rgba(139, 92, 246, 0.4);
}
50% {
box-shadow: 0 0 25px rgba(139, 92, 246, 0.6);
box-shadow: 0 0 40px rgba(139, 92, 246, 0.8);
}
100% {
box-shadow: 0 0 15px rgba(139, 92, 246, 0.3);
box-shadow: 0 0 20px rgba(139, 92, 246, 0.4);
}
}

View File

@@ -41,20 +41,32 @@ const sandbox = {
fetch: async (url) => {
// Mock Version Check
if (url.includes('version.txt')) {
return { ok: true, text: async () => 'v9.9.9' }; // Simulate new version
return { ok: true, text: async () => 'v9.9.9', json: async () => ({}) };
}
// Mock Changelog
if (url.includes('changelog.md')) {
return { ok: true, text: async () => '## v9.9.9\n- Feature: Cool Stuff' };
return { ok: true, text: async () => '## v9.9.9\n- Feature: Cool Stuff', json: async () => ({}) };
}
return { ok: false }; // Fail others to prevent huge cascades
// Mock GitHub Tags API
if (url.includes('api.github.com/') || url.includes('/tags')) {
return { ok: true, json: async () => [{ name: 'v9.9.9' }] };
}
// Mock Menu API
if (url.includes('/food-menu/menu/')) {
return { ok: true, json: async () => ({ dates: [], menu: {} }) };
}
// Mock Orders API
if (url.includes('/user/orders')) {
return { ok: true, json: async () => ({ results: [], count: 0 }) };
}
return { ok: false, status: 404, text: async () => '', json: async () => ({}) };
},
document: {
body: createMockElement('body'),
head: createMockElement('head'),
createElement: (tag) => createMockElement(tag),
querySelector: (sel) => {
if (sel === '.material-icons-round.logo-icon') {
if (sel === '.logo-img' || sel === '.material-icons-round.logo-icon') {
const el = createMockElement('last-updated-icon-mock');
// Mock legacy prop for specific test check if needed,
// but our generic mock handles replaceWith hook

View File

@@ -1 +1 @@
v1.6.4
v1.6.8