add prettierrc config file

This commit is contained in:
Logan Houp
2023-03-11 12:35:07 -05:00
parent c3c6ab52dd
commit c07c73481b
5 changed files with 1068 additions and 1044 deletions

1
js/.prettierrc.json Normal file
View File

@@ -0,0 +1 @@
{}

File diff suppressed because it is too large Load Diff

22
js/package-lock.json generated
View File

@@ -15,6 +15,7 @@
"@types/node": "^18.11.9", "@types/node": "^18.11.9",
"esbuild": "^0.15.11", "esbuild": "^0.15.11",
"esbuild-runner": "^2.2.1", "esbuild-runner": "^2.2.1",
"prettier": "^2.8.4",
"typescript": "^4.5.5" "typescript": "^4.5.5"
} }
}, },
@@ -440,6 +441,21 @@
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.3.tgz", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.3.tgz",
"integrity": "sha512-0Zz1jOzJWERhyhsimS54VTqOteCNwRtIlh8isdL0AXLo0g7xNTfTL7oWrkmCnPhZGocKIkWHBistBrrpoNH3aw==" "integrity": "sha512-0Zz1jOzJWERhyhsimS54VTqOteCNwRtIlh8isdL0AXLo0g7xNTfTL7oWrkmCnPhZGocKIkWHBistBrrpoNH3aw=="
}, },
"node_modules/prettier": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz",
"integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -691,6 +707,12 @@
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.3.tgz", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.3.tgz",
"integrity": "sha512-0Zz1jOzJWERhyhsimS54VTqOteCNwRtIlh8isdL0AXLo0g7xNTfTL7oWrkmCnPhZGocKIkWHBistBrrpoNH3aw==" "integrity": "sha512-0Zz1jOzJWERhyhsimS54VTqOteCNwRtIlh8isdL0AXLo0g7xNTfTL7oWrkmCnPhZGocKIkWHBistBrrpoNH3aw=="
}, },
"prettier": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz",
"integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==",
"dev": true
},
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",

View File

@@ -27,6 +27,7 @@
"@types/node": "^18.11.9", "@types/node": "^18.11.9",
"esbuild": "^0.15.11", "esbuild": "^0.15.11",
"esbuild-runner": "^2.2.1", "esbuild-runner": "^2.2.1",
"prettier": "^2.8.4",
"typescript": "^4.5.5" "typescript": "^4.5.5"
}, },
"dependencies": { "dependencies": {

556
js/v2.ts
View File

@@ -1,360 +1,360 @@
import { import {
Source, Source,
Header, Header,
Cache, Cache,
RangeResponse, RangeResponse,
Compression, Compression,
TileType, TileType,
} from "./index"; } from "./index";
import { decompressSync } from "fflate"; import { decompressSync } from "fflate";
export const shift = (n: number, shift: number) => { export const shift = (n: number, shift: number) => {
return n * Math.pow(2, shift); return n * Math.pow(2, shift);
}; };
export const unshift = (n: number, shift: number) => { export const unshift = (n: number, shift: number) => {
return Math.floor(n / Math.pow(2, shift)); return Math.floor(n / Math.pow(2, shift));
}; };
export const getUint24 = (view: DataView, pos: number) => { export const getUint24 = (view: DataView, pos: number) => {
return shift(view.getUint16(pos + 1, true), 8) + view.getUint8(pos); return shift(view.getUint16(pos + 1, true), 8) + view.getUint8(pos);
}; };
export const getUint48 = (view: DataView, pos: number) => { export const getUint48 = (view: DataView, pos: number) => {
return shift(view.getUint32(pos + 2, true), 16) + view.getUint16(pos, true); return shift(view.getUint32(pos + 2, true), 16) + view.getUint16(pos, true);
}; };
interface Zxy { interface Zxy {
z: number; z: number;
x: number; x: number;
y: number; y: number;
} }
export interface EntryV2 { export interface EntryV2 {
z: number; z: number;
x: number; x: number;
y: number; y: number;
offset: number; offset: number;
length: number; length: number;
is_dir: boolean; is_dir: boolean;
} }
const compare = ( const compare = (
tz: number, tz: number,
tx: number, tx: number,
ty: number, ty: number,
view: DataView, view: DataView,
i: number i: number
) => { ) => {
if (tz != view.getUint8(i)) return tz - view.getUint8(i); if (tz != view.getUint8(i)) return tz - view.getUint8(i);
const x = getUint24(view, i + 1); const x = getUint24(view, i + 1);
if (tx != x) return tx - x; if (tx != x) return tx - x;
const y = getUint24(view, i + 4); const y = getUint24(view, i + 4);
if (ty != y) return ty - y; if (ty != y) return ty - y;
return 0; return 0;
}; };
export const queryLeafdir = ( export const queryLeafdir = (
view: DataView, view: DataView,
z: number, z: number,
x: number, x: number,
y: number y: number
): EntryV2 | null => { ): EntryV2 | null => {
const offset_len = queryView(view, z | 0x80, x, y); const offset_len = queryView(view, z | 0x80, x, y);
if (offset_len) { if (offset_len) {
return { return {
z: z, z: z,
x: x, x: x,
y: y, y: y,
offset: offset_len[0], offset: offset_len[0],
length: offset_len[1], length: offset_len[1],
is_dir: true, is_dir: true,
}; };
} }
return null; return null;
}; };
export const queryTile = (view: DataView, z: number, x: number, y: number) => { export const queryTile = (view: DataView, z: number, x: number, y: number) => {
const offset_len = queryView(view, z, x, y); const offset_len = queryView(view, z, x, y);
if (offset_len) { if (offset_len) {
return { return {
z: z, z: z,
x: x, x: x,
y: y, y: y,
offset: offset_len[0], offset: offset_len[0],
length: offset_len[1], length: offset_len[1],
is_dir: false, is_dir: false,
}; };
} }
return null; return null;
}; };
const queryView = ( const queryView = (
view: DataView, view: DataView,
z: number, z: number,
x: number, x: number,
y: number y: number
): [number, number] | null => { ): [number, number] | null => {
let m = 0; let m = 0;
let n = view.byteLength / 17 - 1; let n = view.byteLength / 17 - 1;
while (m <= n) { while (m <= n) {
const k = (n + m) >> 1; const k = (n + m) >> 1;
const cmp = compare(z, x, y, view, k * 17); const cmp = compare(z, x, y, view, k * 17);
if (cmp > 0) { if (cmp > 0) {
m = k + 1; m = k + 1;
} else if (cmp < 0) { } else if (cmp < 0) {
n = k - 1; n = k - 1;
} else { } else {
return [getUint48(view, k * 17 + 7), view.getUint32(k * 17 + 13, true)]; return [getUint48(view, k * 17 + 7), view.getUint32(k * 17 + 13, true)];
} }
} }
return null; return null;
}; };
const entrySort = (a: EntryV2, b: EntryV2): number => { const entrySort = (a: EntryV2, b: EntryV2): number => {
if (a.is_dir && !b.is_dir) { if (a.is_dir && !b.is_dir) {
return 1; return 1;
} }
if (!a.is_dir && b.is_dir) { if (!a.is_dir && b.is_dir) {
return -1; return -1;
} }
if (a.z !== b.z) { if (a.z !== b.z) {
return a.z - b.z; return a.z - b.z;
} }
if (a.x !== b.x) { if (a.x !== b.x) {
return a.x - b.x; return a.x - b.x;
} }
return a.y - b.y; return a.y - b.y;
}; };
export const parseEntry = (dataview: DataView, i: number): EntryV2 => { export const parseEntry = (dataview: DataView, i: number): EntryV2 => {
const z_raw = dataview.getUint8(i * 17); const z_raw = dataview.getUint8(i * 17);
const z = z_raw & 127; const z = z_raw & 127;
return { return {
z: z, z: z,
x: getUint24(dataview, i * 17 + 1), x: getUint24(dataview, i * 17 + 1),
y: getUint24(dataview, i * 17 + 4), y: getUint24(dataview, i * 17 + 4),
offset: getUint48(dataview, i * 17 + 7), offset: getUint48(dataview, i * 17 + 7),
length: dataview.getUint32(i * 17 + 13, true), length: dataview.getUint32(i * 17 + 13, true),
is_dir: z_raw >> 7 === 1, is_dir: z_raw >> 7 === 1,
}; };
}; };
export const sortDir = (a: ArrayBuffer): ArrayBuffer => { export const sortDir = (a: ArrayBuffer): ArrayBuffer => {
const entries: EntryV2[] = []; const entries: EntryV2[] = [];
const view = new DataView(a); const view = new DataView(a);
for (let i = 0; i < view.byteLength / 17; i++) { for (let i = 0; i < view.byteLength / 17; i++) {
entries.push(parseEntry(view, i)); entries.push(parseEntry(view, i));
} }
return createDirectory(entries); return createDirectory(entries);
}; };
export const createDirectory = (entries: EntryV2[]): ArrayBuffer => { export const createDirectory = (entries: EntryV2[]): ArrayBuffer => {
entries.sort(entrySort); entries.sort(entrySort);
const buffer = new ArrayBuffer(17 * entries.length); const buffer = new ArrayBuffer(17 * entries.length);
const arr = new Uint8Array(buffer); const arr = new Uint8Array(buffer);
for (let i = 0; i < entries.length; i++) { for (let i = 0; i < entries.length; i++) {
const entry = entries[i]; const entry = entries[i];
let z = entry.z; let z = entry.z;
if (entry.is_dir) z = z | 0x80; if (entry.is_dir) z = z | 0x80;
arr[i * 17] = z; arr[i * 17] = z;
arr[i * 17 + 1] = entry.x & 0xff; arr[i * 17 + 1] = entry.x & 0xff;
arr[i * 17 + 2] = (entry.x >> 8) & 0xff; arr[i * 17 + 2] = (entry.x >> 8) & 0xff;
arr[i * 17 + 3] = (entry.x >> 16) & 0xff; arr[i * 17 + 3] = (entry.x >> 16) & 0xff;
arr[i * 17 + 4] = entry.y & 0xff; arr[i * 17 + 4] = entry.y & 0xff;
arr[i * 17 + 5] = (entry.y >> 8) & 0xff; arr[i * 17 + 5] = (entry.y >> 8) & 0xff;
arr[i * 17 + 6] = (entry.y >> 16) & 0xff; arr[i * 17 + 6] = (entry.y >> 16) & 0xff;
arr[i * 17 + 7] = entry.offset & 0xff; arr[i * 17 + 7] = entry.offset & 0xff;
arr[i * 17 + 8] = unshift(entry.offset, 8) & 0xff; arr[i * 17 + 8] = unshift(entry.offset, 8) & 0xff;
arr[i * 17 + 9] = unshift(entry.offset, 16) & 0xff; arr[i * 17 + 9] = unshift(entry.offset, 16) & 0xff;
arr[i * 17 + 10] = unshift(entry.offset, 24) & 0xff; arr[i * 17 + 10] = unshift(entry.offset, 24) & 0xff;
arr[i * 17 + 11] = unshift(entry.offset, 32) & 0xff; arr[i * 17 + 11] = unshift(entry.offset, 32) & 0xff;
arr[i * 17 + 12] = unshift(entry.offset, 48) & 0xff; arr[i * 17 + 12] = unshift(entry.offset, 48) & 0xff;
arr[i * 17 + 13] = entry.length & 0xff; arr[i * 17 + 13] = entry.length & 0xff;
arr[i * 17 + 14] = (entry.length >> 8) & 0xff; arr[i * 17 + 14] = (entry.length >> 8) & 0xff;
arr[i * 17 + 15] = (entry.length >> 16) & 0xff; arr[i * 17 + 15] = (entry.length >> 16) & 0xff;
arr[i * 17 + 16] = (entry.length >> 24) & 0xff; arr[i * 17 + 16] = (entry.length >> 24) & 0xff;
} }
return buffer; return buffer;
}; };
export const deriveLeaf = (view: DataView, tile: Zxy): Zxy | null => { export const deriveLeaf = (view: DataView, tile: Zxy): Zxy | null => {
if (view.byteLength < 17) return null; if (view.byteLength < 17) return null;
const numEntries = view.byteLength / 17; const numEntries = view.byteLength / 17;
const entry = parseEntry(view, numEntries - 1); const entry = parseEntry(view, numEntries - 1);
if (entry.is_dir) { if (entry.is_dir) {
const leaf_level = entry.z; const leaf_level = entry.z;
const level_diff = tile.z - leaf_level; const level_diff = tile.z - leaf_level;
const leaf_x = Math.trunc(tile.x / (1 << level_diff)); const leaf_x = Math.trunc(tile.x / (1 << level_diff));
const leaf_y = Math.trunc(tile.y / (1 << level_diff)); const leaf_y = Math.trunc(tile.y / (1 << level_diff));
return { z: leaf_level, x: leaf_x, y: leaf_y }; return { z: leaf_level, x: leaf_x, y: leaf_y };
} }
return null; return null;
}; };
async function getHeader(source: Source): Promise<Header> { async function getHeader(source: Source): Promise<Header> {
const resp = await source.getBytes(0, 512000); const resp = await source.getBytes(0, 512000);
const dataview = new DataView(resp.data); const dataview = new DataView(resp.data);
const json_size = dataview.getUint32(4, true); const json_size = dataview.getUint32(4, true);
const root_entries = dataview.getUint16(8, true); const root_entries = dataview.getUint16(8, true);
const dec = new TextDecoder("utf-8"); const dec = new TextDecoder("utf-8");
const json_metadata = JSON.parse( const json_metadata = JSON.parse(
dec.decode(new DataView(resp.data, 10, json_size)) dec.decode(new DataView(resp.data, 10, json_size))
); );
let tile_compression = Compression.Unknown; let tile_compression = Compression.Unknown;
if (json_metadata.compression === "gzip") { if (json_metadata.compression === "gzip") {
tile_compression = Compression.Gzip; tile_compression = Compression.Gzip;
} }
let minzoom = 0; let minzoom = 0;
if ("minzoom" in json_metadata) { if ("minzoom" in json_metadata) {
minzoom = +json_metadata.minzoom; minzoom = +json_metadata.minzoom;
} }
let maxzoom = 0; let maxzoom = 0;
if ("maxzoom" in json_metadata) { if ("maxzoom" in json_metadata) {
maxzoom = +json_metadata.maxzoom; maxzoom = +json_metadata.maxzoom;
} }
let center_lon = 0; let center_lon = 0;
let center_lat = 0; let center_lat = 0;
let center_zoom = 0; let center_zoom = 0;
let min_lon = -180.0; let min_lon = -180.0;
let min_lat = -85.0; let min_lat = -85.0;
let max_lon = 180.0; let max_lon = 180.0;
let max_lat = 85.0; let max_lat = 85.0;
if (json_metadata.bounds) { if (json_metadata.bounds) {
const split = json_metadata.bounds.split(","); const split = json_metadata.bounds.split(",");
min_lon = +split[0]; min_lon = +split[0];
min_lat = +split[1]; min_lat = +split[1];
max_lon = +split[2]; max_lon = +split[2];
max_lat = +split[3]; max_lat = +split[3];
} }
if (json_metadata.center) { if (json_metadata.center) {
const split = json_metadata.center.split(","); const split = json_metadata.center.split(",");
center_lon = +split[0]; center_lon = +split[0];
center_lat = +split[1]; center_lat = +split[1];
center_zoom = +split[2]; center_zoom = +split[2];
} }
const header = { const header = {
specVersion: dataview.getUint16(2, true), specVersion: dataview.getUint16(2, true),
rootDirectoryOffset: 10 + json_size, rootDirectoryOffset: 10 + json_size,
rootDirectoryLength: root_entries * 17, rootDirectoryLength: root_entries * 17,
jsonMetadataOffset: 10, jsonMetadataOffset: 10,
jsonMetadataLength: json_size, jsonMetadataLength: json_size,
leafDirectoryOffset: 0, leafDirectoryOffset: 0,
leafDirectoryLength: undefined, leafDirectoryLength: undefined,
tileDataOffset: 0, tileDataOffset: 0,
tileDataLength: undefined, tileDataLength: undefined,
numAddressedTiles: 0, numAddressedTiles: 0,
numTileEntries: 0, numTileEntries: 0,
numTileContents: 0, numTileContents: 0,
clustered: false, clustered: false,
internalCompression: Compression.None, internalCompression: Compression.None,
tileCompression: tile_compression, tileCompression: tile_compression,
tileType: TileType.Mvt, tileType: TileType.Mvt,
minZoom: minzoom, minZoom: minzoom,
maxZoom: maxzoom, maxZoom: maxzoom,
minLon: min_lon, minLon: min_lon,
minLat: min_lat, minLat: min_lat,
maxLon: max_lon, maxLon: max_lon,
maxLat: max_lat, maxLat: max_lat,
centerZoom: center_zoom, centerZoom: center_zoom,
centerLon: center_lon, centerLon: center_lon,
centerLat: center_lat, centerLat: center_lat,
etag: resp.etag, etag: resp.etag,
}; };
return header; return header;
} }
async function getZxy( async function getZxy(
header: Header, header: Header,
source: Source, source: Source,
cache: Cache, cache: Cache,
z: number, z: number,
x: number, x: number,
y: number, y: number,
signal?: AbortSignal signal?: AbortSignal
): Promise<RangeResponse | undefined> { ): Promise<RangeResponse | undefined> {
let root_dir = await cache.getArrayBuffer( let root_dir = await cache.getArrayBuffer(
source, source,
header.rootDirectoryOffset, header.rootDirectoryOffset,
header.rootDirectoryLength, header.rootDirectoryLength,
header header
); );
if (header.specVersion === 1) { if (header.specVersion === 1) {
root_dir = sortDir(root_dir); root_dir = sortDir(root_dir);
} }
const entry = queryTile(new DataView(root_dir), z, x, y); const entry = queryTile(new DataView(root_dir), z, x, y);
if (entry) { if (entry) {
const resp = await source.getBytes(entry.offset, entry.length, signal); const resp = await source.getBytes(entry.offset, entry.length, signal);
let tile_data = resp.data; let tile_data = resp.data;
const view = new DataView(tile_data); const view = new DataView(tile_data);
if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) { if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) {
tile_data = decompressSync(new Uint8Array(tile_data)); tile_data = decompressSync(new Uint8Array(tile_data));
} }
return { return {
data: tile_data, data: tile_data,
}; };
} }
const leafcoords = deriveLeaf(new DataView(root_dir), { z: z, x: x, y: y }); const leafcoords = deriveLeaf(new DataView(root_dir), { z: z, x: x, y: y });
if (leafcoords) { if (leafcoords) {
const leafdir_entry = queryLeafdir( const leafdir_entry = queryLeafdir(
new DataView(root_dir), new DataView(root_dir),
leafcoords.z, leafcoords.z,
leafcoords.x, leafcoords.x,
leafcoords.y leafcoords.y
); );
if (leafdir_entry) { if (leafdir_entry) {
let leaf_dir = await cache.getArrayBuffer( let leaf_dir = await cache.getArrayBuffer(
source, source,
leafdir_entry.offset, leafdir_entry.offset,
leafdir_entry.length, leafdir_entry.length,
header header
); );
if (header.specVersion === 1) { if (header.specVersion === 1) {
leaf_dir = sortDir(leaf_dir); leaf_dir = sortDir(leaf_dir);
} }
const tile_entry = queryTile(new DataView(leaf_dir), z, x, y); const tile_entry = queryTile(new DataView(leaf_dir), z, x, y);
if (tile_entry) { if (tile_entry) {
const resp = await source.getBytes( const resp = await source.getBytes(
tile_entry.offset, tile_entry.offset,
tile_entry.length, tile_entry.length,
signal signal
); );
let tile_data = resp.data; let tile_data = resp.data;
const view = new DataView(tile_data); const view = new DataView(tile_data);
if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) { if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) {
tile_data = decompressSync(new Uint8Array(tile_data)); tile_data = decompressSync(new Uint8Array(tile_data));
} }
return { return {
data: tile_data, data: tile_data,
}; };
} }
} }
} }
return undefined; return undefined;
} }
export default { export default {
getHeader: getHeader, getHeader: getHeader,
getZxy: getZxy, getZxy: getZxy,
}; };