From e8a2d27bc298acc38e57e491eee0a1d2abeca178 Mon Sep 17 00:00:00 2001 From: Gwendolyn Date: Sun, 29 Dec 2024 18:35:55 +0100 Subject: [PATCH] oops xss --- src/c3nav/site/static/site/js/c3nav.js | 46 ++++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/c3nav/site/static/site/js/c3nav.js b/src/c3nav/site/static/site/js/c3nav.js index 4e4a0ce3..18685b91 100644 --- a/src/c3nav/site/static/site/js/c3nav.js +++ b/src/c3nav/site/static/site/js/c3nav.js @@ -50,8 +50,16 @@ function makeClusterIconCreate(color) { return function(cluster) { const childCount = cluster.getChildCount(); + // TODO: use color based on children? + + const div = document.createElement('div'); + div.style.setProperty('--cluster-marker-color', color); + const span = document.createElement('span'); + span.innerText = childCount; + div.append(span); + return new L.DivIcon({ - html: `
${childCount}
`, + html: div, className: 'marker-cluster', iconSize: new L.Point(30, 30) }); @@ -3027,10 +3035,12 @@ QuestsControl = ExpandingControl.extend({ for (const quest of quests) { L.geoJson(quest.point, { pointToLayer: (geom, latlng) => { + const span = document.createElement('span'); + span.innerText = quest_icon; return L.marker(latlng, { icon: L.divIcon({ className: 'symbol-icon symbol-icon-interactive', - html: `${quest_icon}`, + html: span, iconSize: [24, 24], iconAnchor: [12, 12], }) @@ -3486,11 +3496,15 @@ class DataOverlay { style, interactive: feature.interactive, pointToLayer: (geom, latlng) => { + const span = document.createElement('span'); + span.style.setProperty('--icon-color', style.color); + span.innerText = feature.point_icon ?? ''; + return L.marker(latlng, { title: feature.title, icon: L.divIcon({ className: 'symbol-icon ' + (feature.point_icon ? '' : 'symbol-icon-empty ') + (feature.interactive ? 'symbol-icon-interactive' : ''), - html: `${feature.point_icon ?? ''}`, + html: span, iconSize: [24, 24], iconAnchor: [12, 12], }) @@ -3499,19 +3513,31 @@ class DataOverlay { onEachFeature: (f, layer) => { if (feature.interactive) { layer.bindPopup(() => { - let html = `

${feature.title}

`; + const f = document.createDocumentFragment(); + const h4 = document.createElement('h4'); + h4.innerText = feature.title; + f.append(h4); if (feature.external_url != null) { - html += `open external link`; + const a = document.createElement('a'); + a.href = feature.external_url; + a.target = '_blank'; + a.innerText = 'open external link'; + f.append(a); } if (feature.extra_data != null) { - html += ''; + const table = document.createElement('table'); for (const key in feature.extra_data) { - html += ``; + const tr = document.createElement('tr'); + const th = document.createElement('th'); + th.innerText = key; + const td = document.createElement('td'); + td.innerText = feature.extra_data[key]; + tr.append(th, td); + table.append(tr); } - - html += '
${key}${feature.extra_data[key]}
'; + f.append(table); } - return html; + return f; }, { className: 'data-overlay-popup' });