metar-taf-parser 4.0.0 → 4.0.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.
- package/metar-taf-parser.js +80 -24
- package/package.json +3 -3
package/metar-taf-parser.js
CHANGED
|
@@ -87,7 +87,7 @@ function pySplit(string, separator, n) {
|
|
|
87
87
|
*/
|
|
88
88
|
function resolve(obj, path, separator = ".") {
|
|
89
89
|
const properties = Array.isArray(path) ? path : path.split(separator);
|
|
90
|
-
return properties.reduce((prev, curr) => prev
|
|
90
|
+
return properties.reduce((prev, curr) => prev?.[curr], obj);
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
93
|
* For safely casting input values
|
|
@@ -1537,7 +1537,7 @@ class DefaultCommand extends Command {
|
|
|
1537
1537
|
}
|
|
1538
1538
|
else {
|
|
1539
1539
|
const lastRemark = remark[remark.length - 1];
|
|
1540
|
-
if (
|
|
1540
|
+
if (lastRemark?.type === RemarkType.Unknown) {
|
|
1541
1541
|
// Merge with last unknown value
|
|
1542
1542
|
lastRemark.raw = `${lastRemark.raw} ${rmkSplit[0]}`;
|
|
1543
1543
|
}
|
|
@@ -1562,13 +1562,12 @@ class PrecipitationBegCommand extends Command {
|
|
|
1562
1562
|
return __classPrivateFieldGet(this, _PrecipitationBegCommand_regex, "f").test(code);
|
|
1563
1563
|
}
|
|
1564
1564
|
execute(code, remark) {
|
|
1565
|
-
var _a;
|
|
1566
1565
|
const matches = code.match(__classPrivateFieldGet(this, _PrecipitationBegCommand_regex, "f"));
|
|
1567
1566
|
if (!matches)
|
|
1568
1567
|
throw new UnexpectedParseError("Match not found");
|
|
1569
1568
|
const descriptive = matches[2] ? as(matches[2], Descriptive) : undefined;
|
|
1570
1569
|
const phenomenon = as(matches[3], Phenomenon);
|
|
1571
|
-
const description =
|
|
1570
|
+
const description = format(_("Remark.Precipitation.Beg.0", this.locale), descriptive ? _(`Descriptive.${descriptive}`, this.locale) : "", _(`Phenomenon.${phenomenon}`, this.locale), matches[4] || "", matches[5])?.trim();
|
|
1572
1571
|
remark.push({
|
|
1573
1572
|
type: RemarkType.PrecipitationBeg,
|
|
1574
1573
|
description,
|
|
@@ -1593,13 +1592,12 @@ class PrecipitationEndCommand extends Command {
|
|
|
1593
1592
|
return __classPrivateFieldGet(this, _PrecipitationEndCommand_regex, "f").test(code);
|
|
1594
1593
|
}
|
|
1595
1594
|
execute(code, remark) {
|
|
1596
|
-
var _a;
|
|
1597
1595
|
const matches = code.match(__classPrivateFieldGet(this, _PrecipitationEndCommand_regex, "f"));
|
|
1598
1596
|
if (!matches)
|
|
1599
1597
|
throw new UnexpectedParseError("Match not found");
|
|
1600
1598
|
const descriptive = matches[2] ? as(matches[2], Descriptive) : undefined;
|
|
1601
1599
|
const phenomenon = as(matches[3], Phenomenon);
|
|
1602
|
-
const description =
|
|
1600
|
+
const description = format(_("Remark.Precipitation.End", this.locale), descriptive ? _(`Descriptive.${descriptive}`, this.locale) : "", _(`Phenomenon.${phenomenon}`, this.locale), matches[4] || "", matches[5])?.trim();
|
|
1603
1601
|
remark.push({
|
|
1604
1602
|
type: RemarkType.PrecipitationEnd,
|
|
1605
1603
|
description,
|
|
@@ -1790,7 +1788,7 @@ class MainVisibilityCommand {
|
|
|
1790
1788
|
const distance = convertVisibility(matches[1]);
|
|
1791
1789
|
if (!container.visibility)
|
|
1792
1790
|
container.visibility = distance;
|
|
1793
|
-
container.visibility =
|
|
1791
|
+
container.visibility = { ...container.visibility, ...distance };
|
|
1794
1792
|
if (matches[2] === "NDV")
|
|
1795
1793
|
container.visibility.ndv = true;
|
|
1796
1794
|
return true;
|
|
@@ -1850,7 +1848,10 @@ class WindShearCommand {
|
|
|
1850
1848
|
const matches = windString.match(__classPrivateFieldGet(this, _WindShearCommand_regex, "f"));
|
|
1851
1849
|
if (!matches)
|
|
1852
1850
|
throw new UnexpectedParseError("Wind shear should be defined");
|
|
1853
|
-
return
|
|
1851
|
+
return {
|
|
1852
|
+
...makeWind(matches[2], matches[3], matches[4], matches[5]),
|
|
1853
|
+
height: 100 * +matches[1],
|
|
1854
|
+
};
|
|
1854
1855
|
}
|
|
1855
1856
|
execute(container, windString) {
|
|
1856
1857
|
container.windShear = this.parseWindShear(windString);
|
|
@@ -2140,10 +2141,9 @@ class AbstractParser {
|
|
|
2140
2141
|
_AbstractParser_commonSupplier.set(this, new CommandSupplier$1());
|
|
2141
2142
|
}
|
|
2142
2143
|
parseWeatherCondition(input) {
|
|
2143
|
-
var _a;
|
|
2144
2144
|
let intensity;
|
|
2145
2145
|
if (input.match(__classPrivateFieldGet(this, _AbstractParser_INTENSITY_REGEX, "f"))) {
|
|
2146
|
-
const match =
|
|
2146
|
+
const match = input.match(__classPrivateFieldGet(this, _AbstractParser_INTENSITY_REGEX, "f"))?.[0];
|
|
2147
2147
|
if (match)
|
|
2148
2148
|
intensity = match;
|
|
2149
2149
|
}
|
|
@@ -2262,7 +2262,16 @@ class MetarParser extends AbstractParser {
|
|
|
2262
2262
|
*/
|
|
2263
2263
|
parse(input) {
|
|
2264
2264
|
const metarTab = this.tokenize(input);
|
|
2265
|
-
const metar =
|
|
2265
|
+
const metar = {
|
|
2266
|
+
...parseDeliveryTime(metarTab[1]),
|
|
2267
|
+
station: metarTab[0],
|
|
2268
|
+
message: input,
|
|
2269
|
+
remarks: [],
|
|
2270
|
+
clouds: [],
|
|
2271
|
+
weatherConditions: [],
|
|
2272
|
+
trends: [],
|
|
2273
|
+
runwaysInfo: [],
|
|
2274
|
+
};
|
|
2266
2275
|
let index = 2;
|
|
2267
2276
|
while (index < metarTab.length) {
|
|
2268
2277
|
if (!super.generalParse(metar, metarTab[index])) {
|
|
@@ -2335,8 +2344,17 @@ class TAFParser extends AbstractParser {
|
|
|
2335
2344
|
const time = parseDeliveryTime(lines[0][index]);
|
|
2336
2345
|
index += 1;
|
|
2337
2346
|
const validity = parseValidity(lines[0][index]);
|
|
2338
|
-
const taf =
|
|
2339
|
-
|
|
2347
|
+
const taf = {
|
|
2348
|
+
station,
|
|
2349
|
+
amendment,
|
|
2350
|
+
...time,
|
|
2351
|
+
validity,
|
|
2352
|
+
message: input,
|
|
2353
|
+
trends: [],
|
|
2354
|
+
remarks: [],
|
|
2355
|
+
clouds: [],
|
|
2356
|
+
weatherConditions: [],
|
|
2357
|
+
};
|
|
2340
2358
|
for (let i = index + 1; i < lines[0].length; i++) {
|
|
2341
2359
|
const token = lines[0][i];
|
|
2342
2360
|
if (token == this.RMK) {
|
|
@@ -2370,7 +2388,7 @@ class TAFParser extends AbstractParser {
|
|
|
2370
2388
|
// TODO cleanup
|
|
2371
2389
|
function joinProbIfNeeded(ls) {
|
|
2372
2390
|
for (let i = 0; i < ls.length; i++) {
|
|
2373
|
-
if (
|
|
2391
|
+
if (/^PROB\d{2}$/.test(ls[i]) && /^TEMPO/.test(ls[i + 1])) {
|
|
2374
2392
|
ls.splice(i, 2, `${ls[i]} ${ls[i + 1]}`);
|
|
2375
2393
|
i--;
|
|
2376
2394
|
}
|
|
@@ -2397,15 +2415,27 @@ class TAFParser extends AbstractParser {
|
|
|
2397
2415
|
let index = 1;
|
|
2398
2416
|
let trend;
|
|
2399
2417
|
if (lineTokens[0].startsWith(this.FM)) {
|
|
2400
|
-
trend =
|
|
2418
|
+
trend = {
|
|
2419
|
+
...this.makeEmptyTAFTrend(),
|
|
2420
|
+
type: WeatherChangeType.FM,
|
|
2421
|
+
validity: parseFromValidity(lineTokens[0]),
|
|
2422
|
+
};
|
|
2401
2423
|
}
|
|
2402
2424
|
else if (lineTokens[0].startsWith(this.PROB)) {
|
|
2403
2425
|
const validity = this.findLineValidity(index, lineTokens);
|
|
2404
2426
|
if (!validity)
|
|
2405
2427
|
return;
|
|
2406
|
-
trend =
|
|
2428
|
+
trend = {
|
|
2429
|
+
...this.makeEmptyTAFTrend(),
|
|
2430
|
+
type: WeatherChangeType.PROB,
|
|
2431
|
+
validity,
|
|
2432
|
+
};
|
|
2407
2433
|
if (lineTokens.length > 1 && lineTokens[1] === this.TEMPO) {
|
|
2408
|
-
trend =
|
|
2434
|
+
trend = {
|
|
2435
|
+
...this.makeEmptyTAFTrend(),
|
|
2436
|
+
type: WeatherChangeType[lineTokens[1]],
|
|
2437
|
+
validity,
|
|
2438
|
+
};
|
|
2409
2439
|
index = 2;
|
|
2410
2440
|
}
|
|
2411
2441
|
trend.probability = +lineTokens[0].slice(4);
|
|
@@ -2414,7 +2444,11 @@ class TAFParser extends AbstractParser {
|
|
|
2414
2444
|
const validity = this.findLineValidity(index, lineTokens);
|
|
2415
2445
|
if (!validity)
|
|
2416
2446
|
return;
|
|
2417
|
-
trend =
|
|
2447
|
+
trend = {
|
|
2448
|
+
...this.makeEmptyTAFTrend(),
|
|
2449
|
+
type: WeatherChangeType[lineTokens[0]],
|
|
2450
|
+
validity,
|
|
2451
|
+
};
|
|
2418
2452
|
}
|
|
2419
2453
|
this.parseTrend(index, lineTokens, trend);
|
|
2420
2454
|
taf.trends.push(trend);
|
|
@@ -2540,19 +2574,41 @@ function addMonthsUTC(date, count) {
|
|
|
2540
2574
|
}
|
|
2541
2575
|
|
|
2542
2576
|
function metarDatesHydrator(report, date) {
|
|
2543
|
-
return
|
|
2577
|
+
return {
|
|
2578
|
+
...report,
|
|
2579
|
+
issued: determineReportIssuedDate(date, report.day, report.hour, report.minute),
|
|
2580
|
+
};
|
|
2544
2581
|
}
|
|
2545
2582
|
|
|
2546
2583
|
function tafDatesHydrator(report, date) {
|
|
2547
2584
|
const issued = determineReportIssuedDate(date, report.day, report.hour, report.minute);
|
|
2548
|
-
return
|
|
2585
|
+
return {
|
|
2586
|
+
...report,
|
|
2587
|
+
issued,
|
|
2588
|
+
validity: {
|
|
2589
|
+
...report.validity,
|
|
2590
|
+
start: getReportDate(issued, report.validity.startDay, report.validity.startHour),
|
|
2591
|
+
end: getReportDate(issued, report.validity.endDay, report.validity.endHour),
|
|
2592
|
+
},
|
|
2593
|
+
trends: report.trends.map((trend) => ({
|
|
2594
|
+
...trend,
|
|
2595
|
+
validity: (() => {
|
|
2549
2596
|
switch (trend.type) {
|
|
2550
2597
|
case WeatherChangeType.FM:
|
|
2551
|
-
return
|
|
2598
|
+
return {
|
|
2599
|
+
...trend.validity,
|
|
2600
|
+
start: getReportDate(issued, trend.validity.startDay, trend.validity.startHour, trend.validity.startMinutes),
|
|
2601
|
+
};
|
|
2552
2602
|
default:
|
|
2553
|
-
return
|
|
2603
|
+
return {
|
|
2604
|
+
...trend.validity,
|
|
2605
|
+
start: getReportDate(issued, trend.validity.startDay, trend.validity.startHour),
|
|
2606
|
+
end: getReportDate(issued, trend.validity.endDay, trend.validity.endHour),
|
|
2607
|
+
};
|
|
2554
2608
|
}
|
|
2555
|
-
})()
|
|
2609
|
+
})(),
|
|
2610
|
+
})),
|
|
2611
|
+
};
|
|
2556
2612
|
}
|
|
2557
2613
|
|
|
2558
2614
|
function getForecastFromTAF(taf) {
|
|
@@ -2631,7 +2687,7 @@ function parseTAFAsForecast(rawTAF, options) {
|
|
|
2631
2687
|
return getForecastFromTAF(taf);
|
|
2632
2688
|
}
|
|
2633
2689
|
function parse(rawReport, options, parser, datesHydrator) {
|
|
2634
|
-
const lang =
|
|
2690
|
+
const lang = options?.locale || en;
|
|
2635
2691
|
try {
|
|
2636
2692
|
const report = new parser(lang).parse(rawReport);
|
|
2637
2693
|
if (options && "date" in options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metar-taf-parser",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Parse METAR and TAF reports",
|
|
5
5
|
"homepage": "https://aeharding.github.io/metar-taf-parser",
|
|
6
6
|
"keywords": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"build": "yarn clean && rollup -c rollup.config.ts && cp -R dist/locale/. locale/ && cp dist/metar-taf-parser.js metar-taf-parser.js && yarn clean:after",
|
|
26
26
|
"clean:after": "rimraf dist",
|
|
27
27
|
"start": "rollup -c rollup.config.ts -w",
|
|
28
|
-
"check-types": "tsc --noEmit",
|
|
28
|
+
"check-types": "tsc --skipLibCheck --noEmit",
|
|
29
29
|
"check-formatting": "prettier --check '**/*.{js,json,css,md,scss,tsx,ts}'",
|
|
30
30
|
"watch": "watch 'yarn build' src",
|
|
31
31
|
"test": "jest --coverage",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"prettier": "^2.6.2",
|
|
48
48
|
"rollup": "^2.71.1",
|
|
49
49
|
"rollup-plugin-dts": "^4.2.1",
|
|
50
|
-
"ts-jest": "28.0.
|
|
50
|
+
"ts-jest": "^28.0.1",
|
|
51
51
|
"ts-node": "^10.7.0",
|
|
52
52
|
"tsc-alias": "^1.6.7",
|
|
53
53
|
"tslib": "^2.4.0",
|