Migrate JS from SVG to BMAP

This commit is contained in:
2026-09-06 19:40:50 +02:00
parent a9c8a89aac
commit 02b92308d0
13 changed files with 257 additions and 696 deletions
+3 -1
View File
@@ -22,4 +22,6 @@ app/release/
captures/ captures/
local.properties local.properties
keystore.properties keystore.properties
key.jks key.jks
# generated map intermediates; the packed .bmap in assets is what ships
mapdata/*.geojson
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 4.0 MiB

+1 -51
View File
@@ -1,10 +1,8 @@
#!/bin/node #!/bin/node
import {readFileSync,writeFileSync,existsSync} from 'fs' import {readFileSync,existsSync} from 'fs'
import area from '@turf/area' import area from '@turf/area'
import * as turf from '@turf/turf' import * as turf from '@turf/turf'
import * as path from 'path';
import { JSDOM } from 'jsdom';
const countries = const countries =
@@ -162,52 +160,4 @@ async function run(){
} }
} }
function fixSvg(svgPath) {
const countryToRegion = {};
for (const [region, countries] of Object.entries(groups)) {
countries.forEach(country => countryToRegion[country] = region);
}
const absoluteInputPath = path.resolve(svgPath);
if (!existsSync(absoluteInputPath)) {
throw new Error(`Input file not found at: ${absoluteInputPath}`);
}
const svgContent = readFileSync(absoluteInputPath, 'utf8');
const dom = new JSDOM(svgContent, { contentType: 'image/svg+xml' });
const document = dom.window.document;
const svgRoot = document.querySelector('svg');
if (!svgRoot) {
throw new Error("Invalid or empty SVG structure encountered.");
}
if (svgRoot.getAttribute('data-processed') === 'true') {
console.log(`Skipping: File at "${svgPath}" has already been processed.`);
return;
}
const elementGroups = Array.from(svgRoot.querySelectorAll('g'));
elementGroups.forEach(group => {
const currentId = group.getAttribute('id') || '';
const baseIsoCode = currentId.replace(/\d+$/, '');
const regionKey = countryToRegion[baseIsoCode] || 'XXXX';
let regionGroup = svgRoot.querySelector(`g[id="${regionKey}"]`);
if (!regionGroup) {
regionGroup = document.createElementNS('http://w3.org', 'g');
regionGroup.setAttribute('id', regionKey);
svgRoot.appendChild(regionGroup);
}
regionGroup.appendChild(group);
});
svgRoot.setAttribute('data-processed', 'true');
const absoluteOutputPath = path.resolve(svgPath);
let cleanXmlString = svgRoot.outerHTML;
cleanXmlString = cleanXmlString.replace(/[\r\n]+/g, '');
cleanXmlString = cleanXmlString.replace(/xmlns="http:\/\/w3\.org"\s?/g, '');
cleanXmlString = cleanXmlString.replace(/xmlns="http:\/\/www\.w3\.org\/2000\/svg"\s?/g, '');
cleanXmlString = cleanXmlString.replace('<svg', '<svg xmlns="http://www.w3.org/2000/svg"');
writeFileSync(absoluteOutputPath, cleanXmlString, 'utf8');
}
run() run()
fixSvg("./app/src/main/assets/loxim01.svg")
fixSvg("./app/src/main/assets/webmercator01.svg")
fixSvg("./app/src/main/assets/aeqd01.svg")
+18 -57
View File
@@ -1,7 +1,5 @@
#!/bin/bash #!/bin/bash
LOCAL_SVG_PATH="app/src/main/assets/"
GADM_VERSION="4.1" GADM_VERSION="4.1"
GADM_BASEPATH="https://geodata.ucdavis.edu/gadm" GADM_BASEPATH="https://geodata.ucdavis.edu/gadm"
@@ -80,43 +78,7 @@ download_1() {
} }
toSVG_0() { generate_map() {
local input_files=("ATA")
for country in "${countries[@]}"
do
input_file="./temp/0/${country}.json"
if [ -f "$input_file" ]; then
input_files+=("$input_file")
else
echo "Input file $input_file not found."
fi
done
"$mapshaper" -i combine-files ${input_files[@]} -proj webmercator -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/mercator0.svg svg-data=GID_0,COUNTRY id-field=GID_0
"$mapshaper" -i combine-files ${input_files[@]} -proj aeqd +lat_0=90 -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/aeqd0.svg svg-data=GID_0,COUNTRY id-field=GID_0
}
toSVG_1() {
input_files=("ATA")
for country in "${countries[@]}"
do
input_file="./temp/1/${country}.json"
# input_file="./temp/1/gadm41_${country}_1.json"
if [ -f "$input_file" ]; then
input_files+=("$input_file")
else
echo "Input file $input_file not found."
fi
done
"$mapshaper" -i combine-files ${input_files[@]} -proj webmercator -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/mercator1.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
"$mapshaper" -i combine-files ${input_files[@]} -proj aeqd +lat_0=90 -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/aeqd1.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
}
generate_svg_map() {
local OUT_FILE="$1" # First argument: Output destination path local OUT_FILE="$1" # First argument: Output destination path
local PROJ_ARGS="$2" # Second argument: Projection parameters local PROJ_ARGS="$2" # Second argument: Projection parameters
shift 2 # Remove the first two arguments, leaving only the files shift 2 # Remove the first two arguments, leaving only the files
@@ -125,6 +87,9 @@ generate_svg_map() {
echo "Generating: $OUT_FILE using projection [$PROJ_ARGS]" echo "Generating: $OUT_FILE using projection [$PROJ_ARGS]"
echo "Processing ${#FILES_TO_RUN[@]} files..." echo "Processing ${#FILES_TO_RUN[@]} files..."
# Each feature is tagged with the place it belongs to and whether it is a
# country outline or one of its regions. packmap.js groups on that; nothing
# downstream needs the features split into layers.
local JS_PIPELINE_LOGIC=" local JS_PIPELINE_LOGIC="
const conflicts = { const conflicts = {
'Z01': 'IND', 'Z04': 'IND', 'Z05': 'IND', 'Z07': 'IND', 'Z09': 'IND', 'Z01': 'IND', 'Z04': 'IND', 'Z05': 'IND', 'Z07': 'IND', 'Z09': 'IND',
@@ -133,32 +98,27 @@ generate_svg_map() {
}; };
let rawCode = GID_0 || 'UNK'; let rawCode = GID_0 || 'UNK';
let cCode = conflicts[rawCode] ? conflicts[rawCode] : rawCode; let cCode = conflicts[rawCode] ? conflicts[rawCode] : rawCode;
// Antarctica's boundary file carries no country code at either level.
if (cCode === 'UNK') cCode = 'ATA';
let isGidMissing = (!GID || GID === 'undefined' || GID === 'null' || GID === ''); let isGidMissing = (!GID || GID === 'undefined' || GID === 'null' || GID === '');
if (isGidMissing) { CODE = isGidMissing ? cCode : GID;
COUNTRY_GROUP = cCode+'2'; LEVEL = isGidMissing ? 0 : 1;
} else {
COUNTRY_GROUP = cCode+'1';
}
" "
"$mapshaper" -i "${FILES_TO_RUN[@]}" combine-files \ "$mapshaper" -i "${FILES_TO_RUN[@]}" combine-files \
-snap \ -snap \
-merge-layers force\ -merge-layers force\
-proj $PROJ_ARGS densify \ -proj $PROJ_ARGS densify \
-simplify 2% weighted keep-shapes \ -simplify 10% weighted keep-shapes \
-filter-islands min-area=0 \ -filter-islands min-area=0 \
-sort 'this.area' ascending \ -sort 'this.area' ascending \
-each "$JS_PIPELINE_LOGIC" \ -each "$JS_PIPELINE_LOGIC" \
-split COUNTRY_GROUP \
-o "$OUT_FILE" \ -o "$OUT_FILE" \
format=svg \ format=geojson
id-field=GID \
precision=0.1 \
target=*
} }
toSVG_01() { build_maps() {
input_files=() input_files=()
input_files+=("./temp/1/ATA.json") input_files+=("./temp/1/ATA.json")
@@ -178,9 +138,12 @@ toSVG_01() {
fi fi
done done
generate_svg_map "./app/src/main/assets/loxim01.svg" "loxim" "${input_files[@]}" generate_map "./mapdata/loxim01.geojson" "loxim" "${input_files[@]}"
generate_svg_map "./app/src/main/assets/webmercator01.svg" "webmercator" "${input_files[@]}" generate_map "./mapdata/webmercator01.geojson" "webmercator" "${input_files[@]}"
generate_svg_map "./app/src/main/assets/aeqd01.svg" "aeqd +lat_0=90" "${input_files[@]}" generate_map "./mapdata/aeqd01.geojson" "aeqd +lat_0=90" "${input_files[@]}"
# The app reads the packed form; the GeoJSON above is only an intermediate.
node packmap.js ./mapdata/loxim01.geojson ./mapdata/webmercator01.geojson ./mapdata/aeqd01.geojson
} }
do_1() { do_1() {
@@ -199,8 +162,6 @@ do_0() {
} }
# do_0 # do_0
# do_1 # do_1
# toSVG_0 build_maps
# toSVG_1
toSVG_01
#CUW, CCK, XCL, CXR, IOT, BVT, ABW, FLK, GIB, HMD, KIR, SXM, MDV, MCO, NIU, NFK, PCN, MAF, SGS, VAT #CUW, CCK, XCL, CXR, IOT, BVT, ABW, FLK, GIB, HMD, KIR, SXM, MDV, MCO, NIU, NFK, PCN, MAF, SGS, VAT
-325
View File
@@ -1,325 +0,0 @@
var continents = {
XAD:"EEE",
ALA:"EEE",
ALB:"EEE",
AND:"EEE",
AUT:"EEE",
BLR:"EEE",
BEL:"EEE",
BIH:"EEE",
BGR:"EEE",
HRV:"EEE",
CYP:"EEE",
CZE:"EEE",
DNK:"EEE",
EST:"EEE",
FRO:"EEE",
FIN:"EEE",
FRA:"EEE",
DEU:"EEE",
GIB:"EEE",
GRC:"EEE",
GGY:"EEE",
HUN:"EEE",
ISL:"EEE",
IRL:"EEE",
IMN:"EEE",
ITA:"EEE",
JEY:"EEE",
KAZ:"EEE",
XKO:"EEE",
LVA:"EEE",
LIE:"EEE",
LTU:"EEE",
LUX:"EEE",
MLT:"EEE",
MDA:"EEE",
MCO:"EEE",
MNE:"EEE",
NLD:"EEE",
MKD:"EEE",
NOR:"EEE",
POL:"EEE",
PRT:"EEE",
ROU:"EEE",
RUS:"EEE",
SMR:"EEE",
SRB:"EEE",
SVK:"EEE",
SVN:"EEE",
ESP:"EEE",
SJM:"EEE",
SWE:"EEE",
CHE:"EEE",
UKR:"EEE",
GBR:"EEE",
VAT:"EEE",
AFG:"ABB",
ARM:"ABB",
AZE:"ABB",
BHR:"ABB",
BGD:"ABB",
BTN:"ABB",
IOT:"ABB",
BRN:"ABB",
KHM:"ABB",
CCK:"ABB",
CHN:"ABB",
CXR:"ABB",
GEO:"ABB",
HKG:"ABB",
IND:"ABB",
IDN:"ABB",
IRN:"ABB",
IRQ:"ABB",
ISR:"ABB",
JPN:"ABB",
JOR:"ABB",
KWT:"ABB",
KGZ:"ABB",
LAO:"ABB",
LBN:"ABB",
MAC:"ABB",
MYS:"ABB",
MDV:"ABB",
MNG:"ABB",
MMR:"ABB",
NPL:"ABB",
PRK:"ABB",
OMN:"ABB",
PAK:"ABB",
PSE:"ABB",
PHL:"ABB",
QAT:"ABB",
SAU:"ABB",
SGP:"ABB",
KOR:"ABB",
LKA:"ABB",
SYR:"ABB",
TWN:"ABB",
TJK:"ABB",
THA:"ABB",
TLS:"ABB",
TUR:"ABB",
TKM:"ABB",
ARE:"ABB",
UZB:"ABB",
VNM:"ABB",
YEM:"ABB",
ZNC:"ABB",
DZA:"FFF",
AGO:"FFF",
BDI:"FFF",
BEN:"FFF",
BWA:"FFF",
BFA:"FFF",
BDI:"FFF",
CPV:"FFF",
CMR:"FFF",
CAF:"FFF",
TCD:"FFF",
COM:"FFF",
COG:"FFF",
COD:"FFF",
CIV:"FFF",
DJI:"FFF",
EGY:"FFF",
GNQ:"FFF",
ERI:"FFF",
ETH:"FFF",
ATF:"FFF",
GAB:"FFF",
GMB:"FFF",
GHA:"FFF",
GIN:"FFF",
GNB:"FFF",
KEN:"FFF",
LSO:"FFF",
LBR:"FFF",
LBY:"FFF",
MDG:"FFF",
MWI:"FFF",
MLI:"FFF",
MRT:"FFF",
MUS:"FFF",
MYT:"FFF",
MAR:"FFF",
MOZ:"FFF",
NAM:"FFF",
NER:"FFF",
NGA:"FFF",
COD:"FFF",
REU:"FFF",
RWA:"FFF",
STP:"FFF",
SEN:"FFF",
SYC:"FFF",
SLE:"FFF",
SOM:"FFF",
ZAF:"FFF",
SSD:"FFF",
SHN:"FFF",
SDN:"FFF",
SWZ:"FFF",
TZA:"FFF",
TGO:"FFF",
TUN:"FFF",
UGA:"FFF",
COD:"FFF",
ZMB:"FFF",
ZWE:"FFF",
ESH:"FFF",
ABW:"NNN",
AIA:"NNN",
ATG:"NNN",
BHS:"NNN",
BRB:"NNN",
BLZ:"NNN",
BMU:"NNN",
BES:"NNN",
VGB:"NNN",
CAN:"NNN",
CYM:"NNN",
XCL:"NNN",
CRI:"NNN",
CUB:"NNN",
CUW:"NNN",
DMA:"NNN",
DOM:"NNN",
SLV:"NNN",
GRL:"NNN",
GRD:"NNN",
GLP:"NNN",
GTM:"NNN",
HTI:"NNN",
HND:"NNN",
JAM:"NNN",
MTQ:"NNN",
MEX:"NNN",
MSR:"NNN",
ANT:"NNN",
CUW:"NNN",
NIC:"NNN",
PAN:"NNN",
PRI:"NNN",
BLM:"NNN",
KNA:"NNN",
LCA:"NNN",
MAF:"NNN",
SPM:"NNN",
VCT:"NNN",
SXM:"NNN",
TTO:"NNN",
TCA:"NNN",
USA:"NNN",
UMI:"NNN",
VIR:"NNN",
ARG:"SRR",
BOL:"SRR",
BRA:"SRR",
CHL:"SRR",
COL:"SRR",
ECU:"SRR",
FLK:"SRR",
GUF:"SRR",
GUY:"SRR",
PRY:"SRR",
PER:"SRR",
SUR:"SRR",
URY:"SRR",
VEN:"SRR",
ASM:"UUU",
AUS:"UUU",
COK:"UUU",
FJI:"UUU",
PYF:"UUU",
GUM:"UUU",
KIR:"UUU",
MHL:"UUU",
FSM:"UUU",
NRU:"UUU",
NCL:"UUU",
NZL:"UUU",
NIU:"UUU",
NFK:"UUU",
MNP:"UUU",
PLW:"UUU",
PNG:"UUU",
PCN:"UUU",
WSM:"UUU",
SLB:"UUU",
TKL:"UUU",
TON:"UUU",
TUV:"UUU",
VUT:"UUU",
WLF:"UUU",
ATA:"XXX",
BVT:"XXX",
HMD:"XXX",
SGS:"XXX",
}
import fs from "fs"
import {JSDOM} from "jsdom"
function groupByContinent(svgFilePath) {
// Read the SVG file
fs.readFile(svgFilePath, 'utf-8', (err, data) => {
if (err) {
console.error('Error reading SVG file:', err);
return;
}
// Create a virtual DOM with JSDOM
const dom = new JSDOM(data);
const document = dom.window.document;
// Select the root <svg> element
const svgElement = document.querySelector('svg');
// Group <g> elements representing countries by continent
const world = {}; // Renamed continents object to 'world'
svgElement.querySelectorAll('g').forEach(countryGroup => {
const countryId = countryGroup.getAttribute('id');
if (countryId!= null){
const continentId = continents[countryId.replace(/\d/g, "")] || "XXX"; // Remove numbers from country ID to get continent ID
if (!world[continentId]) {
world[continentId] = document.createElementNS('http://www.w3.org/2000/svg', 'g');
world[continentId].setAttribute('id', continentId);
}
world[continentId].innerHTML += countryGroup.outerHTML;
}else{
console.log(countryId,countryGroup.outerHTML)
}
});
// Create new <g> elements for each continent
svgElement.innerHTML = '';
for (const continentId in world) {
svgElement.appendChild(world[continentId]);
}
// Output the modified SVG
fs.writeFile(svgFilePath, svgElement.outerHTML, 'utf-8', err => {
if (err) {
console.error('Error writing to SVG file:', err);
return;
}
console.log('SVG file updated successfully.');
});
});
}
// Example usage:
const svgFileBasePath = "./app/src/main/assets/" ;
groupByContinent(svgFileBasePath+ "webmercator01.svg");
groupByContinent(svgFileBasePath+ "aeqd01.svg");
groupByContinent(svgFileBasePath+ "loxim01.svg");
+3 -1
View File
@@ -1,8 +1,10 @@
{ {
"scripts": {
"pack": "node packmap.js mapdata/loxim01.geojson mapdata/webmercator01.geojson mapdata/aeqd01.geojson"
},
"dependencies": { "dependencies": {
"@turf/area": "^7.3.5", "@turf/area": "^7.3.5",
"@turf/turf": "^7.3.5", "@turf/turf": "^7.3.5",
"jsdom": "^30.0.0",
"mapshaper": "^0.7.22" "mapshaper": "^0.7.22"
}, },
"type": "module" "type": "module"
+232
View File
@@ -0,0 +1,232 @@
#!/bin/node
/**
* Packs the generated map data into the compact binary the app reads.
*
* The app used to ship SVG, which spends about four megabytes per projection
* spelling coordinates out in decimal ASCII inside XML, and needed the map
* parsed as a document at startup. Nothing needs a document: the app wants a
* list of places and the outlines that belong to them, which is what this
* writes.
*
* Input is mapshaper's projected GeoJSON, where each feature carries:
* CODE the place it belongs to, e.g. "FRA" or "FRA_CE"
* LEVEL 0 for a country outline, 1 for one of its regions
*
* Output format. All integers are LEB128 varints and coordinates are in grid
* steps, on a canvas MAP_WIDTH user units across:
*
* "BMAP" 0x02
* precision uvarint, grid steps per user unit
* width, height uvarint, in grid steps
* shapeCount uvarint
* per shape:
* codeLength, code uvarint + UTF-8 bytes
* flags 1 byte, bit 0 = is a region
* ringCount uvarint
* per ring:
* pointCount uvarint
* flags 1 byte, bit 0 = even-odd fill
* pointCount pairs of dx, dy zigzag varint, from the previous point,
* starting from the origin on each ring
*/
import { readFileSync, writeFileSync } from 'fs'
/** Canvas width in user units. Stroke widths in the app are relative to it. */
const MAP_WIDTH = 800
/** Blank edge left around the map, as mapshaper's own SVG output used to. */
const MARGIN = 1
/**
* Grid steps per user unit. Coordinates are snapped to this, so it sets how
* fine the map can be; it is written into the header rather than agreed by
* convention, so raising it only means regenerating the assets.
*/
const PRECISION = 20
function uvarint(bytes, value) {
while (value >= 0x80) {
bytes.push((value & 0x7f) | 0x80)
value >>>= 7
}
bytes.push(value)
}
function svarint(bytes, value) {
uvarint(bytes, value < 0 ? -value * 2 - 1 : value * 2)
}
/** Every polygon of a feature, outer rings and holes alike. */
function ringsOf(geometry) {
if (!geometry) return []
if (geometry.type === 'Polygon') return [geometry.coordinates]
if (geometry.type === 'MultiPolygon') return geometry.coordinates
return []
}
/**
* Groups features by the place they belong to. A country outline and its
* regions arrive as separate features; the code is what ties them together.
*/
function collect(features) {
const shapes = []
const byCode = new Map()
for (const feature of features) {
const code = feature.properties?.CODE
if (!code) continue
const polygons = ringsOf(feature.geometry)
if (polygons.length === 0) continue
let shape = byCode.get(code)
if (!shape) {
shape = { code, isState: feature.properties.LEVEL === 1, rings: [], seen: new Set() }
byCode.set(code, shape)
shapes.push(shape)
}
// A polygon with holes only reads correctly under an even-odd fill, which
// is the rule mapshaper's SVG output used to pick for the same reason.
const evenOdd = polygons.some((polygon) => polygon.length > 1)
for (const polygon of polygons) {
for (const ring of polygon) {
if (ring.length >= 3) shape.rings.push({ ring, evenOdd })
}
}
}
return shapes
}
/** Twice the signed area of a closed ring of `x, y` pairs. */
function shoelace(points) {
let sum = 0
const count = points.length / 2
for (let i = 0, j = count - 1; i < count; j = i++) {
sum += points[j * 2] * points[i * 2 + 1] - points[i * 2] * points[j * 2 + 1]
}
return sum
}
/**
* Snaps every ring to the output grid and throws away what that makes
* redundant: points that land on the one before them, and rings left too small
* to enclose anything. The simplification upstream works to about this
* precision, so a good share of the raw points say nothing once rounded.
*/
function quantize(shapes, canvas) {
const kept = []
for (const shape of shapes) {
const seen = new Set()
const rings = []
for (const { ring, evenOdd } of shape.rings) {
const points = []
let px = null
let py = null
for (const [rx, ry] of ring) {
const x = canvas.x(rx)
const y = canvas.y(ry)
if (x === px && y === py) continue
points.push(x, y)
px = x
py = y
}
if (points.length < 6) continue
// Coordinates are integers now, so any ring that still encloses area
// encloses at least half a grid square. One that comes out at exactly
// zero is a sliver the rounding flattened, and it would draw nothing.
if (shoelace(points) === 0) continue
// Antarctica arrives twice over, once per admin level, because its source
// carries no country code and both levels land on ATA. A ring counted
// twice cancels itself out in the even-odd test the app hit tests with,
// which would leave the shape impossible to tap.
const key = points.join(',')
if (seen.has(key)) continue
seen.add(key)
rings.push({ points, evenOdd })
}
if (rings.length > 0) kept.push({ code: shape.code, isState: shape.isState, rings })
}
// By code, which puts a country next to its own regions. They are neighbours
// on the map, so their coordinates are similar, and the compressor in the APK
// gets noticeably more out of the file for it.
return kept.sort((a, b) => (a.code < b.code ? -1 : a.code > b.code ? 1 : 0))
}
/** Projected metres in, user units on a MAP_WIDTH canvas out, y flipped. */
function fitToCanvas(shapes) {
let minX = Infinity
let minY = Infinity
let maxX = -Infinity
let maxY = -Infinity
for (const shape of shapes) {
for (const { ring } of shape.rings) {
for (const [x, y] of ring) {
if (x < minX) minX = x
if (x > maxX) maxX = x
if (y < minY) minY = y
if (y > maxY) maxY = y
}
}
}
const scale = (MAP_WIDTH - 2 * MARGIN) / (maxX - minX)
return {
width: MAP_WIDTH,
height: 2 * MARGIN + (maxY - minY) * scale,
x: (v) => Math.round((MARGIN + (v - minX) * scale) * PRECISION),
y: (v) => Math.round((MARGIN + (maxY - v) * scale) * PRECISION),
}
}
function pack(path) {
const geojson = JSON.parse(readFileSync(path, 'utf8'))
const collected = collect(geojson.features ?? [])
const canvas = fitToCanvas(collected)
const shapes = quantize(collected, canvas)
const bytes = [0x42, 0x4d, 0x41, 0x50, 0x02] // "BMAP" v2
uvarint(bytes, PRECISION)
uvarint(bytes, Math.round(canvas.width * PRECISION))
uvarint(bytes, Math.round(canvas.height * PRECISION))
uvarint(bytes, shapes.length)
let rings = 0
let points = 0
for (const shape of shapes) {
const code = Buffer.from(shape.code, 'utf8')
uvarint(bytes, code.length)
for (const byte of code) bytes.push(byte)
bytes.push(shape.isState ? 1 : 0)
uvarint(bytes, shape.rings.length)
for (const { points: ring, evenOdd } of shape.rings) {
uvarint(bytes, ring.length / 2)
bytes.push(evenOdd ? 1 : 0)
let px = 0
let py = 0
for (let i = 0; i < ring.length; i += 2) {
svarint(bytes, ring[i] - px)
svarint(bytes, ring[i + 1] - py)
px = ring[i]
py = ring[i + 1]
}
rings++
points += ring.length / 2
}
}
const out = path.replace(/^.*\//, './app/src/main/assets/').replace(/\.geojson$/, '.bmap')
writeFileSync(out, Buffer.from(bytes))
console.log(
`${out}: ${shapes.length} shapes, ${rings} rings, ${points} points, ` +
`${canvas.width}x${canvas.height.toFixed(1)}, ${bytes.length} bytes`,
)
}
const inputs = process.argv.slice(2)
if (inputs.length === 0) {
console.error('usage: node packmap.js <map>.geojson ...')
process.exit(1)
}
inputs.forEach(pack)
-258
View File
@@ -2,77 +2,11 @@
# yarn lockfile v1 # yarn lockfile v1
"@asamuzakjp/css-color@^6.0.5":
version "6.0.7"
resolved "https://registry.yarnpkg.com/@asamuzakjp/css-color/-/css-color-6.0.7.tgz#8f9f67452e6636930949abe047dd553b13276939"
integrity sha512-vC/bk1Lz7Tn/EfU9/apOTBk80/8dyGyWMowPoV1tJ52muDGsDqt2HPT2klrFUiY60MQmQv9q8yIht15JnBgDGw==
dependencies:
"@csstools/css-calc" "^3.3.0"
"@csstools/css-color-parser" "^4.1.10"
"@csstools/css-parser-algorithms" "^4.0.0"
"@csstools/css-tokenizer" "^4.0.0"
lru-cache "^11.5.2"
"@asamuzakjp/dom-selector@^8.3.0":
version "8.3.2"
resolved "https://registry.yarnpkg.com/@asamuzakjp/dom-selector/-/dom-selector-8.3.2.tgz#1e84c1ea1e12a921c1aa94da4b1f657168f09596"
integrity sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==
dependencies:
bidi-js "^1.0.3"
css-tree "^3.2.1"
is-potential-custom-element-name "^1.0.1"
lru-cache "^11.5.2"
"@bokuweb/zstd-wasm@^0.0.27": "@bokuweb/zstd-wasm@^0.0.27":
version "0.0.27" version "0.0.27"
resolved "https://registry.yarnpkg.com/@bokuweb/zstd-wasm/-/zstd-wasm-0.0.27.tgz#89d8ed8c37528c4b9d11f47826b9f603346dfc4c" resolved "https://registry.yarnpkg.com/@bokuweb/zstd-wasm/-/zstd-wasm-0.0.27.tgz#89d8ed8c37528c4b9d11f47826b9f603346dfc4c"
integrity sha512-GDm2uOTK3ESjnYmSeLQifJnBsRCWajKLvN32D2ZcQaaCIJI/Hse9s74f7APXjHit95S10UImsRGkTsbwHmrtmg== integrity sha512-GDm2uOTK3ESjnYmSeLQifJnBsRCWajKLvN32D2ZcQaaCIJI/Hse9s74f7APXjHit95S10UImsRGkTsbwHmrtmg==
"@bramus/specificity@^2.4.2":
version "2.4.2"
resolved "https://registry.yarnpkg.com/@bramus/specificity/-/specificity-2.4.2.tgz#aa8db8eb173fdee7324f82284833106adeecc648"
integrity sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==
dependencies:
css-tree "^3.0.0"
"@csstools/color-helpers@^6.1.1":
version "6.1.1"
resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-6.1.1.tgz#1890f29a4347486b54048d24c6ab8fbef039ee61"
integrity sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==
"@csstools/css-calc@^3.3.0":
version "3.3.0"
resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-3.3.0.tgz#33cc4bdbab8edf1b6e3ab8c1eba849c41a324f1a"
integrity sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==
"@csstools/css-color-parser@^4.1.10":
version "4.2.2"
resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-4.2.2.tgz#f590bc710a26914dbe64c4656813eafc93f4e45e"
integrity sha512-3QKjR/vxyjcSXBLgb6lP0S3MGdvwbmqSsvLPbYdVORqPDc8FX1HAJ0Spk38bxaRXgvENTA47tlhhbb5Z2e8hEg==
dependencies:
"@csstools/color-helpers" "^6.1.1"
"@csstools/css-calc" "^3.3.0"
"@csstools/css-parser-algorithms@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz#e1c65dc09378b42f26a111fca7f7075fc2c26164"
integrity sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==
"@csstools/css-syntax-patches-for-csstree@^1.1.7":
version "1.1.12"
resolved "https://registry.yarnpkg.com/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.12.tgz#34e7156b352b71a482884d659bbd1bf2f738e0c9"
integrity sha512-3vLQK+dXxhBMR2Wx99PTCifE+vHtW2ndZWyla8yK813ev6oGhyn8Lja8jCyGAWTJ+LEYZK7EVtJxrDj8ztevJw==
"@csstools/css-tokenizer@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz#798a33950d11226a0ebb6acafa60f5594424967f"
integrity sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==
"@exodus/bytes@^1.11.0", "@exodus/bytes@^1.15.1", "@exodus/bytes@^1.6.0":
version "1.15.1"
resolved "https://registry.yarnpkg.com/@exodus/bytes/-/bytes-1.15.1.tgz#b13bc464ca162c17abf0837fb3a11aeab79e45d1"
integrity sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==
"@inquirer/ansi@^2.0.8": "@inquirer/ansi@^2.0.8":
version "2.0.8" version "2.0.8"
resolved "https://registry.yarnpkg.com/@inquirer/ansi/-/ansi-2.0.8.tgz#0308f3ed790dfa960f0f1f60045fa67e804de38e" resolved "https://registry.yarnpkg.com/@inquirer/ansi/-/ansi-2.0.8.tgz#0308f3ed790dfa960f0f1f60045fa67e804de38e"
@@ -2060,13 +1994,6 @@ better-sqlite3@^12.10.0:
bindings "^1.5.0" bindings "^1.5.0"
prebuild-install "^7.1.1" prebuild-install "^7.1.1"
bidi-js@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2"
integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==
dependencies:
require-from-string "^2.0.2"
bignumber.js@^9.1.0: bignumber.js@^9.1.0:
version "9.3.1" version "9.3.1"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.1.tgz#759c5aaddf2ffdc4f154f7b493e1c8770f88c4d7" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.1.tgz#759c5aaddf2ffdc4f154f7b493e1c8770f88c4d7"
@@ -2189,14 +2116,6 @@ cookies@^0.8.0:
depd "~2.0.0" depd "~2.0.0"
keygrip "~1.1.0" keygrip "~1.1.0"
css-tree@^3.0.0, css-tree@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-3.2.1.tgz#86cac7011561272b30e6b1e042ba6ce047aa7518"
integrity sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==
dependencies:
mdn-data "2.27.1"
source-map-js "^1.2.1"
d3-array@^2.5.0: d3-array@^2.5.0:
version "2.12.1" version "2.12.1"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81"
@@ -2236,19 +2155,6 @@ d3-voronoi@1.1.2:
resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c" resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c"
integrity sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw== integrity sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==
data-urls@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-7.0.0.tgz#6dce8b63226a1ecfdd907ce18a8ccfb1eee506d3"
integrity sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==
dependencies:
whatwg-mimetype "^5.0.0"
whatwg-url "^16.0.0"
decimal.js@^10.6.0:
version "10.6.0"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a"
integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==
decompress-response@^6.0.0: decompress-response@^6.0.0:
version "6.0.0" version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
@@ -2318,11 +2224,6 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1:
dependencies: dependencies:
once "^1.4.0" once "^1.4.0"
entities@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-8.0.0.tgz#c1df5fe3602429747fa233d0dd26f142f0ce4743"
integrity sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==
event-stream@^4.0.0: event-stream@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-4.0.1.tgz#4092808ec995d0dd75ea4580c1df6a74db2cde65" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-4.0.1.tgz#4092808ec995d0dd75ea4580c1df6a74db2cde65"
@@ -2528,13 +2429,6 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
html-encoding-sniffer@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz#f8d9390b3b348b50d4f61c16dd2ef5c05980a882"
integrity sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==
dependencies:
"@exodus/bytes" "^1.6.0"
hyparquet-compressors@^1.1.1: hyparquet-compressors@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/hyparquet-compressors/-/hyparquet-compressors-1.1.1.tgz#35ab916d4ee3306000279126a937e9a1633725a6" resolved "https://registry.yarnpkg.com/hyparquet-compressors/-/hyparquet-compressors-1.1.1.tgz#35ab916d4ee3306000279126a937e9a1633725a6"
@@ -2640,11 +2534,6 @@ is-inside-container@^1.0.0:
dependencies: dependencies:
is-docker "^3.0.0" is-docker "^3.0.0"
is-potential-custom-element-name@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
is-wsl@^3.1.0: is-wsl@^3.1.0:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.1.tgz#327897b26832a3eb117da6c27492d04ca132594f" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.1.tgz#327897b26832a3eb117da6c27492d04ca132594f"
@@ -2657,33 +2546,6 @@ jpeg-js@^0.4.4:
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa"
integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg== integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==
jsdom@^30.0.0:
version "30.0.1"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-30.0.1.tgz#1b0751cbd0abce86762c48697583b5e91433f6e4"
integrity sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==
dependencies:
"@asamuzakjp/css-color" "^6.0.5"
"@asamuzakjp/dom-selector" "^8.3.0"
"@bramus/specificity" "^2.4.2"
"@csstools/css-syntax-patches-for-csstree" "^1.1.7"
"@exodus/bytes" "^1.15.1"
css-tree "^3.2.1"
data-urls "^7.0.0"
decimal.js "^10.6.0"
html-encoding-sniffer "^6.0.0"
is-potential-custom-element-name "^1.0.1"
lru-cache "^11.5.2"
parse5 "^8.0.1"
saxes "^6.0.0"
symbol-tree "^3.2.4"
tough-cookie "^6.0.2"
undici "^8.9.0"
w3c-xmlserializer "^5.0.0"
webidl-conversions "^8.0.1"
whatwg-mimetype "^5.0.0"
whatwg-url "^17.1.0"
xml-name-validator "^5.0.0"
jsonparse@^1.2.0: jsonparse@^1.2.0:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
@@ -2716,11 +2578,6 @@ lodash@4.18.1:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c"
integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==
lru-cache@^11.5.2:
version "11.5.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.5.2.tgz#00e16665c90c620fba14a3c368732a976493f760"
integrity sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==
map-stream@0.0.7: map-stream@0.0.7:
version "0.0.7" version "0.0.7"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8"
@@ -2766,11 +2623,6 @@ mapshaper@^0.7.22:
"@rollup/rollup-linux-x64-gnu" "^4.44.1" "@rollup/rollup-linux-x64-gnu" "^4.44.1"
better-sqlite3 "^12.10.0" better-sqlite3 "^12.10.0"
mdn-data@2.27.1:
version "2.27.1"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.27.1.tgz#e37b9c50880b75366c4d40ac63d9bbcacdb61f0e"
integrity sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==
mgrs@1.0.0: mgrs@1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/mgrs/-/mgrs-1.0.0.tgz#fb91588e78c90025672395cb40b25f7cd6ad1829" resolved "https://registry.yarnpkg.com/mgrs/-/mgrs-1.0.0.tgz#fb91588e78c90025672395cb40b25f7cd6ad1829"
@@ -2897,13 +2749,6 @@ parse-headers@^2.0.2:
resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.6.tgz#7940f0abe5fe65df2dd25d4ce8800cb35b49d01c" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.6.tgz#7940f0abe5fe65df2dd25d4ce8800cb35b49d01c"
integrity sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A== integrity sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==
parse5@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-8.0.1.tgz#f43bcd2cd683efe084075333e9ce0da7d06da31e"
integrity sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==
dependencies:
entities "^8.0.0"
pause-stream@^0.0.11: pause-stream@^0.0.11:
version "0.0.11" version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
@@ -3018,11 +2863,6 @@ pump@^3.0.0:
end-of-stream "^1.1.0" end-of-stream "^1.1.0"
once "^1.3.1" once "^1.3.1"
punycode@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
queue@6.0.1: queue@6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.1.tgz#abd5a5b0376912f070a25729e0b6a7d565683791" resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.1.tgz#abd5a5b0376912f070a25729e0b6a7d565683791"
@@ -3124,11 +2964,6 @@ reproject@1.2.5:
minimist "^1.2.0" minimist "^1.2.0"
proj4 "^2.4.4" proj4 "^2.4.4"
require-from-string@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
resolve-protobuf-schema@^2.1.0: resolve-protobuf-schema@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758" resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758"
@@ -3176,13 +3011,6 @@ safe-buffer@^5.0.1, safe-buffer@~5.2.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
saxes@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5"
integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==
dependencies:
xmlchars "^2.2.0"
semver@^7.3.5: semver@^7.3.5:
version "7.8.5" version "7.8.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.5.tgz#39b646037dd50c14fb451e7e4cac58ed8b863f69" resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.5.tgz#39b646037dd50c14fb451e7e4cac58ed8b863f69"
@@ -3222,11 +3050,6 @@ slice-source@0.4.1:
resolved "https://registry.yarnpkg.com/slice-source/-/slice-source-0.4.1.tgz#40a57ac03c6668b5da200e05378e000bf2a61d79" resolved "https://registry.yarnpkg.com/slice-source/-/slice-source-0.4.1.tgz#40a57ac03c6668b5da200e05378e000bf2a61d79"
integrity sha512-YiuPbxpCj4hD9Qs06hGAz/OZhQ0eDuALN0lRWJez0eD/RevzKqGdUx1IOMUnXgpr+sXZLq3g8ERwbAH0bCb8vg== integrity sha512-YiuPbxpCj4hD9Qs06hGAz/OZhQ0eDuALN0lRWJez0eD/RevzKqGdUx1IOMUnXgpr+sXZLq3g8ERwbAH0bCb8vg==
source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
splaytree-ts@^1.0.2: splaytree-ts@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/splaytree-ts/-/splaytree-ts-1.0.2.tgz#34963704587aff45eaa09c24713f552bbf56e8f0" resolved "https://registry.yarnpkg.com/splaytree-ts/-/splaytree-ts-1.0.2.tgz#34963704587aff45eaa09c24713f552bbf56e8f0"
@@ -3279,11 +3102,6 @@ supports-color@^7.1.0:
dependencies: dependencies:
has-flag "^4.0.0" has-flag "^4.0.0"
symbol-tree@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
tar-fs@^2.0.0: tar-fs@^2.0.0:
version "2.1.5" version "2.1.5"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.5.tgz#33e9c29413dce0c58ada7ff77db4e5a30afffe70" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.5.tgz#33e9c29413dce0c58ada7ff77db4e5a30afffe70"
@@ -3315,18 +3133,6 @@ tinyqueue@^2.0.3:
resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08" resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA== integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==
tldts-core@^7.4.11:
version "7.4.11"
resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-7.4.11.tgz#a02fba29af72cbf9e658cb3a335f857efc9475f7"
integrity sha512-CW3WN2rIIE/Of21mulhgnGOwoDyEFNygyIBOONSdyAuSATgMMUCpLeUlB+E8sAwA5xRV9hYPl+kyZ9citHCaKg==
tldts@^7.0.5:
version "7.4.11"
resolved "https://registry.yarnpkg.com/tldts/-/tldts-7.4.11.tgz#51d5a3feeb473e592edf671491a24fb23789eed2"
integrity sha512-aBiNayCfTQxuIJBm06M+xR14cYaYlDlSXZbgsnKzKNxDKUVq7KFwTjwBSsb7m9Y5xO8WfPnBc63WaYFMTGlvqw==
dependencies:
tldts-core "^7.4.11"
token-types@^4.1.1: token-types@^4.1.1:
version "4.2.1" version "4.2.1"
resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753" resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753"
@@ -3349,20 +3155,6 @@ topojson-server@3.x:
dependencies: dependencies:
commander "2" commander "2"
tough-cookie@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-6.0.2.tgz#7b1f22fcf2daf06c4ff9d53ec1845f44c6627062"
integrity sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==
dependencies:
tldts "^7.0.5"
tr46@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-6.0.0.tgz#f5a1ae546a0adb32a277a2278d0d17fa2f9093e6"
integrity sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==
dependencies:
punycode "^2.3.1"
tslib@^2.8.1: tslib@^2.8.1:
version "2.8.1" version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
@@ -3390,11 +3182,6 @@ undici-types@~8.3.0:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-8.3.0.tgz#44e9fc9f3244648cdea35e4f9bb2d681e9410809" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-8.3.0.tgz#44e9fc9f3244648cdea35e4f9bb2d681e9410809"
integrity sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ== integrity sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==
undici@^8.9.0:
version "8.10.2"
resolved "https://registry.yarnpkg.com/undici/-/undici-8.10.2.tgz#960bcb0b43c267f86910ea7ca408ada843a44bc7"
integrity sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==
unzipit@2.0.0: unzipit@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/unzipit/-/unzipit-2.0.0.tgz#9461b6a9b067ed9b13f9eda1bc5b93bc448307fa" resolved "https://registry.yarnpkg.com/unzipit/-/unzipit-2.0.0.tgz#9461b6a9b067ed9b13f9eda1bc5b93bc448307fa"
@@ -3405,51 +3192,16 @@ util-deprecate@^1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
w3c-xmlserializer@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c"
integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==
dependencies:
xml-name-validator "^5.0.0"
web-worker@^1.5.0: web-worker@^1.5.0:
version "1.5.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.5.0.tgz#71b2b0fbcc4293e8f0aa4f6b8a3ffebff733dcc5" resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.5.0.tgz#71b2b0fbcc4293e8f0aa4f6b8a3ffebff733dcc5"
integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw== integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==
webidl-conversions@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-8.0.1.tgz#0657e571fe6f06fcb15ca50ed1fdbcb495cd1686"
integrity sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==
webworkify@1.5.0: webworkify@1.5.0:
version "1.5.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/webworkify/-/webworkify-1.5.0.tgz#734ad87a774de6ebdd546e1d3e027da5b8f4a42c" resolved "https://registry.yarnpkg.com/webworkify/-/webworkify-1.5.0.tgz#734ad87a774de6ebdd546e1d3e027da5b8f4a42c"
integrity sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g== integrity sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==
whatwg-mimetype@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz#d8232895dbd527ceaee74efd4162008fb8a8cf48"
integrity sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==
whatwg-url@^16.0.0:
version "16.0.1"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-16.0.1.tgz#047f7f4bd36ef76b7198c172d1b1cebc66f764dd"
integrity sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==
dependencies:
"@exodus/bytes" "^1.11.0"
tr46 "^6.0.0"
webidl-conversions "^8.0.1"
whatwg-url@^17.1.0:
version "17.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-17.1.0.tgz#693144cd2060d324e73b15a717d1f38ecfb3f02e"
integrity sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==
dependencies:
"@exodus/bytes" "^1.15.1"
tr46 "^6.0.0"
webidl-conversions "^8.0.1"
wkt-parser@^1.3.1, wkt-parser@^1.5.5: wkt-parser@^1.3.1, wkt-parser@^1.5.5:
version "1.5.6" version "1.5.6"
resolved "https://registry.yarnpkg.com/wkt-parser/-/wkt-parser-1.5.6.tgz#3a19521914b2a21b7a8203590f5b180b9dba8dfa" resolved "https://registry.yarnpkg.com/wkt-parser/-/wkt-parser-1.5.6.tgz#3a19521914b2a21b7a8203590f5b180b9dba8dfa"
@@ -3475,21 +3227,11 @@ wsl-utils@^1.0.0:
is-wsl "^3.1.0" is-wsl "^3.1.0"
powershell-utils "^0.1.0" powershell-utils "^0.1.0"
xml-name-validator@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673"
integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==
xml-utils@^1.10.2: xml-utils@^1.10.2:
version "1.10.2" version "1.10.2"
resolved "https://registry.yarnpkg.com/xml-utils/-/xml-utils-1.10.2.tgz#436b39ccc25a663ce367ea21abb717afdea5d6b1" resolved "https://registry.yarnpkg.com/xml-utils/-/xml-utils-1.10.2.tgz#436b39ccc25a663ce367ea21abb717afdea5d6b1"
integrity sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA== integrity sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==
xmlchars@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
zarrita@^0.7.1: zarrita@^0.7.1:
version "0.7.5" version "0.7.5"
resolved "https://registry.yarnpkg.com/zarrita/-/zarrita-0.7.5.tgz#74a4d5d5047cd1e930bffaed9234b62437a3fe13" resolved "https://registry.yarnpkg.com/zarrita/-/zarrita-0.7.5.tgz#74a4d5d5047cd1e930bffaed9234b62437a3fe13"