trackswap 0.0.1 → 0.0.2
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/FIT/base.d.ts +91 -0
- package/dist/FIT/base.js +101 -0
- package/dist/FIT/crc.d.ts +1 -0
- package/dist/FIT/crc.js +16 -0
- package/dist/FIT/decoder.d.ts +83 -0
- package/dist/FIT/decoder.js +323 -0
- package/dist/FIT/encoder.d.ts +142 -0
- package/dist/FIT/encoder.js +445 -0
- package/dist/FIT/index.d.ts +12 -0
- package/dist/FIT/index.js +13 -0
- package/dist/FIT/mesg.d.ts +40 -0
- package/dist/FIT/mesg.js +208 -0
- package/dist/FIT/middleware.d.ts +48 -0
- package/dist/FIT/middleware.js +206 -0
- package/dist/FIT/plugins.d.ts +26 -0
- package/dist/FIT/plugins.js +104 -0
- package/dist/FIT/processor.d.ts +58 -0
- package/dist/FIT/processor.js +170 -0
- package/dist/FIT/types/course_point.d.ts +56 -0
- package/dist/FIT/types/course_point.js +58 -0
- package/dist/FIT/types/event.d.ts +49 -0
- package/dist/FIT/types/event.js +50 -0
- package/dist/FIT/types/event_type.d.ts +18 -0
- package/dist/FIT/types/event_type.js +19 -0
- package/dist/FIT/types/file.d.ts +23 -0
- package/dist/FIT/types/file.js +24 -0
- package/dist/FIT/types/index.d.ts +119 -0
- package/dist/FIT/types/index.js +297 -0
- package/dist/FIT/types/mesg_num.d.ts +105 -0
- package/dist/FIT/types/mesg_num.js +106 -0
- package/dist/FIT/types/sport.d.ts +47 -0
- package/dist/FIT/types/sport.js +48 -0
- package/dist/FIT/types.d.ts +231 -0
- package/dist/FIT/types.js +1 -0
- package/dist/FIT/util.d.ts +1 -0
- package/dist/FIT/util.js +7 -0
- package/dist/GPX/base.d.ts +43 -67
- package/dist/GPX/base.js +40 -67
- package/dist/GPX/converters.d.ts +12 -36
- package/dist/GPX/converters.js +11 -103
- package/dist/GPX/decoder.d.ts +5 -5
- package/dist/GPX/decoder.js +6 -0
- package/dist/GPX/encoder.d.ts +4 -0
- package/dist/GPX/encoder.js +3 -0
- package/dist/GPX/index.d.ts +1 -1
- package/dist/GPX/index.js +1 -1
- package/dist/GPX/middleware.d.ts +27 -0
- package/dist/GPX/middleware.js +93 -0
- package/dist/GPX/processor.d.ts +1 -1
- package/dist/GPX/processor.js +12 -11
- package/dist/GPX/types.d.ts +2 -3
- package/dist/TCX/base.d.ts +52 -0
- package/dist/TCX/base.js +62 -0
- package/dist/TCX/converters.d.ts +75 -0
- package/dist/TCX/converters.js +333 -0
- package/dist/TCX/decoder.d.ts +87 -0
- package/dist/TCX/decoder.js +350 -0
- package/dist/TCX/encoder.d.ts +150 -0
- package/dist/TCX/encoder.js +513 -0
- package/dist/TCX/index.d.ts +10 -0
- package/dist/TCX/index.js +9 -0
- package/dist/TCX/middleware.d.ts +27 -0
- package/dist/TCX/middleware.js +93 -0
- package/dist/TCX/processor.d.ts +48 -0
- package/dist/TCX/processor.js +197 -0
- package/dist/TCX/types.d.ts +203 -0
- package/dist/TCX/types.js +1 -0
- package/dist/core/base.d.ts +119 -0
- package/dist/core/base.js +138 -0
- package/dist/core/decoder.d.ts +66 -0
- package/dist/core/decoder.js +90 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +4 -0
- package/dist/core/processor.d.ts +69 -0
- package/dist/core/processor.js +265 -0
- package/dist/core/xml-utils.d.ts +41 -0
- package/dist/core/xml-utils.js +140 -0
- package/package.json +8 -5
package/dist/GPX/converters.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseGPXConverter } from "./base.js";
|
|
2
2
|
// ============ 核心转换器 ============
|
|
3
3
|
/**
|
|
4
4
|
* WPT转换器
|
|
5
5
|
*/
|
|
6
|
-
export class WptConverter extends
|
|
6
|
+
export class WptConverter extends BaseGPXConverter {
|
|
7
7
|
constructor() {
|
|
8
8
|
super(...arguments);
|
|
9
9
|
this.name = "wpt-converter";
|
|
@@ -67,7 +67,7 @@ export class WptConverter extends BaseConverter {
|
|
|
67
67
|
/**
|
|
68
68
|
* Route转换器
|
|
69
69
|
*/
|
|
70
|
-
export class RteConverter extends
|
|
70
|
+
export class RteConverter extends BaseGPXConverter {
|
|
71
71
|
constructor() {
|
|
72
72
|
super(...arguments);
|
|
73
73
|
this.name = "rte-converter";
|
|
@@ -114,7 +114,7 @@ export class RteConverter extends BaseConverter {
|
|
|
114
114
|
/**
|
|
115
115
|
* Track转换器
|
|
116
116
|
*/
|
|
117
|
-
export class TrkConverter extends
|
|
117
|
+
export class TrkConverter extends BaseGPXConverter {
|
|
118
118
|
constructor() {
|
|
119
119
|
super(...arguments);
|
|
120
120
|
this.name = "trk-converter";
|
|
@@ -161,7 +161,7 @@ export class TrkConverter extends BaseConverter {
|
|
|
161
161
|
/**
|
|
162
162
|
* Track Segment转换器
|
|
163
163
|
*/
|
|
164
|
-
export class TrksegConverter extends
|
|
164
|
+
export class TrksegConverter extends BaseGPXConverter {
|
|
165
165
|
constructor() {
|
|
166
166
|
super(...arguments);
|
|
167
167
|
this.name = "trkseg-converter";
|
|
@@ -190,7 +190,7 @@ export class TrksegConverter extends BaseConverter {
|
|
|
190
190
|
/**
|
|
191
191
|
* Link转换器
|
|
192
192
|
*/
|
|
193
|
-
export class LinkConverter extends
|
|
193
|
+
export class LinkConverter extends BaseGPXConverter {
|
|
194
194
|
constructor() {
|
|
195
195
|
super(...arguments);
|
|
196
196
|
this.name = "link-converter";
|
|
@@ -211,7 +211,7 @@ export class LinkConverter extends BaseConverter {
|
|
|
211
211
|
/**
|
|
212
212
|
* Metadata转换器
|
|
213
213
|
*/
|
|
214
|
-
export class MetadataConverter extends
|
|
214
|
+
export class MetadataConverter extends BaseGPXConverter {
|
|
215
215
|
constructor() {
|
|
216
216
|
super(...arguments);
|
|
217
217
|
this.name = "metadata-converter";
|
|
@@ -263,7 +263,7 @@ export class MetadataConverter extends BaseConverter {
|
|
|
263
263
|
/**
|
|
264
264
|
* Person转换器
|
|
265
265
|
*/
|
|
266
|
-
export class PersonConverter extends
|
|
266
|
+
export class PersonConverter extends BaseGPXConverter {
|
|
267
267
|
constructor() {
|
|
268
268
|
super(...arguments);
|
|
269
269
|
this.name = "person-converter";
|
|
@@ -294,7 +294,7 @@ export class PersonConverter extends BaseConverter {
|
|
|
294
294
|
/**
|
|
295
295
|
* Email转换器
|
|
296
296
|
*/
|
|
297
|
-
export class EmailConverter extends
|
|
297
|
+
export class EmailConverter extends BaseGPXConverter {
|
|
298
298
|
constructor() {
|
|
299
299
|
super(...arguments);
|
|
300
300
|
this.name = "email-converter";
|
|
@@ -312,7 +312,7 @@ export class EmailConverter extends BaseConverter {
|
|
|
312
312
|
/**
|
|
313
313
|
* Copyright转换器
|
|
314
314
|
*/
|
|
315
|
-
export class CopyrightConverter extends
|
|
315
|
+
export class CopyrightConverter extends BaseGPXConverter {
|
|
316
316
|
constructor() {
|
|
317
317
|
super(...arguments);
|
|
318
318
|
this.name = "copyright-converter";
|
|
@@ -333,7 +333,7 @@ export class CopyrightConverter extends BaseConverter {
|
|
|
333
333
|
/**
|
|
334
334
|
* Bounds转换器
|
|
335
335
|
*/
|
|
336
|
-
export class BoundsConverter extends
|
|
336
|
+
export class BoundsConverter extends BaseGPXConverter {
|
|
337
337
|
constructor() {
|
|
338
338
|
super(...arguments);
|
|
339
339
|
this.name = "bounds-converter";
|
|
@@ -350,95 +350,3 @@ export class BoundsConverter extends BaseConverter {
|
|
|
350
350
|
return bounds;
|
|
351
351
|
}
|
|
352
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
|
-
}
|
package/dist/GPX/decoder.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExtensionsType, TokenAST } from "../types.js";
|
|
2
|
-
import {
|
|
2
|
+
import { IGPXConverterPlugin, IGPXMiddlewarePlugin } from "./base.js";
|
|
3
3
|
import { GPX11Type } from "./types.js";
|
|
4
4
|
/**
|
|
5
5
|
* GPX解码器主类
|
|
@@ -27,19 +27,19 @@ export declare class GPXDecoder {
|
|
|
27
27
|
/**
|
|
28
28
|
* 注册转换器插件
|
|
29
29
|
*/
|
|
30
|
-
registerConverter(plugin:
|
|
30
|
+
registerConverter(plugin: IGPXConverterPlugin): Promise<void>;
|
|
31
31
|
/**
|
|
32
32
|
* 注册中间件插件 - 真正的扩展点
|
|
33
33
|
*/
|
|
34
|
-
registerMiddleware(plugin:
|
|
34
|
+
registerMiddleware(plugin: IGPXMiddlewarePlugin): Promise<void>;
|
|
35
35
|
/**
|
|
36
36
|
* 获取转换器(返回优先级最高的)
|
|
37
37
|
*/
|
|
38
|
-
getConverter(tag: string):
|
|
38
|
+
getConverter(tag: string): IGPXConverterPlugin | undefined;
|
|
39
39
|
/**
|
|
40
40
|
* 获取指定标签的所有转换器(按优先级排序)
|
|
41
41
|
*/
|
|
42
|
-
getAllConverters(tag: string):
|
|
42
|
+
getAllConverters(tag: string): IGPXConverterPlugin[];
|
|
43
43
|
/**
|
|
44
44
|
* 移除转换器
|
|
45
45
|
*/
|
package/dist/GPX/decoder.js
CHANGED
|
@@ -292,6 +292,12 @@ export class GPXDecoder {
|
|
|
292
292
|
return {
|
|
293
293
|
metadata: new Map(),
|
|
294
294
|
errors: [],
|
|
295
|
+
warnings: [],
|
|
296
|
+
stats: {
|
|
297
|
+
startTime: Date.now(),
|
|
298
|
+
processedTokens: 0,
|
|
299
|
+
convertedElements: 0,
|
|
300
|
+
},
|
|
295
301
|
performance: {
|
|
296
302
|
startTime: Date.now(),
|
|
297
303
|
},
|
package/dist/GPX/encoder.d.ts
CHANGED
package/dist/GPX/encoder.js
CHANGED
package/dist/GPX/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GPXDecoder } from "./decoder.js";
|
|
2
2
|
import { GPXEncoder } from "./encoder.js";
|
|
3
|
-
import { registerDefaultMiddlewares } from "./
|
|
3
|
+
import { registerDefaultMiddlewares } from "./middleware.js";
|
|
4
4
|
import { PipelineStage } from "./processor.js";
|
|
5
5
|
export { GPXDecoder, GPXEncoder, registerDefaultMiddlewares, PipelineStage };
|
|
6
6
|
declare const _default: {
|
package/dist/GPX/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GPXDecoder } from "./decoder.js";
|
|
2
2
|
import { GPXEncoder } from "./encoder.js";
|
|
3
|
-
import { registerDefaultMiddlewares } from "./
|
|
3
|
+
import { registerDefaultMiddlewares } from "./middleware.js";
|
|
4
4
|
import { PipelineStage } from "./processor.js";
|
|
5
5
|
export { GPXDecoder, GPXEncoder, registerDefaultMiddlewares, PipelineStage };
|
|
6
6
|
export default {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Token, TokenAST } from "../types";
|
|
2
|
+
import { BaseGPXMiddleware } from "./base";
|
|
3
|
+
import { DecoderContext } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* 性能监控中间件
|
|
6
|
+
*/
|
|
7
|
+
export declare class PerformanceMiddleware extends BaseGPXMiddleware {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
onTokenize(tokens: Token[], context: DecoderContext): Promise<Token[]>;
|
|
11
|
+
onAstGenerate(ast: TokenAST, context: DecoderContext): Promise<TokenAST>;
|
|
12
|
+
onComplete(result: any, context: DecoderContext): Promise<any>;
|
|
13
|
+
private countNodes;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 验证中间件
|
|
17
|
+
*/
|
|
18
|
+
export declare class ValidationMiddleware extends BaseGPXMiddleware {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
onComplete(result: any, context: DecoderContext): Promise<any>;
|
|
22
|
+
private validateGPX;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 注册所有默认中间件
|
|
26
|
+
*/
|
|
27
|
+
export declare function registerDefaultMiddlewares(decoder: any): Promise<void>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { BaseGPXMiddleware } from "./base";
|
|
2
|
+
// ============ 示例中间件 ============
|
|
3
|
+
/**
|
|
4
|
+
* 性能监控中间件
|
|
5
|
+
*/
|
|
6
|
+
export class PerformanceMiddleware extends BaseGPXMiddleware {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.name = "performance-middleware";
|
|
10
|
+
this.description = "监控解析性能";
|
|
11
|
+
}
|
|
12
|
+
async onTokenize(tokens, context) {
|
|
13
|
+
console.log(`Token化完成,生成了 ${tokens.length} 个token`);
|
|
14
|
+
return tokens;
|
|
15
|
+
}
|
|
16
|
+
async onAstGenerate(ast, context) {
|
|
17
|
+
const nodeCount = this.countNodes(ast);
|
|
18
|
+
console.log(`AST生成完成,包含 ${nodeCount} 个节点`);
|
|
19
|
+
return ast;
|
|
20
|
+
}
|
|
21
|
+
async onComplete(result, context) {
|
|
22
|
+
const performance = context.metadata.get("performance");
|
|
23
|
+
console.log("解析性能统计:", performance);
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
countNodes(ast) {
|
|
27
|
+
let count = 1;
|
|
28
|
+
if (ast.children) {
|
|
29
|
+
for (const child of ast.children) {
|
|
30
|
+
count += this.countNodes(child);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return count;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 验证中间件
|
|
38
|
+
*/
|
|
39
|
+
export class ValidationMiddleware extends BaseGPXMiddleware {
|
|
40
|
+
constructor() {
|
|
41
|
+
super(...arguments);
|
|
42
|
+
this.name = "validation-middleware";
|
|
43
|
+
this.description = "验证GPX数据的完整性";
|
|
44
|
+
}
|
|
45
|
+
async onComplete(result, context) {
|
|
46
|
+
const errors = this.validateGPX(result);
|
|
47
|
+
if (errors.length > 0) {
|
|
48
|
+
console.warn("GPX验证发现问题:", errors);
|
|
49
|
+
context.metadata.set("validation-errors", errors);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log("GPX验证通过");
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
validateGPX(gpx) {
|
|
57
|
+
const errors = [];
|
|
58
|
+
if (!gpx.version) {
|
|
59
|
+
errors.push("缺少GPX版本信息");
|
|
60
|
+
}
|
|
61
|
+
if (!gpx.creator) {
|
|
62
|
+
errors.push("缺少GPX创建者信息");
|
|
63
|
+
}
|
|
64
|
+
// 验证轨迹点
|
|
65
|
+
if (gpx.trk) {
|
|
66
|
+
for (const track of gpx.trk) {
|
|
67
|
+
if (track.trkseg) {
|
|
68
|
+
for (const segment of track.trkseg) {
|
|
69
|
+
if (segment.trkpt) {
|
|
70
|
+
for (const point of segment.trkpt) {
|
|
71
|
+
if (typeof point.lat !== "number" ||
|
|
72
|
+
typeof point.lon !== "number") {
|
|
73
|
+
errors.push("轨迹点坐标无效");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return errors;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// ============ 默认转换器注册函数 ============
|
|
85
|
+
/**
|
|
86
|
+
* 注册所有默认中间件
|
|
87
|
+
*/
|
|
88
|
+
export async function registerDefaultMiddlewares(decoder) {
|
|
89
|
+
const middlewares = [new PerformanceMiddleware(), new ValidationMiddleware()];
|
|
90
|
+
for (const middleware of middlewares) {
|
|
91
|
+
await decoder.registerMiddleware(middleware);
|
|
92
|
+
}
|
|
93
|
+
}
|
package/dist/GPX/processor.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface IPipelineProcessor {
|
|
|
16
16
|
process(context: DecoderContext): Promise<DecoderContext>;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* Tokenize
|
|
19
|
+
* Tokenize处理器, 将xml转为 token
|
|
20
20
|
*/
|
|
21
21
|
export declare class TokenizeProcessor implements IPipelineProcessor {
|
|
22
22
|
stage: PipelineStage;
|
package/dist/GPX/processor.js
CHANGED
|
@@ -10,7 +10,7 @@ export var PipelineStage;
|
|
|
10
10
|
PipelineStage["COMPLETE"] = "complete";
|
|
11
11
|
})(PipelineStage || (PipelineStage = {}));
|
|
12
12
|
/**
|
|
13
|
-
* Tokenize
|
|
13
|
+
* Tokenize处理器, 将xml转为 token
|
|
14
14
|
*/
|
|
15
15
|
export class TokenizeProcessor {
|
|
16
16
|
constructor() {
|
|
@@ -122,18 +122,19 @@ export class ConvertProcessor {
|
|
|
122
122
|
// 处理子节点
|
|
123
123
|
context.ast.children?.forEach((child) => {
|
|
124
124
|
const converter = this.getConverter(child.tag);
|
|
125
|
-
if (converter) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
catch (error) {
|
|
133
|
-
context.errors.push(error);
|
|
134
|
-
console.error(`转换器 ${converter.name} 处理标签 ${child.tag} 时出错:`, error);
|
|
125
|
+
if (!converter) {
|
|
126
|
+
console.error(`标签 ${child.tag} 未找到对应的 converter`);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const result = converter.convert(child, context);
|
|
130
|
+
if (result) {
|
|
131
|
+
this.assignResult(gpx, child.tag, result);
|
|
135
132
|
}
|
|
136
133
|
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
context.errors.push(error);
|
|
136
|
+
console.error(`转换器 ${converter.name} 处理标签 ${child.tag} 时出错:`, error);
|
|
137
|
+
}
|
|
137
138
|
});
|
|
138
139
|
context.result = gpx;
|
|
139
140
|
context.performance.convertTime = Date.now() - startTime;
|
package/dist/GPX/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DegreesType, ExtensionsType, LatitudeType, LongitudeType, Token, TokenAST } from "../types.js";
|
|
2
|
+
import { IProcessingContext } from "../core/base.js";
|
|
2
3
|
/**
|
|
3
4
|
* Two lat/lon pairs defining the extent of an element.
|
|
4
5
|
*/
|
|
@@ -211,14 +212,12 @@ export interface TrksegType {
|
|
|
211
212
|
trkpt?: WptType[];
|
|
212
213
|
extensions?: ExtensionsType;
|
|
213
214
|
}
|
|
214
|
-
export interface DecoderContext {
|
|
215
|
+
export interface DecoderContext extends IProcessingContext {
|
|
215
216
|
rawData?: Buffer;
|
|
216
217
|
xmlContent?: string;
|
|
217
218
|
tokens?: Token[];
|
|
218
219
|
ast?: TokenAST;
|
|
219
220
|
result?: GPX11Type;
|
|
220
|
-
metadata: Map<string, any>;
|
|
221
|
-
errors: Error[];
|
|
222
221
|
performance: {
|
|
223
222
|
startTime: number;
|
|
224
223
|
tokenizeTime?: number;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { IPlugin, IConverterPlugin, IMiddlewarePlugin, BaseConverter, BaseMiddleware } from "../core/base.js";
|
|
2
|
+
import { TCXContext, TCXFileType } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* TCX 插件接口(继承通用插件接口)
|
|
5
|
+
*/
|
|
6
|
+
export interface ITCXPlugin extends IPlugin<TCXContext> {
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* TCX 转换器插件接口(继承通用转换器接口)
|
|
10
|
+
*/
|
|
11
|
+
export interface ITCXConverterPlugin extends IConverterPlugin<TCXContext> {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* TCX 中间件插件接口(继承通用中间件接口)
|
|
15
|
+
*/
|
|
16
|
+
export interface ITCXMiddlewarePlugin extends IMiddlewarePlugin<TCXContext, TCXFileType> {
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* TCX 基础转换器抽象类(继承通用基础转换器)
|
|
20
|
+
*/
|
|
21
|
+
export declare abstract class BaseTCXConverter extends BaseConverter<TCXContext> implements ITCXConverterPlugin {
|
|
22
|
+
/**
|
|
23
|
+
* 解析 TCX 心率值
|
|
24
|
+
*/
|
|
25
|
+
protected parseHeartRate(value: string | number | undefined): number | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* 解析 TCX 时间格式(ISO 8601)
|
|
28
|
+
*/
|
|
29
|
+
protected parseTCXTime(value: string | undefined): Date | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* 解析 TCX 距离值(米)
|
|
32
|
+
*/
|
|
33
|
+
protected parseDistance(value: string | number | undefined): number | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* 解析 TCX 速度值(m/s)
|
|
36
|
+
*/
|
|
37
|
+
protected parseSpeed(value: string | number | undefined): number | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* 解析 TCX 海拔值(米)
|
|
40
|
+
*/
|
|
41
|
+
protected parseAltitude(value: string | number | undefined): number | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* 解析 TCX 坐标值(纬度/经度)
|
|
44
|
+
*/
|
|
45
|
+
protected parseCoordinate(value: string | number | undefined): number | undefined;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* TCX 基础中间件抽象类(继承通用基础中间件)
|
|
49
|
+
*/
|
|
50
|
+
export declare abstract class BaseTCXMiddleware extends BaseMiddleware<TCXContext, TCXFileType> implements ITCXMiddlewarePlugin {
|
|
51
|
+
onError(error: Error, context: TCXContext): Promise<void>;
|
|
52
|
+
}
|
package/dist/TCX/base.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { BaseConverter, BaseMiddleware, } from "../core/base.js";
|
|
2
|
+
// ============ TCX 特定基础类 ============
|
|
3
|
+
/**
|
|
4
|
+
* TCX 基础转换器抽象类(继承通用基础转换器)
|
|
5
|
+
*/
|
|
6
|
+
export class BaseTCXConverter extends BaseConverter {
|
|
7
|
+
// TCX 特定的工具方法可以在这里添加
|
|
8
|
+
/**
|
|
9
|
+
* 解析 TCX 心率值
|
|
10
|
+
*/
|
|
11
|
+
parseHeartRate(value) {
|
|
12
|
+
const hr = this.parseFloat(value);
|
|
13
|
+
return hr > 0 && hr < 300 ? hr : undefined; // 合理的心率范围
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 解析 TCX 时间格式(ISO 8601)
|
|
17
|
+
*/
|
|
18
|
+
parseTCXTime(value) {
|
|
19
|
+
if (!value)
|
|
20
|
+
return undefined;
|
|
21
|
+
// TCX 使用 ISO 8601 格式
|
|
22
|
+
const date = new Date(value);
|
|
23
|
+
return isNaN(date.getTime()) ? undefined : date;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 解析 TCX 距离值(米)
|
|
27
|
+
*/
|
|
28
|
+
parseDistance(value) {
|
|
29
|
+
const distance = this.parseFloat(value);
|
|
30
|
+
return distance >= 0 ? distance : undefined;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 解析 TCX 速度值(m/s)
|
|
34
|
+
*/
|
|
35
|
+
parseSpeed(value) {
|
|
36
|
+
const speed = this.parseFloat(value);
|
|
37
|
+
return speed >= 0 ? speed : undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 解析 TCX 海拔值(米)
|
|
41
|
+
*/
|
|
42
|
+
parseAltitude(value) {
|
|
43
|
+
return this.parseFloat(value);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 解析 TCX 坐标值(纬度/经度)
|
|
47
|
+
*/
|
|
48
|
+
parseCoordinate(value) {
|
|
49
|
+
const coord = this.parseFloat(value);
|
|
50
|
+
return coord !== 0 ? coord : undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* TCX 基础中间件抽象类(继承通用基础中间件)
|
|
55
|
+
*/
|
|
56
|
+
export class BaseTCXMiddleware extends BaseMiddleware {
|
|
57
|
+
// TCX 特定的中间件逻辑可以在这里添加
|
|
58
|
+
async onError(error, context) {
|
|
59
|
+
console.error(`TCX中间件 ${this.name} 处理错误:`, error);
|
|
60
|
+
context.warnings.push(`中间件 ${this.name} 错误: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { TokenAST } from "../types.js";
|
|
2
|
+
import { BaseTCXConverter } from "./base.js";
|
|
3
|
+
import { TCXContext, ActivityType, ActivityLapType, TrackType, TrackpointType, PositionType, ActivityListType, MultiSportSessionType, AbstractSourceType } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* 位置转换器
|
|
6
|
+
*/
|
|
7
|
+
export declare class PositionConverter extends BaseTCXConverter {
|
|
8
|
+
name: string;
|
|
9
|
+
supportedTags: string[];
|
|
10
|
+
convert(ast: TokenAST, context: TCXContext): PositionType | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 轨迹点转换器
|
|
14
|
+
*/
|
|
15
|
+
export declare class TrackpointConverter extends BaseTCXConverter {
|
|
16
|
+
name: string;
|
|
17
|
+
supportedTags: string[];
|
|
18
|
+
convert(ast: TokenAST, context: TCXContext): TrackpointType | undefined;
|
|
19
|
+
protected convertExtensions(extensionsAST: TokenAST): any;
|
|
20
|
+
protected convertExtensionContent(extension: TokenAST): any;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 轨迹转换器
|
|
24
|
+
*/
|
|
25
|
+
export declare class TrackConverter extends BaseTCXConverter {
|
|
26
|
+
name: string;
|
|
27
|
+
supportedTags: string[];
|
|
28
|
+
convert(ast: TokenAST, context: TCXContext): TrackType | undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 活动圈数转换器
|
|
32
|
+
*/
|
|
33
|
+
export declare class ActivityLapConverter extends BaseTCXConverter {
|
|
34
|
+
name: string;
|
|
35
|
+
supportedTags: string[];
|
|
36
|
+
convert(ast: TokenAST, context: TCXContext): ActivityLapType | undefined;
|
|
37
|
+
protected convertExtensions(extensionsAST: TokenAST): any;
|
|
38
|
+
protected convertExtensionContent(extension: TokenAST): any;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 活动转换器
|
|
42
|
+
*/
|
|
43
|
+
export declare class ActivityConverter extends BaseTCXConverter {
|
|
44
|
+
name: string;
|
|
45
|
+
supportedTags: string[];
|
|
46
|
+
convert(ast: TokenAST, context: TCXContext): ActivityType | undefined;
|
|
47
|
+
private convertTraining;
|
|
48
|
+
private convertCreator;
|
|
49
|
+
protected convertExtensions(extensionsAST: TokenAST): any;
|
|
50
|
+
protected convertExtensionContent(extension: TokenAST): any;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 活动列表转换器
|
|
54
|
+
*/
|
|
55
|
+
export declare class ActivityListConverter extends BaseTCXConverter {
|
|
56
|
+
name: string;
|
|
57
|
+
supportedTags: string[];
|
|
58
|
+
convert(ast: TokenAST, context: TCXContext): ActivityListType | undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 多运动会话转换器
|
|
62
|
+
*/
|
|
63
|
+
export declare class MultiSportSessionConverter extends BaseTCXConverter {
|
|
64
|
+
name: string;
|
|
65
|
+
supportedTags: string[];
|
|
66
|
+
convert(ast: TokenAST, context: TCXContext): MultiSportSessionType | undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 抽象来源转换器
|
|
70
|
+
*/
|
|
71
|
+
export declare class AbstractSourceConverter extends BaseTCXConverter {
|
|
72
|
+
name: string;
|
|
73
|
+
supportedTags: string[];
|
|
74
|
+
convert(ast: TokenAST, context: TCXContext): AbstractSourceType | undefined;
|
|
75
|
+
}
|