@imranq2/fhirpatientsummary 1.0.27 → 1.0.28
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.cjs +149 -127
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +149 -127
- package/package.json +8 -5
package/dist/index.js
CHANGED
|
@@ -220,7 +220,7 @@ var TemplateUtilities = class {
|
|
|
220
220
|
renderOrganization(orgRef) {
|
|
221
221
|
const organization = orgRef && this.resolveReference(orgRef);
|
|
222
222
|
if (organization && organization.resourceType === "Organization" && organization.name) {
|
|
223
|
-
return organization.name;
|
|
223
|
+
return this.renderTextAsHtml(organization.name);
|
|
224
224
|
}
|
|
225
225
|
return "";
|
|
226
226
|
}
|
|
@@ -232,7 +232,7 @@ var TemplateUtilities = class {
|
|
|
232
232
|
renderVaccineManufacturer(immunization) {
|
|
233
233
|
const organization = immunization.manufacturer && this.resolveReference(immunization.manufacturer);
|
|
234
234
|
if (organization && organization.resourceType === "Organization" && organization.name) {
|
|
235
|
-
return organization.name;
|
|
235
|
+
return this.renderTextAsHtml(organization.name);
|
|
236
236
|
}
|
|
237
237
|
return "";
|
|
238
238
|
}
|
|
@@ -271,7 +271,7 @@ var TemplateUtilities = class {
|
|
|
271
271
|
*/
|
|
272
272
|
renderMedicationCode(medication) {
|
|
273
273
|
if (medication && medication.code) {
|
|
274
|
-
return this.codeableConcept(medication.code, "display");
|
|
274
|
+
return this.renderTextAsHtml(this.codeableConcept(medication.code, "display"));
|
|
275
275
|
}
|
|
276
276
|
return "";
|
|
277
277
|
}
|
|
@@ -282,7 +282,7 @@ var TemplateUtilities = class {
|
|
|
282
282
|
*/
|
|
283
283
|
renderDoseNumber(doseNumber) {
|
|
284
284
|
if (doseNumber && doseNumber.value !== void 0) {
|
|
285
|
-
return doseNumber.value.toString();
|
|
285
|
+
return this.renderTextAsHtml(doseNumber.value.toString());
|
|
286
286
|
}
|
|
287
287
|
return "";
|
|
288
288
|
}
|
|
@@ -293,7 +293,7 @@ var TemplateUtilities = class {
|
|
|
293
293
|
*/
|
|
294
294
|
renderValueUnit(value) {
|
|
295
295
|
if (value && value.constructor?.name === "Quantity" && value.unit) {
|
|
296
|
-
return value.unit;
|
|
296
|
+
return this.renderTextAsHtml(value.unit);
|
|
297
297
|
}
|
|
298
298
|
return "";
|
|
299
299
|
}
|
|
@@ -359,7 +359,7 @@ var TemplateUtilities = class {
|
|
|
359
359
|
* @returns Comma-separated string of items
|
|
360
360
|
*/
|
|
361
361
|
safeConcat(list, attr) {
|
|
362
|
-
return this.concat(list || [], attr);
|
|
362
|
+
return this.renderTextAsHtml(this.concat(list || [], attr));
|
|
363
363
|
}
|
|
364
364
|
/**
|
|
365
365
|
* Concatenates text from a list of CodeableConcept objects
|
|
@@ -376,7 +376,7 @@ var TemplateUtilities = class {
|
|
|
376
376
|
items.push(item.text);
|
|
377
377
|
}
|
|
378
378
|
}
|
|
379
|
-
return items.join(", ");
|
|
379
|
+
return this.renderTextAsHtml(items.join(", "));
|
|
380
380
|
}
|
|
381
381
|
/**
|
|
382
382
|
* Concatenates reaction manifestations
|
|
@@ -397,7 +397,7 @@ var TemplateUtilities = class {
|
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
|
-
return texts.join(", ");
|
|
400
|
+
return this.renderTextAsHtml(texts.join(", "));
|
|
401
401
|
}
|
|
402
402
|
/**
|
|
403
403
|
* Concatenates dose numbers
|
|
@@ -414,7 +414,7 @@ var TemplateUtilities = class {
|
|
|
414
414
|
doseNumbers.push(item.doseNumberPositiveInt.toString());
|
|
415
415
|
}
|
|
416
416
|
}
|
|
417
|
-
return doseNumbers.join(", ");
|
|
417
|
+
return this.renderTextAsHtml(doseNumbers.join(", "));
|
|
418
418
|
}
|
|
419
419
|
/**
|
|
420
420
|
* Concatenates dosage routes
|
|
@@ -431,7 +431,7 @@ var TemplateUtilities = class {
|
|
|
431
431
|
routes.push(item.route.text);
|
|
432
432
|
}
|
|
433
433
|
}
|
|
434
|
-
return routes.join(", ");
|
|
434
|
+
return this.renderTextAsHtml(routes.join(", "));
|
|
435
435
|
}
|
|
436
436
|
/**
|
|
437
437
|
* Returns the first item from a list of CodeableConcept objects
|
|
@@ -440,7 +440,7 @@ var TemplateUtilities = class {
|
|
|
440
440
|
*/
|
|
441
441
|
firstFromCodeableConceptList(list) {
|
|
442
442
|
if (list && Array.isArray(list) && list[0]) {
|
|
443
|
-
return this.codeableConcept(list[0], "display");
|
|
443
|
+
return this.renderTextAsHtml(this.codeableConcept(list[0], "display"));
|
|
444
444
|
}
|
|
445
445
|
return "";
|
|
446
446
|
}
|
|
@@ -459,7 +459,7 @@ var TemplateUtilities = class {
|
|
|
459
459
|
texts.push(item.text);
|
|
460
460
|
}
|
|
461
461
|
}
|
|
462
|
-
return texts.join(", ");
|
|
462
|
+
return this.renderTextAsHtml(texts.join(", "));
|
|
463
463
|
}
|
|
464
464
|
/**
|
|
465
465
|
* Renders component codes
|
|
@@ -791,9 +791,11 @@ var TemplateUtilities = class {
|
|
|
791
791
|
return "";
|
|
792
792
|
}
|
|
793
793
|
/**
|
|
794
|
-
*
|
|
795
|
-
*
|
|
796
|
-
*
|
|
794
|
+
* Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
|
|
795
|
+
* This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
|
|
796
|
+
* and to preserve formatting. Use this in templates or UI components that need to safely display multi-line or arbitrary text.
|
|
797
|
+
* @param text - The text to render as HTML
|
|
798
|
+
* @returns The HTML-safe string with newlines converted to <br />
|
|
797
799
|
*/
|
|
798
800
|
renderTextAsHtml(text) {
|
|
799
801
|
if (!text || text.trim() === "") {
|
|
@@ -857,7 +859,7 @@ var TemplateUtilities = class {
|
|
|
857
859
|
dateTime = DateTime.fromISO(String(dateValue));
|
|
858
860
|
}
|
|
859
861
|
if (!dateTime.isValid) {
|
|
860
|
-
return String(dateValue);
|
|
862
|
+
return this.renderTextAsHtml(String(dateValue));
|
|
861
863
|
}
|
|
862
864
|
if (dateOnly) {
|
|
863
865
|
dateTime = dateTime.toUTC();
|
|
@@ -873,9 +875,9 @@ var TemplateUtilities = class {
|
|
|
873
875
|
hour12: true,
|
|
874
876
|
timeZoneName: "short"
|
|
875
877
|
};
|
|
876
|
-
return dateTime.toLocaleString(formatOptions);
|
|
878
|
+
return this.renderTextAsHtml(dateTime.toLocaleString(formatOptions));
|
|
877
879
|
} catch {
|
|
878
|
-
return String(dateValue);
|
|
880
|
+
return this.renderTextAsHtml(String(dateValue));
|
|
879
881
|
}
|
|
880
882
|
}
|
|
881
883
|
/**
|
|
@@ -1579,7 +1581,7 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1579
1581
|
const uniqueLanguages = /* @__PURE__ */ new Set();
|
|
1580
1582
|
const preferredLanguages = /* @__PURE__ */ new Set();
|
|
1581
1583
|
patient.communication.forEach((comm) => {
|
|
1582
|
-
const language = templateUtilities.codeableConcept(comm.language);
|
|
1584
|
+
const language = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(comm.language));
|
|
1583
1585
|
if (language) {
|
|
1584
1586
|
if (comm.preferred) {
|
|
1585
1587
|
preferredLanguages.add(language);
|
|
@@ -1637,13 +1639,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1637
1639
|
for (const columnData of rowData.section ?? []) {
|
|
1638
1640
|
switch (columnData.title) {
|
|
1639
1641
|
case "Allergen Name":
|
|
1640
|
-
data["allergen"] = columnData.text?.div ?? "";
|
|
1642
|
+
data["allergen"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1641
1643
|
break;
|
|
1642
1644
|
case "Criticality":
|
|
1643
|
-
data["criticality"] = columnData.text?.div ?? "";
|
|
1645
|
+
data["criticality"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1644
1646
|
break;
|
|
1645
1647
|
case "Recorded Date":
|
|
1646
|
-
data["recordedDate"] = columnData.text?.div ?? "";
|
|
1648
|
+
data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1647
1649
|
break;
|
|
1648
1650
|
default:
|
|
1649
1651
|
break;
|
|
@@ -1764,11 +1766,11 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1764
1766
|
for (const allergy of allergies) {
|
|
1765
1767
|
html += `
|
|
1766
1768
|
<tr id="${templateUtilities.narrativeLinkId(allergy.extension)}">
|
|
1767
|
-
<td class="Name"><span class="AllergenName">${templateUtilities.codeableConcept(allergy.code)}</span></td>
|
|
1768
|
-
<td class="Status">${templateUtilities.codeableConcept(allergy.clinicalStatus) || "-"}</td>
|
|
1769
|
-
<td class="Category">${templateUtilities.safeConcat(allergy.category) || "-"}</td>
|
|
1770
|
-
<td class="Reaction">${templateUtilities.concatReactionManifestation(allergy.reaction) || "-"}</td>
|
|
1771
|
-
<td class="OnsetDate">${templateUtilities.renderTime(allergy.onsetDateTime, timezone) || "-"}</td>
|
|
1769
|
+
<td class="Name"><span class="AllergenName">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.code))}</span></td>
|
|
1770
|
+
<td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.clinicalStatus)) || "-"}</td>
|
|
1771
|
+
<td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || "-"}</td>
|
|
1772
|
+
<td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || "-"}</td>
|
|
1773
|
+
<td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || "-"}</td>
|
|
1772
1774
|
<td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
|
|
1773
1775
|
if (includeResolved) {
|
|
1774
1776
|
let endDate = "-";
|
|
@@ -1781,7 +1783,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1781
1783
|
}
|
|
1782
1784
|
}
|
|
1783
1785
|
html += `
|
|
1784
|
-
<td class="ResolvedDate">${endDate}</td>`;
|
|
1786
|
+
<td class="ResolvedDate">${templateUtilities.renderTextAsHtml(endDate)}</td>`;
|
|
1785
1787
|
}
|
|
1786
1788
|
html += `</tr>`;
|
|
1787
1789
|
}
|
|
@@ -1804,17 +1806,21 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
1804
1806
|
* Generate HTML narrative for Medication resources using summary
|
|
1805
1807
|
* @param resources - FHIR Composition resources
|
|
1806
1808
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
1809
|
+
* @param now - Optional current date to use for calculations (defaults to new Date())
|
|
1807
1810
|
* @returns HTML string for rendering
|
|
1808
1811
|
*/
|
|
1809
|
-
generateSummaryNarrative(resources, timezone) {
|
|
1812
|
+
generateSummaryNarrative(resources, timezone, now) {
|
|
1810
1813
|
const templateUtilities = new TemplateUtilities(resources);
|
|
1811
1814
|
let isSummaryCreated = false;
|
|
1815
|
+
const currentDate = now || /* @__PURE__ */ new Date();
|
|
1816
|
+
const twelveMonthsAgo = new Date(currentDate.getFullYear(), currentDate.getMonth() - 12, currentDate.getDate());
|
|
1812
1817
|
let html = `
|
|
1813
1818
|
<div>
|
|
1814
1819
|
<table>
|
|
1815
1820
|
<thead>
|
|
1816
1821
|
<tr>
|
|
1817
1822
|
<th>Medication</th>
|
|
1823
|
+
<th>Status</th>
|
|
1818
1824
|
<th>Sig</th>
|
|
1819
1825
|
<th>Days of Supply</th>
|
|
1820
1826
|
<th>Refills</th>
|
|
@@ -1828,40 +1834,48 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
1828
1834
|
for (const columnData of rowData.section ?? []) {
|
|
1829
1835
|
switch (columnData.title) {
|
|
1830
1836
|
case "Medication Name":
|
|
1831
|
-
data["medication"] = columnData.text?.div ?? "";
|
|
1837
|
+
data["medication"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1832
1838
|
break;
|
|
1833
1839
|
case "Status":
|
|
1834
|
-
data["status"] = columnData.text?.div ?? "";
|
|
1840
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1835
1841
|
break;
|
|
1836
1842
|
case "Prescriber Instruction":
|
|
1837
|
-
data["sig-prescriber"] = columnData.text?.div ?? "";
|
|
1843
|
+
data["sig-prescriber"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1838
1844
|
break;
|
|
1839
1845
|
case "Pharmacy Instruction":
|
|
1840
|
-
data["sig-pharmacy"] = columnData.text?.div ?? "";
|
|
1846
|
+
data["sig-pharmacy"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1841
1847
|
break;
|
|
1842
1848
|
case "Days Of Supply":
|
|
1843
|
-
data["daysOfSupply"] = columnData.text?.div ?? "";
|
|
1849
|
+
data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1844
1850
|
break;
|
|
1845
1851
|
case "Refills Remaining":
|
|
1846
|
-
data["refills"] = columnData.text?.div ?? "";
|
|
1852
|
+
data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1847
1853
|
break;
|
|
1848
1854
|
case "Authored On Date":
|
|
1849
|
-
data["startDate"] = columnData.text?.div ?? "";
|
|
1855
|
+
data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1850
1856
|
break;
|
|
1851
1857
|
default:
|
|
1852
1858
|
break;
|
|
1853
1859
|
}
|
|
1854
1860
|
}
|
|
1855
|
-
|
|
1861
|
+
let startDateObj;
|
|
1862
|
+
if (data["startDate"]) {
|
|
1863
|
+
startDateObj = new Date(data["startDate"]);
|
|
1864
|
+
if (isNaN(startDateObj.getTime())) {
|
|
1865
|
+
startDateObj = void 0;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
if (data["status"] === "active" || startDateObj && startDateObj >= twelveMonthsAgo) {
|
|
1856
1869
|
isSummaryCreated = true;
|
|
1857
1870
|
html += `
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1871
|
+
<tr>
|
|
1872
|
+
<td>${templateUtilities.renderTextAsHtml(data["medication"])}</td>
|
|
1873
|
+
<td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
|
|
1874
|
+
<td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
|
|
1875
|
+
<td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
|
|
1876
|
+
<td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
|
|
1877
|
+
<td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
|
|
1878
|
+
</tr>`;
|
|
1865
1879
|
}
|
|
1866
1880
|
}
|
|
1867
1881
|
}
|
|
@@ -2083,13 +2097,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2083
2097
|
for (const columnData of rowData.section ?? []) {
|
|
2084
2098
|
switch (columnData.title) {
|
|
2085
2099
|
case "Immunization Name":
|
|
2086
|
-
data["immunization"] = columnData.text?.div ?? "";
|
|
2100
|
+
data["immunization"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2087
2101
|
break;
|
|
2088
2102
|
case "Status":
|
|
2089
|
-
data["status"] = columnData.text?.div ?? "";
|
|
2103
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2090
2104
|
break;
|
|
2091
2105
|
case "occurrenceDateTime":
|
|
2092
|
-
data["occurrenceDateTime"] = columnData.text?.div ?? "";
|
|
2106
|
+
data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2093
2107
|
break;
|
|
2094
2108
|
default:
|
|
2095
2109
|
break;
|
|
@@ -2140,7 +2154,7 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2140
2154
|
const imm = resourceItem;
|
|
2141
2155
|
html += `
|
|
2142
2156
|
<tr id="${templateUtilities.narrativeLinkId(imm)}">
|
|
2143
|
-
<td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
|
|
2157
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(imm.vaccineCode))}</td>
|
|
2144
2158
|
<td>${imm.status || ""}</td>
|
|
2145
2159
|
<td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
|
|
2146
2160
|
<td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
|
|
@@ -2196,7 +2210,7 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2196
2210
|
<tbody>`;
|
|
2197
2211
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
2198
2212
|
for (const cond of activeConditions) {
|
|
2199
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
2213
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
2200
2214
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
2201
2215
|
addedConditionCodes.add(conditionCode);
|
|
2202
2216
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -2256,7 +2270,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2256
2270
|
const vitalData = {};
|
|
2257
2271
|
for (const component of columnData.section?.[0]?.section ?? []) {
|
|
2258
2272
|
if (component.title) {
|
|
2259
|
-
vitalData[component.title] = component.text?.div ?? "";
|
|
2273
|
+
vitalData[component.title] = templateUtilities.renderTextAsHtml(component.text?.div ?? "");
|
|
2260
2274
|
}
|
|
2261
2275
|
}
|
|
2262
2276
|
const vitalValue = templateUtilities.extractObservationSummaryValue(
|
|
@@ -2268,7 +2282,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2268
2282
|
data[dataKey] = vitalValue;
|
|
2269
2283
|
}
|
|
2270
2284
|
}
|
|
2271
|
-
data[columnTitle] = columnData.text?.div ?? "";
|
|
2285
|
+
data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2272
2286
|
}
|
|
2273
2287
|
}
|
|
2274
2288
|
isSummaryCreated = true;
|
|
@@ -2318,7 +2332,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2318
2332
|
for (const obs of observations) {
|
|
2319
2333
|
html += `
|
|
2320
2334
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
2321
|
-
<td>${templateUtilities.codeableConcept(obs.code, "display")}</td>
|
|
2335
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code, "display"))}</td>
|
|
2322
2336
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
2323
2337
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
2324
2338
|
<td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
|
|
@@ -2372,10 +2386,10 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
|
|
|
2372
2386
|
for (const dus of deviceStatements) {
|
|
2373
2387
|
html += `
|
|
2374
2388
|
<tr id="${templateUtilities.narrativeLinkId(dus)}">
|
|
2375
|
-
<td>${templateUtilities.renderDevice(dus.device)}</td>
|
|
2376
|
-
<td>${dus.status || ""}</td>
|
|
2389
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device))}</td>
|
|
2390
|
+
<td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
|
|
2377
2391
|
<td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
|
|
2378
|
-
<td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
|
|
2392
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
|
|
2379
2393
|
</tr>`;
|
|
2380
2394
|
}
|
|
2381
2395
|
html += `
|
|
@@ -2511,149 +2525,150 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2511
2525
|
* Helper function to extract observation field data
|
|
2512
2526
|
* @param column - Column data from the summary
|
|
2513
2527
|
* @param targetData - Record to populate with extracted data
|
|
2528
|
+
* @param templateUtilities - Instance of TemplateUtilities for utility functions
|
|
2514
2529
|
*/
|
|
2515
|
-
extractSummaryObservationFields(column, targetData) {
|
|
2530
|
+
extractSummaryObservationFields(column, targetData, templateUtilities) {
|
|
2516
2531
|
switch (column.title) {
|
|
2517
2532
|
case "Labs Name":
|
|
2518
|
-
targetData["code"] = column.text?.div ?? "";
|
|
2533
|
+
targetData["code"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2519
2534
|
break;
|
|
2520
2535
|
case "effectiveDateTime":
|
|
2521
|
-
targetData["effectiveDateTime"] = column.text?.div ?? "";
|
|
2536
|
+
targetData["effectiveDateTime"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2522
2537
|
break;
|
|
2523
2538
|
case "effectivePeriod.start":
|
|
2524
|
-
targetData["effectivePeriodStart"] = column.text?.div ?? "";
|
|
2539
|
+
targetData["effectivePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2525
2540
|
break;
|
|
2526
2541
|
case "effectivePeriod.end":
|
|
2527
|
-
targetData["effectivePeriodEnd"] = column.text?.div ?? "";
|
|
2542
|
+
targetData["effectivePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2528
2543
|
break;
|
|
2529
2544
|
// valueQuantity
|
|
2530
2545
|
case "valueQuantity.value":
|
|
2531
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2546
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2532
2547
|
targetData["valueType"] = "valueQuantity";
|
|
2533
2548
|
break;
|
|
2534
2549
|
case "valueQuantity.unit":
|
|
2535
|
-
targetData["unit"] = column.text?.div ?? "";
|
|
2550
|
+
targetData["unit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2536
2551
|
break;
|
|
2537
2552
|
// valueCodeableConcept
|
|
2538
2553
|
case "valueCodeableConcept.text":
|
|
2539
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2554
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2540
2555
|
targetData["valueType"] = "valueCodeableConcept";
|
|
2541
2556
|
break;
|
|
2542
2557
|
case "valueCodeableConcept.coding.display":
|
|
2543
2558
|
if (!targetData["value"]) {
|
|
2544
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2559
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2545
2560
|
targetData["valueType"] = "valueCodeableConcept";
|
|
2546
2561
|
}
|
|
2547
2562
|
break;
|
|
2548
2563
|
// valueString
|
|
2549
2564
|
case "valueString":
|
|
2550
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2565
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2551
2566
|
targetData["valueType"] = "valueString";
|
|
2552
2567
|
break;
|
|
2553
2568
|
// valueBoolean
|
|
2554
2569
|
case "valueBoolean":
|
|
2555
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2570
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2556
2571
|
targetData["valueType"] = "valueBoolean";
|
|
2557
2572
|
break;
|
|
2558
2573
|
// valueInteger
|
|
2559
2574
|
case "valueInteger":
|
|
2560
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2575
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2561
2576
|
targetData["valueType"] = "valueInteger";
|
|
2562
2577
|
break;
|
|
2563
2578
|
// valueDateTime
|
|
2564
2579
|
case "valueDateTime":
|
|
2565
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2580
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2566
2581
|
targetData["valueType"] = "valueDateTime";
|
|
2567
2582
|
break;
|
|
2568
2583
|
// valuePeriod
|
|
2569
2584
|
case "valuePeriod.start":
|
|
2570
|
-
targetData["valuePeriodStart"] = column.text?.div ?? "";
|
|
2585
|
+
targetData["valuePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2571
2586
|
targetData["valueType"] = "valuePeriod";
|
|
2572
2587
|
break;
|
|
2573
2588
|
case "valuePeriod.end":
|
|
2574
|
-
targetData["valuePeriodEnd"] = column.text?.div ?? "";
|
|
2589
|
+
targetData["valuePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2575
2590
|
targetData["valueType"] = "valuePeriod";
|
|
2576
2591
|
break;
|
|
2577
2592
|
// valueTime
|
|
2578
2593
|
case "valueTime":
|
|
2579
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2594
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2580
2595
|
targetData["valueType"] = "valueTime";
|
|
2581
2596
|
break;
|
|
2582
2597
|
// valueSampledData
|
|
2583
2598
|
case "valueSampledData.origin.value":
|
|
2584
|
-
targetData["sampledDataOriginValue"] = column.text?.div ?? "";
|
|
2599
|
+
targetData["sampledDataOriginValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2585
2600
|
targetData["valueType"] = "valueSampledData";
|
|
2586
2601
|
break;
|
|
2587
2602
|
case "valueSampledData.origin.unit":
|
|
2588
|
-
targetData["sampledDataOriginUnit"] = column.text?.div ?? "";
|
|
2603
|
+
targetData["sampledDataOriginUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2589
2604
|
break;
|
|
2590
2605
|
case "valueSampledData.period":
|
|
2591
|
-
targetData["sampledDataPeriod"] = column.text?.div ?? "";
|
|
2606
|
+
targetData["sampledDataPeriod"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2592
2607
|
break;
|
|
2593
2608
|
case "valueSampledData.factor":
|
|
2594
|
-
targetData["sampledDataFactor"] = column.text?.div ?? "";
|
|
2609
|
+
targetData["sampledDataFactor"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2595
2610
|
break;
|
|
2596
2611
|
case "valueSampledData.lowerLimit":
|
|
2597
|
-
targetData["sampledDataLowerLimit"] = column.text?.div ?? "";
|
|
2612
|
+
targetData["sampledDataLowerLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2598
2613
|
break;
|
|
2599
2614
|
case "valueSampledData.upperLimit":
|
|
2600
|
-
targetData["sampledDataUpperLimit"] = column.text?.div ?? "";
|
|
2615
|
+
targetData["sampledDataUpperLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2601
2616
|
break;
|
|
2602
2617
|
case "valueSampledData.data":
|
|
2603
|
-
targetData["sampledDataData"] = column.text?.div ?? "";
|
|
2618
|
+
targetData["sampledDataData"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2604
2619
|
break;
|
|
2605
2620
|
// valueRange
|
|
2606
2621
|
case "valueRange.low.value":
|
|
2607
|
-
targetData["valueRangeLowValue"] = column.text?.div ?? "";
|
|
2622
|
+
targetData["valueRangeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2608
2623
|
targetData["valueType"] = "valueRange";
|
|
2609
2624
|
break;
|
|
2610
2625
|
case "valueRange.low.unit":
|
|
2611
|
-
targetData["valueRangeLowUnit"] = column.text?.div ?? "";
|
|
2626
|
+
targetData["valueRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2612
2627
|
break;
|
|
2613
2628
|
case "valueRange.high.value":
|
|
2614
|
-
targetData["valueRangeHighValue"] = column.text?.div ?? "";
|
|
2629
|
+
targetData["valueRangeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2615
2630
|
break;
|
|
2616
2631
|
case "valueRange.high.unit":
|
|
2617
|
-
targetData["valueRangeHighUnit"] = column.text?.div ?? "";
|
|
2632
|
+
targetData["valueRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2618
2633
|
break;
|
|
2619
2634
|
// valueRatio
|
|
2620
2635
|
case "valueRatio.numerator.value":
|
|
2621
|
-
targetData["valueRatioNumeratorValue"] = column.text?.div ?? "";
|
|
2636
|
+
targetData["valueRatioNumeratorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2622
2637
|
targetData["valueType"] = "valueRatio";
|
|
2623
2638
|
break;
|
|
2624
2639
|
case "valueRatio.numerator.unit":
|
|
2625
|
-
targetData["valueRatioNumeratorUnit"] = column.text?.div ?? "";
|
|
2640
|
+
targetData["valueRatioNumeratorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2626
2641
|
break;
|
|
2627
2642
|
case "valueRatio.denominator.value":
|
|
2628
|
-
targetData["valueRatioDenominatorValue"] = column.text?.div ?? "";
|
|
2643
|
+
targetData["valueRatioDenominatorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2629
2644
|
break;
|
|
2630
2645
|
case "valueRatio.denominator.unit":
|
|
2631
|
-
targetData["valueRatioDenominatorUnit"] = column.text?.div ?? "";
|
|
2646
|
+
targetData["valueRatioDenominatorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2632
2647
|
break;
|
|
2633
2648
|
// referenceRange
|
|
2634
2649
|
case "referenceRange.low.value":
|
|
2635
|
-
targetData["referenceRangeLow"] = column.text?.div ?? "";
|
|
2650
|
+
targetData["referenceRangeLow"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2636
2651
|
break;
|
|
2637
2652
|
case "referenceRange.low.unit":
|
|
2638
|
-
targetData["referenceRangeLowUnit"] = column.text?.div ?? "";
|
|
2653
|
+
targetData["referenceRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2639
2654
|
break;
|
|
2640
2655
|
case "referenceRange.high.value":
|
|
2641
|
-
targetData["referenceRangeHigh"] = column.text?.div ?? "";
|
|
2656
|
+
targetData["referenceRangeHigh"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2642
2657
|
break;
|
|
2643
2658
|
case "referenceRange.high.unit":
|
|
2644
|
-
targetData["referenceRangeHighUnit"] = column.text?.div ?? "";
|
|
2659
|
+
targetData["referenceRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2645
2660
|
break;
|
|
2646
2661
|
case "referenceRange.age.low.value":
|
|
2647
|
-
targetData["referenceRangeAgeLowValue"] = column.text?.div ?? "";
|
|
2662
|
+
targetData["referenceRangeAgeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2648
2663
|
break;
|
|
2649
2664
|
case "referenceRange.age.low.unit":
|
|
2650
|
-
targetData["referenceRangeAgeLowUnit"] = column.text?.div ?? "";
|
|
2665
|
+
targetData["referenceRangeAgeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2651
2666
|
break;
|
|
2652
2667
|
case "referenceRange.age.high.value":
|
|
2653
|
-
targetData["referenceRangeAgeHighValue"] = column.text?.div ?? "";
|
|
2668
|
+
targetData["referenceRangeAgeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2654
2669
|
break;
|
|
2655
2670
|
case "referenceRange.age.high.unit":
|
|
2656
|
-
targetData["referenceRangeAgeHighUnit"] = column.text?.div ?? "";
|
|
2671
|
+
targetData["referenceRangeAgeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2657
2672
|
break;
|
|
2658
2673
|
default:
|
|
2659
2674
|
break;
|
|
@@ -2706,28 +2721,28 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2706
2721
|
for (const componentSection of columnData.section) {
|
|
2707
2722
|
const componentData = {};
|
|
2708
2723
|
for (const nestedColumn of componentSection.section ?? []) {
|
|
2709
|
-
this.extractSummaryObservationFields(nestedColumn, componentData);
|
|
2724
|
+
this.extractSummaryObservationFields(nestedColumn, componentData, templateUtilities);
|
|
2710
2725
|
}
|
|
2711
2726
|
if (Object.keys(componentData).length > 0) {
|
|
2712
2727
|
components.push(componentData);
|
|
2713
2728
|
}
|
|
2714
2729
|
}
|
|
2715
2730
|
} else {
|
|
2716
|
-
this.extractSummaryObservationFields(columnData, data);
|
|
2731
|
+
this.extractSummaryObservationFields(columnData, data, templateUtilities);
|
|
2717
2732
|
}
|
|
2718
2733
|
} else if (resourceItem.title === "DiagnosticReportLab Summary Grouped by DiagnosticReport|Lab Code") {
|
|
2719
2734
|
switch (columnData.title) {
|
|
2720
2735
|
case "Diagnostic Report Name":
|
|
2721
|
-
data["report"] = columnData.text?.div ?? "";
|
|
2736
|
+
data["report"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2722
2737
|
break;
|
|
2723
2738
|
case "Performer":
|
|
2724
|
-
data["performer"] = columnData.text?.div ?? "";
|
|
2739
|
+
data["performer"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2725
2740
|
break;
|
|
2726
2741
|
case "Issued Date":
|
|
2727
|
-
data["issued"] = columnData.text?.div ?? "";
|
|
2742
|
+
data["issued"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2728
2743
|
break;
|
|
2729
2744
|
case "Status":
|
|
2730
|
-
data["status"] = columnData.text?.div ?? "";
|
|
2745
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2731
2746
|
break;
|
|
2732
2747
|
default:
|
|
2733
2748
|
break;
|
|
@@ -2752,8 +2767,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2752
2767
|
observationhtml += `
|
|
2753
2768
|
<tr>
|
|
2754
2769
|
<td>${componentCode}</td>
|
|
2755
|
-
<td>${component["formattedValue"] ?? "-"}</td>
|
|
2756
|
-
<td>${component["referenceRange"]?.trim() ?? "-"}</td>
|
|
2770
|
+
<td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? "-"}</td>
|
|
2771
|
+
<td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? "-"}</td>
|
|
2757
2772
|
<td>${date ?? "-"}</td>
|
|
2758
2773
|
</tr>`;
|
|
2759
2774
|
}
|
|
@@ -2766,8 +2781,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2766
2781
|
observationhtml += `
|
|
2767
2782
|
<tr>
|
|
2768
2783
|
<td>${data["code"] ?? "-"}</td>
|
|
2769
|
-
<td>${data["formattedValue"] ?? "-"}</td>
|
|
2770
|
-
<td>${data["referenceRange"]?.trim() ?? "-"}</td>
|
|
2784
|
+
<td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? "-"}</td>
|
|
2785
|
+
<td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? "-"}</td>
|
|
2771
2786
|
<td>${date ?? "-"}</td>
|
|
2772
2787
|
</tr>`;
|
|
2773
2788
|
}
|
|
@@ -2927,7 +2942,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2927
2942
|
<tbody>`;
|
|
2928
2943
|
const observationAdded = /* @__PURE__ */ new Set();
|
|
2929
2944
|
for (const obs of observations) {
|
|
2930
|
-
const obsCode = templateUtilities.codeableConcept(obs.code);
|
|
2945
|
+
const obsCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code));
|
|
2931
2946
|
if (!observationAdded.has(obsCode)) {
|
|
2932
2947
|
observationAdded.add(obsCode);
|
|
2933
2948
|
html += `
|
|
@@ -2966,7 +2981,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2966
2981
|
<tbody>`;
|
|
2967
2982
|
const diagnosticReportAdded = /* @__PURE__ */ new Set();
|
|
2968
2983
|
for (const report of reports) {
|
|
2969
|
-
const reportName = templateUtilities.codeableConcept(report.code);
|
|
2984
|
+
const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(report.code));
|
|
2970
2985
|
if (!diagnosticReportAdded.has(reportName)) {
|
|
2971
2986
|
diagnosticReportAdded.add(reportName);
|
|
2972
2987
|
let resultCount = "";
|
|
@@ -3080,7 +3095,7 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3080
3095
|
const proc = resourceItem;
|
|
3081
3096
|
html += `
|
|
3082
3097
|
<tr id="${templateUtilities.narrativeLinkId(proc)}">
|
|
3083
|
-
<td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
|
|
3098
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(proc.code, "display"))}</td>
|
|
3084
3099
|
<td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
|
|
3085
3100
|
<td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
|
|
3086
3101
|
</tr>`;
|
|
@@ -3132,7 +3147,7 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3132
3147
|
for (const obs of observations) {
|
|
3133
3148
|
html += `
|
|
3134
3149
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
3135
|
-
<td>${templateUtilities.codeableConcept(obs.code)}</td>
|
|
3150
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code))}</td>
|
|
3136
3151
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
3137
3152
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
3138
3153
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
@@ -3177,7 +3192,7 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3177
3192
|
<tbody>`;
|
|
3178
3193
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
3179
3194
|
for (const cond of resolvedConditions) {
|
|
3180
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
3195
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
3181
3196
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3182
3197
|
addedConditionCodes.add(conditionCode);
|
|
3183
3198
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -3263,7 +3278,7 @@ var PlanOfCareTemplate = class {
|
|
|
3263
3278
|
const data = {};
|
|
3264
3279
|
for (const columnData of rowData.section ?? []) {
|
|
3265
3280
|
if (columnData.title) {
|
|
3266
|
-
data[columnData.title] = columnData.text?.div ?? "";
|
|
3281
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3267
3282
|
}
|
|
3268
3283
|
}
|
|
3269
3284
|
if (data["status"] !== "active") {
|
|
@@ -3339,7 +3354,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3339
3354
|
<tbody>`;
|
|
3340
3355
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
3341
3356
|
for (const cond of activeConditions) {
|
|
3342
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
3357
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
3343
3358
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3344
3359
|
addedConditionCodes.add(conditionCode);
|
|
3345
3360
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -3384,7 +3399,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3384
3399
|
if (impression.finding && impression.finding.length > 0) {
|
|
3385
3400
|
findingsHtml = "<ul>";
|
|
3386
3401
|
for (const finding of impression.finding) {
|
|
3387
|
-
const findingText = finding.itemCodeableConcept ? templateUtilities.codeableConcept(finding.itemCodeableConcept) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
|
|
3402
|
+
const findingText = finding.itemCodeableConcept ? templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(finding.itemCodeableConcept)) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
|
|
3388
3403
|
const cause = finding.basis || "";
|
|
3389
3404
|
findingsHtml += `<li>${findingText}${cause ? ` - ${cause}` : ""}</li>`;
|
|
3390
3405
|
}
|
|
@@ -3445,9 +3460,9 @@ var PregnancyTemplate = class _PregnancyTemplate {
|
|
|
3445
3460
|
const obs = resource;
|
|
3446
3461
|
html += `
|
|
3447
3462
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
3448
|
-
<td>${templateUtilities.extractPregnancyStatus(obs)}</td>
|
|
3463
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.extractPregnancyStatus(obs))}</td>
|
|
3449
3464
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
3450
|
-
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
3465
|
+
<td>${obs.effectiveDateTime ? templateUtilities.renderTextAsHtml(templateUtilities.renderTime(obs.effectiveDateTime, timezone)) : obs.effectivePeriod ? templateUtilities.renderTextAsHtml(templateUtilities.renderPeriod(obs.effectivePeriod, timezone)) : ""}</td>
|
|
3451
3466
|
</tr>`;
|
|
3452
3467
|
}
|
|
3453
3468
|
html += `
|
|
@@ -3497,7 +3512,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
|
|
|
3497
3512
|
const consent = resourceItem;
|
|
3498
3513
|
html += `
|
|
3499
3514
|
<tr id="${templateUtilities.narrativeLinkId(consent)}">
|
|
3500
|
-
<td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
|
|
3515
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(consent.scope, "display"))}</td>
|
|
3501
3516
|
<td>${consent.status || ""}</td>
|
|
3502
3517
|
<td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
|
|
3503
3518
|
<td>${consent.dateTime || ""}</td>
|
|
@@ -3518,16 +3533,18 @@ var TypeScriptTemplateMapper = class {
|
|
|
3518
3533
|
* @param resources - FHIR resources
|
|
3519
3534
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3520
3535
|
* @param useSectionSummary - Whether to use the section summary for narrative generation
|
|
3536
|
+
* @param now - Optional current date to use for generating relative dates in the narrative
|
|
3521
3537
|
* @returns HTML string for rendering
|
|
3522
3538
|
*/
|
|
3523
|
-
static generateNarrative(section, resources, timezone, useSectionSummary = false) {
|
|
3539
|
+
static generateNarrative(section, resources, timezone, useSectionSummary = false, now) {
|
|
3524
3540
|
const templateClass = this.sectionToTemplate[section];
|
|
3525
3541
|
if (!templateClass) {
|
|
3526
3542
|
throw new Error(`No template found for section: ${section}`);
|
|
3527
3543
|
}
|
|
3528
3544
|
return useSectionSummary ? templateClass.generateSummaryNarrative(
|
|
3529
3545
|
resources,
|
|
3530
|
-
timezone
|
|
3546
|
+
timezone,
|
|
3547
|
+
now
|
|
3531
3548
|
) : templateClass.generateNarrative(resources, timezone);
|
|
3532
3549
|
}
|
|
3533
3550
|
};
|
|
@@ -3585,14 +3602,15 @@ var NarrativeGenerator = class {
|
|
|
3585
3602
|
* @param resources - Array of domain resources
|
|
3586
3603
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3587
3604
|
* @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
|
|
3605
|
+
* @param now - Optional date parameter
|
|
3588
3606
|
* @returns Generated HTML content or undefined if no resources
|
|
3589
3607
|
*/
|
|
3590
|
-
static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false) {
|
|
3608
|
+
static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false, now) {
|
|
3591
3609
|
if (!resources || resources.length === 0) {
|
|
3592
3610
|
return void 0;
|
|
3593
3611
|
}
|
|
3594
3612
|
try {
|
|
3595
|
-
const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary);
|
|
3613
|
+
const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary, now);
|
|
3596
3614
|
if (!content) {
|
|
3597
3615
|
return void 0;
|
|
3598
3616
|
}
|
|
@@ -3614,8 +3632,8 @@ var NarrativeGenerator = class {
|
|
|
3614
3632
|
const options = aggressive ? AGGRESSIVE_MINIFY_OPTIONS : DEFAULT_MINIFY_OPTIONS;
|
|
3615
3633
|
return await htmlMinify(html, options);
|
|
3616
3634
|
} catch (error) {
|
|
3617
|
-
console.warn("HTML minification failed", error);
|
|
3618
|
-
return
|
|
3635
|
+
console.warn("HTML minification failed", error, html);
|
|
3636
|
+
return `${error instanceof Error ? error.message : String(error)}`;
|
|
3619
3637
|
}
|
|
3620
3638
|
}
|
|
3621
3639
|
/**
|
|
@@ -3644,10 +3662,11 @@ var NarrativeGenerator = class {
|
|
|
3644
3662
|
* @param timezone - Optional timezone to use for date formatting
|
|
3645
3663
|
* @param minify - Whether to minify the HTML content (default: true)
|
|
3646
3664
|
* @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
|
|
3665
|
+
* @param now - Optional date parameter
|
|
3647
3666
|
* @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
|
|
3648
3667
|
*/
|
|
3649
|
-
static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false) {
|
|
3650
|
-
const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary);
|
|
3668
|
+
static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false, now) {
|
|
3669
|
+
const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary, now);
|
|
3651
3670
|
if (!content) {
|
|
3652
3671
|
return void 0;
|
|
3653
3672
|
}
|
|
@@ -3824,8 +3843,9 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3824
3843
|
* @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
|
|
3825
3844
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3826
3845
|
* @param patientId - Optional patient ID to use as primary patient for composition reference
|
|
3846
|
+
* @param now - Optional current date to use for composition date (defaults to new Date())
|
|
3827
3847
|
*/
|
|
3828
|
-
async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId) {
|
|
3848
|
+
async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId, now) {
|
|
3829
3849
|
if (baseUrl.endsWith("/")) {
|
|
3830
3850
|
baseUrl = baseUrl.slice(0, -1);
|
|
3831
3851
|
}
|
|
@@ -3852,20 +3872,22 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3852
3872
|
// Assuming patient is also a practitioner for simplicity
|
|
3853
3873
|
display: authorOrganizationName
|
|
3854
3874
|
}],
|
|
3855
|
-
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3875
|
+
date: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
3856
3876
|
title: "International Patient Summary",
|
|
3857
3877
|
section: this.sections,
|
|
3858
3878
|
text: await NarrativeGenerator.generateNarrativeAsync(
|
|
3859
3879
|
"Patient" /* PATIENT */,
|
|
3860
3880
|
this.patients,
|
|
3861
3881
|
timezone,
|
|
3862
|
-
true
|
|
3882
|
+
true,
|
|
3883
|
+
false,
|
|
3884
|
+
now
|
|
3863
3885
|
)
|
|
3864
3886
|
};
|
|
3865
3887
|
const bundle = {
|
|
3866
3888
|
resourceType: "Bundle",
|
|
3867
3889
|
type: "document",
|
|
3868
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3890
|
+
timestamp: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
3869
3891
|
identifier: {
|
|
3870
3892
|
"system": "urn:ietf:rfc:3986",
|
|
3871
3893
|
"value": "urn:uuid:4dcfd353-49fd-4ab0-b521-c8d57ced74d6"
|