@ohif/app 3.13.0-beta.112 → 3.13.0-beta.114

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.
Files changed (45) hide show
  1. package/dist/{100.bundle.1d81cd3f544858b4.js → 100.bundle.1906f9ae2b66fe58.js} +2 -2
  2. package/dist/{1180.bundle.97e5d7ddb822ada4.js → 1180.bundle.b85ba446cfbf82a9.js} +2 -2
  3. package/dist/{1206.bundle.79ed23079c78f18d.js → 1206.bundle.ecd5aaaca8466ba5.js} +2 -2
  4. package/dist/{1602.bundle.15b448aa8a33f8a3.js → 1602.bundle.58c538f4cfeafc04.js} +4 -4
  5. package/dist/{2779.bundle.d1c8eeb441bf6838.js → 2779.bundle.c50d9f70f57151a4.js} +2 -2
  6. package/dist/{3500.bundle.bff323e7296c7475.js → 3500.bundle.8820a8fab7c4144a.js} +3 -3
  7. package/dist/{3760.bundle.68517e3fbaba0870.js → 3760.bundle.1368166ffc784155.js} +4 -4
  8. package/dist/419.bundle.ba9f959dac4b65e6.js +655 -0
  9. package/dist/{4834.bundle.20712369635ca3b2.js → 4834.bundle.3f085ea647712366.js} +2 -2
  10. package/dist/{5189.bundle.86d3023e7ec28a8f.js → 5189.bundle.bf053e2e1c064914.js} +2 -2
  11. package/dist/{5448.bundle.8cda5b8e4baea275.js → 5448.bundle.1e50777e4c4e122a.js} +1 -1
  12. package/dist/{5696.bundle.a5a7fcaf46e722bd.js → 5696.bundle.d1858642ec96621b.js} +3 -3
  13. package/dist/{5708.bundle.8edb607ae04123db.js → 5708.bundle.07d7d136db71e3ab.js} +4 -4
  14. package/dist/{5910.bundle.c1199bd45e450735.js → 5910.bundle.5561806884c95754.js} +4 -4
  15. package/dist/{6001.bundle.db54385151503e3c.js → 6001.bundle.ab43bf3ef3da02d8.js} +4 -4
  16. package/dist/{7231.bundle.791409f68df0de05.js → 7231.bundle.32e096be83a5dece.js} +8 -6
  17. package/dist/{7248.bundle.b80f39a298a52d10.js → 7248.bundle.eeca01cd07f51f10.js} +5 -5
  18. package/dist/{7295.bundle.39a66efa759102bc.js → 7295.bundle.48faa19b4a5dea0d.js} +6 -6
  19. package/dist/{7463.bundle.afe57ad10829df20.js → 7463.bundle.40668aa8d083d077.js} +2 -2
  20. package/dist/{414.bundle.b80930f5525e536f.js → 7701.bundle.239da7c786e962d9.js} +665 -17
  21. package/dist/{8007.bundle.a3ae96f72b3cc798.js → 8007.bundle.a74956fc12c00f19.js} +18 -12
  22. package/dist/{8423.bundle.11056402679417e0.js → 8423.bundle.6b8ba4230cea3d67.js} +2 -2
  23. package/dist/{8832.bundle.96a209e4a82b6bf4.js → 8832.bundle.e859fea13db9f852.js} +3 -3
  24. package/dist/{899.bundle.6f855ae8df39327e.js → 899.bundle.221329ac8cec3022.js} +2 -2
  25. package/dist/{9068.bundle.29adebcfccb4bc8e.js → 9068.bundle.cd36fcb4e15a153e.js} +4 -4
  26. package/dist/{9116.bundle.72e18d59d3438606.js → 9116.bundle.212df93fa6c89fd5.js} +2 -2
  27. package/dist/{9415.bundle.fca81f7700036325.js → 9415.bundle.cec5bad019e1e0bf.js} +4 -4
  28. package/dist/{9437.bundle.645c37102d332184.js → 9437.bundle.c2beadb9d2b9501e.js} +2 -2
  29. package/dist/app-config.js +42 -251
  30. package/dist/{app.bundle.b346ed66e95b76d0.js → app.bundle.abf5c231a1b49748.js} +2470 -148
  31. package/dist/customizations/ctPresets.jsonc +21 -0
  32. package/dist/customizations/measurementLabels.jsonc +23 -0
  33. package/dist/customizations/patientBirthDate.jsonc +34 -0
  34. package/dist/customizations/smoothRotate.jsonc +42 -0
  35. package/dist/customizations/veterinary.jsonc +5 -0
  36. package/dist/customizations/veterinaryOverlay.jsonc +56 -0
  37. package/dist/index.html +1 -1
  38. package/dist/sw.js +2 -2
  39. package/package.json +5 -5
  40. package/dist/2666.bundle.e54d0f68887f43d2.js +0 -1271
  41. /package/dist/{379.bundle.75b0fb722268f037.js → 379.bundle.4b932c0de4372bc3.js} +0 -0
  42. /package/dist/{4556.bundle.29d68aff99e72e43.js → 4556.bundle.43fbd01f60119590.js} +0 -0
  43. /package/dist/{4683.bundle.0b47cae7de79e58c.js → 4683.bundle.42b75d856c409bef.js} +0 -0
  44. /package/dist/{6650.bundle.defab1d01ae0dcba.js → 6650.bundle.ac76eb90d6f8a353.js} +0 -0
  45. /package/dist/{9290.bundle.5a06e5f28e5dad94.js → 9290.bundle.e966b25e072adc22.js} +0 -0
@@ -86827,31 +86827,53 @@ Compose.propTypes = {
86827
86827
  components: (prop_types_default()).array,
86828
86828
  children: (prop_types_default()).node.isRequired
86829
86829
  };
86830
- // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
86831
- var core_src = __webpack_require__(62901);
86830
+ // EXTERNAL MODULE: ../../core/src/index.ts + 75 modules
86831
+ var core_src = __webpack_require__(50679);
86832
86832
  // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3682 modules
86833
86833
  var ui_next_src = __webpack_require__(39987);
86834
86834
  // EXTERNAL MODULE: ./state/index.js + 1 modules
86835
86835
  var state_0 = __webpack_require__(55461);
86836
86836
  ;// CONCATENATED MODULE: ./utils/preserveQueryParameters.ts
86837
- function preserve(query, current, key) {
86838
- const value = current.get(key);
86839
- if (value) {
86840
- query.append(key, value);
86837
+ /**
86838
+ * Keys preserved when navigating between worklist and viewer modes.
86839
+ * Each key may repeat in the URL; a single occurrence is preserved as a string and
86840
+ * multiple occurrences as an array (see preserveQueryStrings).
86841
+ */
86842
+ const PRESERVE_CUSTOMIZATION_KEYS_KEY = 'ohif.preserveCustomizationKeys';
86843
+ const preserveKeys = ['configUrl', 'multimonitor', 'screenNumber', 'hangingProtocolId', 'customization'];
86844
+ function preserveKey(query, current, key) {
86845
+ const values = current.getAll(key);
86846
+ for (const value of values) {
86847
+ if (value) {
86848
+ query.append(key, value);
86849
+ }
86841
86850
  }
86842
86851
  }
86843
- const preserveKeys = ['configUrl', 'multimonitor', 'screenNumber', 'hangingProtocolId'];
86844
- function preserveQueryParameters(query, current = new URLSearchParams(window.location.search)) {
86845
- for (const key of preserveKeys) {
86846
- preserve(query, current, key);
86852
+ function getPreserveKeys(customizationService) {
86853
+ const customKeys = customizationService?.getValue?.(PRESERVE_CUSTOMIZATION_KEYS_KEY, []) || [];
86854
+ if (!customKeys?.length) {
86855
+ return preserveKeys;
86847
86856
  }
86857
+ return [...preserveKeys, ...customKeys];
86848
86858
  }
86849
- function preserveQueryStrings(query, current = new URLSearchParams(window.location.search)) {
86850
- for (const key of preserveKeys) {
86851
- const value = current.get(key);
86852
- if (value) {
86853
- query[key] = value;
86859
+ function preserveQueryParameters(query, customizationService, current = new URLSearchParams(window.location.search)) {
86860
+ for (const key of getPreserveKeys(customizationService)) {
86861
+ preserveKey(query, current, key);
86862
+ }
86863
+ }
86864
+ function preserveQueryStrings(query, customizationService, current = new URLSearchParams(window.location.search)) {
86865
+ for (const key of getPreserveKeys(customizationService)) {
86866
+ const values = current.getAll(key).filter(Boolean);
86867
+ if (!values.length) {
86868
+ continue;
86854
86869
  }
86870
+ // A single value is stored as a plain string and repeated values as an array.
86871
+ // The worklist stringifier (query-string) serializes both correctly with its
86872
+ // default arrayFormat: a string becomes `key=value` and an array becomes
86873
+ // duplicated `key=a&key=b` keys — no arrayFormat option required by callers.
86874
+ // Keeping single values as strings also keeps them safe under stricter
86875
+ // serializers (e.g. the `qs` library, whose default would index arrays).
86876
+ query[key] = values.length === 1 ? values[0] : values;
86855
86877
  }
86856
86878
  }
86857
86879
  ;// CONCATENATED MODULE: ./hooks/useDebounce.js
@@ -87131,6 +87153,8 @@ function parseFiltersFromURL(params) {
87131
87153
  * Build URL query string from study list state preserving key query parameters.
87132
87154
  */
87133
87155
  function buildQueryFromState(state) {
87156
+ // preserveQueryStrings may write repeated values as arrays, so the value type
87157
+ // must allow string[] in addition to string.
87134
87158
  const query = {};
87135
87159
 
87136
87160
  // Sorting
@@ -87830,7 +87854,12 @@ function WorkList({
87830
87854
  // `workList.columns` is registered as a value (StudyList.defaultColumns) and
87831
87855
  // merged via customization commands, so we read the result directly.
87832
87856
  const customized = customizationService.getCustomization('workList.columns');
87833
- return Array.isArray(customized) ? customized : ui_next_src/* .StudyList.defaultColumns */.Slc.defaultColumns;
87857
+ const resolved = Array.isArray(customized) ? customized : ui_next_src/* .StudyList.defaultColumns */.Slc.defaultColumns;
87858
+ // Expand data-only column specs. A `?customization=` JSONC file (or any
87859
+ // serializable source) cannot carry render functions, so an entry that has
87860
+ // an `id` but no `accessorFn`/`cell` is turned into a display-only text
87861
+ // column that reads `row[id]` — matching `StudyList.textColumn`.
87862
+ return resolved.map(col => col && typeof col === 'object' && col.id && !col.accessorFn && !col.cell ? ui_next_src/* .StudyList.textColumn */.Slc.textColumn(col.id, col.meta?.label ?? col.id, col.meta) : col);
87834
87863
  }, [customizationService]);
87835
87864
  const logoComponent = appConfig?.whiteLabeling?.createLogoComponentFn?.(react) ?? /*#__PURE__*/react.createElement(ui_next_src/* .Icons.OHIFLogoHorizontal */.FI1.OHIFLogoHorizontal, {
87836
87865
  "aria-label": "OHIF logo",
@@ -89551,27 +89580,27 @@ async function loadModule(module) {
89551
89580
  return imported.default;
89552
89581
  }
89553
89582
  if (module === "@ohif/extension-cornerstone") {
89554
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(3833)]).then(__webpack_require__.bind(__webpack_require__, 84461));
89583
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(3833)]).then(__webpack_require__.bind(__webpack_require__, 28772));
89555
89584
  return imported.default;
89556
89585
  }
89557
89586
  if (module === "@ohif/extension-measurement-tracking") {
89558
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(5406), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(7248), __webpack_require__.e(3760)]).then(__webpack_require__.bind(__webpack_require__, 34879));
89587
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(5406), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(7248), __webpack_require__.e(3760)]).then(__webpack_require__.bind(__webpack_require__, 34879));
89559
89588
  return imported.default;
89560
89589
  }
89561
89590
  if (module === "@ohif/extension-cornerstone-dicom-sr") {
89562
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(7248), __webpack_require__.e(976)]).then(__webpack_require__.bind(__webpack_require__, 81107));
89591
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(7248), __webpack_require__.e(976)]).then(__webpack_require__.bind(__webpack_require__, 81107));
89563
89592
  return imported.default;
89564
89593
  }
89565
89594
  if (module === "@ohif/extension-cornerstone-dicom-seg") {
89566
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(5708)]).then(__webpack_require__.bind(__webpack_require__, 53451));
89595
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(5708)]).then(__webpack_require__.bind(__webpack_require__, 53451));
89567
89596
  return imported.default;
89568
89597
  }
89569
89598
  if (module === "@ohif/extension-cornerstone-dicom-pmap") {
89570
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(9415)]).then(__webpack_require__.bind(__webpack_require__, 76494));
89599
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(9415)]).then(__webpack_require__.bind(__webpack_require__, 76494));
89571
89600
  return imported.default;
89572
89601
  }
89573
89602
  if (module === "@ohif/extension-cornerstone-dynamic-volume") {
89574
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(1602)]).then(__webpack_require__.bind(__webpack_require__, 42061));
89603
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(1602)]).then(__webpack_require__.bind(__webpack_require__, 42061));
89575
89604
  return imported.default;
89576
89605
  }
89577
89606
  if (module === "@ohif/extension-dicom-microscopy") {
@@ -89587,11 +89616,11 @@ async function loadModule(module) {
89587
89616
  return imported.default;
89588
89617
  }
89589
89618
  if (module === "@ohif/extension-tmtv") {
89590
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(7295)]).then(__webpack_require__.bind(__webpack_require__, 75366));
89619
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(379), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(7295)]).then(__webpack_require__.bind(__webpack_require__, 75366));
89591
89620
  return imported.default;
89592
89621
  }
89593
89622
  if (module === "@ohif/extension-test") {
89594
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(8007), __webpack_require__.e(414), __webpack_require__.e(8423)]).then(__webpack_require__.bind(__webpack_require__, 49182));
89623
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(8565), __webpack_require__.e(7579), __webpack_require__.e(6577), __webpack_require__.e(5989), __webpack_require__.e(8432), __webpack_require__.e(6650), __webpack_require__.e(8007), __webpack_require__.e(7701), __webpack_require__.e(8423)]).then(__webpack_require__.bind(__webpack_require__, 49182));
89595
89624
  return imported.default;
89596
89625
  }
89597
89626
  if (module === "@ohif/extension-cornerstone-dicom-rt") {
@@ -89603,15 +89632,15 @@ async function loadModule(module) {
89603
89632
  return imported.default;
89604
89633
  }
89605
89634
  if (module === "@ohif/mode-longitudinal") {
89606
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(2666), __webpack_require__.e(5696)]).then(__webpack_require__.bind(__webpack_require__, 63683));
89635
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(419), __webpack_require__.e(5696)]).then(__webpack_require__.bind(__webpack_require__, 63683));
89607
89636
  return imported.default;
89608
89637
  }
89609
89638
  if (module === "@ohif/mode-basic") {
89610
- const imported = await __webpack_require__.e(/* import() */ 2666).then(__webpack_require__.bind(__webpack_require__, 90337));
89639
+ const imported = await __webpack_require__.e(/* import() */ 419).then(__webpack_require__.bind(__webpack_require__, 86750));
89611
89640
  return imported.default;
89612
89641
  }
89613
89642
  if (module === "@ohif/mode-segmentation") {
89614
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(2666), __webpack_require__.e(6001)]).then(__webpack_require__.bind(__webpack_require__, 21992));
89643
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(419), __webpack_require__.e(6001)]).then(__webpack_require__.bind(__webpack_require__, 21992));
89615
89644
  return imported.default;
89616
89645
  }
89617
89646
  if (module === "@ohif/mode-tmtv") {
@@ -90119,6 +90148,12 @@ function ModeRoute({
90119
90148
  appConfig
90120
90149
  });
90121
90150
 
90151
+ // `extensionManager.onModeEnter` resets the customization mode scope via
90152
+ // `customizationService.onModeEnter`; now layer on the `mode` phase blocks
90153
+ // for this mode — the general (`*`) block first, then any block keyed by
90154
+ // this mode's id / routeName so a single mode can override the general one.
90155
+ customizationService.applyModeCustomizations([mode.id, mode.routeName]);
90156
+
90122
90157
  // use the URL hangingProtocolId if it exists, otherwise use the one
90123
90158
  // defined in the mode configuration
90124
90159
  const hangingProtocolIdToUse = hangingProtocolService.getProtocolById(runTimeHangingProtocolId) ? runTimeHangingProtocolId : hangingProtocol;
@@ -90573,7 +90608,7 @@ const createRoutes = ({
90573
90608
 
90574
90609
 
90575
90610
  /**
90576
- * @param {object|func} appConfigOrFunc - application configuration, or a function that returns application configuration
90611
+ * @param {object|function} appConfigOrFunc - application configuration, or a function that returns application configuration
90577
90612
  * @param {object[]} defaultExtensions - array of extension objects
90578
90613
  */
90579
90614
  async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
@@ -90614,8 +90649,25 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
90614
90649
  * Example2: [[ext1, config], ext2, [ext3, config]]
90615
90650
  */
90616
90651
  const loadedExtensions = await importItems([...defaultExtensions, ...appConfig.extensions]);
90652
+ const {
90653
+ customizationService
90654
+ } = servicesManager.services;
90655
+ // Resolve every customization module up front — from
90656
+ // `appConfig.customizationService.requires` and the `?customization=` URL
90657
+ // parameter — long before any mode loads, then apply the `bootstrap` phase
90658
+ // BEFORE extensions register so it is in place while they initialize. Modules
90659
+ // are only loaded when `appConfig.customizationUrlPrefixes` allows their
90660
+ // prefix; the feature is off by default, and a value with an unconfigured
90661
+ // prefix throws here (aborting startup) rather than being silently ignored.
90662
+ await customizationService.loadAndApplyBootstrapCustomizations(extensionManager);
90617
90663
  await extensionManager.registerExtensions(loadedExtensions, appConfig.dataSources);
90618
90664
 
90665
+ // Merge extension default/global modules, then layer on the `global` phase of
90666
+ // the structured config + the URL modules resolved above (so `$apply`-style
90667
+ // overrides see the extension-provided defaults they build on).
90668
+ customizationService.init(extensionManager);
90669
+ customizationService.applyGlobalCustomizations();
90670
+
90619
90671
  // TODO: We no longer use `utils.addServer`
90620
90672
  // TODO: We no longer init webWorkers at app level
90621
90673
  // TODO: We no longer init the user Manager
@@ -94700,8 +94752,7 @@ function App({
94700
94752
  viewportGridService,
94701
94753
  cineService,
94702
94754
  userAuthenticationService,
94703
- uiNotificationService,
94704
- customizationService
94755
+ uiNotificationService
94705
94756
  } = App_servicesManager.services;
94706
94757
  const providers = [[state_0/* .AppConfigProvider */.X, {
94707
94758
  value: appConfigState
@@ -94747,8 +94798,8 @@ function App({
94747
94798
  });
94748
94799
  let authRoutes = null;
94749
94800
 
94750
- // Should there be a generic call to init on the extension manager?
94751
- customizationService.init(App_extensionManager);
94801
+ // customizationService.init(extensionManager) runs in appInit after extensions register;
94802
+ // do not call init again here — repeated init would duplicate-merge unless guarded (see CustomizationService.init).
94752
94803
 
94753
94804
  // Use config to create routes
94754
94805
  const appRoutes = routes_0({
@@ -95272,7 +95323,7 @@ __webpack_require__.d(__webpack_exports__, {
95272
95323
  });
95273
95324
  /* import */ var react__rspack_import_0 = __webpack_require__(86326);
95274
95325
  /* import */ var _contextProviders_SystemProvider__rspack_import_1 = __webpack_require__(62376);
95275
- /* import */ var _utils__rspack_import_2 = __webpack_require__(3682);
95326
+ /* import */ var _utils__rspack_import_2 = __webpack_require__(95339);
95276
95327
 
95277
95328
 
95278
95329
 
@@ -95568,7 +95619,7 @@ const useViewportRef = viewportId => {
95568
95619
  };
95569
95620
 
95570
95621
  },
95571
- 62901(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
95622
+ 50679(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
95572
95623
  "use strict";
95573
95624
 
95574
95625
  // EXPORTS
@@ -97900,8 +97951,8 @@ class ProtocolEngine {
97900
97951
  return this.matchedProtocols.get(highestScoringProtocolId);
97901
97952
  }
97902
97953
  }
97903
- // EXTERNAL MODULE: ../../core/src/utils/index.ts + 33 modules
97904
- var utils = __webpack_require__(3682);
97954
+ // EXTERNAL MODULE: ../../core/src/utils/index.ts + 34 modules
97955
+ var utils = __webpack_require__(95339);
97905
97956
  ;// CONCATENATED MODULE: ../../core/src/services/HangingProtocolService/custom-attribute/isDisplaySetFromUrl.ts
97906
97957
 
97907
97958
 
@@ -99557,10 +99608,1801 @@ UserAuthenticationService.REGISTRATION = {
99557
99608
  // EXTERNAL MODULE: ../../../node_modules/immutability-helper/index.js
99558
99609
  var immutability_helper = __webpack_require__(1752);
99559
99610
  var immutability_helper_default = /*#__PURE__*/__webpack_require__.n(immutability_helper);
99611
+ ;// CONCATENATED MODULE: ../../../node_modules/json5/dist/index.mjs
99612
+ // This is a generated file. Do not edit.
99613
+ var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/;
99614
+ var ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/;
99615
+ var ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/;
99616
+
99617
+ var unicode = {
99618
+ Space_Separator: Space_Separator,
99619
+ ID_Start: ID_Start,
99620
+ ID_Continue: ID_Continue
99621
+ };
99622
+
99623
+ var util = {
99624
+ isSpaceSeparator (c) {
99625
+ return typeof c === 'string' && unicode.Space_Separator.test(c)
99626
+ },
99627
+
99628
+ isIdStartChar (c) {
99629
+ return typeof c === 'string' && (
99630
+ (c >= 'a' && c <= 'z') ||
99631
+ (c >= 'A' && c <= 'Z') ||
99632
+ (c === '$') || (c === '_') ||
99633
+ unicode.ID_Start.test(c)
99634
+ )
99635
+ },
99636
+
99637
+ isIdContinueChar (c) {
99638
+ return typeof c === 'string' && (
99639
+ (c >= 'a' && c <= 'z') ||
99640
+ (c >= 'A' && c <= 'Z') ||
99641
+ (c >= '0' && c <= '9') ||
99642
+ (c === '$') || (c === '_') ||
99643
+ (c === '\u200C') || (c === '\u200D') ||
99644
+ unicode.ID_Continue.test(c)
99645
+ )
99646
+ },
99647
+
99648
+ isDigit (c) {
99649
+ return typeof c === 'string' && /[0-9]/.test(c)
99650
+ },
99651
+
99652
+ isHexDigit (c) {
99653
+ return typeof c === 'string' && /[0-9A-Fa-f]/.test(c)
99654
+ },
99655
+ };
99656
+
99657
+ let source;
99658
+ let parseState;
99659
+ let dist_stack;
99660
+ let pos;
99661
+ let line;
99662
+ let column;
99663
+ let dist_token;
99664
+ let dist_key;
99665
+ let dist_root;
99666
+
99667
+ var dist_parse = function parse (text, reviver) {
99668
+ source = String(text);
99669
+ parseState = 'start';
99670
+ dist_stack = [];
99671
+ pos = 0;
99672
+ line = 1;
99673
+ column = 0;
99674
+ dist_token = undefined;
99675
+ dist_key = undefined;
99676
+ dist_root = undefined;
99677
+
99678
+ do {
99679
+ dist_token = lex();
99680
+
99681
+ // This code is unreachable.
99682
+ // if (!parseStates[parseState]) {
99683
+ // throw invalidParseState()
99684
+ // }
99685
+
99686
+ parseStates[parseState]();
99687
+ } while (dist_token.type !== 'eof')
99688
+
99689
+ if (typeof reviver === 'function') {
99690
+ return internalize({'': dist_root}, '', reviver)
99691
+ }
99692
+
99693
+ return dist_root
99694
+ };
99695
+
99696
+ function internalize (holder, name, reviver) {
99697
+ const value = holder[name];
99698
+ if (value != null && typeof value === 'object') {
99699
+ if (Array.isArray(value)) {
99700
+ for (let i = 0; i < value.length; i++) {
99701
+ const key = String(i);
99702
+ const replacement = internalize(value, key, reviver);
99703
+ if (replacement === undefined) {
99704
+ delete value[key];
99705
+ } else {
99706
+ Object.defineProperty(value, key, {
99707
+ value: replacement,
99708
+ writable: true,
99709
+ enumerable: true,
99710
+ configurable: true,
99711
+ });
99712
+ }
99713
+ }
99714
+ } else {
99715
+ for (const key in value) {
99716
+ const replacement = internalize(value, key, reviver);
99717
+ if (replacement === undefined) {
99718
+ delete value[key];
99719
+ } else {
99720
+ Object.defineProperty(value, key, {
99721
+ value: replacement,
99722
+ writable: true,
99723
+ enumerable: true,
99724
+ configurable: true,
99725
+ });
99726
+ }
99727
+ }
99728
+ }
99729
+ }
99730
+
99731
+ return reviver.call(holder, name, value)
99732
+ }
99733
+
99734
+ let lexState;
99735
+ let dist_buffer;
99736
+ let doubleQuote;
99737
+ let sign;
99738
+ let dist_c;
99739
+
99740
+ function lex () {
99741
+ lexState = 'default';
99742
+ dist_buffer = '';
99743
+ doubleQuote = false;
99744
+ sign = 1;
99745
+
99746
+ for (;;) {
99747
+ dist_c = peek();
99748
+
99749
+ // This code is unreachable.
99750
+ // if (!lexStates[lexState]) {
99751
+ // throw invalidLexState(lexState)
99752
+ // }
99753
+
99754
+ const token = lexStates[lexState]();
99755
+ if (token) {
99756
+ return token
99757
+ }
99758
+ }
99759
+ }
99760
+
99761
+ function peek () {
99762
+ if (source[pos]) {
99763
+ return String.fromCodePoint(source.codePointAt(pos))
99764
+ }
99765
+ }
99766
+
99767
+ function read () {
99768
+ const c = peek();
99769
+
99770
+ if (c === '\n') {
99771
+ line++;
99772
+ column = 0;
99773
+ } else if (c) {
99774
+ column += c.length;
99775
+ } else {
99776
+ column++;
99777
+ }
99778
+
99779
+ if (c) {
99780
+ pos += c.length;
99781
+ }
99782
+
99783
+ return c
99784
+ }
99785
+
99786
+ const lexStates = {
99787
+ default () {
99788
+ switch (dist_c) {
99789
+ case '\t':
99790
+ case '\v':
99791
+ case '\f':
99792
+ case ' ':
99793
+ case '\u00A0':
99794
+ case '\uFEFF':
99795
+ case '\n':
99796
+ case '\r':
99797
+ case '\u2028':
99798
+ case '\u2029':
99799
+ read();
99800
+ return
99801
+
99802
+ case '/':
99803
+ read();
99804
+ lexState = 'comment';
99805
+ return
99806
+
99807
+ case undefined:
99808
+ read();
99809
+ return newToken('eof')
99810
+ }
99811
+
99812
+ if (util.isSpaceSeparator(dist_c)) {
99813
+ read();
99814
+ return
99815
+ }
99816
+
99817
+ // This code is unreachable.
99818
+ // if (!lexStates[parseState]) {
99819
+ // throw invalidLexState(parseState)
99820
+ // }
99821
+
99822
+ return lexStates[parseState]()
99823
+ },
99824
+
99825
+ comment () {
99826
+ switch (dist_c) {
99827
+ case '*':
99828
+ read();
99829
+ lexState = 'multiLineComment';
99830
+ return
99831
+
99832
+ case '/':
99833
+ read();
99834
+ lexState = 'singleLineComment';
99835
+ return
99836
+ }
99837
+
99838
+ throw invalidChar(read())
99839
+ },
99840
+
99841
+ multiLineComment () {
99842
+ switch (dist_c) {
99843
+ case '*':
99844
+ read();
99845
+ lexState = 'multiLineCommentAsterisk';
99846
+ return
99847
+
99848
+ case undefined:
99849
+ throw invalidChar(read())
99850
+ }
99851
+
99852
+ read();
99853
+ },
99854
+
99855
+ multiLineCommentAsterisk () {
99856
+ switch (dist_c) {
99857
+ case '*':
99858
+ read();
99859
+ return
99860
+
99861
+ case '/':
99862
+ read();
99863
+ lexState = 'default';
99864
+ return
99865
+
99866
+ case undefined:
99867
+ throw invalidChar(read())
99868
+ }
99869
+
99870
+ read();
99871
+ lexState = 'multiLineComment';
99872
+ },
99873
+
99874
+ singleLineComment () {
99875
+ switch (dist_c) {
99876
+ case '\n':
99877
+ case '\r':
99878
+ case '\u2028':
99879
+ case '\u2029':
99880
+ read();
99881
+ lexState = 'default';
99882
+ return
99883
+
99884
+ case undefined:
99885
+ read();
99886
+ return newToken('eof')
99887
+ }
99888
+
99889
+ read();
99890
+ },
99891
+
99892
+ value () {
99893
+ switch (dist_c) {
99894
+ case '{':
99895
+ case '[':
99896
+ return newToken('punctuator', read())
99897
+
99898
+ case 'n':
99899
+ read();
99900
+ literal('ull');
99901
+ return newToken('null', null)
99902
+
99903
+ case 't':
99904
+ read();
99905
+ literal('rue');
99906
+ return newToken('boolean', true)
99907
+
99908
+ case 'f':
99909
+ read();
99910
+ literal('alse');
99911
+ return newToken('boolean', false)
99912
+
99913
+ case '-':
99914
+ case '+':
99915
+ if (read() === '-') {
99916
+ sign = -1;
99917
+ }
99918
+
99919
+ lexState = 'sign';
99920
+ return
99921
+
99922
+ case '.':
99923
+ dist_buffer = read();
99924
+ lexState = 'decimalPointLeading';
99925
+ return
99926
+
99927
+ case '0':
99928
+ dist_buffer = read();
99929
+ lexState = 'zero';
99930
+ return
99931
+
99932
+ case '1':
99933
+ case '2':
99934
+ case '3':
99935
+ case '4':
99936
+ case '5':
99937
+ case '6':
99938
+ case '7':
99939
+ case '8':
99940
+ case '9':
99941
+ dist_buffer = read();
99942
+ lexState = 'decimalInteger';
99943
+ return
99944
+
99945
+ case 'I':
99946
+ read();
99947
+ literal('nfinity');
99948
+ return newToken('numeric', Infinity)
99949
+
99950
+ case 'N':
99951
+ read();
99952
+ literal('aN');
99953
+ return newToken('numeric', NaN)
99954
+
99955
+ case '"':
99956
+ case "'":
99957
+ doubleQuote = (read() === '"');
99958
+ dist_buffer = '';
99959
+ lexState = 'string';
99960
+ return
99961
+ }
99962
+
99963
+ throw invalidChar(read())
99964
+ },
99965
+
99966
+ identifierNameStartEscape () {
99967
+ if (dist_c !== 'u') {
99968
+ throw invalidChar(read())
99969
+ }
99970
+
99971
+ read();
99972
+ const u = unicodeEscape();
99973
+ switch (u) {
99974
+ case '$':
99975
+ case '_':
99976
+ break
99977
+
99978
+ default:
99979
+ if (!util.isIdStartChar(u)) {
99980
+ throw invalidIdentifier()
99981
+ }
99982
+
99983
+ break
99984
+ }
99985
+
99986
+ dist_buffer += u;
99987
+ lexState = 'identifierName';
99988
+ },
99989
+
99990
+ identifierName () {
99991
+ switch (dist_c) {
99992
+ case '$':
99993
+ case '_':
99994
+ case '\u200C':
99995
+ case '\u200D':
99996
+ dist_buffer += read();
99997
+ return
99998
+
99999
+ case '\\':
100000
+ read();
100001
+ lexState = 'identifierNameEscape';
100002
+ return
100003
+ }
100004
+
100005
+ if (util.isIdContinueChar(dist_c)) {
100006
+ dist_buffer += read();
100007
+ return
100008
+ }
100009
+
100010
+ return newToken('identifier', dist_buffer)
100011
+ },
100012
+
100013
+ identifierNameEscape () {
100014
+ if (dist_c !== 'u') {
100015
+ throw invalidChar(read())
100016
+ }
100017
+
100018
+ read();
100019
+ const u = unicodeEscape();
100020
+ switch (u) {
100021
+ case '$':
100022
+ case '_':
100023
+ case '\u200C':
100024
+ case '\u200D':
100025
+ break
100026
+
100027
+ default:
100028
+ if (!util.isIdContinueChar(u)) {
100029
+ throw invalidIdentifier()
100030
+ }
100031
+
100032
+ break
100033
+ }
100034
+
100035
+ dist_buffer += u;
100036
+ lexState = 'identifierName';
100037
+ },
100038
+
100039
+ sign () {
100040
+ switch (dist_c) {
100041
+ case '.':
100042
+ dist_buffer = read();
100043
+ lexState = 'decimalPointLeading';
100044
+ return
100045
+
100046
+ case '0':
100047
+ dist_buffer = read();
100048
+ lexState = 'zero';
100049
+ return
100050
+
100051
+ case '1':
100052
+ case '2':
100053
+ case '3':
100054
+ case '4':
100055
+ case '5':
100056
+ case '6':
100057
+ case '7':
100058
+ case '8':
100059
+ case '9':
100060
+ dist_buffer = read();
100061
+ lexState = 'decimalInteger';
100062
+ return
100063
+
100064
+ case 'I':
100065
+ read();
100066
+ literal('nfinity');
100067
+ return newToken('numeric', sign * Infinity)
100068
+
100069
+ case 'N':
100070
+ read();
100071
+ literal('aN');
100072
+ return newToken('numeric', NaN)
100073
+ }
100074
+
100075
+ throw invalidChar(read())
100076
+ },
100077
+
100078
+ zero () {
100079
+ switch (dist_c) {
100080
+ case '.':
100081
+ dist_buffer += read();
100082
+ lexState = 'decimalPoint';
100083
+ return
100084
+
100085
+ case 'e':
100086
+ case 'E':
100087
+ dist_buffer += read();
100088
+ lexState = 'decimalExponent';
100089
+ return
100090
+
100091
+ case 'x':
100092
+ case 'X':
100093
+ dist_buffer += read();
100094
+ lexState = 'hexadecimal';
100095
+ return
100096
+ }
100097
+
100098
+ return newToken('numeric', sign * 0)
100099
+ },
100100
+
100101
+ decimalInteger () {
100102
+ switch (dist_c) {
100103
+ case '.':
100104
+ dist_buffer += read();
100105
+ lexState = 'decimalPoint';
100106
+ return
100107
+
100108
+ case 'e':
100109
+ case 'E':
100110
+ dist_buffer += read();
100111
+ lexState = 'decimalExponent';
100112
+ return
100113
+ }
100114
+
100115
+ if (util.isDigit(dist_c)) {
100116
+ dist_buffer += read();
100117
+ return
100118
+ }
100119
+
100120
+ return newToken('numeric', sign * Number(dist_buffer))
100121
+ },
100122
+
100123
+ decimalPointLeading () {
100124
+ if (util.isDigit(dist_c)) {
100125
+ dist_buffer += read();
100126
+ lexState = 'decimalFraction';
100127
+ return
100128
+ }
100129
+
100130
+ throw invalidChar(read())
100131
+ },
100132
+
100133
+ decimalPoint () {
100134
+ switch (dist_c) {
100135
+ case 'e':
100136
+ case 'E':
100137
+ dist_buffer += read();
100138
+ lexState = 'decimalExponent';
100139
+ return
100140
+ }
100141
+
100142
+ if (util.isDigit(dist_c)) {
100143
+ dist_buffer += read();
100144
+ lexState = 'decimalFraction';
100145
+ return
100146
+ }
100147
+
100148
+ return newToken('numeric', sign * Number(dist_buffer))
100149
+ },
100150
+
100151
+ decimalFraction () {
100152
+ switch (dist_c) {
100153
+ case 'e':
100154
+ case 'E':
100155
+ dist_buffer += read();
100156
+ lexState = 'decimalExponent';
100157
+ return
100158
+ }
100159
+
100160
+ if (util.isDigit(dist_c)) {
100161
+ dist_buffer += read();
100162
+ return
100163
+ }
100164
+
100165
+ return newToken('numeric', sign * Number(dist_buffer))
100166
+ },
100167
+
100168
+ decimalExponent () {
100169
+ switch (dist_c) {
100170
+ case '+':
100171
+ case '-':
100172
+ dist_buffer += read();
100173
+ lexState = 'decimalExponentSign';
100174
+ return
100175
+ }
100176
+
100177
+ if (util.isDigit(dist_c)) {
100178
+ dist_buffer += read();
100179
+ lexState = 'decimalExponentInteger';
100180
+ return
100181
+ }
100182
+
100183
+ throw invalidChar(read())
100184
+ },
100185
+
100186
+ decimalExponentSign () {
100187
+ if (util.isDigit(dist_c)) {
100188
+ dist_buffer += read();
100189
+ lexState = 'decimalExponentInteger';
100190
+ return
100191
+ }
100192
+
100193
+ throw invalidChar(read())
100194
+ },
100195
+
100196
+ decimalExponentInteger () {
100197
+ if (util.isDigit(dist_c)) {
100198
+ dist_buffer += read();
100199
+ return
100200
+ }
100201
+
100202
+ return newToken('numeric', sign * Number(dist_buffer))
100203
+ },
100204
+
100205
+ hexadecimal () {
100206
+ if (util.isHexDigit(dist_c)) {
100207
+ dist_buffer += read();
100208
+ lexState = 'hexadecimalInteger';
100209
+ return
100210
+ }
100211
+
100212
+ throw invalidChar(read())
100213
+ },
100214
+
100215
+ hexadecimalInteger () {
100216
+ if (util.isHexDigit(dist_c)) {
100217
+ dist_buffer += read();
100218
+ return
100219
+ }
100220
+
100221
+ return newToken('numeric', sign * Number(dist_buffer))
100222
+ },
100223
+
100224
+ string () {
100225
+ switch (dist_c) {
100226
+ case '\\':
100227
+ read();
100228
+ dist_buffer += dist_escape();
100229
+ return
100230
+
100231
+ case '"':
100232
+ if (doubleQuote) {
100233
+ read();
100234
+ return newToken('string', dist_buffer)
100235
+ }
100236
+
100237
+ dist_buffer += read();
100238
+ return
100239
+
100240
+ case "'":
100241
+ if (!doubleQuote) {
100242
+ read();
100243
+ return newToken('string', dist_buffer)
100244
+ }
100245
+
100246
+ dist_buffer += read();
100247
+ return
100248
+
100249
+ case '\n':
100250
+ case '\r':
100251
+ throw invalidChar(read())
100252
+
100253
+ case '\u2028':
100254
+ case '\u2029':
100255
+ separatorChar(dist_c);
100256
+ break
100257
+
100258
+ case undefined:
100259
+ throw invalidChar(read())
100260
+ }
100261
+
100262
+ dist_buffer += read();
100263
+ },
100264
+
100265
+ start () {
100266
+ switch (dist_c) {
100267
+ case '{':
100268
+ case '[':
100269
+ return newToken('punctuator', read())
100270
+
100271
+ // This code is unreachable since the default lexState handles eof.
100272
+ // case undefined:
100273
+ // return newToken('eof')
100274
+ }
100275
+
100276
+ lexState = 'value';
100277
+ },
100278
+
100279
+ beforePropertyName () {
100280
+ switch (dist_c) {
100281
+ case '$':
100282
+ case '_':
100283
+ dist_buffer = read();
100284
+ lexState = 'identifierName';
100285
+ return
100286
+
100287
+ case '\\':
100288
+ read();
100289
+ lexState = 'identifierNameStartEscape';
100290
+ return
100291
+
100292
+ case '}':
100293
+ return newToken('punctuator', read())
100294
+
100295
+ case '"':
100296
+ case "'":
100297
+ doubleQuote = (read() === '"');
100298
+ lexState = 'string';
100299
+ return
100300
+ }
100301
+
100302
+ if (util.isIdStartChar(dist_c)) {
100303
+ dist_buffer += read();
100304
+ lexState = 'identifierName';
100305
+ return
100306
+ }
100307
+
100308
+ throw invalidChar(read())
100309
+ },
100310
+
100311
+ afterPropertyName () {
100312
+ if (dist_c === ':') {
100313
+ return newToken('punctuator', read())
100314
+ }
100315
+
100316
+ throw invalidChar(read())
100317
+ },
100318
+
100319
+ beforePropertyValue () {
100320
+ lexState = 'value';
100321
+ },
100322
+
100323
+ afterPropertyValue () {
100324
+ switch (dist_c) {
100325
+ case ',':
100326
+ case '}':
100327
+ return newToken('punctuator', read())
100328
+ }
100329
+
100330
+ throw invalidChar(read())
100331
+ },
100332
+
100333
+ beforeArrayValue () {
100334
+ if (dist_c === ']') {
100335
+ return newToken('punctuator', read())
100336
+ }
100337
+
100338
+ lexState = 'value';
100339
+ },
100340
+
100341
+ afterArrayValue () {
100342
+ switch (dist_c) {
100343
+ case ',':
100344
+ case ']':
100345
+ return newToken('punctuator', read())
100346
+ }
100347
+
100348
+ throw invalidChar(read())
100349
+ },
100350
+
100351
+ end () {
100352
+ // This code is unreachable since it's handled by the default lexState.
100353
+ // if (c === undefined) {
100354
+ // read()
100355
+ // return newToken('eof')
100356
+ // }
100357
+
100358
+ throw invalidChar(read())
100359
+ },
100360
+ };
100361
+
100362
+ function newToken (type, value) {
100363
+ return {
100364
+ type,
100365
+ value,
100366
+ line,
100367
+ column,
100368
+ }
100369
+ }
100370
+
100371
+ function literal (s) {
100372
+ for (const c of s) {
100373
+ const p = peek();
100374
+
100375
+ if (p !== c) {
100376
+ throw invalidChar(read())
100377
+ }
100378
+
100379
+ read();
100380
+ }
100381
+ }
100382
+
100383
+ function dist_escape () {
100384
+ const c = peek();
100385
+ switch (c) {
100386
+ case 'b':
100387
+ read();
100388
+ return '\b'
100389
+
100390
+ case 'f':
100391
+ read();
100392
+ return '\f'
100393
+
100394
+ case 'n':
100395
+ read();
100396
+ return '\n'
100397
+
100398
+ case 'r':
100399
+ read();
100400
+ return '\r'
100401
+
100402
+ case 't':
100403
+ read();
100404
+ return '\t'
100405
+
100406
+ case 'v':
100407
+ read();
100408
+ return '\v'
100409
+
100410
+ case '0':
100411
+ read();
100412
+ if (util.isDigit(peek())) {
100413
+ throw invalidChar(read())
100414
+ }
100415
+
100416
+ return '\0'
100417
+
100418
+ case 'x':
100419
+ read();
100420
+ return hexEscape()
100421
+
100422
+ case 'u':
100423
+ read();
100424
+ return unicodeEscape()
100425
+
100426
+ case '\n':
100427
+ case '\u2028':
100428
+ case '\u2029':
100429
+ read();
100430
+ return ''
100431
+
100432
+ case '\r':
100433
+ read();
100434
+ if (peek() === '\n') {
100435
+ read();
100436
+ }
100437
+
100438
+ return ''
100439
+
100440
+ case '1':
100441
+ case '2':
100442
+ case '3':
100443
+ case '4':
100444
+ case '5':
100445
+ case '6':
100446
+ case '7':
100447
+ case '8':
100448
+ case '9':
100449
+ throw invalidChar(read())
100450
+
100451
+ case undefined:
100452
+ throw invalidChar(read())
100453
+ }
100454
+
100455
+ return read()
100456
+ }
100457
+
100458
+ function hexEscape () {
100459
+ let buffer = '';
100460
+ let c = peek();
100461
+
100462
+ if (!util.isHexDigit(c)) {
100463
+ throw invalidChar(read())
100464
+ }
100465
+
100466
+ buffer += read();
100467
+
100468
+ c = peek();
100469
+ if (!util.isHexDigit(c)) {
100470
+ throw invalidChar(read())
100471
+ }
100472
+
100473
+ buffer += read();
100474
+
100475
+ return String.fromCodePoint(parseInt(buffer, 16))
100476
+ }
100477
+
100478
+ function unicodeEscape () {
100479
+ let buffer = '';
100480
+ let count = 4;
100481
+
100482
+ while (count-- > 0) {
100483
+ const c = peek();
100484
+ if (!util.isHexDigit(c)) {
100485
+ throw invalidChar(read())
100486
+ }
100487
+
100488
+ buffer += read();
100489
+ }
100490
+
100491
+ return String.fromCodePoint(parseInt(buffer, 16))
100492
+ }
100493
+
100494
+ const parseStates = {
100495
+ start () {
100496
+ if (dist_token.type === 'eof') {
100497
+ throw invalidEOF()
100498
+ }
100499
+
100500
+ push();
100501
+ },
100502
+
100503
+ beforePropertyName () {
100504
+ switch (dist_token.type) {
100505
+ case 'identifier':
100506
+ case 'string':
100507
+ dist_key = dist_token.value;
100508
+ parseState = 'afterPropertyName';
100509
+ return
100510
+
100511
+ case 'punctuator':
100512
+ // This code is unreachable since it's handled by the lexState.
100513
+ // if (token.value !== '}') {
100514
+ // throw invalidToken()
100515
+ // }
100516
+
100517
+ pop();
100518
+ return
100519
+
100520
+ case 'eof':
100521
+ throw invalidEOF()
100522
+ }
100523
+
100524
+ // This code is unreachable since it's handled by the lexState.
100525
+ // throw invalidToken()
100526
+ },
100527
+
100528
+ afterPropertyName () {
100529
+ // This code is unreachable since it's handled by the lexState.
100530
+ // if (token.type !== 'punctuator' || token.value !== ':') {
100531
+ // throw invalidToken()
100532
+ // }
100533
+
100534
+ if (dist_token.type === 'eof') {
100535
+ throw invalidEOF()
100536
+ }
100537
+
100538
+ parseState = 'beforePropertyValue';
100539
+ },
100540
+
100541
+ beforePropertyValue () {
100542
+ if (dist_token.type === 'eof') {
100543
+ throw invalidEOF()
100544
+ }
100545
+
100546
+ push();
100547
+ },
100548
+
100549
+ beforeArrayValue () {
100550
+ if (dist_token.type === 'eof') {
100551
+ throw invalidEOF()
100552
+ }
100553
+
100554
+ if (dist_token.type === 'punctuator' && dist_token.value === ']') {
100555
+ pop();
100556
+ return
100557
+ }
100558
+
100559
+ push();
100560
+ },
100561
+
100562
+ afterPropertyValue () {
100563
+ // This code is unreachable since it's handled by the lexState.
100564
+ // if (token.type !== 'punctuator') {
100565
+ // throw invalidToken()
100566
+ // }
100567
+
100568
+ if (dist_token.type === 'eof') {
100569
+ throw invalidEOF()
100570
+ }
100571
+
100572
+ switch (dist_token.value) {
100573
+ case ',':
100574
+ parseState = 'beforePropertyName';
100575
+ return
100576
+
100577
+ case '}':
100578
+ pop();
100579
+ }
100580
+
100581
+ // This code is unreachable since it's handled by the lexState.
100582
+ // throw invalidToken()
100583
+ },
100584
+
100585
+ afterArrayValue () {
100586
+ // This code is unreachable since it's handled by the lexState.
100587
+ // if (token.type !== 'punctuator') {
100588
+ // throw invalidToken()
100589
+ // }
100590
+
100591
+ if (dist_token.type === 'eof') {
100592
+ throw invalidEOF()
100593
+ }
100594
+
100595
+ switch (dist_token.value) {
100596
+ case ',':
100597
+ parseState = 'beforeArrayValue';
100598
+ return
100599
+
100600
+ case ']':
100601
+ pop();
100602
+ }
100603
+
100604
+ // This code is unreachable since it's handled by the lexState.
100605
+ // throw invalidToken()
100606
+ },
100607
+
100608
+ end () {
100609
+ // This code is unreachable since it's handled by the lexState.
100610
+ // if (token.type !== 'eof') {
100611
+ // throw invalidToken()
100612
+ // }
100613
+ },
100614
+ };
100615
+
100616
+ function push () {
100617
+ let value;
100618
+
100619
+ switch (dist_token.type) {
100620
+ case 'punctuator':
100621
+ switch (dist_token.value) {
100622
+ case '{':
100623
+ value = {};
100624
+ break
100625
+
100626
+ case '[':
100627
+ value = [];
100628
+ break
100629
+ }
100630
+
100631
+ break
100632
+
100633
+ case 'null':
100634
+ case 'boolean':
100635
+ case 'numeric':
100636
+ case 'string':
100637
+ value = dist_token.value;
100638
+ break
100639
+
100640
+ // This code is unreachable.
100641
+ // default:
100642
+ // throw invalidToken()
100643
+ }
100644
+
100645
+ if (dist_root === undefined) {
100646
+ dist_root = value;
100647
+ } else {
100648
+ const parent = dist_stack[dist_stack.length - 1];
100649
+ if (Array.isArray(parent)) {
100650
+ parent.push(value);
100651
+ } else {
100652
+ Object.defineProperty(parent, dist_key, {
100653
+ value,
100654
+ writable: true,
100655
+ enumerable: true,
100656
+ configurable: true,
100657
+ });
100658
+ }
100659
+ }
100660
+
100661
+ if (value !== null && typeof value === 'object') {
100662
+ dist_stack.push(value);
100663
+
100664
+ if (Array.isArray(value)) {
100665
+ parseState = 'beforeArrayValue';
100666
+ } else {
100667
+ parseState = 'beforePropertyName';
100668
+ }
100669
+ } else {
100670
+ const current = dist_stack[dist_stack.length - 1];
100671
+ if (current == null) {
100672
+ parseState = 'end';
100673
+ } else if (Array.isArray(current)) {
100674
+ parseState = 'afterArrayValue';
100675
+ } else {
100676
+ parseState = 'afterPropertyValue';
100677
+ }
100678
+ }
100679
+ }
100680
+
100681
+ function pop () {
100682
+ dist_stack.pop();
100683
+
100684
+ const current = dist_stack[dist_stack.length - 1];
100685
+ if (current == null) {
100686
+ parseState = 'end';
100687
+ } else if (Array.isArray(current)) {
100688
+ parseState = 'afterArrayValue';
100689
+ } else {
100690
+ parseState = 'afterPropertyValue';
100691
+ }
100692
+ }
100693
+
100694
+ // This code is unreachable.
100695
+ // function invalidParseState () {
100696
+ // return new Error(`JSON5: invalid parse state '${parseState}'`)
100697
+ // }
100698
+
100699
+ // This code is unreachable.
100700
+ // function invalidLexState (state) {
100701
+ // return new Error(`JSON5: invalid lex state '${state}'`)
100702
+ // }
100703
+
100704
+ function invalidChar (c) {
100705
+ if (c === undefined) {
100706
+ return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
100707
+ }
100708
+
100709
+ return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
100710
+ }
100711
+
100712
+ function invalidEOF () {
100713
+ return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
100714
+ }
100715
+
100716
+ // This code is unreachable.
100717
+ // function invalidToken () {
100718
+ // if (token.type === 'eof') {
100719
+ // return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
100720
+ // }
100721
+
100722
+ // const c = String.fromCodePoint(token.value.codePointAt(0))
100723
+ // return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
100724
+ // }
100725
+
100726
+ function invalidIdentifier () {
100727
+ column -= 5;
100728
+ return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`)
100729
+ }
100730
+
100731
+ function separatorChar (c) {
100732
+ console.warn(`JSON5: '${formatChar(c)}' in strings is not valid ECMAScript; consider escaping`);
100733
+ }
100734
+
100735
+ function formatChar (c) {
100736
+ const replacements = {
100737
+ "'": "\\'",
100738
+ '"': '\\"',
100739
+ '\\': '\\\\',
100740
+ '\b': '\\b',
100741
+ '\f': '\\f',
100742
+ '\n': '\\n',
100743
+ '\r': '\\r',
100744
+ '\t': '\\t',
100745
+ '\v': '\\v',
100746
+ '\0': '\\0',
100747
+ '\u2028': '\\u2028',
100748
+ '\u2029': '\\u2029',
100749
+ };
100750
+
100751
+ if (replacements[c]) {
100752
+ return replacements[c]
100753
+ }
100754
+
100755
+ if (c < ' ') {
100756
+ const hexString = c.charCodeAt(0).toString(16);
100757
+ return '\\x' + ('00' + hexString).substring(hexString.length)
100758
+ }
100759
+
100760
+ return c
100761
+ }
100762
+
100763
+ function syntaxError (message) {
100764
+ const err = new SyntaxError(message);
100765
+ err.lineNumber = line;
100766
+ err.columnNumber = column;
100767
+ return err
100768
+ }
100769
+
100770
+ var dist_stringify = function stringify (value, replacer, space) {
100771
+ const stack = [];
100772
+ let indent = '';
100773
+ let propertyList;
100774
+ let replacerFunc;
100775
+ let gap = '';
100776
+ let quote;
100777
+
100778
+ if (
100779
+ replacer != null &&
100780
+ typeof replacer === 'object' &&
100781
+ !Array.isArray(replacer)
100782
+ ) {
100783
+ space = replacer.space;
100784
+ quote = replacer.quote;
100785
+ replacer = replacer.replacer;
100786
+ }
100787
+
100788
+ if (typeof replacer === 'function') {
100789
+ replacerFunc = replacer;
100790
+ } else if (Array.isArray(replacer)) {
100791
+ propertyList = [];
100792
+ for (const v of replacer) {
100793
+ let item;
100794
+
100795
+ if (typeof v === 'string') {
100796
+ item = v;
100797
+ } else if (
100798
+ typeof v === 'number' ||
100799
+ v instanceof String ||
100800
+ v instanceof Number
100801
+ ) {
100802
+ item = String(v);
100803
+ }
100804
+
100805
+ if (item !== undefined && propertyList.indexOf(item) < 0) {
100806
+ propertyList.push(item);
100807
+ }
100808
+ }
100809
+ }
100810
+
100811
+ if (space instanceof Number) {
100812
+ space = Number(space);
100813
+ } else if (space instanceof String) {
100814
+ space = String(space);
100815
+ }
100816
+
100817
+ if (typeof space === 'number') {
100818
+ if (space > 0) {
100819
+ space = Math.min(10, Math.floor(space));
100820
+ gap = ' '.substr(0, space);
100821
+ }
100822
+ } else if (typeof space === 'string') {
100823
+ gap = space.substr(0, 10);
100824
+ }
100825
+
100826
+ return serializeProperty('', {'': value})
100827
+
100828
+ function serializeProperty (key, holder) {
100829
+ let value = holder[key];
100830
+ if (value != null) {
100831
+ if (typeof value.toJSON5 === 'function') {
100832
+ value = value.toJSON5(key);
100833
+ } else if (typeof value.toJSON === 'function') {
100834
+ value = value.toJSON(key);
100835
+ }
100836
+ }
100837
+
100838
+ if (replacerFunc) {
100839
+ value = replacerFunc.call(holder, key, value);
100840
+ }
100841
+
100842
+ if (value instanceof Number) {
100843
+ value = Number(value);
100844
+ } else if (value instanceof String) {
100845
+ value = String(value);
100846
+ } else if (value instanceof Boolean) {
100847
+ value = value.valueOf();
100848
+ }
100849
+
100850
+ switch (value) {
100851
+ case null: return 'null'
100852
+ case true: return 'true'
100853
+ case false: return 'false'
100854
+ }
100855
+
100856
+ if (typeof value === 'string') {
100857
+ return quoteString(value, false)
100858
+ }
100859
+
100860
+ if (typeof value === 'number') {
100861
+ return String(value)
100862
+ }
100863
+
100864
+ if (typeof value === 'object') {
100865
+ return Array.isArray(value) ? serializeArray(value) : serializeObject(value)
100866
+ }
100867
+
100868
+ return undefined
100869
+ }
100870
+
100871
+ function quoteString (value) {
100872
+ const quotes = {
100873
+ "'": 0.1,
100874
+ '"': 0.2,
100875
+ };
100876
+
100877
+ const replacements = {
100878
+ "'": "\\'",
100879
+ '"': '\\"',
100880
+ '\\': '\\\\',
100881
+ '\b': '\\b',
100882
+ '\f': '\\f',
100883
+ '\n': '\\n',
100884
+ '\r': '\\r',
100885
+ '\t': '\\t',
100886
+ '\v': '\\v',
100887
+ '\0': '\\0',
100888
+ '\u2028': '\\u2028',
100889
+ '\u2029': '\\u2029',
100890
+ };
100891
+
100892
+ let product = '';
100893
+
100894
+ for (let i = 0; i < value.length; i++) {
100895
+ const c = value[i];
100896
+ switch (c) {
100897
+ case "'":
100898
+ case '"':
100899
+ quotes[c]++;
100900
+ product += c;
100901
+ continue
100902
+
100903
+ case '\0':
100904
+ if (util.isDigit(value[i + 1])) {
100905
+ product += '\\x00';
100906
+ continue
100907
+ }
100908
+ }
100909
+
100910
+ if (replacements[c]) {
100911
+ product += replacements[c];
100912
+ continue
100913
+ }
100914
+
100915
+ if (c < ' ') {
100916
+ let hexString = c.charCodeAt(0).toString(16);
100917
+ product += '\\x' + ('00' + hexString).substring(hexString.length);
100918
+ continue
100919
+ }
100920
+
100921
+ product += c;
100922
+ }
100923
+
100924
+ const quoteChar = quote || Object.keys(quotes).reduce((a, b) => (quotes[a] < quotes[b]) ? a : b);
100925
+
100926
+ product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar]);
100927
+
100928
+ return quoteChar + product + quoteChar
100929
+ }
100930
+
100931
+ function serializeObject (value) {
100932
+ if (stack.indexOf(value) >= 0) {
100933
+ throw TypeError('Converting circular structure to JSON5')
100934
+ }
100935
+
100936
+ stack.push(value);
100937
+
100938
+ let stepback = indent;
100939
+ indent = indent + gap;
100940
+
100941
+ let keys = propertyList || Object.keys(value);
100942
+ let partial = [];
100943
+ for (const key of keys) {
100944
+ const propertyString = serializeProperty(key, value);
100945
+ if (propertyString !== undefined) {
100946
+ let member = serializeKey(key) + ':';
100947
+ if (gap !== '') {
100948
+ member += ' ';
100949
+ }
100950
+ member += propertyString;
100951
+ partial.push(member);
100952
+ }
100953
+ }
100954
+
100955
+ let final;
100956
+ if (partial.length === 0) {
100957
+ final = '{}';
100958
+ } else {
100959
+ let properties;
100960
+ if (gap === '') {
100961
+ properties = partial.join(',');
100962
+ final = '{' + properties + '}';
100963
+ } else {
100964
+ let separator = ',\n' + indent;
100965
+ properties = partial.join(separator);
100966
+ final = '{\n' + indent + properties + ',\n' + stepback + '}';
100967
+ }
100968
+ }
100969
+
100970
+ stack.pop();
100971
+ indent = stepback;
100972
+ return final
100973
+ }
100974
+
100975
+ function serializeKey (key) {
100976
+ if (key.length === 0) {
100977
+ return quoteString(key, true)
100978
+ }
100979
+
100980
+ const firstChar = String.fromCodePoint(key.codePointAt(0));
100981
+ if (!util.isIdStartChar(firstChar)) {
100982
+ return quoteString(key, true)
100983
+ }
100984
+
100985
+ for (let i = firstChar.length; i < key.length; i++) {
100986
+ if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) {
100987
+ return quoteString(key, true)
100988
+ }
100989
+ }
100990
+
100991
+ return key
100992
+ }
100993
+
100994
+ function serializeArray (value) {
100995
+ if (stack.indexOf(value) >= 0) {
100996
+ throw TypeError('Converting circular structure to JSON5')
100997
+ }
100998
+
100999
+ stack.push(value);
101000
+
101001
+ let stepback = indent;
101002
+ indent = indent + gap;
101003
+
101004
+ let partial = [];
101005
+ for (let i = 0; i < value.length; i++) {
101006
+ const propertyString = serializeProperty(String(i), value);
101007
+ partial.push((propertyString !== undefined) ? propertyString : 'null');
101008
+ }
101009
+
101010
+ let final;
101011
+ if (partial.length === 0) {
101012
+ final = '[]';
101013
+ } else {
101014
+ if (gap === '') {
101015
+ let properties = partial.join(',');
101016
+ final = '[' + properties + ']';
101017
+ } else {
101018
+ let separator = ',\n' + indent;
101019
+ let properties = partial.join(separator);
101020
+ final = '[\n' + indent + properties + ',\n' + stepback + ']';
101021
+ }
101022
+ }
101023
+
101024
+ stack.pop();
101025
+ indent = stepback;
101026
+ return final
101027
+ }
101028
+ };
101029
+
101030
+ const JSON5 = {
101031
+ parse: dist_parse,
101032
+ stringify: dist_stringify,
101033
+ };
101034
+
101035
+ var lib = JSON5;
101036
+
101037
+ /* export default */ const dist = (lib);
101038
+
101039
+ ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/customizationUrlDefaults.ts
101040
+ /**
101041
+ * Policy for the `?customization=` URL query parameter.
101042
+ *
101043
+ * The effective policy comes from the **app config** property
101044
+ * `customizationUrlPrefixes` (NOT a customization — a customization must never
101045
+ * be able to widen its own allowlist). When that property is absent the policy
101046
+ * has no prefixes, so the feature is **off by default**: any `?customization=`
101047
+ * value is rejected because its prefix is not configured.
101048
+ *
101049
+ * Shape:
101050
+ * - prefixes: map of prefix -> base URL used to resolve a customization value
101051
+ * to a fetched `.jsonc` data file. The `default` prefix (no slashes) is used
101052
+ * for values with no leading slash; every other prefix must start and end
101053
+ * with a slash (e.g. `/remote/`) and is matched against the leading
101054
+ * `/segment/` of the value.
101055
+ *
101056
+ * Example app config:
101057
+ * window.config = {
101058
+ * customizationUrlPrefixes: {
101059
+ * default: './customizations/',
101060
+ * '/remote/': 'https://cdn.example.com/ohif-customizations/',
101061
+ * },
101062
+ * };
101063
+ */
101064
+
101065
+ /**
101066
+ * App config property name holding the prefix allowlist. Read directly off
101067
+ * `appConfig` — deliberately not a customization key.
101068
+ */
101069
+ const CUSTOMIZATION_URL_PREFIXES_KEY = 'customizationUrlPrefixes';
101070
+ const DEFAULT_PREFIX = 'default';
101071
+
101072
+ /** Off by default: no prefixes are allowed until the app config configures them. */
101073
+ const customizationUrlDefaults = {
101074
+ prefixes: {}
101075
+ };
101076
+ /* export default */ const CustomizationService_customizationUrlDefaults = ((/* unused pure expression or super */ null && (customizationUrlDefaults)));
101077
+ ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/getUrlCustomizationModulePayload.ts
101078
+ /**
101079
+ * Extracts the phase-tagged payload from a loaded customization module.
101080
+ *
101081
+ * A module is considered to carry a payload when it declares any of the
101082
+ * lifecycle phase blocks (`bootstrap` / `global` / `mode`) or a `requires`
101083
+ * edge. Returns `null` when none are present so callers can warn/skip a module
101084
+ * that does nothing.
101085
+ */
101086
+ function getUrlCustomizationModulePayload(module) {
101087
+ if (!module || typeof module !== 'object') {
101088
+ return null;
101089
+ }
101090
+ const hasBootstrap = isPhaseInput(module.bootstrap);
101091
+ const hasGlobal = isPhaseInput(module.global);
101092
+ const hasMode = module.mode && typeof module.mode === 'object' && !Array.isArray(module.mode);
101093
+ const hasRequires = typeof module.requires === 'string' || Array.isArray(module.requires) && module.requires.length > 0;
101094
+ if (!hasBootstrap && !hasGlobal && !hasMode && !hasRequires) {
101095
+ return null;
101096
+ }
101097
+ return {
101098
+ ...(hasBootstrap ? {
101099
+ bootstrap: module.bootstrap
101100
+ } : {}),
101101
+ ...(hasGlobal ? {
101102
+ global: module.global
101103
+ } : {}),
101104
+ ...(hasMode ? {
101105
+ mode: module.mode
101106
+ } : {}),
101107
+ ...(hasRequires ? {
101108
+ requires: module.requires
101109
+ } : {})
101110
+ };
101111
+ }
101112
+
101113
+ /** A phase block is either an object map or an array of references. */
101114
+ function isPhaseInput(value) {
101115
+ if (Array.isArray(value)) {
101116
+ return value.length > 0;
101117
+ }
101118
+ return Boolean(value) && typeof value === 'object';
101119
+ }
101120
+ ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/validate.ts
101121
+
101122
+ const FULL_URL_REGEX = /^([a-z][a-z0-9+.-]*:|\/\/)/i;
101123
+
101124
+ /**
101125
+ * Fully percent-decode a customization value so validation runs against the
101126
+ * string the URL parser (used by `import()`) ultimately resolves — not the
101127
+ * escaped form. This is what blocks encoded traversal such as `%2e%2e`
101128
+ * (decodes to `..`) or `%2f` (decodes to `/`): the WHATWG URL parser treats
101129
+ * `%2e%2e` as a `..` path segment and would otherwise let a value escape the
101130
+ * configured prefix directory.
101131
+ *
101132
+ * Returns the stable decoded string, or `null` when the value is malformed
101133
+ * (invalid escape), still contains a literal `%` after decoding, or nests
101134
+ * encoding too deeply to settle. Legitimate customization names are plain
101135
+ * identifiers/paths and never need percent-encoding, so rejecting these is safe.
101136
+ */
101137
+ function fullyDecodeValue(value) {
101138
+ let current = value;
101139
+ for (let i = 0; i < 5; i++) {
101140
+ if (!current.includes('%')) {
101141
+ return current;
101142
+ }
101143
+ let decoded;
101144
+ try {
101145
+ decoded = decodeURIComponent(current);
101146
+ } catch {
101147
+ return null;
101148
+ }
101149
+ if (decoded === current) {
101150
+ // Stable but still contains a literal `%`; treat as unsafe.
101151
+ return null;
101152
+ }
101153
+ current = decoded;
101154
+ }
101155
+ return null;
101156
+ }
101157
+ function parseCustomizationParams(params, paramKey = 'customization') {
101158
+ const out = [];
101159
+ const keys = Array.from(new Set(params.keys()));
101160
+ for (const key of keys) {
101161
+ if (key.toLowerCase() !== paramKey.toLowerCase()) {
101162
+ continue;
101163
+ }
101164
+ for (const raw of params.getAll(key)) {
101165
+ if (!raw) continue;
101166
+ for (const piece of raw.split(',')) {
101167
+ const trimmed = piece.trim();
101168
+ if (trimmed) {
101169
+ out.push(trimmed);
101170
+ }
101171
+ }
101172
+ }
101173
+ }
101174
+ return out;
101175
+ }
101176
+
101177
+ /**
101178
+ * Splits a customization value into its prefix and name.
101179
+ *
101180
+ * - A value with **no leading slash** uses the special `default` prefix and the
101181
+ * whole value is the name (e.g. `abc/def` -> prefix `default`, name `abc/def`).
101182
+ * - A value with a **leading slash** is matched against its first `/segment/`,
101183
+ * which becomes the prefix (slashes included), and the remainder is the name
101184
+ * (e.g. `/remote/def` -> prefix `/remote/`, name `def`). This is why every
101185
+ * prefix other than `default` must start and end with a slash.
101186
+ *
101187
+ * Returns `null` when there is no usable name part.
101188
+ */
101189
+ function splitPrefixAndName(value) {
101190
+ if (!value) {
101191
+ return null;
101192
+ }
101193
+ if (!value.startsWith('/')) {
101194
+ return {
101195
+ prefix: DEFAULT_PREFIX,
101196
+ name: value
101197
+ };
101198
+ }
101199
+ const rest = value.slice(1);
101200
+ const slashIdx = rest.indexOf('/');
101201
+ if (slashIdx <= 0) {
101202
+ return null;
101203
+ }
101204
+ const segment = rest.slice(0, slashIdx);
101205
+ const name = rest.slice(slashIdx + 1);
101206
+ if (!segment || !name) {
101207
+ return null;
101208
+ }
101209
+ return {
101210
+ prefix: `/${segment}/`,
101211
+ name
101212
+ };
101213
+ }
101214
+ function buildNormalized(prefix, name) {
101215
+ return prefix === DEFAULT_PREFIX ? `/${DEFAULT_PREFIX}/${name}` : `${prefix}${name}`;
101216
+ }
101217
+ function normalizeCustomizationValue(value) {
101218
+ if (!value) {
101219
+ return null;
101220
+ }
101221
+ const split = splitPrefixAndName(value.trim());
101222
+ if (!split) {
101223
+ return null;
101224
+ }
101225
+ return buildNormalized(split.prefix, split.name);
101226
+ }
101227
+ function hasUnsafeNameSegments(name) {
101228
+ if (!name.trim()) {
101229
+ return true;
101230
+ }
101231
+ return name.split('/').some(seg => !seg || seg === '.' || seg === '..' || seg.includes('..'));
101232
+ }
101233
+ function validateCustomizationRequests(raws, policy) {
101234
+ const result = {
101235
+ valid: [],
101236
+ rejected: []
101237
+ };
101238
+ const prefixes = policy.prefixes || {};
101239
+ for (const raw of raws) {
101240
+ // Validate against the fully decoded value so percent-encoded traversal
101241
+ // (e.g. `%2e%2e`, `%2f`) cannot slip past the checks below and escape the
101242
+ // configured prefix once the URL parser normalizes the import path.
101243
+ const decoded = fullyDecodeValue(raw);
101244
+ if (decoded === null) {
101245
+ result.rejected.push({
101246
+ raw,
101247
+ reason: 'contains malformed or unsupported percent-encoding'
101248
+ });
101249
+ continue;
101250
+ }
101251
+ if (decoded.includes('..')) {
101252
+ result.rejected.push({
101253
+ raw,
101254
+ reason: 'contains ".." traversal segment'
101255
+ });
101256
+ continue;
101257
+ }
101258
+ if (FULL_URL_REGEX.test(decoded)) {
101259
+ result.rejected.push({
101260
+ raw,
101261
+ reason: 'full URLs are not permitted'
101262
+ });
101263
+ continue;
101264
+ }
101265
+ const split = splitPrefixAndName(decoded.trim());
101266
+ if (!split) {
101267
+ result.rejected.push({
101268
+ raw,
101269
+ reason: 'could not be split into a prefix and name'
101270
+ });
101271
+ continue;
101272
+ }
101273
+ const {
101274
+ prefix,
101275
+ name
101276
+ } = split;
101277
+ if (!Object.prototype.hasOwnProperty.call(prefixes, prefix)) {
101278
+ result.rejected.push({
101279
+ raw,
101280
+ reason: `unknown prefix "${prefix}"`
101281
+ });
101282
+ continue;
101283
+ }
101284
+ if (hasUnsafeNameSegments(name)) {
101285
+ result.rejected.push({
101286
+ raw,
101287
+ reason: 'invalid or unsafe customization name'
101288
+ });
101289
+ continue;
101290
+ }
101291
+ result.valid.push({
101292
+ raw,
101293
+ normalized: buildNormalized(prefix, name),
101294
+ prefix,
101295
+ name
101296
+ });
101297
+ }
101298
+ return result;
101299
+ }
101300
+ ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/resolve.ts
101301
+ const ABSOLUTE_URL_REGEX = /^([a-z][a-z0-9+.-]*:|\/\/)/i;
101302
+
101303
+ // Used only to parse same-origin/relative paths into a comparable URL. Any
101304
+ // host works since we compare origin + pathname against the base built the
101305
+ // same way; it is never part of the returned value.
101306
+ const PARSE_BASE = 'https://ohif.invalid';
101307
+ function getViewerPublicUrl() {
101308
+ if (typeof window === 'undefined') {
101309
+ return '/';
101310
+ }
101311
+ return window.PUBLIC_URL || '/';
101312
+ }
101313
+
101314
+ /**
101315
+ * Defense-in-depth containment check on the *final* resolved string. We parse
101316
+ * both the resolved URL and its configured base directory with the same URL
101317
+ * parser that `import()` uses — which collapses `.`/`..`/`%2e%2e` path segments
101318
+ * — and require the result to stay within the base directory. Validation should
101319
+ * already have rejected traversal, but parsing the final string here guarantees
101320
+ * a module can never load outside its allowlisted prefix even if an earlier
101321
+ * check is bypassed.
101322
+ */
101323
+ function assertWithinBase(finalUrl, baseDirUrl, request) {
101324
+ let resolved;
101325
+ let baseDir;
101326
+ try {
101327
+ resolved = new URL(finalUrl, PARSE_BASE);
101328
+ baseDir = new URL(baseDirUrl, PARSE_BASE);
101329
+ } catch {
101330
+ throw new Error(`Customization URL could not be parsed for "${request.raw}"`);
101331
+ }
101332
+ const baseDirPath = baseDir.pathname.endsWith('/') ? baseDir.pathname : `${baseDir.pathname}/`;
101333
+ const within = resolved.origin === baseDir.origin && resolved.pathname.startsWith(baseDirPath);
101334
+ if (!within) {
101335
+ throw new Error(`Customization "${request.raw}" escapes its configured prefix directory`);
101336
+ }
101337
+ }
101338
+ function resolveCustomizationUrl(request, policy) {
101339
+ const prefixes = policy.prefixes || {};
101340
+ const base = prefixes[request.prefix];
101341
+ if (!base) {
101342
+ throw new Error(`Unknown customization prefix: ${request.prefix}`);
101343
+ }
101344
+ if (request.name.includes('..')) {
101345
+ throw new Error(`Customization name contains traversal: ${request.name}`);
101346
+ }
101347
+ const fileName = request.name.endsWith('.jsonc') ? request.name : `${request.name}.jsonc`;
101348
+ const baseWithSlash = base.endsWith('/') ? base : `${base}/`;
101349
+ const joined = `${baseWithSlash}${fileName}`;
101350
+ if (ABSOLUTE_URL_REGEX.test(base)) {
101351
+ assertWithinBase(joined, baseWithSlash, request);
101352
+ return joined;
101353
+ }
101354
+ const origin = typeof window !== 'undefined' && window.location?.origin ? window.location.origin : '';
101355
+ const publicUrl = getViewerPublicUrl();
101356
+ const root = publicUrl?.startsWith('/') ? publicUrl : `/${publicUrl || ''}`;
101357
+ const strip = value => value.startsWith('./') ? value.slice(2) : value.startsWith('/') ? value.slice(1) : value;
101358
+ const relative = strip(joined);
101359
+ const relativeBase = strip(baseWithSlash);
101360
+ const rootWithSlash = root.endsWith('/') ? root : `${root}/`;
101361
+ const path = `${rootWithSlash}${relative}`;
101362
+ const baseDirPath = `${rootWithSlash}${relativeBase}`;
101363
+ const finalUrl = origin ? `${origin}${path}` : path;
101364
+ assertWithinBase(finalUrl, origin ? `${origin}${baseDirPath}` : baseDirPath, request);
101365
+ return finalUrl;
101366
+ }
101367
+ ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/customizationUrl.ts
101368
+
101369
+
101370
+
101371
+
101372
+
101373
+ /**
101374
+ * Builds the `?customization=` policy from the **app config** property
101375
+ * `customizationUrlPrefixes` (read off `extensionManager.appConfig`). This is
101376
+ * intentionally not a customization: customizations can be loaded from the URL,
101377
+ * so letting one define prefixes would let it widen its own allowlist. When the
101378
+ * property is absent the policy has no prefixes and the feature is off.
101379
+ */
101380
+ function getCustomizationUrlPolicy(customizationService) {
101381
+ const prefixes = customizationService?.extensionManager?.appConfig?.[CUSTOMIZATION_URL_PREFIXES_KEY];
101382
+ if (prefixes && typeof prefixes === 'object') {
101383
+ return {
101384
+ prefixes
101385
+ };
101386
+ }
101387
+ return customizationUrlDefaults;
101388
+ }
101389
+
99560
101390
  ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/CustomizationService.ts
99561
101391
  var _CustomizationService;
99562
101392
 
99563
101393
 
101394
+
101395
+
101396
+
101397
+
101398
+
101399
+ /**
101400
+ * Reserved key in a `mode` phase block for the "general" customizations that
101401
+ * apply to every mode. The general block is applied FIRST on each mode enter;
101402
+ * a block keyed by the entered mode's id / routeName is applied after it so a
101403
+ * single mode can override the general values.
101404
+ */
101405
+ const GENERAL_MODE_KEY = '*';
99564
101406
  const CustomizationService_EVENTS = {
99565
101407
  MODE_CUSTOMIZATION_MODIFIED: 'event::CustomizationService:modeModified',
99566
101408
  GLOBAL_CUSTOMIZATION_MODIFIED: 'event::CustomizationService:globalModified',
@@ -99583,7 +101425,8 @@ let CustomizationService_CustomizationScope = /*#__PURE__*/function (Customizati
99583
101425
  CustomizationScope["Mode"] = "mode";
99584
101426
  /**
99585
101427
  * Default customizations that serve as fallbacks when no global or mode-specific
99586
- * customizations are defined. These can only be defined once.
101428
+ * customizations are defined. These are not cleared when the service re-inits
101429
+ * for a mode change; only Mode scope is reset.
99587
101430
  */
99588
101431
  CustomizationScope["Default"] = "default";
99589
101432
  return CustomizationScope;
@@ -99638,10 +101481,9 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99638
101481
  */
99639
101482
  this.modeCustomizations = new Map();
99640
101483
  /**
99641
- * A collection of default customizations used as fallbacks. These serve as
99642
- * the base configuration and are registered at setup. Default customizations
99643
- * provide baseline values that can be overridden by mode or global customizations.
99644
- * Use these for cases where default values are necessary for predictable behavior.
101484
+ * A collection of default customizations used as fallbacks. Entries are merged
101485
+ * over time (including from `init()` re-reading extension default modules) and
101486
+ * are not cleared on mode change. Mode and Global scopes override these values.
99645
101487
  */
99646
101488
  this.defaultCustomizations = new Map();
99647
101489
  /**
@@ -99650,43 +101492,285 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99650
101492
  */
99651
101493
  this.transformedCustomizations = new Map();
99652
101494
  this.configuration = void 0;
101495
+ /**
101496
+ * URL customization modules already imported and applied (key = normalized `/prefix/name`).
101497
+ * Entries are kept for the lifetime of the page: repeated loads skip imports, and the app
101498
+ * normally applies `?customization=` only at bootstrap (see {@link applyWindowUrlCustomizations}).
101499
+ */
101500
+ this._urlCustomizationLoaded = new Map();
101501
+ this._urlCustomizationPending = new Map();
101502
+ /**
101503
+ * Every URL customization module resolved this page session, in load order
101504
+ * (dependencies before dependents). The lifecycle phase appliers
101505
+ * ({@link applyBootstrapCustomizations}, {@link applyGlobalCustomizations},
101506
+ * {@link applyModeCustomizations}) iterate this list so a module's phase
101507
+ * blocks are applied at the right time regardless of when it was fetched.
101508
+ */
101509
+ this._resolvedUrlModules = [];
101510
+ /**
101511
+ * Normalized form of `appConfig.customizationService`. Either a phase-tagged
101512
+ * config ({@link PhasedCustomizationConfig}) or, for the legacy array/object
101513
+ * form, the references to add (Global) during {@link init}.
101514
+ */
101515
+ this._customizationConfig = null;
101516
+ /** Id/aliases of the mode currently entered, used to re-apply mode phase blocks. */
101517
+ this._currentModeIds = [];
101518
+ /**
101519
+ * Extension module entry ids (e.g. `${extensionId}.customizationModule.default`) whose
101520
+ * default/global payloads have already been merged via {@link init}. Matches the URL
101521
+ * loader pattern: repeated {@link init} skips work for the same slot so immutability-style
101522
+ * merges are not applied twice. A slot is recorded only after a module was present and applied;
101523
+ * if a module appears only on a later {@link init} (e.g. a newly registered extension), it is merged then.
101524
+ */
101525
+ this._extensionCustomizationModuleApplied = new Set();
99653
101526
  this.configuration = configuration;
99654
101527
  this.commandsManager = commandsManager;
99655
101528
  }
101529
+
101530
+ // ===========================================================================
101531
+ // Public API
101532
+ // ===========================================================================
101533
+
101534
+ /**
101535
+ * Clears mode customizations and merges each extension's `customizationModule.default` /
101536
+ * `customizationModule.global` into the service. Safe to call multiple times (e.g. from
101537
+ * {@link onModeEnter}): each extension module slot is merged at most once per page session,
101538
+ * matching the deduplication pattern used for URL-loaded modules in {@link requires}.
101539
+ * Slots with no module yet are left unmarked so a later call can merge when the module appears.
101540
+ */
99656
101541
  init(extensionManager) {
99657
101542
  this.extensionManager = extensionManager;
99658
- // Clear defaults as those are defined by the customization modules
99659
- this.defaultCustomizations.clear();
99660
- // Clear modes because those are defined in onModeEnter functions.
101543
+ // Mode customizations are defined per mode in onModeEnter; reset them here.
101544
+ // Default customizations are not cleared — they are merged again from
101545
+ // extension modules below so definitions stay available across mode changes.
99661
101546
  this.modeCustomizations.clear();
99662
101547
  this.extensionManager.getRegisteredExtensionIds().forEach(extensionId => {
99663
101548
  const keyDefault = `${extensionId}.customizationModule.default`;
99664
- const defaultCustomizations = this._findExtensionValue(keyDefault);
99665
- if (defaultCustomizations) {
99666
- const {
99667
- value
99668
- } = defaultCustomizations;
99669
- this._addReference(value, CustomizationService_CustomizationScope.Default);
101549
+ if (!this._extensionCustomizationModuleApplied.has(keyDefault)) {
101550
+ const defaultCustomizations = this._findExtensionValue(keyDefault);
101551
+ if (defaultCustomizations) {
101552
+ const {
101553
+ value
101554
+ } = defaultCustomizations;
101555
+ this._addReference(value, CustomizationService_CustomizationScope.Default);
101556
+ this._extensionCustomizationModuleApplied.add(keyDefault);
101557
+ }
99670
101558
  }
99671
101559
  const keyGlobal = `${extensionId}.customizationModule.global`;
99672
- const globalCustomizations = this._findExtensionValue(keyGlobal);
99673
- if (globalCustomizations) {
99674
- const {
99675
- value
99676
- } = globalCustomizations;
99677
- this._addReference(value, CustomizationService_CustomizationScope.Global);
101560
+ if (!this._extensionCustomizationModuleApplied.has(keyGlobal)) {
101561
+ const globalCustomizations = this._findExtensionValue(keyGlobal);
101562
+ if (globalCustomizations) {
101563
+ const {
101564
+ value
101565
+ } = globalCustomizations;
101566
+ this._addReference(value, CustomizationService_CustomizationScope.Global);
101567
+ this._extensionCustomizationModuleApplied.add(keyGlobal);
101568
+ }
99678
101569
  }
99679
101570
  });
99680
101571
 
99681
- // Only add references for the configuration once.
99682
- if (!this.configuration?._hasBeenAdded) {
99683
- this.addReferences(this.configuration);
101572
+ // Only add references for the configuration once. The phase-tagged config
101573
+ // form (bootstrap/global/mode) is applied by the lifecycle appliers
101574
+ // instead, so only the legacy array/object form is added here as Global.
101575
+ const config = this._getCustomizationConfig();
101576
+ if (config.legacyReferences !== undefined && !this.configuration?._hasBeenAdded) {
101577
+ this.addReferences(config.legacyReferences);
99684
101578
  Object.defineProperty(this.configuration, '_hasBeenAdded', {
99685
101579
  value: true,
99686
101580
  writable: false
99687
101581
  });
99688
101582
  }
99689
101583
  }
101584
+
101585
+ /**
101586
+ * Memoized, normalized view of `appConfig.customizationService`. Detects the
101587
+ * phase-tagged form (any of `requires` / `bootstrap` / `global` / `mode`)
101588
+ * and otherwise treats the value as legacy Global references.
101589
+ */
101590
+ _getCustomizationConfig() {
101591
+ if (!this._customizationConfig) {
101592
+ this._customizationConfig = normalizeCustomizationConfig(this.configuration);
101593
+ }
101594
+ return this._customizationConfig;
101595
+ }
101596
+
101597
+ /**
101598
+ * Loads and applies `?customization=` modules from `window.location.search`.
101599
+ *
101600
+ * **Throws on disallowed values.** A `?customization=` value whose prefix is
101601
+ * not in `appConfig.customizationUrlPrefixes` (the default — the feature is off
101602
+ * until prefixes are configured) rejects this promise, which by design aborts
101603
+ * app bootstrap rather than silently ignoring the request.
101604
+ *
101605
+ * **Intended SPA behavior:** The shell typically calls this once during startup. It does not
101606
+ * run again on client-side route changes. The query key `customization` may still appear in
101607
+ * URLs (for example preserved by worklist navigation) without implying that modules are
101608
+ * re-evaluated on every navigation. Modules resolved here are also deduplicated by normalized
101609
+ * URL for the lifetime of the page in {@link requires}. To pick up a different `?customization=`
101610
+ * set, use a full page load or call {@link applyCustomizationUrlSearchParams} /
101611
+ * {@link requires} from your own integration code when appropriate.
101612
+ *
101613
+ * **What is loaded:** Each `?customization=` entry resolves to a JSONC file (JSON with
101614
+ * comments / trailing commas) under a configured prefix directory. The file is fetched and
101615
+ * parsed as **data** — it is never executed. Executable code (plugins, modes, extensions)
101616
+ * loads only through `pluginConfig.json`, never from the customization URL path. A module's
101617
+ * `global` payload is applied as global customizations and its `requires` are loaded first.
101618
+ */
101619
+ async applyWindowUrlCustomizations(overrides) {
101620
+ if (typeof window === 'undefined') {
101621
+ return;
101622
+ }
101623
+ await this.applyCustomizationUrlSearchParams(new URLSearchParams(window.location.search), overrides);
101624
+ }
101625
+
101626
+ /**
101627
+ * Parses `?customization=` values from the search string and delegates to
101628
+ * {@link requires}.
101629
+ */
101630
+ async applyCustomizationUrlSearchParams(params, overrides) {
101631
+ const raws = parseCustomizationParams(params);
101632
+ if (!raws.length) {
101633
+ return;
101634
+ }
101635
+ await this.requires(raws, overrides);
101636
+ }
101637
+
101638
+ /**
101639
+ * Depth-first dynamic import of URL customization modules
101640
+ * `requires` edges and `customization` field
101641
+ * references are loaded before dependents. Already-loaded modules (same normalized key) are
101642
+ * skipped for the rest of the page session; they are not unloaded when the address bar changes.
101643
+ *
101644
+ * Invalid query entries, resolve failures, failed imports, and modules without a
101645
+ * customization payload are warned and skipped.
101646
+ */
101647
+ requires(names, overrides) {
101648
+ return this.loadCustomizationModules(names, overrides).then(newlyLoaded => {
101649
+ // Back-compat: a direct `requires()` / `applyWindowUrlCustomizations()`
101650
+ // call applies the `global` slice immediately. The `bootstrap` and
101651
+ // `mode` phases are driven by the boot orchestration
101652
+ // ({@link loadAndApplyBootstrapCustomizations}) and {@link onModeEnter}.
101653
+ this._applyLoadedUrlCustomizationModules(newlyLoaded);
101654
+ return newlyLoaded;
101655
+ });
101656
+ }
101657
+
101658
+ /**
101659
+ * Resolves (fetches + parses) the given URL customization modules and their
101660
+ * `requires` dependencies depth-first, WITHOUT applying any phase block.
101661
+ * Newly resolved modules are appended to {@link _resolvedUrlModules} in load
101662
+ * order so the lifecycle appliers can apply each phase at the right time.
101663
+ *
101664
+ * Rejects (aborting the load) when any entry is disallowed by the policy.
101665
+ */
101666
+ loadCustomizationModules(names, overrides) {
101667
+ const policy = overrides?.policy ?? getCustomizationUrlPolicy(this);
101668
+ const list = (Array.isArray(names) ? names : [names]).map(s => String(s).trim()).filter(Boolean);
101669
+ if (!list.length) {
101670
+ return Promise.resolve([]);
101671
+ }
101672
+ const {
101673
+ valid,
101674
+ rejected
101675
+ } = validateCustomizationRequests(list, policy);
101676
+ const logger = overrides?.logger || console;
101677
+ // A `?customization=` value that is not allowed by the configured prefixes is
101678
+ // a hard error: stop the load and let it propagate. The feature is off until
101679
+ // `appConfig.customizationUrlPrefixes` allows a prefix, so on a default build
101680
+ // any `?customization=` value throws here rather than being silently ignored.
101681
+ if (rejected.length) {
101682
+ const details = rejected.map(r => `"${r.raw}" (${r.reason})`).join('; ');
101683
+ return Promise.reject(new Error(`[customizationUrl] refusing to load customization(s): ${details}. ` + `Allowed prefixes are configured in appConfig.customizationUrlPrefixes.`));
101684
+ }
101685
+ if (!valid.length) {
101686
+ return Promise.resolve([]);
101687
+ }
101688
+ const importFn = overrides?.importFn ?? this._urlDefaultImport.bind(this);
101689
+ const requestedSet = new Set();
101690
+ const newlyLoaded = [];
101691
+ return valid.reduce((prev, request) => prev.then(() => this._urlCustomizationLoadOne(request, policy, importFn, logger, requestedSet, newlyLoaded)), Promise.resolve()).then(() => {
101692
+ this._resolvedUrlModules.push(...newlyLoaded);
101693
+ return newlyLoaded;
101694
+ });
101695
+ }
101696
+
101697
+ /**
101698
+ * Boot-time entry point that runs BEFORE extensions are registered. It:
101699
+ * 1. records the ExtensionManager (so the URL policy / appConfig is readable),
101700
+ * 2. resolves every customization module requested via the
101701
+ * `appConfig.customizationService.requires` list and the `?customization=`
101702
+ * URL parameter (their data is fetched once, up front — long before any
101703
+ * mode loads), and
101704
+ * 3. applies the `bootstrap` phase blocks.
101705
+ *
101706
+ * Rejects (aborting bootstrap) if a `?customization=` value is disallowed.
101707
+ */
101708
+ async loadAndApplyBootstrapCustomizations(extensionManager, overrides) {
101709
+ this.extensionManager = extensionManager;
101710
+ const config = this._getCustomizationConfig();
101711
+ const names = [];
101712
+ const requires = config.phased?.requires;
101713
+ if (typeof requires === 'string' && requires) {
101714
+ names.push(requires);
101715
+ } else if (Array.isArray(requires)) {
101716
+ names.push(...requires.filter(name => typeof name === 'string' && name));
101717
+ }
101718
+ if (typeof window !== 'undefined') {
101719
+ names.push(...parseCustomizationParams(new URLSearchParams(window.location.search)));
101720
+ }
101721
+ if (names.length) {
101722
+ await this.loadCustomizationModules(names, overrides);
101723
+ }
101724
+ this.applyBootstrapCustomizations();
101725
+ }
101726
+
101727
+ /**
101728
+ * Applies the `bootstrap` phase (Global scope) of the structured app config
101729
+ * and every resolved URL module. App-config blocks apply first so URL modules
101730
+ * layer on top.
101731
+ */
101732
+ applyBootstrapCustomizations() {
101733
+ this._applyPhase('bootstrap');
101734
+ }
101735
+
101736
+ /**
101737
+ * Applies the `global` phase (Global scope) of the structured app config and
101738
+ * every resolved URL module. Call after {@link init} so extension default /
101739
+ * global customizations are already in place for `$apply`-style merges.
101740
+ */
101741
+ applyGlobalCustomizations() {
101742
+ this._applyPhase('global');
101743
+ }
101744
+
101745
+ /**
101746
+ * Applies the `mode` phase (Mode scope) for the entered mode. The general
101747
+ * block (`*`) is applied FIRST, then any block keyed by one of `modeIds`
101748
+ * (the mode's id / routeName), so a single mode can override the general
101749
+ * values. Call this AFTER `customizationService.onModeEnter()` has reset the
101750
+ * mode scope (i.e. after `extensionManager.onModeEnter()`).
101751
+ */
101752
+ applyModeCustomizations(modeIds) {
101753
+ const ids = (Array.isArray(modeIds) ? modeIds : [modeIds]).filter(Boolean);
101754
+ this._currentModeIds = ids;
101755
+ const blocks = this._collectPhaseBlocks('mode');
101756
+
101757
+ // General first, for every source.
101758
+ for (const block of blocks) {
101759
+ const general = block.mode?.[GENERAL_MODE_KEY];
101760
+ if (general) {
101761
+ this.setCustomizations(general, CustomizationService_CustomizationScope.Mode);
101762
+ }
101763
+ }
101764
+ // Then mode-specific, for every source.
101765
+ for (const block of blocks) {
101766
+ for (const id of ids) {
101767
+ const specific = block.mode?.[id];
101768
+ if (specific) {
101769
+ this.setCustomizations(specific, CustomizationService_CustomizationScope.Mode);
101770
+ }
101771
+ }
101772
+ }
101773
+ }
99690
101774
  onModeEnter() {
99691
101775
  this.clearTransformedCustomizations();
99692
101776
  this.init(this.extensionManager);
@@ -99694,14 +101778,6 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99694
101778
  onModeExit() {
99695
101779
  this.clearTransformedCustomizations();
99696
101780
  }
99697
- clearTransformedCustomizations() {
99698
- super.reset();
99699
- const modeCustomizationKeys = Array.from(this.modeCustomizations.keys());
99700
- for (const key of modeCustomizationKeys) {
99701
- this.transformedCustomizations.delete(key);
99702
- }
99703
- this.modeCustomizations.clear();
99704
- }
99705
101781
 
99706
101782
  /**
99707
101783
  * Unified getter for customizations.
@@ -99724,6 +101800,14 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99724
101800
  return newTransformed;
99725
101801
  }
99726
101802
 
101803
+ /**
101804
+ * Returns a customization value, or the provided fallback when unset.
101805
+ */
101806
+ getValue(customizationId, fallbackValue) {
101807
+ const value = this.getCustomization(customizationId);
101808
+ return value === undefined ? fallbackValue : value;
101809
+ }
101810
+
99727
101811
  /**
99728
101812
  * Takes an object with multiple properties, each property containing
99729
101813
  * immutability-helper commands, and applies them one by one.
@@ -99760,30 +101844,6 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99760
101844
  this._setCustomization(customizationId, customization, scope);
99761
101845
  }
99762
101846
 
99763
- /**
99764
- * Internal method to set a single customization
99765
- */
99766
- _setCustomization(customizationId, customization, scope = CustomizationService_CustomizationScope.Mode) {
99767
- // if (typeof customization === 'string') {
99768
- // const extensionValue = this._findExtensionValue(customization);
99769
- // customization = extensionValue.value;
99770
- // }
99771
-
99772
- switch (scope) {
99773
- case CustomizationService_CustomizationScope.Global:
99774
- this.setGlobalCustomization(customizationId, customization);
99775
- break;
99776
- case CustomizationService_CustomizationScope.Mode:
99777
- this.setModeCustomization(customizationId, customization);
99778
- break;
99779
- case CustomizationService_CustomizationScope.Default:
99780
- this.setDefaultCustomization(customizationId, customization);
99781
- break;
99782
- default:
99783
- throw new Error(`Invalid customization scope: ${scope}`);
99784
- }
99785
- }
99786
-
99787
101847
  /**
99788
101848
  * Gets all customizations for a given scope.
99789
101849
  *
@@ -99830,6 +101890,249 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99830
101890
  return result.$transform?.(this) || result;
99831
101891
  }
99832
101892
 
101893
+ /**
101894
+ * Registers a custom command to be used in customization updates.
101895
+ * @param commandName - The name of the command (without the $ prefix)
101896
+ * it will be prefixed with $
101897
+ * @param handler - Function that handles the command it receives the value and the original value
101898
+ */
101899
+ registerCustomUpdateCommand(commandName, handler) {
101900
+ if (!commandName.startsWith('$')) {
101901
+ commandName = '$' + commandName;
101902
+ }
101903
+ (0,immutability_helper.extend)(commandName, handler);
101904
+ }
101905
+ _addReference(value, type = CustomizationService_CustomizationScope.Global) {
101906
+ if (!value) {
101907
+ return;
101908
+ }
101909
+ if (typeof value === 'string') {
101910
+ const extensionValue = this._findExtensionValue(value);
101911
+ value = extensionValue.value;
101912
+ }
101913
+ Object.entries(value).forEach(([id, customization]) => {
101914
+ const setName = type === CustomizationService_CustomizationScope.Global && 'setGlobalCustomization' || type === CustomizationService_CustomizationScope.Default && 'setDefaultCustomization' || 'setModeCustomization';
101915
+ this[setName](id, customization);
101916
+ });
101917
+ }
101918
+
101919
+ /**
101920
+ * Customizations can be specified as an array of strings or customizations,
101921
+ * or as an object whose key is the reference id, and the value is the string
101922
+ * or customization.
101923
+ */
101924
+ addReferences(references, type = CustomizationService_CustomizationScope.Global) {
101925
+ if (!references) {
101926
+ return;
101927
+ }
101928
+ if (Array.isArray(references)) {
101929
+ references.forEach(item => {
101930
+ this._addReference(item, type);
101931
+ });
101932
+ } else {
101933
+ this._addReference(references, type);
101934
+ }
101935
+ }
101936
+
101937
+ // ===========================================================================
101938
+ // Private methods
101939
+ // ===========================================================================
101940
+
101941
+ clearTransformedCustomizations() {
101942
+ super.reset();
101943
+ const modeCustomizationKeys = Array.from(this.modeCustomizations.keys());
101944
+ for (const key of modeCustomizationKeys) {
101945
+ this.transformedCustomizations.delete(key);
101946
+ }
101947
+ this.modeCustomizations.clear();
101948
+ }
101949
+
101950
+ /**
101951
+ * Default loader for a `?customization=` module. Customization files are
101952
+ * **data**, not code: the file is fetched and parsed as JSONC (JSON with
101953
+ * comments / trailing commas, via JSON5 which is a superset). It is never
101954
+ * executed. Executable modules — plugins, modes and extensions — load only
101955
+ * through `pluginConfig.json`, never from the customization URL path.
101956
+ */
101957
+ async _urlDefaultImport(url) {
101958
+ if (typeof fetch !== 'function') {
101959
+ throw new Error(`No fetch implementation available to load customization ${url}`);
101960
+ }
101961
+ const response = await fetch(url);
101962
+ if (!response.ok) {
101963
+ throw new Error(`Failed to fetch customization ${url}: ${response.status} ${response.statusText}`);
101964
+ }
101965
+ const text = await response.text();
101966
+ return dist.parse(text);
101967
+ }
101968
+ _normalizeImportedCustomizationModule(imported) {
101969
+ return imported && typeof imported === 'object' && 'customizations' in imported ? imported : imported && typeof imported.default === 'object' ? imported.default : imported;
101970
+ }
101971
+ _collectUrlDependencyRefs(module) {
101972
+ const refs = new Set();
101973
+ const payload = getUrlCustomizationModulePayload(module);
101974
+ if (!payload || typeof payload !== 'object') {
101975
+ return Array.from(refs);
101976
+ }
101977
+ const moduleRequires = payload.requires;
101978
+ if (typeof moduleRequires === 'string' && moduleRequires) {
101979
+ refs.add(moduleRequires);
101980
+ } else if (Array.isArray(moduleRequires)) {
101981
+ for (const id of moduleRequires) {
101982
+ if (typeof id === 'string' && id) {
101983
+ refs.add(id);
101984
+ }
101985
+ }
101986
+ }
101987
+ return Array.from(refs);
101988
+ }
101989
+ _urlDependencyToRequest(name, policy) {
101990
+ // `requires` entries are module names to load; each is validated/resolved like any
101991
+ // other URL customization request. Entries that don't resolve to a valid module
101992
+ // (e.g. a bare customization-key reference) are rejected by validation and
101993
+ // skipped — there is no namespace carve-out.
101994
+ const result = validateCustomizationRequests([name], policy);
101995
+ if (result.valid.length) {
101996
+ return result.valid[0];
101997
+ }
101998
+ return null;
101999
+ }
102000
+ _urlCustomizationLoadOne(request, policy, importFn, logger, requestedSet, newlyLoaded) {
102001
+ const key = request.normalized;
102002
+ if (this._urlCustomizationLoaded.has(key)) {
102003
+ return Promise.resolve(this._urlCustomizationLoaded.get(key) || null);
102004
+ }
102005
+ if (this._urlCustomizationPending.has(key)) {
102006
+ return this._urlCustomizationPending.get(key);
102007
+ }
102008
+ requestedSet.add(key);
102009
+ const promise = this._urlCustomizationLoadOneBody(request, policy, importFn, logger, requestedSet, newlyLoaded);
102010
+ this._urlCustomizationPending.set(key, promise);
102011
+ // Use then(success, failure) for cleanup — `finally` left rejections unhandled
102012
+ // with the current Promise polyfill in the Jest/Node test stack.
102013
+ promise.then(() => this._urlCustomizationPending.delete(key), () => this._urlCustomizationPending.delete(key));
102014
+ return promise;
102015
+ }
102016
+ _urlCustomizationLoadOneBody(request, policy, importFn, logger, requestedSet, newlyLoaded) {
102017
+ const key = request.normalized;
102018
+ const importFailedSentinel = Symbol('importFailed');
102019
+ let url;
102020
+ try {
102021
+ url = resolveCustomizationUrl(request, policy);
102022
+ } catch (err) {
102023
+ const msg = `[customizationUrl] failed to resolve "${request.raw}": ${err.message}`;
102024
+ logger.warn(msg);
102025
+ return Promise.resolve(null);
102026
+ }
102027
+ return importFn(url).catch(err => {
102028
+ logger.warn(`[customizationUrl] failed to import customization "${request.raw}" (${url})`, err);
102029
+ return importFailedSentinel;
102030
+ }).then(importedOrSentinel => {
102031
+ if (importedOrSentinel === importFailedSentinel) {
102032
+ return null;
102033
+ }
102034
+ const imported = importedOrSentinel;
102035
+ const module = this._normalizeImportedCustomizationModule(imported);
102036
+ if (!module || typeof module !== 'object') {
102037
+ const msg = `[customizationUrl] missing customization module "${request.raw}" (${url}): module is not an object`;
102038
+ logger.warn(msg);
102039
+ return null;
102040
+ }
102041
+ if (!getUrlCustomizationModulePayload(module)) {
102042
+ const msg = `[customizationUrl] missing customization module "${request.raw}" (${url}): no customizations payload`;
102043
+ logger.warn(msg);
102044
+ return null;
102045
+ }
102046
+ const depRefs = this._collectUrlDependencyRefs(module);
102047
+ let depsChain = Promise.resolve();
102048
+ for (const depRef of depRefs) {
102049
+ depsChain = depsChain.then(() => {
102050
+ const depRequest = this._urlDependencyToRequest(depRef, policy);
102051
+ if (!depRequest || requestedSet.has(depRequest.normalized)) {
102052
+ return undefined;
102053
+ }
102054
+ return this._urlCustomizationLoadOne(depRequest, policy, importFn, logger, requestedSet, newlyLoaded);
102055
+ });
102056
+ }
102057
+ return depsChain.then(() => {
102058
+ const loaded = {
102059
+ request,
102060
+ module,
102061
+ url
102062
+ };
102063
+ this._urlCustomizationLoaded.set(key, loaded);
102064
+ newlyLoaded.push(loaded);
102065
+ return loaded;
102066
+ });
102067
+ });
102068
+ }
102069
+ _applyLoadedUrlCustomizationModules(loaded) {
102070
+ if (!loaded?.length) {
102071
+ return;
102072
+ }
102073
+ for (const entry of loaded) {
102074
+ const payload = getUrlCustomizationModulePayload(entry.module);
102075
+ if (payload?.global) {
102076
+ this.setCustomizations(payload.global, CustomizationService_CustomizationScope.Global);
102077
+ }
102078
+ }
102079
+ }
102080
+
102081
+ /**
102082
+ * Collects the phase blocks for `phase` from every source, in apply order:
102083
+ * the structured app config first, then each resolved URL module in load
102084
+ * order. Used by {@link applyModeCustomizations}; the simpler `bootstrap` /
102085
+ * `global` phases go through {@link _applyPhase}.
102086
+ */
102087
+ _collectPhaseBlocks(phase) {
102088
+ const blocks = [];
102089
+ const phased = this._getCustomizationConfig().phased;
102090
+ if (phased && phased[phase] !== undefined) {
102091
+ blocks.push(phased);
102092
+ }
102093
+ for (const entry of this._resolvedUrlModules) {
102094
+ const payload = getUrlCustomizationModulePayload(entry.module);
102095
+ if (payload && payload[phase] !== undefined) {
102096
+ blocks.push(payload);
102097
+ }
102098
+ }
102099
+ return blocks;
102100
+ }
102101
+
102102
+ /** Applies a Global-scoped phase (`bootstrap` / `global`) from all sources. */
102103
+ _applyPhase(phase) {
102104
+ for (const block of this._collectPhaseBlocks(phase)) {
102105
+ const value = block[phase];
102106
+ if (value) {
102107
+ this.setCustomizations(value, CustomizationService_CustomizationScope.Global);
102108
+ }
102109
+ }
102110
+ }
102111
+
102112
+ /**
102113
+ * Internal method to set a single customization
102114
+ */
102115
+ _setCustomization(customizationId, customization, scope = CustomizationService_CustomizationScope.Mode) {
102116
+ // if (typeof customization === 'string') {
102117
+ // const extensionValue = this._findExtensionValue(customization);
102118
+ // customization = extensionValue.value;
102119
+ // }
102120
+
102121
+ switch (scope) {
102122
+ case CustomizationService_CustomizationScope.Global:
102123
+ this.setGlobalCustomization(customizationId, customization);
102124
+ break;
102125
+ case CustomizationService_CustomizationScope.Mode:
102126
+ this.setModeCustomization(customizationId, customization);
102127
+ break;
102128
+ case CustomizationService_CustomizationScope.Default:
102129
+ this.setDefaultCustomization(customizationId, customization);
102130
+ break;
102131
+ default:
102132
+ throw new Error(`Invalid customization scope: ${scope}`);
102133
+ }
102134
+ }
102135
+
99833
102136
  /**
99834
102137
  *
99835
102138
  * Sets a mode-specific customization.
@@ -99860,14 +102163,15 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99860
102163
  this.globalCustomizations.set(id, this._update(sourceCustomization, value));
99861
102164
  this.transformedCustomizations.clear();
99862
102165
  this._broadcastEvent(this.EVENTS.GLOBAL_CUSTOMIZATION_MODIFIED, {
99863
- buttons: this.defaultCustomizations,
99864
- button: this.defaultCustomizations.get(id)
102166
+ buttons: this.globalCustomizations,
102167
+ button: this.globalCustomizations.get(id)
99865
102168
  });
99866
102169
  }
99867
102170
  setDefaultCustomization(id, value) {
99868
- if (this.defaultCustomizations.has(id)) {
99869
- console.warn(`Trying to update existing default for customization ${id}`);
99870
- }
102171
+ // There are two inits now, without a clear between them, so we can't warn about existing defaults
102172
+ // if (this.defaultCustomizations.has(id)) {
102173
+ // console.warn(`Trying to update existing default for customization ${id}`);
102174
+ // }
99871
102175
  this.transformedCustomizations.clear();
99872
102176
  const sourceCustomization = this.defaultCustomizations.get(id);
99873
102177
  this.defaultCustomizations.set(id, this._update(sourceCustomization, value));
@@ -99881,19 +102185,6 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99881
102185
  return entry;
99882
102186
  }
99883
102187
 
99884
- /**
99885
- * Registers a custom command to be used in customization updates.
99886
- * @param commandName - The name of the command (without the $ prefix)
99887
- * it will be prefixed with $
99888
- * @param handler - Function that handles the command it receives the value and the original value
99889
- */
99890
- registerCustomUpdateCommand(commandName, handler) {
99891
- if (!commandName.startsWith('$')) {
99892
- commandName = '$' + commandName;
99893
- }
99894
- (0,immutability_helper.extend)(commandName, handler);
99895
- }
99896
-
99897
102188
  /**
99898
102189
  * Uses immutability-helper to apply the user's commands (e.g. $set, $push, $apply, etc.)
99899
102190
  * Takes into account the 'mergeType' if it's explicitly 'Replace'; otherwise does a normal update.
@@ -99927,37 +102218,6 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
99927
102218
  ...value
99928
102219
  };
99929
102220
  }
99930
- _addReference(value, type = CustomizationService_CustomizationScope.Global) {
99931
- if (!value) {
99932
- return;
99933
- }
99934
- if (typeof value === 'string') {
99935
- const extensionValue = this._findExtensionValue(value);
99936
- value = extensionValue.value;
99937
- }
99938
- Object.entries(value).forEach(([id, customization]) => {
99939
- const setName = type === CustomizationService_CustomizationScope.Global && 'setGlobalCustomization' || type === CustomizationService_CustomizationScope.Default && 'setDefaultCustomization' || 'setModeCustomization';
99940
- this[setName](id, customization);
99941
- });
99942
- }
99943
-
99944
- /**
99945
- * Customizations can be specified as an array of strings or customizations,
99946
- * or as an object whose key is the reference id, and the value is the string
99947
- * or customization.
99948
- */
99949
- addReferences(references, type = CustomizationService_CustomizationScope.Global) {
99950
- if (!references) {
99951
- return;
99952
- }
99953
- if (Array.isArray(references)) {
99954
- references.forEach(item => {
99955
- this._addReference(item, type);
99956
- });
99957
- } else {
99958
- this._addReference(references, type);
99959
- }
99960
- }
99961
102221
  }
99962
102222
 
99963
102223
  /** Add custom $filter command */
@@ -100048,6 +102308,45 @@ CustomizationService.REGISTRATION = {
100048
102308
  }
100049
102309
  return deepFilter(original, query);
100050
102310
  });
102311
+ const PHASE_CONFIG_KEYS = ['requires', 'bootstrap', 'global', 'mode'];
102312
+
102313
+ /**
102314
+ * Normalizes `appConfig.customizationService` into either:
102315
+ * - `{ phased }` — the structured, phase-tagged config, detected by
102316
+ * the presence of any of `requires` / `bootstrap`
102317
+ * / `global` / `mode`; or
102318
+ * - `{ legacyReferences }` — the legacy array / object-map form, which is
102319
+ * added (Global scope) during `init()` exactly as
102320
+ * before.
102321
+ */
102322
+ function normalizeCustomizationConfig(configuration) {
102323
+ if (!configuration) {
102324
+ return {};
102325
+ }
102326
+ if (Array.isArray(configuration)) {
102327
+ return {
102328
+ legacyReferences: configuration
102329
+ };
102330
+ }
102331
+ if (typeof configuration === 'object') {
102332
+ const isPhased = PHASE_CONFIG_KEYS.some(key => key in configuration);
102333
+ if (isPhased) {
102334
+ const phased = {};
102335
+ for (const key of PHASE_CONFIG_KEYS) {
102336
+ if (key in configuration) {
102337
+ phased[key] = configuration[key];
102338
+ }
102339
+ }
102340
+ return {
102341
+ phased
102342
+ };
102343
+ }
102344
+ return {
102345
+ legacyReferences: configuration
102346
+ };
102347
+ }
102348
+ return {};
102349
+ }
100051
102350
  function hasDollarKey(value) {
100052
102351
  if (Array.isArray(value)) {
100053
102352
  for (const item of value) {
@@ -100076,6 +102375,7 @@ function hasDollarKey(value) {
100076
102375
  }
100077
102376
  ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/index.ts
100078
102377
 
102378
+
100079
102379
  /* export default */ const services_CustomizationService = (CustomizationService);
100080
102380
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
100081
102381
  var react = __webpack_require__(86326);
@@ -101178,7 +103478,7 @@ class MultiMonitorService {
101178
103478
  * Try moving the screen to the correct location - this will only work with
101179
103479
  * screens opened with openWindow containing no more than 1 tab.
101180
103480
  */
101181
- async onModeEnter() {
103481
+ onModeEnter() {
101182
103482
  this.setBasePath();
101183
103483
  if (this.isMultimonitor && this.screenNumber === -1 || window.location.href.toLowerCase().indexOf('launchall') !== -1) {
101184
103484
  this.launchAll();
@@ -101229,6 +103529,7 @@ MultiMonitorService.REGISTRATION = {
101229
103529
 
101230
103530
 
101231
103531
 
103532
+
101232
103533
 
101233
103534
 
101234
103535
  ;// CONCATENATED MODULE: ../../core/src/extensions/ExtensionManager.ts
@@ -106454,7 +108755,7 @@ const guid = () => {
106454
108755
  /* export default */ const __rspack_default_export = (guid);
106455
108756
 
106456
108757
  },
106457
- 3682(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
108758
+ 95339(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
106458
108759
  "use strict";
106459
108760
 
106460
108761
  // EXPORTS
@@ -106470,7 +108771,7 @@ __webpack_require__.d(__webpack_exports__, {
106470
108771
  Wf: () => (/* reexport */ utils_roundNumber)
106471
108772
  });
106472
108773
 
106473
- // UNUSED EXPORTS: MeasurementFilters, ObjectPath, Queue, absoluteUrl, createStudyBrowserTabs, downloadBlob, downloadCSVReport, downloadCsv, downloadDicom, downloadUrl, formatDate, generateAcceptHeader, getClosestOrientationFromIOP, hierarchicalListUtils, isDicomUid, isDisplaySetReconstructable, isEqualWithin, isImage, isLowPriorityModality, makeCancelable, makeDeferred, progressTrackingUtils, resolveObjectPath, sortBy, sortInstancesByPosition, splitComma, structuredCloneWithFunctions, thumbnailNoImageModalities, toNumber, urlUtil, writeScript
108774
+ // UNUSED EXPORTS: MeasurementFilters, ObjectPath, Queue, absoluteUrl, createStudyBrowserTabs, downloadBlob, downloadCSVReport, downloadCsv, downloadDicom, downloadUrl, formatDate, formatValue, generateAcceptHeader, getClosestOrientationFromIOP, hierarchicalListUtils, isDicomUid, isDisplaySetReconstructable, isEqualWithin, isImage, isLowPriorityModality, makeCancelable, makeDeferred, progressTrackingUtils, resolveObjectPath, sortBy, sortInstancesByPosition, splitComma, structuredCloneWithFunctions, thumbnailNoImageModalities, toNumber, urlUtil, writeScript
106474
108775
  // NAMESPACE OBJECT: ../../core/src/utils/measurementFilters.ts
106475
108776
  var measurementFilters_namespaceObject = {};
106476
108777
  __webpack_require__.r(measurementFilters_namespaceObject);
@@ -107119,6 +109420,25 @@ function formatPN(name) {
107119
109420
  // Trim any extraneous whitespace
107120
109421
  return cleaned.trim();
107121
109422
  }
109423
+ ;// CONCATENATED MODULE: ../../core/src/utils/formatValue.js
109424
+ /**
109425
+ * Formats values for safe text display.
109426
+ */
109427
+ function formatValue(value) {
109428
+ if (value == null) {
109429
+ return null;
109430
+ }
109431
+ if (typeof value === 'string') {
109432
+ return value;
109433
+ }
109434
+ if (typeof value === 'object' && typeof value.Alphabetic === 'string') {
109435
+ return value.Alphabetic;
109436
+ }
109437
+ if (typeof value === 'number' || typeof value === 'boolean') {
109438
+ return String(value);
109439
+ }
109440
+ return null;
109441
+ }
107122
109442
  ;// CONCATENATED MODULE: ../../core/src/utils/generateAcceptHeader.ts
107123
109443
  const generateAcceptHeader = (configAcceptHeader = [], requestTransferSyntaxUID = '*',
107124
109444
  //default to accept all transfer syntax
@@ -108530,6 +110850,7 @@ var thumbnailNoImageModalities = __webpack_require__(88555);
108530
110850
 
108531
110851
 
108532
110852
 
110853
+
108533
110854
 
108534
110855
 
108535
110856
  // Commented out unused functionality.
@@ -108553,6 +110874,7 @@ const utils = {
108553
110874
  formatDate: formatDate,
108554
110875
  formatTime: formatTime,
108555
110876
  formatPN: formatPN,
110877
+ formatValue: formatValue,
108556
110878
  b64toBlob: utils_b64toBlob,
108557
110879
  urlUtil: utils_urlUtil,
108558
110880
  imageIdToURI: imageIdToURI,
@@ -110401,7 +112723,7 @@ const detectionOptions = {
110401
112723
  }
110402
112724
  });
110403
112725
  ;// CONCATENATED MODULE: ../../i18n/package.json
110404
- var package_namespaceObject = JSON.parse('{"rE":"3.13.0-beta.111"}')
112726
+ var package_namespaceObject = JSON.parse('{"rE":"3.13.0-beta.113"}')
110405
112727
  ;// CONCATENATED MODULE: ../../i18n/src/utils.js
110406
112728
  const languagesMap = {
110407
112729
  ar: 'Arabic',
@@ -274871,8 +277193,8 @@ const withNotification = Component => {
274871
277193
  // EXTERNAL MODULE: ../../../node_modules/lodash.merge/index.js
274872
277194
  var lodash_merge = __webpack_require__(2816);
274873
277195
  var lodash_merge_default = /*#__PURE__*/__webpack_require__.n(lodash_merge);
274874
- // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
274875
- var core_src = __webpack_require__(62901);
277196
+ // EXTERNAL MODULE: ../../core/src/index.ts + 75 modules
277197
+ var core_src = __webpack_require__(50679);
274876
277198
  ;// CONCATENATED MODULE: ../../ui-next/src/contextProviders/ViewportGridProvider.tsx
274877
277199
 
274878
277200
 
@@ -443569,7 +445891,7 @@ __webpack_require__.u = (chunkId) => {
443569
445891
  // return url for filenames not based on template
443570
445892
 
443571
445893
  // return url for filenames based on template
443572
- return "" + ({1644: "interpolation",6915: "histogram-worker",8547: "compute",8781: "polySeg",}[chunkId] || chunkId) + ".bundle." + {100: "1d81cd3f544858b4",1180: "97e5d7ddb822ada4",1206: "79ed23079c78f18d",1229: "f721ec472f3d61bf",1602: "15b448aa8a33f8a3",1644: "9aea6a9ef4bd1f89",2195: "3045b375883a2e79",2666: "e54d0f68887f43d2",2779: "d1c8eeb441bf6838",3500: "bff323e7296c7475",3760: "68517e3fbaba0870",379: "75b0fb722268f037",3856: "cc247da8b523d738",414: "b80930f5525e536f",4556: "29d68aff99e72e43",4683: "0b47cae7de79e58c",4834: "20712369635ca3b2",5189: "86d3023e7ec28a8f",5406: "4dcfa7c697973300",5448: "8cda5b8e4baea275",5696: "a5a7fcaf46e722bd",5708: "8edb607ae04123db",5731: "a4e001a42e60e779",5910: "c1199bd45e450735",5989: "f3905a4493574e09",6001: "db54385151503e3c",6577: "a3e571d5f84837ea",6650: "defab1d01ae0dcba",6915: "11211bad02ea21bb",7231: "791409f68df0de05",7248: "b80f39a298a52d10",7295: "39a66efa759102bc",7463: "afe57ad10829df20",7579: "9369c6c58a5d6df5",8007: "a3ae96f72b3cc798",8423: "11056402679417e0",8432: "6df9d7dee19b3e77",8547: "4922bddc18cacdbd",8565: "a7532bbc39906b3c",8781: "c549b9f4bad23335",8832: "96a209e4a82b6bf4",899: "6f855ae8df39327e",9068: "29adebcfccb4bc8e",9116: "72e18d59d3438606",9290: "5a06e5f28e5dad94",9415: "fca81f7700036325",9437: "645c37102d332184",}[chunkId] + ".js"
445894
+ return "" + ({1644: "interpolation",6915: "histogram-worker",8547: "compute",8781: "polySeg",}[chunkId] || chunkId) + ".bundle." + {100: "1906f9ae2b66fe58",1180: "b85ba446cfbf82a9",1206: "ecd5aaaca8466ba5",1229: "f721ec472f3d61bf",1602: "58c538f4cfeafc04",1644: "9aea6a9ef4bd1f89",2195: "3045b375883a2e79",2779: "c50d9f70f57151a4",3500: "8820a8fab7c4144a",3760: "1368166ffc784155",379: "4b932c0de4372bc3",3856: "cc247da8b523d738",419: "ba9f959dac4b65e6",4556: "43fbd01f60119590",4683: "42b75d856c409bef",4834: "3f085ea647712366",5189: "bf053e2e1c064914",5406: "4dcfa7c697973300",5448: "1e50777e4c4e122a",5696: "d1858642ec96621b",5708: "07d7d136db71e3ab",5731: "a4e001a42e60e779",5910: "5561806884c95754",5989: "f3905a4493574e09",6001: "ab43bf3ef3da02d8",6577: "a3e571d5f84837ea",6650: "ac76eb90d6f8a353",6915: "11211bad02ea21bb",7231: "32e096be83a5dece",7248: "eeca01cd07f51f10",7295: "48faa19b4a5dea0d",7463: "40668aa8d083d077",7579: "9369c6c58a5d6df5",7701: "239da7c786e962d9",8007: "a74956fc12c00f19",8423: "6b8ba4230cea3d67",8432: "6df9d7dee19b3e77",8547: "4922bddc18cacdbd",8565: "a7532bbc39906b3c",8781: "c549b9f4bad23335",8832: "e859fea13db9f852",899: "221329ac8cec3022",9068: "cd36fcb4e15a153e",9116: "212df93fa6c89fd5",9290: "e966b25e072adc22",9415: "cec5bad019e1e0bf",9437: "c2beadb9d2b9501e",}[chunkId] + ".js"
443573
445895
  }
443574
445896
  })();
443575
445897
  // webpack/runtime/get mini-css chunk filename
@@ -443929,7 +446251,7 @@ chunkLoadingGlobal.push = __rspack_jsonp.bind(null, chunkLoadingGlobal.push.bind
443929
446251
  })();
443930
446252
  // webpack/runtime/chunk_prefetch_trigger
443931
446253
  (() => {
443932
- var chunkToChildrenMap = {"3833":[7231],"3760":[7231,9068,1206],"976":[7231,9068],"5708":[7231,899],"9415":[7231,5448],"1602":[7231],"9116":[7463],"7295":[7231],"8423":[7231],"3500":[8432,6650,8007,414,5910],"5910":[7231]};
446254
+ var chunkToChildrenMap = {"3833":[7231],"3760":[7231,9068,1206],"976":[7231,9068],"5708":[7231,899],"9415":[7231,5448],"1602":[7231],"9116":[7463],"7295":[7231],"8423":[7231],"3500":[8432,6650,8007,7701,5910],"5910":[7231]};
443933
446255
  __webpack_require__.f.prefetch = (chunkId, promises) => {
443934
446256
  Promise.all(promises).then(() => {
443935
446257
  var chunks = chunkToChildrenMap[chunkId];