parse-tmx 3.2.0 → 3.3.0
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.
- package/dist/index.d.ts +19 -24
- package/dist/index.js +59 -72
- package/package.json +6 -9
package/dist/index.d.ts
CHANGED
|
@@ -265,6 +265,11 @@ export interface TMXPropertyNode extends TMXNode<{
|
|
|
265
265
|
_: string;
|
|
266
266
|
}
|
|
267
267
|
//#endregion
|
|
268
|
+
//#region src/models/tmx/node/TMXPropertiesElement.d.ts
|
|
269
|
+
export interface TMXPropertiesElement {
|
|
270
|
+
property: TMXPropertyNode[];
|
|
271
|
+
}
|
|
272
|
+
//#endregion
|
|
268
273
|
//#region src/models/tmx/node/TMXPropertiesNode.d.ts
|
|
269
274
|
export interface TMXPropertiesNode extends TMXNode<Record<string, never>, TMXPropertyNode> {}
|
|
270
275
|
//#endregion
|
|
@@ -278,9 +283,7 @@ export interface TMXObjectNode extends TMXNode<TMXObjectShared, TMXDataNode | TM
|
|
|
278
283
|
polygon?: TMXNode<{
|
|
279
284
|
points: string;
|
|
280
285
|
}>[];
|
|
281
|
-
properties?:
|
|
282
|
-
property: TMXPropertyNode[];
|
|
283
|
-
}[];
|
|
286
|
+
properties?: TMXPropertiesElement[];
|
|
284
287
|
text?: TMXTextNode[];
|
|
285
288
|
}
|
|
286
289
|
//#endregion
|
|
@@ -288,9 +291,7 @@ export interface TMXObjectNode extends TMXNode<TMXObjectShared, TMXDataNode | TM
|
|
|
288
291
|
export interface TMXTileNode extends TMXNode<TMXTileShared, TMXPropertiesNode> {
|
|
289
292
|
animation?: Record<string, TMXNode<number>[]>[];
|
|
290
293
|
objectgroup?: Record<string, TMXObjectNode[]>[];
|
|
291
|
-
properties?:
|
|
292
|
-
property: TMXPropertyNode[];
|
|
293
|
-
}[];
|
|
294
|
+
properties?: TMXPropertiesElement[];
|
|
294
295
|
}
|
|
295
296
|
//#endregion
|
|
296
297
|
//#region src/models/tmx/node/TMXEmbeddedTilesetNode.d.ts
|
|
@@ -304,6 +305,9 @@ export declare const checkIsTMXEmbeddedTilesetNode: (node: TMXDataNode | TMXEmbe
|
|
|
304
305
|
//#region src/services/cloneNodeWithType.d.ts
|
|
305
306
|
export declare const cloneNodeWithType: <TParsed>(node: BaseTMXNode<unknown>) => TParsed;
|
|
306
307
|
//#endregion
|
|
308
|
+
//#region src/services/decodeTileData.d.ts
|
|
309
|
+
export declare const decodeTileData: (nodeData: TMXDataNode | TMXEmbeddedTilesetNode) => Promise<number[]>;
|
|
310
|
+
//#endregion
|
|
307
311
|
//#region src/services/getDecompressedBytes.d.ts
|
|
308
312
|
export declare const getDecompressedBytes: (bytes: Uint8Array<ArrayBuffer>, compression: Compression.Gzip | Compression.Zlib) => Promise<Uint8Array<ArrayBuffer>>;
|
|
309
313
|
//#endregion
|
|
@@ -315,26 +319,19 @@ export interface TMXLayerNode extends TMXNode<TMXLayerShared, TMXDataNode | TMXE
|
|
|
315
319
|
data?: TMXDataNode[] | TMXEmbeddedTilesetNode[];
|
|
316
320
|
image?: TMXImageNode[];
|
|
317
321
|
object?: TMXObjectNode[];
|
|
318
|
-
properties?:
|
|
319
|
-
property: TMXPropertyNode[];
|
|
320
|
-
}[];
|
|
322
|
+
properties?: TMXPropertiesElement[];
|
|
321
323
|
}
|
|
322
324
|
//#endregion
|
|
325
|
+
//#region src/services/parseLayer.d.ts
|
|
326
|
+
export declare const parseLayer: (node: TMXLayerNode) => TMXLayerParsed;
|
|
327
|
+
//#endregion
|
|
323
328
|
//#region src/models/tmx/node/TMXGroupLayerNode.d.ts
|
|
324
329
|
export interface TMXGroupLayerNode extends TMXNode<TMXGroupLayerShared, TMXLayerNode> {
|
|
325
|
-
properties?:
|
|
326
|
-
property: TMXPropertyNode[];
|
|
327
|
-
}[];
|
|
330
|
+
properties?: TMXPropertiesElement[];
|
|
328
331
|
}
|
|
329
332
|
//#endregion
|
|
330
|
-
//#region src/services/parseGroup.d.ts
|
|
331
|
-
export declare const parseGroup: (node: TMXGroupLayerNode, expectedCount: number, translateFlips: boolean) => Promise<TMXGroupLayerParsed>;
|
|
332
|
-
//#endregion
|
|
333
|
-
//#region src/services/parseLayer.d.ts
|
|
334
|
-
export declare const parseLayer: (node: TMXLayerNode) => TMXLayerParsed;
|
|
335
|
-
//#endregion
|
|
336
333
|
//#region src/services/parseNode.d.ts
|
|
337
|
-
export declare const parseNode: <TNode extends TMXGroupLayerNode | TMXLayerNode, TParsedNode = TNode extends TMXLayerNode ? TMXLayerParsed : TMXGroupLayerParsed>(node: TNode,
|
|
334
|
+
export declare const parseNode: <TNode extends TMXGroupLayerNode | TMXLayerNode, TParsedNode = TNode extends TMXLayerNode ? TMXLayerParsed : TMXGroupLayerParsed>(node: TNode, tileCount: number, translateFlips: boolean) => Promise<TParsedNode>;
|
|
338
335
|
//#endregion
|
|
339
336
|
//#region src/services/parseObject.d.ts
|
|
340
337
|
export declare const parseObject: (node: TMXObjectNode) => TMXObjectParsed;
|
|
@@ -343,9 +340,7 @@ export declare const parseObject: (node: TMXObjectNode) => TMXObjectParsed;
|
|
|
343
340
|
export declare const parseObjectShape: (node: TMXObjectNode) => Shape;
|
|
344
341
|
//#endregion
|
|
345
342
|
//#region src/services/parseProperties.d.ts
|
|
346
|
-
export declare const parseProperties: (properties:
|
|
347
|
-
property: TMXPropertyNode[];
|
|
348
|
-
}[]) => TMXPropertiesParsed;
|
|
343
|
+
export declare const parseProperties: (properties: TMXPropertiesElement[]) => TMXPropertiesParsed;
|
|
349
344
|
//#endregion
|
|
350
345
|
//#region src/services/parseTile.d.ts
|
|
351
346
|
export declare const parseTile: (node: TMXTileNode) => TMXTileParsed;
|
|
@@ -354,7 +349,7 @@ export declare const parseTile: (node: TMXTileNode) => TMXTileParsed;
|
|
|
354
349
|
export declare const parseTileId: (gid: number) => number;
|
|
355
350
|
//#endregion
|
|
356
351
|
//#region src/services/parseTileLayer.d.ts
|
|
357
|
-
export declare const parseTileLayer: (node: TMXLayerNode,
|
|
352
|
+
export declare const parseTileLayer: (node: TMXLayerNode, tileCount: number, translateFlips: boolean) => Promise<TMXLayerParsed>;
|
|
358
353
|
//#endregion
|
|
359
354
|
//#region src/models/tmx/node/TMXExternalTilesetNode.d.ts
|
|
360
355
|
export interface TMXExternalTilesetNode extends TMXNode<TMXExternalTilesetShared> {}
|
|
@@ -372,7 +367,7 @@ export declare const parseXmlString: <T extends object>(xmlString: string) => Pr
|
|
|
372
367
|
export declare const parseXmlValue: (value: string) => boolean | number | string;
|
|
373
368
|
//#endregion
|
|
374
369
|
//#region src/services/unpackTileBytes.d.ts
|
|
375
|
-
export declare const unpackTileBytes: (bytes: Uint8Array
|
|
370
|
+
export declare const unpackTileBytes: (bytes: Uint8Array) => number[];
|
|
376
371
|
//#endregion
|
|
377
372
|
//#region src/models/tmx/node/TMXExportNode.d.ts
|
|
378
373
|
export interface TMXExportNode extends TMXNode<TMXExportShared> {}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { InvalidOperationError, Operation, exhaustiveGuard, normalizeString, takeOne } from "@esposter/shared";
|
|
2
2
|
import { parseStringPromise } from "@esposter/xml2js";
|
|
3
|
-
import parseDataUrl from "data-urls";
|
|
4
3
|
//#region src/models/tmx/node/TMXNodeType.ts
|
|
5
4
|
let TMXNodeType = /* @__PURE__ */ function(TMXNodeType) {
|
|
6
5
|
TMXNodeType["Data"] = "data";
|
|
@@ -55,17 +54,9 @@ var TMXParsed = class {
|
|
|
55
54
|
//#endregion
|
|
56
55
|
//#region src/services/cloneNodeWithType.ts
|
|
57
56
|
const cloneNodeWithType = (node) => {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
return
|
|
61
|
-
};
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/services/parseGroup.ts
|
|
64
|
-
const parseGroup = async (node, expectedCount, translateFlips) => {
|
|
65
|
-
const { $$ } = node;
|
|
66
|
-
const group = cloneNodeWithType(node);
|
|
67
|
-
group.layers = await Promise.all($$.map((l) => parseNode(l, expectedCount, translateFlips)));
|
|
68
|
-
return group;
|
|
57
|
+
const attributes = structuredClone(node.$);
|
|
58
|
+
attributes.type = node["#name"];
|
|
59
|
+
return attributes;
|
|
69
60
|
};
|
|
70
61
|
//#endregion
|
|
71
62
|
//#region src/models/Flipped.ts
|
|
@@ -143,7 +134,7 @@ const parseLayer = (node) => {
|
|
|
143
134
|
const { image, object, properties } = node;
|
|
144
135
|
const layer = cloneNodeWithType(node);
|
|
145
136
|
if (image) layer.image = structuredClone(takeOne(image).$);
|
|
146
|
-
if (object) layer.objects = object.map((
|
|
137
|
+
if (object) layer.objects = object.map((objectNode) => parseObject(objectNode));
|
|
147
138
|
if (properties) layer.properties = parseProperties(properties);
|
|
148
139
|
return layer;
|
|
149
140
|
};
|
|
@@ -173,63 +164,64 @@ const getDecompressedBytes = async (bytes, compression) => {
|
|
|
173
164
|
};
|
|
174
165
|
//#endregion
|
|
175
166
|
//#region src/services/unpackTileBytes.ts
|
|
176
|
-
const unpackTileBytes = (bytes
|
|
177
|
-
if (bytes.byteLength !==
|
|
167
|
+
const unpackTileBytes = (bytes) => {
|
|
168
|
+
if (bytes.byteLength % Uint32Array.BYTES_PER_ELEMENT !== 0) throw new InvalidOperationError(Operation.Read, "TMXLayer", `expected whole ${Uint32Array.BYTES_PER_ELEMENT}-byte tiles, received ${bytes.byteLength} bytes`);
|
|
178
169
|
const unpackedTiles = [];
|
|
179
170
|
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
180
|
-
for (let
|
|
171
|
+
for (let byteIndex = 0; byteIndex < bytes.byteLength; byteIndex += Uint32Array.BYTES_PER_ELEMENT) unpackedTiles.push(dataView.getUint32(byteIndex, true));
|
|
181
172
|
return unpackedTiles;
|
|
182
173
|
};
|
|
183
174
|
//#endregion
|
|
175
|
+
//#region src/services/decodeTileData.ts
|
|
176
|
+
const decodeTileData = async (nodeData) => {
|
|
177
|
+
if (checkIsTMXEmbeddedTilesetNode(nodeData)) return nodeData.tile?.map(({ $ }) => $.gid ?? 0) ?? [];
|
|
178
|
+
const { $, _ } = nodeData;
|
|
179
|
+
const { compression, encoding } = $;
|
|
180
|
+
const layerData = normalizeString(_);
|
|
181
|
+
switch (encoding) {
|
|
182
|
+
case "base64": {
|
|
183
|
+
const bytes = Uint8Array.fromBase64(layerData);
|
|
184
|
+
switch (compression) {
|
|
185
|
+
case "gzip":
|
|
186
|
+
case "zlib": return unpackTileBytes(await getDecompressedBytes(bytes, compression));
|
|
187
|
+
case void 0: return unpackTileBytes(bytes);
|
|
188
|
+
default: return exhaustiveGuard(compression);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
case "csv": return layerData.split(",").map(Number);
|
|
192
|
+
default: return exhaustiveGuard(encoding);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
//#endregion
|
|
184
196
|
//#region src/services/parseTileLayer.ts
|
|
185
|
-
const parseTileLayer = async (node,
|
|
197
|
+
const parseTileLayer = async (node, tileCount, translateFlips) => {
|
|
186
198
|
const { data, properties } = node;
|
|
187
199
|
if (!data) throw new InvalidOperationError(Operation.Read, "TMXLayer", "data is missing");
|
|
188
200
|
const layer = cloneNodeWithType(node);
|
|
189
201
|
if (properties) layer.properties = parseProperties(properties);
|
|
190
202
|
const nodeData = takeOne(data);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const { $, _ } = nodeData;
|
|
194
|
-
const { compression, encoding } = $;
|
|
195
|
-
const layerData = normalizeString(_);
|
|
196
|
-
switch (encoding) {
|
|
197
|
-
case "base64": {
|
|
198
|
-
const bytes = Uint8Array.fromBase64(layerData);
|
|
199
|
-
switch (compression) {
|
|
200
|
-
case "gzip":
|
|
201
|
-
case "zlib":
|
|
202
|
-
layer.data = unpackTileBytes(await getDecompressedBytes(bytes, compression), expectedCount);
|
|
203
|
-
break;
|
|
204
|
-
case void 0:
|
|
205
|
-
layer.data = unpackTileBytes(bytes, expectedCount);
|
|
206
|
-
break;
|
|
207
|
-
default: exhaustiveGuard(compression);
|
|
208
|
-
}
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
case "csv":
|
|
212
|
-
layer.data = layerData.split(",").map(Number);
|
|
213
|
-
break;
|
|
214
|
-
default: exhaustiveGuard(encoding);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
203
|
+
const tiles = await decodeTileData(nodeData);
|
|
204
|
+
if (tiles.length !== tileCount) throw new InvalidOperationError(Operation.Read, "TMXLayer", `expected ${tileCount} tiles, received ${tiles.length}`);
|
|
217
205
|
if (translateFlips) {
|
|
218
|
-
layer.data
|
|
219
|
-
layer.flips =
|
|
220
|
-
|
|
221
|
-
}
|
|
206
|
+
layer.data = tiles.map((gid) => parseTileId(gid));
|
|
207
|
+
layer.flips = tiles.map((gid) => parseFlips(gid));
|
|
208
|
+
} else layer.data = tiles;
|
|
222
209
|
return layer;
|
|
223
210
|
};
|
|
224
211
|
//#endregion
|
|
225
212
|
//#region src/services/parseNode.ts
|
|
226
|
-
const
|
|
213
|
+
const parseGroup = async (node, tileCount, translateFlips) => {
|
|
214
|
+
const group = cloneNodeWithType(node);
|
|
215
|
+
group.layers = await Promise.all(node.$$.map((layerNode) => parseNode(layerNode, tileCount, translateFlips)));
|
|
216
|
+
return group;
|
|
217
|
+
};
|
|
218
|
+
const parseNode = (node, tileCount, translateFlips) => {
|
|
227
219
|
const tmxNodeType = node["#name"];
|
|
228
220
|
switch (tmxNodeType) {
|
|
229
|
-
case "group": return parseGroup(node,
|
|
221
|
+
case "group": return parseGroup(node, tileCount, translateFlips);
|
|
230
222
|
case "imagelayer":
|
|
231
223
|
case "objectgroup": return Promise.resolve(parseLayer(node));
|
|
232
|
-
case "layer": return parseTileLayer(node,
|
|
224
|
+
case "layer": return parseTileLayer(node, tileCount, translateFlips);
|
|
233
225
|
default: throw new InvalidOperationError(Operation.Read, parseNode.name, tmxNodeType);
|
|
234
226
|
}
|
|
235
227
|
};
|
|
@@ -251,17 +243,15 @@ const parseTile = (node) => {
|
|
|
251
243
|
const parseTileset = (node) => {
|
|
252
244
|
if (checkIsExternalTileset(node.$)) return structuredClone(node.$);
|
|
253
245
|
const { $, $$, tile } = node;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
throw new InvalidOperationError(Operation.Read, parseTileset.name, $.name);
|
|
246
|
+
const imageNode = $$.find((childNode) => childNode["#name"] === "image");
|
|
247
|
+
if (!imageNode) throw new InvalidOperationError(Operation.Read, parseTileset.name, $.name);
|
|
248
|
+
const image = structuredClone(imageNode.$);
|
|
249
|
+
const tiles = tile?.map((tileNode) => parseTile(tileNode)) ?? [];
|
|
250
|
+
return {
|
|
251
|
+
...$,
|
|
252
|
+
image,
|
|
253
|
+
tiles
|
|
254
|
+
};
|
|
265
255
|
};
|
|
266
256
|
//#endregion
|
|
267
257
|
//#region src/services/parseXmlValue.ts
|
|
@@ -274,20 +264,17 @@ const parseXmlValue = (value) => {
|
|
|
274
264
|
};
|
|
275
265
|
//#endregion
|
|
276
266
|
//#region src/services/parseXmlString.ts
|
|
277
|
-
const parseXmlString = (xmlString) => {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
preserveChildrenOrder: true
|
|
283
|
-
});
|
|
284
|
-
};
|
|
267
|
+
const parseXmlString = (xmlString) => parseStringPromise(xmlString, {
|
|
268
|
+
attrValueProcessors: [(value) => parseXmlValue(value)],
|
|
269
|
+
explicitChildren: true,
|
|
270
|
+
preserveChildrenOrder: true
|
|
271
|
+
});
|
|
285
272
|
//#endregion
|
|
286
273
|
//#region src/parseTmx.ts
|
|
287
274
|
const parseTmx = async (xmlString, translateFlips = false) => {
|
|
288
275
|
const { map: { $, $$ } } = await parseXmlString(xmlString);
|
|
289
276
|
const map = new TMXMapParsed($);
|
|
290
|
-
const
|
|
277
|
+
const tileCount = map.width * map.height;
|
|
291
278
|
for (const node of $$) {
|
|
292
279
|
const tmxNodeType = node["#name"];
|
|
293
280
|
switch (tmxNodeType) {
|
|
@@ -304,7 +291,7 @@ const parseTmx = async (xmlString, translateFlips = false) => {
|
|
|
304
291
|
case "imagelayer":
|
|
305
292
|
case "layer":
|
|
306
293
|
case "objectgroup": {
|
|
307
|
-
const layer = await parseNode(node,
|
|
294
|
+
const layer = await parseNode(node, tileCount, translateFlips);
|
|
308
295
|
map.layers.push(layer);
|
|
309
296
|
break;
|
|
310
297
|
}
|
|
@@ -327,4 +314,4 @@ var BaseTMXNode = class {
|
|
|
327
314
|
$;
|
|
328
315
|
};
|
|
329
316
|
//#endregion
|
|
330
|
-
export { BaseTMXNode, Compression, Encoding, Flipped, Flippeds, Shape, TMXMapParsed, TMXMapShared, TMXNodeType, TMXParsed, checkIsExternalTileset, checkIsTMXEmbeddedTilesetNode, cloneNodeWithType, getDecompressedBytes, parseFlips,
|
|
317
|
+
export { BaseTMXNode, Compression, Encoding, Flipped, Flippeds, Shape, TMXMapParsed, TMXMapShared, TMXNodeType, TMXParsed, checkIsExternalTileset, checkIsTMXEmbeddedTilesetNode, cloneNodeWithType, decodeTileData, getDecompressedBytes, parseFlips, parseLayer, parseNode, parseObject, parseObjectShape, parseProperties, parseTile, parseTileId, parseTileLayer, parseTileset, parseTmx, parseXmlString, parseXmlValue, unpackTileBytes };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "parse-tmx",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "A parser for tmx.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"game-development",
|
|
@@ -52,19 +52,16 @@
|
|
|
52
52
|
"typecheck": "tsc"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@esposter/shared": "3.
|
|
56
|
-
"@esposter/xml2js": "3.
|
|
57
|
-
"data-urls": "^7.0.0"
|
|
55
|
+
"@esposter/shared": "3.3.0",
|
|
56
|
+
"@esposter/xml2js": "3.3.0"
|
|
58
57
|
},
|
|
59
58
|
"devDependencies": {
|
|
60
59
|
"@arethetypeswrong/core": "^0.18.5",
|
|
61
|
-
"@esposter/configuration": "3.
|
|
62
|
-
"@types/data-urls": "^3.0.5",
|
|
63
|
-
"@types/xml2js": "^0.4.14",
|
|
60
|
+
"@esposter/configuration": "3.3.0",
|
|
64
61
|
"publint": "^0.3.24",
|
|
65
62
|
"tsdown": "^0.23.0",
|
|
66
63
|
"type-fest": "^5.10.0",
|
|
67
|
-
"vitest": "^5.0.
|
|
64
|
+
"vitest": "^5.0.2"
|
|
68
65
|
},
|
|
69
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "5854a00717502d8de96adc8b44d3621ab85f9b57"
|
|
70
67
|
}
|