Nach reload mit bereits erteilter einwilligung blieb das e-youtube-base-video
leer: ich kehrte frueh zurueck und ueberliess es Elementors eigenem render
(unzuverlaessig). Die anderen blocker haben einen server-platzhalter, den
loadPreConsented direkt laedt - das JS-gebaute YouTube-element nicht.
Jetzt verwalte ich das widget mit embed-URL komplett selbst:
- nicht eingewilligt -> platzhalter (eingeklappt, kein weissraum)
- eingewilligt (auch nach reload) -> iframe wird sofort direkt gebaut (16:9),
unabhaengig von Elementor/iframe_api.
Reload-fallback nur noch ohne URL.
+ version 1.4.7.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der reload-ansatz aus 1.4.4 fuer e-youtube-base war unzuverlaessig (Elementor
rendert nach reload nicht sicher nativ). Zurueck zum direkten weg: aus dem
"source"-key habe ich die embed-URL -> ich baue das iframe bei einwilligung
selbst (unabhaengig von Elementor/iframe_api). Das iframe bekommt eine
responsive 16:9-aspect-ratio (data-cb-aspect) und laedt damit voll und in
originalproportionen, auch ohne definite parent-hoehe.
Reload-pfad bleibt nur fuer den fall ganz ohne URL (video_type-fallback).
Weissraum-einklappen unveraendert. node --check ok.
+ version 1.4.6.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zwei faelle, die 1.4.4 nicht abdeckte:
- Eigenes iframe im HTML-widget liegt in <div style="height:800px"> - inline-
hoehe, keine klasse. Mein klassenbasiertes einklappen verfehlte das.
- WordPress-oEmbed (testbeitrag, ohne Elementor) reserviert die hoehe ueber
einen ::before-padding-trick, nicht ueber aspect-ratio.
Neu: statt inline-styles zu manipulieren wird per attribut [data-cb-collapsed]
+ EINER eingeschleusten CSS-regel alles neutralisiert (aspect-ratio, min/height,
::before/::after padding-hack, inline height via !important). Original-styles
bleiben unangetastet -> beim laden kommt die volle groesse exakt zurueck.
shouldCollapse() greift jetzt auch bei inline-hoehe und computed aspect-ratio,
aber nur bei "engen" wrappern (<=1 kind), damit keine ganze section schrumpft.
Logik isoliert getestet.
+ version 1.4.5.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der weissraum kam nicht von meinem platzhalter, sondern vom seitenverhaeltnis-
container (z. B. Elementor .e-youtube-base mit 16:9, oder wp-block-embed
aspect-ratio) - das reserviert die hoehe per CSS, unabhaengig vom inhalt.
- collapseAncestors(): bekannte aspect-ratio/video-wrapper um einen platzhalter
werden eingeklappt (aspect-ratio/min-height/height auto !important), solange
der blocker steht -> kein leerraum darunter. Laeuft fuer server-platzhalter
(autodetect) und JS-gebaute (Elementor-widgets).
- restoreCollapsed(): bei einwilligung wird die reservierung wieder entfernt,
sodass das embed in originalgroesse laedt.
- Elementor JS-widgets (e-youtube-base etc.) nutzen jetzt durchgaengig den
reload-pfad bei einwilligung -> Elementor rendert das video nativ in voller
originalgroesse statt eines geratenen iframes.
+ version 1.4.4 (assets cache-busting).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Das Warn-Emoji "⚠" im platzhalter-text loeste WordPress' wp-emoji aus, das
die grafik von s.w.org nachlud (drittanbieter-request). Emoji aus den texten
entfernt; das warn-dreieck wird jetzt rein per CSS gezeichnet (kein netzwerk).
Hinweis: s.w.org ist der WP-emoji-CDN, NICHT Google.
2) Der platzhalter reservierte die hoehe des eingebetteten elements -> bei
kuerzerem inhalt entstand weissraum darunter. Hoehen-reservierung entfernt
(PHP min-height-style, JS minHeight, CSS min-height:180px) - der content
blocker ist jetzt exakt so hoch wie sein eigener inhalt. Die original-masse
bleiben als data-attribute fuer das iframe nach einwilligung erhalten.
3) Redundante, partielle de_DE-.po/.mo (mit altem emoji) entfernt - deutsche
locales nutzen direkt die deutschen quell-strings.
+ version 1.4.3 (assets cache-busting).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das YouTube-video auf der startseite ist kein .elementor-widget-video, sondern
Elementors neueres element <div class="e-youtube-base" data-e-type="e-youtube"
data-settings='{"source":"https://www.youtube.com/watch?v=..."}'>. Daher griff
weder server-autodetect (kein iframe) noch mein client-handler -> leere box.
- selektor erweitert um .e-youtube-base/.e-vimeo-base und
[data-e-type^="e-youtube"|"e-vimeo"].
- URL-extraktion liest jetzt auch den key "source" (und "url").
An der echten data-settings der live-seite verifiziert.
+ version 1.4.2 (assets cache-busting).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wenn ein Elementor-video per JS gebaut wird und im DOM weder URL noch
Thumbnail steht (nur {"video_type":"youtube"}), konnte mein handler keinen
platzhalter bauen -> Elementor baut nichts (API blockiert) -> leere box.
Fallback: dienst ueber den video_type erkennen und trotzdem einen
einwilligungs-platzhalter zeigen. Da keine embed-URL bekannt ist, gibt dessen
button die einwilligung und laedt die seite neu - danach rendert Elementor das
video normal (scripts sind dann freigegeben). "Einmal laden" entfaellt dort.
+ version 1.4.1 (assets cache-busting fuer die JS-aenderung).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Header stand bereits auf 1.4.0, CB_VERSION aber auf 1.3.0. Dadurch wurden
geaenderte frontend.js/admin.js mit unveraendertem ?ver=1.3.0 ausgeliefert
und vom browser/cache als alte version geladen. Jetzt konsistent 1.4.0, damit
die JS-fixes (script-guard, elementor-youtube-erkennung) tatsaechlich greifen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Loest die YouTube/Vimeo-API-Luecke: viele dienste laden ueber <script>
(z. B. youtube.com/iframe_api, www-widgetapi.js, analytics) statt iframes -
oft per JavaScript nachgeladen, daher fuer den scanner unsichtbar.
- Pro dienst aktivierbar ueber das (umbenannte) feld "Zugehoerige Skripte
blockieren (z. B. YouTube-/Vimeo-API)" = das vorhandene loads_script-flag.
Presets (YouTube, Vimeo, Maps) haben es bereits an.
- Server-seitig: passende <script src> werden zu type="text/plain"
(src -> data-cb-src) neutralisiert, laden also nicht.
- Client-seitig: winziger guard ganz frueh im <head> patcht
appendChild/insertBefore/replaceChild und neutralisiert dynamisch
injizierte scripts VOR dem einfuegen -> kein request. Faengt damit auch
die per JS nachgeladene iframe_api ab.
- Einwilligung (per-dienst-consent, z. B. ueber den video-platzhalter)
schaltet die scripts via cbActivateScripts frei und laedt sie nach.
- Neuer shortcode [content_blocker_consent id="…"] als einwilligungs-button
fuer reine skript-dienste ohne sichtbaren platzhalter.
- guard-logik mit DOM-mock getestet (block + reinject), server-regex
isoliert geprueft. i18n DE/EN ergaenzt (127 strings).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Feature "Schriften lokal hosten" komplett zurueckgebaut (class-fonts.php,
tab, ajax-endpunkte, output-buffer, admin-js-handler, optionen).
- Scan: wird fonts.googleapis.com / fonts.gstatic.com erkannt, steht in der
Aktion-spalte jetzt der nicht-klickbare hinweis "Schriftart fuer
DSGVO-konformen Betrieb lokal hosten." statt eines buttons.
- i18n entsprechend bereinigt (123 strings).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Lizenz-Tab: bei vollen Plaetzen erscheint ein "Lizenz upgraden"-Button
(https://lucas-orth.de/wp-plugins/gdpr-content-blocker/) zusaetzlich zur
domain-freigabe.
- Neues Feature "Schriften": Google Fonts lokal hosten (button-modell).
Admin klickt "Jetzt herunterladen & einbinden" -> plugin scannt die seiten,
laedt googleapis-CSS + gstatic-schriftdateien einmalig in den uploads-ordner,
schreibt die pfade lokal um und tauscht sie per output-buffer im quelltext.
Abgedeckt: <link>, inline-@import/url() UND @import/url() in gleicher-origin
externen CSS-dateien (mit absolutierung der restlichen relativen pfade).
preconnect/dns-prefetch zu google-font-hosts werden entfernt (kein IP-leak).
Toggle zum aus/einschalten + "Lokale Schriften loeschen".
- i18n-pipeline robuster: build-en-mo.py nutzt jetzt translations-en.json
(lookup per quell-string, reihenfolge-unabhaengig) und bricht mit liste ab,
falls eine uebersetzung fehlt. Alle neuen strings DE/EN ergaenzt (139).
- version 1.3.0 (header + CB_VERSION).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Nur ladende <link rel=...> (stylesheet/preload/icon/...) werden gezaehlt;
rel=profile/canonical/pingback etc. (z.B. gmpg.org) sind keine Requests mehr.
- Plugin-Version + Header auf 1.2.0 (passend zu readme), Changelog-Eintrag.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Aufklapp-Pfeil deutlich groesser (26px).
- Tabs: kein Fokus-Kasten mehr, nur untere Linie markiert den aktiven Tab.
- CB_VERSION + Header auf 1.1.0 -> bricht gecachte alte admin.js/frontend.js
(Ursache, dass ein Dienst auf einer Seite nicht aufklappbar war).
- Aufklappen via Event-Delegation (robust gegen Load-Order/dynamische Zeilen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
UI:
- Ein-/Ausklappen jetzt mit grossem +/- Icon statt kleinem Pfeil.
- "Entfernen" ist ein Papierkorb-Symbol (dashicon).
- Aktiver Tab klar gekennzeichnet (Akzent-Unterstrich + Farbe).
- 20px Abstand zwischen Tabs und Inhalt.
Funktionen:
- Scan erkennt Anbieter, fuer die es eine Vorlage gibt ("Vorlage verfuegbar"),
und "Vorlage uebernehmen" fuellt die komplette Vorlage statt nur Host/Pattern.
- Platzhalter: Checkbox "Diesen Dienst kuenftig immer laden" (Standard AN).
Abgewaehlt -> Inhalt wird nur einmal geladen, keine dauerhafte Einwilligung.
i18n:
- Sprachumschaltung: Deutsch fuer alle de_* Locales, Englisch fuer alle anderen
(plugin_locale-Filter). Vollstaendige englische Uebersetzung (126 Strings,
inkl. Vorlagentexte/Empfaenger) als gdpr-content-blocker-en_US.po/.mo.
- Helper-Skripte (extract/build) in hilfsdaten/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Eltern-Ordner ist jetzt EIN Git-Repo (statt getrennter Repos).
- root .gitignore haelt Secrets (.env), node_modules, DB und Build-Artefakte raus.
- release.ps1: manueller Release (ZIP bauen + ans Backend laden).
- root README mit Struktur und Release-Ablauf.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>