@imranq2/fhirpatientsummary 1.0.8 → 1.0.10

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 CHANGED
@@ -949,7 +949,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
949
949
  }
950
950
  }
951
951
  }
952
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">`;
952
+ let html = "";
953
953
  html += `
954
954
  <div class="ActiveAllergies">
955
955
  <h3>Active Allergies and Intolerances</h3>
@@ -1006,8 +1006,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1006
1006
  html += `
1007
1007
  </tbody>
1008
1008
  </table>
1009
- </div>
1010
- </div>`;
1009
+ </div>`;
1011
1010
  return html;
1012
1011
  }
1013
1012
  /**
@@ -1117,7 +1116,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1117
1116
  * @returns HTML string for rendering
1118
1117
  */
1119
1118
  static renderMedicationRequests(templateUtilities, medications) {
1120
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">
1119
+ let html = `
1121
1120
  <table>
1122
1121
  <thead>
1123
1122
  <tr>
@@ -1167,7 +1166,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1167
1166
  }
1168
1167
  html += `
1169
1168
  </tbody>
1170
- </table></div>`;
1169
+ </table>`;
1171
1170
  return html;
1172
1171
  }
1173
1172
  /**
@@ -1177,7 +1176,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1177
1176
  * @returns HTML string for rendering
1178
1177
  */
1179
1178
  static renderMedicationStatements(templateUtilities, medications) {
1180
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">
1179
+ let html = `
1181
1180
  <table>
1182
1181
  <thead>
1183
1182
  <tr>
@@ -1221,7 +1220,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1221
1220
  }
1222
1221
  html += `
1223
1222
  </tbody>
1224
- </table></div>`;
1223
+ </table>`;
1225
1224
  return html;
1226
1225
  }
1227
1226
  };
@@ -1247,7 +1246,7 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
1247
1246
  const templateUtilities = new TemplateUtilities(resource);
1248
1247
  let html = `
1249
1248
  <h5>Immunizations</h5>
1250
- <table class="hapiPropertyTable">
1249
+ <table>
1251
1250
  <thead>
1252
1251
  <tr>
1253
1252
  <th>Immunization</th>
@@ -1303,7 +1302,7 @@ var ProblemListTemplate = class _ProblemListTemplate {
1303
1302
  */
1304
1303
  static generateStaticNarrative(resource, timezone) {
1305
1304
  const templateUtilities = new TemplateUtilities(resource);
1306
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">`;
1305
+ let html = ``;
1307
1306
  const activeConditions = [];
1308
1307
  const resolvedConditions = [];
1309
1308
  if (resource.entry && Array.isArray(resource.entry)) {
@@ -1379,7 +1378,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
1379
1378
  </table>
1380
1379
  </div>`;
1381
1380
  }
1382
- html += `</div>`;
1383
1381
  return html;
1384
1382
  }
1385
1383
  };
@@ -1405,7 +1403,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
1405
1403
  const templateUtilities = new TemplateUtilities(resource);
1406
1404
  let html = `
1407
1405
  <h5>Vital Signs</h5>
1408
- <table class="hapiPropertyTable">
1406
+ <table>
1409
1407
  <thead>
1410
1408
  <tr>
1411
1409
  <th>Code</th>
@@ -1464,7 +1462,7 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1464
1462
  const templateUtilities = new TemplateUtilities(resource);
1465
1463
  let html = `
1466
1464
  <h5>Medical Devices</h5>
1467
- <table class="hapiPropertyTable">
1465
+ <table>
1468
1466
  <thead>
1469
1467
  <tr>
1470
1468
  <th>Device</th>
@@ -1557,7 +1555,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1557
1555
  static renderObservations(templateUtilities, observations, timezone) {
1558
1556
  let html = `
1559
1557
  <h5>Diagnostic Results: Observations</h5>
1560
- <table class="hapiPropertyTable">
1558
+ <table>
1561
1559
  <thead>
1562
1560
  <tr>
1563
1561
  <th>Code</th>
@@ -1597,7 +1595,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1597
1595
  static renderDiagnosticReports(templateUtilities, reports, timezone) {
1598
1596
  let html = `
1599
1597
  <h5>Diagnostic Results: Reports</h5>
1600
- <table class="hapiPropertyTable">
1598
+ <table>
1601
1599
  <thead>
1602
1600
  <tr>
1603
1601
  <th>Report</th>
@@ -1650,7 +1648,7 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1650
1648
  const templateUtilities = new TemplateUtilities(resource);
1651
1649
  let html = `
1652
1650
  <h5>History Of Procedures</h5>
1653
- <table class="hapiPropertyTable">
1651
+ <table>
1654
1652
  <thead>
1655
1653
  <tr>
1656
1654
  <th>Procedure</th>
@@ -1701,7 +1699,7 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
1701
1699
  const templateUtilities = new TemplateUtilities(resource);
1702
1700
  let html = `
1703
1701
  <h5>Social History</h5>
1704
- <table class="hapiPropertyTable">
1702
+ <table>
1705
1703
  <thead>
1706
1704
  <tr>
1707
1705
  <th>Code</th>
@@ -1747,7 +1745,7 @@ var PastHistoryOfIllnessTemplate = class {
1747
1745
  const templateUtilities = new TemplateUtilities(resource);
1748
1746
  let html = `
1749
1747
  <h5>Past History of Illnesses</h5>
1750
- <table class="hapiPropertyTable">
1748
+ <table>
1751
1749
  <thead>
1752
1750
  <tr>
1753
1751
  <th>Medical Problems</th>
@@ -1792,7 +1790,7 @@ var PlanOfCareTemplate = class {
1792
1790
  const templateUtilities = new TemplateUtilities(resource);
1793
1791
  let html = `
1794
1792
  <h5>Plan of Care</h5>
1795
- <table class="hapiPropertyTable">
1793
+ <table>
1796
1794
  <thead>
1797
1795
  <tr>
1798
1796
  <th>Activity</th>
@@ -1847,7 +1845,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
1847
1845
  const templateUtilities = new TemplateUtilities(resource);
1848
1846
  let html = `
1849
1847
  <h5>Functional Status</h5>
1850
- <table class="hapiPropertyTable">
1848
+ <table>
1851
1849
  <thead>
1852
1850
  <tr>
1853
1851
  <th>Assessment</th>
@@ -1902,7 +1900,7 @@ var PregnancyTemplate = class _PregnancyTemplate {
1902
1900
  const templateUtilities = new TemplateUtilities(resource);
1903
1901
  let html = `
1904
1902
  <h5>Pregnancy</h5>
1905
- <table class="hapiPropertyTable">
1903
+ <table>
1906
1904
  <thead>
1907
1905
  <tr>
1908
1906
  <th>Code</th>
@@ -1956,7 +1954,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
1956
1954
  const templateUtilities = new TemplateUtilities(resource);
1957
1955
  let html = `
1958
1956
  <h5>Advance Directives</h5>
1959
- <table class="hapiPropertyTable">
1957
+ <table>
1960
1958
  <thead>
1961
1959
  <tr>
1962
1960
  <th>Scope</th>
@@ -2000,7 +1998,7 @@ var FamilyHistoryTemplate = class {
2000
1998
  const templateUtilities = new TemplateUtilities(resource);
2001
1999
  let html = `
2002
2000
  <h5>Family History</h5>
2003
- <table class="hapiPropertyTable">
2001
+ <table>
2004
2002
  <thead>
2005
2003
  <tr>
2006
2004
  <th>Relationship</th>
@@ -2081,7 +2079,7 @@ var ClinicalImpressionTemplate = class {
2081
2079
  const templateUtilities = new TemplateUtilities(resource);
2082
2080
  let html = `
2083
2081
  <h5>Clinical Impressions</h5>
2084
- <table class="hapiPropertyTable">
2082
+ <table>
2085
2083
  <thead>
2086
2084
  <tr>
2087
2085
  <th>Date</th>
@@ -2193,15 +2191,42 @@ TypeScriptTemplateMapper.sectionToTemplate = {
2193
2191
  };
2194
2192
 
2195
2193
  // src/generators/narrative_generator.ts
2194
+ var import_html_minifier_terser = require("html-minifier-terser");
2195
+ var DEFAULT_MINIFY_OPTIONS = {
2196
+ collapseWhitespace: true,
2197
+ conservativeCollapse: true,
2198
+ // Preserves one whitespace
2199
+ removeComments: true,
2200
+ caseSensitive: true,
2201
+ // Important for XML/XHTML
2202
+ minifyCSS: true,
2203
+ minifyJS: false,
2204
+ decodeEntities: true,
2205
+ keepClosingSlash: true,
2206
+ // Important for XML/XHTML
2207
+ removeEmptyAttributes: true
2208
+ };
2209
+ var AGGRESSIVE_MINIFY_OPTIONS = {
2210
+ ...DEFAULT_MINIFY_OPTIONS,
2211
+ collapseWhitespace: true,
2212
+ conservativeCollapse: false,
2213
+ // Don't preserve whitespace
2214
+ removeAttributeQuotes: true,
2215
+ removeRedundantAttributes: true,
2216
+ removeEmptyElements: false,
2217
+ // Don't remove empty elements as they may be semantically important
2218
+ removeOptionalTags: true
2219
+ };
2196
2220
  var NarrativeGenerator = class {
2197
2221
  /**
2198
2222
  * Generates narrative HTML content for a section
2199
2223
  * @param section - IPS section type
2200
2224
  * @param resources - Array of domain resources
2201
2225
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2226
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
2202
2227
  * @returns Generated HTML content or undefined if no resources
2203
2228
  */
2204
- static generateNarrativeContent(section, resources, timezone) {
2229
+ static async generateNarrativeContentAsync(section, resources, timezone, wrapInXhtml = true) {
2205
2230
  if (!resources || resources.length === 0) {
2206
2231
  return void 0;
2207
2232
  }
@@ -2213,48 +2238,81 @@ var NarrativeGenerator = class {
2213
2238
  resource
2214
2239
  }))
2215
2240
  };
2216
- return TypeScriptTemplateMapper.generateNarrative(section, bundle, timezone);
2241
+ const content = TypeScriptTemplateMapper.generateNarrative(section, bundle, timezone);
2242
+ if (!content) {
2243
+ return void 0;
2244
+ }
2245
+ if (wrapInXhtml) {
2246
+ return await this.wrapInXhtmlAsync(content);
2247
+ } else {
2248
+ return await this.minifyHtmlAsync(content);
2249
+ }
2217
2250
  } catch (error) {
2218
2251
  console.error(`Error generating narrative for section ${section}:`, error);
2219
2252
  return `<div class="error">Error generating narrative: ${error instanceof Error ? error.message : String(error)}</div>`;
2220
2253
  }
2221
2254
  }
2222
2255
  /**
2223
- * Creates a complete FHIR Narrative object
2256
+ * Minifies HTML content asynchronously using html-minifier-terser
2257
+ * @param html - HTML content to minify
2258
+ * @param aggressive - Whether to use more aggressive minification
2259
+ * @returns Promise that resolves to minified HTML content
2260
+ */
2261
+ static async minifyHtmlAsync(html, aggressive = false) {
2262
+ if (!html) return html;
2263
+ try {
2264
+ const options = aggressive ? AGGRESSIVE_MINIFY_OPTIONS : DEFAULT_MINIFY_OPTIONS;
2265
+ return await (0, import_html_minifier_terser.minify)(html, options);
2266
+ } catch (error) {
2267
+ console.warn("HTML minification failed", error);
2268
+ return html;
2269
+ }
2270
+ }
2271
+ /**
2272
+ * Creates a complete FHIR Narrative object asynchronously
2224
2273
  * @param content - HTML content
2225
- * @returns FHIR Narrative object
2274
+ * @param minify - Whether to minify the HTML content (default: true)
2275
+ * @returns Promise that resolves to a FHIR Narrative object
2226
2276
  */
2227
- static createNarrative(content) {
2228
- content = content.replace(/\s+/g, " ").trim();
2277
+ static async createNarrativeAsync(content, minify = true) {
2229
2278
  const divMatch = content.match(/^<div[^>]*>(.*?)<\/div>$/);
2230
2279
  if (divMatch) {
2231
2280
  content = divMatch[1];
2232
2281
  }
2282
+ if (minify) {
2283
+ content = await this.minifyHtmlAsync(content);
2284
+ }
2233
2285
  return {
2234
2286
  status: "generated",
2235
2287
  div: `<div xmlns="http://www.w3.org/1999/xhtml">${content}</div>`
2236
2288
  };
2237
2289
  }
2238
2290
  /**
2239
- * Generates a complete FHIR Narrative object for a section
2291
+ * Generates a complete FHIR Narrative object for a section asynchronously
2240
2292
  * @param section - IPS section type
2241
2293
  * @param resources - Array of domain resources
2242
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2243
- * @returns FHIR Narrative object or undefined if no resources
2294
+ * @param timezone - Optional timezone to use for date formatting
2295
+ * @param minify - Whether to minify the HTML content (default: true)
2296
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
2297
+ * @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
2244
2298
  */
2245
- static generateNarrative(section, resources, timezone) {
2246
- const content = this.generateNarrativeContent(section, resources, timezone);
2299
+ static async generateNarrativeAsync(section, resources, timezone, minify = true, wrapInXhtml) {
2300
+ const content = await this.generateNarrativeContentAsync(section, resources, timezone, wrapInXhtml);
2247
2301
  if (!content) {
2248
2302
  return void 0;
2249
2303
  }
2250
- return this.createNarrative(content);
2304
+ return await this.createNarrativeAsync(content, minify);
2251
2305
  }
2252
2306
  /**
2253
- * Wrap content in XHTML div with FHIR namespace
2307
+ * Wrap content in XHTML div with FHIR namespace asynchronously
2254
2308
  * @param content - HTML content to wrap
2255
- * @returns XHTML div string
2309
+ * @param minify - Whether to minify the HTML content before wrapping (default: false)
2310
+ * @returns Promise that resolves to XHTML div string
2256
2311
  */
2257
- static wrapInXhtml(content) {
2312
+ static async wrapInXhtmlAsync(content, minify = false) {
2313
+ if (minify) {
2314
+ content = await this.minifyHtmlAsync(content);
2315
+ }
2258
2316
  return `<div xmlns="http://www.w3.org/1999/xhtml">${content}</div>`;
2259
2317
  }
2260
2318
  };
@@ -2278,8 +2336,14 @@ var ComprehensiveIPSCompositionBuilder = class {
2278
2336
  this.patient = patient;
2279
2337
  return this;
2280
2338
  }
2281
- // Comprehensive method to add sections with validation
2282
- addSection(sectionType, resources, timezone, options) {
2339
+ /**
2340
+ * Adds a section to the composition with async HTML minification
2341
+ * @param sectionType - IPS section type
2342
+ * @param resources - Array of domain resources
2343
+ * @param timezone - Optional timezone to use for date formatting
2344
+ * @param options - Optional configuration options
2345
+ */
2346
+ async addSectionAsync(sectionType, resources, timezone, options) {
2283
2347
  const validResources = resources;
2284
2348
  for (const resource of validResources) {
2285
2349
  this.resources.add(resource);
@@ -2291,7 +2355,13 @@ var ComprehensiveIPSCompositionBuilder = class {
2291
2355
  return this;
2292
2356
  }
2293
2357
  if (sectionType !== "Patient" /* PATIENT */) {
2294
- const narrative = NarrativeGenerator.generateNarrative(sectionType, validResources, timezone);
2358
+ const narrative = await NarrativeGenerator.generateNarrativeAsync(
2359
+ sectionType,
2360
+ validResources,
2361
+ timezone,
2362
+ true,
2363
+ false
2364
+ );
2295
2365
  const sectionEntry = {
2296
2366
  title: IPS_SECTION_DISPLAY_NAMES[sectionType] || sectionType,
2297
2367
  code: {
@@ -2318,9 +2388,9 @@ var ComprehensiveIPSCompositionBuilder = class {
2318
2388
  /**
2319
2389
  * Reads a FHIR Bundle and extracts resources for each section defined in IPSSections.
2320
2390
  * @param bundle - FHIR Bundle containing resources
2321
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2391
+ * @param timezone - Optional timezone to use for date formatting
2322
2392
  */
2323
- read_bundle(bundle, timezone) {
2393
+ async readBundleAsync(bundle, timezone) {
2324
2394
  if (!bundle.entry) {
2325
2395
  return this;
2326
2396
  }
@@ -2337,7 +2407,9 @@ var ComprehensiveIPSCompositionBuilder = class {
2337
2407
  resources = resources.filter(customFilter);
2338
2408
  }
2339
2409
  if (resources.length > 0) {
2340
- this.addSection(sectionType, resources, timezone, { isOptional: true });
2410
+ await this.addSectionAsync(sectionType, resources, timezone, {
2411
+ isOptional: true
2412
+ });
2341
2413
  }
2342
2414
  }
2343
2415
  return this;
@@ -2371,7 +2443,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2371
2443
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
2372
2444
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2373
2445
  */
2374
- build_bundle(authorOrganizationId, authorOrganizationName, baseUrl, timezone) {
2446
+ async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone) {
2375
2447
  if (baseUrl.endsWith("/")) {
2376
2448
  baseUrl = baseUrl.slice(0, -1);
2377
2449
  }
@@ -2400,7 +2472,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2400
2472
  date: (/* @__PURE__ */ new Date()).toISOString(),
2401
2473
  title: "International Patient Summary",
2402
2474
  section: this.sections,
2403
- text: this.createCompositionNarrative(timezone)
2475
+ text: await this.createCompositionNarrativeAsync(timezone)
2404
2476
  };
2405
2477
  const bundle = {
2406
2478
  resourceType: "Bundle",
@@ -2445,13 +2517,14 @@ var ComprehensiveIPSCompositionBuilder = class {
2445
2517
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2446
2518
  * @private
2447
2519
  */
2448
- createCompositionNarrative(timezone) {
2520
+ async createCompositionNarrativeAsync(timezone) {
2449
2521
  const patient = this.patient;
2450
2522
  let fullNarrativeContent = "";
2451
- const patientNarrative = NarrativeGenerator.generateNarrativeContent(
2523
+ const patientNarrative = await NarrativeGenerator.generateNarrativeContentAsync(
2452
2524
  "Patient" /* PATIENT */,
2453
2525
  [patient],
2454
- timezone
2526
+ timezone,
2527
+ false
2455
2528
  );
2456
2529
  fullNarrativeContent = fullNarrativeContent.concat(patientNarrative || "");
2457
2530
  for (const sectionType of Object.values(IPSSections)) {
@@ -2462,13 +2535,18 @@ var ComprehensiveIPSCompositionBuilder = class {
2462
2535
  const allResources = Array.from(this.resources);
2463
2536
  const resources = allResources.filter((r) => resourceTypesForSection.includes(r.resourceType));
2464
2537
  if (resources.length > 0) {
2465
- const sectionNarrative = NarrativeGenerator.generateNarrativeContent(sectionType, resources, timezone);
2538
+ const sectionNarrative = await NarrativeGenerator.generateNarrativeContentAsync(
2539
+ sectionType,
2540
+ resources,
2541
+ timezone,
2542
+ false
2543
+ );
2466
2544
  fullNarrativeContent = fullNarrativeContent.concat(sectionNarrative || "");
2467
2545
  }
2468
2546
  }
2469
2547
  return {
2470
2548
  status: "generated",
2471
- div: NarrativeGenerator.wrapInXhtml(fullNarrativeContent)
2549
+ div: await NarrativeGenerator.wrapInXhtmlAsync(fullNarrativeContent, true)
2472
2550
  };
2473
2551
  }
2474
2552
  };
package/dist/index.d.cts CHANGED
@@ -643,16 +643,23 @@ declare class ComprehensiveIPSCompositionBuilder {
643
643
  * @param patient - FHIR Patient resource to set
644
644
  */
645
645
  setPatient(patient: TPatient): this;
646
- addSection<T extends TDomainResource>(sectionType: IPSSections, resources: T[], timezone: string | undefined, options?: {
646
+ /**
647
+ * Adds a section to the composition with async HTML minification
648
+ * @param sectionType - IPS section type
649
+ * @param resources - Array of domain resources
650
+ * @param timezone - Optional timezone to use for date formatting
651
+ * @param options - Optional configuration options
652
+ */
653
+ addSectionAsync<T extends TDomainResource>(sectionType: IPSSections, resources: T[], timezone: string | undefined, options?: {
647
654
  isOptional?: boolean;
648
655
  customLoincCode?: string;
649
- }): this;
656
+ }): Promise<this>;
650
657
  /**
651
658
  * Reads a FHIR Bundle and extracts resources for each section defined in IPSSections.
652
659
  * @param bundle - FHIR Bundle containing resources
653
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
660
+ * @param timezone - Optional timezone to use for date formatting
654
661
  */
655
- read_bundle(bundle: TBundle, timezone: string | undefined): this;
662
+ readBundleAsync(bundle: TBundle, timezone: string | undefined): Promise<this>;
656
663
  /**
657
664
  * Builds the final Composition sections, ensuring all mandatory sections are present.
658
665
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
@@ -665,13 +672,13 @@ declare class ComprehensiveIPSCompositionBuilder {
665
672
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
666
673
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
667
674
  */
668
- build_bundle(authorOrganizationId: string, authorOrganizationName: string, baseUrl: string, timezone: string | undefined): TBundle;
675
+ buildBundleAsync(authorOrganizationId: string, authorOrganizationName: string, baseUrl: string, timezone: string | undefined): Promise<TBundle>;
669
676
  /**
670
677
  * Creates a narrative for the composition based on the patient and sections.
671
678
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
672
679
  * @private
673
680
  */
674
- private createCompositionNarrative;
681
+ private createCompositionNarrativeAsync;
675
682
  }
676
683
 
677
684
  interface Narrative {
@@ -688,29 +695,41 @@ declare class NarrativeGenerator {
688
695
  * @param section - IPS section type
689
696
  * @param resources - Array of domain resources
690
697
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
698
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
691
699
  * @returns Generated HTML content or undefined if no resources
692
700
  */
693
- static generateNarrativeContent<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined): string | undefined;
701
+ static generateNarrativeContentAsync<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined, wrapInXhtml?: boolean): Promise<string | undefined>;
694
702
  /**
695
- * Creates a complete FHIR Narrative object
703
+ * Minifies HTML content asynchronously using html-minifier-terser
704
+ * @param html - HTML content to minify
705
+ * @param aggressive - Whether to use more aggressive minification
706
+ * @returns Promise that resolves to minified HTML content
707
+ */
708
+ static minifyHtmlAsync(html: string, aggressive?: boolean): Promise<string>;
709
+ /**
710
+ * Creates a complete FHIR Narrative object asynchronously
696
711
  * @param content - HTML content
697
- * @returns FHIR Narrative object
712
+ * @param minify - Whether to minify the HTML content (default: true)
713
+ * @returns Promise that resolves to a FHIR Narrative object
698
714
  */
699
- static createNarrative(content: string): Narrative;
715
+ static createNarrativeAsync(content: string, minify?: boolean): Promise<Narrative>;
700
716
  /**
701
- * Generates a complete FHIR Narrative object for a section
717
+ * Generates a complete FHIR Narrative object for a section asynchronously
702
718
  * @param section - IPS section type
703
719
  * @param resources - Array of domain resources
704
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
705
- * @returns FHIR Narrative object or undefined if no resources
720
+ * @param timezone - Optional timezone to use for date formatting
721
+ * @param minify - Whether to minify the HTML content (default: true)
722
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
723
+ * @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
706
724
  */
707
- static generateNarrative<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined): Narrative | undefined;
725
+ static generateNarrativeAsync<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined, minify: boolean | undefined, wrapInXhtml: boolean): Promise<Narrative | undefined>;
708
726
  /**
709
- * Wrap content in XHTML div with FHIR namespace
727
+ * Wrap content in XHTML div with FHIR namespace asynchronously
710
728
  * @param content - HTML content to wrap
711
- * @returns XHTML div string
729
+ * @param minify - Whether to minify the HTML content before wrapping (default: false)
730
+ * @returns Promise that resolves to XHTML div string
712
731
  */
713
- static wrapInXhtml(content: string): string;
732
+ static wrapInXhtmlAsync(content: string, minify?: boolean): Promise<string>;
714
733
  }
715
734
 
716
735
  declare const myPackage: (taco?: string) => string;
package/dist/index.d.ts CHANGED
@@ -643,16 +643,23 @@ declare class ComprehensiveIPSCompositionBuilder {
643
643
  * @param patient - FHIR Patient resource to set
644
644
  */
645
645
  setPatient(patient: TPatient): this;
646
- addSection<T extends TDomainResource>(sectionType: IPSSections, resources: T[], timezone: string | undefined, options?: {
646
+ /**
647
+ * Adds a section to the composition with async HTML minification
648
+ * @param sectionType - IPS section type
649
+ * @param resources - Array of domain resources
650
+ * @param timezone - Optional timezone to use for date formatting
651
+ * @param options - Optional configuration options
652
+ */
653
+ addSectionAsync<T extends TDomainResource>(sectionType: IPSSections, resources: T[], timezone: string | undefined, options?: {
647
654
  isOptional?: boolean;
648
655
  customLoincCode?: string;
649
- }): this;
656
+ }): Promise<this>;
650
657
  /**
651
658
  * Reads a FHIR Bundle and extracts resources for each section defined in IPSSections.
652
659
  * @param bundle - FHIR Bundle containing resources
653
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
660
+ * @param timezone - Optional timezone to use for date formatting
654
661
  */
655
- read_bundle(bundle: TBundle, timezone: string | undefined): this;
662
+ readBundleAsync(bundle: TBundle, timezone: string | undefined): Promise<this>;
656
663
  /**
657
664
  * Builds the final Composition sections, ensuring all mandatory sections are present.
658
665
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
@@ -665,13 +672,13 @@ declare class ComprehensiveIPSCompositionBuilder {
665
672
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
666
673
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
667
674
  */
668
- build_bundle(authorOrganizationId: string, authorOrganizationName: string, baseUrl: string, timezone: string | undefined): TBundle;
675
+ buildBundleAsync(authorOrganizationId: string, authorOrganizationName: string, baseUrl: string, timezone: string | undefined): Promise<TBundle>;
669
676
  /**
670
677
  * Creates a narrative for the composition based on the patient and sections.
671
678
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
672
679
  * @private
673
680
  */
674
- private createCompositionNarrative;
681
+ private createCompositionNarrativeAsync;
675
682
  }
676
683
 
677
684
  interface Narrative {
@@ -688,29 +695,41 @@ declare class NarrativeGenerator {
688
695
  * @param section - IPS section type
689
696
  * @param resources - Array of domain resources
690
697
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
698
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
691
699
  * @returns Generated HTML content or undefined if no resources
692
700
  */
693
- static generateNarrativeContent<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined): string | undefined;
701
+ static generateNarrativeContentAsync<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined, wrapInXhtml?: boolean): Promise<string | undefined>;
694
702
  /**
695
- * Creates a complete FHIR Narrative object
703
+ * Minifies HTML content asynchronously using html-minifier-terser
704
+ * @param html - HTML content to minify
705
+ * @param aggressive - Whether to use more aggressive minification
706
+ * @returns Promise that resolves to minified HTML content
707
+ */
708
+ static minifyHtmlAsync(html: string, aggressive?: boolean): Promise<string>;
709
+ /**
710
+ * Creates a complete FHIR Narrative object asynchronously
696
711
  * @param content - HTML content
697
- * @returns FHIR Narrative object
712
+ * @param minify - Whether to minify the HTML content (default: true)
713
+ * @returns Promise that resolves to a FHIR Narrative object
698
714
  */
699
- static createNarrative(content: string): Narrative;
715
+ static createNarrativeAsync(content: string, minify?: boolean): Promise<Narrative>;
700
716
  /**
701
- * Generates a complete FHIR Narrative object for a section
717
+ * Generates a complete FHIR Narrative object for a section asynchronously
702
718
  * @param section - IPS section type
703
719
  * @param resources - Array of domain resources
704
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
705
- * @returns FHIR Narrative object or undefined if no resources
720
+ * @param timezone - Optional timezone to use for date formatting
721
+ * @param minify - Whether to minify the HTML content (default: true)
722
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
723
+ * @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
706
724
  */
707
- static generateNarrative<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined): Narrative | undefined;
725
+ static generateNarrativeAsync<T extends TDomainResource>(section: IPSSections, resources: T[], timezone: string | undefined, minify: boolean | undefined, wrapInXhtml: boolean): Promise<Narrative | undefined>;
708
726
  /**
709
- * Wrap content in XHTML div with FHIR namespace
727
+ * Wrap content in XHTML div with FHIR namespace asynchronously
710
728
  * @param content - HTML content to wrap
711
- * @returns XHTML div string
729
+ * @param minify - Whether to minify the HTML content before wrapping (default: false)
730
+ * @returns Promise that resolves to XHTML div string
712
731
  */
713
- static wrapInXhtml(content: string): string;
732
+ static wrapInXhtmlAsync(content: string, minify?: boolean): Promise<string>;
714
733
  }
715
734
 
716
735
  declare const myPackage: (taco?: string) => string;
package/dist/index.js CHANGED
@@ -921,7 +921,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
921
921
  }
922
922
  }
923
923
  }
924
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">`;
924
+ let html = "";
925
925
  html += `
926
926
  <div class="ActiveAllergies">
927
927
  <h3>Active Allergies and Intolerances</h3>
@@ -978,8 +978,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
978
978
  html += `
979
979
  </tbody>
980
980
  </table>
981
- </div>
982
- </div>`;
981
+ </div>`;
983
982
  return html;
984
983
  }
985
984
  /**
@@ -1089,7 +1088,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1089
1088
  * @returns HTML string for rendering
1090
1089
  */
1091
1090
  static renderMedicationRequests(templateUtilities, medications) {
1092
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">
1091
+ let html = `
1093
1092
  <table>
1094
1093
  <thead>
1095
1094
  <tr>
@@ -1139,7 +1138,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1139
1138
  }
1140
1139
  html += `
1141
1140
  </tbody>
1142
- </table></div>`;
1141
+ </table>`;
1143
1142
  return html;
1144
1143
  }
1145
1144
  /**
@@ -1149,7 +1148,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1149
1148
  * @returns HTML string for rendering
1150
1149
  */
1151
1150
  static renderMedicationStatements(templateUtilities, medications) {
1152
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">
1151
+ let html = `
1153
1152
  <table>
1154
1153
  <thead>
1155
1154
  <tr>
@@ -1193,7 +1192,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1193
1192
  }
1194
1193
  html += `
1195
1194
  </tbody>
1196
- </table></div>`;
1195
+ </table>`;
1197
1196
  return html;
1198
1197
  }
1199
1198
  };
@@ -1219,7 +1218,7 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
1219
1218
  const templateUtilities = new TemplateUtilities(resource);
1220
1219
  let html = `
1221
1220
  <h5>Immunizations</h5>
1222
- <table class="hapiPropertyTable">
1221
+ <table>
1223
1222
  <thead>
1224
1223
  <tr>
1225
1224
  <th>Immunization</th>
@@ -1275,7 +1274,7 @@ var ProblemListTemplate = class _ProblemListTemplate {
1275
1274
  */
1276
1275
  static generateStaticNarrative(resource, timezone) {
1277
1276
  const templateUtilities = new TemplateUtilities(resource);
1278
- let html = `<div xmlns="http://www.w3.org/1999/xhtml">`;
1277
+ let html = ``;
1279
1278
  const activeConditions = [];
1280
1279
  const resolvedConditions = [];
1281
1280
  if (resource.entry && Array.isArray(resource.entry)) {
@@ -1351,7 +1350,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
1351
1350
  </table>
1352
1351
  </div>`;
1353
1352
  }
1354
- html += `</div>`;
1355
1353
  return html;
1356
1354
  }
1357
1355
  };
@@ -1377,7 +1375,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
1377
1375
  const templateUtilities = new TemplateUtilities(resource);
1378
1376
  let html = `
1379
1377
  <h5>Vital Signs</h5>
1380
- <table class="hapiPropertyTable">
1378
+ <table>
1381
1379
  <thead>
1382
1380
  <tr>
1383
1381
  <th>Code</th>
@@ -1436,7 +1434,7 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1436
1434
  const templateUtilities = new TemplateUtilities(resource);
1437
1435
  let html = `
1438
1436
  <h5>Medical Devices</h5>
1439
- <table class="hapiPropertyTable">
1437
+ <table>
1440
1438
  <thead>
1441
1439
  <tr>
1442
1440
  <th>Device</th>
@@ -1529,7 +1527,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1529
1527
  static renderObservations(templateUtilities, observations, timezone) {
1530
1528
  let html = `
1531
1529
  <h5>Diagnostic Results: Observations</h5>
1532
- <table class="hapiPropertyTable">
1530
+ <table>
1533
1531
  <thead>
1534
1532
  <tr>
1535
1533
  <th>Code</th>
@@ -1569,7 +1567,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1569
1567
  static renderDiagnosticReports(templateUtilities, reports, timezone) {
1570
1568
  let html = `
1571
1569
  <h5>Diagnostic Results: Reports</h5>
1572
- <table class="hapiPropertyTable">
1570
+ <table>
1573
1571
  <thead>
1574
1572
  <tr>
1575
1573
  <th>Report</th>
@@ -1622,7 +1620,7 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1622
1620
  const templateUtilities = new TemplateUtilities(resource);
1623
1621
  let html = `
1624
1622
  <h5>History Of Procedures</h5>
1625
- <table class="hapiPropertyTable">
1623
+ <table>
1626
1624
  <thead>
1627
1625
  <tr>
1628
1626
  <th>Procedure</th>
@@ -1673,7 +1671,7 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
1673
1671
  const templateUtilities = new TemplateUtilities(resource);
1674
1672
  let html = `
1675
1673
  <h5>Social History</h5>
1676
- <table class="hapiPropertyTable">
1674
+ <table>
1677
1675
  <thead>
1678
1676
  <tr>
1679
1677
  <th>Code</th>
@@ -1719,7 +1717,7 @@ var PastHistoryOfIllnessTemplate = class {
1719
1717
  const templateUtilities = new TemplateUtilities(resource);
1720
1718
  let html = `
1721
1719
  <h5>Past History of Illnesses</h5>
1722
- <table class="hapiPropertyTable">
1720
+ <table>
1723
1721
  <thead>
1724
1722
  <tr>
1725
1723
  <th>Medical Problems</th>
@@ -1764,7 +1762,7 @@ var PlanOfCareTemplate = class {
1764
1762
  const templateUtilities = new TemplateUtilities(resource);
1765
1763
  let html = `
1766
1764
  <h5>Plan of Care</h5>
1767
- <table class="hapiPropertyTable">
1765
+ <table>
1768
1766
  <thead>
1769
1767
  <tr>
1770
1768
  <th>Activity</th>
@@ -1819,7 +1817,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
1819
1817
  const templateUtilities = new TemplateUtilities(resource);
1820
1818
  let html = `
1821
1819
  <h5>Functional Status</h5>
1822
- <table class="hapiPropertyTable">
1820
+ <table>
1823
1821
  <thead>
1824
1822
  <tr>
1825
1823
  <th>Assessment</th>
@@ -1874,7 +1872,7 @@ var PregnancyTemplate = class _PregnancyTemplate {
1874
1872
  const templateUtilities = new TemplateUtilities(resource);
1875
1873
  let html = `
1876
1874
  <h5>Pregnancy</h5>
1877
- <table class="hapiPropertyTable">
1875
+ <table>
1878
1876
  <thead>
1879
1877
  <tr>
1880
1878
  <th>Code</th>
@@ -1928,7 +1926,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
1928
1926
  const templateUtilities = new TemplateUtilities(resource);
1929
1927
  let html = `
1930
1928
  <h5>Advance Directives</h5>
1931
- <table class="hapiPropertyTable">
1929
+ <table>
1932
1930
  <thead>
1933
1931
  <tr>
1934
1932
  <th>Scope</th>
@@ -1972,7 +1970,7 @@ var FamilyHistoryTemplate = class {
1972
1970
  const templateUtilities = new TemplateUtilities(resource);
1973
1971
  let html = `
1974
1972
  <h5>Family History</h5>
1975
- <table class="hapiPropertyTable">
1973
+ <table>
1976
1974
  <thead>
1977
1975
  <tr>
1978
1976
  <th>Relationship</th>
@@ -2053,7 +2051,7 @@ var ClinicalImpressionTemplate = class {
2053
2051
  const templateUtilities = new TemplateUtilities(resource);
2054
2052
  let html = `
2055
2053
  <h5>Clinical Impressions</h5>
2056
- <table class="hapiPropertyTable">
2054
+ <table>
2057
2055
  <thead>
2058
2056
  <tr>
2059
2057
  <th>Date</th>
@@ -2165,15 +2163,42 @@ TypeScriptTemplateMapper.sectionToTemplate = {
2165
2163
  };
2166
2164
 
2167
2165
  // src/generators/narrative_generator.ts
2166
+ import { minify as htmlMinify } from "html-minifier-terser";
2167
+ var DEFAULT_MINIFY_OPTIONS = {
2168
+ collapseWhitespace: true,
2169
+ conservativeCollapse: true,
2170
+ // Preserves one whitespace
2171
+ removeComments: true,
2172
+ caseSensitive: true,
2173
+ // Important for XML/XHTML
2174
+ minifyCSS: true,
2175
+ minifyJS: false,
2176
+ decodeEntities: true,
2177
+ keepClosingSlash: true,
2178
+ // Important for XML/XHTML
2179
+ removeEmptyAttributes: true
2180
+ };
2181
+ var AGGRESSIVE_MINIFY_OPTIONS = {
2182
+ ...DEFAULT_MINIFY_OPTIONS,
2183
+ collapseWhitespace: true,
2184
+ conservativeCollapse: false,
2185
+ // Don't preserve whitespace
2186
+ removeAttributeQuotes: true,
2187
+ removeRedundantAttributes: true,
2188
+ removeEmptyElements: false,
2189
+ // Don't remove empty elements as they may be semantically important
2190
+ removeOptionalTags: true
2191
+ };
2168
2192
  var NarrativeGenerator = class {
2169
2193
  /**
2170
2194
  * Generates narrative HTML content for a section
2171
2195
  * @param section - IPS section type
2172
2196
  * @param resources - Array of domain resources
2173
2197
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2198
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
2174
2199
  * @returns Generated HTML content or undefined if no resources
2175
2200
  */
2176
- static generateNarrativeContent(section, resources, timezone) {
2201
+ static async generateNarrativeContentAsync(section, resources, timezone, wrapInXhtml = true) {
2177
2202
  if (!resources || resources.length === 0) {
2178
2203
  return void 0;
2179
2204
  }
@@ -2185,48 +2210,81 @@ var NarrativeGenerator = class {
2185
2210
  resource
2186
2211
  }))
2187
2212
  };
2188
- return TypeScriptTemplateMapper.generateNarrative(section, bundle, timezone);
2213
+ const content = TypeScriptTemplateMapper.generateNarrative(section, bundle, timezone);
2214
+ if (!content) {
2215
+ return void 0;
2216
+ }
2217
+ if (wrapInXhtml) {
2218
+ return await this.wrapInXhtmlAsync(content);
2219
+ } else {
2220
+ return await this.minifyHtmlAsync(content);
2221
+ }
2189
2222
  } catch (error) {
2190
2223
  console.error(`Error generating narrative for section ${section}:`, error);
2191
2224
  return `<div class="error">Error generating narrative: ${error instanceof Error ? error.message : String(error)}</div>`;
2192
2225
  }
2193
2226
  }
2194
2227
  /**
2195
- * Creates a complete FHIR Narrative object
2228
+ * Minifies HTML content asynchronously using html-minifier-terser
2229
+ * @param html - HTML content to minify
2230
+ * @param aggressive - Whether to use more aggressive minification
2231
+ * @returns Promise that resolves to minified HTML content
2232
+ */
2233
+ static async minifyHtmlAsync(html, aggressive = false) {
2234
+ if (!html) return html;
2235
+ try {
2236
+ const options = aggressive ? AGGRESSIVE_MINIFY_OPTIONS : DEFAULT_MINIFY_OPTIONS;
2237
+ return await htmlMinify(html, options);
2238
+ } catch (error) {
2239
+ console.warn("HTML minification failed", error);
2240
+ return html;
2241
+ }
2242
+ }
2243
+ /**
2244
+ * Creates a complete FHIR Narrative object asynchronously
2196
2245
  * @param content - HTML content
2197
- * @returns FHIR Narrative object
2246
+ * @param minify - Whether to minify the HTML content (default: true)
2247
+ * @returns Promise that resolves to a FHIR Narrative object
2198
2248
  */
2199
- static createNarrative(content) {
2200
- content = content.replace(/\s+/g, " ").trim();
2249
+ static async createNarrativeAsync(content, minify = true) {
2201
2250
  const divMatch = content.match(/^<div[^>]*>(.*?)<\/div>$/);
2202
2251
  if (divMatch) {
2203
2252
  content = divMatch[1];
2204
2253
  }
2254
+ if (minify) {
2255
+ content = await this.minifyHtmlAsync(content);
2256
+ }
2205
2257
  return {
2206
2258
  status: "generated",
2207
2259
  div: `<div xmlns="http://www.w3.org/1999/xhtml">${content}</div>`
2208
2260
  };
2209
2261
  }
2210
2262
  /**
2211
- * Generates a complete FHIR Narrative object for a section
2263
+ * Generates a complete FHIR Narrative object for a section asynchronously
2212
2264
  * @param section - IPS section type
2213
2265
  * @param resources - Array of domain resources
2214
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2215
- * @returns FHIR Narrative object or undefined if no resources
2266
+ * @param timezone - Optional timezone to use for date formatting
2267
+ * @param minify - Whether to minify the HTML content (default: true)
2268
+ * @param wrapInXhtml - Whether to wrap the content in XHTML div
2269
+ * @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
2216
2270
  */
2217
- static generateNarrative(section, resources, timezone) {
2218
- const content = this.generateNarrativeContent(section, resources, timezone);
2271
+ static async generateNarrativeAsync(section, resources, timezone, minify = true, wrapInXhtml) {
2272
+ const content = await this.generateNarrativeContentAsync(section, resources, timezone, wrapInXhtml);
2219
2273
  if (!content) {
2220
2274
  return void 0;
2221
2275
  }
2222
- return this.createNarrative(content);
2276
+ return await this.createNarrativeAsync(content, minify);
2223
2277
  }
2224
2278
  /**
2225
- * Wrap content in XHTML div with FHIR namespace
2279
+ * Wrap content in XHTML div with FHIR namespace asynchronously
2226
2280
  * @param content - HTML content to wrap
2227
- * @returns XHTML div string
2281
+ * @param minify - Whether to minify the HTML content before wrapping (default: false)
2282
+ * @returns Promise that resolves to XHTML div string
2228
2283
  */
2229
- static wrapInXhtml(content) {
2284
+ static async wrapInXhtmlAsync(content, minify = false) {
2285
+ if (minify) {
2286
+ content = await this.minifyHtmlAsync(content);
2287
+ }
2230
2288
  return `<div xmlns="http://www.w3.org/1999/xhtml">${content}</div>`;
2231
2289
  }
2232
2290
  };
@@ -2250,8 +2308,14 @@ var ComprehensiveIPSCompositionBuilder = class {
2250
2308
  this.patient = patient;
2251
2309
  return this;
2252
2310
  }
2253
- // Comprehensive method to add sections with validation
2254
- addSection(sectionType, resources, timezone, options) {
2311
+ /**
2312
+ * Adds a section to the composition with async HTML minification
2313
+ * @param sectionType - IPS section type
2314
+ * @param resources - Array of domain resources
2315
+ * @param timezone - Optional timezone to use for date formatting
2316
+ * @param options - Optional configuration options
2317
+ */
2318
+ async addSectionAsync(sectionType, resources, timezone, options) {
2255
2319
  const validResources = resources;
2256
2320
  for (const resource of validResources) {
2257
2321
  this.resources.add(resource);
@@ -2263,7 +2327,13 @@ var ComprehensiveIPSCompositionBuilder = class {
2263
2327
  return this;
2264
2328
  }
2265
2329
  if (sectionType !== "Patient" /* PATIENT */) {
2266
- const narrative = NarrativeGenerator.generateNarrative(sectionType, validResources, timezone);
2330
+ const narrative = await NarrativeGenerator.generateNarrativeAsync(
2331
+ sectionType,
2332
+ validResources,
2333
+ timezone,
2334
+ true,
2335
+ false
2336
+ );
2267
2337
  const sectionEntry = {
2268
2338
  title: IPS_SECTION_DISPLAY_NAMES[sectionType] || sectionType,
2269
2339
  code: {
@@ -2290,9 +2360,9 @@ var ComprehensiveIPSCompositionBuilder = class {
2290
2360
  /**
2291
2361
  * Reads a FHIR Bundle and extracts resources for each section defined in IPSSections.
2292
2362
  * @param bundle - FHIR Bundle containing resources
2293
- * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2363
+ * @param timezone - Optional timezone to use for date formatting
2294
2364
  */
2295
- read_bundle(bundle, timezone) {
2365
+ async readBundleAsync(bundle, timezone) {
2296
2366
  if (!bundle.entry) {
2297
2367
  return this;
2298
2368
  }
@@ -2309,7 +2379,9 @@ var ComprehensiveIPSCompositionBuilder = class {
2309
2379
  resources = resources.filter(customFilter);
2310
2380
  }
2311
2381
  if (resources.length > 0) {
2312
- this.addSection(sectionType, resources, timezone, { isOptional: true });
2382
+ await this.addSectionAsync(sectionType, resources, timezone, {
2383
+ isOptional: true
2384
+ });
2313
2385
  }
2314
2386
  }
2315
2387
  return this;
@@ -2343,7 +2415,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2343
2415
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
2344
2416
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2345
2417
  */
2346
- build_bundle(authorOrganizationId, authorOrganizationName, baseUrl, timezone) {
2418
+ async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone) {
2347
2419
  if (baseUrl.endsWith("/")) {
2348
2420
  baseUrl = baseUrl.slice(0, -1);
2349
2421
  }
@@ -2372,7 +2444,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2372
2444
  date: (/* @__PURE__ */ new Date()).toISOString(),
2373
2445
  title: "International Patient Summary",
2374
2446
  section: this.sections,
2375
- text: this.createCompositionNarrative(timezone)
2447
+ text: await this.createCompositionNarrativeAsync(timezone)
2376
2448
  };
2377
2449
  const bundle = {
2378
2450
  resourceType: "Bundle",
@@ -2417,13 +2489,14 @@ var ComprehensiveIPSCompositionBuilder = class {
2417
2489
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2418
2490
  * @private
2419
2491
  */
2420
- createCompositionNarrative(timezone) {
2492
+ async createCompositionNarrativeAsync(timezone) {
2421
2493
  const patient = this.patient;
2422
2494
  let fullNarrativeContent = "";
2423
- const patientNarrative = NarrativeGenerator.generateNarrativeContent(
2495
+ const patientNarrative = await NarrativeGenerator.generateNarrativeContentAsync(
2424
2496
  "Patient" /* PATIENT */,
2425
2497
  [patient],
2426
- timezone
2498
+ timezone,
2499
+ false
2427
2500
  );
2428
2501
  fullNarrativeContent = fullNarrativeContent.concat(patientNarrative || "");
2429
2502
  for (const sectionType of Object.values(IPSSections)) {
@@ -2434,13 +2507,18 @@ var ComprehensiveIPSCompositionBuilder = class {
2434
2507
  const allResources = Array.from(this.resources);
2435
2508
  const resources = allResources.filter((r) => resourceTypesForSection.includes(r.resourceType));
2436
2509
  if (resources.length > 0) {
2437
- const sectionNarrative = NarrativeGenerator.generateNarrativeContent(sectionType, resources, timezone);
2510
+ const sectionNarrative = await NarrativeGenerator.generateNarrativeContentAsync(
2511
+ sectionType,
2512
+ resources,
2513
+ timezone,
2514
+ false
2515
+ );
2438
2516
  fullNarrativeContent = fullNarrativeContent.concat(sectionNarrative || "");
2439
2517
  }
2440
2518
  }
2441
2519
  return {
2442
2520
  status: "generated",
2443
- div: NarrativeGenerator.wrapInXhtml(fullNarrativeContent)
2521
+ div: await NarrativeGenerator.wrapInXhtmlAsync(fullNarrativeContent, true)
2444
2522
  };
2445
2523
  }
2446
2524
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imranq2/fhirpatientsummary",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "A template for creating npm packages using TypeScript and VSCode",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -34,9 +34,9 @@
34
34
  "test:watch": "jest --watch",
35
35
  "test": "jest --coverage",
36
36
  "typecheck": "tsc --noEmit",
37
- "check:cjs-import": "node test/build/cjs-import-check.cjs",
38
- "check:esm-import": "node --experimental-vm-modules test/build/esm-import-check.mjs",
39
- "check:ts-import": "ts-node --project tsconfig.json test/build/ts-import-check.ts"
37
+ "check:cjs-import": "node tests/build/cjs-import-check.cjs",
38
+ "check:esm-import": "node --experimental-vm-modules tests/build/esm-import-check.mjs",
39
+ "check:ts-import": "ts-node --project tsconfig.json tests/build/ts-import-check.ts"
40
40
  },
41
41
  "repository": {
42
42
  "type": "git",
@@ -67,11 +67,13 @@
67
67
  },
68
68
  "homepage": "https://github.com/icanbwell/fhir-patient-summary#readme",
69
69
  "dependencies": {
70
+ "html-minifier-terser": "^7.2.0",
70
71
  "luxon": "^3.6.1",
71
72
  "turndown": "^7.2.0"
72
73
  },
73
74
  "devDependencies": {
74
75
  "@eslint/js": "^9.29.0",
76
+ "@types/html-minifier-terser": "^7.0.2",
75
77
  "@types/jest": "^30.0.0",
76
78
  "@types/js-beautify": "^1.14.3",
77
79
  "@types/luxon": "^3.6.2",