fix(import): keep KML points visible when remote icons are blocked

This commit is contained in:
Mazeyar Moeini Feizabadi committed 2026-10-14 13:16:10 +02:00
1 parent ae51f9aee9
commit c58ff5c215
6 files changed
+146 -4

No files matched your search

+11 -1
View File
@@ -493,7 +493,17 @@ export function sanitizeKmlDocument(doc, resolveLocal = () => null) {
const local = resolveLocal(value);
if (local) href.textContent = local;
else if (/^data:image\/(png|jpeg|gif|webp|bmp);/i.test(value)) continue;
else drop(href);
else {
const icon = href.parentNode;
// An empty Icon explicitly hides the billboard in Cesium. Remove the
// blocked icon definition so the loader supplies its local default pin.
// Authored empty Icons (with no blocked href) still mean no marker.
drop(
icon?.localName === 'Icon' && icon.parentNode?.localName === 'IconStyle'
? icon
: href,
);
}
}
for (const overlay of elementsNamed(doc, 'GroundOverlay')) {
if (!elementsNamed(overlay, 'href').length) drop(overlay);
+37
View File
@@ -426,6 +426,43 @@ test('KML extended metadata is removed before the document reaches the loader',
assert.deepEqual(placemark.childNodes, [point]);
assert.equal(metadata.parentNode, null);
});
test('blocked icon sources fall back to local pins without changing intentional empty icons', () => {
const blocked = xmlEl('Icon', {}, [
xmlEl('href', {}, 'https://example.invalid/icon.png'),
]);
const blank = xmlEl('Icon');
const embedded = xmlEl('Icon', {}, [
xmlEl('href', {}, 'data:image/png;base64,AAAA'),
]);
const packed = xmlEl('Icon', {}, [xmlEl('href', {}, 'packed.png')]);
const iconStyle = xmlEl('IconStyle', {}, [
xmlEl('scale', {}, '0.3'),
blocked,
]);
const doc = xmlDoc(
xmlEl('kml', {}, [
xmlEl('Style', {}, [iconStyle]),
...[blank, embedded, packed].map((icon) =>
xmlEl('Style', {}, [xmlEl('IconStyle', {}, [icon])]),
),
]),
);
assert.equal(
sanitizeKmlDocument(doc, (href) =>
href === 'packed.png' ? 'blob:local-image' : null,
).removed,
1,
);
assert.equal(blocked.parentNode, null);
assert.equal(iconStyle.childNodes[0].textContent, '0.3');
assert.equal(blank.parentNode.localName, 'IconStyle');
assert.equal(
embedded.childNodes[0].textContent,
'data:image/png;base64,AAAA',
);
assert.equal(packed.childNodes[0].textContent, 'blob:local-image');
});
const trkpt = (lat, lon, time) =>
xmlEl('trkpt', { lat, lon }, time ? [xmlEl('time', {}, time)] : []);