metar-taf-parser 1.3.1 → 3.1.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/README.md +125 -13
- package/dist/command/common.js +14 -12
- package/dist/command/metar/AltimeterCommand.d.ts +7 -0
- package/dist/command/metar/AltimeterCommand.js +26 -0
- package/dist/command/metar/AltimeterMercuryCommand.d.ts +7 -0
- package/dist/command/metar/AltimeterMercuryCommand.js +51 -0
- package/dist/command/metar/RunwayCommand.d.ts +7 -0
- package/dist/command/metar/RunwayCommand.js +60 -0
- package/dist/command/metar/TemperatureCommand.d.ts +7 -0
- package/dist/command/metar/TemperatureCommand.js +51 -0
- package/dist/command/metar.d.ts +1 -22
- package/dist/command/metar.js +11 -115
- package/dist/command/remark/CeilingHeightCommand.d.ts +18 -0
- package/dist/command/remark/CeilingHeightCommand.js +40 -0
- package/dist/command/remark/CeilingSecondLocationCommand.d.ts +12 -0
- package/dist/command/remark/CeilingSecondLocationCommand.js +40 -0
- package/dist/command/remark/Command.d.ts +8 -0
- package/dist/command/remark/Command.js +9 -0
- package/dist/command/remark/DefaultCommand.d.ts +11 -0
- package/dist/command/remark/DefaultCommand.js +38 -0
- package/dist/command/remark/HailSizeCommand.d.ts +11 -0
- package/dist/command/remark/HailSizeCommand.js +38 -0
- package/dist/command/remark/HourlyMaximumMinimumTemperatureCommand.d.ts +18 -0
- package/dist/command/remark/HourlyMaximumMinimumTemperatureCommand.js +39 -0
- package/dist/command/remark/HourlyMaximumTemperatureCommand.d.ts +14 -0
- package/dist/command/remark/HourlyMaximumTemperatureCommand.js +38 -0
- package/dist/command/remark/HourlyMinimumTemperatureCommand.d.ts +14 -0
- package/dist/command/remark/HourlyMinimumTemperatureCommand.js +38 -0
- package/dist/command/remark/HourlyPrecipitationAmountCommand.d.ts +14 -0
- package/dist/command/remark/HourlyPrecipitationAmountCommand.js +38 -0
- package/dist/command/remark/HourlyPressureCommand.d.ts +32 -0
- package/dist/command/remark/HourlyPressureCommand.js +40 -0
- package/dist/command/remark/HourlyTemperatureDewPointCommand.d.ts +18 -0
- package/dist/command/remark/HourlyTemperatureDewPointCommand.js +52 -0
- package/dist/command/remark/IceAccretionCommand.d.ts +15 -0
- package/dist/command/remark/IceAccretionCommand.js +38 -0
- package/dist/command/remark/ObscurationCommand.d.ts +14 -0
- package/dist/command/remark/ObscurationCommand.js +44 -0
- package/dist/command/remark/PrecipitationAmount24HourCommand.d.ts +14 -0
- package/dist/command/remark/PrecipitationAmount24HourCommand.js +39 -0
- package/dist/command/remark/PrecipitationAmount36HourCommand.d.ts +15 -0
- package/dist/command/remark/PrecipitationAmount36HourCommand.js +41 -0
- package/dist/command/remark/PrecipitationBegCommand.d.ts +15 -0
- package/dist/command/remark/PrecipitationBegCommand.js +45 -0
- package/dist/command/remark/PrecipitationBegEndCommand.d.ts +17 -0
- package/dist/command/remark/PrecipitationBegEndCommand.js +46 -0
- package/dist/command/remark/PrecipitationEndCommand.d.ts +15 -0
- package/dist/command/remark/PrecipitationEndCommand.js +45 -0
- package/dist/command/remark/PrevailingVisibilityCommand.d.ts +12 -0
- package/dist/command/remark/PrevailingVisibilityCommand.js +41 -0
- package/dist/command/remark/SeaLevelPressureCommand.d.ts +11 -0
- package/dist/command/remark/SeaLevelPressureCommand.js +39 -0
- package/dist/command/remark/SecondLocationVisibilityCommand.d.ts +12 -0
- package/dist/command/remark/SecondLocationVisibilityCommand.js +41 -0
- package/dist/command/remark/SectorVisibilityCommand.d.ts +13 -0
- package/dist/command/remark/SectorVisibilityCommand.js +42 -0
- package/dist/command/remark/SmallHailSizeCommand.d.ts +11 -0
- package/dist/command/remark/SmallHailSizeCommand.js +38 -0
- package/dist/command/remark/SnowDepthCommand.d.ts +11 -0
- package/dist/command/remark/SnowDepthCommand.js +38 -0
- package/dist/command/remark/SnowIncreaseCommand.d.ts +12 -0
- package/dist/command/remark/SnowIncreaseCommand.js +40 -0
- package/dist/command/remark/SnowPelletsCommand.d.ts +11 -0
- package/dist/command/remark/SnowPelletsCommand.js +37 -0
- package/dist/command/remark/SunshineDurationCommand.d.ts +11 -0
- package/dist/command/remark/SunshineDurationCommand.js +38 -0
- package/dist/command/remark/SurfaceVisibilityCommand.d.ts +11 -0
- package/dist/command/remark/SurfaceVisibilityCommand.js +39 -0
- package/dist/command/remark/ThunderStormLocationCommand.d.ts +12 -0
- package/dist/command/remark/ThunderStormLocationCommand.js +40 -0
- package/dist/command/remark/ThunderStormLocationMovingCommand.d.ts +19 -0
- package/dist/command/remark/ThunderStormLocationMovingCommand.js +42 -0
- package/dist/command/remark/TornadicActivityBegCommand.d.ts +16 -0
- package/dist/command/remark/TornadicActivityBegCommand.js +44 -0
- package/dist/command/remark/TornadicActivityBegEndCommand.d.ts +18 -0
- package/dist/command/remark/TornadicActivityBegEndCommand.js +46 -0
- package/dist/command/remark/TornadicActivityEndCommand.d.ts +16 -0
- package/dist/command/remark/TornadicActivityEndCommand.js +44 -0
- package/dist/command/remark/TowerVisibilityCommand.d.ts +11 -0
- package/dist/command/remark/TowerVisibilityCommand.js +39 -0
- package/dist/command/remark/VariableSkyCommand.d.ts +12 -0
- package/dist/command/remark/VariableSkyCommand.js +41 -0
- package/dist/command/remark/VariableSkyHeightCommand.d.ts +13 -0
- package/dist/command/remark/VariableSkyHeightCommand.js +43 -0
- package/dist/command/remark/VirgaDirectionCommand.d.ts +12 -0
- package/dist/command/remark/VirgaDirectionCommand.js +40 -0
- package/dist/command/remark/WaterEquivalentSnowCommand.d.ts +11 -0
- package/dist/command/remark/WaterEquivalentSnowCommand.js +38 -0
- package/dist/command/remark/WindPeakCommandCommand.d.ts +17 -0
- package/dist/command/remark/WindPeakCommandCommand.js +42 -0
- package/dist/command/remark/WindShiftCommand.d.ts +12 -0
- package/dist/command/remark/WindShiftCommand.js +38 -0
- package/dist/command/remark/WindShiftFropaCommand.d.ts +12 -0
- package/dist/command/remark/WindShiftFropaCommand.js +38 -0
- package/dist/command/remark.d.ts +100 -194
- package/dist/command/remark.js +136 -755
- package/dist/commons/converter.d.ts +14 -2
- package/dist/commons/converter.js +53 -5
- package/dist/commons/errors.d.ts +6 -2
- package/dist/commons/errors.js +15 -8
- package/dist/commons/i18n.d.ts +2 -2
- package/dist/commons/i18n.js +9 -3
- package/dist/dates/metar.d.ts +5 -0
- package/dist/dates/metar.js +8 -0
- package/dist/dates/taf.d.ts +28 -0
- package/dist/dates/taf.js +17 -0
- package/dist/forecast/forecast.d.ts +36 -0
- package/dist/forecast/forecast.js +72 -0
- package/dist/helpers/date.d.ts +11 -0
- package/dist/helpers/date.js +56 -0
- package/dist/helpers/helpers.d.ts +7 -0
- package/dist/helpers/helpers.js +14 -1
- package/dist/index.d.ts +23 -2
- package/dist/index.js +24 -7
- package/dist/model/enum.d.ts +44 -0
- package/dist/model/enum.js +50 -1
- package/dist/model/model.d.ts +84 -19
- package/dist/model/model.js +3 -1
- package/dist/parser/parser.d.ts +13 -6
- package/dist/parser/parser.js +64 -30
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
# ✈️ [metar-taf-parser](https://aeharding.github.io/metar-taf-parser)
|
|
2
2
|
|
|
3
|
-
Parser for METeorological Aerodrome Reports (METARs) and Terminal Aerodrome Forecasts (TAFs). This is a port of [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser) to Typescript
|
|
3
|
+
Parser for METeorological Aerodrome Reports (METARs) and Terminal Aerodrome Forecasts (TAFs). This is a port of [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser) to Typescript with some additional features.
|
|
4
4
|
|
|
5
5
|
[Check out the demo here](https://aeharding.github.io/metar-taf-parser)
|
|
6
6
|
|
|
7
|
+
Features:
|
|
8
|
+
|
|
9
|
+
- ✈️ Complete METAR and TAF parsing
|
|
10
|
+
- 🛠 Fully typed
|
|
11
|
+
- 🪶 Dependency free
|
|
12
|
+
- 🧪 Full test suite
|
|
13
|
+
- ✅ Runs anywhere: Web browser or Node
|
|
14
|
+
- 🌎 i18n: Translations
|
|
15
|
+
- 🌏 i18n: Handling international TAF & METAR report format differences
|
|
16
|
+
- 🌪 Remark parsing to human and machine readable formats
|
|
17
|
+
- 🗓 [`Forecast` abstraction](https://aeharding.github.io/metar-taf-parser/forecast) to easily query TAF reports by `Date`
|
|
18
|
+
|
|
7
19
|
## Installation
|
|
8
20
|
|
|
9
21
|
```sh
|
|
@@ -14,31 +26,131 @@ npm i --save metar-taf-parser
|
|
|
14
26
|
|
|
15
27
|
## Usage
|
|
16
28
|
|
|
17
|
-
###
|
|
29
|
+
### Parsing
|
|
30
|
+
|
|
31
|
+
The `parseMetar` & `parseTAF` functions are designed to parse the raw report string into an object representation of a METAR/TAF.
|
|
32
|
+
|
|
33
|
+
#### `parseMetar`
|
|
18
34
|
|
|
19
35
|
```ts
|
|
20
|
-
import { parseMetar } from
|
|
36
|
+
import { parseMetar } from "metar-taf-parser";
|
|
37
|
+
|
|
38
|
+
const metar = parseMetar(rawMetarString);
|
|
21
39
|
|
|
22
|
-
|
|
40
|
+
// -or-
|
|
41
|
+
|
|
42
|
+
// Optionally pass a date (approximately when the report was issued, +/- a week)
|
|
43
|
+
// to get the issued date on the report:
|
|
44
|
+
const datedMetar = parseMetar(rawMetarString, { date: new Date() });
|
|
23
45
|
```
|
|
24
46
|
|
|
25
|
-
|
|
47
|
+
#### `parseTAF`
|
|
48
|
+
|
|
49
|
+
👉 **Note:** One of the common use cases for TAF reports is to get relevant forecast data for a given date. Check out [the `Forecast` abstraction](#higher-level-parsing-the-forecast-abstraction) below which may provide TAF data in a more normalized format, depending on your use case.
|
|
26
50
|
|
|
27
51
|
```ts
|
|
28
|
-
import { parseTAF } from
|
|
52
|
+
import { parseTAF } from "metar-taf-parser";
|
|
53
|
+
|
|
54
|
+
const taf = parseTAF(rawTAFString);
|
|
55
|
+
|
|
56
|
+
// -or-
|
|
57
|
+
|
|
58
|
+
// Optionally pass a date (approximately when the report was issued, +/- a week)
|
|
59
|
+
// to get the report issued and trend validity dates (start/end) on the report:
|
|
60
|
+
const datedTAF = parseTAF(rawTAFString, { date: new Date() });
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Higher level parsing: The Forecast abstraction
|
|
64
|
+
|
|
65
|
+
TAF reports are a little funky... FM, BECMG, PROB, etc. You may find the `Forecast` abstraction more helpful.
|
|
66
|
+
|
|
67
|
+
#### `parseTAFAsForecast`
|
|
68
|
+
|
|
69
|
+
Returns a more normalized TAF report. Most notably: while the `parseTAF` function returns initial weather conditions on the base of the returned result (and further conditions on `trends[]`), the `parseTAFAsForecast` function returns the initial weather conditions as the first element of the `forecast[]` property, followed by subsequent trends. This makes it much easier to iterate though.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { parseTAFAsForecast } from "metar-taf-parser";
|
|
73
|
+
|
|
74
|
+
// You must provide an issued date to use the Forecast abstraction
|
|
75
|
+
const report = parseTAFAsForecast(rawTAFString, { date: tafIssuedDate });
|
|
76
|
+
|
|
77
|
+
console.log(report.forecast);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### `getCompositeForecastForDate`
|
|
81
|
+
|
|
82
|
+
> ⚠️ **Warning:** Experimental API
|
|
83
|
+
|
|
84
|
+
Provides all relevant weather conditions for a given timestamp. It returns a `ICompositeForecast` with a `base` and `additional` component. The `base` component is the base weather condition period (the FM part of the report) - and there will always be one.
|
|
85
|
+
|
|
86
|
+
The `additional` property is an array of weather condition periods valid for the given timestamp (any `BECMG`, `PROB`, `TEMPO`, etc.)
|
|
29
87
|
|
|
30
|
-
|
|
88
|
+
You will still need to write some logic to use this API to determine what data to use - for example, if `additional[0].visibility` exists, use it over `base.visibility`.
|
|
89
|
+
|
|
90
|
+
#### Example
|
|
91
|
+
|
|
92
|
+
This example provides an array of hourly weather conditions over the duration of the TAF report.
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { eachHourOfInterval } from "date-fns";
|
|
96
|
+
import {
|
|
97
|
+
parseTAFAsForecast,
|
|
98
|
+
getCompositeForecastForDate,
|
|
99
|
+
} from "metar-taf-parser";
|
|
100
|
+
|
|
101
|
+
const report = parseTAFAsForecast(rawTAFString, { date: tafIssuedDate });
|
|
102
|
+
|
|
103
|
+
const forecastPerHour = eachHourOfInterval({
|
|
104
|
+
start: report.start,
|
|
105
|
+
end: report.end,
|
|
106
|
+
}).map((hour) => ({
|
|
107
|
+
hour,
|
|
108
|
+
...getCompositeForecastForDate(hour, report),
|
|
109
|
+
}));
|
|
31
110
|
```
|
|
32
111
|
|
|
33
112
|
## i18n
|
|
34
113
|
|
|
114
|
+
The `description` property in the `Remark` is translated, if available.
|
|
115
|
+
|
|
35
116
|
```ts
|
|
36
|
-
import { parseMetar } from
|
|
37
|
-
import de from
|
|
117
|
+
import { parseMetar } from "metar-taf-parser";
|
|
118
|
+
import de from "metar-taf-parser/dist/locale/de";
|
|
38
119
|
|
|
39
|
-
const
|
|
120
|
+
const rawMetarReport = "KTTN 051853Z 04011KT RMK SLP176";
|
|
40
121
|
|
|
41
|
-
const metarResult = parseMetar(
|
|
122
|
+
const metarResult = parseMetar(rawMetarReport, {
|
|
123
|
+
locale: de,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
console.log(metarReport.remarks[0].description);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Handling remarks
|
|
130
|
+
|
|
131
|
+
Remarks may be found on base TAF and METARs, along with TAF trends.
|
|
132
|
+
|
|
133
|
+
Each Remark will have a `description` (if translated), `type` and `raw` properties. There are additional properties for each unique remark, depending on the remark's `type`. We can type guard on `type` to access these unique properties.
|
|
134
|
+
|
|
135
|
+
If the remark is not understood, it will have `type` as `RemarkType.Unknown`, with `raw` containing everything until the next understood remark.
|
|
136
|
+
|
|
137
|
+
### Example
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { Remark, RemarkType } from "metar-taf-parser";
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Find the sea level pressure given remarks, if defined
|
|
144
|
+
*/
|
|
145
|
+
function findSeaLevelPressure(remarks: Remark[]): number | undefined {
|
|
146
|
+
for (const remark of remarks) {
|
|
147
|
+
switch (remark.type) {
|
|
148
|
+
case RemarkType.SeaLevelPressure:
|
|
149
|
+
// can now access remark.pressure
|
|
150
|
+
return remark.pressure;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
42
154
|
```
|
|
43
155
|
|
|
44
156
|
## Development
|
|
@@ -49,8 +161,8 @@ Please see [the example site README.md](example/README.md).
|
|
|
49
161
|
|
|
50
162
|
## Contributing
|
|
51
163
|
|
|
52
|
-
This project is
|
|
164
|
+
This project is based on [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser) and the parsing should be as similar to that project as possible. That being said, PRs are welcome.
|
|
53
165
|
|
|
54
166
|
## Acknowledgment
|
|
55
167
|
|
|
56
|
-
This software port was made possible due to the fantastic work of [@mivek](https://github.com/mivek) in [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser). If you like this project, please [consider buying @mivek a coffee](https://ko-fi.com/mivek).
|
|
168
|
+
This software port was made possible due to the fantastic work of [@mivek](https://github.com/mivek) in [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser). If you like this project, please [consider buying @mivek a coffee](https://ko-fi.com/mivek).
|
package/dist/command/common.js
CHANGED
|
@@ -92,8 +92,10 @@ class MainVisibilityCommand {
|
|
|
92
92
|
return false;
|
|
93
93
|
const distance = converter.convertVisibility(matches[1]);
|
|
94
94
|
if (!container.visibility)
|
|
95
|
-
container.visibility =
|
|
96
|
-
container.visibility
|
|
95
|
+
container.visibility = distance;
|
|
96
|
+
container.visibility = Object.assign(Object.assign({}, container.visibility), distance);
|
|
97
|
+
if (matches[2] === "NDV")
|
|
98
|
+
container.visibility.ndv = true;
|
|
97
99
|
return true;
|
|
98
100
|
}
|
|
99
101
|
}
|
|
@@ -136,7 +138,7 @@ class WindVariationCommand {
|
|
|
136
138
|
}
|
|
137
139
|
execute(container, windString) {
|
|
138
140
|
if (!container.wind)
|
|
139
|
-
throw new errors_1.
|
|
141
|
+
throw new errors_1.UnexpectedParseError();
|
|
140
142
|
this.parseWindVariation(container.wind, windString);
|
|
141
143
|
return true;
|
|
142
144
|
}
|
|
@@ -182,7 +184,7 @@ exports.VerticalVisibilityCommand = VerticalVisibilityCommand;
|
|
|
182
184
|
_VerticalVisibilityCommand_regex = new WeakMap();
|
|
183
185
|
class MinimalVisibilityCommand {
|
|
184
186
|
constructor() {
|
|
185
|
-
_MinimalVisibilityCommand_regex.set(this, /^(\d{4}[a-
|
|
187
|
+
_MinimalVisibilityCommand_regex.set(this, /^(\d{4}[a-zA-Z]{1,2})$/);
|
|
186
188
|
}
|
|
187
189
|
execute(container, visibilityString) {
|
|
188
190
|
const matches = visibilityString.match(__classPrivateFieldGet(this, _MinimalVisibilityCommand_regex, "f"));
|
|
@@ -190,8 +192,10 @@ class MinimalVisibilityCommand {
|
|
|
190
192
|
throw new errors_1.UnexpectedParseError("Vertical visibility should be defined");
|
|
191
193
|
if (!container.visibility)
|
|
192
194
|
throw new errors_1.UnexpectedParseError("container.visibility not instantiated");
|
|
193
|
-
container.visibility.
|
|
194
|
-
|
|
195
|
+
container.visibility.min = {
|
|
196
|
+
value: +matches[1].slice(0, 4),
|
|
197
|
+
direction: matches[1].slice(4),
|
|
198
|
+
};
|
|
195
199
|
return true;
|
|
196
200
|
}
|
|
197
201
|
canParse(windString) {
|
|
@@ -202,12 +206,11 @@ exports.MinimalVisibilityCommand = MinimalVisibilityCommand;
|
|
|
202
206
|
_MinimalVisibilityCommand_regex = new WeakMap();
|
|
203
207
|
class MainVisibilityNauticalMilesCommand {
|
|
204
208
|
constructor() {
|
|
205
|
-
_MainVisibilityNauticalMilesCommand_regex.set(this, /^(\d)*(\s)?((\d\/\d)?SM)$/);
|
|
209
|
+
_MainVisibilityNauticalMilesCommand_regex.set(this, /^(P|M)?(\d)*(\s)?((\d\/\d)?SM)$/);
|
|
206
210
|
}
|
|
207
211
|
execute(container, visibilityString) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
container.visibility.distance = visibilityString;
|
|
212
|
+
const distance = converter.convertNauticalMilesVisibility(visibilityString);
|
|
213
|
+
container.visibility = distance;
|
|
211
214
|
return true;
|
|
212
215
|
}
|
|
213
216
|
canParse(windString) {
|
|
@@ -230,8 +233,7 @@ class CommandSupplier {
|
|
|
230
233
|
]);
|
|
231
234
|
}
|
|
232
235
|
get(input) {
|
|
233
|
-
for (
|
|
234
|
-
const command = __classPrivateFieldGet(this, _CommandSupplier_commands, "f")[i];
|
|
236
|
+
for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands, "f")) {
|
|
235
237
|
if (command.canParse(input))
|
|
236
238
|
return command;
|
|
237
239
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var _AltimeterCommand_regex;
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.AltimeterCommand = void 0;
|
|
10
|
+
const errors_1 = require("../../commons/errors");
|
|
11
|
+
class AltimeterCommand {
|
|
12
|
+
constructor() {
|
|
13
|
+
_AltimeterCommand_regex.set(this, /^Q(\d{4})$/);
|
|
14
|
+
}
|
|
15
|
+
canParse(input) {
|
|
16
|
+
return __classPrivateFieldGet(this, _AltimeterCommand_regex, "f").test(input);
|
|
17
|
+
}
|
|
18
|
+
execute(metar, input) {
|
|
19
|
+
const matches = input.match(__classPrivateFieldGet(this, _AltimeterCommand_regex, "f"));
|
|
20
|
+
if (!matches)
|
|
21
|
+
throw new errors_1.UnexpectedParseError("Match not found");
|
|
22
|
+
metar.altimeter = Math.trunc(+matches[1]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.AltimeterCommand = AltimeterCommand;
|
|
26
|
+
_AltimeterCommand_regex = new WeakMap();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
26
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
27
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
28
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
29
|
+
};
|
|
30
|
+
var _AltimeterMercuryCommand_regex;
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.AltimeterMercuryCommand = void 0;
|
|
33
|
+
const converter = __importStar(require("../../commons/converter"));
|
|
34
|
+
const errors_1 = require("../../commons/errors");
|
|
35
|
+
class AltimeterMercuryCommand {
|
|
36
|
+
constructor() {
|
|
37
|
+
_AltimeterMercuryCommand_regex.set(this, /^A(\d{4})$/);
|
|
38
|
+
}
|
|
39
|
+
canParse(input) {
|
|
40
|
+
return __classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f").test(input);
|
|
41
|
+
}
|
|
42
|
+
execute(metar, input) {
|
|
43
|
+
const matches = input.match(__classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f"));
|
|
44
|
+
if (!matches)
|
|
45
|
+
throw new errors_1.UnexpectedParseError("Match not found");
|
|
46
|
+
const mercury = +matches[1] / 100;
|
|
47
|
+
metar.altimeter = Math.trunc(converter.convertInchesMercuryToPascal(mercury));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.AltimeterMercuryCommand = AltimeterMercuryCommand;
|
|
51
|
+
_AltimeterMercuryCommand_regex = new WeakMap();
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var _RunwayCommand_genericRegex, _RunwayCommand_runwayMaxRangeRegex, _RunwayCommand_runwayRegex;
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RunwayCommand = void 0;
|
|
10
|
+
const errors_1 = require("../../commons/errors");
|
|
11
|
+
const helpers_1 = require("../../helpers/helpers");
|
|
12
|
+
const enum_1 = require("../../model/enum");
|
|
13
|
+
class RunwayCommand {
|
|
14
|
+
constructor() {
|
|
15
|
+
_RunwayCommand_genericRegex.set(this, /^(R\d{2}\w?\/)/);
|
|
16
|
+
_RunwayCommand_runwayMaxRangeRegex.set(this, /^R(\d{2}\w?)\/(\d{4})V(\d{3,4})([UDN])?(FT)?/);
|
|
17
|
+
_RunwayCommand_runwayRegex.set(this, /^R(\d{2}\w?)\/([MP])?(\d{4})([UDN])?(FT)?$/);
|
|
18
|
+
}
|
|
19
|
+
canParse(input) {
|
|
20
|
+
return __classPrivateFieldGet(this, _RunwayCommand_genericRegex, "f").test(input);
|
|
21
|
+
}
|
|
22
|
+
execute(metar, input) {
|
|
23
|
+
// TODO idk if this matches super well...
|
|
24
|
+
if (__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f").test(input)) {
|
|
25
|
+
const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f"));
|
|
26
|
+
if (!matches)
|
|
27
|
+
throw new errors_1.UnexpectedParseError("Should be able to parse");
|
|
28
|
+
const indicator = matches[2] ? (0, helpers_1.as)(matches[2], enum_1.ValueIndicator) : undefined;
|
|
29
|
+
const trend = matches[4] ? (0, helpers_1.as)(matches[4], enum_1.RunwayInfoTrend) : undefined;
|
|
30
|
+
const unit = matches[5]
|
|
31
|
+
? (0, helpers_1.as)(matches[5], enum_1.RunwayInfoUnit)
|
|
32
|
+
: enum_1.RunwayInfoUnit.Meters;
|
|
33
|
+
metar.runwaysInfo.push({
|
|
34
|
+
name: matches[1],
|
|
35
|
+
indicator,
|
|
36
|
+
minRange: +matches[3],
|
|
37
|
+
trend,
|
|
38
|
+
unit,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
else if (__classPrivateFieldGet(this, _RunwayCommand_runwayMaxRangeRegex, "f").test(input)) {
|
|
42
|
+
const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayMaxRangeRegex, "f"));
|
|
43
|
+
if (!matches)
|
|
44
|
+
throw new errors_1.UnexpectedParseError("Should be able to parse");
|
|
45
|
+
const trend = matches[4] ? (0, helpers_1.as)(matches[4], enum_1.RunwayInfoTrend) : undefined;
|
|
46
|
+
const unit = matches[5]
|
|
47
|
+
? (0, helpers_1.as)(matches[5], enum_1.RunwayInfoUnit)
|
|
48
|
+
: enum_1.RunwayInfoUnit.Meters;
|
|
49
|
+
metar.runwaysInfo.push({
|
|
50
|
+
name: matches[1],
|
|
51
|
+
minRange: +matches[2],
|
|
52
|
+
maxRange: +matches[3],
|
|
53
|
+
trend,
|
|
54
|
+
unit,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.RunwayCommand = RunwayCommand;
|
|
60
|
+
_RunwayCommand_genericRegex = new WeakMap(), _RunwayCommand_runwayMaxRangeRegex = new WeakMap(), _RunwayCommand_runwayRegex = new WeakMap();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
26
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
27
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
28
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
29
|
+
};
|
|
30
|
+
var _TemperatureCommand_regex;
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.TemperatureCommand = void 0;
|
|
33
|
+
const converter = __importStar(require("../../commons/converter"));
|
|
34
|
+
const errors_1 = require("../../commons/errors");
|
|
35
|
+
class TemperatureCommand {
|
|
36
|
+
constructor() {
|
|
37
|
+
_TemperatureCommand_regex.set(this, /^(M?\d{2})\/(M?\d{2})$/);
|
|
38
|
+
}
|
|
39
|
+
canParse(input) {
|
|
40
|
+
return __classPrivateFieldGet(this, _TemperatureCommand_regex, "f").test(input);
|
|
41
|
+
}
|
|
42
|
+
execute(metar, input) {
|
|
43
|
+
const matches = input.match(__classPrivateFieldGet(this, _TemperatureCommand_regex, "f"));
|
|
44
|
+
if (!matches)
|
|
45
|
+
throw new errors_1.UnexpectedParseError("Match not found");
|
|
46
|
+
metar.temperature = converter.convertTemperature(matches[1]);
|
|
47
|
+
metar.dewPoint = converter.convertTemperature(matches[2]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.TemperatureCommand = TemperatureCommand;
|
|
51
|
+
_TemperatureCommand_regex = new WeakMap();
|
package/dist/command/metar.d.ts
CHANGED
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
import { IMetar } from "../model/model";
|
|
2
|
-
interface ICommand {
|
|
2
|
+
export interface ICommand {
|
|
3
3
|
canParse(str: string): boolean;
|
|
4
4
|
execute(metar: IMetar, str: string): void;
|
|
5
5
|
}
|
|
6
|
-
export declare class AltimeterCommand implements ICommand {
|
|
7
|
-
#private;
|
|
8
|
-
canParse(input: string): boolean;
|
|
9
|
-
execute(metar: IMetar, input: string): void;
|
|
10
|
-
}
|
|
11
|
-
export declare class AltimeterMercuryCommand implements ICommand {
|
|
12
|
-
#private;
|
|
13
|
-
canParse(input: string): boolean;
|
|
14
|
-
execute(metar: IMetar, input: string): void;
|
|
15
|
-
}
|
|
16
|
-
export declare class RunwayCommand implements ICommand {
|
|
17
|
-
#private;
|
|
18
|
-
canParse(input: string): boolean;
|
|
19
|
-
execute(metar: IMetar, input: string): void;
|
|
20
|
-
}
|
|
21
|
-
export declare class TemperatureCommand implements ICommand {
|
|
22
|
-
#private;
|
|
23
|
-
canParse(input: string): boolean;
|
|
24
|
-
execute(metar: IMetar, input: string): void;
|
|
25
|
-
}
|
|
26
6
|
export declare class CommandSupplier {
|
|
27
7
|
#private;
|
|
28
8
|
get(input: string): ICommand | undefined;
|
|
29
9
|
}
|
|
30
|
-
export {};
|
package/dist/command/metar.js
CHANGED
|
@@ -1,131 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
26
3
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
27
4
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
28
5
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
29
6
|
};
|
|
30
|
-
var
|
|
7
|
+
var _CommandSupplier_commands;
|
|
31
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.CommandSupplier =
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
_AltimeterCommand_regex.set(this, /^Q(\d{4})$/);
|
|
38
|
-
}
|
|
39
|
-
canParse(input) {
|
|
40
|
-
return __classPrivateFieldGet(this, _AltimeterCommand_regex, "f").test(input);
|
|
41
|
-
}
|
|
42
|
-
execute(metar, input) {
|
|
43
|
-
const matches = input.match(__classPrivateFieldGet(this, _AltimeterCommand_regex, "f"));
|
|
44
|
-
if (!matches)
|
|
45
|
-
throw new errors_1.UnexpectedParseError("Match not found");
|
|
46
|
-
metar.altimeter = Math.trunc(+matches[1]);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
exports.AltimeterCommand = AltimeterCommand;
|
|
50
|
-
_AltimeterCommand_regex = new WeakMap();
|
|
51
|
-
class AltimeterMercuryCommand {
|
|
52
|
-
constructor() {
|
|
53
|
-
_AltimeterMercuryCommand_regex.set(this, /^A(\d{4})$/);
|
|
54
|
-
}
|
|
55
|
-
canParse(input) {
|
|
56
|
-
return __classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f").test(input);
|
|
57
|
-
}
|
|
58
|
-
execute(metar, input) {
|
|
59
|
-
const matches = input.match(__classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f"));
|
|
60
|
-
if (!matches)
|
|
61
|
-
throw new errors_1.UnexpectedParseError("Match not found");
|
|
62
|
-
const mercury = +matches[1] / 100;
|
|
63
|
-
metar.altimeter = Math.trunc(converter.convertInchesMercuryToPascal(mercury));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
exports.AltimeterMercuryCommand = AltimeterMercuryCommand;
|
|
67
|
-
_AltimeterMercuryCommand_regex = new WeakMap();
|
|
68
|
-
class RunwayCommand {
|
|
69
|
-
constructor() {
|
|
70
|
-
_RunwayCommand_genericRegex.set(this, /^(R\d{2}\w?\/)/);
|
|
71
|
-
_RunwayCommand_runwayMaxRangeRegex.set(this, /^R(\d{2}\w?)\/(\d{4})V(\d{3})(\w{0,2})/);
|
|
72
|
-
_RunwayCommand_runwayRegex.set(this, /^R(\d{2}\w?)\/(\w)?(\d{4})(\w{0,2})$/);
|
|
73
|
-
}
|
|
74
|
-
canParse(input) {
|
|
75
|
-
return __classPrivateFieldGet(this, _RunwayCommand_genericRegex, "f").test(input);
|
|
76
|
-
}
|
|
77
|
-
execute(metar, input) {
|
|
78
|
-
const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f"));
|
|
79
|
-
// TODO idk if this matches super well...
|
|
80
|
-
if (matches) {
|
|
81
|
-
metar.runwaysInfo.push({
|
|
82
|
-
name: matches[1],
|
|
83
|
-
minRange: +matches[3],
|
|
84
|
-
trend: matches[4],
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
const maxRangeMatches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayMaxRangeRegex, "f"));
|
|
88
|
-
if (maxRangeMatches) {
|
|
89
|
-
metar.runwaysInfo.push({
|
|
90
|
-
name: maxRangeMatches[1],
|
|
91
|
-
minRange: +maxRangeMatches[2],
|
|
92
|
-
maxRange: +maxRangeMatches[3],
|
|
93
|
-
trend: maxRangeMatches[4],
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
exports.RunwayCommand = RunwayCommand;
|
|
99
|
-
_RunwayCommand_genericRegex = new WeakMap(), _RunwayCommand_runwayMaxRangeRegex = new WeakMap(), _RunwayCommand_runwayRegex = new WeakMap();
|
|
100
|
-
class TemperatureCommand {
|
|
101
|
-
constructor() {
|
|
102
|
-
_TemperatureCommand_regex.set(this, /^(M?\d{2})\/(M?\d{2})$/);
|
|
103
|
-
}
|
|
104
|
-
canParse(input) {
|
|
105
|
-
return __classPrivateFieldGet(this, _TemperatureCommand_regex, "f").test(input);
|
|
106
|
-
}
|
|
107
|
-
execute(metar, input) {
|
|
108
|
-
const matches = input.match(__classPrivateFieldGet(this, _TemperatureCommand_regex, "f"));
|
|
109
|
-
if (!matches)
|
|
110
|
-
throw new errors_1.UnexpectedParseError("Match not found");
|
|
111
|
-
metar.temperature = converter.convertTemperature(matches[1]);
|
|
112
|
-
metar.dewPoint = converter.convertTemperature(matches[2]);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
exports.TemperatureCommand = TemperatureCommand;
|
|
116
|
-
_TemperatureCommand_regex = new WeakMap();
|
|
9
|
+
exports.CommandSupplier = void 0;
|
|
10
|
+
const AltimeterCommand_1 = require("./metar/AltimeterCommand");
|
|
11
|
+
const AltimeterMercuryCommand_1 = require("./metar/AltimeterMercuryCommand");
|
|
12
|
+
const RunwayCommand_1 = require("./metar/RunwayCommand");
|
|
13
|
+
const TemperatureCommand_1 = require("./metar/TemperatureCommand");
|
|
117
14
|
class CommandSupplier {
|
|
118
15
|
constructor() {
|
|
119
16
|
_CommandSupplier_commands.set(this, [
|
|
120
|
-
new RunwayCommand(),
|
|
121
|
-
new TemperatureCommand(),
|
|
122
|
-
new AltimeterCommand(),
|
|
123
|
-
new AltimeterMercuryCommand(),
|
|
17
|
+
new RunwayCommand_1.RunwayCommand(),
|
|
18
|
+
new TemperatureCommand_1.TemperatureCommand(),
|
|
19
|
+
new AltimeterCommand_1.AltimeterCommand(),
|
|
20
|
+
new AltimeterMercuryCommand_1.AltimeterMercuryCommand(),
|
|
124
21
|
]);
|
|
125
22
|
}
|
|
126
23
|
get(input) {
|
|
127
|
-
for (
|
|
128
|
-
const command = __classPrivateFieldGet(this, _CommandSupplier_commands, "f")[i];
|
|
24
|
+
for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands, "f")) {
|
|
129
25
|
if (command.canParse(input))
|
|
130
26
|
return command;
|
|
131
27
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IBaseRemark, RemarkType, Remark } from "../remark";
|
|
2
|
+
import { Command } from "./Command";
|
|
3
|
+
export interface ICeilingHeightRemark extends IBaseRemark {
|
|
4
|
+
type: RemarkType.CeilingHeight;
|
|
5
|
+
/**
|
|
6
|
+
* Ceiling min height (varying between min and max) above ground level
|
|
7
|
+
*/
|
|
8
|
+
min: number;
|
|
9
|
+
/**
|
|
10
|
+
* Ceiling max height (varying between min and max) above ground level
|
|
11
|
+
*/
|
|
12
|
+
max: number;
|
|
13
|
+
}
|
|
14
|
+
export declare class CeilingHeightCommand extends Command {
|
|
15
|
+
#private;
|
|
16
|
+
canParse(code: string): boolean;
|
|
17
|
+
execute(code: string, remark: Remark[]): [string, Remark[]];
|
|
18
|
+
}
|