import { countryData } from "https://esm.town/v/jdan/countryData";
import { blob } from "https://esm.town/v/std/blob?v=10";
export async function svgMapOfCountry(country: string) {
const mapUrl = (await countryData())
.find((value) => value.countryLabel === country)
.mapLabel
.replaceAll("+", "_");
if (!mapUrl) {
throw new Error(`Unable to find map for country: ${country}`);
}
const cacheKey = `cache-jdan/svgMapOfCountry/${country}`;
const cached = await blob.getJSON(cacheKey);
if (cached) {
return cached;
}
const res = await fetch(mapUrl);
if (res.status !== 200) {
throw new Error(`[${res.status}] Error fetching ${mapUrl}`);
}
const mapData = await res.json();
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
mapData.data.features.forEach(feature => {
const processRing = (ring) => {
ring.forEach(([x, y_]) => {
const y = 90 - y_;
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
});
};
const geometry = feature.geometry;
if (geometry.type === "Polygon" || geometry.type === "MultiPolygon") {
const polygons = geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates;
polygons.forEach(polygon => {
polygon.forEach(ring => processRing(ring));
});
}
});
const width = maxX - minX;
const height = maxY - minY;
const strokeWidth = Math.min(width, height) * 0.004;
const style = `fill: none; stroke: black; stroke-width: ${strokeWidth}px`;
const viewBox = `${minX} ${minY} ${width} ${height}`;
let svgString = `<svg viewBox="${viewBox}" xmlns="http://www.w3.org/2000/svg">\n`;
const ringToPathD = (ring) => {
let d = `M ${ring[0][0]} ${90 - ring[0][1]} `;
ring.slice(1).forEach(coord => {
d += `L ${coord[0]} ${90 - coord[1]} `;
});
return d + "Z";
};
mapData.data.features.forEach(feature => {
const geometry = feature.geometry;
if (geometry.type === "Polygon" || geometry.type === "MultiPolygon") {
const polygons = geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates;
polygons.forEach(polygon => {
let d = "";
polygon.forEach((ring, index) => {
d += ringToPathD(ring);
});
svgString += `<path d="${d}" style="${style}"></path>\n`;
});
}
});
svgString += "</svg>";
return svgString;
}