trackswap 0.0.1 → 0.0.3
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/README.md +322 -281
- package/dist/FIT/base.d.ts +61 -0
- package/dist/FIT/crc.d.ts +1 -0
- package/dist/FIT/decoder.d.ts +35 -0
- package/dist/FIT/encoder.d.ts +45 -0
- package/dist/FIT/index.d.ts +12 -0
- package/dist/FIT/mesg.d.ts +37 -0
- package/dist/FIT/middleware.d.ts +33 -0
- package/dist/FIT/plugins.d.ts +17 -0
- package/dist/FIT/processor.d.ts +34 -0
- package/dist/FIT/types/course_point.d.ts +56 -0
- package/dist/FIT/types/event.d.ts +49 -0
- package/dist/FIT/types/event_type.d.ts +18 -0
- package/dist/FIT/types/file.d.ts +23 -0
- package/dist/FIT/types/index.d.ts +119 -0
- package/dist/FIT/types/mesg_num.d.ts +105 -0
- package/dist/FIT/types/sport.d.ts +47 -0
- package/dist/FIT/types.d.ts +196 -0
- package/dist/FIT/util.d.ts +1 -0
- package/dist/GPX/base.d.ts +14 -77
- package/dist/GPX/converters.d.ts +12 -66
- package/dist/GPX/decoder.d.ts +5 -71
- package/dist/GPX/encoder.d.ts +4 -109
- package/dist/GPX/index.d.ts +1 -1
- package/dist/GPX/middleware.d.ts +18 -0
- package/dist/GPX/processor.d.ts +0 -18
- package/dist/GPX/types.d.ts +2 -111
- package/dist/TCX/base.d.ts +19 -0
- package/dist/TCX/converters.d.ts +51 -0
- package/dist/TCX/decoder.d.ts +33 -0
- package/dist/TCX/encoder.d.ts +41 -0
- package/dist/TCX/index.d.ts +13 -0
- package/dist/TCX/middleware.d.ts +18 -0
- package/dist/TCX/processor.d.ts +30 -0
- package/dist/TCX/types.d.ts +190 -0
- package/dist/TrackSwap.d.ts +37 -33
- package/dist/core/base.d.ts +73 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/xml-utils.d.ts +17 -0
- package/dist/index.js +24 -5
- package/dist/sport/base.d.ts +63 -0
- package/dist/sport/converters.d.ts +33 -0
- package/dist/sport/encoders.d.ts +34 -0
- package/dist/sport/index.d.ts +17 -0
- package/dist/sport/processor.d.ts +19 -0
- package/dist/types.d.ts +91 -13
- package/package.json +25 -7
- package/dist/GPX/base.js +0 -83
- package/dist/GPX/converters.js +0 -444
- package/dist/GPX/decoder.js +0 -403
- package/dist/GPX/encoder.js +0 -510
- package/dist/GPX/extensions/index.js +0 -14
- package/dist/GPX/index.js +0 -11
- package/dist/GPX/processor.js +0 -187
- package/dist/GPX/types.js +0 -1
- package/dist/GPX/util.js +0 -18
- package/dist/TrackSwap.js +0 -84
- package/dist/types.js +0 -1
package/dist/GPX/converters.js
DELETED
|
@@ -1,444 +0,0 @@
|
|
|
1
|
-
import { BaseConverter, BaseMiddleware } from "./base.js";
|
|
2
|
-
// ============ 核心转换器 ============
|
|
3
|
-
/**
|
|
4
|
-
* WPT转换器
|
|
5
|
-
*/
|
|
6
|
-
export class WptConverter extends BaseConverter {
|
|
7
|
-
constructor() {
|
|
8
|
-
super(...arguments);
|
|
9
|
-
this.name = "wpt-converter";
|
|
10
|
-
this.supportedTags = ["wpt", "trkpt", "rtept"];
|
|
11
|
-
this.version = "1.0.0";
|
|
12
|
-
}
|
|
13
|
-
convert(ast, context) {
|
|
14
|
-
if (!this.hasRequiredAttributes(ast, ["lat", "lon"])) {
|
|
15
|
-
console.error(`${this.name}: 缺少必需的lat或lon属性`);
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
const wpt = {
|
|
19
|
-
lat: this.parseFloat(ast.attributes["lat"]),
|
|
20
|
-
lon: this.parseFloat(ast.attributes["lon"]),
|
|
21
|
-
};
|
|
22
|
-
// 处理其他属性
|
|
23
|
-
this.extractAttributes(ast, wpt, {
|
|
24
|
-
lat: "lat",
|
|
25
|
-
lon: "lon",
|
|
26
|
-
});
|
|
27
|
-
// 处理子节点
|
|
28
|
-
this.processChildren(ast, wpt, {
|
|
29
|
-
ele: (child, target) => (target.ele = this.parseFloat(child.value)),
|
|
30
|
-
time: (child, target) => (target.time = new Date(this.parseString(child.value))),
|
|
31
|
-
speed: (child, target) => (target.speed = this.parseFloat(child.value)),
|
|
32
|
-
course: (child, target) => (target.course = this.parseFloat(child.value)),
|
|
33
|
-
name: (child, target) => (target.name = this.parseString(child.value)),
|
|
34
|
-
cmt: (child, target) => (target.cmt = this.parseString(child.value)),
|
|
35
|
-
desc: (child, target) => (target.desc = this.parseString(child.value)),
|
|
36
|
-
src: (child, target) => (target.src = this.parseString(child.value)),
|
|
37
|
-
sym: (child, target) => (target.sym = this.parseString(child.value)),
|
|
38
|
-
type: (child, target) => (target.type = this.parseString(child.value)),
|
|
39
|
-
fix: (child, target) => (target.fix = this.parseString(child.value)),
|
|
40
|
-
sat: (child, target) => (target.sat = this.parseString(child.value)),
|
|
41
|
-
hdop: (child, target) => (target.hdop = this.parseFloat(child.value)),
|
|
42
|
-
vdop: (child, target) => (target.vdop = this.parseFloat(child.value)),
|
|
43
|
-
pdop: (child, target) => (target.pdop = this.parseFloat(child.value)),
|
|
44
|
-
ageofdgpsdata: (child, target) => (target.ageofdgpsdata = this.parseFloat(child.value)),
|
|
45
|
-
geoidheight: (child, target) => (target.geoidheight = this.parseFloat(child.value)),
|
|
46
|
-
magvar: (child, target) => (target.magvar = this.parseFloat(child.value)),
|
|
47
|
-
dgpsid: (child, target) => (target.dgpsid = this.parseFloat(child.value)),
|
|
48
|
-
extensions: (child, target) => {
|
|
49
|
-
// 查找extensions转换器
|
|
50
|
-
const decoder = context.metadata.get("decoder");
|
|
51
|
-
if (decoder) {
|
|
52
|
-
target.extensions = decoder.convertExtensions(child);
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
link: (child, target) => {
|
|
56
|
-
if (!target.link)
|
|
57
|
-
target.link = [];
|
|
58
|
-
const decoder = context.metadata.get("decoder");
|
|
59
|
-
const link = decoder?.getConverter("link")?.convert(child, context);
|
|
60
|
-
if (link && target.link)
|
|
61
|
-
target.link.push(link);
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
return wpt;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Route转换器
|
|
69
|
-
*/
|
|
70
|
-
export class RteConverter extends BaseConverter {
|
|
71
|
-
constructor() {
|
|
72
|
-
super(...arguments);
|
|
73
|
-
this.name = "rte-converter";
|
|
74
|
-
this.supportedTags = ["rte"];
|
|
75
|
-
}
|
|
76
|
-
convert(ast, context) {
|
|
77
|
-
const rte = { rtept: [] };
|
|
78
|
-
this.processChildren(ast, rte, {
|
|
79
|
-
name: (child, target) => (target.name = this.parseString(child.value)),
|
|
80
|
-
cmt: (child, target) => (target.cmt = this.parseString(child.value)),
|
|
81
|
-
desc: (child, target) => (target.desc = this.parseString(child.value)),
|
|
82
|
-
src: (child, target) => (target.src = this.parseString(child.value)),
|
|
83
|
-
number: (child, target) => (target.number = this.parseFloat(child.value)),
|
|
84
|
-
type: (child, target) => (target.type = this.parseString(child.value)),
|
|
85
|
-
rtept: (child, target) => {
|
|
86
|
-
const decoder = context.metadata.get("decoder");
|
|
87
|
-
const wpt = decoder?.getConverter("wpt")?.convert(child, context);
|
|
88
|
-
if (wpt && target.rtept) {
|
|
89
|
-
target.rtept.push(wpt);
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
extensions: (child, target) => {
|
|
93
|
-
const decoder = context.metadata.get("decoder");
|
|
94
|
-
if (decoder) {
|
|
95
|
-
target.extensions = decoder.convertExtensions(child);
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
link: (child, target) => {
|
|
99
|
-
if (!target.link)
|
|
100
|
-
target.link = [];
|
|
101
|
-
const decoder = context.metadata.get("decoder");
|
|
102
|
-
child.children?.forEach((linkChild) => {
|
|
103
|
-
const link = decoder
|
|
104
|
-
?.getConverter("link")
|
|
105
|
-
?.convert(linkChild, context);
|
|
106
|
-
if (link && target.link)
|
|
107
|
-
target.link.push(link);
|
|
108
|
-
});
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
return rte;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Track转换器
|
|
116
|
-
*/
|
|
117
|
-
export class TrkConverter extends BaseConverter {
|
|
118
|
-
constructor() {
|
|
119
|
-
super(...arguments);
|
|
120
|
-
this.name = "trk-converter";
|
|
121
|
-
this.supportedTags = ["trk"];
|
|
122
|
-
}
|
|
123
|
-
convert(ast, context) {
|
|
124
|
-
const trk = { trkseg: [] };
|
|
125
|
-
this.processChildren(ast, trk, {
|
|
126
|
-
name: (child, target) => (target.name = this.parseString(child.value)),
|
|
127
|
-
cmt: (child, target) => (target.cmt = this.parseString(child.value)),
|
|
128
|
-
desc: (child, target) => (target.desc = this.parseString(child.value)),
|
|
129
|
-
src: (child, target) => (target.src = this.parseString(child.value)),
|
|
130
|
-
number: (child, target) => (target.number = this.parseFloat(child.value)),
|
|
131
|
-
type: (child, target) => (target.type = this.parseString(child.value)),
|
|
132
|
-
trkseg: (child, target) => {
|
|
133
|
-
const decoder = context.metadata.get("decoder");
|
|
134
|
-
const trkseg = decoder?.getConverter("trkseg")?.convert(child, context);
|
|
135
|
-
if (trkseg && target.trkseg) {
|
|
136
|
-
target.trkseg.push(trkseg);
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
extensions: (child, target) => {
|
|
140
|
-
const decoder = context.metadata.get("decoder");
|
|
141
|
-
if (decoder) {
|
|
142
|
-
target.extensions = decoder.convertExtensions(child);
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
link: (child, target) => {
|
|
146
|
-
if (!target.link)
|
|
147
|
-
target.link = [];
|
|
148
|
-
const decoder = context.metadata.get("decoder");
|
|
149
|
-
child.children?.forEach((linkChild) => {
|
|
150
|
-
const link = decoder
|
|
151
|
-
?.getConverter("link")
|
|
152
|
-
?.convert(linkChild, context);
|
|
153
|
-
if (link && target.link)
|
|
154
|
-
target.link.push(link);
|
|
155
|
-
});
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
return trk;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Track Segment转换器
|
|
163
|
-
*/
|
|
164
|
-
export class TrksegConverter extends BaseConverter {
|
|
165
|
-
constructor() {
|
|
166
|
-
super(...arguments);
|
|
167
|
-
this.name = "trkseg-converter";
|
|
168
|
-
this.supportedTags = ["trkseg"];
|
|
169
|
-
}
|
|
170
|
-
convert(ast, context) {
|
|
171
|
-
const trkseg = { trkpt: [] };
|
|
172
|
-
this.processChildren(ast, trkseg, {
|
|
173
|
-
trkpt: (child, target) => {
|
|
174
|
-
const decoder = context.metadata.get("decoder");
|
|
175
|
-
const wpt = decoder?.getConverter("wpt")?.convert(child, context);
|
|
176
|
-
if (wpt && target.trkpt) {
|
|
177
|
-
target.trkpt.push(wpt);
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
extensions: (child, target) => {
|
|
181
|
-
const decoder = context.metadata.get("decoder");
|
|
182
|
-
if (decoder) {
|
|
183
|
-
target.extensions = decoder.convertExtensions(child);
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
});
|
|
187
|
-
return trkseg;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Link转换器
|
|
192
|
-
*/
|
|
193
|
-
export class LinkConverter extends BaseConverter {
|
|
194
|
-
constructor() {
|
|
195
|
-
super(...arguments);
|
|
196
|
-
this.name = "link-converter";
|
|
197
|
-
this.supportedTags = ["link"];
|
|
198
|
-
}
|
|
199
|
-
convert(ast, context) {
|
|
200
|
-
const link = {};
|
|
201
|
-
if (ast.attributes?.href) {
|
|
202
|
-
link.href = ast.attributes.href;
|
|
203
|
-
}
|
|
204
|
-
this.processChildren(ast, link, {
|
|
205
|
-
text: (child, target) => (target.text = this.parseString(child.value)),
|
|
206
|
-
type: (child, target) => (target.type = this.parseString(child.value)),
|
|
207
|
-
});
|
|
208
|
-
return link;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Metadata转换器
|
|
213
|
-
*/
|
|
214
|
-
export class MetadataConverter extends BaseConverter {
|
|
215
|
-
constructor() {
|
|
216
|
-
super(...arguments);
|
|
217
|
-
this.name = "metadata-converter";
|
|
218
|
-
this.supportedTags = ["metadata"];
|
|
219
|
-
}
|
|
220
|
-
convert(ast, context) {
|
|
221
|
-
const metadata = {};
|
|
222
|
-
this.processChildren(ast, metadata, {
|
|
223
|
-
name: (child, target) => (target.name = this.parseString(child.value)),
|
|
224
|
-
desc: (child, target) => (target.desc = this.parseString(child.value)),
|
|
225
|
-
keywords: (child, target) => (target.keywords = this.parseString(child.value)),
|
|
226
|
-
time: (child, target) => (target.time = new Date(this.parseString(child.value))),
|
|
227
|
-
author: (child, target) => {
|
|
228
|
-
const decoder = context.metadata.get("decoder");
|
|
229
|
-
target.author = decoder
|
|
230
|
-
?.getConverter("author")
|
|
231
|
-
?.convert(child, context);
|
|
232
|
-
},
|
|
233
|
-
copyright: (child, target) => {
|
|
234
|
-
const decoder = context.metadata.get("decoder");
|
|
235
|
-
target.copyright = decoder
|
|
236
|
-
?.getConverter("copyright")
|
|
237
|
-
?.convert(child, context);
|
|
238
|
-
},
|
|
239
|
-
bounds: (child, target) => {
|
|
240
|
-
const decoder = context.metadata.get("decoder");
|
|
241
|
-
target.bounds = decoder
|
|
242
|
-
?.getConverter("bounds")
|
|
243
|
-
?.convert(child, context);
|
|
244
|
-
},
|
|
245
|
-
extensions: (child, target) => {
|
|
246
|
-
const decoder = context.metadata.get("decoder");
|
|
247
|
-
if (decoder) {
|
|
248
|
-
target.extensions = decoder.convertExtensions(child);
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
link: (child, target) => {
|
|
252
|
-
if (!target.link)
|
|
253
|
-
target.link = [];
|
|
254
|
-
const decoder = context.metadata.get("decoder");
|
|
255
|
-
const link = decoder?.getConverter("link")?.convert(child, context);
|
|
256
|
-
if (link && target.link)
|
|
257
|
-
target.link.push(link);
|
|
258
|
-
},
|
|
259
|
-
});
|
|
260
|
-
return metadata;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Person转换器
|
|
265
|
-
*/
|
|
266
|
-
export class PersonConverter extends BaseConverter {
|
|
267
|
-
constructor() {
|
|
268
|
-
super(...arguments);
|
|
269
|
-
this.name = "person-converter";
|
|
270
|
-
this.supportedTags = ["author"];
|
|
271
|
-
}
|
|
272
|
-
convert(ast, context) {
|
|
273
|
-
const person = {};
|
|
274
|
-
// 如果author标签直接包含文本值(如 <author>Matschi1000</author>)
|
|
275
|
-
if (ast.value && !ast.children?.length) {
|
|
276
|
-
person.name = this.parseString(ast.value);
|
|
277
|
-
return person;
|
|
278
|
-
}
|
|
279
|
-
// 处理包含子元素的情况(如 <author><name>...</name><email>...</email></author>)
|
|
280
|
-
this.processChildren(ast, person, {
|
|
281
|
-
name: (child, target) => (target.name = this.parseString(child.value)),
|
|
282
|
-
email: (child, target) => {
|
|
283
|
-
const decoder = context.metadata.get("decoder");
|
|
284
|
-
target.email = decoder?.getConverter("email")?.convert(child, context);
|
|
285
|
-
},
|
|
286
|
-
link: (child, target) => {
|
|
287
|
-
const decoder = context.metadata.get("decoder");
|
|
288
|
-
target.link = decoder?.getConverter("link")?.convert(child, context);
|
|
289
|
-
},
|
|
290
|
-
});
|
|
291
|
-
return person;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Email转换器
|
|
296
|
-
*/
|
|
297
|
-
export class EmailConverter extends BaseConverter {
|
|
298
|
-
constructor() {
|
|
299
|
-
super(...arguments);
|
|
300
|
-
this.name = "email-converter";
|
|
301
|
-
this.supportedTags = ["email"];
|
|
302
|
-
}
|
|
303
|
-
convert(ast, context) {
|
|
304
|
-
const email = {};
|
|
305
|
-
this.processChildren(ast, email, {
|
|
306
|
-
id: (child, target) => (target.id = this.parseString(child.value)),
|
|
307
|
-
domain: (child, target) => (target.domain = this.parseString(child.value)),
|
|
308
|
-
});
|
|
309
|
-
return email;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Copyright转换器
|
|
314
|
-
*/
|
|
315
|
-
export class CopyrightConverter extends BaseConverter {
|
|
316
|
-
constructor() {
|
|
317
|
-
super(...arguments);
|
|
318
|
-
this.name = "copyright-converter";
|
|
319
|
-
this.supportedTags = ["copyright"];
|
|
320
|
-
}
|
|
321
|
-
convert(ast, context) {
|
|
322
|
-
const copyright = {};
|
|
323
|
-
if (ast.attributes?.author) {
|
|
324
|
-
copyright.author = ast.attributes.author;
|
|
325
|
-
}
|
|
326
|
-
this.processChildren(ast, copyright, {
|
|
327
|
-
year: (child, target) => (target.year = this.parseString(child.value)),
|
|
328
|
-
license: (child, target) => (target.license = this.parseString(child.value)),
|
|
329
|
-
});
|
|
330
|
-
return copyright;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Bounds转换器
|
|
335
|
-
*/
|
|
336
|
-
export class BoundsConverter extends BaseConverter {
|
|
337
|
-
constructor() {
|
|
338
|
-
super(...arguments);
|
|
339
|
-
this.name = "bounds-converter";
|
|
340
|
-
this.supportedTags = ["bounds"];
|
|
341
|
-
}
|
|
342
|
-
convert(ast, context) {
|
|
343
|
-
const bounds = {};
|
|
344
|
-
this.extractAttributes(ast, bounds, {
|
|
345
|
-
minlat: "minlat",
|
|
346
|
-
minlon: "minlon",
|
|
347
|
-
maxlat: "maxlat",
|
|
348
|
-
maxlon: "maxlon",
|
|
349
|
-
});
|
|
350
|
-
return bounds;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
// ============ 示例中间件 ============
|
|
354
|
-
/**
|
|
355
|
-
* 性能监控中间件
|
|
356
|
-
*/
|
|
357
|
-
export class PerformanceMiddleware extends BaseMiddleware {
|
|
358
|
-
constructor() {
|
|
359
|
-
super(...arguments);
|
|
360
|
-
this.name = "performance-middleware";
|
|
361
|
-
this.description = "监控解析性能";
|
|
362
|
-
}
|
|
363
|
-
async onTokenize(tokens, context) {
|
|
364
|
-
console.log(`Token化完成,生成了 ${tokens.length} 个token`);
|
|
365
|
-
return tokens;
|
|
366
|
-
}
|
|
367
|
-
async onAstGenerate(ast, context) {
|
|
368
|
-
const nodeCount = this.countNodes(ast);
|
|
369
|
-
console.log(`AST生成完成,包含 ${nodeCount} 个节点`);
|
|
370
|
-
return ast;
|
|
371
|
-
}
|
|
372
|
-
async onComplete(result, context) {
|
|
373
|
-
const performance = context.metadata.get("performance");
|
|
374
|
-
console.log("解析性能统计:", performance);
|
|
375
|
-
return result;
|
|
376
|
-
}
|
|
377
|
-
countNodes(ast) {
|
|
378
|
-
let count = 1;
|
|
379
|
-
if (ast.children) {
|
|
380
|
-
for (const child of ast.children) {
|
|
381
|
-
count += this.countNodes(child);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return count;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* 验证中间件
|
|
389
|
-
*/
|
|
390
|
-
export class ValidationMiddleware extends BaseMiddleware {
|
|
391
|
-
constructor() {
|
|
392
|
-
super(...arguments);
|
|
393
|
-
this.name = "validation-middleware";
|
|
394
|
-
this.description = "验证GPX数据的完整性";
|
|
395
|
-
}
|
|
396
|
-
async onComplete(result, context) {
|
|
397
|
-
const errors = this.validateGPX(result);
|
|
398
|
-
if (errors.length > 0) {
|
|
399
|
-
console.warn("GPX验证发现问题:", errors);
|
|
400
|
-
context.metadata.set("validation-errors", errors);
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
console.log("GPX验证通过");
|
|
404
|
-
}
|
|
405
|
-
return result;
|
|
406
|
-
}
|
|
407
|
-
validateGPX(gpx) {
|
|
408
|
-
const errors = [];
|
|
409
|
-
if (!gpx.version) {
|
|
410
|
-
errors.push("缺少GPX版本信息");
|
|
411
|
-
}
|
|
412
|
-
if (!gpx.creator) {
|
|
413
|
-
errors.push("缺少GPX创建者信息");
|
|
414
|
-
}
|
|
415
|
-
// 验证轨迹点
|
|
416
|
-
if (gpx.trk) {
|
|
417
|
-
for (const track of gpx.trk) {
|
|
418
|
-
if (track.trkseg) {
|
|
419
|
-
for (const segment of track.trkseg) {
|
|
420
|
-
if (segment.trkpt) {
|
|
421
|
-
for (const point of segment.trkpt) {
|
|
422
|
-
if (typeof point.lat !== "number" ||
|
|
423
|
-
typeof point.lon !== "number") {
|
|
424
|
-
errors.push("轨迹点坐标无效");
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return errors;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
// ============ 默认转换器注册函数 ============
|
|
436
|
-
/**
|
|
437
|
-
* 注册所有默认中间件
|
|
438
|
-
*/
|
|
439
|
-
export async function registerDefaultMiddlewares(decoder) {
|
|
440
|
-
const middlewares = [new PerformanceMiddleware(), new ValidationMiddleware()];
|
|
441
|
-
for (const middleware of middlewares) {
|
|
442
|
-
await decoder.registerMiddleware(middleware);
|
|
443
|
-
}
|
|
444
|
-
}
|