Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
492bb96fff | ||
|
|
9e3862093e | ||
|
|
c90c03084b | ||
|
|
76e179b077 |
No files matched your search
@@ -229,6 +229,26 @@
|
|||||||
],
|
],
|
||||||
"port": 8107
|
"port": 8107
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "becker",
|
||||||
|
"runtimeExecutable": "powershell",
|
||||||
|
"runtimeArgs": [
|
||||||
|
"-NoProfile",
|
||||||
|
"-Command",
|
||||||
|
"$env:APP_ENV='dev'; $env:DATABASE_URL='sqlite:///C:/Django Project/KantSites/var/becker.db'; $env:MEDIA_DIRECTORY='C:/Django Project/KantSites/var/becker-media'; $env:SITE_ORIGIN='http://127.0.0.1:8116'; & C:/php84/php.exe -d upload_max_filesize=8M -d post_max_size=10M -d memory_limit=256M -S 127.0.0.1:8116 -t public bin/dev-router.php"
|
||||||
|
],
|
||||||
|
"port": 8116
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "becker-prod",
|
||||||
|
"runtimeExecutable": "powershell",
|
||||||
|
"runtimeArgs": [
|
||||||
|
"-NoProfile",
|
||||||
|
"-Command",
|
||||||
|
"$env:APP_ENV='prod'; $env:APP_DEBUG='0'; $env:DATABASE_URL='sqlite:///C:/Django Project/KantSites/var/becker.db'; $env:MEDIA_DIRECTORY='C:/Django Project/KantSites/var/becker-media'; $env:SITE_ORIGIN='http://127.0.0.1:8117'; & C:/php84/php.exe -d upload_max_filesize=8M -d post_max_size=10M -d memory_limit=256M -S 127.0.0.1:8117 -t public bin/dev-router.php"
|
||||||
|
],
|
||||||
|
"port": 8117
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "luximmo",
|
"name": "luximmo",
|
||||||
"runtimeExecutable": "powershell",
|
"runtimeExecutable": "powershell",
|
||||||
|
|||||||
@@ -1,5 +1,25 @@
|
|||||||
# Projektstatus
|
# Projektstatus
|
||||||
|
|
||||||
|
## Neue Installation „Becker – Just In Time e. Kfm.“, Wiernsheim (10.11.2026)
|
||||||
|
|
||||||
|
**Anlass:** Umut lieferte `Becker-Just-In-Time-Version-5.zip` (ChatGPT-Sites-Entwurf), `Logo_Becker_original.pdf` und sieben Werbemotive mit Logos: „nachbauen, an die CI halten, eigenen Senf dazugeben, Bilder entlogolisieren und von ChatGPT ohne Logos nachbauen lassen“.
|
||||||
|
|
||||||
|
**Umgesetzt:** Die Fotos hat ChatGPT in Umuts Konto neu erzeugt (11 Motive, `var/becker-quelle/ki`, Originale in `var/becker-quelle/original`); die Asbestmotive zeigen dabei Schutzanzug und Atemschutz. `scripts/build-becker-assets.php` stellt das Logo aus dem PDF-Rasterbild frei (Kopf quer, Fuß gestapelt, drei Leistungssymbole, Favicon). `sh scripts/reset-becker.sh [var/becker-quelle]` baut alles neu: Navy #172234 + Logo-Gold #F4B43A, Montserrat/Manrope, Startseite mit Hero, Leistungskarten, Vorher/Nachher-Regler (Plugin „vergleich“), Ablauf, Einblicke-Galerie, Team, Seiten `/gartenbau`, `/zaunbau`, `/asbestsanierung`, `/kontakt` (Formular `anfrage` in zwei Schritten), Impressum, Datenschutz, 404, Paket `var/becker-paket.zip`. Port 8116 (dev) / 8117 (prod), Passwort in `var/becker-zugang.txt`.
|
||||||
|
|
||||||
|
**Geprüft:** Lighthouse im Produktionsmodus für `/`, `/gartenbau`, `/asbestsanierung`, `/kontakt`: Leistung mobil 97–98, Desktop 99–100; Barrierefreiheit, Best Practices, SEO, Agentic Browsing je 100. Ganzseitige Aufnahmen 1440 und 390 px angesehen. Gold-Streifen als Inline-SVG (vorher CSS-Verlauf, sah treppig aus). Nicht geprüft: `test:browser`, Formularversand, Bedienung des Reglers per Tastatur von Hand.
|
||||||
|
|
||||||
|
**Kern:** neues Symbol `house` (geschlossene Hausform, Tür ausgespart) in `public/assets/icons.js`, per `node scripts/build-icons.mjs` in Twig und Validator; Becker nutzt es als Startseiten-Punkt im Menü. `tests/icons.test.mjs` und PHPUnit-Filter „Icon“ (26) grün. Das Becker-Paket braucht deshalb einen Kern mit diesem Symbol (nächstes Release).
|
||||||
|
|
||||||
|
**Offen:** Impressum – „e. Kfm.“ verlangt Registergericht und HRA-Nummer (fehlen); die im Entwurf als USt-IdNr. genannte „48116/36926“ ist eine Steuernummer und steht deshalb nicht drin. E-Mail: Entwurf `info@becker-justintime.de`, Logo-PDF `Becker-Justintime@web.de` – verwendet ist die aus dem Entwurf. Fotos sind KI-Symbolbilder (so im Bildnachweis). Domain/Hosting unbekannt.
|
||||||
|
|
||||||
|
## Fassung 1.39.1: SVG statt Schriftzeichen auf der Website, Luximmo-Immobilien (09.11.2026)
|
||||||
|
|
||||||
|
**Anlass:** Umut: „nur eigene SVGs nutzen“. Bildbetrachter, PDF-Betrachter, Nach-oben-Knopf, Video-Knopf, Menüpfeile, Brotkrumen, Weiterlesen, Blättern und Zitatsterne sind SVG (Masken in `site.css`, sonst eingebettet).
|
||||||
|
|
||||||
|
**Geprüft:** PHPUnit 692 grün (PHP 8.4), `npm test` 41, `test:editor`, `test:browser`, Twig-Lint; Symbole im Browser nachgemessen. Tag `v1.39.1`, Download stimmt mit der Prüfsumme überein.
|
||||||
|
|
||||||
|
**Offen:** Die Verwaltung enthält weiter Schriftzeichen (Editor-Symbole samt Plugin-Bausteinen, Pfeile auf Knöpfen). `var/luximmo-paket.zip` trägt Fassung 1.39.0 und hat die Immobilien-Seite. Im Menü von Luximmo bricht der fünfte Punkt zwischen etwa 1025 und 1130 px um. Immoscout-Plugin aktuell 1.5.2: Paket-Import ersetzt die Mediathek, der Abgleich holt die Bilder danach neu.
|
||||||
|
|
||||||
## Kern: Plugins mit PHP-Code; Plugin „ImmoScout-Abgleich“ für DEEG (09.11.2026)
|
## Kern: Plugins mit PHP-Code; Plugin „ImmoScout-Abgleich“ für DEEG (09.11.2026)
|
||||||
|
|
||||||
**Anlass:** Umut: ImmoScout-Objekte im Takt abgleichen, kostenlos per URL, „100 % ein Plugin“, „wie WordPress“.
|
**Anlass:** Umut: ImmoScout-Objekte im Takt abgleichen, kostenlos per URL, „100 % ein Plugin“, „wie WordPress“.
|
||||||
|
|||||||
@@ -39,10 +39,6 @@
|
|||||||
/* latin */
|
/* latin */
|
||||||
@font-face{font-family:'DM Sans';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/dm-sans-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
@font-face{font-family:'DM Sans';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/dm-sans-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
@font-face{font-family:'Manrope';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/manrope-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
|
||||||
/* latin */
|
|
||||||
@font-face{font-family:'Manrope';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/manrope-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
|
||||||
/* latin-ext */
|
|
||||||
@font-face{font-family:'Lora';font-style:normal;font-weight:500 600;font-display:swap;src:url(/assets/fonts/lora-500-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
@font-face{font-family:'Lora';font-style:normal;font-weight:500 600;font-display:swap;src:url(/assets/fonts/lora-500-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||||||
/* latin */
|
/* latin */
|
||||||
@font-face{font-family:'Lora';font-style:normal;font-weight:500 600;font-display:swap;src:url(/assets/fonts/lora-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
@font-face{font-family:'Lora';font-style:normal;font-weight:500 600;font-display:swap;src:url(/assets/fonts/lora-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||||||
@@ -50,3 +46,11 @@
|
|||||||
@font-face{font-family:'Instrument Sans';font-style:normal;font-weight:400 600;font-display:swap;src:url(/assets/fonts/instrument-sans-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
@font-face{font-family:'Instrument Sans';font-style:normal;font-weight:400 600;font-display:swap;src:url(/assets/fonts/instrument-sans-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||||||
/* latin */
|
/* latin */
|
||||||
@font-face{font-family:'Instrument Sans';font-style:normal;font-weight:400 600;font-display:swap;src:url(/assets/fonts/instrument-sans-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
@font-face{font-family:'Instrument Sans';font-style:normal;font-weight:400 600;font-display:swap;src:url(/assets/fonts/instrument-sans-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||||||
|
/* latin-ext */
|
||||||
|
@font-face{font-family:'Manrope';font-style:normal;font-weight:400 800;font-display:swap;src:url(/assets/fonts/manrope-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||||||
|
/* latin */
|
||||||
|
@font-face{font-family:'Manrope';font-style:normal;font-weight:400 800;font-display:swap;src:url(/assets/fonts/manrope-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||||||
|
/* latin-ext */
|
||||||
|
@font-face{font-family:'Montserrat';font-style:normal;font-weight:700 800;font-display:swap;src:url(/assets/fonts/montserrat-700-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||||||
|
/* latin */
|
||||||
|
@font-face{font-family:'Montserrat';font-style:normal;font-weight:700 800;font-display:swap;src:url(/assets/fonts/montserrat-700-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -74,6 +74,7 @@ export const ICON_PATHS = {
|
|||||||
star: 'm12 3 2.7 5.9 6.3.7-4.7 4.3 1.3 6.1L12 17l-5.6 3 1.3-6.1L3 9.6l6.3-.7Z',
|
star: 'm12 3 2.7 5.9 6.3.7-4.7 4.3 1.3 6.1L12 17l-5.6 3 1.3-6.1L3 9.6l6.3-.7Z',
|
||||||
// Haus, Garten und Handwerk
|
// Haus, Garten und Handwerk
|
||||||
home: 'm3 11.5 9-7.5 9 7.5M5.5 10v10h13V10M10 20v-6.5h4V20',
|
home: 'm3 11.5 9-7.5 9 7.5M5.5 10v10h13V10M10 20v-6.5h4V20',
|
||||||
|
house: 'M4 10.5 12 4l8 6.5V19a1 1 0 0 1-1 1h-4.5v-5.5h-5V20H5a1 1 0 0 1-1-1Z',
|
||||||
building: 'M5 21V4h10v17m0-12h4v12M3 21h18M8.5 7.5h3m-3 3.5h3m-3 3.5h3',
|
building: 'M5 21V4h10v17m0-12h4v12M3 21h18M8.5 7.5h3m-3 3.5h3m-3 3.5h3',
|
||||||
wrench: 'M14.5 3.5a5 5 0 0 0-4.6 6.9L3.5 16.8a1.9 1.9 0 0 0 2.7 2.7l6.4-6.4a5 5 0 0 0 6.9-4.6l-3 3-3-1-1-3Z',
|
wrench: 'M14.5 3.5a5 5 0 0 0-4.6 6.9L3.5 16.8a1.9 1.9 0 0 0 2.7 2.7l6.4-6.4a5 5 0 0 0 6.9-4.6l-3 3-3-1-1-3Z',
|
||||||
hammer: 'M14 8.5 4.5 18a1.5 1.5 0 0 0 2.1 2.1L16 10.5M11 6l3-3 3.5 1L21 7.5 18.5 10l-2-2-2.5 2.5Z',
|
hammer: 'M14 8.5 4.5 18a1.5 1.5 0 0 0 2.1 2.1L16 10.5M11 6l3-3 3.5 1L21 7.5 18.5 10l-2-2-2.5 2.5Z',
|
||||||
@@ -128,7 +129,7 @@ export const ICON_LABELS = {
|
|||||||
mic: 'Mikrofon', book: 'Buch',
|
mic: 'Mikrofon', book: 'Buch',
|
||||||
user: 'Person', people: 'Personen', login: 'Anmelden', lock: 'Schloss', key: 'Schlüssel', shield: 'Schutz',
|
user: 'Person', people: 'Personen', login: 'Anmelden', lock: 'Schloss', key: 'Schlüssel', shield: 'Schutz',
|
||||||
eye: 'Ansehen', 'thumbs-up': 'Daumen hoch', award: 'Auszeichnung', graduation: 'Ausbildung', heart: 'Herz', star: 'Stern',
|
eye: 'Ansehen', 'thumbs-up': 'Daumen hoch', award: 'Auszeichnung', graduation: 'Ausbildung', heart: 'Herz', star: 'Stern',
|
||||||
home: 'Haus', building: 'Gebäude', wrench: 'Werkzeug', hammer: 'Hammer', brush: 'Malerrolle', ruler: 'Lineal',
|
home: 'Haus', house: 'Haus (Fläche)', building: 'Gebäude', wrench: 'Werkzeug', hammer: 'Hammer', brush: 'Malerrolle', ruler: 'Lineal',
|
||||||
leaf: 'Blatt', tree: 'Baum', sun: 'Sonne', droplet: 'Wasser', flame: 'Flamme', bolt: 'Strom', solar: 'Solar',
|
leaf: 'Blatt', tree: 'Baum', sun: 'Sonne', droplet: 'Wasser', flame: 'Flamme', bolt: 'Strom', solar: 'Solar',
|
||||||
thermometer: 'Temperatur', snowflake: 'Kälte', car: 'Auto',
|
thermometer: 'Temperatur', snowflake: 'Kälte', car: 'Auto',
|
||||||
check: 'Häkchen', 'check-circle': 'Häkchen im Kreis', info: 'Info', help: 'Frage', alert: 'Warnung',
|
check: 'Häkchen', 'check-circle': 'Häkchen im Kreis', info: 'Info', help: 'Frage', alert: 'Warnung',
|
||||||
@@ -144,7 +145,7 @@ export const ICON_GROUPS = [
|
|||||||
['Handel & Geld', ['shop', 'cart', 'tag', 'euro', 'credit-card', 'gift', 'percent', 'truck', 'package', 'briefcase']],
|
['Handel & Geld', ['shop', 'cart', 'tag', 'euro', 'credit-card', 'gift', 'percent', 'truck', 'package', 'briefcase']],
|
||||||
['Dateien & Medien', ['document', 'download', 'upload', 'print', 'link', 'share', 'image', 'camera', 'video', 'play', 'pause', 'music', 'mic', 'book']],
|
['Dateien & Medien', ['document', 'download', 'upload', 'print', 'link', 'share', 'image', 'camera', 'video', 'play', 'pause', 'music', 'mic', 'book']],
|
||||||
['Personen & Sicherheit', ['user', 'people', 'login', 'lock', 'key', 'shield', 'eye', 'thumbs-up', 'award', 'graduation', 'heart', 'star']],
|
['Personen & Sicherheit', ['user', 'people', 'login', 'lock', 'key', 'shield', 'eye', 'thumbs-up', 'award', 'graduation', 'heart', 'star']],
|
||||||
['Haus & Handwerk', ['home', 'building', 'wrench', 'hammer', 'brush', 'ruler', 'leaf', 'tree', 'sun', 'droplet', 'flame', 'bolt', 'solar', 'thermometer', 'snowflake', 'car']],
|
['Haus & Handwerk', ['home', 'house', 'building', 'wrench', 'hammer', 'brush', 'ruler', 'leaf', 'tree', 'sun', 'droplet', 'flame', 'bolt', 'solar', 'thermometer', 'snowflake', 'car']],
|
||||||
['Allgemein', ['check', 'check-circle', 'info', 'help', 'alert', 'search', 'settings', 'filter', 'grid', 'list', 'sparkle', 'coffee', 'utensils', 'laptop', 'hardware', 'network', 'design']],
|
['Allgemein', ['check', 'check-circle', 'info', 'help', 'alert', 'search', 'settings', 'filter', 'grid', 'list', 'sparkle', 'coffee', 'utensils', 'laptop', 'hardware', 'network', 'design']],
|
||||||
['Soziale Netzwerke', ['facebook', 'instagram', 'whatsapp']],
|
['Soziale Netzwerke', ['facebook', 'instagram', 'whatsapp']],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bereitet Logo und Fotos von „Becker – Just In Time e. Kfm.“ für die Mediathek des Nachbaus vor.
|
||||||
|
*
|
||||||
|
* Quellordner (var/becker-quelle):
|
||||||
|
* - logo-original.png: das Rasterbild aus Logo_Becker_original.pdf (1536 × 1024, Navy-Grund #172234),
|
||||||
|
* - ki/*.png: die von ChatGPT ohne Logos neu erzeugten Fotos (10.11.2026, nach Umuts Vorlagen).
|
||||||
|
*
|
||||||
|
* Daraus entstehen im Zielordner:
|
||||||
|
* - logo.png: Bagger-Signet links, „BECKER / JUST IN TIME e. Kfm.“ rechts – für den Kopf,
|
||||||
|
* - logo-gross.png: das Logo gestapelt mit den drei Leistungssymbolen – für den Fuß,
|
||||||
|
* - favicon.png: das Bagger-Signet auf Navy, 192 × 192,
|
||||||
|
* - je Foto eine WebP-Datei (Startbild 1920 px, sonst 1600 px breit).
|
||||||
|
*
|
||||||
|
* Der Navy-Grund des Logos wird weich freigestellt: Deckkraft aus dem Farbabstand zum Grund,
|
||||||
|
* die Kantenfarbe zurückgerechnet. So passt das Logo auf jede dunkle Fläche.
|
||||||
|
*
|
||||||
|
* Aufruf: php scripts/build-becker-assets.php <Quellordner> <Zielordner>
|
||||||
|
*/
|
||||||
|
$quelle = rtrim($argv[1] ?? '', '/\\');
|
||||||
|
$ziel = rtrim($argv[2] ?? '', '/\\');
|
||||||
|
if ('' === $quelle || '' === $ziel || !is_file($quelle.'/logo-original.png')) {
|
||||||
|
fwrite(STDERR, "Aufruf: php scripts/build-becker-assets.php <Ordner mit logo-original.png und ki/> <Zielordner>\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!is_dir($ziel) && !mkdir($ziel, 0775, true)) {
|
||||||
|
fwrite(STDERR, "Zielordner lässt sich nicht anlegen: $ziel\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$logo = imagecreatefrompng($quelle.'/logo-original.png');
|
||||||
|
$grund = [23, 34, 52];
|
||||||
|
|
||||||
|
/** Ein Ausschnitt des Logos mit freigestelltem Navy-Grund. */
|
||||||
|
$freistellen = static function (int $x, int $y, int $b, int $h) use ($logo, $grund): GdImage {
|
||||||
|
$bild = imagecreatetruecolor($b, $h);
|
||||||
|
imagealphablending($bild, false);
|
||||||
|
imagesavealpha($bild, true);
|
||||||
|
for ($j = 0; $j < $h; ++$j) {
|
||||||
|
for ($i = 0; $i < $b; ++$i) {
|
||||||
|
$c = imagecolorat($logo, $x + $i, $y + $j);
|
||||||
|
$p = [$c >> 16 & 0xFF, $c >> 8 & 0xFF, $c & 0xFF];
|
||||||
|
$abstand = max(abs($p[0] - $grund[0]), abs($p[1] - $grund[1]), abs($p[2] - $grund[2]));
|
||||||
|
$a = min(1.0, max(0.0, ($abstand - 6) / 90));
|
||||||
|
if ($a <= 0.0) {
|
||||||
|
imagesetpixel($bild, $i, $j, imagecolorallocatealpha($bild, 0, 0, 0, 127));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$f = array_map(static fn (int $k): int => (int) max(0, min(255, round($grund[$k] + ($p[$k] - $grund[$k]) / $a))), [0, 1, 2]);
|
||||||
|
imagesetpixel($bild, $i, $j, imagecolorallocatealpha($bild, $f[0], $f[1], $f[2], (int) round(127 * (1 - $a))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bild;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Verkleinert mit Durchsichtigkeit. */
|
||||||
|
$verkleinern = static function (GdImage $bild, int $breite): GdImage {
|
||||||
|
$hoehe = (int) round(imagesy($bild) * $breite / imagesx($bild));
|
||||||
|
$neu = imagecreatetruecolor($breite, $hoehe);
|
||||||
|
imagealphablending($neu, false);
|
||||||
|
imagesavealpha($neu, true);
|
||||||
|
imagefill($neu, 0, 0, imagecolorallocatealpha($neu, 0, 0, 0, 127));
|
||||||
|
imagecopyresampled($neu, $bild, 0, 0, 0, 0, $breite, $hoehe, imagesx($bild), imagesy($bild));
|
||||||
|
|
||||||
|
return $neu;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bänder im Original (gemessen): Signet y 15–455 / x 360–1196, „BECKER“ y 466–636,
|
||||||
|
// „JUST IN TIME e. Kfm.“ mit Linien y 647–701 / x 162–1382, Leistungssymbole y 722–897.
|
||||||
|
$signet = $freistellen(352, 8, 852, 456);
|
||||||
|
$schrift = $freistellen(154, 458, 1236, 252);
|
||||||
|
|
||||||
|
// Querformat für den Kopf: Signet links (so hoch wie die Schrift plus etwas), Schrift rechts.
|
||||||
|
$sh = 330;
|
||||||
|
$sb = (int) round(852 * $sh / 456);
|
||||||
|
$quer = imagecreatetruecolor($sb + 36 + 1236, $sh);
|
||||||
|
imagealphablending($quer, false);
|
||||||
|
imagesavealpha($quer, true);
|
||||||
|
imagefill($quer, 0, 0, imagecolorallocatealpha($quer, 0, 0, 0, 127));
|
||||||
|
imagealphablending($quer, true);
|
||||||
|
imagecopyresampled($quer, $signet, 0, 0, 0, 0, $sb, $sh, 852, 456);
|
||||||
|
imagecopy($quer, $schrift, $sb + 36, (int) round(($sh - 252) / 2) + 10, 0, 0, 1236, 252);
|
||||||
|
imagealphablending($quer, false);
|
||||||
|
imagepng($verkleinern($quer, 760), $ziel.'/logo.png', 9);
|
||||||
|
echo 'logo.png: 760 × '.(int) round($sh * 760 / imagesx($quer))."\n";
|
||||||
|
|
||||||
|
$gross = $freistellen(100, 8, 1336, 898);
|
||||||
|
imagepng($verkleinern($gross, 560), $ziel.'/logo-gross.png', 9);
|
||||||
|
echo "logo-gross.png: 560 px breit\n";
|
||||||
|
|
||||||
|
// Die drei Leistungssymbole des Logos (Blätter, Zaun, Dach) einzeln, quadratisch, 128 px.
|
||||||
|
foreach (['symbol-garten' => [250, 716, 186, 120], 'symbol-zaun' => [679, 716, 176, 124], 'symbol-asbest' => [1071, 716, 226, 120]] as $name => [$x, $y, $b, $h]) {
|
||||||
|
$teil = $freistellen($x, $y, $b, $h);
|
||||||
|
$q = max($b, $h);
|
||||||
|
$quadrat = imagecreatetruecolor(128, 128);
|
||||||
|
imagealphablending($quadrat, false);
|
||||||
|
imagesavealpha($quadrat, true);
|
||||||
|
imagefill($quadrat, 0, 0, imagecolorallocatealpha($quadrat, 0, 0, 0, 127));
|
||||||
|
$f = 128 / $q;
|
||||||
|
imagecopyresampled($quadrat, $teil, (int) round((128 - $b * $f) / 2), (int) round((128 - $h * $f) / 2), 0, 0, (int) round($b * $f), (int) round($h * $f), $b, $h);
|
||||||
|
imagepng($quadrat, $ziel.'/'.$name.'.png', 9);
|
||||||
|
echo "$name.png: 128 × 128\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seitensymbol: Signet mittig auf Navy.
|
||||||
|
$fav = imagecreatetruecolor(192, 192);
|
||||||
|
imagefill($fav, 0, 0, imagecolorallocate($fav, ...$grund));
|
||||||
|
imagecopyresampled($fav, $logo, 14, 22 + (int) round((148 - 164 * 440 / 836) / 2), 360, 15, 164, (int) round(164 * 440 / 836), 836, 440);
|
||||||
|
imagepng($fav, $ziel.'/favicon.png', 9);
|
||||||
|
echo "favicon.png: 192 × 192\n";
|
||||||
|
|
||||||
|
// Fotos: ChatGPT liefert PNG; als WebP auf Zielbreite.
|
||||||
|
foreach (['haus' => 1920, 'team' => 1600, 'zaun' => 1600, 'zauntor' => 1600, 'asbest' => 1600, 'dach' => 1600,
|
||||||
|
'bagger' => 1600, 'terrasse' => 1600, 'zisterne' => 1600, 'vorher' => 1600, 'nachher' => 1600] as $name => $breite) {
|
||||||
|
$pfad = $quelle.'/ki/'.$name.'.png';
|
||||||
|
if (!is_file($pfad)) {
|
||||||
|
fwrite(STDERR, "Foto fehlt: $pfad\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$bild = imagecreatefrompng($pfad);
|
||||||
|
$breite = min($breite, imagesx($bild));
|
||||||
|
$hoehe = (int) round(imagesy($bild) * $breite / imagesx($bild));
|
||||||
|
$neu = imagecreatetruecolor($breite, $hoehe);
|
||||||
|
imagecopyresampled($neu, $bild, 0, 0, 0, 0, $breite, $hoehe, imagesx($bild), imagesy($bild));
|
||||||
|
imagewebp($neu, $ziel.'/'.$name.'.webp', 80);
|
||||||
|
echo "$name.webp: $breite × $hoehe\n";
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Wirft die Becker-Installation (Becker – Just In Time e. Kfm., Wiernsheim) weg und baut sie neu auf.
|
||||||
|
# Nur fuer den Aufbau gedacht.
|
||||||
|
# Erstes Argument (optional): Quellordner mit logo-original.png (Rasterbild aus Logo_Becker_original.pdf)
|
||||||
|
# und ki/*.png (die ohne Logos neu erzeugten Fotos). Dann entstehen Logo, Symbole und WebP-Fotos neu.
|
||||||
|
set -e
|
||||||
|
root="C:/Django Project/KantSites"
|
||||||
|
php="${PHP_BINARY:-C:/php84/php.exe}"
|
||||||
|
export DATABASE_URL="sqlite:///$root/var/becker.db"
|
||||||
|
export MEDIA_DIRECTORY="$root/var/becker-media"
|
||||||
|
assets="$root/var/becker-assets"
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
"$php" scripts/build-becker-assets.php "$1" "$assets"
|
||||||
|
fi
|
||||||
|
if [ ! -f "$assets/haus.webp" ] || [ ! -f "$assets/logo.png" ]; then
|
||||||
|
echo "Bilder fehlen: erst mit dem Quellordner (z. B. var/becker-quelle) als Argument aufrufen." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rm -f "$root/var/becker.db"
|
||||||
|
rm -rf "$root/var/becker-media"
|
||||||
|
"$php" vendor/bin/doctrine-migrations migrate --no-interaction -q
|
||||||
|
"$php" -d memory_limit=512M scripts/seed-becker.php "$assets"
|
||||||
|
# Manrope und Montserrat vom eigenen Server; der Abruf ergaenzt fonts.css nur.
|
||||||
|
if [ -f "$root/var/cacert.pem" ]; then
|
||||||
|
"$php" -d curl.cainfo="$root/var/cacert.pem" -d openssl.cafile="$root/var/cacert.pem" bin/console cms:fonts:fetch
|
||||||
|
else
|
||||||
|
"$php" bin/console cms:fonts:fetch
|
||||||
|
fi
|
||||||
|
# Das Inhaltspaket fuer eine Live-Seite (ADR 118): dort unter System -> Inhalte uebertragen importieren.
|
||||||
|
rm -f "$root/var/becker-paket.zip"
|
||||||
|
"$php" bin/console cms:paket:export --ziel="$root/var/becker-paket.zip"
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -16,7 +16,7 @@ final class DocumentValidator
|
|||||||
/** Blocks introduced with schema v6 for the sections a marketing page actually needs. */
|
/** Blocks introduced with schema v6 for the sections a marketing page actually needs. */
|
||||||
public const V6_TYPES = ['iconcard', 'stat', 'quote', 'logos', 'cta', 'contact', 'divider', 'spacer', 'accordion', 'accordionitem'];
|
public const V6_TYPES = ['iconcard', 'stat', 'quote', 'logos', 'cta', 'contact', 'divider', 'spacer', 'accordion', 'accordionitem'];
|
||||||
/** Icons ship as inline SVG from this fixed list; no icon font and no external request. */
|
/** Icons ship as inline SVG from this fixed list; no icon font and no external request. */
|
||||||
public const ICONS = ['arrow-up-right', 'arrow-right', 'arrow-left', 'arrow-up', 'arrow-down', 'chevron-right', 'chevron-left', 'chevron-up', 'chevron-down', 'arrow-circle', 'external', 'refresh', 'menu', 'close', 'plus', 'minus', 'phone', 'app', 'mail', 'chat', 'send', 'calendar', 'clock', 'pin', 'map', 'navigation', 'web', 'wifi', 'support', 'shop', 'cart', 'tag', 'euro', 'credit-card', 'gift', 'percent', 'truck', 'package', 'briefcase', 'document', 'download', 'upload', 'print', 'link', 'share', 'image', 'camera', 'video', 'play', 'pause', 'music', 'mic', 'book', 'user', 'people', 'login', 'lock', 'key', 'shield', 'eye', 'thumbs-up', 'award', 'graduation', 'heart', 'star', 'home', 'building', 'wrench', 'hammer', 'brush', 'ruler', 'leaf', 'tree', 'sun', 'droplet', 'flame', 'bolt', 'solar', 'thermometer', 'snowflake', 'car', 'check', 'check-circle', 'info', 'help', 'alert', 'search', 'settings', 'filter', 'grid', 'list', 'sparkle', 'coffee', 'utensils', 'laptop', 'hardware', 'network', 'design', 'facebook', 'instagram', 'whatsapp'];
|
public const ICONS = ['arrow-up-right', 'arrow-right', 'arrow-left', 'arrow-up', 'arrow-down', 'chevron-right', 'chevron-left', 'chevron-up', 'chevron-down', 'arrow-circle', 'external', 'refresh', 'menu', 'close', 'plus', 'minus', 'phone', 'app', 'mail', 'chat', 'send', 'calendar', 'clock', 'pin', 'map', 'navigation', 'web', 'wifi', 'support', 'shop', 'cart', 'tag', 'euro', 'credit-card', 'gift', 'percent', 'truck', 'package', 'briefcase', 'document', 'download', 'upload', 'print', 'link', 'share', 'image', 'camera', 'video', 'play', 'pause', 'music', 'mic', 'book', 'user', 'people', 'login', 'lock', 'key', 'shield', 'eye', 'thumbs-up', 'award', 'graduation', 'heart', 'star', 'home', 'house', 'building', 'wrench', 'hammer', 'brush', 'ruler', 'leaf', 'tree', 'sun', 'droplet', 'flame', 'bolt', 'solar', 'thermometer', 'snowflake', 'car', 'check', 'check-circle', 'info', 'help', 'alert', 'search', 'settings', 'filter', 'grid', 'list', 'sparkle', 'coffee', 'utensils', 'laptop', 'hardware', 'network', 'design', 'facebook', 'instagram', 'whatsapp'];
|
||||||
/** Das Symbol eines Buttons, wenn keins gewählt ist: der Pfeil, den jeder Button vor v25 hatte. */
|
/** Das Symbol eines Buttons, wenn keins gewählt ist: der Pfeil, den jeder Button vor v25 hatte. */
|
||||||
public const BUTTON_DEFAULT_ICON = 'arrow-up-right';
|
public const BUTTON_DEFAULT_ICON = 'arrow-up-right';
|
||||||
public const SPACER_SIZES = ['small', 'medium', 'large', 'huge'];
|
public const SPACER_SIZES = ['small', 'medium', 'large', 'huge'];
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
heart: 'M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7.4 4.3 4.3 0 0 1 19.5 10c0 5.4-7.5 10-7.5 10Z',
|
heart: 'M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7.4 4.3 4.3 0 0 1 19.5 10c0 5.4-7.5 10-7.5 10Z',
|
||||||
star: 'm12 3 2.7 5.9 6.3.7-4.7 4.3 1.3 6.1L12 17l-5.6 3 1.3-6.1L3 9.6l6.3-.7Z',
|
star: 'm12 3 2.7 5.9 6.3.7-4.7 4.3 1.3 6.1L12 17l-5.6 3 1.3-6.1L3 9.6l6.3-.7Z',
|
||||||
home: 'm3 11.5 9-7.5 9 7.5M5.5 10v10h13V10M10 20v-6.5h4V20',
|
home: 'm3 11.5 9-7.5 9 7.5M5.5 10v10h13V10M10 20v-6.5h4V20',
|
||||||
|
house: 'M4 10.5 12 4l8 6.5V19a1 1 0 0 1-1 1h-4.5v-5.5h-5V20H5a1 1 0 0 1-1-1Z',
|
||||||
building: 'M5 21V4h10v17m0-12h4v12M3 21h18M8.5 7.5h3m-3 3.5h3m-3 3.5h3',
|
building: 'M5 21V4h10v17m0-12h4v12M3 21h18M8.5 7.5h3m-3 3.5h3m-3 3.5h3',
|
||||||
wrench: 'M14.5 3.5a5 5 0 0 0-4.6 6.9L3.5 16.8a1.9 1.9 0 0 0 2.7 2.7l6.4-6.4a5 5 0 0 0 6.9-4.6l-3 3-3-1-1-3Z',
|
wrench: 'M14.5 3.5a5 5 0 0 0-4.6 6.9L3.5 16.8a1.9 1.9 0 0 0 2.7 2.7l6.4-6.4a5 5 0 0 0 6.9-4.6l-3 3-3-1-1-3Z',
|
||||||
hammer: 'M14 8.5 4.5 18a1.5 1.5 0 0 0 2.1 2.1L16 10.5M11 6l3-3 3.5 1L21 7.5 18.5 10l-2-2-2.5 2.5Z',
|
hammer: 'M14 8.5 4.5 18a1.5 1.5 0 0 0 2.1 2.1L16 10.5M11 6l3-3 3.5 1L21 7.5 18.5 10l-2-2-2.5 2.5Z',
|
||||||
|
|||||||
Reference in new issue
Block a user