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.
Files changed (58) hide show
  1. package/README.md +322 -281
  2. package/dist/FIT/base.d.ts +61 -0
  3. package/dist/FIT/crc.d.ts +1 -0
  4. package/dist/FIT/decoder.d.ts +35 -0
  5. package/dist/FIT/encoder.d.ts +45 -0
  6. package/dist/FIT/index.d.ts +12 -0
  7. package/dist/FIT/mesg.d.ts +37 -0
  8. package/dist/FIT/middleware.d.ts +33 -0
  9. package/dist/FIT/plugins.d.ts +17 -0
  10. package/dist/FIT/processor.d.ts +34 -0
  11. package/dist/FIT/types/course_point.d.ts +56 -0
  12. package/dist/FIT/types/event.d.ts +49 -0
  13. package/dist/FIT/types/event_type.d.ts +18 -0
  14. package/dist/FIT/types/file.d.ts +23 -0
  15. package/dist/FIT/types/index.d.ts +119 -0
  16. package/dist/FIT/types/mesg_num.d.ts +105 -0
  17. package/dist/FIT/types/sport.d.ts +47 -0
  18. package/dist/FIT/types.d.ts +196 -0
  19. package/dist/FIT/util.d.ts +1 -0
  20. package/dist/GPX/base.d.ts +14 -77
  21. package/dist/GPX/converters.d.ts +12 -66
  22. package/dist/GPX/decoder.d.ts +5 -71
  23. package/dist/GPX/encoder.d.ts +4 -109
  24. package/dist/GPX/index.d.ts +1 -1
  25. package/dist/GPX/middleware.d.ts +18 -0
  26. package/dist/GPX/processor.d.ts +0 -18
  27. package/dist/GPX/types.d.ts +2 -111
  28. package/dist/TCX/base.d.ts +19 -0
  29. package/dist/TCX/converters.d.ts +51 -0
  30. package/dist/TCX/decoder.d.ts +33 -0
  31. package/dist/TCX/encoder.d.ts +41 -0
  32. package/dist/TCX/index.d.ts +13 -0
  33. package/dist/TCX/middleware.d.ts +18 -0
  34. package/dist/TCX/processor.d.ts +30 -0
  35. package/dist/TCX/types.d.ts +190 -0
  36. package/dist/TrackSwap.d.ts +37 -33
  37. package/dist/core/base.d.ts +73 -0
  38. package/dist/core/index.d.ts +2 -0
  39. package/dist/core/xml-utils.d.ts +17 -0
  40. package/dist/index.js +24 -5
  41. package/dist/sport/base.d.ts +63 -0
  42. package/dist/sport/converters.d.ts +33 -0
  43. package/dist/sport/encoders.d.ts +34 -0
  44. package/dist/sport/index.d.ts +17 -0
  45. package/dist/sport/processor.d.ts +19 -0
  46. package/dist/types.d.ts +91 -13
  47. package/package.json +25 -7
  48. package/dist/GPX/base.js +0 -83
  49. package/dist/GPX/converters.js +0 -444
  50. package/dist/GPX/decoder.js +0 -403
  51. package/dist/GPX/encoder.js +0 -510
  52. package/dist/GPX/extensions/index.js +0 -14
  53. package/dist/GPX/index.js +0 -11
  54. package/dist/GPX/processor.js +0 -187
  55. package/dist/GPX/types.js +0 -1
  56. package/dist/GPX/util.js +0 -18
  57. package/dist/TrackSwap.js +0 -84
  58. package/dist/types.js +0 -1
@@ -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
- }