@ham2k/extension-sdk 0.5.0 → 0.5.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/dist/index.d.ts +1 -1
- package/dist/templateContext.js +20 -0
- package/dist/templates.js +9 -0
- package/docs/templates.md +24 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/templateContext.js
CHANGED
|
@@ -60,6 +60,7 @@ function qsoValues(qso) {
|
|
|
60
60
|
const their = qso.their ?? {};
|
|
61
61
|
const our = qso.our ?? {};
|
|
62
62
|
const startMillis = Number(qso.startAtMillis ?? 0);
|
|
63
|
+
const serialSent = refField(qso.refs, "ourSerial");
|
|
63
64
|
return {
|
|
64
65
|
call: their.call ?? "",
|
|
65
66
|
their,
|
|
@@ -71,12 +72,31 @@ function qsoValues(qso) {
|
|
|
71
72
|
// sides — `qso.our.sent` is what WE sent, i.e. the report they received.
|
|
72
73
|
rstSent: our.sent ?? "",
|
|
73
74
|
rstRcvd: their.sent ?? "",
|
|
75
|
+
// Unpadded, as stored: `001` or `1` is the operator's call, not the
|
|
76
|
+
// contest's, so it is left to the `pad` filter.
|
|
77
|
+
serialSent,
|
|
78
|
+
serialRcvd: refField(qso.refs, "theirSerial"),
|
|
79
|
+
// The short forms are the SENT side: a CW message is what we send, and
|
|
80
|
+
// that is where these get typed.
|
|
81
|
+
rst: our.sent ?? "",
|
|
82
|
+
serial: serialSent,
|
|
74
83
|
notes: qso.notes ?? "",
|
|
75
84
|
refs: qso.refs ?? [],
|
|
76
85
|
...startMillis > 0 ? dateValues(startMillis) : { date: "", dateCompact: "", time: "", at: "" },
|
|
77
86
|
startAtMillis: startMillis
|
|
78
87
|
};
|
|
79
88
|
}
|
|
89
|
+
function refField(refs, field) {
|
|
90
|
+
if (!Array.isArray(refs)) return "";
|
|
91
|
+
for (const ref of refs) {
|
|
92
|
+
if (ref === null || typeof ref !== "object" || Array.isArray(ref)) continue;
|
|
93
|
+
const value = ref[field];
|
|
94
|
+
if (typeof value !== "string" && typeof value !== "number") continue;
|
|
95
|
+
const text = String(value).trim();
|
|
96
|
+
if (text !== "") return text;
|
|
97
|
+
}
|
|
98
|
+
return "";
|
|
99
|
+
}
|
|
80
100
|
function logValues(values) {
|
|
81
101
|
return {
|
|
82
102
|
station: values.station ?? "",
|
package/dist/templates.js
CHANGED
|
@@ -30,7 +30,16 @@ function registerFilters(liquid2) {
|
|
|
30
30
|
(value) => String(value ?? "").replace(/[^A-Za-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")
|
|
31
31
|
);
|
|
32
32
|
liquid2.registerFilter("alnum", (value) => String(value ?? "").replace(/[^A-Za-z0-9]/g, ""));
|
|
33
|
+
liquid2.registerFilter("pad", (value, width = 3) => {
|
|
34
|
+
const text = String(value ?? "").trim();
|
|
35
|
+
return text === "" ? "" : text.padStart(Number(width) || 0, "0");
|
|
36
|
+
});
|
|
37
|
+
liquid2.registerFilter("cut", (value, digits = "09") => {
|
|
38
|
+
const chosen = String(digits ?? "");
|
|
39
|
+
return String(value ?? "").replace(/[0159]/g, (digit) => chosen.includes(digit) ? CUT_NUMBERS[digit] : digit);
|
|
40
|
+
});
|
|
33
41
|
}
|
|
42
|
+
const CUT_NUMBERS = { "0": "T", "1": "A", "5": "E", "9": "N" };
|
|
34
43
|
class TemplateError extends Error {
|
|
35
44
|
constructor(message, options) {
|
|
36
45
|
super(message);
|
package/docs/templates.md
CHANGED
|
@@ -74,12 +74,22 @@ that contact's length.
|
|
|
74
74
|
|
|
75
75
|
### `qso` — one contact
|
|
76
76
|
`call`, `their`, `our` (both whole, so `qso.their.guess.name` reaches the
|
|
77
|
-
lookup's answer), `band`, `mode`, `freq`, `rstSent`, `rstRcvd`, `
|
|
78
|
-
`date`, `dateCompact`, `time`, `at`, `startAtMillis`,
|
|
77
|
+
lookup's answer), `band`, `mode`, `freq`, `rstSent`, `rstRcvd`, `serialSent`,
|
|
78
|
+
`serialRcvd`, `notes`, `date`, `dateCompact`, `time`, `at`, `startAtMillis`,
|
|
79
|
+
`refs` — and two short forms for the sent side, `rst` (= `rstSent`) and
|
|
80
|
+
`serial` (= `serialSent`), since a CW message is what we send and that is
|
|
81
|
+
where these get typed: `{{ qso.call }} {{ qso.rst | cut }} {{ qso.serial | pad: 3 | cut }}`.
|
|
79
82
|
|
|
80
83
|
`rstSent` is what WE sent — QSON stores each side's report under its own
|
|
81
84
|
`sent`, and these are named for the operator's view of the contact.
|
|
82
85
|
|
|
86
|
+
`serialSent` / `serialRcvd` are a contest's serial numbers, blank outside
|
|
87
|
+
one. A contest keeps them on its own ref, so they are found by field name —
|
|
88
|
+
the first ref carrying `ourSerial` / `theirSerial` — which is what lets one
|
|
89
|
+
message serve every serial contest (docs/design/contests.md §5.8). In a CW
|
|
90
|
+
message `serialSent` is the number the serial field is SHOWING, the one the
|
|
91
|
+
QSO will be logged with. It is unpadded (`7`, not `007`): use `pad`.
|
|
92
|
+
|
|
83
93
|
### `config` — a panel's own form values
|
|
84
94
|
Whatever that panel's `form` declared, under the keys it used.
|
|
85
95
|
|
|
@@ -112,12 +122,19 @@ with nothing to say it was invented.
|
|
|
112
122
|
|
|
113
123
|
All of Liquid's own (`date`, `downcase`, `upcase`, `strip`, `default`,
|
|
114
124
|
`join`, `size`, `first`, `last`, `round`, `truncate`, `replace`, `map`,
|
|
115
|
-
`where`, …), plus
|
|
125
|
+
`where`, …), plus four:
|
|
116
126
|
|
|
117
127
|
| filter | does | example |
|
|
118
128
|
|---|---|---|
|
|
119
129
|
| `dash` | non-alphanumerics → `-`, collapsed and trimmed, **case preserved** | `N0CALL/P` → `N0CALL-P` |
|
|
120
130
|
| `alnum` | strip to alphanumerics | `2026-07-27` → `20260727` |
|
|
131
|
+
| `pad: n` | zero-pad on the left to `n` characters (default 3); **blank stays blank** | `7` → `007` |
|
|
132
|
+
| `cut: "digits"` | CW cut numbers for the listed digits, of `0`→`T` `1`→`A` `5`→`E` `9`→`N`; default `"09"` | `599` → `5NN`, `{{ 9 \| pad: 3 \| cut }}` → `TTN` |
|
|
133
|
+
|
|
134
|
+
`pad` leaves a blank alone because a CW message can be keyed before the
|
|
135
|
+
serial field has a number, and `000` sent in that gap is a serial the log
|
|
136
|
+
will never agree with. Order matters with `cut`: pad first, or the padding
|
|
137
|
+
zeros go out uncut.
|
|
121
138
|
|
|
122
139
|
`alnum` is app-polo's `compact` helper under a different name: Liquid already
|
|
123
140
|
has a `compact` (it drops nils from an **array**, and `op.refs`/`qso.refs` are
|
|
@@ -140,6 +157,10 @@ Each of these was measured against the shipped runtime, not assumed.
|
|
|
140
157
|
number as SECONDS, so epoch millis render in the year 58567. Use the `…At`
|
|
141
158
|
strings.
|
|
142
159
|
|
|
160
|
+
**`cut`'s digit list must be quoted.** Liquid reads a bare `0159` as the
|
|
161
|
+
number 159 before the filter sees it, so `{{ n | cut: 09 }}` cuts only the
|
|
162
|
+
nines — the zero is gone with no error. Write `cut: "09"`.
|
|
163
|
+
|
|
143
164
|
**Unknown names are silent.** An unknown variable renders empty and an
|
|
144
165
|
unknown filter passes its value through. That is deliberate — an operator's
|
|
145
166
|
typo costs one line, not the document — but it means a misspelled
|