Show waypoint photos from newer p4n2gpx exports

A newer p4n2gpx run (Ruby rewrite, ~/test/mapping/p4n2gpx) started
emitting one plain GPX <link href> per park4night listing photo,
which this app parsed but never displayed. Gpx.waypoint_photos
collects them into a photos property; the waypoint popup renders them
as a row of thumbnails above the description, each opening full-size
in a new tab. Absent on older exports and plain GPS waypoints, so the
row just doesn't render for those.
This commit is contained in:
randy committed 2026-09-07 22:38:22 +02:00
1 parent dd272ffb8a
commit dd0ad6d845
6 files changed
+72 -2

No files matched your search

+15
View File
@@ -582,6 +582,21 @@ html, body {
line-height: 1.4;
}
.gpx-popup__photos {
display: flex;
gap: 4px;
margin: 4px 0;
overflow-x: auto;
}
.gpx-popup__photo {
width: 64px;
height: 64px;
flex-shrink: 0;
object-fit: cover;
border-radius: 4px;
}
.gpx-popup__meta {
margin-top: 8px;
padding-top: 6px;
+18 -1
View File
@@ -754,10 +754,11 @@ function gpxFileUrl(path) {
// properties come straight from an uploaded GPX file — untrusted input —
// so every value is escaped before landing in the popup's HTML.
function popupHtml({ name, description, time, category }) {
function popupHtml({ name, description, time, category, photos }) {
const parts = [];
if (name) parts.push(`<strong>${escapeHtml(name)}</strong>`);
if (category) parts.push(`<p class="gpx-popup__category">${escapeHtml(category)}</p>`);
if (photos?.length > 0) parts.push(formatPhotos(photos));
if (description) parts.push(formatDescription(description));
if (time) {
const parsed = new Date(time);
@@ -808,6 +809,22 @@ function escapeHtml(text) {
const DESCRIPTION_META_LINE = /^(Rating|Services|Activities):\s*(.+)$/i;
const DESCRIPTION_LINK_LINE = /^https?:\/\/\S+$/;
// <link> photo URLs (a newer p4n2gpx export adds one per park4night listing
// photo — see lib/maptool/gpx.rb's waypoint_photos) as a row of thumbnails,
// each opening the full-size image in a new tab. Untrusted URLs from an
// uploaded file, same as everywhere else in this popup — escaped for use as
// both an href and an img src.
function formatPhotos(photos) {
const thumbs = photos
.map((url) => escapeHtml(url))
.map(
(url) =>
`<a href="${url}" target="_blank" rel="noopener noreferrer"><img class="gpx-popup__photo" src="${url}" loading="lazy" alt=""></a>`,
)
.join("");
return `<div class="gpx-popup__photos">${thumbs}</div>`;
}
function formatDescription(description) {
const body = [];
const meta = [];