@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.cjs
CHANGED
|
@@ -161,6 +161,9 @@ var IPSSectionSummaryCompositionFilter = {
|
|
|
161
161
|
// [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)),
|
|
162
162
|
["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && c.code === "procedure_summary_document")
|
|
163
163
|
};
|
|
164
|
+
var IPSSectionSummaryIPSCompositionFilter = {
|
|
165
|
+
["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")
|
|
166
|
+
};
|
|
164
167
|
var IPSSectionResourceHelper = class {
|
|
165
168
|
static getResourceFilterForSection(section) {
|
|
166
169
|
return IPSSectionResourceFilters[section];
|
|
@@ -173,6 +176,9 @@ var IPSSectionResourceHelper = class {
|
|
|
173
176
|
static getSummaryCompositionFilterForSection(section) {
|
|
174
177
|
return IPSSectionSummaryCompositionFilter[section];
|
|
175
178
|
}
|
|
179
|
+
static getSummaryIPSCompositionFilterForSection(section) {
|
|
180
|
+
return IPSSectionSummaryIPSCompositionFilter[section];
|
|
181
|
+
}
|
|
176
182
|
};
|
|
177
183
|
|
|
178
184
|
// src/narratives/templates/typescript/TemplateUtilities.ts
|
|
@@ -248,7 +254,7 @@ var TemplateUtilities = class {
|
|
|
248
254
|
renderOrganization(orgRef) {
|
|
249
255
|
const organization = orgRef && this.resolveReference(orgRef);
|
|
250
256
|
if (organization && organization.resourceType === "Organization" && organization.name) {
|
|
251
|
-
return organization.name;
|
|
257
|
+
return this.renderTextAsHtml(organization.name);
|
|
252
258
|
}
|
|
253
259
|
return "";
|
|
254
260
|
}
|
|
@@ -260,7 +266,7 @@ var TemplateUtilities = class {
|
|
|
260
266
|
renderVaccineManufacturer(immunization) {
|
|
261
267
|
const organization = immunization.manufacturer && this.resolveReference(immunization.manufacturer);
|
|
262
268
|
if (organization && organization.resourceType === "Organization" && organization.name) {
|
|
263
|
-
return organization.name;
|
|
269
|
+
return this.renderTextAsHtml(organization.name);
|
|
264
270
|
}
|
|
265
271
|
return "";
|
|
266
272
|
}
|
|
@@ -299,7 +305,7 @@ var TemplateUtilities = class {
|
|
|
299
305
|
*/
|
|
300
306
|
renderMedicationCode(medication) {
|
|
301
307
|
if (medication && medication.code) {
|
|
302
|
-
return this.codeableConcept(medication.code, "display");
|
|
308
|
+
return this.renderTextAsHtml(this.codeableConcept(medication.code, "display"));
|
|
303
309
|
}
|
|
304
310
|
return "";
|
|
305
311
|
}
|
|
@@ -310,7 +316,7 @@ var TemplateUtilities = class {
|
|
|
310
316
|
*/
|
|
311
317
|
renderDoseNumber(doseNumber) {
|
|
312
318
|
if (doseNumber && doseNumber.value !== void 0) {
|
|
313
|
-
return doseNumber.value.toString();
|
|
319
|
+
return this.renderTextAsHtml(doseNumber.value.toString());
|
|
314
320
|
}
|
|
315
321
|
return "";
|
|
316
322
|
}
|
|
@@ -321,7 +327,7 @@ var TemplateUtilities = class {
|
|
|
321
327
|
*/
|
|
322
328
|
renderValueUnit(value) {
|
|
323
329
|
if (value && value.constructor?.name === "Quantity" && value.unit) {
|
|
324
|
-
return value.unit;
|
|
330
|
+
return this.renderTextAsHtml(value.unit);
|
|
325
331
|
}
|
|
326
332
|
return "";
|
|
327
333
|
}
|
|
@@ -387,7 +393,7 @@ var TemplateUtilities = class {
|
|
|
387
393
|
* @returns Comma-separated string of items
|
|
388
394
|
*/
|
|
389
395
|
safeConcat(list, attr) {
|
|
390
|
-
return this.concat(list || [], attr);
|
|
396
|
+
return this.renderTextAsHtml(this.concat(list || [], attr));
|
|
391
397
|
}
|
|
392
398
|
/**
|
|
393
399
|
* Concatenates text from a list of CodeableConcept objects
|
|
@@ -404,7 +410,7 @@ var TemplateUtilities = class {
|
|
|
404
410
|
items.push(item.text);
|
|
405
411
|
}
|
|
406
412
|
}
|
|
407
|
-
return items.join(", ");
|
|
413
|
+
return this.renderTextAsHtml(items.join(", "));
|
|
408
414
|
}
|
|
409
415
|
/**
|
|
410
416
|
* Concatenates reaction manifestations
|
|
@@ -425,7 +431,7 @@ var TemplateUtilities = class {
|
|
|
425
431
|
}
|
|
426
432
|
}
|
|
427
433
|
}
|
|
428
|
-
return texts.join(", ");
|
|
434
|
+
return this.renderTextAsHtml(texts.join(", "));
|
|
429
435
|
}
|
|
430
436
|
/**
|
|
431
437
|
* Concatenates dose numbers
|
|
@@ -442,7 +448,7 @@ var TemplateUtilities = class {
|
|
|
442
448
|
doseNumbers.push(item.doseNumberPositiveInt.toString());
|
|
443
449
|
}
|
|
444
450
|
}
|
|
445
|
-
return doseNumbers.join(", ");
|
|
451
|
+
return this.renderTextAsHtml(doseNumbers.join(", "));
|
|
446
452
|
}
|
|
447
453
|
/**
|
|
448
454
|
* Concatenates dosage routes
|
|
@@ -459,7 +465,7 @@ var TemplateUtilities = class {
|
|
|
459
465
|
routes.push(item.route.text);
|
|
460
466
|
}
|
|
461
467
|
}
|
|
462
|
-
return routes.join(", ");
|
|
468
|
+
return this.renderTextAsHtml(routes.join(", "));
|
|
463
469
|
}
|
|
464
470
|
/**
|
|
465
471
|
* Returns the first item from a list of CodeableConcept objects
|
|
@@ -468,7 +474,7 @@ var TemplateUtilities = class {
|
|
|
468
474
|
*/
|
|
469
475
|
firstFromCodeableConceptList(list) {
|
|
470
476
|
if (list && Array.isArray(list) && list[0]) {
|
|
471
|
-
return this.codeableConcept(list[0], "display");
|
|
477
|
+
return this.renderTextAsHtml(this.codeableConcept(list[0], "display"));
|
|
472
478
|
}
|
|
473
479
|
return "";
|
|
474
480
|
}
|
|
@@ -487,7 +493,7 @@ var TemplateUtilities = class {
|
|
|
487
493
|
texts.push(item.text);
|
|
488
494
|
}
|
|
489
495
|
}
|
|
490
|
-
return texts.join(", ");
|
|
496
|
+
return this.renderTextAsHtml(texts.join(", "));
|
|
491
497
|
}
|
|
492
498
|
/**
|
|
493
499
|
* Renders component codes
|
|
@@ -819,9 +825,11 @@ var TemplateUtilities = class {
|
|
|
819
825
|
return "";
|
|
820
826
|
}
|
|
821
827
|
/**
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
828
|
+
* Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
|
|
829
|
+
* This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
|
|
830
|
+
* and to preserve formatting. Use this in templates or UI components that need to safely display multi-line or arbitrary text.
|
|
831
|
+
* @param text - The text to render as HTML
|
|
832
|
+
* @returns The HTML-safe string with newlines converted to <br />
|
|
825
833
|
*/
|
|
826
834
|
renderTextAsHtml(text) {
|
|
827
835
|
if (!text || text.trim() === "") {
|
|
@@ -885,7 +893,7 @@ var TemplateUtilities = class {
|
|
|
885
893
|
dateTime = import_luxon.DateTime.fromISO(String(dateValue));
|
|
886
894
|
}
|
|
887
895
|
if (!dateTime.isValid) {
|
|
888
|
-
return String(dateValue);
|
|
896
|
+
return this.renderTextAsHtml(String(dateValue));
|
|
889
897
|
}
|
|
890
898
|
if (dateOnly) {
|
|
891
899
|
dateTime = dateTime.toUTC();
|
|
@@ -901,9 +909,9 @@ var TemplateUtilities = class {
|
|
|
901
909
|
hour12: true,
|
|
902
910
|
timeZoneName: "short"
|
|
903
911
|
};
|
|
904
|
-
return dateTime.toLocaleString(formatOptions);
|
|
912
|
+
return this.renderTextAsHtml(dateTime.toLocaleString(formatOptions));
|
|
905
913
|
} catch {
|
|
906
|
-
return String(dateValue);
|
|
914
|
+
return this.renderTextAsHtml(String(dateValue));
|
|
907
915
|
}
|
|
908
916
|
}
|
|
909
917
|
/**
|
|
@@ -1607,7 +1615,7 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1607
1615
|
const uniqueLanguages = /* @__PURE__ */ new Set();
|
|
1608
1616
|
const preferredLanguages = /* @__PURE__ */ new Set();
|
|
1609
1617
|
patient.communication.forEach((comm) => {
|
|
1610
|
-
const language = templateUtilities.codeableConcept(comm.language);
|
|
1618
|
+
const language = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(comm.language));
|
|
1611
1619
|
if (language) {
|
|
1612
1620
|
if (comm.preferred) {
|
|
1613
1621
|
preferredLanguages.add(language);
|
|
@@ -1665,13 +1673,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1665
1673
|
for (const columnData of rowData.section ?? []) {
|
|
1666
1674
|
switch (columnData.title) {
|
|
1667
1675
|
case "Allergen Name":
|
|
1668
|
-
data["allergen"] = columnData.text?.div ?? "";
|
|
1676
|
+
data["allergen"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1669
1677
|
break;
|
|
1670
1678
|
case "Criticality":
|
|
1671
|
-
data["criticality"] = columnData.text?.div ?? "";
|
|
1679
|
+
data["criticality"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1672
1680
|
break;
|
|
1673
1681
|
case "Recorded Date":
|
|
1674
|
-
data["recordedDate"] = columnData.text?.div ?? "";
|
|
1682
|
+
data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1675
1683
|
break;
|
|
1676
1684
|
default:
|
|
1677
1685
|
break;
|
|
@@ -1792,11 +1800,11 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1792
1800
|
for (const allergy of allergies) {
|
|
1793
1801
|
html += `
|
|
1794
1802
|
<tr id="${templateUtilities.narrativeLinkId(allergy.extension)}">
|
|
1795
|
-
<td class="Name"><span class="AllergenName">${templateUtilities.codeableConcept(allergy.code)}</span></td>
|
|
1796
|
-
<td class="Status">${templateUtilities.codeableConcept(allergy.clinicalStatus) || "-"}</td>
|
|
1797
|
-
<td class="Category">${templateUtilities.safeConcat(allergy.category) || "-"}</td>
|
|
1798
|
-
<td class="Reaction">${templateUtilities.concatReactionManifestation(allergy.reaction) || "-"}</td>
|
|
1799
|
-
<td class="OnsetDate">${templateUtilities.renderTime(allergy.onsetDateTime, timezone) || "-"}</td>
|
|
1803
|
+
<td class="Name"><span class="AllergenName">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.code))}</span></td>
|
|
1804
|
+
<td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.clinicalStatus)) || "-"}</td>
|
|
1805
|
+
<td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || "-"}</td>
|
|
1806
|
+
<td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || "-"}</td>
|
|
1807
|
+
<td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || "-"}</td>
|
|
1800
1808
|
<td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
|
|
1801
1809
|
if (includeResolved) {
|
|
1802
1810
|
let endDate = "-";
|
|
@@ -1809,7 +1817,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1809
1817
|
}
|
|
1810
1818
|
}
|
|
1811
1819
|
html += `
|
|
1812
|
-
<td class="ResolvedDate">${endDate}</td>`;
|
|
1820
|
+
<td class="ResolvedDate">${templateUtilities.renderTextAsHtml(endDate)}</td>`;
|
|
1813
1821
|
}
|
|
1814
1822
|
html += `</tr>`;
|
|
1815
1823
|
}
|
|
@@ -1832,17 +1840,21 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
1832
1840
|
* Generate HTML narrative for Medication resources using summary
|
|
1833
1841
|
* @param resources - FHIR Composition resources
|
|
1834
1842
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
1843
|
+
* @param now - Optional current date to use for calculations (defaults to new Date())
|
|
1835
1844
|
* @returns HTML string for rendering
|
|
1836
1845
|
*/
|
|
1837
|
-
generateSummaryNarrative(resources, timezone) {
|
|
1846
|
+
generateSummaryNarrative(resources, timezone, now) {
|
|
1838
1847
|
const templateUtilities = new TemplateUtilities(resources);
|
|
1839
1848
|
let isSummaryCreated = false;
|
|
1849
|
+
const currentDate = now || /* @__PURE__ */ new Date();
|
|
1850
|
+
const twelveMonthsAgo = new Date(currentDate.getFullYear(), currentDate.getMonth() - 12, currentDate.getDate());
|
|
1840
1851
|
let html = `
|
|
1841
1852
|
<div>
|
|
1842
1853
|
<table>
|
|
1843
1854
|
<thead>
|
|
1844
1855
|
<tr>
|
|
1845
1856
|
<th>Medication</th>
|
|
1857
|
+
<th>Status</th>
|
|
1846
1858
|
<th>Sig</th>
|
|
1847
1859
|
<th>Days of Supply</th>
|
|
1848
1860
|
<th>Refills</th>
|
|
@@ -1856,40 +1868,48 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
1856
1868
|
for (const columnData of rowData.section ?? []) {
|
|
1857
1869
|
switch (columnData.title) {
|
|
1858
1870
|
case "Medication Name":
|
|
1859
|
-
data["medication"] = columnData.text?.div ?? "";
|
|
1871
|
+
data["medication"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1860
1872
|
break;
|
|
1861
1873
|
case "Status":
|
|
1862
|
-
data["status"] = columnData.text?.div ?? "";
|
|
1874
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1863
1875
|
break;
|
|
1864
1876
|
case "Prescriber Instruction":
|
|
1865
|
-
data["sig-prescriber"] = columnData.text?.div ?? "";
|
|
1877
|
+
data["sig-prescriber"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1866
1878
|
break;
|
|
1867
1879
|
case "Pharmacy Instruction":
|
|
1868
|
-
data["sig-pharmacy"] = columnData.text?.div ?? "";
|
|
1880
|
+
data["sig-pharmacy"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1869
1881
|
break;
|
|
1870
1882
|
case "Days Of Supply":
|
|
1871
|
-
data["daysOfSupply"] = columnData.text?.div ?? "";
|
|
1883
|
+
data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1872
1884
|
break;
|
|
1873
1885
|
case "Refills Remaining":
|
|
1874
|
-
data["refills"] = columnData.text?.div ?? "";
|
|
1886
|
+
data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1875
1887
|
break;
|
|
1876
1888
|
case "Authored On Date":
|
|
1877
|
-
data["startDate"] = columnData.text?.div ?? "";
|
|
1889
|
+
data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1878
1890
|
break;
|
|
1879
1891
|
default:
|
|
1880
1892
|
break;
|
|
1881
1893
|
}
|
|
1882
1894
|
}
|
|
1883
|
-
|
|
1895
|
+
let startDateObj;
|
|
1896
|
+
if (data["startDate"]) {
|
|
1897
|
+
startDateObj = new Date(data["startDate"]);
|
|
1898
|
+
if (isNaN(startDateObj.getTime())) {
|
|
1899
|
+
startDateObj = void 0;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
if (data["status"] === "active" || startDateObj && startDateObj >= twelveMonthsAgo) {
|
|
1884
1903
|
isSummaryCreated = true;
|
|
1885
1904
|
html += `
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1905
|
+
<tr>
|
|
1906
|
+
<td>${templateUtilities.renderTextAsHtml(data["medication"])}</td>
|
|
1907
|
+
<td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
|
|
1908
|
+
<td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
|
|
1909
|
+
<td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
|
|
1910
|
+
<td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
|
|
1911
|
+
<td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
|
|
1912
|
+
</tr>`;
|
|
1893
1913
|
}
|
|
1894
1914
|
}
|
|
1895
1915
|
}
|
|
@@ -2111,13 +2131,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2111
2131
|
for (const columnData of rowData.section ?? []) {
|
|
2112
2132
|
switch (columnData.title) {
|
|
2113
2133
|
case "Immunization Name":
|
|
2114
|
-
data["immunization"] = columnData.text?.div ?? "";
|
|
2134
|
+
data["immunization"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2115
2135
|
break;
|
|
2116
2136
|
case "Status":
|
|
2117
|
-
data["status"] = columnData.text?.div ?? "";
|
|
2137
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2118
2138
|
break;
|
|
2119
2139
|
case "occurrenceDateTime":
|
|
2120
|
-
data["occurrenceDateTime"] = columnData.text?.div ?? "";
|
|
2140
|
+
data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2121
2141
|
break;
|
|
2122
2142
|
default:
|
|
2123
2143
|
break;
|
|
@@ -2168,7 +2188,7 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2168
2188
|
const imm = resourceItem;
|
|
2169
2189
|
html += `
|
|
2170
2190
|
<tr id="${templateUtilities.narrativeLinkId(imm)}">
|
|
2171
|
-
<td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
|
|
2191
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(imm.vaccineCode))}</td>
|
|
2172
2192
|
<td>${imm.status || ""}</td>
|
|
2173
2193
|
<td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
|
|
2174
2194
|
<td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
|
|
@@ -2224,7 +2244,7 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2224
2244
|
<tbody>`;
|
|
2225
2245
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
2226
2246
|
for (const cond of activeConditions) {
|
|
2227
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
2247
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
2228
2248
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
2229
2249
|
addedConditionCodes.add(conditionCode);
|
|
2230
2250
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -2284,7 +2304,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2284
2304
|
const vitalData = {};
|
|
2285
2305
|
for (const component of columnData.section?.[0]?.section ?? []) {
|
|
2286
2306
|
if (component.title) {
|
|
2287
|
-
vitalData[component.title] = component.text?.div ?? "";
|
|
2307
|
+
vitalData[component.title] = templateUtilities.renderTextAsHtml(component.text?.div ?? "");
|
|
2288
2308
|
}
|
|
2289
2309
|
}
|
|
2290
2310
|
const vitalValue = templateUtilities.extractObservationSummaryValue(
|
|
@@ -2296,7 +2316,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2296
2316
|
data[dataKey] = vitalValue;
|
|
2297
2317
|
}
|
|
2298
2318
|
}
|
|
2299
|
-
data[columnTitle] = columnData.text?.div ?? "";
|
|
2319
|
+
data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2300
2320
|
}
|
|
2301
2321
|
}
|
|
2302
2322
|
isSummaryCreated = true;
|
|
@@ -2346,7 +2366,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2346
2366
|
for (const obs of observations) {
|
|
2347
2367
|
html += `
|
|
2348
2368
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
2349
|
-
<td>${templateUtilities.codeableConcept(obs.code, "display")}</td>
|
|
2369
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code, "display"))}</td>
|
|
2350
2370
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
2351
2371
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
2352
2372
|
<td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
|
|
@@ -2400,10 +2420,10 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
|
|
|
2400
2420
|
for (const dus of deviceStatements) {
|
|
2401
2421
|
html += `
|
|
2402
2422
|
<tr id="${templateUtilities.narrativeLinkId(dus)}">
|
|
2403
|
-
<td>${templateUtilities.renderDevice(dus.device)}</td>
|
|
2404
|
-
<td>${dus.status || ""}</td>
|
|
2423
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device))}</td>
|
|
2424
|
+
<td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
|
|
2405
2425
|
<td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
|
|
2406
|
-
<td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
|
|
2426
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
|
|
2407
2427
|
</tr>`;
|
|
2408
2428
|
}
|
|
2409
2429
|
html += `
|
|
@@ -2539,149 +2559,150 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2539
2559
|
* Helper function to extract observation field data
|
|
2540
2560
|
* @param column - Column data from the summary
|
|
2541
2561
|
* @param targetData - Record to populate with extracted data
|
|
2562
|
+
* @param templateUtilities - Instance of TemplateUtilities for utility functions
|
|
2542
2563
|
*/
|
|
2543
|
-
extractSummaryObservationFields(column, targetData) {
|
|
2564
|
+
extractSummaryObservationFields(column, targetData, templateUtilities) {
|
|
2544
2565
|
switch (column.title) {
|
|
2545
2566
|
case "Labs Name":
|
|
2546
|
-
targetData["code"] = column.text?.div ?? "";
|
|
2567
|
+
targetData["code"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2547
2568
|
break;
|
|
2548
2569
|
case "effectiveDateTime":
|
|
2549
|
-
targetData["effectiveDateTime"] = column.text?.div ?? "";
|
|
2570
|
+
targetData["effectiveDateTime"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2550
2571
|
break;
|
|
2551
2572
|
case "effectivePeriod.start":
|
|
2552
|
-
targetData["effectivePeriodStart"] = column.text?.div ?? "";
|
|
2573
|
+
targetData["effectivePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2553
2574
|
break;
|
|
2554
2575
|
case "effectivePeriod.end":
|
|
2555
|
-
targetData["effectivePeriodEnd"] = column.text?.div ?? "";
|
|
2576
|
+
targetData["effectivePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2556
2577
|
break;
|
|
2557
2578
|
// valueQuantity
|
|
2558
2579
|
case "valueQuantity.value":
|
|
2559
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2580
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2560
2581
|
targetData["valueType"] = "valueQuantity";
|
|
2561
2582
|
break;
|
|
2562
2583
|
case "valueQuantity.unit":
|
|
2563
|
-
targetData["unit"] = column.text?.div ?? "";
|
|
2584
|
+
targetData["unit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2564
2585
|
break;
|
|
2565
2586
|
// valueCodeableConcept
|
|
2566
2587
|
case "valueCodeableConcept.text":
|
|
2567
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2588
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2568
2589
|
targetData["valueType"] = "valueCodeableConcept";
|
|
2569
2590
|
break;
|
|
2570
2591
|
case "valueCodeableConcept.coding.display":
|
|
2571
2592
|
if (!targetData["value"]) {
|
|
2572
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2593
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2573
2594
|
targetData["valueType"] = "valueCodeableConcept";
|
|
2574
2595
|
}
|
|
2575
2596
|
break;
|
|
2576
2597
|
// valueString
|
|
2577
2598
|
case "valueString":
|
|
2578
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2599
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2579
2600
|
targetData["valueType"] = "valueString";
|
|
2580
2601
|
break;
|
|
2581
2602
|
// valueBoolean
|
|
2582
2603
|
case "valueBoolean":
|
|
2583
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2604
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2584
2605
|
targetData["valueType"] = "valueBoolean";
|
|
2585
2606
|
break;
|
|
2586
2607
|
// valueInteger
|
|
2587
2608
|
case "valueInteger":
|
|
2588
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2609
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2589
2610
|
targetData["valueType"] = "valueInteger";
|
|
2590
2611
|
break;
|
|
2591
2612
|
// valueDateTime
|
|
2592
2613
|
case "valueDateTime":
|
|
2593
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2614
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2594
2615
|
targetData["valueType"] = "valueDateTime";
|
|
2595
2616
|
break;
|
|
2596
2617
|
// valuePeriod
|
|
2597
2618
|
case "valuePeriod.start":
|
|
2598
|
-
targetData["valuePeriodStart"] = column.text?.div ?? "";
|
|
2619
|
+
targetData["valuePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2599
2620
|
targetData["valueType"] = "valuePeriod";
|
|
2600
2621
|
break;
|
|
2601
2622
|
case "valuePeriod.end":
|
|
2602
|
-
targetData["valuePeriodEnd"] = column.text?.div ?? "";
|
|
2623
|
+
targetData["valuePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2603
2624
|
targetData["valueType"] = "valuePeriod";
|
|
2604
2625
|
break;
|
|
2605
2626
|
// valueTime
|
|
2606
2627
|
case "valueTime":
|
|
2607
|
-
targetData["value"] = column.text?.div ?? "";
|
|
2628
|
+
targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2608
2629
|
targetData["valueType"] = "valueTime";
|
|
2609
2630
|
break;
|
|
2610
2631
|
// valueSampledData
|
|
2611
2632
|
case "valueSampledData.origin.value":
|
|
2612
|
-
targetData["sampledDataOriginValue"] = column.text?.div ?? "";
|
|
2633
|
+
targetData["sampledDataOriginValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2613
2634
|
targetData["valueType"] = "valueSampledData";
|
|
2614
2635
|
break;
|
|
2615
2636
|
case "valueSampledData.origin.unit":
|
|
2616
|
-
targetData["sampledDataOriginUnit"] = column.text?.div ?? "";
|
|
2637
|
+
targetData["sampledDataOriginUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2617
2638
|
break;
|
|
2618
2639
|
case "valueSampledData.period":
|
|
2619
|
-
targetData["sampledDataPeriod"] = column.text?.div ?? "";
|
|
2640
|
+
targetData["sampledDataPeriod"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2620
2641
|
break;
|
|
2621
2642
|
case "valueSampledData.factor":
|
|
2622
|
-
targetData["sampledDataFactor"] = column.text?.div ?? "";
|
|
2643
|
+
targetData["sampledDataFactor"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2623
2644
|
break;
|
|
2624
2645
|
case "valueSampledData.lowerLimit":
|
|
2625
|
-
targetData["sampledDataLowerLimit"] = column.text?.div ?? "";
|
|
2646
|
+
targetData["sampledDataLowerLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2626
2647
|
break;
|
|
2627
2648
|
case "valueSampledData.upperLimit":
|
|
2628
|
-
targetData["sampledDataUpperLimit"] = column.text?.div ?? "";
|
|
2649
|
+
targetData["sampledDataUpperLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2629
2650
|
break;
|
|
2630
2651
|
case "valueSampledData.data":
|
|
2631
|
-
targetData["sampledDataData"] = column.text?.div ?? "";
|
|
2652
|
+
targetData["sampledDataData"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2632
2653
|
break;
|
|
2633
2654
|
// valueRange
|
|
2634
2655
|
case "valueRange.low.value":
|
|
2635
|
-
targetData["valueRangeLowValue"] = column.text?.div ?? "";
|
|
2656
|
+
targetData["valueRangeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2636
2657
|
targetData["valueType"] = "valueRange";
|
|
2637
2658
|
break;
|
|
2638
2659
|
case "valueRange.low.unit":
|
|
2639
|
-
targetData["valueRangeLowUnit"] = column.text?.div ?? "";
|
|
2660
|
+
targetData["valueRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2640
2661
|
break;
|
|
2641
2662
|
case "valueRange.high.value":
|
|
2642
|
-
targetData["valueRangeHighValue"] = column.text?.div ?? "";
|
|
2663
|
+
targetData["valueRangeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2643
2664
|
break;
|
|
2644
2665
|
case "valueRange.high.unit":
|
|
2645
|
-
targetData["valueRangeHighUnit"] = column.text?.div ?? "";
|
|
2666
|
+
targetData["valueRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2646
2667
|
break;
|
|
2647
2668
|
// valueRatio
|
|
2648
2669
|
case "valueRatio.numerator.value":
|
|
2649
|
-
targetData["valueRatioNumeratorValue"] = column.text?.div ?? "";
|
|
2670
|
+
targetData["valueRatioNumeratorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2650
2671
|
targetData["valueType"] = "valueRatio";
|
|
2651
2672
|
break;
|
|
2652
2673
|
case "valueRatio.numerator.unit":
|
|
2653
|
-
targetData["valueRatioNumeratorUnit"] = column.text?.div ?? "";
|
|
2674
|
+
targetData["valueRatioNumeratorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2654
2675
|
break;
|
|
2655
2676
|
case "valueRatio.denominator.value":
|
|
2656
|
-
targetData["valueRatioDenominatorValue"] = column.text?.div ?? "";
|
|
2677
|
+
targetData["valueRatioDenominatorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2657
2678
|
break;
|
|
2658
2679
|
case "valueRatio.denominator.unit":
|
|
2659
|
-
targetData["valueRatioDenominatorUnit"] = column.text?.div ?? "";
|
|
2680
|
+
targetData["valueRatioDenominatorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2660
2681
|
break;
|
|
2661
2682
|
// referenceRange
|
|
2662
2683
|
case "referenceRange.low.value":
|
|
2663
|
-
targetData["referenceRangeLow"] = column.text?.div ?? "";
|
|
2684
|
+
targetData["referenceRangeLow"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2664
2685
|
break;
|
|
2665
2686
|
case "referenceRange.low.unit":
|
|
2666
|
-
targetData["referenceRangeLowUnit"] = column.text?.div ?? "";
|
|
2687
|
+
targetData["referenceRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2667
2688
|
break;
|
|
2668
2689
|
case "referenceRange.high.value":
|
|
2669
|
-
targetData["referenceRangeHigh"] = column.text?.div ?? "";
|
|
2690
|
+
targetData["referenceRangeHigh"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2670
2691
|
break;
|
|
2671
2692
|
case "referenceRange.high.unit":
|
|
2672
|
-
targetData["referenceRangeHighUnit"] = column.text?.div ?? "";
|
|
2693
|
+
targetData["referenceRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2673
2694
|
break;
|
|
2674
2695
|
case "referenceRange.age.low.value":
|
|
2675
|
-
targetData["referenceRangeAgeLowValue"] = column.text?.div ?? "";
|
|
2696
|
+
targetData["referenceRangeAgeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2676
2697
|
break;
|
|
2677
2698
|
case "referenceRange.age.low.unit":
|
|
2678
|
-
targetData["referenceRangeAgeLowUnit"] = column.text?.div ?? "";
|
|
2699
|
+
targetData["referenceRangeAgeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2679
2700
|
break;
|
|
2680
2701
|
case "referenceRange.age.high.value":
|
|
2681
|
-
targetData["referenceRangeAgeHighValue"] = column.text?.div ?? "";
|
|
2702
|
+
targetData["referenceRangeAgeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2682
2703
|
break;
|
|
2683
2704
|
case "referenceRange.age.high.unit":
|
|
2684
|
-
targetData["referenceRangeAgeHighUnit"] = column.text?.div ?? "";
|
|
2705
|
+
targetData["referenceRangeAgeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
|
|
2685
2706
|
break;
|
|
2686
2707
|
default:
|
|
2687
2708
|
break;
|
|
@@ -2734,28 +2755,28 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2734
2755
|
for (const componentSection of columnData.section) {
|
|
2735
2756
|
const componentData = {};
|
|
2736
2757
|
for (const nestedColumn of componentSection.section ?? []) {
|
|
2737
|
-
this.extractSummaryObservationFields(nestedColumn, componentData);
|
|
2758
|
+
this.extractSummaryObservationFields(nestedColumn, componentData, templateUtilities);
|
|
2738
2759
|
}
|
|
2739
2760
|
if (Object.keys(componentData).length > 0) {
|
|
2740
2761
|
components.push(componentData);
|
|
2741
2762
|
}
|
|
2742
2763
|
}
|
|
2743
2764
|
} else {
|
|
2744
|
-
this.extractSummaryObservationFields(columnData, data);
|
|
2765
|
+
this.extractSummaryObservationFields(columnData, data, templateUtilities);
|
|
2745
2766
|
}
|
|
2746
2767
|
} else if (resourceItem.title === "DiagnosticReportLab Summary Grouped by DiagnosticReport|Lab Code") {
|
|
2747
2768
|
switch (columnData.title) {
|
|
2748
2769
|
case "Diagnostic Report Name":
|
|
2749
|
-
data["report"] = columnData.text?.div ?? "";
|
|
2770
|
+
data["report"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2750
2771
|
break;
|
|
2751
2772
|
case "Performer":
|
|
2752
|
-
data["performer"] = columnData.text?.div ?? "";
|
|
2773
|
+
data["performer"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2753
2774
|
break;
|
|
2754
2775
|
case "Issued Date":
|
|
2755
|
-
data["issued"] = columnData.text?.div ?? "";
|
|
2776
|
+
data["issued"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2756
2777
|
break;
|
|
2757
2778
|
case "Status":
|
|
2758
|
-
data["status"] = columnData.text?.div ?? "";
|
|
2779
|
+
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2759
2780
|
break;
|
|
2760
2781
|
default:
|
|
2761
2782
|
break;
|
|
@@ -2780,8 +2801,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2780
2801
|
observationhtml += `
|
|
2781
2802
|
<tr>
|
|
2782
2803
|
<td>${componentCode}</td>
|
|
2783
|
-
<td>${component["formattedValue"] ?? "-"}</td>
|
|
2784
|
-
<td>${component["referenceRange"]?.trim() ?? "-"}</td>
|
|
2804
|
+
<td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? "-"}</td>
|
|
2805
|
+
<td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? "-"}</td>
|
|
2785
2806
|
<td>${date ?? "-"}</td>
|
|
2786
2807
|
</tr>`;
|
|
2787
2808
|
}
|
|
@@ -2794,8 +2815,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2794
2815
|
observationhtml += `
|
|
2795
2816
|
<tr>
|
|
2796
2817
|
<td>${data["code"] ?? "-"}</td>
|
|
2797
|
-
<td>${data["formattedValue"] ?? "-"}</td>
|
|
2798
|
-
<td>${data["referenceRange"]?.trim() ?? "-"}</td>
|
|
2818
|
+
<td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? "-"}</td>
|
|
2819
|
+
<td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? "-"}</td>
|
|
2799
2820
|
<td>${date ?? "-"}</td>
|
|
2800
2821
|
</tr>`;
|
|
2801
2822
|
}
|
|
@@ -2955,7 +2976,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2955
2976
|
<tbody>`;
|
|
2956
2977
|
const observationAdded = /* @__PURE__ */ new Set();
|
|
2957
2978
|
for (const obs of observations) {
|
|
2958
|
-
const obsCode = templateUtilities.codeableConcept(obs.code);
|
|
2979
|
+
const obsCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code));
|
|
2959
2980
|
if (!observationAdded.has(obsCode)) {
|
|
2960
2981
|
observationAdded.add(obsCode);
|
|
2961
2982
|
html += `
|
|
@@ -2994,7 +3015,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2994
3015
|
<tbody>`;
|
|
2995
3016
|
const diagnosticReportAdded = /* @__PURE__ */ new Set();
|
|
2996
3017
|
for (const report of reports) {
|
|
2997
|
-
const reportName = templateUtilities.codeableConcept(report.code);
|
|
3018
|
+
const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(report.code));
|
|
2998
3019
|
if (!diagnosticReportAdded.has(reportName)) {
|
|
2999
3020
|
diagnosticReportAdded.add(reportName);
|
|
3000
3021
|
let resultCount = "";
|
|
@@ -3108,7 +3129,7 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3108
3129
|
const proc = resourceItem;
|
|
3109
3130
|
html += `
|
|
3110
3131
|
<tr id="${templateUtilities.narrativeLinkId(proc)}">
|
|
3111
|
-
<td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
|
|
3132
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(proc.code, "display"))}</td>
|
|
3112
3133
|
<td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
|
|
3113
3134
|
<td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
|
|
3114
3135
|
</tr>`;
|
|
@@ -3160,7 +3181,7 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3160
3181
|
for (const obs of observations) {
|
|
3161
3182
|
html += `
|
|
3162
3183
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
3163
|
-
<td>${templateUtilities.codeableConcept(obs.code)}</td>
|
|
3184
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code))}</td>
|
|
3164
3185
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
3165
3186
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
3166
3187
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
@@ -3205,7 +3226,7 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3205
3226
|
<tbody>`;
|
|
3206
3227
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
3207
3228
|
for (const cond of resolvedConditions) {
|
|
3208
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
3229
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
3209
3230
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3210
3231
|
addedConditionCodes.add(conditionCode);
|
|
3211
3232
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -3291,7 +3312,7 @@ var PlanOfCareTemplate = class {
|
|
|
3291
3312
|
const data = {};
|
|
3292
3313
|
for (const columnData of rowData.section ?? []) {
|
|
3293
3314
|
if (columnData.title) {
|
|
3294
|
-
data[columnData.title] = columnData.text?.div ?? "";
|
|
3315
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3295
3316
|
}
|
|
3296
3317
|
}
|
|
3297
3318
|
if (data["status"] !== "active") {
|
|
@@ -3367,7 +3388,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3367
3388
|
<tbody>`;
|
|
3368
3389
|
const addedConditionCodes = /* @__PURE__ */ new Set();
|
|
3369
3390
|
for (const cond of activeConditions) {
|
|
3370
|
-
const conditionCode = templateUtilities.codeableConcept(cond.code);
|
|
3391
|
+
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
|
|
3371
3392
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3372
3393
|
addedConditionCodes.add(conditionCode);
|
|
3373
3394
|
html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
|
|
@@ -3412,7 +3433,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3412
3433
|
if (impression.finding && impression.finding.length > 0) {
|
|
3413
3434
|
findingsHtml = "<ul>";
|
|
3414
3435
|
for (const finding of impression.finding) {
|
|
3415
|
-
const findingText = finding.itemCodeableConcept ? templateUtilities.codeableConcept(finding.itemCodeableConcept) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
|
|
3436
|
+
const findingText = finding.itemCodeableConcept ? templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(finding.itemCodeableConcept)) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
|
|
3416
3437
|
const cause = finding.basis || "";
|
|
3417
3438
|
findingsHtml += `<li>${findingText}${cause ? ` - ${cause}` : ""}</li>`;
|
|
3418
3439
|
}
|
|
@@ -3473,9 +3494,9 @@ var PregnancyTemplate = class _PregnancyTemplate {
|
|
|
3473
3494
|
const obs = resource;
|
|
3474
3495
|
html += `
|
|
3475
3496
|
<tr id="${templateUtilities.narrativeLinkId(obs)}">
|
|
3476
|
-
<td>${templateUtilities.extractPregnancyStatus(obs)}</td>
|
|
3497
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.extractPregnancyStatus(obs))}</td>
|
|
3477
3498
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
3478
|
-
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
3499
|
+
<td>${obs.effectiveDateTime ? templateUtilities.renderTextAsHtml(templateUtilities.renderTime(obs.effectiveDateTime, timezone)) : obs.effectivePeriod ? templateUtilities.renderTextAsHtml(templateUtilities.renderPeriod(obs.effectivePeriod, timezone)) : ""}</td>
|
|
3479
3500
|
</tr>`;
|
|
3480
3501
|
}
|
|
3481
3502
|
html += `
|
|
@@ -3525,7 +3546,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
|
|
|
3525
3546
|
const consent = resourceItem;
|
|
3526
3547
|
html += `
|
|
3527
3548
|
<tr id="${templateUtilities.narrativeLinkId(consent)}">
|
|
3528
|
-
<td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
|
|
3549
|
+
<td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(consent.scope, "display"))}</td>
|
|
3529
3550
|
<td>${consent.status || ""}</td>
|
|
3530
3551
|
<td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
|
|
3531
3552
|
<td>${consent.dateTime || ""}</td>
|
|
@@ -3546,16 +3567,18 @@ var TypeScriptTemplateMapper = class {
|
|
|
3546
3567
|
* @param resources - FHIR resources
|
|
3547
3568
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3548
3569
|
* @param useSectionSummary - Whether to use the section summary for narrative generation
|
|
3570
|
+
* @param now - Optional current date to use for generating relative dates in the narrative
|
|
3549
3571
|
* @returns HTML string for rendering
|
|
3550
3572
|
*/
|
|
3551
|
-
static generateNarrative(section, resources, timezone, useSectionSummary = false) {
|
|
3573
|
+
static generateNarrative(section, resources, timezone, useSectionSummary = false, now) {
|
|
3552
3574
|
const templateClass = this.sectionToTemplate[section];
|
|
3553
3575
|
if (!templateClass) {
|
|
3554
3576
|
throw new Error(`No template found for section: ${section}`);
|
|
3555
3577
|
}
|
|
3556
3578
|
return useSectionSummary ? templateClass.generateSummaryNarrative(
|
|
3557
3579
|
resources,
|
|
3558
|
-
timezone
|
|
3580
|
+
timezone,
|
|
3581
|
+
now
|
|
3559
3582
|
) : templateClass.generateNarrative(resources, timezone);
|
|
3560
3583
|
}
|
|
3561
3584
|
};
|
|
@@ -3613,14 +3636,15 @@ var NarrativeGenerator = class {
|
|
|
3613
3636
|
* @param resources - Array of domain resources
|
|
3614
3637
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3615
3638
|
* @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
|
|
3639
|
+
* @param now - Optional date parameter
|
|
3616
3640
|
* @returns Generated HTML content or undefined if no resources
|
|
3617
3641
|
*/
|
|
3618
|
-
static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false) {
|
|
3642
|
+
static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false, now) {
|
|
3619
3643
|
if (!resources || resources.length === 0) {
|
|
3620
3644
|
return void 0;
|
|
3621
3645
|
}
|
|
3622
3646
|
try {
|
|
3623
|
-
const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary);
|
|
3647
|
+
const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary, now);
|
|
3624
3648
|
if (!content) {
|
|
3625
3649
|
return void 0;
|
|
3626
3650
|
}
|
|
@@ -3642,8 +3666,8 @@ var NarrativeGenerator = class {
|
|
|
3642
3666
|
const options = aggressive ? AGGRESSIVE_MINIFY_OPTIONS : DEFAULT_MINIFY_OPTIONS;
|
|
3643
3667
|
return await (0, import_html_minifier_terser.minify)(html, options);
|
|
3644
3668
|
} catch (error) {
|
|
3645
|
-
console.warn("HTML minification failed", error);
|
|
3646
|
-
return
|
|
3669
|
+
console.warn("HTML minification failed", error, html);
|
|
3670
|
+
return `${error instanceof Error ? error.message : String(error)}`;
|
|
3647
3671
|
}
|
|
3648
3672
|
}
|
|
3649
3673
|
/**
|
|
@@ -3672,10 +3696,11 @@ var NarrativeGenerator = class {
|
|
|
3672
3696
|
* @param timezone - Optional timezone to use for date formatting
|
|
3673
3697
|
* @param minify - Whether to minify the HTML content (default: true)
|
|
3674
3698
|
* @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
|
|
3699
|
+
* @param now - Optional date parameter
|
|
3675
3700
|
* @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
|
|
3676
3701
|
*/
|
|
3677
|
-
static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false) {
|
|
3678
|
-
const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary);
|
|
3702
|
+
static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false, now) {
|
|
3703
|
+
const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary, now);
|
|
3679
3704
|
if (!content) {
|
|
3680
3705
|
return void 0;
|
|
3681
3706
|
}
|
|
@@ -3833,6 +3858,12 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3833
3858
|
if (sectionType === "Patient" /* PATIENT */) {
|
|
3834
3859
|
continue;
|
|
3835
3860
|
}
|
|
3861
|
+
const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
|
|
3862
|
+
const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
|
|
3863
|
+
if (sectionIPSSummary.length > 0) {
|
|
3864
|
+
await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
|
|
3865
|
+
continue;
|
|
3866
|
+
}
|
|
3836
3867
|
const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
|
|
3837
3868
|
const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
|
|
3838
3869
|
if (sectionSummary.length > 0) {
|
|
@@ -3852,8 +3883,9 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3852
3883
|
* @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
|
|
3853
3884
|
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3854
3885
|
* @param patientId - Optional patient ID to use as primary patient for composition reference
|
|
3886
|
+
* @param now - Optional current date to use for composition date (defaults to new Date())
|
|
3855
3887
|
*/
|
|
3856
|
-
async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId) {
|
|
3888
|
+
async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId, now) {
|
|
3857
3889
|
if (baseUrl.endsWith("/")) {
|
|
3858
3890
|
baseUrl = baseUrl.slice(0, -1);
|
|
3859
3891
|
}
|
|
@@ -3880,20 +3912,22 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
3880
3912
|
// Assuming patient is also a practitioner for simplicity
|
|
3881
3913
|
display: authorOrganizationName
|
|
3882
3914
|
}],
|
|
3883
|
-
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3915
|
+
date: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
3884
3916
|
title: "International Patient Summary",
|
|
3885
3917
|
section: this.sections,
|
|
3886
3918
|
text: await NarrativeGenerator.generateNarrativeAsync(
|
|
3887
3919
|
"Patient" /* PATIENT */,
|
|
3888
3920
|
this.patients,
|
|
3889
3921
|
timezone,
|
|
3890
|
-
true
|
|
3922
|
+
true,
|
|
3923
|
+
false,
|
|
3924
|
+
now
|
|
3891
3925
|
)
|
|
3892
3926
|
};
|
|
3893
3927
|
const bundle = {
|
|
3894
3928
|
resourceType: "Bundle",
|
|
3895
3929
|
type: "document",
|
|
3896
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3930
|
+
timestamp: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
3897
3931
|
identifier: {
|
|
3898
3932
|
"system": "urn:ietf:rfc:3986",
|
|
3899
3933
|
"value": "urn:uuid:4dcfd353-49fd-4ab0-b521-c8d57ced74d6"
|