feat: complete CDN elimination + SVG icon build pipeline
CDN cleanup:
- entry.html.twig: remove PhotoSwipe CDN + duplicate JS (main.js handles it)
- dailies.html.twig: remove PhotoSwipe CDN + duplicate JS
- home.html.twig: remove PhotoSwipe CDN + MapLibre CDN + maplibre-utils.js
script tags; add {% block map_assets %} to register map bundle
SVG build pipeline:
- Add lucide-static devDependency; gen-weather-icons.js reads icon SVGs
from node_modules and emits templates/partials/weather-icons.html.twig
- package.json build script now runs gen-weather-icons.js before esbuild
- entry-journal.html.twig includes generated partial instead of hardcoded map
- Rebuild: main.js 83.7kb, map.js 860.7kb, all fonts; zero CDN requests remain
This commit is contained in:
Generated
+9
-1
@@ -13,7 +13,8 @@
|
||||
"scrollama": "^3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.21"
|
||||
"esbuild": "^0.21",
|
||||
"lucide-static": "latest"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
@@ -747,6 +748,13 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lucide-static": {
|
||||
"version": "1.21.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-static/-/lucide-static-1.21.0.tgz",
|
||||
"integrity": "sha512-6248z2/4sEyKkYAPPUYxOPiB2RCfMmLdMHuoOhsTFnoD40ixAoHmTVhOPux8ADa1NTBmzpEKF7WNePm+Ms503Q==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/maplibre-gl": {
|
||||
"version": "4.7.1",
|
||||
"resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.7.1.tgz",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "esbuild js/src/main.js --bundle --minify --format=iife --outfile=js/main.js --loader:.woff2=file --loader:.woff=file --asset-names=../fonts/[name] && esbuild js/src/map.js --bundle --minify --format=iife --outfile=js/map.js && mkdir -p css-compiled fonts && { mv js/main.css css-compiled/main.css 2>/dev/null || true; } && { mv js/map.css css-compiled/map.css 2>/dev/null || true; }"
|
||||
"build": "node scripts/gen-weather-icons.js && esbuild js/src/main.js --bundle --minify --format=iife --outfile=js/main.js --loader:.woff2=file --loader:.woff=file --asset-names=../fonts/[name] && esbuild js/src/map.js --bundle --minify --format=iife --outfile=js/map.js && mkdir -p css-compiled fonts && { mv js/main.css css-compiled/main.css 2>/dev/null || true; } && { mv js/map.css css-compiled/map.css 2>/dev/null || true; }"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource-variable/dm-sans": "latest",
|
||||
@@ -12,6 +12,7 @@
|
||||
"scrollama": "^3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.21"
|
||||
"esbuild": "^0.21",
|
||||
"lucide-static": "latest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const iconMap = {
|
||||
'sunny': 'sun',
|
||||
'partly cloudy': 'cloud-sun',
|
||||
'cloudy': 'cloud',
|
||||
'foggy': 'cloud-fog',
|
||||
'drizzle': 'cloud-drizzle',
|
||||
'rain': 'cloud-rain',
|
||||
'snow': 'cloud-snow',
|
||||
'thunderstorm': 'cloud-lightning'
|
||||
};
|
||||
|
||||
const wrapAttrs = 'width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"';
|
||||
|
||||
function buildSvg(iconName) {
|
||||
const src = path.resolve(__dirname, '..', 'node_modules', 'lucide-static', 'icons', iconName + '.svg');
|
||||
const raw = fs.readFileSync(src, 'utf8');
|
||||
const inner = raw
|
||||
.replace(/^[\s\S]*?<svg[^>]*>/, '')
|
||||
.replace(/<\/svg>[\s\S]*$/, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
return `<svg ${wrapAttrs}>${inner}</svg>`;
|
||||
}
|
||||
|
||||
const entries = Object.entries(iconMap);
|
||||
const lines = entries.map(([condition, iconName], i) => {
|
||||
const svg = buildSvg(iconName).replace(/'/g, "\\'");
|
||||
const pad = ' '.repeat(Math.max(0, 16 - condition.length));
|
||||
const comma = i < entries.length - 1 ? ',' : '';
|
||||
return ` '${condition}':${pad}'${svg}'${comma}`;
|
||||
});
|
||||
|
||||
const twig = [
|
||||
'{# Auto-generated by scripts/gen-weather-icons.js — do not edit directly #}',
|
||||
'{% set weather_icons = {',
|
||||
...lines,
|
||||
'} %}'
|
||||
].join('\n') + '\n';
|
||||
|
||||
const dest = path.resolve(__dirname, '..', 'templates', 'partials', 'weather-icons.html.twig');
|
||||
fs.writeFileSync(dest, twig);
|
||||
console.log('Generated ' + path.relative(path.resolve(__dirname, '..'), dest));
|
||||
@@ -6,7 +6,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.css">
|
||||
{% set journal_entries = page.collection() %}
|
||||
{% set stories_page = grav.pages.find(page.parent().route ~ '/stories') %}
|
||||
{% set story_entries = stories_page ? stories_page.children.published() : [] %}
|
||||
@@ -68,67 +67,4 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import PhotoSwipeLightbox from 'https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe-lightbox.esm.min.js';
|
||||
|
||||
const lightbox = new PhotoSwipeLightbox({
|
||||
gallery: '.pswp-gallery',
|
||||
children: 'a.journal-photo-slide',
|
||||
pswpModule: () => import('https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.esm.min.js')
|
||||
});
|
||||
lightbox.on('afterOpen', function () {
|
||||
var pswp = lightbox.pswp;
|
||||
var keyDir = 0;
|
||||
var clearTimer = null;
|
||||
function onKey(e) {
|
||||
if (e.key === 'ArrowRight') keyDir = 1;
|
||||
else if (e.key === 'ArrowLeft') keyDir = -1;
|
||||
else keyDir = 0;
|
||||
}
|
||||
document.addEventListener('keydown', onKey, true);
|
||||
pswp.on('change', function () {
|
||||
if (!keyDir) return;
|
||||
var dir = keyDir;
|
||||
keyDir = 0;
|
||||
var el = pswp.currSlide && pswp.currSlide.container;
|
||||
if (!el) return;
|
||||
el.classList.remove('pswp-key-from-left', 'pswp-key-from-right');
|
||||
el.offsetWidth;
|
||||
el.classList.add(dir > 0 ? 'pswp-key-from-right' : 'pswp-key-from-left');
|
||||
clearTimeout(clearTimer);
|
||||
clearTimer = setTimeout(function () { el.classList.remove('pswp-key-from-left', 'pswp-key-from-right'); }, 400);
|
||||
});
|
||||
pswp.on('close', function () {
|
||||
document.removeEventListener('keydown', onKey, true);
|
||||
clearTimeout(clearTimer);
|
||||
});
|
||||
});
|
||||
lightbox.init();
|
||||
|
||||
/* Per-strip: dot sync + expand button → tap the visible slide to trigger pswp */
|
||||
document.querySelectorAll('.journal-photo-wrap').forEach(function (wrap) {
|
||||
var strip = wrap.querySelector('.journal-photo-strip');
|
||||
var slides = Array.from(strip.querySelectorAll('a.journal-photo-slide'));
|
||||
var expandBtn = wrap.querySelector('.journal-photo-expand');
|
||||
var article = wrap.closest('article');
|
||||
var dots = article ? Array.from(article.querySelectorAll('.journal-photo-dot')) : [];
|
||||
var visibleIdx = 0;
|
||||
|
||||
var io = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (e) {
|
||||
if (!e.isIntersecting) return;
|
||||
visibleIdx = slides.indexOf(e.target);
|
||||
dots.forEach(function (d) { d.classList.remove('is-active'); });
|
||||
if (dots[visibleIdx]) dots[visibleIdx].classList.add('is-active');
|
||||
});
|
||||
}, { root: strip, threshold: 0.5 });
|
||||
slides.forEach(function (s) { io.observe(s); });
|
||||
|
||||
if (expandBtn && slides.length) {
|
||||
expandBtn.addEventListener('click', function () {
|
||||
slides[visibleIdx].dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,129 +1,12 @@
|
||||
{% extends 'default.html.twig' %}
|
||||
{% extends 'partials/base.html.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{% set weather_icons = {
|
||||
'Sunny': '☀️', 'Partly cloudy': '⛅', 'Cloudy': '☁️',
|
||||
'Foggy': '🌫️', 'Drizzle': '🌦️', 'Rain': '🌧️',
|
||||
'Snow': '❄️', 'Thunderstorm': '⛈️'
|
||||
} %}
|
||||
|
||||
{% set hero = null %}
|
||||
{% if page.header.hero_image and page.media[page.header.hero_image] is defined %}
|
||||
{% set hero = page.media[page.header.hero_image] %}
|
||||
{% elseif page.media.images|length > 0 %}
|
||||
{% set hero = page.media.images|first %}
|
||||
{% endif %}
|
||||
|
||||
<a class="back-pill entry-back-fixed" href="{{ page.parent().url }}" onclick="if(history.length > 1){ history.back(); return false; }">← Back</a>
|
||||
|
||||
<article class="entry">
|
||||
{% if hero %}
|
||||
<div class="entry-hero">
|
||||
<img src="{{ hero.cropResize(1440, 720).url }}" alt="{{ page.title }}" loading="eager">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% set entry = page %}
|
||||
{% include 'partials/entry-journal.html.twig' %}
|
||||
|
||||
<header class="entry-header">
|
||||
<div class="entry-header-meta">
|
||||
<time class="entry-date" datetime="{{ page.date|date('Y-m-d') }}">
|
||||
{{ page.date|date('l, d F Y') }}
|
||||
</time>
|
||||
{% if page.header.location_city or page.header.location_country %}
|
||||
<p class="entry-location">
|
||||
{%- set _loc = [] -%}
|
||||
{%- if page.header.location_city -%}{%- set _loc = _loc|merge([page.header.location_city]) -%}{%- endif -%}
|
||||
{%- if page.header.location_country -%}{%- set _loc = _loc|merge([page.header.location_country]) -%}{%- endif -%}
|
||||
📍 {{ _loc|join(', ') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if page.header.weather_desc or page.header.weather_temp_c %}
|
||||
<p class="entry-weather">
|
||||
{% if page.header.weather_desc %}
|
||||
{{ weather_icons[page.header.weather_desc] ?? '🌡️' }} {{ page.header.weather_desc }}
|
||||
{% endif %}
|
||||
{% if page.header.weather_temp_c %}
|
||||
· {{ page.header.weather_temp_c|round }}°C
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<h1 class="entry-title">{{ page.title }}</h1>
|
||||
<div class="entry-title-rule"></div>
|
||||
</header>
|
||||
|
||||
<div class="entry-body">
|
||||
{{ page.content|raw }}
|
||||
</div>
|
||||
|
||||
{% set images = page.media.images %}
|
||||
{% if images|length > 0 %}
|
||||
<div class="entry-gallery" id="entry-gallery">
|
||||
{% for image in images %}
|
||||
<button class="gallery-thumb" data-full="{{ image.url }}" data-alt="{{ image.filename }}" aria-label="View {{ image.filename }}">
|
||||
<img src="{{ image.cropResize(300, 300).url }}" alt="{{ image.filename }}" loading="lazy">
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="lightbox" id="lightbox" role="dialog" aria-modal="true" aria-label="Photo viewer" hidden>
|
||||
<button class="lightbox-close" id="lb-close" aria-label="Close">✕</button>
|
||||
<button class="lightbox-prev" id="lb-prev" aria-label="Previous">‹</button>
|
||||
<img class="lightbox-img" id="lb-img" src="" alt="">
|
||||
<button class="lightbox-next" id="lb-next" aria-label="Next">›</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var gallery = document.getElementById('entry-gallery');
|
||||
var lightbox = document.getElementById('lightbox');
|
||||
var lbImg = document.getElementById('lb-img');
|
||||
var thumbs = Array.from(gallery.querySelectorAll('.gallery-thumb'));
|
||||
var current = 0;
|
||||
|
||||
function open(index) {
|
||||
current = index;
|
||||
var btn = thumbs[index];
|
||||
lbImg.src = btn.dataset.full;
|
||||
lbImg.alt = btn.dataset.alt;
|
||||
lightbox.hidden = false;
|
||||
document.body.style.overflow = 'hidden';
|
||||
document.getElementById('lb-close').focus();
|
||||
}
|
||||
|
||||
function close() {
|
||||
lightbox.hidden = true;
|
||||
document.body.style.overflow = '';
|
||||
thumbs[current].focus();
|
||||
}
|
||||
|
||||
function prev() { open((current - 1 + thumbs.length) % thumbs.length); }
|
||||
function next() { open((current + 1) % thumbs.length); }
|
||||
|
||||
thumbs.forEach(function(btn, i) {
|
||||
btn.addEventListener('click', function() { open(i); });
|
||||
});
|
||||
|
||||
document.getElementById('lb-close').addEventListener('click', close);
|
||||
document.getElementById('lb-prev').addEventListener('click', prev);
|
||||
document.getElementById('lb-next').addEventListener('click', next);
|
||||
|
||||
lightbox.addEventListener('click', function(e) {
|
||||
if (e.target === lightbox) close();
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (lightbox.hidden) return;
|
||||
if (e.key === 'Escape') close();
|
||||
if (e.key === 'ArrowLeft') prev();
|
||||
if (e.key === 'ArrowRight') next();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<footer class="entry-footer">
|
||||
<a class="back-pill" href="{{ page.parent().url }}" onclick="if(history.length > 1){ history.back(); return false; }">← Back</a>
|
||||
</footer>
|
||||
</article>
|
||||
<footer class="entry-footer">
|
||||
<a class="back-pill" href="{{ page.parent().url }}" onclick="if(history.length > 1){ history.back(); return false; }">← Back</a>
|
||||
</footer>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
{% extends 'partials/base.html.twig' %}
|
||||
|
||||
{% block map_assets %}
|
||||
{% do assets.addCss('theme://css-compiled/map.css') %}
|
||||
{% do assets.addJs('theme://js/map.js', {group: 'bottom'}) %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.css">
|
||||
{% set trip_route = config.site.active_trip %}
|
||||
{% set trip = grav.pages.find(trip_route) %}
|
||||
|
||||
@@ -80,12 +84,6 @@
|
||||
</div>
|
||||
|
||||
{% if map_entries|length > 0 %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.js"></script>
|
||||
{% if home_gpx_urls|length > 0 %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/@mapbox/togeojson@0.16.2/togeojson.min.js"></script>
|
||||
{% endif %}
|
||||
<script src="{{ url('theme://js/maplibre-utils.js') }}"></script>
|
||||
<script>
|
||||
var HOME_ENTRIES = {{ map_entries|json_encode|raw }};
|
||||
var HOME_GPX_URLS = {{ home_gpx_urls|json_encode|raw }};
|
||||
@@ -138,68 +136,6 @@ homeMap.on('load', function () {
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<script type="module">
|
||||
import PhotoSwipeLightbox from 'https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe-lightbox.esm.min.js';
|
||||
const lightbox = new PhotoSwipeLightbox({
|
||||
gallery: '.pswp-gallery',
|
||||
children: 'a.journal-photo-slide',
|
||||
pswpModule: () => import('https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.esm.min.js')
|
||||
});
|
||||
lightbox.on('afterOpen', function () {
|
||||
var pswp = lightbox.pswp;
|
||||
var keyDir = 0;
|
||||
var clearTimer = null;
|
||||
function onKey(e) {
|
||||
if (e.key === 'ArrowRight') keyDir = 1;
|
||||
else if (e.key === 'ArrowLeft') keyDir = -1;
|
||||
else keyDir = 0;
|
||||
}
|
||||
document.addEventListener('keydown', onKey, true);
|
||||
pswp.on('change', function () {
|
||||
if (!keyDir) return;
|
||||
var dir = keyDir;
|
||||
keyDir = 0;
|
||||
var el = pswp.currSlide && pswp.currSlide.container;
|
||||
if (!el) return;
|
||||
el.classList.remove('pswp-key-from-left', 'pswp-key-from-right');
|
||||
el.offsetWidth;
|
||||
el.classList.add(dir > 0 ? 'pswp-key-from-right' : 'pswp-key-from-left');
|
||||
clearTimeout(clearTimer);
|
||||
clearTimer = setTimeout(function () { el.classList.remove('pswp-key-from-left', 'pswp-key-from-right'); }, 400);
|
||||
});
|
||||
pswp.on('close', function () {
|
||||
document.removeEventListener('keydown', onKey, true);
|
||||
clearTimeout(clearTimer);
|
||||
});
|
||||
});
|
||||
lightbox.init();
|
||||
|
||||
document.querySelectorAll('.journal-photo-wrap').forEach(function (wrap) {
|
||||
var strip = wrap.querySelector('.journal-photo-strip');
|
||||
var slides = Array.from(strip.querySelectorAll('a.journal-photo-slide'));
|
||||
var expandBtn = wrap.querySelector('.journal-photo-expand');
|
||||
var article = wrap.closest('article');
|
||||
var dots = article ? Array.from(article.querySelectorAll('.journal-photo-dot')) : [];
|
||||
var visibleIdx = 0;
|
||||
|
||||
var io = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (e) {
|
||||
if (!e.isIntersecting) return;
|
||||
visibleIdx = slides.indexOf(e.target);
|
||||
dots.forEach(function (d) { d.classList.remove('is-active'); });
|
||||
if (dots[visibleIdx]) dots[visibleIdx].classList.add('is-active');
|
||||
});
|
||||
}, { root: strip, threshold: 0.5 });
|
||||
slides.forEach(function (s) { io.observe(s); });
|
||||
|
||||
if (expandBtn && slides.length) {
|
||||
expandBtn.addEventListener('click', function () {
|
||||
slides[visibleIdx].dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{% else %}
|
||||
{# ══════════════════════════════════════════════════════ BETWEEN-TRIPS MODE #}
|
||||
|
||||
@@ -305,9 +241,6 @@ document.querySelectorAll('.journal-photo-wrap').forEach(function (wrap) {
|
||||
</div>
|
||||
|
||||
{% if highlights_map_entries|length > 0 %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.js"></script>
|
||||
<script src="{{ url('theme://js/maplibre-utils.js') }}"></script>
|
||||
<script>
|
||||
var HIGHLIGHTS_ENTRIES = {{ highlights_map_entries|json_encode|raw }};
|
||||
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
{% set weather_icons = {
|
||||
'sunny': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>',
|
||||
'partly cloudy': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="M20 12h2"/><path d="m19.07 4.93-1.41 1.41"/><path d="M15.947 12.65a4 4 0 0 0-5.925-4.128"/><path d="M13 22H7a5 5 0 1 1 4.9-6H13a3 3 0 0 1 0 6Z"/></svg>',
|
||||
'cloudy': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"/></svg>',
|
||||
'foggy': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="M16 17H7"/><path d="M17 21H9"/></svg>',
|
||||
'drizzle': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="M8 19v1"/><path d="M8 14v1"/><path d="M16 19v1"/><path d="M16 14v1"/><path d="M12 21v1"/><path d="M12 16v1"/></svg>',
|
||||
'rain': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="M16 14v6"/><path d="M8 14v6"/><path d="M12 16v6"/></svg>',
|
||||
'snow': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="M8 15h.01"/><path d="M8 19h.01"/><path d="M12 17h.01"/><path d="M12 21h.01"/><path d="M16 15h.01"/><path d="M16 19h.01"/></svg>',
|
||||
'thunderstorm': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 16.326A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 .5 8.973"/><path d="m13 12-3 5h4l-3 5"/></svg>'
|
||||
} %}
|
||||
{% include 'partials/weather-icons.html.twig' %}
|
||||
<article class="journal-post" id="entry-{{ entry.slug }}" data-type="journal" data-lat="{{ entry.header.lat }}" data-lng="{{ entry.header.lng }}">
|
||||
<header class="journal-post-header">
|
||||
<h2 class="journal-post-title">{{ entry.title }}</h2>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{# Auto-generated by scripts/gen-weather-icons.js — do not edit directly #}
|
||||
{% set weather_icons = {
|
||||
'sunny': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4" /> <path d="M12 2v2" /> <path d="M12 20v2" /> <path d="m4.93 4.93 1.41 1.41" /> <path d="m17.66 17.66 1.41 1.41" /> <path d="M2 12h2" /> <path d="M20 12h2" /> <path d="m6.34 17.66-1.41 1.41" /> <path d="m19.07 4.93-1.41 1.41" /></svg>',
|
||||
'partly cloudy': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2v2" /> <path d="m4.93 4.93 1.41 1.41" /> <path d="M20 12h2" /> <path d="m19.07 4.93-1.41 1.41" /> <path d="M15.947 12.65a4 4 0 0 0-5.925-4.128" /> <path d="M13 22H7a5 5 0 1 1 4.9-6H13a3 3 0 0 1 0 6Z" /></svg>',
|
||||
'cloudy': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" /></svg>',
|
||||
'foggy': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242" /> <path d="M16 17H7" /> <path d="M17 21H9" /></svg>',
|
||||
'drizzle': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242" /> <path d="M8 19v1" /> <path d="M8 14v1" /> <path d="M16 19v1" /> <path d="M16 14v1" /> <path d="M12 21v1" /> <path d="M12 16v1" /></svg>',
|
||||
'rain': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242" /> <path d="M16 14v6" /> <path d="M8 14v6" /> <path d="M12 16v6" /></svg>',
|
||||
'snow': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242" /> <path d="M8 15h.01" /> <path d="M8 19h.01" /> <path d="M12 17h.01" /> <path d="M12 21h.01" /> <path d="M16 15h.01" /> <path d="M16 19h.01" /></svg>',
|
||||
'thunderstorm': '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 16.326A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 .5 8.973" /> <path d="m13 12-3 5h4l-3 5" /></svg>'
|
||||
} %}
|
||||
Reference in New Issue
Block a user