ezmedicationinput 0.1.1 → 0.1.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.
- package/README.md +60 -20
- package/dist/context.js +10 -5
- package/dist/fhir.d.ts +1 -1
- package/dist/fhir.js +40 -32
- package/dist/format.d.ts +3 -2
- package/dist/format.js +371 -86
- package/dist/i18n.d.ts +31 -0
- package/dist/i18n.js +664 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +53 -19
- package/dist/internal-types.d.ts +33 -0
- package/dist/internal-types.js +2 -0
- package/dist/maps.d.ts +2 -0
- package/dist/maps.js +543 -350
- package/dist/package.json +3 -0
- package/dist/parser.d.ts +2 -31
- package/dist/parser.js +809 -142
- package/dist/safety.js +7 -4
- package/dist/schedule.js +148 -76
- package/dist/suggest.js +391 -79
- package/dist/types.d.ts +26 -8
- package/dist/types.js +12 -9
- package/dist/utils/array.d.ts +1 -0
- package/dist/utils/array.js +11 -0
- package/dist/utils/enum.d.ts +2 -0
- package/dist/utils/enum.js +7 -0
- package/dist/utils/object.d.ts +7 -0
- package/dist/utils/object.js +34 -0
- package/package.json +2 -2
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.THAI_SITE_TRANSLATIONS = exports.getRegisteredSigTranslations = exports.registerSigTranslation = void 0;
|
|
4
|
+
exports.registerSigLocalization = registerSigLocalization;
|
|
5
|
+
exports.getRegisteredSigLocalizations = getRegisteredSigLocalizations;
|
|
6
|
+
exports.resolveSigLocalization = resolveSigLocalization;
|
|
7
|
+
exports.resolveSigTranslation = resolveSigTranslation;
|
|
8
|
+
const types_1 = require("./types");
|
|
9
|
+
const REGISTERED_LOCALIZATIONS = new Map();
|
|
10
|
+
function registerSigLocalization(localization) {
|
|
11
|
+
REGISTERED_LOCALIZATIONS.set(localization.locale.toLowerCase(), localization);
|
|
12
|
+
}
|
|
13
|
+
function getRegisteredSigLocalizations() {
|
|
14
|
+
return Array.from(REGISTERED_LOCALIZATIONS.values());
|
|
15
|
+
}
|
|
16
|
+
function resolveSigLocalization(locale, config) {
|
|
17
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
18
|
+
const normalizedLocale = (_a = config === null || config === void 0 ? void 0 : config.locale) !== null && _a !== void 0 ? _a : locale;
|
|
19
|
+
const targetKey = normalizedLocale === null || normalizedLocale === void 0 ? void 0 : normalizedLocale.toLowerCase();
|
|
20
|
+
const base = targetKey ? REGISTERED_LOCALIZATIONS.get(targetKey) : undefined;
|
|
21
|
+
const inherited = (config === null || config === void 0 ? void 0 : config.inherit)
|
|
22
|
+
? REGISTERED_LOCALIZATIONS.get(config.inherit.toLowerCase())
|
|
23
|
+
: undefined;
|
|
24
|
+
if (!base && !inherited && !config) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const resolvedLocale = (_f = (_e = (_d = (_c = (_b = config === null || config === void 0 ? void 0 : config.locale) !== null && _b !== void 0 ? _b : config === null || config === void 0 ? void 0 : config.inherit) !== null && _c !== void 0 ? _c : base === null || base === void 0 ? void 0 : base.locale) !== null && _d !== void 0 ? _d : inherited === null || inherited === void 0 ? void 0 : inherited.locale) !== null && _e !== void 0 ? _e : targetKey) !== null && _f !== void 0 ? _f : "custom";
|
|
28
|
+
const result = {
|
|
29
|
+
locale: resolvedLocale
|
|
30
|
+
};
|
|
31
|
+
if (base === null || base === void 0 ? void 0 : base.formatShort) {
|
|
32
|
+
result.formatShort = base.formatShort;
|
|
33
|
+
}
|
|
34
|
+
if (base === null || base === void 0 ? void 0 : base.formatLong) {
|
|
35
|
+
result.formatLong = base.formatLong;
|
|
36
|
+
}
|
|
37
|
+
if (inherited === null || inherited === void 0 ? void 0 : inherited.formatShort) {
|
|
38
|
+
result.formatShort = inherited.formatShort;
|
|
39
|
+
}
|
|
40
|
+
if (inherited === null || inherited === void 0 ? void 0 : inherited.formatLong) {
|
|
41
|
+
result.formatLong = inherited.formatLong;
|
|
42
|
+
}
|
|
43
|
+
if ((config === null || config === void 0 ? void 0 : config.formatShort) !== undefined) {
|
|
44
|
+
result.formatShort = config.formatShort;
|
|
45
|
+
}
|
|
46
|
+
if ((config === null || config === void 0 ? void 0 : config.formatLong) !== undefined) {
|
|
47
|
+
result.formatLong = config.formatLong;
|
|
48
|
+
}
|
|
49
|
+
if (!result.formatShort && !result.formatLong) {
|
|
50
|
+
return (_g = base !== null && base !== void 0 ? base : inherited) !== null && _g !== void 0 ? _g : result;
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
registerSigLocalization({
|
|
55
|
+
locale: "en",
|
|
56
|
+
formatShort: ({ defaultText }) => defaultText,
|
|
57
|
+
formatLong: ({ defaultText }) => defaultText
|
|
58
|
+
});
|
|
59
|
+
exports.registerSigTranslation = registerSigLocalization;
|
|
60
|
+
exports.getRegisteredSigTranslations = getRegisteredSigLocalizations;
|
|
61
|
+
function resolveSigTranslation(locale, config) {
|
|
62
|
+
return resolveSigLocalization(locale, config);
|
|
63
|
+
}
|
|
64
|
+
function createThaiLocalization() {
|
|
65
|
+
return {
|
|
66
|
+
locale: "th",
|
|
67
|
+
formatShort: ({ internal }) => formatShortThai(internal),
|
|
68
|
+
formatLong: ({ internal }) => formatLongThai(internal)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
registerSigLocalization(createThaiLocalization());
|
|
72
|
+
// Thai formatting helpers
|
|
73
|
+
const ROUTE_SHORT = {
|
|
74
|
+
[types_1.RouteCode["Oral route"]]: "PO",
|
|
75
|
+
[types_1.RouteCode["Sublingual route"]]: "SL",
|
|
76
|
+
[types_1.RouteCode["Buccal route"]]: "BUC",
|
|
77
|
+
[types_1.RouteCode["Respiratory tract route (qualifier value)"]]: "INH",
|
|
78
|
+
[types_1.RouteCode["Nasal route"]]: "IN",
|
|
79
|
+
[types_1.RouteCode["Topical route"]]: "TOP",
|
|
80
|
+
[types_1.RouteCode["Transdermal route"]]: "TD",
|
|
81
|
+
[types_1.RouteCode["Subcutaneous route"]]: "SC",
|
|
82
|
+
[types_1.RouteCode["Intramuscular route"]]: "IM",
|
|
83
|
+
[types_1.RouteCode["Intravenous route"]]: "IV",
|
|
84
|
+
[types_1.RouteCode["Per rectum"]]: "PR",
|
|
85
|
+
[types_1.RouteCode["Per vagina"]]: "PV",
|
|
86
|
+
[types_1.RouteCode["Ophthalmic route"]]: "OPH",
|
|
87
|
+
[types_1.RouteCode["Otic route"]]: "OT",
|
|
88
|
+
[types_1.RouteCode["Intravitreal route (qualifier value)"]]: "IVT"
|
|
89
|
+
};
|
|
90
|
+
const WHEN_TEXT_THAI = {
|
|
91
|
+
[types_1.EventTiming["Before Sleep"]]: "ก่อนนอน",
|
|
92
|
+
[types_1.EventTiming["Before Meal"]]: "ก่อนอาหาร",
|
|
93
|
+
[types_1.EventTiming["Before Breakfast"]]: "ก่อนอาหารเช้า",
|
|
94
|
+
[types_1.EventTiming["Before Lunch"]]: "ก่อนอาหารกลางวัน",
|
|
95
|
+
[types_1.EventTiming["Before Dinner"]]: "ก่อนอาหารเย็น",
|
|
96
|
+
[types_1.EventTiming["After Meal"]]: "หลังอาหาร",
|
|
97
|
+
[types_1.EventTiming["After Breakfast"]]: "หลังอาหารเช้า",
|
|
98
|
+
[types_1.EventTiming["After Lunch"]]: "หลังอาหารกลางวัน",
|
|
99
|
+
[types_1.EventTiming["After Dinner"]]: "หลังอาหารเย็น",
|
|
100
|
+
[types_1.EventTiming.Meal]: "พร้อมอาหาร",
|
|
101
|
+
[types_1.EventTiming.Breakfast]: "พร้อมอาหารเช้า",
|
|
102
|
+
[types_1.EventTiming.Lunch]: "พร้อมอาหารกลางวัน",
|
|
103
|
+
[types_1.EventTiming.Dinner]: "พร้อมอาหารเย็น",
|
|
104
|
+
[types_1.EventTiming.Morning]: "ตอนเช้า",
|
|
105
|
+
[types_1.EventTiming["Early Morning"]]: "เช้าตรู่",
|
|
106
|
+
[types_1.EventTiming["Late Morning"]]: "สาย",
|
|
107
|
+
[types_1.EventTiming.Noon]: "ตอนเที่ยง",
|
|
108
|
+
[types_1.EventTiming.Afternoon]: "ตอนบ่าย",
|
|
109
|
+
[types_1.EventTiming["Early Afternoon"]]: "บ่ายต้น",
|
|
110
|
+
[types_1.EventTiming["Late Afternoon"]]: "บ่ายแก่",
|
|
111
|
+
[types_1.EventTiming.Evening]: "ตอนเย็น",
|
|
112
|
+
[types_1.EventTiming["Early Evening"]]: "หัวค่ำ",
|
|
113
|
+
[types_1.EventTiming["Late Evening"]]: "ดึก",
|
|
114
|
+
[types_1.EventTiming.Night]: "ตอนกลางคืน",
|
|
115
|
+
[types_1.EventTiming.Wake]: "หลังตื่นนอน",
|
|
116
|
+
[types_1.EventTiming["After Sleep"]]: "หลังจากนอน",
|
|
117
|
+
[types_1.EventTiming.Immediate]: "ทันที"
|
|
118
|
+
};
|
|
119
|
+
const DAY_NAMES_THAI = {
|
|
120
|
+
mon: "วันจันทร์",
|
|
121
|
+
tue: "วันอังคาร",
|
|
122
|
+
wed: "วันพุธ",
|
|
123
|
+
thu: "วันพฤหัสบดี",
|
|
124
|
+
fri: "วันศุกร์",
|
|
125
|
+
sat: "วันเสาร์",
|
|
126
|
+
sun: "วันอาทิตย์"
|
|
127
|
+
};
|
|
128
|
+
exports.THAI_SITE_TRANSLATIONS = {
|
|
129
|
+
"right eye": "ตาขวา",
|
|
130
|
+
"left eye": "ตาซ้าย",
|
|
131
|
+
"both eyes": "ตาทั้งสองข้าง",
|
|
132
|
+
"right ear": "หูขวา",
|
|
133
|
+
"left ear": "หูซ้าย",
|
|
134
|
+
"both ears": "หูทั้งสองข้าง",
|
|
135
|
+
ear: "หู",
|
|
136
|
+
ears: "หูทั้งสองข้าง",
|
|
137
|
+
"right nostril": "รูจมูกขวา",
|
|
138
|
+
"left nostril": "รูจมูกซ้าย",
|
|
139
|
+
"both nostrils": "รูจมูกทั้งสองข้าง",
|
|
140
|
+
"right arm": "แขนขวา",
|
|
141
|
+
"left arm": "แขนซ้าย",
|
|
142
|
+
"both arms": "แขนทั้งสองข้าง",
|
|
143
|
+
"right leg": "ขาขวา",
|
|
144
|
+
"left leg": "ขาซ้าย",
|
|
145
|
+
"both legs": "ขาทั้งสองข้าง",
|
|
146
|
+
"right hand": "มือขวา",
|
|
147
|
+
"left hand": "มือซ้าย",
|
|
148
|
+
"both hands": "มือทั้งสองข้าง",
|
|
149
|
+
"right foot": "เท้าขวา",
|
|
150
|
+
"left foot": "เท้าซ้าย",
|
|
151
|
+
"both feet": "เท้าทั้งสองข้าง",
|
|
152
|
+
abdomen: "ช่องท้อง",
|
|
153
|
+
belly: "ท้อง",
|
|
154
|
+
back: "แผ่นหลัง",
|
|
155
|
+
cheek: "แก้ม",
|
|
156
|
+
cheeks: "แก้มทั้งสองข้าง",
|
|
157
|
+
forearm: "ปลายแขน",
|
|
158
|
+
shoulder: "ไหล่",
|
|
159
|
+
shoulders: "ไหล่ทั้งสองข้าง",
|
|
160
|
+
thigh: "ต้นขา",
|
|
161
|
+
thighs: "ต้นขาทั้งสองข้าง"
|
|
162
|
+
};
|
|
163
|
+
const DEFAULT_THAI_ROUTE_GRAMMAR = { verb: "ใช้" };
|
|
164
|
+
const THAI_ROUTE_GRAMMAR = {
|
|
165
|
+
[types_1.RouteCode["Oral route"]]: { verb: "รับประทาน", routePhrase: "ทางปาก" },
|
|
166
|
+
[types_1.RouteCode["Sublingual route"]]: { verb: "อมใต้ลิ้น", routePhrase: "ใต้ลิ้น" },
|
|
167
|
+
[types_1.RouteCode["Buccal route"]]: { verb: "อมกระพุ้งแก้ม", routePhrase: "ที่กระพุ้งแก้ม" },
|
|
168
|
+
[types_1.RouteCode["Respiratory tract route (qualifier value)"]]: {
|
|
169
|
+
verb: "สูด",
|
|
170
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "โดยการสูดดม"),
|
|
171
|
+
sitePreposition: "ที่"
|
|
172
|
+
},
|
|
173
|
+
[types_1.RouteCode["Nasal route"]]: {
|
|
174
|
+
verb: "พ่น",
|
|
175
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "ทางจมูก"),
|
|
176
|
+
sitePreposition: "ที่"
|
|
177
|
+
},
|
|
178
|
+
[types_1.RouteCode["Topical route"]]: {
|
|
179
|
+
verb: "ทา",
|
|
180
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "บริเวณผิวหนัง"),
|
|
181
|
+
sitePreposition: "บริเวณ"
|
|
182
|
+
},
|
|
183
|
+
[types_1.RouteCode["Transdermal route"]]: {
|
|
184
|
+
verb: "ติด",
|
|
185
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "แบบแผ่นแปะผิวหนัง"),
|
|
186
|
+
sitePreposition: "บริเวณ"
|
|
187
|
+
},
|
|
188
|
+
[types_1.RouteCode["Subcutaneous route"]]: {
|
|
189
|
+
verb: "ฉีด",
|
|
190
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "เข้าใต้ผิวหนัง"),
|
|
191
|
+
sitePreposition: "ที่"
|
|
192
|
+
},
|
|
193
|
+
[types_1.RouteCode["Intramuscular route"]]: {
|
|
194
|
+
verb: "ฉีด",
|
|
195
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "เข้ากล้ามเนื้อ"),
|
|
196
|
+
sitePreposition: "ที่"
|
|
197
|
+
},
|
|
198
|
+
[types_1.RouteCode["Intravenous route"]]: {
|
|
199
|
+
verb: "ฉีด",
|
|
200
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "เข้าหลอดเลือดดำ"),
|
|
201
|
+
sitePreposition: "ที่"
|
|
202
|
+
},
|
|
203
|
+
[types_1.RouteCode["Per rectum"]]: {
|
|
204
|
+
verb: "สอด",
|
|
205
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "ทางทวารหนัก"),
|
|
206
|
+
sitePreposition: "ที่"
|
|
207
|
+
},
|
|
208
|
+
[types_1.RouteCode["Per vagina"]]: {
|
|
209
|
+
verb: "สอด",
|
|
210
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "ทางช่องคลอด"),
|
|
211
|
+
sitePreposition: "ที่"
|
|
212
|
+
},
|
|
213
|
+
[types_1.RouteCode["Ophthalmic route"]]: {
|
|
214
|
+
verb: "หยอด",
|
|
215
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "ที่ดวงตา"),
|
|
216
|
+
sitePreposition: "ที่"
|
|
217
|
+
},
|
|
218
|
+
[types_1.RouteCode["Otic route"]]: {
|
|
219
|
+
verb: "หยอด",
|
|
220
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "ที่หู"),
|
|
221
|
+
sitePreposition: "ที่"
|
|
222
|
+
},
|
|
223
|
+
[types_1.RouteCode["Intravitreal route (qualifier value)"]]: {
|
|
224
|
+
verb: "ฉีด",
|
|
225
|
+
routePhrase: ({ hasSite }) => (hasSite ? undefined : "เข้าดวงตา"),
|
|
226
|
+
sitePreposition: "ที่"
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
function resolveRouteGrammarThai(internal) {
|
|
230
|
+
var _a;
|
|
231
|
+
if (internal.routeCode && THAI_ROUTE_GRAMMAR[internal.routeCode]) {
|
|
232
|
+
return (_a = THAI_ROUTE_GRAMMAR[internal.routeCode]) !== null && _a !== void 0 ? _a : DEFAULT_THAI_ROUTE_GRAMMAR;
|
|
233
|
+
}
|
|
234
|
+
const grammar = grammarFromRouteTextThai(internal.routeText);
|
|
235
|
+
return grammar !== null && grammar !== void 0 ? grammar : DEFAULT_THAI_ROUTE_GRAMMAR;
|
|
236
|
+
}
|
|
237
|
+
function grammarFromRouteTextThai(text) {
|
|
238
|
+
if (!text)
|
|
239
|
+
return undefined;
|
|
240
|
+
const normalized = text.trim().toLowerCase();
|
|
241
|
+
if (!normalized)
|
|
242
|
+
return undefined;
|
|
243
|
+
if (normalized.includes("mouth") || normalized.includes("oral")) {
|
|
244
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Oral route"]];
|
|
245
|
+
}
|
|
246
|
+
if (normalized.includes("ophthalm")) {
|
|
247
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Ophthalmic route"]];
|
|
248
|
+
}
|
|
249
|
+
if (normalized.includes("intravitreal")) {
|
|
250
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Intravitreal route (qualifier value)"]];
|
|
251
|
+
}
|
|
252
|
+
if (normalized.includes("topical")) {
|
|
253
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Topical route"]];
|
|
254
|
+
}
|
|
255
|
+
if (normalized.includes("transdermal")) {
|
|
256
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Transdermal route"]];
|
|
257
|
+
}
|
|
258
|
+
if (normalized.includes("subcutaneous") || normalized === "sc" || normalized === "sq") {
|
|
259
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Subcutaneous route"]];
|
|
260
|
+
}
|
|
261
|
+
if (normalized.includes("intramuscular") || normalized === "im") {
|
|
262
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Intramuscular route"]];
|
|
263
|
+
}
|
|
264
|
+
if (normalized.includes("intravenous") || normalized === "iv") {
|
|
265
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Intravenous route"]];
|
|
266
|
+
}
|
|
267
|
+
if (normalized.includes("nasal")) {
|
|
268
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Nasal route"]];
|
|
269
|
+
}
|
|
270
|
+
if (normalized.includes("inhal")) {
|
|
271
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Respiratory tract route (qualifier value)"]];
|
|
272
|
+
}
|
|
273
|
+
return undefined;
|
|
274
|
+
}
|
|
275
|
+
function formatDoseThaiShort(internal) {
|
|
276
|
+
if (internal.doseRange) {
|
|
277
|
+
const { low, high } = internal.doseRange;
|
|
278
|
+
const base = `${stripTrailingZero(low)}-${stripTrailingZero(high)}`;
|
|
279
|
+
if (internal.unit) {
|
|
280
|
+
return `${base} ${formatUnitThai(internal.unit, high, "short")}`;
|
|
281
|
+
}
|
|
282
|
+
return base;
|
|
283
|
+
}
|
|
284
|
+
if (internal.dose !== undefined) {
|
|
285
|
+
const amount = stripTrailingZero(internal.dose);
|
|
286
|
+
if (internal.unit) {
|
|
287
|
+
return `${amount} ${formatUnitThai(internal.unit, internal.dose, "short")}`;
|
|
288
|
+
}
|
|
289
|
+
return amount;
|
|
290
|
+
}
|
|
291
|
+
return undefined;
|
|
292
|
+
}
|
|
293
|
+
function formatDoseThaiLong(internal) {
|
|
294
|
+
if (internal.doseRange) {
|
|
295
|
+
const { low, high } = internal.doseRange;
|
|
296
|
+
if (internal.unit) {
|
|
297
|
+
const unit = formatUnitThai(internal.unit, high, "long");
|
|
298
|
+
return `ครั้งละ ${stripTrailingZero(low)} ถึง ${stripTrailingZero(high)} ${unit}`;
|
|
299
|
+
}
|
|
300
|
+
return `ครั้งละ ${stripTrailingZero(low)} ถึง ${stripTrailingZero(high)}`;
|
|
301
|
+
}
|
|
302
|
+
if (internal.dose !== undefined) {
|
|
303
|
+
if (internal.unit) {
|
|
304
|
+
const unit = formatUnitThai(internal.unit, internal.dose, "long");
|
|
305
|
+
return `ครั้งละ ${stripTrailingZero(internal.dose)} ${unit}`;
|
|
306
|
+
}
|
|
307
|
+
return `ครั้งละ ${stripTrailingZero(internal.dose)}`;
|
|
308
|
+
}
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
function formatUnitThai(unit, value, style) {
|
|
312
|
+
const lower = unit.toLowerCase();
|
|
313
|
+
const quantity = Math.abs(value);
|
|
314
|
+
const mapping = {
|
|
315
|
+
tab: { short: "เม็ด", long: "เม็ด" },
|
|
316
|
+
tablet: { short: "เม็ด", long: "เม็ด" },
|
|
317
|
+
cap: { short: "แคปซูล", long: "แคปซูล" },
|
|
318
|
+
capsule: { short: "แคปซูล", long: "แคปซูล" },
|
|
319
|
+
ml: { short: "มล.", long: "มิลลิลิตร" },
|
|
320
|
+
milliliter: { short: "มล.", long: "มิลลิลิตร" },
|
|
321
|
+
milliliters: { short: "มล.", long: "มิลลิลิตร" },
|
|
322
|
+
mg: { short: "มก.", long: "มิลลิกรัม" },
|
|
323
|
+
mcg: { short: "ไมโครกรัม", long: "ไมโครกรัม" },
|
|
324
|
+
ug: { short: "ไมโครกรัม", long: "ไมโครกรัม" },
|
|
325
|
+
puff: { short: "พัฟ", long: "พัฟ" },
|
|
326
|
+
puffs: { short: "พัฟ", long: "พัฟ" },
|
|
327
|
+
spray: { short: "พ่น", long: "พ่น" },
|
|
328
|
+
sprays: { short: "พ่น", long: "พ่น" },
|
|
329
|
+
drop: { short: "หยด", long: "หยด" },
|
|
330
|
+
drops: { short: "หยด", long: "หยด" },
|
|
331
|
+
patch: { short: "แผ่น", long: "แผ่นแปะ" },
|
|
332
|
+
patches: { short: "แผ่น", long: "แผ่นแปะ" },
|
|
333
|
+
suppository: { short: "ยาเหน็บ", long: "ยาเหน็บ" },
|
|
334
|
+
suppositories: { short: "ยาเหน็บ", long: "ยาเหน็บ" }
|
|
335
|
+
};
|
|
336
|
+
const entry = mapping[lower];
|
|
337
|
+
if (entry) {
|
|
338
|
+
return style === "short" ? entry.short : entry.long;
|
|
339
|
+
}
|
|
340
|
+
return unit;
|
|
341
|
+
}
|
|
342
|
+
function describeFrequencyThai(internal) {
|
|
343
|
+
const { frequency, frequencyMax, period, periodMax, periodUnit, timingCode } = internal;
|
|
344
|
+
if (frequency !== undefined &&
|
|
345
|
+
frequencyMax !== undefined &&
|
|
346
|
+
periodUnit === types_1.FhirPeriodUnit.Day &&
|
|
347
|
+
(!period || period === 1)) {
|
|
348
|
+
if (frequency === 1 && frequencyMax === 1) {
|
|
349
|
+
return "วันละครั้ง";
|
|
350
|
+
}
|
|
351
|
+
if (frequency === 1 && frequencyMax === 2) {
|
|
352
|
+
return "วันละ 1 ถึง 2 ครั้ง";
|
|
353
|
+
}
|
|
354
|
+
return `วันละ ${stripTrailingZero(frequency)} ถึง ${stripTrailingZero(frequencyMax)} ครั้ง`;
|
|
355
|
+
}
|
|
356
|
+
if (frequency && periodUnit === types_1.FhirPeriodUnit.Day && (!period || period === 1)) {
|
|
357
|
+
if (frequency === 1)
|
|
358
|
+
return "วันละครั้ง";
|
|
359
|
+
if (frequency === 2)
|
|
360
|
+
return "วันละ 2 ครั้ง";
|
|
361
|
+
if (frequency === 3)
|
|
362
|
+
return "วันละ 3 ครั้ง";
|
|
363
|
+
if (frequency === 4)
|
|
364
|
+
return "วันละ 4 ครั้ง";
|
|
365
|
+
return `วันละ ${stripTrailingZero(frequency)} ครั้ง`;
|
|
366
|
+
}
|
|
367
|
+
if (periodUnit === types_1.FhirPeriodUnit.Hour && period) {
|
|
368
|
+
if (periodMax && periodMax !== period) {
|
|
369
|
+
return `ทุก ${stripTrailingZero(period)} ถึง ${stripTrailingZero(periodMax)} ชั่วโมง`;
|
|
370
|
+
}
|
|
371
|
+
return `ทุก ${stripTrailingZero(period)} ชั่วโมง`;
|
|
372
|
+
}
|
|
373
|
+
if (periodUnit === types_1.FhirPeriodUnit.Day && period && period !== 1) {
|
|
374
|
+
if (period === 2 && (!periodMax || periodMax === 2)) {
|
|
375
|
+
return "วันเว้นวัน";
|
|
376
|
+
}
|
|
377
|
+
if (periodMax && periodMax !== period) {
|
|
378
|
+
return `ทุก ${stripTrailingZero(period)} ถึง ${stripTrailingZero(periodMax)} วัน`;
|
|
379
|
+
}
|
|
380
|
+
return `ทุก ${stripTrailingZero(period)} วัน`;
|
|
381
|
+
}
|
|
382
|
+
if (periodUnit === types_1.FhirPeriodUnit.Week && period) {
|
|
383
|
+
if (period === 1 && (!periodMax || periodMax === 1)) {
|
|
384
|
+
return "สัปดาห์ละครั้ง";
|
|
385
|
+
}
|
|
386
|
+
if (periodMax && periodMax !== period) {
|
|
387
|
+
return `ทุก ${stripTrailingZero(period)} ถึง ${stripTrailingZero(periodMax)} สัปดาห์`;
|
|
388
|
+
}
|
|
389
|
+
return `ทุก ${stripTrailingZero(period)} สัปดาห์`;
|
|
390
|
+
}
|
|
391
|
+
if (periodUnit === types_1.FhirPeriodUnit.Month && period) {
|
|
392
|
+
if (period === 1 && (!periodMax || periodMax === 1)) {
|
|
393
|
+
return "เดือนละครั้ง";
|
|
394
|
+
}
|
|
395
|
+
if (periodMax && periodMax !== period) {
|
|
396
|
+
return `ทุก ${stripTrailingZero(period)} ถึง ${stripTrailingZero(periodMax)} เดือน`;
|
|
397
|
+
}
|
|
398
|
+
return `ทุก ${stripTrailingZero(period)} เดือน`;
|
|
399
|
+
}
|
|
400
|
+
if (timingCode) {
|
|
401
|
+
const map = {
|
|
402
|
+
BID: "วันละ 2 ครั้ง",
|
|
403
|
+
TID: "วันละ 3 ครั้ง",
|
|
404
|
+
QID: "วันละ 4 ครั้ง",
|
|
405
|
+
QD: "วันละครั้ง",
|
|
406
|
+
QOD: "วันเว้นวัน",
|
|
407
|
+
Q6H: "ทุก 6 ชั่วโมง",
|
|
408
|
+
Q8H: "ทุก 8 ชั่วโมง",
|
|
409
|
+
WK: "สัปดาห์ละครั้ง",
|
|
410
|
+
MO: "เดือนละครั้ง"
|
|
411
|
+
};
|
|
412
|
+
const value = map[timingCode.toUpperCase()];
|
|
413
|
+
if (value) {
|
|
414
|
+
return value;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (frequency && periodUnit === undefined && period === undefined) {
|
|
418
|
+
if (frequency === 1)
|
|
419
|
+
return "ครั้งเดียว";
|
|
420
|
+
return `${stripTrailingZero(frequency)} ครั้ง`;
|
|
421
|
+
}
|
|
422
|
+
return undefined;
|
|
423
|
+
}
|
|
424
|
+
function collectWhenPhrasesThai(internal) {
|
|
425
|
+
if (!internal.when.length) {
|
|
426
|
+
return [];
|
|
427
|
+
}
|
|
428
|
+
const unique = [];
|
|
429
|
+
const seen = new Set();
|
|
430
|
+
for (const code of internal.when) {
|
|
431
|
+
if (!seen.has(code)) {
|
|
432
|
+
seen.add(code);
|
|
433
|
+
unique.push(code);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
const hasSpecificAfter = unique.some((code) => code === types_1.EventTiming["After Breakfast"] ||
|
|
437
|
+
code === types_1.EventTiming["After Lunch"] ||
|
|
438
|
+
code === types_1.EventTiming["After Dinner"]);
|
|
439
|
+
const hasSpecificBefore = unique.some((code) => code === types_1.EventTiming["Before Breakfast"] ||
|
|
440
|
+
code === types_1.EventTiming["Before Lunch"] ||
|
|
441
|
+
code === types_1.EventTiming["Before Dinner"]);
|
|
442
|
+
const hasSpecificWith = unique.some((code) => code === types_1.EventTiming.Breakfast ||
|
|
443
|
+
code === types_1.EventTiming.Lunch ||
|
|
444
|
+
code === types_1.EventTiming.Dinner);
|
|
445
|
+
return unique
|
|
446
|
+
.filter((code) => {
|
|
447
|
+
if (code === types_1.EventTiming["After Meal"] && hasSpecificAfter) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
if (code === types_1.EventTiming["Before Meal"] && hasSpecificBefore) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
if (code === types_1.EventTiming.Meal && hasSpecificWith) {
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
return true;
|
|
457
|
+
})
|
|
458
|
+
.map((code) => { var _a; return (_a = WHEN_TEXT_THAI[code]) !== null && _a !== void 0 ? _a : undefined; })
|
|
459
|
+
.filter((text) => Boolean(text));
|
|
460
|
+
}
|
|
461
|
+
function joinWithAndThai(parts) {
|
|
462
|
+
if (!parts.length) {
|
|
463
|
+
return "";
|
|
464
|
+
}
|
|
465
|
+
if (parts.length === 1) {
|
|
466
|
+
return parts[0];
|
|
467
|
+
}
|
|
468
|
+
if (parts.length === 2) {
|
|
469
|
+
return `${parts[0]} และ ${parts[1]}`;
|
|
470
|
+
}
|
|
471
|
+
return `${parts.slice(0, -1).join(", ")} และ ${parts[parts.length - 1]}`;
|
|
472
|
+
}
|
|
473
|
+
function combineFrequencyAndEventsThai(frequency, events) {
|
|
474
|
+
if (!frequency) {
|
|
475
|
+
if (!events.length) {
|
|
476
|
+
return {};
|
|
477
|
+
}
|
|
478
|
+
return { event: joinWithAndThai(events) };
|
|
479
|
+
}
|
|
480
|
+
if (!events.length) {
|
|
481
|
+
return { frequency };
|
|
482
|
+
}
|
|
483
|
+
if (events.length === 1 && events[0] === "ก่อนนอน") {
|
|
484
|
+
if (frequency.includes("วันละ")) {
|
|
485
|
+
return { frequency: `${frequency} และ ${events[0]}` };
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return { frequency, event: joinWithAndThai(events) };
|
|
489
|
+
}
|
|
490
|
+
function buildRoutePhraseThai(internal, grammar, hasSite) {
|
|
491
|
+
var _a;
|
|
492
|
+
if (typeof grammar.routePhrase === "function") {
|
|
493
|
+
return grammar.routePhrase({ hasSite, internal });
|
|
494
|
+
}
|
|
495
|
+
if (typeof grammar.routePhrase === "string") {
|
|
496
|
+
return grammar.routePhrase;
|
|
497
|
+
}
|
|
498
|
+
const text = (_a = internal.routeText) === null || _a === void 0 ? void 0 : _a.trim();
|
|
499
|
+
if (!text) {
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
const normalized = text.toLowerCase();
|
|
503
|
+
if (normalized.startsWith("by ") || normalized.startsWith("per ") || normalized.startsWith("via ")) {
|
|
504
|
+
return text;
|
|
505
|
+
}
|
|
506
|
+
if (normalized === "oral") {
|
|
507
|
+
return "ทางปาก";
|
|
508
|
+
}
|
|
509
|
+
if (normalized === "intravenous") {
|
|
510
|
+
return "เข้าหลอดเลือดดำ";
|
|
511
|
+
}
|
|
512
|
+
if (normalized === "intramuscular") {
|
|
513
|
+
return "เข้ากล้ามเนื้อ";
|
|
514
|
+
}
|
|
515
|
+
if (normalized === "subcutaneous") {
|
|
516
|
+
return "เข้าใต้ผิวหนัง";
|
|
517
|
+
}
|
|
518
|
+
if (normalized === "topical") {
|
|
519
|
+
return "บริเวณผิวหนัง";
|
|
520
|
+
}
|
|
521
|
+
if (normalized === "transdermal") {
|
|
522
|
+
return "แบบแผ่นแปะผิวหนัง";
|
|
523
|
+
}
|
|
524
|
+
if (normalized === "intranasal" || normalized === "nasal") {
|
|
525
|
+
return "ทางจมูก";
|
|
526
|
+
}
|
|
527
|
+
if (normalized.includes("inhal")) {
|
|
528
|
+
return "โดยการสูดดม";
|
|
529
|
+
}
|
|
530
|
+
return text;
|
|
531
|
+
}
|
|
532
|
+
function formatSiteThai(internal, grammar) {
|
|
533
|
+
var _a, _b;
|
|
534
|
+
const text = (_a = internal.siteText) === null || _a === void 0 ? void 0 : _a.trim();
|
|
535
|
+
if (!text) {
|
|
536
|
+
return undefined;
|
|
537
|
+
}
|
|
538
|
+
const translated = translateSiteThai(text);
|
|
539
|
+
const preposition = (_b = grammar.sitePreposition) !== null && _b !== void 0 ? _b : "ที่";
|
|
540
|
+
const separator = /^[\u0E00-\u0E7F]/.test(translated) ? "" : " ";
|
|
541
|
+
return `${preposition}${separator}${translated}`.trim();
|
|
542
|
+
}
|
|
543
|
+
function translateSiteThai(site) {
|
|
544
|
+
var _a;
|
|
545
|
+
const normalized = site.trim().toLowerCase().replace(/\s+/g, " ");
|
|
546
|
+
if (!normalized) {
|
|
547
|
+
return site;
|
|
548
|
+
}
|
|
549
|
+
return (_a = exports.THAI_SITE_TRANSLATIONS[normalized]) !== null && _a !== void 0 ? _a : site;
|
|
550
|
+
}
|
|
551
|
+
function describeDayOfWeekThai(internal) {
|
|
552
|
+
if (!internal.dayOfWeek.length) {
|
|
553
|
+
return undefined;
|
|
554
|
+
}
|
|
555
|
+
const days = internal.dayOfWeek
|
|
556
|
+
.map((d) => { var _a; return (_a = DAY_NAMES_THAI[d]) !== null && _a !== void 0 ? _a : undefined; })
|
|
557
|
+
.filter((d) => Boolean(d));
|
|
558
|
+
if (!days.length) {
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
return `ใน${joinWithAndThai(days)}`;
|
|
562
|
+
}
|
|
563
|
+
function formatAsNeededThai(internal) {
|
|
564
|
+
if (!internal.asNeeded) {
|
|
565
|
+
return undefined;
|
|
566
|
+
}
|
|
567
|
+
if (internal.asNeededReason) {
|
|
568
|
+
return `ใช้เมื่อจำเป็นสำหรับ ${internal.asNeededReason}`;
|
|
569
|
+
}
|
|
570
|
+
return "ใช้เมื่อจำเป็น";
|
|
571
|
+
}
|
|
572
|
+
function formatShortThai(internal) {
|
|
573
|
+
const parts = [];
|
|
574
|
+
const dose = formatDoseThaiShort(internal);
|
|
575
|
+
if (dose) {
|
|
576
|
+
parts.push(dose);
|
|
577
|
+
}
|
|
578
|
+
if (internal.routeCode) {
|
|
579
|
+
const short = ROUTE_SHORT[internal.routeCode];
|
|
580
|
+
if (short) {
|
|
581
|
+
parts.push(short);
|
|
582
|
+
}
|
|
583
|
+
else if (internal.routeText) {
|
|
584
|
+
parts.push(internal.routeText);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
else if (internal.routeText) {
|
|
588
|
+
parts.push(internal.routeText);
|
|
589
|
+
}
|
|
590
|
+
const timing = describeFrequencyThai(internal);
|
|
591
|
+
if (timing) {
|
|
592
|
+
parts.push(timing);
|
|
593
|
+
}
|
|
594
|
+
else if (internal.timingCode) {
|
|
595
|
+
parts.push(internal.timingCode);
|
|
596
|
+
}
|
|
597
|
+
else if (internal.period && internal.periodUnit) {
|
|
598
|
+
const base = stripTrailingZero(internal.period);
|
|
599
|
+
const qualifier = internal.periodMax && internal.periodMax !== internal.period
|
|
600
|
+
? `${base}-${stripTrailingZero(internal.periodMax)}`
|
|
601
|
+
: base;
|
|
602
|
+
parts.push(`Q${qualifier}${internal.periodUnit.toUpperCase()}`);
|
|
603
|
+
}
|
|
604
|
+
if (internal.when.length) {
|
|
605
|
+
const events = collectWhenPhrasesThai(internal);
|
|
606
|
+
if (events.length) {
|
|
607
|
+
parts.push(events.join(" "));
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (internal.dayOfWeek.length) {
|
|
611
|
+
const days = internal.dayOfWeek
|
|
612
|
+
.map((d) => { var _a, _b; return (_b = (_a = DAY_NAMES_THAI[d]) === null || _a === void 0 ? void 0 : _a.replace(/^วัน/, "")) !== null && _b !== void 0 ? _b : d; })
|
|
613
|
+
.join(",");
|
|
614
|
+
parts.push(days);
|
|
615
|
+
}
|
|
616
|
+
const asNeeded = formatAsNeededThai(internal);
|
|
617
|
+
if (asNeeded) {
|
|
618
|
+
parts.push(asNeeded);
|
|
619
|
+
}
|
|
620
|
+
return parts.filter(Boolean).join(" ");
|
|
621
|
+
}
|
|
622
|
+
function formatLongThai(internal) {
|
|
623
|
+
var _a;
|
|
624
|
+
const grammar = resolveRouteGrammarThai(internal);
|
|
625
|
+
const dosePart = (_a = formatDoseThaiLong(internal)) !== null && _a !== void 0 ? _a : "ยา";
|
|
626
|
+
const sitePart = formatSiteThai(internal, grammar);
|
|
627
|
+
const routePart = buildRoutePhraseThai(internal, grammar, Boolean(sitePart));
|
|
628
|
+
const frequencyPart = describeFrequencyThai(internal);
|
|
629
|
+
const eventParts = collectWhenPhrasesThai(internal);
|
|
630
|
+
const timing = combineFrequencyAndEventsThai(frequencyPart, eventParts);
|
|
631
|
+
const dayPart = describeDayOfWeekThai(internal);
|
|
632
|
+
const asNeeded = formatAsNeededThai(internal);
|
|
633
|
+
const segments = [dosePart];
|
|
634
|
+
if (routePart) {
|
|
635
|
+
segments.push(routePart);
|
|
636
|
+
}
|
|
637
|
+
if (timing.frequency) {
|
|
638
|
+
segments.push(timing.frequency);
|
|
639
|
+
}
|
|
640
|
+
if (timing.event) {
|
|
641
|
+
segments.push(timing.event);
|
|
642
|
+
}
|
|
643
|
+
if (dayPart) {
|
|
644
|
+
segments.push(dayPart);
|
|
645
|
+
}
|
|
646
|
+
if (asNeeded) {
|
|
647
|
+
segments.push(asNeeded);
|
|
648
|
+
}
|
|
649
|
+
if (sitePart) {
|
|
650
|
+
segments.push(sitePart);
|
|
651
|
+
}
|
|
652
|
+
const body = segments.filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
653
|
+
if (!body) {
|
|
654
|
+
return `${grammar.verb}.`;
|
|
655
|
+
}
|
|
656
|
+
return `${grammar.verb} ${body}.`;
|
|
657
|
+
}
|
|
658
|
+
function stripTrailingZero(value) {
|
|
659
|
+
const text = value.toString();
|
|
660
|
+
if (text.includes(".")) {
|
|
661
|
+
return text.replace(/\.0+$/, "").replace(/0+$/, "");
|
|
662
|
+
}
|
|
663
|
+
return text;
|
|
664
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { FhirDosage, ParseOptions, ParseResult } from "./types";
|
|
1
|
+
import { FhirDosage, FormatOptions, ParseOptions, ParseResult } from "./types";
|
|
2
2
|
export { parseInternal } from "./parser";
|
|
3
3
|
export { suggestSig } from "./suggest";
|
|
4
4
|
export * from "./types";
|
|
5
5
|
export { nextDueDoses } from "./schedule";
|
|
6
|
+
export { getRegisteredSigLocalizations, registerSigLocalization, resolveSigLocalization, resolveSigTranslation } from "./i18n";
|
|
7
|
+
export type { SigLocalization, SigLocalizationConfig, SigTranslation, SigTranslationConfig } from "./i18n";
|
|
6
8
|
export declare function parseSig(input: string, options?: ParseOptions): ParseResult;
|
|
7
|
-
export declare function formatSig(dosage: FhirDosage, style?: "short" | "long"): string;
|
|
8
|
-
export declare function fromFhirDosage(dosage: FhirDosage): ParseResult;
|
|
9
|
+
export declare function formatSig(dosage: FhirDosage, style?: "short" | "long", options?: FormatOptions): string;
|
|
10
|
+
export declare function fromFhirDosage(dosage: FhirDosage, options?: FormatOptions): ParseResult;
|