maplibre-tilepackage-protocol 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ import globals from "globals";
2
+ import pluginJs from "@eslint/js";
3
+
4
+ /** @type {import('eslint').Linter.Config[]} */
5
+ export default [
6
+ {
7
+ rules: {
8
+ semi: "error",
9
+ "no-var": "error",
10
+ "prefer-const": "error",
11
+ },
12
+ languageOptions: {
13
+ ecmaVersion: 2017,
14
+ sourceType: "module",
15
+ globals: globals.browser,
16
+ },
17
+ plugins: {
18
+ prettier: {
19
+ "prettier/prettier": "error",
20
+ //"linebreak-style": ["error", "windows"],
21
+ "no-console": ["error", { allow: ["info", "warn", "error"] }],
22
+ "no-unused-vars": ["error", { vars: "all", args: "none" }],
23
+ semi: ["error", "always"],
24
+ },
25
+ },
26
+ },
27
+ pluginJs.configs.recommended,
28
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maplibre-tilepackage-protocol",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Maplibre-gl-js protocol for reading VTPK and TPKX files",
5
5
  "homepage": "https://github.com/spatialillusions/maplibre-tilepackage-protocol#readme",
6
6
  "bugs": {
@@ -40,4 +40,4 @@
40
40
  "require": "./src/index.js"
41
41
  }
42
42
  }
43
- }
43
+ }
@@ -12,16 +12,23 @@ export default async function defaultDecompress(buf, compression) {
12
12
  return buf;
13
13
  }
14
14
  if (compression === "gzip") {
15
- if (typeof globalThis.DecompressionStream === "undefined") {
15
+ // Safe global detection for DecompressionStream feature test
16
+ const g =
17
+ typeof globalThis !== "undefined"
18
+ ? globalThis
19
+ : typeof window !== "undefined"
20
+ ? window
21
+ : typeof self !== "undefined"
22
+ ? self
23
+ : {};
24
+ if (typeof g.DecompressionStream === "undefined") {
16
25
  return fflate.decompressSync(new Uint8Array(buf));
17
26
  }
18
27
  const stream = new Response(buf).body;
19
28
  if (!stream) {
20
29
  throw new Error("Failed to read response stream");
21
30
  }
22
- const result = stream.pipeThrough(
23
- new globalThis.DecompressionStream("gzip"),
24
- );
31
+ const result = stream.pipeThrough(new g.DecompressionStream("gzip"));
25
32
  return new Response(result).arrayBuffer();
26
33
  }
27
34
  throw new Error("Compression method not supported");
package/src/index.js CHANGED
@@ -6,13 +6,23 @@ import defaultDecompress from "./default-decompress.js";
6
6
  import getJsonFromFile from "./get-json-from-file.js";
7
7
  import SharedPromiseCache from "./shared-promise-cache.js";
8
8
 
9
+ /**
10
+ * Escape literal newlines in JSON text.
11
+ * Replaces actual newline characters with the JSON escape sequence.
12
+ */
13
+ function escapeJsonNewlines(text) {
14
+ // Replace literal newlines with JSON escape sequences
15
+ // This handles \r\n, \n, and \r
16
+ return text.replace(/\r\n/g, "\\n").replace(/[\r\n]/g, "\\n");
17
+ }
18
+
9
19
  function calculateFilename(z, x, y, header) {
10
20
  const zoom = z.toString().padStart(2, "0");
11
21
  const baseRow = Math.floor(y / 128) * 128;
12
22
  const baseCol = Math.floor(x / 128) * 128;
13
23
  const rowHex = baseRow.toString(16).padStart(4, "0");
14
24
  const colHex = baseCol.toString(16).padStart(4, "0");
15
- let basePath = header.type === "tpkx" ? "tile" : "p12/tile";
25
+ const basePath = header.type === "tpkx" ? "tile" : "p12/tile";
16
26
  return `${basePath}/L${zoom}/R${rowHex}C${colHex}.bundle`;
17
27
  }
18
28
 
@@ -172,13 +182,16 @@ export class TilePackage {
172
182
  let metadata = {};
173
183
  if (header.packageType === "vtpk") {
174
184
  const resp = await this.source.getBytes(
175
- header.jsonMetadataOffset,
176
- header.jsonMetadataLength,
185
+ header.metadataOffset,
186
+ header.metadataLength,
177
187
  undefined,
178
188
  header.etag,
179
189
  );
180
190
  const decoder = new TextDecoder("utf-8");
181
- metadata = JSON.parse(decoder.decode(resp.data));
191
+ const jsonText = decoder.decode(resp.data);
192
+ console.log("test", jsonText);
193
+ console.log("escaped text", escapeJsonNewlines(jsonText));
194
+ metadata = JSON.parse(escapeJsonNewlines(jsonText));
182
195
  }
183
196
  metadata.name = header.name;
184
197
  return metadata;
package/src/source.js CHANGED
@@ -56,9 +56,18 @@ export class FetchSource extends Source {
56
56
  this.url = url;
57
57
  this.customHeaders = customHeaders;
58
58
  this.mustReload = false;
59
+ // Safe global detection for legacy environments without globalThis
60
+ const g =
61
+ typeof globalThis !== "undefined"
62
+ ? globalThis
63
+ : typeof window !== "undefined"
64
+ ? window
65
+ : typeof self !== "undefined"
66
+ ? self
67
+ : {};
59
68
  let userAgent = "";
60
- if ("navigator" in globalThis) {
61
- userAgent = globalThis.navigator.userAgent || "";
69
+ if (g && typeof g.navigator !== "undefined") {
70
+ userAgent = g.navigator.userAgent || "";
62
71
  }
63
72
  const isWindows = userAgent.indexOf("Windows") > -1;
64
73
  const isChromiumBased = /Chrome|Chromium|Edg|OPR|Brave/.test(userAgent);