@imranq2/fhirpatientsummary 1.0.27 → 1.0.29
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 +161 -127
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +161 -127
- package/package.json +8 -5
package/dist/index.js
CHANGED
|
@@ -133,6 +133,9 @@ var IPSSectionSummaryCompositionFilter = {
|
|
|
133
133
|
// [IPSSections.DIAGNOSTIC_REPORTS]: (resource) => resource.resourceType === 'Composition' && resource.type?.coding?.some((c: any) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && ["lab_summary_document", "diagnosticreportlab_summary_document"].includes(c.code)),
|
|
134
134
|
["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && c.code === "procedure_summary_document")
|
|
135
135
|
};
|
|
136
|
+
var IPSSectionSummaryIPSCompositionFilter = {
|
|
137
|
+
["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && c.code === "ips_vital_summary_document")
|
|
138
|
+
};
|
|
136
139
|
var IPSSectionResourceHelper = class {
|
|
137
140
|
static getResourceFilterForSection(section) {
|
|
138
141
|
return IPSSectionResourceFilters[section];
|
|
@@ -145,6 +148,9 @@ var IPSSectionResourceHelper = class {
|
|
|
145
148
|
static getSummaryCompositionFilterForSection(section) {
|
|
146
149
|
return IPSSectionSummaryCompositionFilter[section];
|
|
147
150
|
}
|
|
151
|
+
static getSummaryIPSCompositionFilterForSection(section) {
|
|
152
|
+
return IPSSectionSummaryIPSCompositionFilter[section];
|
|
153
|
+
}
|
|
148
154
|
};
|
|
149
155
|
|
|
150
156
|
// src/narratives/templates/typescript/TemplateUtilities.ts
|
|
@@ -220,7 +226,7 @@ var TemplateUtilities = class {
|
|
|
220
226
|
renderOrganization(orgRef) {
|
|
221
227
|
const organization = orgRef && this.resolveReference(orgRef);
|
|
222
228
|
if (organization && organization.resourceType === "Organization" && organization.name) {
|
|
223
|
-
return organization.name;
|
|
229
|
+
return this.renderTextAsHtml(organization.name);
|
|
224
230
|
}
|
|
225
231
|
return "";
|
|
226
232
|
}
|
|
@@ -232,7 +238,7 @@ var TemplateUtilities = class {
|
|
|
232
238
|
renderVaccineManufacturer(immunization) {
|
|
233
239
|
const organization = immunization.manufacturer && this.resolveReference(immunization.manufacturer);
|
|
234
240
|
if (organization && organization.resourceType === "Organization" && organization.name) {
|
|
235
|
-
return organization.name;
|
|
241
|
+
return this.renderTextAsHtml(organization.name);
|
|
236
242
|
}
|
|
237
243
|
return "";
|
|
238
244
|
}
|
|
@@ -271,7 +277,7 @@ var TemplateUtilities = class {
|
|
|
271
277
|
*/
|
|
272
278
|
renderMedicationCode(medication) {
|
|
273
279
|
if (medication && medication.code) {
|
|
274
|
-
return this.codeableConcept(medication.code, "display");
|
|
280
|
+
return this.renderTextAsHtml(this.codeableConcept(medication.code, "display"));
|
|
275
281
|
}
|
|
276
282
|
return "";
|
|
277
283
|
}
|
|
@@ -282,7 +288,7 @@ var TemplateUtilities = class {
|
|
|
282
288
|
*/
|
|
283
289
|
renderDoseNumber(doseNumber) {
|
|
284
290
|
if (doseNumber && doseNumber.value !== void 0) {
|
|
285
|
-
return doseNumber.value.toString();
|
|
291
|
+
return this.renderTextAsHtml(doseNumber.value.toString());
|
|
286
292
|
}
|
|
287
293
|
return "";
|
|
288
294
|
}
|
|
@@ -293,7 +299,7 @@ var TemplateUtilities = class {
|
|
|
293
299
|
*/
|
|
294
300
|
renderValueUnit(value) {
|
|
295
301
|
if (value && value.constructor?.name === "Quantity" && value.unit) {
|
|
296
|
-
return value.unit;
|
|
302
|
+
return this.renderTextAsHtml(value.unit);
|
|
297
303
|
}
|
|
298
304
|
return "";
|
|
299
305
|
}
|
|
@@ -359,7 +365,7 @@ var TemplateUtilities = class {
|
|
|
359
365
|
* @returns Comma-separated string of items
|
|
360
366
|
*/
|
|
361
367
|
safeConcat(list, attr) {
|
|
362
|
-
return this.concat(list || [], attr);
|
|
368
|
+
return this.renderTextAsHtml(this.concat(list || [], attr));
|
|
363
369
|
}
|
|
364
370
|
/**
|
|
365
371
|
* Concatenates text from a list of CodeableConcept objects
|
|
@@ -376,7 +382,7 @@ var TemplateUtilities = class {
|
|
|
376
382
|
items.push(item.text);
|
|
377
383
|
}
|
|
378
384
|
}
|
|
379
|
-
return items.join(", ");
|
|
385
|
+
return this.renderTextAsHtml(items.join(", "));
|
|
380
386
|
}
|
|
381
387
|
/**
|
|
382
388
|
* Concatenates reaction manifestations
|
|
@@ -397,7 +403,7 @@ var TemplateUtilities = class {
|
|
|
397
403
|
}
|
|
398
404
|
}
|
|
399
405
|
}
|
|
400
|
-
return texts.join(", ");
|
|
406
|
+
return this.renderTextAsHtml(texts.join(", "));
|
|
401
407
|
}
|
|
402
408
|
/**
|
|
403
409
|
* Concatenates dose numbers
|
|
@@ -414,7 +420,7 @@ var TemplateUtilities = class {
|
|
|
414
420
|
doseNumbers.push(item.doseNumberPositiveInt.toString());
|
|
415
421
|
}
|
|
416
422
|
}
|
|
417
|
-
return doseNumbers.join(", ");
|
|
423
|
+
return this.renderTextAsHtml(doseNumbers.join(", "));
|
|
418
424
|
}
|
|
419
425
|
/**
|
|
420
426
|
* Concatenates dosage routes
|
|
@@ -431,7 +437,7 @@ var TemplateUtilities = class {
|
|
|
431
437
|
routes.push(item.route.text);
|
|
432
438
|
}
|
|
433
439
|
}
|
|
434
|
-
return routes.join(", ");
|
|
440
|
+
return this.renderTextAsHtml(routes.join(", "));
|
|
435
441
|
}
|
|
436
442
|
/**
|
|
437
443
|
* Returns the first item from a list of CodeableConcept objects
|
|
@@ -440,7 +446,7 @@ var TemplateUtilities = class {
|
|
|
440
446
|
*/
|
|
441
447
|
firstFromCodeableConceptList(list) {
|
|
442
448
|
if (list && Array.isArray(list) && list[0]) {
|
|
443
|
-
return this.codeableConcept(list[0], "display");
|
|
449
|
+
return this.renderTextAsHtml(this.codeableConcept(list[0], "display"));
|
|
444
450
|
}
|
|
445
451
|
return "";
|
|
446
452
|
}
|
|
@@ -459,7 +465,7 @@ var TemplateUtilities = class {
|
|
|
459
465
|
texts.push(item.text);
|
|
460
466
|
}
|
|
461
467
|
}
|
|
462
|
-
return texts.join(", ");
|
|
468
|
+
return this.renderTextAsHtml(texts.join(", "));
|
|
463
469
|
}
|
|
464
470
|
/**
|
|
465
471
|
* Renders component codes
|
|
@@ -791,9 +797,11 @@ var TemplateUtilities = class {
|
|
|
791
797
|
return "";
|
|
792
798
|
}
|
|
793
799
|
/**
|
|
794
|
-
*
|
|
795
|
-
*
|
|
796
|
-
*
|
|
800
|
+
* Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
|
|
801
|
+
* This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
|
|
802
|
+
* and to preserve formatting. Use this in templates or UI components that need to safely display multi-line or arbitrary text.
|
|
803
|
+
* @param text - The text to render as HTML
|
|
804
|
+
* @returns The HTML-safe string with newlines converted to <br />
|
|
797
805
|
*/
|
|
798
806
|
renderTextAsHtml(text) {
|
|
799
807
|
if (!text || text.trim() === "") {
|
|
@@ -857,7 +865,7 @@ var TemplateUtilities = class {
|
|
|
857
865
|
dateTime = DateTime.fromISO(String(dateValue));
|
|
858
866
|
}
|
|
859
867
|
if (!dateTime.isValid) {
|
|
860
|
-
return String(dateValue);
|
|
868
|
+
return this.renderTextAsHtml(String(dateValue));
|
|
861
869
|
}
|
|
862
870
|
if (dateOnly) {
|
|
863
871
|
dateTime = dateTime.toUTC();
|
|
@@ -873,9 +881,9 @@ var TemplateUtilities = class {
|
|
|
873
881
|
hour12: true,
|
|
874
882
|
timeZoneName: "short"
|
|
875
883
|
};
|
|
876
|
-
return dateTime.toLocaleString(formatOptions);
|
|
884
|
+
return this.renderTextAsHtml(dateTime.toLocaleString(formatOptions));
|
|
877
885
|
} catch {
|
|
878
|
-
return String(dateValue);
|
|
886
|
+
return this.renderTextAsHtml(String(dateValue));
|
|
879
887
|
}
|
|
880
888
|
}
|
|
881
889
|
/**
|
|
@@ -1579,7 +1587,7 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1579
1587
|
const uniqueLanguages = /* @__PURE__ */ new Set();
|
|
1580
1588
|
const preferredLanguages = /* @__PURE__ */ new Set();
|
|
1581
1589
|
patient.communication.forEach((comm) => {
|
|
1582
|
-
const language = templateUtilities.codeableConcept(comm.language);
|
|
1590
|
+
const language = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(comm.language));
|
|
1583
1591
|
if (language) {
|
|
1584
1592
|
if (comm.preferred) {
|
|
1585
1593
|
preferredLanguages.add(language);
|
|
@@ -1637,13 +1645,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1637
1645
|
for (const columnData of rowData.section ?? []) {
|
|
1638
1646
|
switch (columnData.title) {
|
|
1639
1647
|
case "Allergen Name":
|
|
1640
|
-
data["allergen"] = columnData.text?.div ?? "";
|
|
1648
|
+
data["allergen"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1641
1649
|
break;
|
|
1642
1650
|
case "Criticality":
|
|
1643
|
-
data["criticality"] = columnData.text?.div ?? "";
|
|
1651
|
+
data["criticality"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1644
1652
|
break;
|
|
1645
1653
|
case "Recorded Date":
|
|
1646
|
-
data["recordedDate"] = columnData.text?.div ?? "";
|
|
1654
|
+
data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1647
1655
|
break;
|
|
1648
1656
|
default:
|
|
1649
1657
|
break;
|
|
@@ -1764,11 +1772,11 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1764
1772
|
for (const allergy of allergies) {
|
|
1765
1773
|
html += `
|
|
1766
1774
|
<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>
|
|
1775
|
+
<td class="Name"><span class="AllergenName">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.code))}</span></td>
|
|
1776
|
+
<td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.clinicalStatus)) || "-"}</td>
|
|
1777
|
+
<td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || "-"}</td>
|
|
1778
|
+
<td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || "-"}</td>
|
|
1779
|
+
<td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || "-"}</td>
|
|
1772
1780
|
<td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
|
|
1773
1781
|
if (includeResolved) {
|
|
1774
1782
|
let endDate = "-";
|
|
@@ -1781,7 +1789,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1781
1789
|
}
|
|
1782
1790
|
}
|
|
1783
1791
|
html += `
|
|
1784
|
-
<td class="ResolvedDate">${endDate}</td>`;
|
|
1792
|
+
<td class="ResolvedDate">${templateUtilities.renderTextAsHtml(endDate)}</td>`;
|
|
1785
1793
|
}
|
|
1786
1794
|
html += `</tr>`;
|
|
1787
1795
|
}
|
|
@@ -1804,17 +1812,21 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
1804
1812
|
* Generate HTML narrative for Medication resources using summary
|
|
1805
1813
|
* @param resources - FHIR Composition resources
|
|
1806
1814
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
1815
|
+
* @param now - Optional current date to use for calculations (defaults to new Date())
|
|
1807
1816
|
* @returns HTML string for rendering
|
|
1808
1817
|
*/
|
|
1809
|
-
generateSummaryNarrative(resources, timezone) {
|
|
1818
|
+
generateSummaryNarrative(resources, timezone, now) {
|
|
1810
1819
|
const templateUtilities = new TemplateUtilities(resources);
|
|
1811
1820
|
let isSummaryCreated = false;
|
|
1821
|
+
const currentDate = now || /* @__PURE__ */ new Date();
|
|
1822
|
+
const twelveMonthsAgo = new Date(currentDate.getFullYear(), currentDate.getMonth() - 12, currentDate.getDate());
|
|
1812
1823
|
let html = `
|
|
1813
1824
|
<div>
|
|
1814
1825
|
<table>
|
|
1815
1826
|
<thead>
|
|
1816
1827
|
<tr>
|
|
1817
1828
|
<th>Medication</th>
|
|
1829
|
+
<th>Status</th>
|
|
1818
1830
|
<th>Sig</th>
|
|
1819
1831
|
<th>Days of Supply</th>
|
|
1820
1832
|
<th>Refills</th>
|
|
@@ -1828,40 +1840,48 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
1828
1840
|
for (const columnData of rowData.section ?? []) {
|
|
1829
1841
|
switch (columnData.title) {
|
|
1830
1842
|
case "Medication Name":
|
|
1831
|
-
data["medication"] = columnData.text?.div ?? "";
|
|
1843
|
+
data["medication"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1832
1844
|
break;
|
|
1833
1845
|
case "Status":
|
|
1834
|
-
data["status"] = columnData.text?.div ?? "";
|
|
1846
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1835
1847
|
break;
|
|
1836
1848
|
case "Prescriber Instruction":
|
|
1837
|
-
data["sig-prescriber"] = columnData.text?.div ?? "";
|
|
1849
|
+
data["sig-prescriber"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1838
1850
|
break;
|
|
1839
1851
|
case "Pharmacy Instruction":
|
|
1840
|
-
data["sig-pharmacy"] = columnData.text?.div ?? "";
|
|
1852
|
+
data["sig-pharmacy"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1841
1853
|
break;
|
|
1842
1854
|
case "Days Of Supply":
|
|
1843
|
-
data["daysOfSupply"] = columnData.text?.div ?? "";
|
|
1855
|
+
data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1844
1856
|
break;
|
|
1845
1857
|
case "Refills Remaining":
|
|
1846
|
-
data["refills"] = columnData.text?.div ?? "";
|
|
1858
|
+
data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1847
1859
|
break;
|
|
1848
1860
|
case "Authored On Date":
|
|
1849
|
-
data["startDate"] = columnData.text?.div ?? "";
|
|
1861
|
+
data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1850
1862
|
break;
|
|
1851
1863
|
default:
|
|
1852
1864
|
break;
|
|
1853
1865
|
}
|
|
1854
1866
|
}
|
|
1855
|
-
|
|
1867
|
+
let startDateObj;
|
|
1868
|
+
if (data["startDate"]) {
|
|
1869
|
+
startDateObj = new Date(data["startDate"]);
|
|
1870
|
+
if (isNaN(startDateObj.getTime())) {
|
|
1871
|
+
startDateObj = void 0;
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
if (data["status"] === "active" || startDateObj && startDateObj >= twelveMonthsAgo) {
|
|
1856
1875
|
isSummaryCreated = true;
|
|
1857
1876
|
html += `
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1877
|
+
<tr>
|
|
1878
|
+
<td>${templateUtilities.renderTextAsHtml(data["medication"])}</td>
|
|
1879
|
+
<td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
|
|
1880
|
+
<td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
|
|
1881
|
+
<td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
|
|
1882
|
+
<td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
|
|
1883
|
+
<td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
|
|
1884
|
+
</tr>`;
|
|
1865
1885
|
}
|
|
1866
1886
|
}
|
|
1867
1887
|
}
|
|
@@ -2083,13 +2103,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2083
2103
|
for (const columnData of rowData.section ?? []) {
|
|
2084
2104
|
switch (columnData.title) {
|
|
2085
2105
|
case "Immunization Name":
|
|
2086
|
-
data["immunization"] = columnData.text?.div ?? "";
|
|
2106
|
+
data["immunization"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2087
2107
|
break;
|
|
2088
2108
|
case "Status":
|
|
2089
|
-
data["status"] = columnData.text?.div ?? "";
|
|
2109
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2090
2110
|
break;
|
|
2091
2111
|
case "occurrenceDateTime":
|
|
2092
|
-
data["occurrenceDateTime"] = columnData.text?.div ?? "";
|
|
2112
|
+
data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2093
2113
|
break;
|
|
2094
2114
|
default:
|
|
2095
2115
|
break;
|
|
@@ -2140,7 +2160,7 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2140
2160
|
const imm = resourceItem;
|
|
2141
2161
|
html += `
|
|
2142
2162
|
<tr id="${templateUtilities.narrativeLinkId(imm)}">
|
|
2143
|
-
<td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
|
|
2163
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(imm.vaccineCode))}</td>
|
|
2144
2164
|
<td>${imm.status || ""}</td>
|
|
2145
2165
|
<td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
|
|
2146
2166
|
<td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
|
|
@@ -2196,7 +2216,7 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2196
2216
|
<tbody>`;
|
|
2197
2217
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
2198
2218
|
for (const cond of activeConditions) {
|
|
2199
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
2219
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
2200
2220
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
2201
2221
|
addedConditionCodes.add(conditionCode);
|
|
2202
2222
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -2256,7 +2276,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2256
2276
|
const vitalData = {};
|
|
2257
2277
|
for (const component of columnData.section?.[0]?.section ?? []) {
|
|
2258
2278
|
if (component.title) {
|
|
2259
|
-
vitalData[component.title] = component.text?.div ?? "";
|
|
2279
|
+
vitalData[component.title] = templateUtilities.renderTextAsHtml(component.text?.div ?? "");
|
|
2260
2280
|
}
|
|
2261
2281
|
}
|
|
2262
2282
|
const vitalValue = templateUtilities.extractObservationSummaryValue(
|
|
@@ -2268,7 +2288,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2268
2288
|
data[dataKey] = vitalValue;
|
|
2269
2289
|
}
|
|
2270
2290
|
}
|
|
2271
|
-
data[columnTitle] = columnData.text?.div ?? "";
|
|
2291
|
+
data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2272
2292
|
}
|
|
2273
2293
|
}
|
|
2274
2294
|
isSummaryCreated = true;
|
|
@@ -2318,7 +2338,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2318
2338
|
for (const obs of observations) {
|
|
2319
2339
|
html += `
|
|
2320
2340
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
2321
|
-
<td>${templateUtilities.codeableConcept(obs.code, "display")}</td>
|
|
2341
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code, "display"))}</td>
|
|
2322
2342
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
2323
2343
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
2324
2344
|
<td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
|
|
@@ -2372,10 +2392,10 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
|
|
|
2372
2392
|
for (const dus of deviceStatements) {
|
|
2373
2393
|
html += `
|
|
2374
2394
|
<tr id="${templateUtilities.narrativeLinkId(dus)}">
|
|
2375
|
-
<td>${templateUtilities.renderDevice(dus.device)}</td>
|
|
2376
|
-
<td>${dus.status || ""}</td>
|
|
2395
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device))}</td>
|
|
2396
|
+
<td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
|
|
2377
2397
|
<td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
|
|
2378
|
-
<td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
|
|
2398
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
|
|
2379
2399
|
</tr>`;
|
|
2380
2400
|
}
|
|
2381
2401
|
html += `
|
|
@@ -2511,149 +2531,150 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2511
2531
|
* Helper function to extract observation field data
|
|
2512
2532
|
* @param column - Column data from the summary
|
|
2513
2533
|
* @param targetData - Record to populate with extracted data
|
|
2534
|
+
* @param templateUtilities - Instance of TemplateUtilities for utility functions
|
|
2514
2535
|
*/
|
|
2515
|
-
extractSummaryObservationFields(column, targetData) {
|
|
2536
|
+
extractSummaryObservationFields(column, targetData, templateUtilities) {
|
|
2516
2537
|
switch (column.title) {
|
|
2517
2538
|
case "Labs Name":
|
|
2518
|
-
targetData["code"] = column.text?.div ?? "";
|
|
2539
|
+
targetData["code"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2519
2540
|
break;
|
|
2520
2541
|
case "effectiveDateTime":
|
|
2521
|
-
targetData["effectiveDateTime"] = column.text?.div ?? "";
|
|
2542
|
+
targetData["effectiveDateTime"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2522
2543
|
break;
|
|
2523
2544
|
case "effectivePeriod.start":
|
|
2524
|
-
targetData["effectivePeriodStart"] = column.text?.div ?? "";
|
|
2545
|
+
targetData["effectivePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2525
2546
|
break;
|
|
2526
2547
|
case "effectivePeriod.end":
|
|
2527
|
-
targetData["effectivePeriodEnd"] = column.text?.div ?? "";
|
|
2548
|
+
targetData["effectivePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2528
2549
|
break;
|
|
2529
2550
|
// valueQuantity
|
|
2530
2551
|
case "valueQuantity.value":
|
|
2531
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2552
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2532
2553
|
targetData["valueType"] = "valueQuantity";
|
|
2533
2554
|
break;
|
|
2534
2555
|
case "valueQuantity.unit":
|
|
2535
|
-
targetData["unit"] = column.text?.div ?? "";
|
|
2556
|
+
targetData["unit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2536
2557
|
break;
|
|
2537
2558
|
// valueCodeableConcept
|
|
2538
2559
|
case "valueCodeableConcept.text":
|
|
2539
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2560
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2540
2561
|
targetData["valueType"] = "valueCodeableConcept";
|
|
2541
2562
|
break;
|
|
2542
2563
|
case "valueCodeableConcept.coding.display":
|
|
2543
2564
|
if (!targetData["value"]) {
|
|
2544
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2565
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2545
2566
|
targetData["valueType"] = "valueCodeableConcept";
|
|
2546
2567
|
}
|
|
2547
2568
|
break;
|
|
2548
2569
|
// valueString
|
|
2549
2570
|
case "valueString":
|
|
2550
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2571
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2551
2572
|
targetData["valueType"] = "valueString";
|
|
2552
2573
|
break;
|
|
2553
2574
|
// valueBoolean
|
|
2554
2575
|
case "valueBoolean":
|
|
2555
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2576
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2556
2577
|
targetData["valueType"] = "valueBoolean";
|
|
2557
2578
|
break;
|
|
2558
2579
|
// valueInteger
|
|
2559
2580
|
case "valueInteger":
|
|
2560
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2581
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2561
2582
|
targetData["valueType"] = "valueInteger";
|
|
2562
2583
|
break;
|
|
2563
2584
|
// valueDateTime
|
|
2564
2585
|
case "valueDateTime":
|
|
2565
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2586
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2566
2587
|
targetData["valueType"] = "valueDateTime";
|
|
2567
2588
|
break;
|
|
2568
2589
|
// valuePeriod
|
|
2569
2590
|
case "valuePeriod.start":
|
|
2570
|
-
targetData["valuePeriodStart"] = column.text?.div ?? "";
|
|
2591
|
+
targetData["valuePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2571
2592
|
targetData["valueType"] = "valuePeriod";
|
|
2572
2593
|
break;
|
|
2573
2594
|
case "valuePeriod.end":
|
|
2574
|
-
targetData["valuePeriodEnd"] = column.text?.div ?? "";
|
|
2595
|
+
targetData["valuePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2575
2596
|
targetData["valueType"] = "valuePeriod";
|
|
2576
2597
|
break;
|
|
2577
2598
|
// valueTime
|
|
2578
2599
|
case "valueTime":
|
|
2579
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2600
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2580
2601
|
targetData["valueType"] = "valueTime";
|
|
2581
2602
|
break;
|
|
2582
2603
|
// valueSampledData
|
|
2583
2604
|
case "valueSampledData.origin.value":
|
|
2584
|
-
targetData["sampledDataOriginValue"] = column.text?.div ?? "";
|
|
2605
|
+
targetData["sampledDataOriginValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2585
2606
|
targetData["valueType"] = "valueSampledData";
|
|
2586
2607
|
break;
|
|
2587
2608
|
case "valueSampledData.origin.unit":
|
|
2588
|
-
targetData["sampledDataOriginUnit"] = column.text?.div ?? "";
|
|
2609
|
+
targetData["sampledDataOriginUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2589
2610
|
break;
|
|
2590
2611
|
case "valueSampledData.period":
|
|
2591
|
-
targetData["sampledDataPeriod"] = column.text?.div ?? "";
|
|
2612
|
+
targetData["sampledDataPeriod"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2592
2613
|
break;
|
|
2593
2614
|
case "valueSampledData.factor":
|
|
2594
|
-
targetData["sampledDataFactor"] = column.text?.div ?? "";
|
|
2615
|
+
targetData["sampledDataFactor"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2595
2616
|
break;
|
|
2596
2617
|
case "valueSampledData.lowerLimit":
|
|
2597
|
-
targetData["sampledDataLowerLimit"] = column.text?.div ?? "";
|
|
2618
|
+
targetData["sampledDataLowerLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2598
2619
|
break;
|
|
2599
2620
|
case "valueSampledData.upperLimit":
|
|
2600
|
-
targetData["sampledDataUpperLimit"] = column.text?.div ?? "";
|
|
2621
|
+
targetData["sampledDataUpperLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2601
2622
|
break;
|
|
2602
2623
|
case "valueSampledData.data":
|
|
2603
|
-
targetData["sampledDataData"] = column.text?.div ?? "";
|
|
2624
|
+
targetData["sampledDataData"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2604
2625
|
break;
|
|
2605
2626
|
// valueRange
|
|
2606
2627
|
case "valueRange.low.value":
|
|
2607
|
-
targetData["valueRangeLowValue"] = column.text?.div ?? "";
|
|
2628
|
+
targetData["valueRangeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2608
2629
|
targetData["valueType"] = "valueRange";
|
|
2609
2630
|
break;
|
|
2610
2631
|
case "valueRange.low.unit":
|
|
2611
|
-
targetData["valueRangeLowUnit"] = column.text?.div ?? "";
|
|
2632
|
+
targetData["valueRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2612
2633
|
break;
|
|
2613
2634
|
case "valueRange.high.value":
|
|
2614
|
-
targetData["valueRangeHighValue"] = column.text?.div ?? "";
|
|
2635
|
+
targetData["valueRangeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2615
2636
|
break;
|
|
2616
2637
|
case "valueRange.high.unit":
|
|
2617
|
-
targetData["valueRangeHighUnit"] = column.text?.div ?? "";
|
|
2638
|
+
targetData["valueRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2618
2639
|
break;
|
|
2619
2640
|
// valueRatio
|
|
2620
2641
|
case "valueRatio.numerator.value":
|
|
2621
|
-
targetData["valueRatioNumeratorValue"] = column.text?.div ?? "";
|
|
2642
|
+
targetData["valueRatioNumeratorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2622
2643
|
targetData["valueType"] = "valueRatio";
|
|
2623
2644
|
break;
|
|
2624
2645
|
case "valueRatio.numerator.unit":
|
|
2625
|
-
targetData["valueRatioNumeratorUnit"] = column.text?.div ?? "";
|
|
2646
|
+
targetData["valueRatioNumeratorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2626
2647
|
break;
|
|
2627
2648
|
case "valueRatio.denominator.value":
|
|
2628
|
-
targetData["valueRatioDenominatorValue"] = column.text?.div ?? "";
|
|
2649
|
+
targetData["valueRatioDenominatorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2629
2650
|
break;
|
|
2630
2651
|
case "valueRatio.denominator.unit":
|
|
2631
|
-
targetData["valueRatioDenominatorUnit"] = column.text?.div ?? "";
|
|
2652
|
+
targetData["valueRatioDenominatorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2632
2653
|
break;
|
|
2633
2654
|
// referenceRange
|
|
2634
2655
|
case "referenceRange.low.value":
|
|
2635
|
-
targetData["referenceRangeLow"] = column.text?.div ?? "";
|
|
2656
|
+
targetData["referenceRangeLow"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2636
2657
|
break;
|
|
2637
2658
|
case "referenceRange.low.unit":
|
|
2638
|
-
targetData["referenceRangeLowUnit"] = column.text?.div ?? "";
|
|
2659
|
+
targetData["referenceRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2639
2660
|
break;
|
|
2640
2661
|
case "referenceRange.high.value":
|
|
2641
|
-
targetData["referenceRangeHigh"] = column.text?.div ?? "";
|
|
2662
|
+
targetData["referenceRangeHigh"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2642
2663
|
break;
|
|
2643
2664
|
case "referenceRange.high.unit":
|
|
2644
|
-
targetData["referenceRangeHighUnit"] = column.text?.div ?? "";
|
|
2665
|
+
targetData["referenceRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2645
2666
|
break;
|
|
2646
2667
|
case "referenceRange.age.low.value":
|
|
2647
|
-
targetData["referenceRangeAgeLowValue"] = column.text?.div ?? "";
|
|
2668
|
+
targetData["referenceRangeAgeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2648
2669
|
break;
|
|
2649
2670
|
case "referenceRange.age.low.unit":
|
|
2650
|
-
targetData["referenceRangeAgeLowUnit"] = column.text?.div ?? "";
|
|
2671
|
+
targetData["referenceRangeAgeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2651
2672
|
break;
|
|
2652
2673
|
case "referenceRange.age.high.value":
|
|
2653
|
-
targetData["referenceRangeAgeHighValue"] = column.text?.div ?? "";
|
|
2674
|
+
targetData["referenceRangeAgeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2654
2675
|
break;
|
|
2655
2676
|
case "referenceRange.age.high.unit":
|
|
2656
|
-
targetData["referenceRangeAgeHighUnit"] = column.text?.div ?? "";
|
|
2677
|
+
targetData["referenceRangeAgeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2657
2678
|
break;
|
|
2658
2679
|
default:
|
|
2659
2680
|
break;
|
|
@@ -2706,28 +2727,28 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2706
2727
|
for (const componentSection of columnData.section) {
|
|
2707
2728
|
const componentData = {};
|
|
2708
2729
|
for (const nestedColumn of componentSection.section ?? []) {
|
|
2709
|
-
this.extractSummaryObservationFields(nestedColumn, componentData);
|
|
2730
|
+
this.extractSummaryObservationFields(nestedColumn, componentData, templateUtilities);
|
|
2710
2731
|
}
|
|
2711
2732
|
if (Object.keys(componentData).length > 0) {
|
|
2712
2733
|
components.push(componentData);
|
|
2713
2734
|
}
|
|
2714
2735
|
}
|
|
2715
2736
|
} else {
|
|
2716
|
-
this.extractSummaryObservationFields(columnData, data);
|
|
2737
|
+
this.extractSummaryObservationFields(columnData, data, templateUtilities);
|
|
2717
2738
|
}
|
|
2718
2739
|
} else if (resourceItem.title === "DiagnosticReportLab Summary Grouped by DiagnosticReport|Lab Code") {
|
|
2719
2740
|
switch (columnData.title) {
|
|
2720
2741
|
case "Diagnostic Report Name":
|
|
2721
|
-
data["report"] = columnData.text?.div ?? "";
|
|
2742
|
+
data["report"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2722
2743
|
break;
|
|
2723
2744
|
case "Performer":
|
|
2724
|
-
data["performer"] = columnData.text?.div ?? "";
|
|
2745
|
+
data["performer"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2725
2746
|
break;
|
|
2726
2747
|
case "Issued Date":
|
|
2727
|
-
data["issued"] = columnData.text?.div ?? "";
|
|
2748
|
+
data["issued"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2728
2749
|
break;
|
|
2729
2750
|
case "Status":
|
|
2730
|
-
data["status"] = columnData.text?.div ?? "";
|
|
2751
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2731
2752
|
break;
|
|
2732
2753
|
default:
|
|
2733
2754
|
break;
|
|
@@ -2752,8 +2773,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2752
2773
|
observationhtml += `
|
|
2753
2774
|
<tr>
|
|
2754
2775
|
<td>${componentCode}</td>
|
|
2755
|
-
<td>${component["formattedValue"] ?? "-"}</td>
|
|
2756
|
-
<td>${component["referenceRange"]?.trim() ?? "-"}</td>
|
|
2776
|
+
<td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? "-"}</td>
|
|
2777
|
+
<td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? "-"}</td>
|
|
2757
2778
|
<td>${date ?? "-"}</td>
|
|
2758
2779
|
</tr>`;
|
|
2759
2780
|
}
|
|
@@ -2766,8 +2787,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2766
2787
|
observationhtml += `
|
|
2767
2788
|
<tr>
|
|
2768
2789
|
<td>${data["code"] ?? "-"}</td>
|
|
2769
|
-
<td>${data["formattedValue"] ?? "-"}</td>
|
|
2770
|
-
<td>${data["referenceRange"]?.trim() ?? "-"}</td>
|
|
2790
|
+
<td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? "-"}</td>
|
|
2791
|
+
<td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? "-"}</td>
|
|
2771
2792
|
<td>${date ?? "-"}</td>
|
|
2772
2793
|
</tr>`;
|
|
2773
2794
|
}
|
|
@@ -2927,7 +2948,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2927
2948
|
<tbody>`;
|
|
2928
2949
|
const observationAdded = /* @__PURE__ */ new Set();
|
|
2929
2950
|
for (const obs of observations) {
|
|
2930
|
-
const obsCode = templateUtilities.codeableConcept(obs.code);
|
|
2951
|
+
const obsCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code));
|
|
2931
2952
|
if (!observationAdded.has(obsCode)) {
|
|
2932
2953
|
observationAdded.add(obsCode);
|
|
2933
2954
|
html += `
|
|
@@ -2966,7 +2987,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2966
2987
|
<tbody>`;
|
|
2967
2988
|
const diagnosticReportAdded = /* @__PURE__ */ new Set();
|
|
2968
2989
|
for (const report of reports) {
|
|
2969
|
-
const reportName = templateUtilities.codeableConcept(report.code);
|
|
2990
|
+
const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(report.code));
|
|
2970
2991
|
if (!diagnosticReportAdded.has(reportName)) {
|
|
2971
2992
|
diagnosticReportAdded.add(reportName);
|
|
2972
2993
|
let resultCount = "";
|
|
@@ -3080,7 +3101,7 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3080
3101
|
const proc = resourceItem;
|
|
3081
3102
|
html += `
|
|
3082
3103
|
<tr id="${templateUtilities.narrativeLinkId(proc)}">
|
|
3083
|
-
<td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
|
|
3104
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(proc.code, "display"))}</td>
|
|
3084
3105
|
<td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
|
|
3085
3106
|
<td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
|
|
3086
3107
|
</tr>`;
|
|
@@ -3132,7 +3153,7 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3132
3153
|
for (const obs of observations) {
|
|
3133
3154
|
html += `
|
|
3134
3155
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
3135
|
-
<td>${templateUtilities.codeableConcept(obs.code)}</td>
|
|
3156
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code))}</td>
|
|
3136
3157
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
3137
3158
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
3138
3159
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
@@ -3177,7 +3198,7 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3177
3198
|
<tbody>`;
|
|
3178
3199
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
3179
3200
|
for (const cond of resolvedConditions) {
|
|
3180
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
3201
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
3181
3202
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3182
3203
|
addedConditionCodes.add(conditionCode);
|
|
3183
3204
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -3263,7 +3284,7 @@ var PlanOfCareTemplate = class {
|
|
|
3263
3284
|
const data = {};
|
|
3264
3285
|
for (const columnData of rowData.section ?? []) {
|
|
3265
3286
|
if (columnData.title) {
|
|
3266
|
-
data[columnData.title] = columnData.text?.div ?? "";
|
|
3287
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3267
3288
|
}
|
|
3268
3289
|
}
|
|
3269
3290
|
if (data["status"] !== "active") {
|
|
@@ -3339,7 +3360,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3339
3360
|
<tbody>`;
|
|
3340
3361
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
3341
3362
|
for (const cond of activeConditions) {
|
|
3342
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
3363
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
3343
3364
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3344
3365
|
addedConditionCodes.add(conditionCode);
|
|
3345
3366
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -3384,7 +3405,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3384
3405
|
if (impression.finding && impression.finding.length > 0) {
|
|
3385
3406
|
findingsHtml = "<ul>";
|
|
3386
3407
|
for (const finding of impression.finding) {
|
|
3387
|
-
const findingText = finding.itemCodeableConcept ? templateUtilities.codeableConcept(finding.itemCodeableConcept) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
|
|
3408
|
+
const findingText = finding.itemCodeableConcept ? templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(finding.itemCodeableConcept)) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
|
|
3388
3409
|
const cause = finding.basis || "";
|
|
3389
3410
|
findingsHtml += `<li>${findingText}${cause ? ` - ${cause}` : ""}</li>`;
|
|
3390
3411
|
}
|
|
@@ -3445,9 +3466,9 @@ var PregnancyTemplate = class _PregnancyTemplate {
|
|
|
3445
3466
|
const obs = resource;
|
|
3446
3467
|
html += `
|
|
3447
3468
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
3448
|
-
<td>${templateUtilities.extractPregnancyStatus(obs)}</td>
|
|
3469
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.extractPregnancyStatus(obs))}</td>
|
|
3449
3470
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
3450
|
-
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
3471
|
+
<td>${obs.effectiveDateTime ? templateUtilities.renderTextAsHtml(templateUtilities.renderTime(obs.effectiveDateTime, timezone)) : obs.effectivePeriod ? templateUtilities.renderTextAsHtml(templateUtilities.renderPeriod(obs.effectivePeriod, timezone)) : ""}</td>
|
|
3451
3472
|
</tr>`;
|
|
3452
3473
|
}
|
|
3453
3474
|
html += `
|
|
@@ -3497,7 +3518,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
|
|
|
3497
3518
|
const consent = resourceItem;
|
|
3498
3519
|
html += `
|
|
3499
3520
|
<tr id="${templateUtilities.narrativeLinkId(consent)}">
|
|
3500
|
-
<td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
|
|
3521
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(consent.scope, "display"))}</td>
|
|
3501
3522
|
<td>${consent.status || ""}</td>
|
|
3502
3523
|
<td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
|
|
3503
3524
|
<td>${consent.dateTime || ""}</td>
|
|
@@ -3518,16 +3539,18 @@ var TypeScriptTemplateMapper = class {
|
|
|
3518
3539
|
* @param resources - FHIR resources
|
|
3519
3540
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3520
3541
|
* @param useSectionSummary - Whether to use the section summary for narrative generation
|
|
3542
|
+
* @param now - Optional current date to use for generating relative dates in the narrative
|
|
3521
3543
|
* @returns HTML string for rendering
|
|
3522
3544
|
*/
|
|
3523
|
-
static generateNarrative(section, resources, timezone, useSectionSummary = false) {
|
|
3545
|
+
static generateNarrative(section, resources, timezone, useSectionSummary = false, now) {
|
|
3524
3546
|
const templateClass = this.sectionToTemplate[section];
|
|
3525
3547
|
if (!templateClass) {
|
|
3526
3548
|
throw new Error(`No template found for section: ${section}`);
|
|
3527
3549
|
}
|
|
3528
3550
|
return useSectionSummary ? templateClass.generateSummaryNarrative(
|
|
3529
3551
|
resources,
|
|
3530
|
-
timezone
|
|
3552
|
+
timezone,
|
|
3553
|
+
now
|
|
3531
3554
|
) : templateClass.generateNarrative(resources, timezone);
|
|
3532
3555
|
}
|
|
3533
3556
|
};
|
|
@@ -3585,14 +3608,15 @@ var NarrativeGenerator = class {
|
|
|
3585
3608
|
* @param resources - Array of domain resources
|
|
3586
3609
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3587
3610
|
* @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
|
|
3611
|
+
* @param now - Optional date parameter
|
|
3588
3612
|
* @returns Generated HTML content or undefined if no resources
|
|
3589
3613
|
*/
|
|
3590
|
-
static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false) {
|
|
3614
|
+
static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false, now) {
|
|
3591
3615
|
if (!resources || resources.length === 0) {
|
|
3592
3616
|
return void 0;
|
|
3593
3617
|
}
|
|
3594
3618
|
try {
|
|
3595
|
-
const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary);
|
|
3619
|
+
const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary, now);
|
|
3596
3620
|
if (!content) {
|
|
3597
3621
|
return void 0;
|
|
3598
3622
|
}
|
|
@@ -3614,8 +3638,8 @@ var NarrativeGenerator = class {
|
|
|
3614
3638
|
const options = aggressive ? AGGRESSIVE_MINIFY_OPTIONS : DEFAULT_MINIFY_OPTIONS;
|
|
3615
3639
|
return await htmlMinify(html, options);
|
|
3616
3640
|
} catch (error) {
|
|
3617
|
-
console.warn("HTML minification failed", error);
|
|
3618
|
-
return
|
|
3641
|
+
console.warn("HTML minification failed", error, html);
|
|
3642
|
+
return `${error instanceof Error ? error.message : String(error)}`;
|
|
3619
3643
|
}
|
|
3620
3644
|
}
|
|
3621
3645
|
/**
|
|
@@ -3644,10 +3668,11 @@ var NarrativeGenerator = class {
|
|
|
3644
3668
|
* @param timezone - Optional timezone to use for date formatting
|
|
3645
3669
|
* @param minify - Whether to minify the HTML content (default: true)
|
|
3646
3670
|
* @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
|
|
3671
|
+
* @param now - Optional date parameter
|
|
3647
3672
|
* @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
|
|
3648
3673
|
*/
|
|
3649
|
-
static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false) {
|
|
3650
|
-
const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary);
|
|
3674
|
+
static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false, now) {
|
|
3675
|
+
const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary, now);
|
|
3651
3676
|
if (!content) {
|
|
3652
3677
|
return void 0;
|
|
3653
3678
|
}
|
|
@@ -3805,6 +3830,12 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3805
3830
|
if (sectionType === "Patient" /* PATIENT */) {
|
|
3806
3831
|
continue;
|
|
3807
3832
|
}
|
|
3833
|
+
const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
|
|
3834
|
+
const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
|
|
3835
|
+
if (sectionIPSSummary.length > 0) {
|
|
3836
|
+
await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
|
|
3837
|
+
continue;
|
|
3838
|
+
}
|
|
3808
3839
|
const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
|
|
3809
3840
|
const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
|
|
3810
3841
|
if (sectionSummary.length > 0) {
|
|
@@ -3824,8 +3855,9 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3824
3855
|
* @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
|
|
3825
3856
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3826
3857
|
* @param patientId - Optional patient ID to use as primary patient for composition reference
|
|
3858
|
+
* @param now - Optional current date to use for composition date (defaults to new Date())
|
|
3827
3859
|
*/
|
|
3828
|
-
async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId) {
|
|
3860
|
+
async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId, now) {
|
|
3829
3861
|
if (baseUrl.endsWith("/")) {
|
|
3830
3862
|
baseUrl = baseUrl.slice(0, -1);
|
|
3831
3863
|
}
|
|
@@ -3852,20 +3884,22 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3852
3884
|
// Assuming patient is also a practitioner for simplicity
|
|
3853
3885
|
display: authorOrganizationName
|
|
3854
3886
|
}],
|
|
3855
|
-
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3887
|
+
date: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
3856
3888
|
title: "International Patient Summary",
|
|
3857
3889
|
section: this.sections,
|
|
3858
3890
|
text: await NarrativeGenerator.generateNarrativeAsync(
|
|
3859
3891
|
"Patient" /* PATIENT */,
|
|
3860
3892
|
this.patients,
|
|
3861
3893
|
timezone,
|
|
3862
|
-
true
|
|
3894
|
+
true,
|
|
3895
|
+
false,
|
|
3896
|
+
now
|
|
3863
3897
|
)
|
|
3864
3898
|
};
|
|
3865
3899
|
const bundle = {
|
|
3866
3900
|
resourceType: "Bundle",
|
|
3867
3901
|
type: "document",
|
|
3868
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3902
|
+
timestamp: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
3869
3903
|
identifier: {
|
|
3870
3904
|
"system": "urn:ietf:rfc:3986",
|
|
3871
3905
|
"value": "urn:uuid:4dcfd353-49fd-4ab0-b521-c8d57ced74d6"
|