Versión inicial del plugin FP Genocide Maps (v1.5.2)
CPT geep_map + shortcode [geep_maps] para la sección Architecture of Genocide de la home: acordeón exclusivo con imagen por mapa, lightbox con botón de compartir y enlaces #map-<slug>. Soporte WPML (EN/AR) con herencia de la imagen del idioma original y CSS RTL.
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
# FP Genocide Maps
|
||||||
|
|
||||||
|
Plugin de WordPress para gestionar los mapas de la sección **"Architecture of Genocide"** de la home de GEEP (Global Energy Embargo for Palestine).
|
||||||
|
|
||||||
|
## Qué hace
|
||||||
|
|
||||||
|
- Registra el tipo de contenido **Genocide Maps** (`geep_map`): cada mapa es una entrada con título, descripción, imagen destacada (el mapa) y orden.
|
||||||
|
- El shortcode **`[geep_maps]`** pinta la sección completa: columna de imagen + acordeón de mapas, replicando el diseño original construido en Divi 5.
|
||||||
|
- Acordeón exclusivo: siempre hay un mapa seleccionado (el primero al cargar); al seleccionar otro, la imagen cambia con un fundido.
|
||||||
|
- **Lightbox**: clic en la imagen para ampliarla, con botón de compartir (diálogo nativo en móvil, copia al portapapeles en escritorio).
|
||||||
|
- **Enlaces compartibles** por mapa: `#map-<slug>` selecciona ese mapa al cargar la página y desplaza hasta la sección.
|
||||||
|
- **WPML**: tipo de contenido traducible (EN/AR); si una traducción no tiene imagen propia, hereda la del idioma original. Textos de interfaz localizados y CSS con soporte RTL.
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
1. Activar el plugin (al activarse por primera vez siembra los 8 mapas originales y marca el CPT como traducible en WPML).
|
||||||
|
2. Insertar `[geep_maps]` donde deba aparecer la sección (en la home va dentro de un módulo de código de Divi).
|
||||||
|
3. Gestionar los mapas desde el menú **Genocide Maps** del administrador: añadir, editar, asignar imagen destacada y ordenar con el campo *Order*.
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
- WordPress con Divi 5 (el diseño usa las variables globales de color/radio del sitio, con valores de respaldo).
|
||||||
|
- WPML para el funcionamiento multilingüe (opcional: sin WPML funciona en un solo idioma).
|
||||||
|
- PHP 7.4+.
|
||||||
@@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
* FP Genocide Maps — front-end styles.
|
||||||
|
*
|
||||||
|
* Replicates 1:1 the CSS Divi 5 generated for the original "texto mapa" row
|
||||||
|
* (row_3 / column_5 / column_6 / image_2 / toggle_0..7 on page 1834), so the
|
||||||
|
* section looks identical to the hand-built Divi version it replaces.
|
||||||
|
* Color/radius values reference the site's Divi global variables with their
|
||||||
|
* current values as fallbacks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --- Layout: replicates row_3's two flex columns (14/24 + 2/5, 2% gap). --- */
|
||||||
|
.geep-maps {
|
||||||
|
display: flex;
|
||||||
|
column-gap: 2%;
|
||||||
|
row-gap: 10px;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-maps-col-map {
|
||||||
|
width: calc(58.3333% - 2% * 0.41667); /* .et_flex_column_14_24 with 2% gap */
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-maps-col-toggles {
|
||||||
|
width: calc(40% - 2% * 0.6); /* .et_flex_column_2_5 with 2% gap */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 15px;
|
||||||
|
padding-left: 10px; /* column_6 */
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 767px) {
|
||||||
|
.geep-maps {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-maps-col-map,
|
||||||
|
.geep-maps-col-toggles {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Map image: replicates the Divi image module (image_2). --- */
|
||||||
|
.geep-maps-image {
|
||||||
|
display: flex;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-maps-image-wrap {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: var(--gvid-4up6riitl2, 40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-map-img {
|
||||||
|
position: relative;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-map-img.is-active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-map-img.is-active.is-shown {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Toggles: replicates the 8 Divi toggle modules (toggle_0..7). --- */
|
||||||
|
.geep-toggle {
|
||||||
|
background-color: var(--gcid-primary-color, #d96c5d);
|
||||||
|
padding: 10px 2px 0 5px;
|
||||||
|
border: 0 solid #333;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle.geep-toggle--first {
|
||||||
|
padding: 0 2px 2px 5px; /* toggle_0 had slightly different padding */
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle-title {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 0 0 40px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
/* Same line spacing as the intro paragraph above the section. */
|
||||||
|
line-height: var(--gvid-pfs7jbw9ep, 1.4em);
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle--close .geep-toggle-title {
|
||||||
|
color: var(--gcid-mpn8tovm4t, #fff5f0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle--open .geep-toggle-title {
|
||||||
|
color: var(--gcid-heading-color, #424242) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checkbox-style marker: identical size and position in both states so
|
||||||
|
* nothing shifts when a map is selected; the open one is filled white.
|
||||||
|
*/
|
||||||
|
.geep-toggle-title::before {
|
||||||
|
content: "";
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -9px;
|
||||||
|
left: 0;
|
||||||
|
right: auto;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border: 2px solid var(--gcid-secondary-color, #ffffff);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle--open .geep-toggle-title::before {
|
||||||
|
background: var(--gcid-secondary-color, #ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle-content {
|
||||||
|
position: relative;
|
||||||
|
padding-top: 20px;
|
||||||
|
/* Align the excerpt with the title text (which sits after the marker). */
|
||||||
|
padding-left: 40px;
|
||||||
|
color: var(--gcid-secondary-color, #ffffff);
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle--close .geep-toggle-content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep content visible while the open/close animation is running. */
|
||||||
|
.geep-toggle .geep-toggle-content.geep-animating {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-toggle-content p:last-of-type {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- RTL (Arabic): mirror icon and paddings. --- */
|
||||||
|
.rtl .geep-maps-col-toggles {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rtl .geep-toggle-title {
|
||||||
|
padding: 0 40px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rtl .geep-toggle-title::before {
|
||||||
|
left: auto;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rtl .geep-toggle-content {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Lightbox: click the map to view it larger + share its URL. --- */
|
||||||
|
.geep-maps-image-wrap {
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 999999;
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 3vh 3vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox.is-open {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-noscroll,
|
||||||
|
.geep-lightbox-noscroll body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-backdrop {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(20, 20, 20, 0.85);
|
||||||
|
cursor: zoom-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-inner {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
max-width: 94vw;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: calc(94vh - 60px);
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: var(--gcid-mpn8tovm4t, #fff5f0);
|
||||||
|
color: var(--gcid-heading-color, #424242);
|
||||||
|
border: 0;
|
||||||
|
border-radius: 40px;
|
||||||
|
padding: 10px 18px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-btn:hover {
|
||||||
|
background: var(--gcid-secondary-color, #ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-close {
|
||||||
|
padding: 10px 14px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geep-lightbox-toast {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 18px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: var(--gcid-heading-color, #424242);
|
||||||
|
color: var(--gcid-secondary-color, #ffffff);
|
||||||
|
border-radius: 40px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
/**
|
||||||
|
* FP Genocide Maps — front-end behavior.
|
||||||
|
*
|
||||||
|
* - Exclusive accordion with one map always open (700 ms slide, Divi's
|
||||||
|
* default speed); opening a map swaps the image with a fade.
|
||||||
|
* - Clicking the map image opens it in a lightbox with a share button.
|
||||||
|
* - Each map has a shareable URL (#map-<slug>): visiting it opens that map
|
||||||
|
* and scrolls the section into view.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var DURATION = 700;
|
||||||
|
var HASH_PREFIX = '#map-';
|
||||||
|
|
||||||
|
function slideDown(el) {
|
||||||
|
el.classList.add('geep-animating');
|
||||||
|
el.style.overflow = 'hidden';
|
||||||
|
el.style.height = '0px';
|
||||||
|
var target = el.scrollHeight;
|
||||||
|
el.style.transition = 'height ' + DURATION + 'ms ease-in-out';
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
el.style.height = target + 'px';
|
||||||
|
});
|
||||||
|
window.setTimeout(function () {
|
||||||
|
el.style.transition = '';
|
||||||
|
el.style.height = '';
|
||||||
|
el.style.overflow = '';
|
||||||
|
el.classList.remove('geep-animating');
|
||||||
|
}, DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
function slideUp(el, done) {
|
||||||
|
el.classList.add('geep-animating');
|
||||||
|
el.style.overflow = 'hidden';
|
||||||
|
el.style.height = el.scrollHeight + 'px';
|
||||||
|
el.style.transition = 'height ' + DURATION + 'ms ease-in-out';
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
el.style.height = '0px';
|
||||||
|
});
|
||||||
|
window.setTimeout(function () {
|
||||||
|
el.style.transition = '';
|
||||||
|
el.style.height = '';
|
||||||
|
el.style.overflow = '';
|
||||||
|
el.classList.remove('geep-animating');
|
||||||
|
done();
|
||||||
|
}, DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(root) {
|
||||||
|
var labels;
|
||||||
|
try {
|
||||||
|
labels = JSON.parse(root.getAttribute('data-labels') || '{}');
|
||||||
|
} catch (e) {
|
||||||
|
labels = {};
|
||||||
|
}
|
||||||
|
var images = root.querySelectorAll('.geep-map-img');
|
||||||
|
// The first map is rendered open by the shortcode.
|
||||||
|
var current = root.querySelector('.geep-toggle--open');
|
||||||
|
|
||||||
|
function showMap(key) {
|
||||||
|
// No fallback: a map without its own image leaves the gap empty.
|
||||||
|
var target = null;
|
||||||
|
if (key) {
|
||||||
|
images.forEach(function (img) {
|
||||||
|
if (img.getAttribute('data-map') === key) {
|
||||||
|
target = img;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
images.forEach(function (img) {
|
||||||
|
if (img !== target) {
|
||||||
|
img.classList.remove('is-active', 'is-shown');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (target && !target.classList.contains('is-active')) {
|
||||||
|
target.classList.add('is-active');
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
target.classList.add('is-shown');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(toggle) {
|
||||||
|
var content = toggle.querySelector('.geep-toggle-content');
|
||||||
|
toggle.classList.remove('geep-toggle--open');
|
||||||
|
slideUp(content, function () {
|
||||||
|
toggle.classList.add('geep-toggle--close');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function open(toggle) {
|
||||||
|
var content = toggle.querySelector('.geep-toggle-content');
|
||||||
|
toggle.classList.remove('geep-toggle--close');
|
||||||
|
toggle.classList.add('geep-toggle--open');
|
||||||
|
slideDown(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(toggle) {
|
||||||
|
if (toggle === current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (current) {
|
||||||
|
close(current);
|
||||||
|
}
|
||||||
|
open(toggle);
|
||||||
|
current = toggle;
|
||||||
|
showMap(toggle.getAttribute('data-map'));
|
||||||
|
}
|
||||||
|
|
||||||
|
root.querySelectorAll('.geep-toggle').forEach(function (toggle) {
|
||||||
|
var title = toggle.querySelector('.geep-toggle-title');
|
||||||
|
var content = toggle.querySelector('.geep-toggle-content');
|
||||||
|
if (!title || !content) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
title.addEventListener('click', function () {
|
||||||
|
if (content.classList.contains('geep-animating')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
select(toggle);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
* Shareable URLs: #map-<slug> selects that map on page load.
|
||||||
|
* ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
function shareUrl() {
|
||||||
|
var base = window.location.href.split('#')[0];
|
||||||
|
if (!current) {
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
return base + HASH_PREFIX + encodeURIComponent(current.getAttribute('data-slug'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function openFromHash() {
|
||||||
|
if (window.location.hash.indexOf(HASH_PREFIX) !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var slug = decodeURIComponent(window.location.hash.slice(HASH_PREFIX.length));
|
||||||
|
var target = null;
|
||||||
|
root.querySelectorAll('.geep-toggle').forEach(function (t) {
|
||||||
|
if (t.getAttribute('data-slug') === slug) {
|
||||||
|
target = t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!target || target === current) {
|
||||||
|
if (target) {
|
||||||
|
root.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Switch instantly (no slide) — the page is just loading.
|
||||||
|
if (current) {
|
||||||
|
current.classList.remove('geep-toggle--open');
|
||||||
|
current.classList.add('geep-toggle--close');
|
||||||
|
}
|
||||||
|
target.classList.remove('geep-toggle--close');
|
||||||
|
target.classList.add('geep-toggle--open');
|
||||||
|
current = target;
|
||||||
|
showMap(target.getAttribute('data-map'));
|
||||||
|
root.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
|
||||||
|
openFromHash();
|
||||||
|
window.addEventListener('hashchange', openFromHash);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
* Lightbox with share button.
|
||||||
|
* ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
var lightbox = null;
|
||||||
|
var toastTimer = null;
|
||||||
|
|
||||||
|
function buildLightbox() {
|
||||||
|
var lb = document.createElement('div');
|
||||||
|
lb.className = 'geep-lightbox';
|
||||||
|
lb.setAttribute('role', 'dialog');
|
||||||
|
lb.setAttribute('aria-modal', 'true');
|
||||||
|
lb.innerHTML =
|
||||||
|
'<div class="geep-lightbox-backdrop"></div>' +
|
||||||
|
'<figure class="geep-lightbox-inner">' +
|
||||||
|
'<div class="geep-lightbox-actions">' +
|
||||||
|
'<button type="button" class="geep-lightbox-btn geep-lightbox-share">' +
|
||||||
|
'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.6" y1="10.6" x2="15.4" y2="6.4"/><line x1="8.6" y1="13.4" x2="15.4" y2="17.6"/></svg>' +
|
||||||
|
'<span>' + (labels.share || 'Share map') + '</span>' +
|
||||||
|
'</button>' +
|
||||||
|
'<button type="button" class="geep-lightbox-btn geep-lightbox-close" aria-label="' + (labels.close || 'Close') + '">×</button>' +
|
||||||
|
'</div>' +
|
||||||
|
'<img class="geep-lightbox-img" alt="">' +
|
||||||
|
'<div class="geep-lightbox-toast" hidden>' + (labels.copied || 'Link copied!') + '</div>' +
|
||||||
|
'</figure>';
|
||||||
|
document.body.appendChild(lb);
|
||||||
|
|
||||||
|
lb.querySelector('.geep-lightbox-backdrop').addEventListener('click', closeLightbox);
|
||||||
|
lb.querySelector('.geep-lightbox-close').addEventListener('click', closeLightbox);
|
||||||
|
lb.querySelector('.geep-lightbox-share').addEventListener('click', share);
|
||||||
|
return lb;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openLightbox() {
|
||||||
|
var active = root.querySelector('.geep-map-img.is-active');
|
||||||
|
if (!active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!lightbox) {
|
||||||
|
lightbox = buildLightbox();
|
||||||
|
}
|
||||||
|
var img = lightbox.querySelector('.geep-lightbox-img');
|
||||||
|
var key = active.getAttribute('data-map');
|
||||||
|
var full = active.src; // src attribute holds the full-size file.
|
||||||
|
|
||||||
|
// Show instantly whatever variant the page already downloaded for
|
||||||
|
// this map (it is in cache), instead of leaving the previous map
|
||||||
|
// on screen while the big file downloads.
|
||||||
|
img.dataset.map = key;
|
||||||
|
img.src = active.currentSrc || full;
|
||||||
|
img.alt = current ? current.querySelector('.geep-toggle-title').textContent : '';
|
||||||
|
|
||||||
|
// Then upgrade to the full-size file in the background.
|
||||||
|
if (img.src !== full) {
|
||||||
|
var pre = new Image();
|
||||||
|
pre.onload = function () {
|
||||||
|
// Only swap if the lightbox still shows this same map.
|
||||||
|
if (lightbox.classList.contains('is-open') && img.dataset.map === key) {
|
||||||
|
img.src = full;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pre.src = full;
|
||||||
|
}
|
||||||
|
|
||||||
|
lightbox.classList.add('is-open');
|
||||||
|
document.documentElement.classList.add('geep-lightbox-noscroll');
|
||||||
|
document.addEventListener('keydown', onKeydown);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeLightbox() {
|
||||||
|
if (!lightbox) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lightbox.classList.remove('is-open');
|
||||||
|
document.documentElement.classList.remove('geep-lightbox-noscroll');
|
||||||
|
document.removeEventListener('keydown', onKeydown);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeydown(e) {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
closeLightbox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toast() {
|
||||||
|
var t = lightbox.querySelector('.geep-lightbox-toast');
|
||||||
|
t.hidden = false;
|
||||||
|
window.clearTimeout(toastTimer);
|
||||||
|
toastTimer = window.setTimeout(function () {
|
||||||
|
t.hidden = true;
|
||||||
|
}, 2200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function share() {
|
||||||
|
var url = shareUrl();
|
||||||
|
var title = current ? current.querySelector('.geep-toggle-title').textContent : document.title;
|
||||||
|
if (navigator.share) {
|
||||||
|
navigator.share({ title: title, url: url }).catch(function () {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
navigator.clipboard.writeText(url).then(toast, function () {
|
||||||
|
fallbackCopy(url);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fallbackCopy(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fallbackCopy(url) {
|
||||||
|
var ta = document.createElement('textarea');
|
||||||
|
ta.value = url;
|
||||||
|
ta.style.position = 'fixed';
|
||||||
|
ta.style.opacity = '0';
|
||||||
|
document.body.appendChild(ta);
|
||||||
|
ta.select();
|
||||||
|
try {
|
||||||
|
document.execCommand('copy');
|
||||||
|
toast();
|
||||||
|
} catch (e) {}
|
||||||
|
document.body.removeChild(ta);
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrap = root.querySelector('.geep-maps-image-wrap');
|
||||||
|
if (wrap) {
|
||||||
|
wrap.addEventListener('click', openLightbox);
|
||||||
|
wrap.addEventListener('keydown', function (e) {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
e.preventDefault();
|
||||||
|
openLightbox();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ready(fn) {
|
||||||
|
if (document.readyState !== 'loading') {
|
||||||
|
fn();
|
||||||
|
} else {
|
||||||
|
document.addEventListener('DOMContentLoaded', fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function () {
|
||||||
|
document.querySelectorAll('.geep-maps').forEach(init);
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -0,0 +1,325 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: FP Genocide Maps
|
||||||
|
* Plugin URI: https://freepress.coop
|
||||||
|
* Description: Manages the "Architecture of Genocide" maps shown on the home page. Each map is a post (title + description + image); the [geep_maps] shortcode renders the accordion + map image replicating the original Divi design, swapping the image when a toggle is opened.
|
||||||
|
* Version: 1.5.2
|
||||||
|
* Author: Freepress Coop
|
||||||
|
* Author URI: https://www.freepress.coop
|
||||||
|
* Requires PHP: 7.4
|
||||||
|
* License: GPL-2.0-or-later
|
||||||
|
* Text Domain: fp-genocide-maps
|
||||||
|
*
|
||||||
|
* @package FP_Genocide_Maps
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FPGM_CPT = 'geep_map';
|
||||||
|
const FPGM_VERSION = '1.5.2';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the Map custom post type (admin-only, not publicly queryable).
|
||||||
|
*/
|
||||||
|
function fpgm_register_cpt() {
|
||||||
|
register_post_type(
|
||||||
|
FPGM_CPT,
|
||||||
|
array(
|
||||||
|
'labels' => array(
|
||||||
|
'name' => __( 'Genocide Maps', 'fp-genocide-maps' ),
|
||||||
|
'singular_name' => __( 'Map', 'fp-genocide-maps' ),
|
||||||
|
'add_new' => __( 'Add New Map', 'fp-genocide-maps' ),
|
||||||
|
'add_new_item' => __( 'Add New Map', 'fp-genocide-maps' ),
|
||||||
|
'edit_item' => __( 'Edit Map', 'fp-genocide-maps' ),
|
||||||
|
'new_item' => __( 'New Map', 'fp-genocide-maps' ),
|
||||||
|
'view_item' => __( 'View Map', 'fp-genocide-maps' ),
|
||||||
|
'search_items' => __( 'Search Maps', 'fp-genocide-maps' ),
|
||||||
|
'not_found' => __( 'No maps found', 'fp-genocide-maps' ),
|
||||||
|
'featured_image' => __( 'Map image', 'fp-genocide-maps' ),
|
||||||
|
'set_featured_image' => __( 'Select map image', 'fp-genocide-maps' ),
|
||||||
|
),
|
||||||
|
'public' => false,
|
||||||
|
'show_ui' => true,
|
||||||
|
'show_in_menu' => true,
|
||||||
|
'show_in_rest' => false,
|
||||||
|
'exclude_from_search' => true,
|
||||||
|
'menu_icon' => 'dashicons-location-alt',
|
||||||
|
'menu_position' => 21,
|
||||||
|
'supports' => array( 'title', 'editor', 'thumbnail', 'page-attributes' ),
|
||||||
|
'hierarchical' => false,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
add_action( 'init', 'fpgm_register_cpt' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Front-end assets. The stylesheet replicates the exact Divi-generated design
|
||||||
|
* of the original section, so it is tiny and safe to load site-wide.
|
||||||
|
*/
|
||||||
|
function fpgm_enqueue_assets() {
|
||||||
|
wp_enqueue_style( 'fpgm-maps', plugins_url( 'assets/css/geep-maps.css', __FILE__ ), array(), FPGM_VERSION );
|
||||||
|
wp_enqueue_script( 'fpgm-maps', plugins_url( 'assets/js/geep-maps.js', __FILE__ ), array(), FPGM_VERSION, true );
|
||||||
|
}
|
||||||
|
add_action( 'wp_enqueue_scripts', 'fpgm_enqueue_assets' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [geep_maps] — image column + accordion column, mirroring the original
|
||||||
|
* "texto mapa" Divi row (columns 14/24 and 2/5, 2% gap).
|
||||||
|
*/
|
||||||
|
function fpgm_shortcode() {
|
||||||
|
$maps = get_posts(
|
||||||
|
array(
|
||||||
|
'post_type' => FPGM_CPT,
|
||||||
|
'posts_per_page' => -1,
|
||||||
|
'orderby' => array(
|
||||||
|
'menu_order' => 'ASC',
|
||||||
|
'date' => 'ASC',
|
||||||
|
),
|
||||||
|
'order' => 'ASC',
|
||||||
|
'suppress_filters' => false, // Let WPML return the current language.
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( empty( $maps ) ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map images are language-independent: when a translation has no image of
|
||||||
|
// its own, fall back to the original post's image (e.g. Arabic maps show
|
||||||
|
// the image assigned to the English one). Setting an image on the
|
||||||
|
// translation still overrides this.
|
||||||
|
$get_thumb = function ( $post_id ) {
|
||||||
|
$thumb = get_post_thumbnail_id( $post_id );
|
||||||
|
if ( ! $thumb ) {
|
||||||
|
$original = apply_filters( 'wpml_original_element_id', null, $post_id, 'post_' . FPGM_CPT );
|
||||||
|
if ( $original && (int) $original !== (int) $post_id ) {
|
||||||
|
$thumb = get_post_thumbnail_id( (int) $original );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $thumb;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The first map starts open, so its image (if it has one) is the one
|
||||||
|
// visible on load. Maps without an image simply leave the gap empty.
|
||||||
|
$first_thumb = $get_thumb( $maps[0]->ID );
|
||||||
|
$active_key = $first_thumb ? (string) $first_thumb : '';
|
||||||
|
|
||||||
|
// One image per map that has one. The visible size tops out around 660px
|
||||||
|
// (58% of the 90%-wide row), so tell the browser it never needs the
|
||||||
|
// full-size file: with `sizes` it picks the smallest sufficient variant.
|
||||||
|
$sizes = '(max-width: 767px) 100vw, 50vw';
|
||||||
|
|
||||||
|
$images_html = '';
|
||||||
|
$toggles_html = '';
|
||||||
|
$first = true;
|
||||||
|
$rendered_keys = array();
|
||||||
|
foreach ( $maps as $map ) {
|
||||||
|
$thumb_id = $get_thumb( $map->ID );
|
||||||
|
$map_key = '';
|
||||||
|
|
||||||
|
if ( $thumb_id ) {
|
||||||
|
$map_key = (string) $thumb_id;
|
||||||
|
if ( ! in_array( $map_key, $rendered_keys, true ) ) {
|
||||||
|
$rendered_keys[] = $map_key;
|
||||||
|
$images_html .= wp_get_attachment_image(
|
||||||
|
$thumb_id,
|
||||||
|
'full',
|
||||||
|
false,
|
||||||
|
array(
|
||||||
|
'class' => 'geep-map-img' . ( $map_key === $active_key ? ' is-active is-shown' : '' ),
|
||||||
|
'data-map' => $map_key,
|
||||||
|
'loading' => 'lazy',
|
||||||
|
'sizes' => $sizes,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$toggles_html .= sprintf(
|
||||||
|
'<div class="geep-toggle %s%s" data-map="%s" data-slug="%s">' .
|
||||||
|
'<h4 class="geep-toggle-title">%s</h4>' .
|
||||||
|
'<div class="geep-toggle-content">%s</div>' .
|
||||||
|
'</div>',
|
||||||
|
$first ? 'geep-toggle--open' : 'geep-toggle--close',
|
||||||
|
$first ? ' geep-toggle--first' : '',
|
||||||
|
esc_attr( $map_key ),
|
||||||
|
esc_attr( urldecode( $map->post_name ) ), // Readable form (Arabic slugs are stored percent-encoded).
|
||||||
|
esc_html( get_the_title( $map ) ),
|
||||||
|
wp_kses_post( wpautop( $map->post_content ) )
|
||||||
|
);
|
||||||
|
$first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI labels for the lightbox, in the language of the current page.
|
||||||
|
$is_ar = 'ar' === apply_filters( 'wpml_current_language', null );
|
||||||
|
$labels = array(
|
||||||
|
'share' => $is_ar ? 'مشاركة الخريطة' : 'Share map',
|
||||||
|
'copied' => $is_ar ? 'تم نسخ الرابط' : 'Link copied!',
|
||||||
|
'close' => $is_ar ? 'إغلاق' : 'Close',
|
||||||
|
'zoom' => $is_ar ? 'عرض الخريطة بحجم أكبر' : 'View map larger',
|
||||||
|
);
|
||||||
|
|
||||||
|
return '<div class="geep-maps" data-labels="' . esc_attr( wp_json_encode( $labels ) ) . '">' .
|
||||||
|
'<div class="geep-maps-col-map"><div class="geep-maps-image"><span class="geep-maps-image-wrap" role="button" tabindex="0" aria-label="' . esc_attr( $labels['zoom'] ) . '">' . $images_html . '</span></div></div>' .
|
||||||
|
'<div class="geep-maps-col-toggles">' . $toggles_html . '</div>' .
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
add_shortcode( 'geep_maps', 'fpgm_shortcode' );
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------
|
||||||
|
* Admin: list-table columns and default-image setting.
|
||||||
|
* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add image + order columns to the Maps list table.
|
||||||
|
*
|
||||||
|
* @param array $columns Existing columns.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function fpgm_admin_columns( $columns ) {
|
||||||
|
$new = array();
|
||||||
|
foreach ( $columns as $key => $label ) {
|
||||||
|
if ( 'title' === $key ) {
|
||||||
|
$new['fpgm_image'] = __( 'Map image', 'fp-genocide-maps' );
|
||||||
|
}
|
||||||
|
$new[ $key ] = $label;
|
||||||
|
}
|
||||||
|
$new['fpgm_order'] = __( 'Order', 'fp-genocide-maps' );
|
||||||
|
return $new;
|
||||||
|
}
|
||||||
|
add_filter( 'manage_' . FPGM_CPT . '_posts_columns', 'fpgm_admin_columns' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the custom columns.
|
||||||
|
*
|
||||||
|
* @param string $column Column key.
|
||||||
|
* @param int $post_id Post ID.
|
||||||
|
*/
|
||||||
|
function fpgm_admin_columns_content( $column, $post_id ) {
|
||||||
|
if ( 'fpgm_image' === $column ) {
|
||||||
|
if ( has_post_thumbnail( $post_id ) ) {
|
||||||
|
echo get_the_post_thumbnail( $post_id, array( 80, 60 ), array( 'style' => 'border-radius:4px;height:auto;' ) );
|
||||||
|
} else {
|
||||||
|
echo '<span style="color:#a00;">' . esc_html__( 'No image', 'fp-genocide-maps' ) . '</span>';
|
||||||
|
}
|
||||||
|
} elseif ( 'fpgm_order' === $column ) {
|
||||||
|
echo (int) get_post_field( 'menu_order', $post_id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_action( 'manage_' . FPGM_CPT . '_posts_custom_column', 'fpgm_admin_columns_content', 10, 2 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order the admin list by menu_order, like the front end.
|
||||||
|
*
|
||||||
|
* @param WP_Query $query Current query.
|
||||||
|
*/
|
||||||
|
function fpgm_admin_order( $query ) {
|
||||||
|
if ( is_admin() && $query->is_main_query() && FPGM_CPT === $query->get( 'post_type' ) && ! $query->get( 'orderby' ) ) {
|
||||||
|
$query->set( 'orderby', 'menu_order' );
|
||||||
|
$query->set( 'order', 'ASC' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_action( 'pre_get_posts', 'fpgm_admin_order' );
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------
|
||||||
|
* Activation: seed the current 8 maps (EN + AR, linked in WPML).
|
||||||
|
* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the initial maps from the content that used to live in the Divi
|
||||||
|
* toggles, once, on first activation.
|
||||||
|
*/
|
||||||
|
function fpgm_activate() {
|
||||||
|
fpgm_register_cpt();
|
||||||
|
|
||||||
|
// Register the CPT as translatable in WPML *before* seeding, otherwise
|
||||||
|
// wpml_set_element_language_details silently ignores the posts and the
|
||||||
|
// AR/EN pairs never get linked. Mode 2 = translatable, display the
|
||||||
|
// original when no translation exists (same as wpml-config.xml).
|
||||||
|
global $sitepress;
|
||||||
|
if ( $sitepress && method_exists( $sitepress, 'get_setting' ) ) {
|
||||||
|
$sync = (array) $sitepress->get_setting( 'custom_posts_sync_option', array() );
|
||||||
|
$sync[ FPGM_CPT ] = 2;
|
||||||
|
$sitepress->set_setting( 'custom_posts_sync_option', $sync, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing = get_posts(
|
||||||
|
array(
|
||||||
|
'post_type' => FPGM_CPT,
|
||||||
|
'posts_per_page' => 1,
|
||||||
|
'post_status' => 'any',
|
||||||
|
'suppress_filters' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if ( ! empty( $existing ) ) {
|
||||||
|
return; // Already seeded.
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = __DIR__ . '/includes/seed-data.json';
|
||||||
|
if ( ! file_exists( $file ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$data = json_decode( file_get_contents( $file ), true );
|
||||||
|
if ( empty( $data['en'] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$has_wpml = has_filter( 'wpml_element_trid' );
|
||||||
|
|
||||||
|
foreach ( $data['en'] as $i => $item ) {
|
||||||
|
$en_id = wp_insert_post(
|
||||||
|
array(
|
||||||
|
'post_type' => FPGM_CPT,
|
||||||
|
'post_status' => 'publish',
|
||||||
|
'post_title' => wp_strip_all_tags( $item['title'] ),
|
||||||
|
'post_content' => $item['content'],
|
||||||
|
'menu_order' => $i + 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if ( ! $en_id || is_wp_error( $en_id ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $has_wpml ) {
|
||||||
|
$trid = apply_filters( 'wpml_element_trid', null, $en_id, 'post_' . FPGM_CPT );
|
||||||
|
do_action(
|
||||||
|
'wpml_set_element_language_details',
|
||||||
|
array(
|
||||||
|
'element_id' => $en_id,
|
||||||
|
'element_type' => 'post_' . FPGM_CPT,
|
||||||
|
'trid' => $trid,
|
||||||
|
'language_code' => 'en',
|
||||||
|
'source_language_code' => null,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Arabic counterpart (same position in the list).
|
||||||
|
if ( ! empty( $data['ar'][ $i ]['title'] ) ) {
|
||||||
|
$ar_id = wp_insert_post(
|
||||||
|
array(
|
||||||
|
'post_type' => FPGM_CPT,
|
||||||
|
'post_status' => 'publish',
|
||||||
|
'post_title' => wp_strip_all_tags( $data['ar'][ $i ]['title'] ),
|
||||||
|
'post_content' => $data['ar'][ $i ]['content'],
|
||||||
|
'menu_order' => $i + 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if ( $ar_id && ! is_wp_error( $ar_id ) ) {
|
||||||
|
do_action(
|
||||||
|
'wpml_set_element_language_details',
|
||||||
|
array(
|
||||||
|
'element_id' => $ar_id,
|
||||||
|
'element_type' => 'post_' . FPGM_CPT,
|
||||||
|
'trid' => $trid,
|
||||||
|
'language_code' => 'ar',
|
||||||
|
'source_language_code' => 'en',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
register_activation_hook( __FILE__, 'fpgm_activate' );
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "Offshore Gas Infrastructure in the Eastern Mediterranean Sea",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Gas is extracted by the Israeli colonial regime in offshore gas platforms in the Eastern Mediterranean Sea. Some of these are located inside of the declared maritime waters of Palestine and Lebanon. From these gas fields, gas is transported to land-based facilities, where it is liquified and transported on ships to ports in Europe. It is estimated that in the coming years, gas infrastructure will expand, further curtailing Palestinian rights and their energy sovereignty. </span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Illegal Gas Imports into Europe",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Ships transport gas, including stolen Palestinian and Lebanese Israeli gas, via Egypt to LNG terminals across Europe, traded under the EU-Egypt-Israel Memorandum of Understanding. The pipeline connecting the gas fields with Egypt crosses Palestinian EEZ without Palestinian consent or financial revenues, making the whole infrastructure and therefore exports illegal. Framing this gas as 'decarbonisation' hides its bloody origins and Europe's growing reliance on companies greenwashing the genocide.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Petroleum Supply Chain from Brazil via the Refining Facility in Sardinia",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Crude oil from off-shore Brazilian oil fields is extracted on FPSO (Floating Production, Storage, and Offloading) units and shipped to a refinery in Sardinia (Leg 1). Here crude oil is distilled into refined petroleum products, including military-grade aircraft fuel and shipped to Israel (Leg 2). The SARAS refinery in Sardinia is operated by Vitol, the world’s largest commodity trader with a dark history of facilitating the plunder of oil resources.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Coal Supply Route from South Africa",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Coal is mined in the Mpumalanga province, as well as parts of KwaZulu-Natal and Limpopo mines in the interior of South Africa. It is transported to the coast via rail freight corridors to the Richard’s Bay Coal Terminal. From here, bulk carrier ships transport the coal to the Israeli port of Khodeira (Hadera) via the Mediterranean Sea. Since the coal embargo in Colombia, South Africa has become the biggest supplier of coal to the Israeli colonial regime.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Military Fuel Supply Route from the United States",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">The Valero refinery in Houston has been contracted by the US government to supply aircraft-grade fuel (JP-8) and diesel for military vehicles to the Israeli Occupation Forces. Paid for by American tax-payers, these fuels are shipped on tankers to the port of Asqalan (Ashkelon) in Israel, enabling the bombardment and destruction of Gaza. Valero has also emerged as one of the largest refiners of Venezuelan crude oil since the kidnapping of president Maduro.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "The Baku-Tbilisi-Ceyhan Crude Oil Pipeline",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Azerbaijani crude oil is extracted from the Caspian Sea from where it is sent to the Sangachal terminal near Baku. Here the oil flows through the Baku-Tbilisi-Ceyhan pipeline which runs for 1099 miles across Azerbaijan, Georgia and Türkiye, culminating at the port of Ceyhan. Oil tankers make regular runs from the port of Ceyhan to the port of Ashkelon. During this iteration of the genocide, the BTC pipeline is the the largest route of crude oil supplies to the Israeli colonial regime.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Crude Oil Supply Route from Türkiye",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">From the port of Ceyhan in Türkiye, oil tankers transport crude oil to the port of Asqalan (Ashkelon) in Israel. Despite an embargo on trade with the Israeli colonial regime being announced by the Turkish government, Greek-owned shipping vessels have deliberately operated in the ‘dark’ as a way to bypass the embargo and keep fueling the genocide.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Coal Supply Route from Colombia",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Colombia used to be the largest exporter of coal to Israel, until popular pressures from below by indigenous communities and workers brought into place a coal embargo in 2024. However, with the change of government in 2026, it is expected that the coal trade from Colombia to Israel will resume with ships leaving key coal terminals to deliver cargo via the Mediterranean Sea.</span></p>"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ar": [
|
||||||
|
{
|
||||||
|
"title": "البنية التحتية للغاز البحري في شرق البحر الأبيض المتوسط",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">يقوم النظام الاستعماري الإسرائيلي باستخراج الغاز من منصات الغاز البحرية في شرق البحر الأبيض المتوسط. وتقع بعض هذه المنصات داخل المياه الإقليمية المعلنة لفلسطين ولبنان. ومن هذه الحقول، يُنقل الغاز إلى منشآت برية، حيث يتم تسييله ونقله على متن سفن إلى موانئ في أوروبا. وتشير التقديرات إلى أن البنية التحتية للغاز ستتوسع في السنوات المقبلة، مما سيؤدي إلى مزيد من الانتقاص من حقوق الفلسطينيين وسيادتهم في مجال الطاقة. </span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "الواردات غير القانونية للغاز إلى أوروبا",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">تنقل السفن الغاز، بما في ذلك الغاز الفلسطيني واللبناني المسروق من إسرائيل، عبر مصر إلى محطات الغاز الطبيعي المسال في أنحاء أوروبا، ويتم تداوله بموجب مذكرة التفاهم بين الاتحاد الأوروبي ومصر وإسرائيل. ويعبر خط الأنابيب الذي يربط حقول الغاز بمصر المنطقة الاقتصادية الخالصة الفلسطينية دون موافقة فلسطينية أو عائدات مالية، مما يجعل البنية التحتية بأكملها، وبالتالي الصادرات، غير قانونية. وتصوير هذا الغاز على أنه جزء من «التحول إلى الاقتصاد الخالي من الكربون» يخفي أصوله الدموية واعتماد أوروبا المتزايد على الشركات التي تقوم بـ«التبييض الأخضر» للإبادة الجماعية. </span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "سلسلة توريد النفط من البرازيل عبر منشأة التكرير في سردينيا",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">يُستخرج النفط الخام من حقول النفط البحرية البرازيلية على متن وحدات FPSO (وحدات الإنتاج والتخزين والتفريغ العائمة) ويُشحن إلى مصفاة في سردينيا (المرحلة الأولى). وهناك، يُقطر النفط الخام ليصبح منتجات بترولية مكررة، بما في ذلك وقود الطائرات من النوع العسكري، ثم يُشحن إلى إسرائيل (المرحلة الثانية). تدير شركة «فيتول» مصفاة «ساراس» في سردينيا، وهي أكبر شركة لتجارة السلع الأساسية في العالم ولها تاريخ مظلم في تسهيل نهب الموارد النفطية. </span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "طريق توريد الفحم من جنوب أفريقيا",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">يُستخرج الفحم من مقاطعة مبومالانجا، وكذلك من أجزاء من مناجم كوازولو-ناتال وليمبوبو في المناطق الداخلية لجنوب أفريقيا. ويتم نقله إلى الساحل عبر ممرات الشحن بالسكك الحديدية إلى محطة ريتشاردز باي للفحم. ومن هناك، تنقل سفن الشحن السائبة الفحم إلى ميناء خوديرا (هديرا) الإسرائيلي عبر البحر الأبيض المتوسط. ومنذ فرض الحظر على استيراد الفحم من كولومبيا، أصبحت جنوب أفريقيا أكبر مورد للفحم للنظام الاستعماري الإسرائيلي. </span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "طريق إمداد الوقود العسكري من الولايات المتحدة",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">تعاقدت الحكومة الأمريكية مع مصفاة «فاليرو» في هيوستن لتزويد قوات الاحتلال الإسرائيلية بالوقود المخصص للطائرات (JP-8) والديزل المخصص للمركبات العسكرية. ويتم شحن هذه الوقودات، التي يدفع ثمنها دافعو الضرائب الأمريكيون، على متن ناقلات إلى ميناء أسقلان (عسقلان) في إسرائيل، مما يتيح قصف غزة وتدميرها. كما برزت شركة «فاليرو» كواحدة من أكبر شركات تكرير النفط الخام الفنزويلي منذ اختطاف الرئيس مادورو. </span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "The Baku-Tbilisi-Ceyhan Crude Oil Pipeline",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Azerbaijani crude oil is extracted from the Caspian Sea from where it is sent to the Sangachal terminal near Baku. Here the oil flows through the Baku-Tbilisi-Ceyhan pipeline which runs for 1099 miles across Azerbaijan, Georgia and Türkiye, culminating at the port of Ceyhan. Oil tankers make regular runs from the port of Ceyhan to the port of Ashkelon. During this iteration of the genocide, the BTC pipeline is the the largest route of crude oil supplies to the Israeli colonial regime.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Crude Oil Supply Route from Türkiye",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">From the port of Ceyhan in Türkiye, oil tankers transport crude oil to the port of Asqalan (Ashkelon) in Israel. Despite an embargo on trade with the Israeli colonial regime being announced by the Turkish government, Greek-owned shipping vessels have deliberately operated in the ‘dark’ as a way to bypass the embargo and keep fueling the genocide.</span></p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Coal Supply Route from Colombia",
|
||||||
|
"content": "<p><span style=\"font-weight: 400;\">Colombia used to be the largest exporter of coal to Israel, until popular pressures from below by indigenous communities and workers brought into place a coal embargo in 2024. However, with the change of government in 2026, it is expected that the coal trade from Colombia to Israel will resume with ships leaving key coal terminals to deliver cargo via the Mediterranean Sea. </span></p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<wpml-config>
|
||||||
|
<custom-types>
|
||||||
|
<custom-type translate="1" display-as-translated="1">geep_map</custom-type>
|
||||||
|
</custom-types>
|
||||||
|
</wpml-config>
|
||||||
Reference in New Issue
Block a user