@bnsights/bbsf-utilities 1.0.69 → 1.2.0

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 (122) hide show
  1. package/README.md +167 -2
  2. package/auth/index.d.ts +5 -0
  3. package/auth/public-api.d.ts +1 -0
  4. package/fesm2022/bnsights-bbsf-utilities-auth.mjs +10 -0
  5. package/fesm2022/bnsights-bbsf-utilities-auth.mjs.map +1 -0
  6. package/fesm2022/bnsights-bbsf-utilities-http.mjs +10 -0
  7. package/fesm2022/bnsights-bbsf-utilities-http.mjs.map +1 -0
  8. package/fesm2022/bnsights-bbsf-utilities-translate.mjs +10 -0
  9. package/fesm2022/bnsights-bbsf-utilities-translate.mjs.map +1 -0
  10. package/fesm2022/bnsights-bbsf-utilities-ui.mjs +10 -0
  11. package/fesm2022/bnsights-bbsf-utilities-ui.mjs.map +1 -0
  12. package/fesm2022/bnsights-bbsf-utilities.mjs +369 -3842
  13. package/fesm2022/bnsights-bbsf-utilities.mjs.map +1 -1
  14. package/http/index.d.ts +5 -0
  15. package/http/public-api.d.ts +4 -0
  16. package/lib/bbsf-utilities.module.d.ts +22 -2
  17. package/lib/shared/authentication/auth.service.d.ts +0 -1
  18. package/lib/shared/models/index.d.ts +0 -1
  19. package/lib/shared/services/index.d.ts +0 -1
  20. package/lib/shared/services/language.service.d.ts +12 -0
  21. package/lib/shared/services/request-handler.service.d.ts +2 -3
  22. package/lib/shared/services/styles-bundle.service.d.ts +7 -1
  23. package/package.json +32 -25
  24. package/public-api.d.ts +14 -12
  25. package/translate/index.d.ts +5 -0
  26. package/translate/public-api.d.ts +3 -0
  27. package/ui/index.d.ts +5 -0
  28. package/ui/public-api.d.ts +4 -0
  29. package/esm2022/bnsights-bbsf-utilities.mjs +0 -5
  30. package/esm2022/lib/bbsf-utilities.module.mjs +0 -63
  31. package/esm2022/lib/shared/authentication/auth.service.mjs +0 -260
  32. package/esm2022/lib/shared/authentication/index.mjs +0 -2
  33. package/esm2022/lib/shared/config/environment.mjs +0 -12
  34. package/esm2022/lib/shared/config/word/constants.mjs +0 -105
  35. package/esm2022/lib/shared/config/word/docx-document.mjs +0 -348
  36. package/esm2022/lib/shared/config/word/helpers/index.mjs +0 -4
  37. package/esm2022/lib/shared/config/word/helpers/render-document-file.mjs +0 -154
  38. package/esm2022/lib/shared/config/word/helpers/xml-builder.mjs +0 -1836
  39. package/esm2022/lib/shared/config/word/html-to-docx.mjs +0 -187
  40. package/esm2022/lib/shared/config/word/index.mjs +0 -50
  41. package/esm2022/lib/shared/config/word/namespaces.mjs +0 -37
  42. package/esm2022/lib/shared/config/word/schemas/content-types.mjs +0 -26
  43. package/esm2022/lib/shared/config/word/schemas/core.mjs +0 -27
  44. package/esm2022/lib/shared/config/word/schemas/document-rels.mjs +0 -16
  45. package/esm2022/lib/shared/config/word/schemas/document.template.mjs +0 -107
  46. package/esm2022/lib/shared/config/word/schemas/font-table.mjs +0 -40
  47. package/esm2022/lib/shared/config/word/schemas/generic-rels.mjs +0 -11
  48. package/esm2022/lib/shared/config/word/schemas/index.mjs +0 -13
  49. package/esm2022/lib/shared/config/word/schemas/numbering.mjs +0 -17
  50. package/esm2022/lib/shared/config/word/schemas/rels.mjs +0 -11
  51. package/esm2022/lib/shared/config/word/schemas/settings.mjs +0 -13
  52. package/esm2022/lib/shared/config/word/schemas/styles.mjs +0 -147
  53. package/esm2022/lib/shared/config/word/schemas/theme.mjs +0 -198
  54. package/esm2022/lib/shared/config/word/schemas/web-settings.mjs +0 -9
  55. package/esm2022/lib/shared/config/word/utils/color-conversion.mjs +0 -60
  56. package/esm2022/lib/shared/config/word/utils/list.mjs +0 -51
  57. package/esm2022/lib/shared/config/word/utils/unit-conversion.mjs +0 -30
  58. package/esm2022/lib/shared/config/word/utils/url.mjs +0 -7
  59. package/esm2022/lib/shared/config/word/utils/vnode.mjs +0 -3
  60. package/esm2022/lib/shared/config/word/word-work/templates/documentTemplate.mjs +0 -54
  61. package/esm2022/lib/shared/config/word/word-work/templates/index.mjs +0 -4
  62. package/esm2022/lib/shared/config/word/word-work/templates/mhtDocumentTemplate.mjs +0 -22
  63. package/esm2022/lib/shared/config/word/word-work/templates/mhtPartTemplate.mjs +0 -10
  64. package/esm2022/lib/shared/config/word/word-work/utils.mjs +0 -26
  65. package/esm2022/lib/shared/enums/authentication-modes-enums.mjs +0 -8
  66. package/esm2022/lib/shared/index.mjs +0 -4
  67. package/esm2022/lib/shared/models/UserModel.mjs +0 -3
  68. package/esm2022/lib/shared/models/area-model.mjs +0 -3
  69. package/esm2022/lib/shared/models/error-model.mjs +0 -3
  70. package/esm2022/lib/shared/models/index.mjs +0 -6
  71. package/esm2022/lib/shared/models/request-options-model.mjs +0 -11
  72. package/esm2022/lib/shared/models/speech-language.mjs +0 -3
  73. package/esm2022/lib/shared/models/word-document-model.mjs +0 -8
  74. package/esm2022/lib/shared/services/appearance-configuration.service.mjs +0 -35
  75. package/esm2022/lib/shared/services/configuration.service.mjs +0 -48
  76. package/esm2022/lib/shared/services/control-validation.service.mjs +0 -173
  77. package/esm2022/lib/shared/services/environment.service.mjs +0 -83
  78. package/esm2022/lib/shared/services/index.mjs +0 -15
  79. package/esm2022/lib/shared/services/language.service.mjs +0 -21
  80. package/esm2022/lib/shared/services/master-layout.service.mjs +0 -77
  81. package/esm2022/lib/shared/services/preload.service.mjs +0 -54
  82. package/esm2022/lib/shared/services/request-handler.service.mjs +0 -260
  83. package/esm2022/lib/shared/services/speech-recognition.service.mjs +0 -76
  84. package/esm2022/lib/shared/services/styles-bundle.service.mjs +0 -55
  85. package/esm2022/lib/shared/services/translate.service.mjs +0 -14
  86. package/esm2022/lib/shared/services/translation-resolver.service.mjs +0 -7
  87. package/esm2022/lib/shared/services/utility.service.mjs +0 -87
  88. package/esm2022/lib/shared/services/word-document.service.mjs +0 -38
  89. package/esm2022/public-api.mjs +0 -34
  90. package/lib/shared/config/word/constants.d.ts +0 -124
  91. package/lib/shared/config/word/docx-document.d.ts +0 -73
  92. package/lib/shared/config/word/helpers/index.d.ts +0 -1
  93. package/lib/shared/config/word/helpers/render-document-file.d.ts +0 -2
  94. package/lib/shared/config/word/helpers/xml-builder.d.ts +0 -16
  95. package/lib/shared/config/word/html-to-docx.d.ts +0 -1
  96. package/lib/shared/config/word/index.d.ts +0 -1
  97. package/lib/shared/config/word/namespaces.d.ts +0 -36
  98. package/lib/shared/config/word/schemas/content-types.d.ts +0 -1
  99. package/lib/shared/config/word/schemas/core.d.ts +0 -1
  100. package/lib/shared/config/word/schemas/document-rels.d.ts +0 -1
  101. package/lib/shared/config/word/schemas/document.template.d.ts +0 -4
  102. package/lib/shared/config/word/schemas/font-table.d.ts +0 -1
  103. package/lib/shared/config/word/schemas/generic-rels.d.ts +0 -1
  104. package/lib/shared/config/word/schemas/index.d.ts +0 -12
  105. package/lib/shared/config/word/schemas/numbering.d.ts +0 -1
  106. package/lib/shared/config/word/schemas/rels.d.ts +0 -1
  107. package/lib/shared/config/word/schemas/settings.d.ts +0 -1
  108. package/lib/shared/config/word/schemas/styles.d.ts +0 -1
  109. package/lib/shared/config/word/schemas/theme.d.ts +0 -1
  110. package/lib/shared/config/word/schemas/web-settings.d.ts +0 -1
  111. package/lib/shared/config/word/utils/color-conversion.d.ts +0 -7
  112. package/lib/shared/config/word/utils/list.d.ts +0 -6
  113. package/lib/shared/config/word/utils/unit-conversion.d.ts +0 -29
  114. package/lib/shared/config/word/utils/url.d.ts +0 -1
  115. package/lib/shared/config/word/utils/vnode.d.ts +0 -1
  116. package/lib/shared/config/word/word-work/templates/documentTemplate.d.ts +0 -12
  117. package/lib/shared/config/word/word-work/templates/index.d.ts +0 -3
  118. package/lib/shared/config/word/word-work/templates/mhtDocumentTemplate.d.ts +0 -1
  119. package/lib/shared/config/word/word-work/templates/mhtPartTemplate.d.ts +0 -1
  120. package/lib/shared/config/word/word-work/utils.d.ts +0 -1
  121. package/lib/shared/models/word-document-model.d.ts +0 -16
  122. package/lib/shared/services/word-document.service.d.ts +0 -8
@@ -1,37 +1,22 @@
1
1
  import { DOCUMENT, CommonModule } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { Injectable, Inject, inject, NgModule } from '@angular/core';
3
+ import { Injectable, inject, Inject, NgModule } from '@angular/core';
4
4
  import * as i1$1 from '@angular/router';
5
- import { RouterModule } from '@angular/router';
5
+ import { Router, RouterModule } from '@angular/router';
6
6
  import * as i4 from '@ngx-translate/core';
7
7
  import { TranslateService } from '@ngx-translate/core';
8
8
  import * as i1$2 from 'ng-block-ui';
9
9
  import { BlockUI, BlockUIModule } from 'ng-block-ui';
10
- import * as i2 from 'ngx-toastr';
11
- import { ToastrService, ToastrModule } from 'ngx-toastr';
10
+ import { ToastrService, provideToastr } from 'ngx-toastr';
12
11
  import * as i4$1 from 'ngx-cookie-service';
13
12
  import { CookieService } from 'ngx-cookie-service';
14
13
  import * as i1 from '@angular/common/http';
15
14
  import { HttpParams, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
16
- import { Subject, throwError, Observable, lastValueFrom, BehaviorSubject } from 'rxjs';
15
+ import { Subject, throwError, of, Observable, lastValueFrom, BehaviorSubject } from 'rxjs';
17
16
  import { JwtHelperService } from '@auth0/angular-jwt';
18
17
  import { __decorate } from 'tslib';
19
18
  import { plainToClass } from 'class-transformer';
20
- import { takeUntil, tap, map } from 'rxjs/operators';
21
- import JSZip from 'jszip';
22
- import { fragment, create } from 'xmlbuilder2';
23
- import VNode$1 from 'virtual-dom/vnode/vnode';
24
- import VText from 'virtual-dom/vnode/vtext';
25
- import HTMLToVDOM from 'html-to-vdom';
26
- import { cloneDeep } from 'lodash';
27
- import { nanoid } from 'nanoid';
28
- import isVNode from 'virtual-dom/vnode/is-vnode';
29
- import isVText from 'virtual-dom/vnode/is-vtext';
30
- import escape from 'escape-html';
31
- import colorNames from 'color-name';
32
- import imageToBase64 from 'image-to-base64';
33
- import mimeTypes from 'mime-types';
34
- import sizeOf from 'image-size';
19
+ import { takeUntil, tap, map, shareReplay, take } from 'rxjs/operators';
35
20
 
36
21
  class User {
37
22
  }
@@ -66,10 +51,10 @@ class AppearanceConfigurationService {
66
51
  getLogo() {
67
52
  return this.configService.getConfigurationValue('AnonymousLayout_Logo');
68
53
  }
69
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppearanceConfigurationService, deps: [{ token: ConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
70
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppearanceConfigurationService, providedIn: 'root' }); }
54
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AppearanceConfigurationService, deps: [{ token: ConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
55
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AppearanceConfigurationService, providedIn: 'root' }); }
71
56
  }
72
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppearanceConfigurationService, decorators: [{
57
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AppearanceConfigurationService, decorators: [{
73
58
  type: Injectable,
74
59
  args: [{
75
60
  providedIn: 'root'
@@ -110,10 +95,10 @@ class ConfigurationService {
110
95
  return selectedKey;
111
96
  }
112
97
  }
113
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConfigurationService, deps: [{ token: i1.HttpClient }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
114
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConfigurationService, providedIn: 'root' }); }
98
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfigurationService, deps: [{ token: i1.HttpClient }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
99
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfigurationService, providedIn: 'root' }); }
115
100
  }
116
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConfigurationService, decorators: [{
101
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfigurationService, decorators: [{
117
102
  type: Injectable,
118
103
  args: [{
119
104
  providedIn: 'root'
@@ -137,14 +122,6 @@ class RequestOptionsModel {
137
122
  }
138
123
  }
139
124
 
140
- class WordDocumentModel {
141
- constructor() {
142
- this.options = new DocumentOptionsModel();
143
- }
144
- }
145
- class DocumentOptionsModel {
146
- }
147
-
148
125
  class LanguageDTO {
149
126
  }
150
127
 
@@ -302,13 +279,13 @@ class ControlValidationService {
302
279
  let control = form.get(controlName);
303
280
  return control;
304
281
  }
305
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ControlValidationService, deps: [{ token: UtilityService }], target: i0.ɵɵFactoryTarget.Injectable }); }
306
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ControlValidationService, providedIn: 'root' }); }
282
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ControlValidationService, deps: [{ token: UtilityService }], target: i0.ɵɵFactoryTarget.Injectable }); }
283
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ControlValidationService, providedIn: 'root' }); }
307
284
  }
308
285
  __decorate([
309
286
  BlockUI()
310
287
  ], ControlValidationService.prototype, "blockUI", void 0);
311
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ControlValidationService, decorators: [{
288
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ControlValidationService, decorators: [{
312
289
  type: Injectable,
313
290
  args: [{
314
291
  providedIn: 'root'
@@ -397,10 +374,10 @@ class EnvironmentService {
397
374
  let cookieName = environment["BBSF_CookieName"];
398
375
  return cookieName;
399
376
  }
400
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EnvironmentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
401
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EnvironmentService, providedIn: 'root' }); }
377
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: EnvironmentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
378
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: EnvironmentService, providedIn: 'root' }); }
402
379
  }
403
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EnvironmentService, decorators: [{
380
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: EnvironmentService, decorators: [{
404
381
  type: Injectable,
405
382
  args: [{
406
383
  providedIn: 'root'
@@ -466,10 +443,10 @@ class MasterLayoutService {
466
443
  params = params.append('RoleID', permissionSetID);
467
444
  return this.http.post(this.apiUrl + 'SwitchRole', null, null, params);
468
445
  }
469
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MasterLayoutService, deps: [{ token: i1$1.Router }, { token: RequestHandlerService }, { token: AuthService }, { token: StylesBundleService }, { token: i4.TranslateService }, { token: EnvironmentService }], target: i0.ɵɵFactoryTarget.Injectable }); }
470
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MasterLayoutService, providedIn: 'root' }); }
446
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MasterLayoutService, deps: [{ token: i1$1.Router }, { token: RequestHandlerService }, { token: AuthService }, { token: StylesBundleService }, { token: i4.TranslateService }, { token: EnvironmentService }], target: i0.ɵɵFactoryTarget.Injectable }); }
447
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MasterLayoutService, providedIn: 'root' }); }
471
448
  }
472
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MasterLayoutService, decorators: [{
449
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MasterLayoutService, decorators: [{
473
450
  type: Injectable,
474
451
  args: [{
475
452
  providedIn: 'root',
@@ -477,15 +454,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
477
454
  }], ctorParameters: () => [{ type: i1$1.Router }, { type: RequestHandlerService }, { type: AuthService }, { type: StylesBundleService }, { type: i4.TranslateService }, { type: EnvironmentService }] });
478
455
 
479
456
  class RequestHandlerService {
480
- constructor(http, authService, environmentService, utilityService, bbsfTranslateService, router) {
457
+ constructor(http, authService, environmentService, utilityService, bbsfTranslateService) {
481
458
  this.http = http;
482
459
  this.authService = authService;
483
460
  this.environmentService = environmentService;
484
461
  this.utilityService = utilityService;
485
462
  this.bbsfTranslateService = bbsfTranslateService;
486
- this.router = router;
487
463
  this.currentLanguage = "";
488
464
  this.onDestroy$ = new Subject();
465
+ this.router = inject(Router);
489
466
  //using localStorage to avoid call getCurrentLanguage() because it is not all to use async in constructor
490
467
  this.bbsfTranslateService.onLangChange.subscribe((event) => {
491
468
  if (this.currentLanguage != event.lang) {
@@ -718,12 +695,15 @@ class RequestHandlerService {
718
695
  'Image-Upload': 'true',
719
696
  });
720
697
  }
721
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RequestHandlerService, deps: [{ token: i1.HttpClient }, { token: AuthService }, { token: EnvironmentService }, { token: UtilityService }, { token: BBSFTranslateService }, { token: i1$1.Router }], target: i0.ɵɵFactoryTarget.Injectable }); }
722
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RequestHandlerService }); }
698
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: RequestHandlerService, deps: [{ token: i1.HttpClient }, { token: AuthService }, { token: EnvironmentService }, { token: UtilityService }, { token: BBSFTranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
699
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: RequestHandlerService, providedIn: 'root' }); }
723
700
  }
724
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RequestHandlerService, decorators: [{
725
- type: Injectable
726
- }], ctorParameters: () => [{ type: i1.HttpClient }, { type: AuthService }, { type: EnvironmentService }, { type: UtilityService }, { type: BBSFTranslateService }, { type: i1$1.Router }] });
701
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: RequestHandlerService, decorators: [{
702
+ type: Injectable,
703
+ args: [{
704
+ providedIn: 'root',
705
+ }]
706
+ }], ctorParameters: () => [{ type: i1.HttpClient }, { type: AuthService }, { type: EnvironmentService }, { type: UtilityService }, { type: BBSFTranslateService }] });
727
707
 
728
708
  class StylesBundleService {
729
709
  constructor(document, translateService) {
@@ -751,22 +731,43 @@ class StylesBundleService {
751
731
  loadStyleBundle(styleName) {
752
732
  const head = this.document.getElementsByTagName('head')[0];
753
733
  let themeLink = this.document.getElementById('client-theme');
754
- if (themeLink && themeLink.href.includes(styleName)) {
755
- return;
756
- }
757
- else if (themeLink && !themeLink.href.includes(styleName)) {
758
- themeLink.remove();
734
+ let shouldRemoveOld = false;
735
+ if (themeLink) {
736
+ // ✅ Check if current CSS already loaded (by exact filename)
737
+ const currentFileName = this.getFileName(themeLink.href);
738
+ const requestedFileName = this.getFileName(styleName);
739
+ if (currentFileName === requestedFileName) {
740
+ return; // Same CSS already loaded
741
+ }
742
+ else {
743
+ shouldRemoveOld = true; // Mark for removal after new CSS is added
744
+ }
759
745
  }
746
+ // ✅ Add new CSS first (prevents FOUC)
760
747
  const style = this.document.createElement('link');
761
748
  style.id = 'client-theme';
762
749
  style.rel = 'stylesheet';
763
750
  style.href = `${styleName}`;
764
751
  head.appendChild(style);
752
+ // ✅ Remove old CSS after new one is added (smooth transition)
753
+ if (shouldRemoveOld && themeLink) {
754
+ themeLink.remove();
755
+ }
765
756
  }
766
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: StylesBundleService, deps: [{ token: DOCUMENT }, { token: BBSFTranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
767
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: StylesBundleService, providedIn: 'root' }); }
757
+ /**
758
+ * Extract filename from full path
759
+ * @param path Full path or just filename
760
+ * @returns The filename only
761
+ */
762
+ getFileName(path) {
763
+ // Extract just the filename from full path
764
+ const parts = path.split('/');
765
+ return parts[parts.length - 1];
766
+ }
767
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: StylesBundleService, deps: [{ token: DOCUMENT }, { token: BBSFTranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
768
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: StylesBundleService, providedIn: 'root' }); }
768
769
  }
769
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: StylesBundleService, decorators: [{
770
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: StylesBundleService, decorators: [{
770
771
  type: Injectable,
771
772
  args: [{
772
773
  providedIn: 'root'
@@ -777,10 +778,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
777
778
  }] }, { type: BBSFTranslateService }] });
778
779
 
779
780
  class BBSFTranslateService extends TranslateService {
780
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BBSFTranslateService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
781
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BBSFTranslateService, providedIn: 'root' }); }
781
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BBSFTranslateService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
782
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BBSFTranslateService, providedIn: 'root' }); }
782
783
  }
783
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BBSFTranslateService, decorators: [{
784
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BBSFTranslateService, decorators: [{
784
785
  type: Injectable,
785
786
  args: [{
786
787
  providedIn: 'root'
@@ -860,3805 +861,287 @@ class UtilityService {
860
861
  stopBlockUI() {
861
862
  this.blockUI.stop();
862
863
  }
863
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilityService, deps: [{ token: BBSFTranslateService }, { token: EnvironmentService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
864
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilityService, providedIn: 'root' }); }
864
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: UtilityService, deps: [{ token: BBSFTranslateService }, { token: EnvironmentService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
865
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: UtilityService, providedIn: 'root' }); }
865
866
  }
866
867
  __decorate([
867
868
  BlockUI()
868
869
  ], UtilityService.prototype, "blockUI", void 0);
869
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilityService, decorators: [{
870
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: UtilityService, decorators: [{
870
871
  type: Injectable,
871
872
  args: [{
872
873
  providedIn: 'root'
873
874
  }]
874
875
  }], ctorParameters: () => [{ type: BBSFTranslateService }, { type: EnvironmentService }, { type: i0.Injector }], propDecorators: { blockUI: [] } });
875
876
 
876
- const contentTypesXML = `
877
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
878
-
879
- <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
880
- <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />
881
- <Default Extension="jpeg" ContentType="image/jpeg"/>
882
- <Default Extension="png" ContentType="image/png"/>
883
- <Default Extension="xml" ContentType="application/xml"/>
884
- <Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
885
- <Override PartName="/word/_rels/document.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
886
- <Override PartName="/word/_rels/footer1.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
887
- <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
888
- <Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
889
- <Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/>
890
- <Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
891
- <Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
892
- <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
893
- <Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>
894
- <Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/>
895
- <Override PartName="/word/afchunk.mht" ContentType="message/rfc822"/>
896
- <Override PartName="/word/afchunkheader.mht" ContentType="message/rfc822"/>
897
- <Override PartName="/word/afchunkfooter.mht" ContentType="message/rfc822"/>
898
- </Types>
899
- `;
900
-
901
- const namespaces = {
902
- a: 'http://schemas.openxmlformats.org/drawingml/2006/main',
903
- b: 'http://schemas.openxmlformats.org/officeDocument/2006/bibliography',
904
- cdr: 'http://schemas.openxmlformats.org/drawingml/2006/chartDrawing',
905
- dc: 'http://purl.org/dc/elements/1.1/',
906
- dcmitype: 'http://purl.org/dc/dcmitype/',
907
- dcterms: 'http://purl.org/dc/terms/',
908
- o: 'urn:schemas-microsoft-com:office:office',
909
- pic: 'http://schemas.openxmlformats.org/drawingml/2006/picture',
910
- r: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
911
- v: 'urn:schemas-microsoft-com:vml',
912
- ve: 'http://schemas.openxmlformats.org/markup-compatibility/2006',
913
- vt: 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
914
- w: 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
915
- w10: 'urn:schemas-microsoft-com:office:word',
916
- wp: 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
917
- wne: 'http://schemas.microsoft.com/office/word/2006/wordml',
918
- xsd: 'http://www.w3.org/2001/XMLSchema',
919
- xsi: 'http://www.w3.org/2001/XMLSchema-instance',
920
- numbering: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering',
921
- hyperlinks: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
922
- images: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
923
- styles: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles',
924
- headers: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/header',
925
- footers: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer',
926
- themes: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme',
927
- coreProperties: 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
928
- officeDocumentRelation: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument',
929
- corePropertiesRelation: 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
930
- settingsRelation: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings',
931
- webSettingsRelation: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings',
932
- sl: 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
933
- contentTypes: 'http://schemas.openxmlformats.org/package/2006/content-types',
934
- relationship: 'http://schemas.openxmlformats.org/package/2006/relationships',
935
- };
936
-
937
- const applicationName = 'html-to-docx';
938
- const defaultOrientation = 'portrait';
939
- const landscapeWidth = 15840;
940
- const landscapeHeight = 12240;
941
- const landscapeMargins = {
942
- top: 1800,
943
- right: 1440,
944
- bottom: 1800,
945
- left: 1440,
946
- header: 720,
947
- footer: 720,
948
- gutter: 0,
949
- };
950
- const portraitMargins = {
951
- top: 1440,
952
- right: 1800,
953
- bottom: 1440,
954
- left: 1800,
955
- header: 720,
956
- footer: 720,
957
- gutter: 0,
958
- };
959
- const defaultFont = 'Times New Roman';
960
- const defaultFontSize = 22;
961
- const defaultDocumentOptions = {
962
- orientation: defaultOrientation,
963
- margins: cloneDeep(portraitMargins),
964
- title: '',
965
- subject: '',
966
- creator: applicationName,
967
- keywords: [applicationName],
968
- description: '',
969
- lastModifiedBy: applicationName,
970
- revision: 1,
971
- createdAt: new Date(),
972
- modifiedAt: new Date(),
973
- headerType: 'default',
974
- header: false,
975
- footerType: 'default',
976
- footer: false,
977
- font: defaultFont,
978
- fontSize: defaultFontSize,
979
- complexScriptFontSize: defaultFontSize,
980
- table: {
981
- row: {
982
- cantSplit: false,
983
- },
984
- },
985
- pageSize: {
986
- width: landscapeHeight,
987
- height: landscapeWidth,
988
- },
989
- pageNumber: false,
990
- skipFirstHeaderFooter: false,
991
- lineNumber: false,
992
- lineNumberOptions: {
993
- countBy: 1,
994
- start: 0,
995
- restart: 'continuous',
996
- },
997
- numbering: {
998
- defaultOrderedListStyleType: 'decimal',
999
- },
1000
- };
1001
- const defaultHTMLString = '<p></p>';
1002
- const relsFolderName = '_rels';
1003
- const headerFileName = 'header1';
1004
- const footerFileName = 'footer1';
1005
- const themeFileName = 'theme1';
1006
- const documentFileName = 'document';
1007
- const headerType = 'header';
1008
- const footerType = 'footer';
1009
- const themeType = 'theme';
1010
- const hyperlinkType = 'hyperlink';
1011
- const imageType = 'image';
1012
- const internalRelationship = 'Internal';
1013
- const wordFolder = 'word';
1014
- const themeFolder = 'theme';
1015
- const paragraphBordersObject = {
1016
- top: {
1017
- size: 0,
1018
- spacing: 3,
1019
- color: 'FFFFFF',
1020
- },
1021
- left: {
1022
- size: 0,
1023
- spacing: 3,
1024
- color: 'FFFFFF',
1025
- },
1026
- bottom: {
1027
- size: 0,
1028
- spacing: 3,
1029
- color: 'FFFFFF',
1030
- },
1031
- right: {
1032
- size: 0,
1033
- spacing: 3,
1034
- color: 'FFFFFF',
1035
- },
1036
- };
1037
- const colorlessColors = ['transparent', 'auto'];
1038
- const verticalAlignValues = ['top', 'middle', 'bottom'];
1039
-
1040
- const generateCoreXML = (title = '', subject = '', creator = applicationName, keywords = [applicationName], description = '', lastModifiedBy = applicationName, revision = 1, createdAt = new Date(), modifiedAt = new Date()) => `
1041
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1042
-
1043
- <cp:coreProperties
1044
- xmlns:cp="${namespaces.coreProperties}"
1045
- xmlns:dc="${namespaces.dc}"
1046
- xmlns:dcterms="${namespaces.dcterms}"
1047
- xmlns:dcmitype="${namespaces.dcmitype}"
1048
- xmlns:xsi="${namespaces.xsi}"
1049
- >
1050
- <dc:title>${title}</dc:title>
1051
- <dc:subject>${subject}</dc:subject>
1052
- <dc:creator>${creator}</dc:creator>
1053
- ${keywords && Array.isArray(keywords)
1054
- ? `<cp:keywords>${keywords.join(', ')}</cp:keywords>`
1055
- : ''}
1056
- <dc:description>${description}</dc:description>
1057
- <cp:lastModifiedBy>${lastModifiedBy}</cp:lastModifiedBy>
1058
- <cp:revision>${revision}</cp:revision>
1059
- <dcterms:created xsi:type="dcterms:W3CDTF">${createdAt instanceof Date ? createdAt.toISOString() : new Date().toISOString()}</dcterms:created>
1060
- <dcterms:modified xsi:type="dcterms:W3CDTF">${modifiedAt instanceof Date ? modifiedAt.toISOString() : new Date().toISOString()}</dcterms:modified>
1061
- </cp:coreProperties>
1062
- `;
1063
-
1064
- const documentRelsXML = `
1065
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1066
-
1067
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
1068
- <Relationship Id="rId1" Type="${namespaces.numbering}" Target="numbering.xml"/>
1069
- <Relationship Id="rId2" Type="${namespaces.styles}" Target="styles.xml"/>
1070
- <Relationship Id="rId3" Type="${namespaces.settingsRelation}" Target="settings.xml"/>
1071
- <Relationship Id="rId4" Type="${namespaces.webSettingsRelation}" Target="webSettings.xml"/>
1072
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunk.mht" Id="htmlChunk" />
1073
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkheader.mht" Id="htmlChunkHeader" />
1074
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkfooter.mht" Id="htmlChunkFooter" />
1075
- </Relationships>
1076
- `;
1077
-
1078
- const relsXML = `
1079
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1080
-
1081
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
1082
- <Relationship Id="rId1" Type="${namespaces.officeDocumentRelation}" Target="word/document.xml"/>
1083
- <Relationship Id="rId2" Type="${namespaces.corePropertiesRelation}" Target="docProps/core.xml"/>
1084
- </Relationships>
1085
- `;
1086
-
1087
- const generateNumberingXMLTemplate = () => `
1088
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1089
-
1090
- <w:numbering
1091
- xmlns:w="${namespaces.w}"
1092
- xmlns:ve="${namespaces.ve}"
1093
- xmlns:o="${namespaces.o}"
1094
- xmlns:r="${namespaces.r}"
1095
- xmlns:v="${namespaces.v}"
1096
- xmlns:wp="${namespaces.wp}"
1097
- xmlns:w10="${namespaces.w10}"
1098
- xmlns:wne="${namespaces.wne}">
1099
- </w:numbering>
1100
- `;
1101
-
1102
- const generateStylesXML = (font = defaultFont, fontSize = defaultFontSize, complexScriptFontSize = defaultFontSize) => `
1103
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1104
-
1105
- <w:styles xmlns:w="${namespaces.w}" xmlns:r="${namespaces.r}">
1106
- <w:docDefaults>
1107
- <w:rPrDefault>
1108
- <w:rPr>
1109
- <w:rFonts w:ascii="${font}" w:eastAsiaTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi" />
1110
- <w:sz w:val="${fontSize}" />
1111
- <w:szCs w:val="${complexScriptFontSize}" />
1112
- <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA" />
1113
- </w:rPr>
1114
- </w:rPrDefault>
1115
- <w:pPrDefault>
1116
- <w:pPr>
1117
- <w:spacing w:after="120" w:line="240" w:lineRule="atLeast" />
1118
- </w:pPr>
1119
- </w:pPrDefault>
1120
- </w:docDefaults>
1121
- <w:style w:type="character" w:styleId="Hyperlink">
1122
- <w:name w:val="Hyperlink" />
1123
- <w:rPr>
1124
- <w:color w:val="0000FF" />
1125
- <w:u w:val="single" />
1126
- </w:rPr>
1127
- </w:style>
1128
- <w:style w:type="paragraph" w:styleId="Heading1">
1129
- <w:name w:val="heading 1" />
1130
- <w:basedOn w:val="Normal" />
1131
- <w:next w:val="Normal" />
1132
- <w:uiPriority w:val="9" />
1133
- <w:qFormat />
1134
- <w:pPr>
1135
- <w:keepNext />
1136
- <w:keepLines />
1137
- <w:spacing w:before="480" />
1138
- <w:outlineLvl w:val="0" />
1139
- </w:pPr>
1140
- <w:rPr>
1141
- <w:b />
1142
- <w:sz w:val="48" />
1143
- <w:szCs w:val="48" />
1144
- </w:rPr>
1145
- </w:style>
1146
- <w:style w:type="paragraph" w:styleId="Heading2">
1147
- <w:name w:val="heading 2" />
1148
- <w:basedOn w:val="Normal" />
1149
- <w:next w:val="Normal" />
1150
- <w:uiPriority w:val="9" />
1151
- <w:unhideWhenUsed />
1152
- <w:qFormat />
1153
- <w:pPr>
1154
- <w:keepNext />
1155
- <w:keepLines />
1156
- <w:spacing w:before="360" w:after="80" />
1157
- <w:outlineLvl w:val="1" />
1158
- </w:pPr>
1159
- <w:rPr>
1160
- <w:b />
1161
- <w:sz w:val="36" />
1162
- <w:szCs w:val="36" />
1163
- </w:rPr>
1164
- </w:style>
1165
- <w:style w:type="paragraph" w:styleId="Heading3">
1166
- <w:name w:val="heading 3" />
1167
- <w:basedOn w:val="Normal" />
1168
- <w:next w:val="Normal" />
1169
- <w:uiPriority w:val="9" />
1170
- <w:semiHidden />
1171
- <w:unhideWhenUsed />
1172
- <w:qFormat />
1173
- <w:pPr>
1174
- <w:keepNext />
1175
- <w:keepLines />
1176
- <w:spacing w:before="280" w:after="80" />
1177
- <w:outlineLvl w:val="2" />
1178
- </w:pPr>
1179
- <w:rPr>
1180
- <w:b />
1181
- <w:sz w:val="28" />
1182
- <w:szCs w:val="28" />
1183
- </w:rPr>
1184
- </w:style>
1185
- <w:style w:type="paragraph" w:styleId="Heading4">
1186
- <w:name w:val="heading 4" />
1187
- <w:basedOn w:val="Normal" />
1188
- <w:next w:val="Normal" />
1189
- <w:uiPriority w:val="9" />
1190
- <w:semiHidden />
1191
- <w:unhideWhenUsed />
1192
- <w:qFormat />
1193
- <w:pPr>
1194
- <w:keepNext />
1195
- <w:keepLines />
1196
- <w:spacing w:before="240" w:after="40" />
1197
- <w:outlineLvl w:val="3" />
1198
- </w:pPr>
1199
- <w:rPr>
1200
- <w:b />
1201
- <w:sz w:val="24" />
1202
- <w:szCs w:val="24" />
1203
- </w:rPr>
1204
- </w:style>
1205
- <w:style w:type="paragraph" w:styleId="Heading5">
1206
- <w:name w:val="heading 5" />
1207
- <w:basedOn w:val="Normal" />
1208
- <w:next w:val="Normal" />
1209
- <w:uiPriority w:val="9" />
1210
- <w:semiHidden />
1211
- <w:unhideWhenUsed />
1212
- <w:qFormat />
1213
- <w:pPr>
1214
- <w:keepNext />
1215
- <w:keepLines />
1216
- <w:spacing w:before="220" w:after="40" />
1217
- <w:outlineLvl w:val="4" />
1218
- </w:pPr>
1219
- <w:rPr>
1220
- <w:b />
1221
- </w:rPr>
1222
- </w:style>
1223
- <w:style w:type="paragraph" w:styleId="Heading6">
1224
- <w:name w:val="heading 6" />
1225
- <w:basedOn w:val="Normal" />
1226
- <w:next w:val="Normal" />
1227
- <w:uiPriority w:val="9" />
1228
- <w:semiHidden />
1229
- <w:unhideWhenUsed />
1230
- <w:qFormat />
1231
- <w:pPr>
1232
- <w:keepNext />
1233
- <w:keepLines />
1234
- <w:spacing w:before="200" w:after="40" />
1235
- <w:outlineLvl w:val="5" />
1236
- </w:pPr>
1237
- <w:rPr>
1238
- <w:b />
1239
- <w:sz w:val="20" />
1240
- <w:szCs w:val="20" />
1241
- </w:rPr>
1242
- </w:style>
1243
- </w:styles>
1244
- `;
1245
-
1246
- const fontTableXML = `
1247
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1248
-
1249
- <w:fonts
1250
- xmlns:r="${namespaces.r}"
1251
- xmlns:w="${namespaces.w}"
1252
- >
1253
- <w:font w:name="Symbol">
1254
- <w:panose1 w:val="05050102010706020507"/>
1255
- <w:charset w:val="02"/>
1256
- <w:family w:val="decorative"/>
1257
- <w:pitch w:val="variable"/>
1258
- <w:sig w:usb0="00000000" w:usb1="10000000" w:usb2="00000000" w:usb3="00000000" w:csb0="80000000" w:csb1="00000000"/>
1259
- </w:font>
1260
- <w:font w:name="Calibri">
1261
- <w:panose1 w:val="020F0502020204030204"/>
1262
- <w:charset w:val="00"/>
1263
- <w:family w:val="swiss"/>
1264
- <w:pitch w:val="variable"/>
1265
- <w:sig w:usb0="E4002EFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
1266
- </w:font>
1267
- <w:font w:name="Times New Roman">
1268
- <w:panose1 w:val="02020603050405020304"/>
1269
- <w:charset w:val="00"/>
1270
- <w:family w:val="roman"/>
1271
- <w:pitch w:val="variable"/>
1272
- <w:sig w:usb0="E0002EFF" w:usb1="C000785B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
1273
- </w:font>
1274
- <w:font w:name="Calibri Light">
1275
- <w:panose1 w:val="020F0302020204030204"/>
1276
- <w:charset w:val="00"/>
1277
- <w:family w:val="swiss"/>
1278
- <w:pitch w:val="variable"/>
1279
- <w:sig w:usb0="E4002EFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
1280
- </w:font>
1281
- </w:fonts>
1282
- `;
1283
-
1284
- const generateThemeXML = (font = defaultFont) => `
1285
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1286
-
1287
- <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">
1288
- <a:themeElements>
1289
- <a:clrScheme name="Office">
1290
- <a:dk1>
1291
- <a:sysClr val="windowText" lastClr="000000"/>
1292
- </a:dk1>
1293
- <a:lt1>
1294
- <a:sysClr val="window" lastClr="FFFFFF"/>
1295
- </a:lt1>
1296
- <a:dk2>
1297
- <a:srgbClr val="44546A"/>
1298
- </a:dk2>
1299
- <a:lt2>
1300
- <a:srgbClr val="E7E6E6"/>
1301
- </a:lt2>
1302
- <a:accent1>
1303
- <a:srgbClr val="4472C4"/>
1304
- </a:accent1>
1305
- <a:accent2>
1306
- <a:srgbClr val="ED7D31"/>
1307
- </a:accent2>
1308
- <a:accent3>
1309
- <a:srgbClr val="A5A5A5"/>
1310
- </a:accent3>
1311
- <a:accent4>
1312
- <a:srgbClr val="FFC000"/>
1313
- </a:accent4>
1314
- <a:accent5>
1315
- <a:srgbClr val="5B9BD5"/>
1316
- </a:accent5>
1317
- <a:accent6>
1318
- <a:srgbClr val="70AD47"/>
1319
- </a:accent6>
1320
- <a:hlink>
1321
- <a:srgbClr val="0563C1"/>
1322
- </a:hlink>
1323
- <a:folHlink>
1324
- <a:srgbClr val="954F72"/>
1325
- </a:folHlink>
1326
- </a:clrScheme>
1327
- <a:fontScheme name="Office">
1328
- <a:majorFont>
1329
- <a:latin typeface="${font}"/>
1330
- <a:ea typeface="${font}"/>
1331
- <a:cs typeface=""/>
1332
- </a:majorFont>
1333
- <a:minorFont>
1334
- <a:latin typeface="${font}"/>
1335
- <a:ea typeface="${font}"/>
1336
- <a:cs typeface=""/>
1337
- </a:minorFont>
1338
- </a:fontScheme>
1339
- <a:fmtScheme name="Office">
1340
- <a:fillStyleLst>
1341
- <a:solidFill>
1342
- <a:schemeClr val="phClr"/>
1343
- </a:solidFill>
1344
- <a:gradFill rotWithShape="1">
1345
- <a:gsLst>
1346
- <a:gs pos="0">
1347
- <a:schemeClr val="phClr">
1348
- <a:lumMod val="110000"/>
1349
- <a:satMod val="105000"/>
1350
- <a:tint val="67000"/>
1351
- </a:schemeClr>
1352
- </a:gs>
1353
- <a:gs pos="50000">
1354
- <a:schemeClr val="phClr">
1355
- <a:lumMod val="105000"/>
1356
- <a:satMod val="103000"/>
1357
- <a:tint val="73000"/>
1358
- </a:schemeClr>
1359
- </a:gs>
1360
- <a:gs pos="100000">
1361
- <a:schemeClr val="phClr">
1362
- <a:lumMod val="105000"/>
1363
- <a:satMod val="109000"/>
1364
- <a:tint val="81000"/>
1365
- </a:schemeClr>
1366
- </a:gs>
1367
- </a:gsLst>
1368
- <a:lin ang="5400000" scaled="0"/>
1369
- </a:gradFill>
1370
- <a:gradFill rotWithShape="1">
1371
- <a:gsLst>
1372
- <a:gs pos="0">
1373
- <a:schemeClr val="phClr">
1374
- <a:satMod val="103000"/>
1375
- <a:lumMod val="102000"/>
1376
- <a:tint val="94000"/>
1377
- </a:schemeClr>
1378
- </a:gs>
1379
- <a:gs pos="50000">
1380
- <a:schemeClr val="phClr">
1381
- <a:satMod val="110000"/>
1382
- <a:lumMod val="100000"/>
1383
- <a:shade val="100000"/>
1384
- </a:schemeClr>
1385
- </a:gs>
1386
- <a:gs pos="100000">
1387
- <a:schemeClr val="phClr">
1388
- <a:lumMod val="99000"/>
1389
- <a:satMod val="120000"/>
1390
- <a:shade val="78000"/>
1391
- </a:schemeClr>
1392
- </a:gs>
1393
- </a:gsLst>
1394
- <a:lin ang="5400000" scaled="0"/>
1395
- </a:gradFill>
1396
- </a:fillStyleLst>
1397
- <a:lnStyleLst>
1398
- <a:ln w="6350" cap="flat" cmpd="sng" algn="ctr">
1399
- <a:solidFill>
1400
- <a:schemeClr val="phClr"/>
1401
- </a:solidFill>
1402
- <a:prstDash val="solid"/>
1403
- <a:miter lim="800000"/>
1404
- </a:ln>
1405
- <a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">
1406
- <a:solidFill>
1407
- <a:schemeClr val="phClr"/>
1408
- </a:solidFill>
1409
- <a:prstDash val="solid"/>
1410
- <a:miter lim="800000"/>
1411
- </a:ln>
1412
- <a:ln w="19050" cap="flat" cmpd="sng" algn="ctr">
1413
- <a:solidFill>
1414
- <a:schemeClr val="phClr"/>
1415
- </a:solidFill>
1416
- <a:prstDash val="solid"/>
1417
- <a:miter lim="800000"/>
1418
- </a:ln>
1419
- </a:lnStyleLst>
1420
- <a:effectStyleLst>
1421
- <a:effectStyle>
1422
- <a:effectLst/>
1423
- </a:effectStyle>
1424
- <a:effectStyle>
1425
- <a:effectLst/>
1426
- </a:effectStyle>
1427
- <a:effectStyle>
1428
- <a:effectLst>
1429
- <a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0">
1430
- <a:srgbClr val="000000">
1431
- <a:alpha val="63000"/>
1432
- </a:srgbClr>
1433
- </a:outerShdw>
1434
- </a:effectLst>
1435
- </a:effectStyle>
1436
- </a:effectStyleLst>
1437
- <a:bgFillStyleLst>
1438
- <a:solidFill>
1439
- <a:schemeClr val="phClr"/>
1440
- </a:solidFill>
1441
- <a:solidFill>
1442
- <a:schemeClr val="phClr">
1443
- <a:tint val="95000"/>
1444
- <a:satMod val="170000"/>
1445
- </a:schemeClr>
1446
- </a:solidFill>
1447
- <a:gradFill rotWithShape="1">
1448
- <a:gsLst>
1449
- <a:gs pos="0">
1450
- <a:schemeClr val="phClr">
1451
- <a:tint val="93000"/>
1452
- <a:satMod val="150000"/>
1453
- <a:shade val="98000"/>
1454
- <a:lumMod val="102000"/>
1455
- </a:schemeClr>
1456
- </a:gs>
1457
- <a:gs pos="50000">
1458
- <a:schemeClr val="phClr">
1459
- <a:tint val="98000"/>
1460
- <a:satMod val="130000"/>
1461
- <a:shade val="90000"/>
1462
- <a:lumMod val="103000"/>
1463
- </a:schemeClr>
1464
- </a:gs>
1465
- <a:gs pos="100000">
1466
- <a:schemeClr val="phClr">
1467
- <a:shade val="63000"/>
1468
- <a:satMod val="120000"/>
1469
- </a:schemeClr>
1470
- </a:gs>
1471
- </a:gsLst>
1472
- <a:lin ang="5400000" scaled="0"/>
1473
- </a:gradFill>
1474
- </a:bgFillStyleLst>
1475
- </a:fmtScheme>
1476
- </a:themeElements>
1477
- </a:theme>
1478
- `;
1479
-
1480
- const settingsXML = `
1481
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1482
-
1483
- <w:settings xmlns:w="${namespaces.w}" xmlns:o="${namespaces.o}" xmlns:r="${namespaces.r}" xmlns:v="${namespaces.v}" xmlns:w10="${namespaces.w10}" xmlns:sl="${namespaces.sl}">
1484
- <w:zoom w:percent="100"/>
1485
- <w:defaultTabStop w:val="720"/>
1486
- <w:decimalSymbol w:val="."/>
1487
- <w:listSeparator w:val=","/>
1488
- </w:settings>
1489
- `;
1490
-
1491
- const webSettingsXML = `
1492
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1493
-
1494
- <w:webSettings xmlns:w="${namespaces.w}" xmlns:r="${namespaces.r}">
1495
- </w:webSettings>
1496
- `;
1497
-
1498
- const genericRelsXML = `
1499
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1500
-
1501
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
1502
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunk.mht" Id="htmlChunk" />
1503
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkheader.mht" Id="htmlChunkHeader" />
1504
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkfooter.mht" Id="htmlChunkFooter" />
1505
- </Relationships>
1506
- `;
1507
-
1508
- const generateDocumentTemplate = (width, height, orientation, margins) => `
1509
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1510
- <w:document
1511
- xmlns:a="${namespaces.a}"
1512
- xmlns:cdr="${namespaces.cdr}"
1513
- xmlns:o="${namespaces.o}"
1514
- xmlns:pic="${namespaces.pic}"
1515
- xmlns:r="${namespaces.r}"
1516
- xmlns:v="${namespaces.v}"
1517
- xmlns:ve="${namespaces.ve}"
1518
- xmlns:vt="${namespaces.vt}"
1519
- xmlns:w="${namespaces.w}"
1520
- xmlns:w10="${namespaces.w10}"
1521
- xmlns:wp="${namespaces.wp}"
1522
- xmlns:wne="${namespaces.wne}"
1523
- >
1524
- <w:body>
1525
-
1526
- <w:altChunk r:id="htmlChunk" />
1527
- <w:sectPr>
1528
- <w:pgSz w:w="${width}" w:h="${height}" w:orient="${orientation}" />
1529
- <w:pgMar w:top="${margins.top}"
1530
- w:right="${margins.right}"
1531
- w:bottom="${margins.bottom}"
1532
- w:left="${margins.left}"
1533
- w:header="${margins.header}"
1534
- w:footer="${margins.footer}"
1535
- w:gutter="${margins.gutter}"/>
1536
- </w:sectPr>
1537
- </w:body>
1538
- </w:document>
1539
- `;
1540
- const generateDocumentTemplateHeader = `
1541
- <w:hdr
1542
- xmlns:a="${namespaces.a}"
1543
- xmlns:cdr="${namespaces.cdr}"
1544
- xmlns:o="${namespaces.o}"
1545
- xmlns:pic="${namespaces.pic}"
1546
- xmlns:r="${namespaces.r}"
1547
- xmlns:v="${namespaces.v}"
1548
- xmlns:ve="${namespaces.ve}"
1549
- xmlns:vt="${namespaces.vt}"
1550
- xmlns:w="${namespaces.w}"
1551
- xmlns:w10="${namespaces.w10}"
1552
- xmlns:wp="${namespaces.wp}"
1553
- xmlns:wne="${namespaces.wne}"
1554
- >
1555
- <w:altChunk r:id="htmlChunkHeader" />
1556
- </w:hdr>
1557
- `;
1558
- const generateDocumentTemplateFooter = `
1559
- <w:ftr
1560
- xmlns:a="${namespaces.a}"
1561
- xmlns:cdr="${namespaces.cdr}"
1562
- xmlns:o="${namespaces.o}"
1563
- xmlns:pic="${namespaces.pic}"
1564
- xmlns:r="${namespaces.r}"
1565
- xmlns:v="${namespaces.v}"
1566
- xmlns:ve="${namespaces.ve}"
1567
- xmlns:vt="${namespaces.vt}"
1568
- xmlns:w="${namespaces.w}"
1569
- xmlns:w10="${namespaces.w10}"
1570
- xmlns:wp="${namespaces.wp}"
1571
- >
1572
- <w:altChunk r:id="htmlChunkFooter" />
1573
- <w:p w:rsidR="0014021C" w:rsidRDefault="0014021C" w:rsidP="0014021C">
1574
- <w:pPr>
1575
- <w:pStyle w:val="Footer"/>
1576
- <w:jc w:val="center"/>
1577
- </w:pPr>
1578
- <w:fldSimple xmlns:ns2="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns2:instr="PAGE">
1579
- <w:r/>
1580
- </w:fldSimple>
1581
- </w:p>
1582
- </w:ftr>
1583
- `;
1584
- const generateDocumentTemplateFooterWithoutPaging = `
1585
- <w:ftr
1586
- xmlns:a="${namespaces.a}"
1587
- xmlns:cdr="${namespaces.cdr}"
1588
- xmlns:o="${namespaces.o}"
1589
- xmlns:pic="${namespaces.pic}"
1590
- xmlns:r="${namespaces.r}"
1591
- xmlns:v="${namespaces.v}"
1592
- xmlns:ve="${namespaces.ve}"
1593
- xmlns:vt="${namespaces.vt}"
1594
- xmlns:w="${namespaces.w}"
1595
- xmlns:w10="${namespaces.w10}"
1596
- xmlns:wp="${namespaces.wp}"
1597
- >
1598
- <w:altChunk r:id="htmlChunkFooter" />
1599
- </w:ftr>
1600
- `;
1601
- { /* <w:altChunk r:id="htmlChunkFooter" /> */ }
1602
- {
1603
- /* <w:altChunk r:id="htmlChunkFooter" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" /> */
1604
- }
1605
- {
1606
- /* <w:ftr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
1607
- <fldSimple xmlns:ns2="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns2:instr="PAGE">
1608
- </fldSimple>
1609
- <w:altChunk r:id="htmlChunkFooter" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
1610
- </w:ftr> */
877
+ /**
878
+ * Language service with internal caching
879
+ */
880
+ class LanguageService {
881
+ constructor(http) {
882
+ this.http = http;
883
+ this.apiUrl = '/api/Language/';
884
+ this._languages = [];
885
+ this.isLoading = false;
886
+ this.isLoaded = false;
887
+ this.loadRequest$ = null;
888
+ }
889
+ /** Pure getter - no side effects */
890
+ get languages() {
891
+ return this._languages;
892
+ }
893
+ /** Internal method - loads languages from API (race-condition safe) */
894
+ loadLanguages() {
895
+ if (this.isLoaded || this.isLoading)
896
+ return; // Sync guard prevents race condition
897
+ this.isLoading = true; // Set immediately to block concurrent calls
898
+ this.loadRequest$ = this.http.get(this.apiUrl + 'GetAll', null, null).pipe(tap((languages) => {
899
+ this._languages = languages;
900
+ this.isLoaded = true;
901
+ this.isLoading = false;
902
+ }), shareReplay(1));
903
+ // take(1) ensures auto-unsubscribe after completion
904
+ this.loadRequest$.pipe(take(1)).subscribe({
905
+ error: (err) => {
906
+ this.isLoading = false;
907
+ this.loadRequest$ = null;
908
+ }
909
+ });
910
+ }
911
+ /** Get languages as Observable - triggers load if not loaded */
912
+ getLanguages() {
913
+ if (this.isLoaded) {
914
+ return of(this._languages);
915
+ }
916
+ if (!this.isLoading) {
917
+ this.loadLanguages();
918
+ }
919
+ return this.loadRequest$ ?? of(this._languages);
920
+ }
921
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LanguageService, deps: [{ token: RequestHandlerService }], target: i0.ɵɵFactoryTarget.Injectable }); }
922
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LanguageService, providedIn: 'root' }); }
1611
923
  }
924
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LanguageService, decorators: [{
925
+ type: Injectable,
926
+ args: [{
927
+ providedIn: 'root',
928
+ }]
929
+ }], ctorParameters: () => [{ type: RequestHandlerService }] });
1612
930
 
1613
- /* eslint-disable no-param-reassign */
1614
- const rgbRegex = /rgb\((\d+),\s*([\d.]+),\s*([\d.]+)\)/i;
1615
- const hslRegex = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/i;
1616
- const hexRegex = /#([0-9A-F]{6})/i;
1617
- const hex3Regex = /#([0-9A-F])([0-9A-F])([0-9A-F])/i;
1618
- // eslint-disable-next-line import/prefer-default-export
1619
- const rgbToHex = (red, green, blue) => {
1620
- const hexColorCode = [red, green, blue]
1621
- .map((x) => {
1622
- // eslint-disable-next-line radix, no-param-reassign
1623
- x = parseInt(x).toString(16);
1624
- return x.length === 1 ? `0${x}` : x;
1625
- })
1626
- .join('');
1627
- return hexColorCode;
1628
- };
1629
- const hslToHex = (hue, saturation, luminosity) => {
1630
- hue /= 360;
1631
- saturation /= 100;
1632
- luminosity /= 100;
1633
- // eslint-disable-next-line one-var
1634
- let red, green, blue;
1635
- if (saturation === 0) {
1636
- // eslint-disable-next-line no-multi-assign
1637
- red = green = blue = luminosity; // achromatic
931
+ class SpeechRecognitionService {
932
+ constructor(zone, utilityService) {
933
+ this.zone = zone;
934
+ this.utilityService = utilityService;
935
+ this.isListening = false;
936
+ this.isSupported = false;
937
+ this.language = 'en-US';
938
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
939
+ if (SpeechRecognition) {
940
+ this.recognition = new SpeechRecognition();
941
+ this.recognition.continuous = true;
942
+ this.recognition.interimResults = false;
943
+ this.recognition.maxAlternatives = 1;
944
+ this.isSupported = true;
945
+ }
1638
946
  }
1639
- else {
1640
- const hue2rgb = (p, q, t) => {
1641
- if (t < 0)
1642
- t += 1;
1643
- if (t > 1)
1644
- t -= 1;
1645
- if (t < 1 / 6)
1646
- return p + (q - p) * 6 * t;
1647
- if (t < 1 / 2)
1648
- return q;
1649
- if (t < 2 / 3)
1650
- return p + (q - p) * (2 / 3 - t) * 6;
1651
- return p;
1652
- };
1653
- const q = luminosity < 0.5
1654
- ? luminosity * (1 + saturation)
1655
- : luminosity + saturation - luminosity * saturation;
1656
- const p = 2 * luminosity - q;
1657
- red = hue2rgb(p, q, hue + 1 / 3);
1658
- green = hue2rgb(p, q, hue);
1659
- blue = hue2rgb(p, q, hue - 1 / 3);
947
+ startListening(language = this.language) {
948
+ if (!this.isSupported) {
949
+ return throwError(() => new Error('Web Speech API is not supported in this browser.'));
950
+ }
951
+ return new Observable(observer => {
952
+ this.isListening = true;
953
+ this.recognition.lang = language;
954
+ this.recognition.start();
955
+ this.recognition.onresult = (event) => {
956
+ this.zone.run(() => {
957
+ const transcript = event.results[event.results.length - 1][0].transcript;
958
+ observer.next(transcript);
959
+ });
960
+ };
961
+ this.recognition.onspeechend = () => {
962
+ this.stopListening();
963
+ };
964
+ this.recognition.onerror = (event) => {
965
+ this.zone.run(() => {
966
+ if (event.error === 'not-allowed') {
967
+ this.utilityService.notifyErrorMessage(this.utilityService.getResourceValue("MicAccessDenied"));
968
+ observer.error('Microphone access denied by the user.');
969
+ }
970
+ else {
971
+ observer.error(event.error);
972
+ }
973
+ });
974
+ };
975
+ this.recognition.onend = () => {
976
+ this.zone.run(() => {
977
+ if (this.isListening) {
978
+ this.recognition.start(); // Automatically restart
979
+ }
980
+ else {
981
+ observer.complete();
982
+ }
983
+ });
984
+ };
985
+ });
1660
986
  }
1661
- return [red, green, blue]
1662
- .map((x) => {
1663
- const hex = Math.round(x * 255).toString(16);
1664
- return hex.length === 1 ? `0${hex}` : hex;
1665
- })
1666
- .join('');
1667
- };
1668
- const hex3ToHex = (red, green, blue) => {
1669
- const hexColorCode = [red, green, blue].map((x) => `${x}${x}`).join('');
1670
- return hexColorCode;
1671
- };
1672
-
1673
- const pixelRegex = /([\d.]+)px/i;
1674
- const percentageRegex = /([\d.]+)%/i;
1675
- const pointRegex = /([\d.]+)pt/i;
1676
- const cmRegex = /([\d.]+)cm/i;
1677
- const inchRegex = /([\d.]+)in/i;
1678
- const pixelToEMU = (pixelValue) => Math.round(pixelValue * 9525);
1679
- const EMUToPixel = (EMUValue) => Math.round(EMUValue / 9525);
1680
- const TWIPToEMU = (TWIPValue) => Math.round(TWIPValue * 635);
1681
- const EMUToTWIP = (EMUValue) => Math.round(EMUValue / 635);
1682
- const pointToTWIP = (pointValue) => Math.round(pointValue * 20);
1683
- const TWIPToPoint = (TWIPValue) => Math.round(TWIPValue / 20);
1684
- const pointToHIP = (pointValue) => Math.round(pointValue * 2);
1685
- const HIPToPoint = (HIPValue) => Math.round(HIPValue / 2);
1686
- const HIPToTWIP = (HIPValue) => Math.round(HIPValue * 10);
1687
- const TWIPToHIP = (TWIPValue) => Math.round(TWIPValue / 10);
1688
- const pixelToTWIP = (pixelValue) => EMUToTWIP(pixelToEMU(pixelValue));
1689
- const TWIPToPixel = (TWIPValue) => EMUToPixel(TWIPToEMU(TWIPValue));
1690
- const pixelToHIP = (pixelValue) => TWIPToHIP(EMUToTWIP(pixelToEMU(pixelValue)));
1691
- const HIPToPixel = (HIPValue) => EMUToPixel(TWIPToEMU(HIPToTWIP(HIPValue)));
1692
- const inchToPoint = (inchValue) => Math.round(inchValue * 72);
1693
- const inchToTWIP = (inchValue) => pointToTWIP(inchToPoint(inchValue));
1694
- const cmToInch = (cmValue) => cmValue * 0.3937008;
1695
- const cmToTWIP = (cmValue) => inchToTWIP(cmToInch(cmValue));
1696
- const pixelToPoint = (pixelValue) => HIPToPoint(pixelToHIP(pixelValue));
1697
- const pointToPixel = (pointValue) => HIPToPixel(pointToHIP(pointValue));
1698
- const EIPToPoint = (EIPValue) => Math.round(EIPValue / 8);
1699
- const pointToEIP = (PointValue) => Math.round(PointValue * 8);
1700
- const pixelToEIP = (pixelValue) => pointToEIP(pixelToPoint(pixelValue));
1701
- const EIPToPixel = (EIPValue) => pointToPixel(EIPToPoint(EIPValue));
1702
-
1703
- // eslint-disable-next-line import/prefer-default-export
1704
- const vNodeHasChildren = (vNode) => vNode && vNode.children && Array.isArray(vNode.children) && vNode.children.length;
1705
-
1706
- const isValidUrl = (urlString) => {
1707
- const urlRegex = /http(s)?:\/\/(\w+:?\w*@)?(\S+)(:\d+)?((?<=\.)\w+)+(\/([\w#!:.?+=&%@!\-/])*)?/gi;
1708
- return Boolean(urlRegex.test(urlString));
1709
- };
987
+ stopListening() {
988
+ if (this.isSupported) {
989
+ this.isListening = false;
990
+ this.recognition.stop();
991
+ }
992
+ }
993
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SpeechRecognitionService, deps: [{ token: i0.NgZone }, { token: UtilityService }], target: i0.ɵɵFactoryTarget.Injectable }); }
994
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SpeechRecognitionService, providedIn: 'root' }); }
995
+ }
996
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SpeechRecognitionService, decorators: [{
997
+ type: Injectable,
998
+ args: [{
999
+ providedIn: 'root'
1000
+ }]
1001
+ }], ctorParameters: () => [{ type: i0.NgZone }, { type: UtilityService }] });
1710
1002
 
1711
- /* eslint-disable no-await-in-loop */
1712
- /* eslint-disable radix */
1713
- /* eslint-disable no-param-reassign */
1714
- /* eslint-disable no-case-declarations */
1715
- /* eslint-disable no-plusplus */
1716
- /* eslint-disable no-else-return */
1717
- // eslint-disable-next-line consistent-return
1718
- const fixupColorCode = (colorCodeString) => {
1719
- if (Object.prototype.hasOwnProperty.call(colorNames, colorCodeString.toLowerCase())) {
1720
- const [red, green, blue] = colorNames[colorCodeString.toLowerCase()];
1721
- return rgbToHex(red, green, blue);
1003
+ class FileLoaderService {
1004
+ // environment:any;
1005
+ constructor(translate, http) {
1006
+ this.translate = translate;
1007
+ this.http = http;
1008
+ this.availableLanguages = ['en', 'ar']; // Add more languages as needed
1009
+ this.translate.addLangs(this.availableLanguages);
1722
1010
  }
1723
- else if (rgbRegex.test(colorCodeString)) {
1724
- const matchedParts = colorCodeString.match(rgbRegex);
1725
- const red = matchedParts[1];
1726
- const green = matchedParts[2];
1727
- const blue = matchedParts[3];
1728
- return rgbToHex(red, green, blue);
1011
+ loadEnvironment() {
1012
+ return new Promise((resolve, reject) => {
1013
+ const script = document.createElement('script');
1014
+ script.src = '/assets/config/environment.js';
1015
+ script.onload = () => {
1016
+ if (window.Environment) {
1017
+ Object.assign(environment, window.Environment);
1018
+ resolve();
1019
+ }
1020
+ else {
1021
+ reject('Environment variables not found.');
1022
+ }
1023
+ };
1024
+ script.onerror = () => reject('Failed to load environment.js');
1025
+ document.head.appendChild(script);
1026
+ });
1729
1027
  }
1730
- else if (hslRegex.test(colorCodeString)) {
1731
- const matchedParts = colorCodeString.match(hslRegex);
1732
- const hue = matchedParts[1];
1733
- const saturation = matchedParts[2];
1734
- const luminosity = matchedParts[3];
1735
- return hslToHex(hue, saturation, luminosity);
1028
+ async preloadTranslations() {
1029
+ try {
1030
+ const requests = this.availableLanguages.map(async (lang) => {
1031
+ const translations = await lastValueFrom(this.http.get(`/assets/i18n/${lang}.json`));
1032
+ this.translate.setTranslation(lang, translations, true);
1033
+ });
1034
+ await Promise.all(requests);
1035
+ this.translate.use('en'); // Set default language manually
1036
+ }
1037
+ catch (error) {
1038
+ console.error('Error preloading translations:', error);
1039
+ }
1736
1040
  }
1737
- else if (hexRegex.test(colorCodeString)) {
1738
- const matchedParts = colorCodeString.match(hexRegex);
1739
- return matchedParts[1];
1041
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: FileLoaderService, deps: [{ token: BBSFTranslateService }, { token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
1042
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: FileLoaderService, providedIn: 'root' }); }
1043
+ }
1044
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: FileLoaderService, decorators: [{
1045
+ type: Injectable,
1046
+ args: [{
1047
+ providedIn: 'root',
1048
+ }]
1049
+ }], ctorParameters: () => [{ type: BBSFTranslateService }, { type: i1.HttpClient }] });
1050
+
1051
+ class AuthService {
1052
+ static { this.user = null; }
1053
+ get user() {
1054
+ if (!this._user) {
1055
+ this._user = this.getUserManager();
1056
+ }
1057
+ return this._user;
1740
1058
  }
1741
- else if (hex3Regex.test(colorCodeString)) {
1742
- const matchedParts = colorCodeString.match(hex3Regex);
1743
- const red = matchedParts[1];
1744
- const green = matchedParts[2];
1745
- const blue = matchedParts[3];
1746
- return hex3ToHex(red, green, blue);
1059
+ static { this.UserClaims = null; }
1060
+ //refresh
1061
+ static { this.timers = []; }
1062
+ static { this.seconds = 0; }
1063
+ constructor(injector, http, environmentService, translateService, router, cookieService, utilityService) {
1064
+ this.injector = injector;
1065
+ this.http = http;
1066
+ this.environmentService = environmentService;
1067
+ this.translateService = translateService;
1068
+ this.router = router;
1069
+ this.cookieService = cookieService;
1070
+ this.utilityService = utilityService;
1071
+ this.redirectUrl = '';
1072
+ this.jwtHelper = new JwtHelperService();
1073
+ this.isAuthenticatedSubject = new BehaviorSubject(this.hasToken());
1074
+ this.isAuthenticate$ = this.isAuthenticatedSubject.asObservable();
1747
1075
  }
1748
- else {
1749
- return '000000';
1076
+ get TOKEN_KEY() {
1077
+ if (!this._TOKEN_KEY) {
1078
+ this._TOKEN_KEY = this.environmentService.getCookieName();
1079
+ }
1080
+ return this._TOKEN_KEY;
1750
1081
  }
1751
- };
1752
- const buildRunFontFragment = (fontName = defaultFont) => fragment({ namespaceAlias: { w: namespaces.w } })
1753
- .ele('@w', 'rFonts')
1754
- .att('@w', 'ascii', fontName)
1755
- .att('@w', 'hAnsi', fontName)
1756
- .up();
1757
- const buildRunStyleFragment = (type = 'Hyperlink') => fragment({ namespaceAlias: { w: namespaces.w } })
1758
- .ele('@w', 'rStyle')
1759
- .att('@w', 'val', type)
1760
- .up();
1761
- const buildTableRowHeight = (tableRowHeight) => fragment({ namespaceAlias: { w: namespaces.w } })
1762
- .ele('@w', 'trHeight')
1763
- .att('@w', 'val', tableRowHeight)
1764
- .att('@w', 'hRule', 'atLeast')
1765
- .up();
1766
- const buildVerticalAlignment = (verticalAlignment) => {
1767
- if (verticalAlignment.toLowerCase() === 'middle') {
1768
- verticalAlignment = 'center';
1082
+ hasToken() {
1083
+ const token = this.cookieService.get(this.TOKEN_KEY);
1084
+ return token && !this.jwtHelper.isTokenExpired(token);
1769
1085
  }
1770
- return fragment({ namespaceAlias: { w: namespaces.w } })
1771
- .ele('@w', 'vAlign')
1772
- .att('@w', 'val', verticalAlignment)
1773
- .up();
1774
- };
1775
- const buildVerticalMerge = (verticalMerge = 'continue') => fragment({ namespaceAlias: { w: namespaces.w } })
1776
- .ele('@w', 'vMerge')
1777
- .att('@w', 'val', verticalMerge)
1778
- .up();
1779
- const buildColor = (colorCode) => fragment({ namespaceAlias: { w: namespaces.w } })
1780
- .ele('@w', 'color')
1781
- .att('@w', 'val', colorCode)
1782
- .up();
1783
- const buildFontSize = (fontSize) => fragment({ namespaceAlias: { w: namespaces.w } })
1784
- .ele('@w', 'sz')
1785
- .att('@w', 'val', fontSize)
1786
- .up();
1787
- const buildShading = (colorCode) => fragment({ namespaceAlias: { w: namespaces.w } })
1788
- .ele('@w', 'shd')
1789
- .att('@w', 'val', 'clear')
1790
- .att('@w', 'fill', colorCode)
1791
- .up();
1792
- const buildHighlight = (color = 'yellow') => fragment({ namespaceAlias: { w: namespaces.w } })
1793
- .ele('@w', 'highlight')
1794
- .att('@w', 'val', color)
1795
- .up();
1796
- const buildVertAlign = (type = 'baseline') => fragment({ namespaceAlias: { w: namespaces.w } })
1797
- .ele('@w', 'vertAlign')
1798
- .att('@w', 'val', type)
1799
- .up();
1800
- const buildStrike = () => fragment({ namespaceAlias: { w: namespaces.w } })
1801
- .ele('@w', 'strike')
1802
- .att('@w', 'val', true)
1803
- .up();
1804
- const buildBold = () => fragment({ namespaceAlias: { w: namespaces.w } })
1805
- .ele('@w', 'b')
1806
- .up();
1807
- const buildItalics = () => fragment({ namespaceAlias: { w: namespaces.w } })
1808
- .ele('@w', 'i')
1809
- .up();
1810
- const buildUnderline = (type = 'single') => fragment({ namespaceAlias: { w: namespaces.w } })
1811
- .ele('@w', 'u')
1812
- .att('@w', 'val', type)
1813
- .up();
1814
- const buildLineBreak = (type = 'textWrapping') => fragment({ namespaceAlias: { w: namespaces.w } })
1815
- .ele('@w', 'br')
1816
- .att('@w', 'type', type)
1817
- .up();
1818
- const buildBorder = (borderSide = 'top', borderSize = 0, borderSpacing = 0, borderColor = fixupColorCode('black'), borderStroke = 'single') => fragment({ namespaceAlias: { w: namespaces.w } })
1819
- .ele('@w', borderSide)
1820
- .att('@w', 'val', borderStroke)
1821
- .att('@w', 'sz', borderSize)
1822
- .att('@w', 'space', borderSpacing)
1823
- .att('@w', 'color', borderColor)
1824
- .up();
1825
- const buildTextElement = (text) => fragment({ namespaceAlias: { w: namespaces.w } })
1826
- .ele('@w', 't')
1827
- .att('@xml', 'space', 'preserve')
1828
- .txt(text)
1829
- .up();
1830
- // eslint-disable-next-line consistent-return
1831
- const fixupLineHeight = (lineHeight, fontSize) => {
1832
- // FIXME: If line height is anything other than a number
1833
- // eslint-disable-next-line no-restricted-globals
1834
- if (!isNaN(lineHeight)) {
1835
- if (fontSize) {
1836
- const actualLineHeight = +lineHeight * fontSize;
1837
- return HIPToTWIP(actualLineHeight);
1086
+ getUserManager() {
1087
+ const token = this.cookieService.get(this.TOKEN_KEY);
1088
+ if (token) {
1089
+ if (!this.jwtHelper.isTokenExpired(token))
1090
+ this.handleAccessTokenWithoutLanguage(token);
1091
+ else
1092
+ this.cookieService.delete(this.TOKEN_KEY, '/');
1838
1093
  }
1839
1094
  else {
1840
- // 240 TWIP or 12 point is default line height
1841
- return +lineHeight * 240;
1095
+ AuthService.timers.map(t => clearInterval(t));
1096
+ AuthService.timers = [];
1097
+ AuthService.user = null;
1098
+ this._user = null;
1842
1099
  }
1100
+ return AuthService.user;
1843
1101
  }
1844
- else {
1845
- // 240 TWIP or 12 point is default line height
1846
- return 240;
1847
- }
1848
- };
1849
- // eslint-disable-next-line consistent-return
1850
- const fixupFontSize$1 = (fontSizeString) => {
1851
- if (pointRegex.test(fontSizeString)) {
1852
- const matchedParts = fontSizeString.match(pointRegex);
1853
- // convert point to half point
1854
- return pointToHIP(matchedParts[1]);
1102
+ getUser() {
1103
+ this._user = AuthService.user;
1855
1104
  }
1856
- else if (pixelRegex.test(fontSizeString)) {
1857
- const matchedParts = fontSizeString.match(pixelRegex);
1858
- // convert pixels to half point
1859
- return pixelToHIP(matchedParts[1]);
1105
+ storUser(User) {
1106
+ AuthService.user = this._user = this.user;
1860
1107
  }
1861
- };
1862
- // eslint-disable-next-line consistent-return
1863
- const fixupRowHeight = (rowHeightString) => {
1864
- if (pointRegex.test(rowHeightString)) {
1865
- const matchedParts = rowHeightString.match(pointRegex);
1866
- // convert point to half point
1867
- return pointToTWIP(matchedParts[1]);
1108
+ getCurrentUser() {
1109
+ return AuthService.user;
1868
1110
  }
1869
- else if (pixelRegex.test(rowHeightString)) {
1870
- const matchedParts = rowHeightString.match(pixelRegex);
1871
- // convert pixels to half point
1872
- return pixelToTWIP(matchedParts[1]);
1111
+ isAuthenticated() {
1112
+ AuthService.user = this.user;
1113
+ return AuthService.user != null && !this.jwtHelper.isTokenExpired(AuthService.user.access_token);
1873
1114
  }
1874
- else if (cmRegex.test(rowHeightString)) {
1875
- const matchedParts = rowHeightString.match(cmRegex);
1876
- return cmToTWIP(matchedParts[1]);
1115
+ isUserInRole(allowedPermission) {
1116
+ let selectedPermissionSetID = Number.parseInt(AuthService.user.profile['selectedpermissionsetid']);
1117
+ return allowedPermission.includes(selectedPermissionSetID);
1877
1118
  }
1878
- else if (inchRegex.test(rowHeightString)) {
1879
- const matchedParts = rowHeightString.match(inchRegex);
1880
- return inchToTWIP(matchedParts[1]);
1119
+ isUserPermissionSetsInRoles(allowedPermission) {
1120
+ const permissionSetSIDString = AuthService.user.profile['permissionSetSID'];
1121
+ if (!permissionSetSIDString) {
1122
+ return false;
1123
+ }
1124
+ // Split comma-separated string and convert to numbers
1125
+ const userPermissionSets = permissionSetSIDString
1126
+ .split(',')
1127
+ .map(id => Number.parseInt(id.trim()))
1128
+ .filter(id => !isNaN(id)); // Filter out invalid numbers
1129
+ // Check if any user permission set is in the allowed permissions
1130
+ return userPermissionSets.some(permissionSetID => allowedPermission.includes(permissionSetID));
1881
1131
  }
1882
- };
1883
- // eslint-disable-next-line consistent-return
1884
- const fixupColumnWidth = (columnWidthString) => {
1885
- if (pointRegex.test(columnWidthString)) {
1886
- const matchedParts = columnWidthString.match(pointRegex);
1887
- return pointToTWIP(matchedParts[1]);
1132
+ authorizationHeaderValue() {
1133
+ return AuthService.user
1134
+ ? `${AuthService.user.token_type} ${AuthService.user.access_token}`
1135
+ : '';
1888
1136
  }
1889
- else if (pixelRegex.test(columnWidthString)) {
1890
- const matchedParts = columnWidthString.match(pixelRegex);
1891
- return pixelToTWIP(matchedParts[1]);
1137
+ name() {
1138
+ return AuthService.user != null ? AuthService.user.profile.given_name : '';
1892
1139
  }
1893
- else if (cmRegex.test(columnWidthString)) {
1894
- const matchedParts = columnWidthString.match(cmRegex);
1895
- return cmToTWIP(matchedParts[1]);
1140
+ setUrl(url) {
1141
+ localStorage.setItem('redirectUrl', url);
1896
1142
  }
1897
- else if (inchRegex.test(columnWidthString)) {
1898
- const matchedParts = columnWidthString.match(inchRegex);
1899
- return inchToTWIP(matchedParts[1]);
1900
- }
1901
- };
1902
- // eslint-disable-next-line consistent-return
1903
- const fixupMargin = (marginString) => {
1904
- if (pointRegex.test(marginString)) {
1905
- const matchedParts = marginString.match(pointRegex);
1906
- // convert point to half point
1907
- return pointToTWIP(matchedParts[1]);
1908
- }
1909
- else if (pixelRegex.test(marginString)) {
1910
- const matchedParts = marginString.match(pixelRegex);
1911
- // convert pixels to half point
1912
- return pixelToTWIP(matchedParts[1]);
1913
- }
1914
- };
1915
- const modifiedStyleAttributesBuilder = (vNode, attributes, options) => {
1916
- const modifiedAttributes = { ...attributes };
1917
- // styles
1918
- if (isVNode(vNode) && vNode.properties && vNode.properties.style) {
1919
- if (vNode.properties.style.color && !colorlessColors.includes(vNode.properties.style.color)) {
1920
- modifiedAttributes.color = fixupColorCode(vNode.properties.style.color);
1921
- }
1922
- if (vNode.properties.style['background-color'] &&
1923
- !colorlessColors.includes(vNode.properties.style['background-color'])) {
1924
- modifiedAttributes.backgroundColor = fixupColorCode(vNode.properties.style['background-color']);
1925
- }
1926
- if (vNode.properties.style['vertical-align'] &&
1927
- verticalAlignValues.includes(vNode.properties.style['vertical-align'])) {
1928
- modifiedAttributes.verticalAlign = vNode.properties.style['vertical-align'];
1929
- }
1930
- if (vNode.properties.style['text-align'] &&
1931
- ['left', 'right', 'center', 'justify'].includes(vNode.properties.style['text-align'])) {
1932
- modifiedAttributes.textAlign = vNode.properties.style['text-align'];
1933
- }
1934
- // FIXME: remove bold check when other font weights are handled.
1935
- if (vNode.properties.style['font-weight'] && vNode.properties.style['font-weight'] === 'bold') {
1936
- modifiedAttributes.strong = vNode.properties.style['font-weight'];
1937
- }
1938
- if (vNode.properties.style['font-size']) {
1939
- modifiedAttributes.fontSize = fixupFontSize$1(vNode.properties.style['font-size']);
1940
- }
1941
- if (vNode.properties.style['line-height']) {
1942
- modifiedAttributes.lineHeight = fixupLineHeight(vNode.properties.style['line-height'], vNode.properties.style['font-size']
1943
- ? fixupFontSize$1(vNode.properties.style['font-size'])
1944
- : null);
1945
- }
1946
- if (vNode.properties.style['margin-left'] || vNode.properties.style['margin-right']) {
1947
- const leftMargin = fixupMargin(vNode.properties.style['margin-left']);
1948
- const rightMargin = fixupMargin(vNode.properties.style['margin-right']);
1949
- const indentation = {};
1950
- if (leftMargin) {
1951
- indentation.left = leftMargin;
1952
- }
1953
- if (rightMargin) {
1954
- indentation.right = rightMargin;
1955
- }
1956
- if (leftMargin || rightMargin) {
1957
- modifiedAttributes.indentation = indentation;
1958
- }
1959
- }
1960
- if (vNode.properties.style.display) {
1961
- modifiedAttributes.display = vNode.properties.style.display;
1962
- }
1963
- if (vNode.properties.style.width) {
1964
- modifiedAttributes.width = vNode.properties.style.width;
1965
- }
1966
- }
1967
- // paragraph only
1968
- if (options && options.isParagraph) {
1969
- if (isVNode(vNode) && vNode.tagName === 'blockquote') {
1970
- modifiedAttributes.indentation = { left: 284 };
1971
- modifiedAttributes.textAlign = 'justify';
1972
- }
1973
- else if (isVNode(vNode) && vNode.tagName === 'code') {
1974
- modifiedAttributes.highlightColor = 'lightGray';
1975
- }
1976
- else if (isVNode(vNode) && vNode.tagName === 'pre') {
1977
- modifiedAttributes.font = 'Courier';
1978
- }
1979
- }
1980
- return modifiedAttributes;
1981
- };
1982
- // html tag to formatting function
1983
- // options are passed to the formatting function if needed
1984
- const buildFormatting = (htmlTag, options) => {
1985
- switch (htmlTag) {
1986
- case 'strong':
1987
- case 'b':
1988
- return buildBold();
1989
- case 'em':
1990
- case 'i':
1991
- return buildItalics();
1992
- case 'ins':
1993
- case 'u':
1994
- return buildUnderline();
1995
- case 'strike':
1996
- case 'del':
1997
- case 's':
1998
- return buildStrike();
1999
- case 'sub':
2000
- return buildVertAlign('subscript');
2001
- case 'sup':
2002
- return buildVertAlign('superscript');
2003
- case 'mark':
2004
- return buildHighlight();
2005
- case 'code':
2006
- return buildHighlight('lightGray');
2007
- case 'highlightColor':
2008
- return buildHighlight(options && options.color ? options.color : 'lightGray');
2009
- case 'font':
2010
- case 'pre':
2011
- return buildRunFontFragment('Courier');
2012
- case 'color':
2013
- return buildColor(options && options.color ? options.color : 'black');
2014
- case 'backgroundColor':
2015
- return buildShading(options && options.color ? options.color : 'black');
2016
- case 'fontSize':
2017
- // does this need a unit of measure?
2018
- return buildFontSize(options && options.fontSize ? options.fontSize : 10);
2019
- case 'hyperlink':
2020
- return buildRunStyleFragment('Hyperlink');
2021
- }
2022
- return null;
2023
- };
2024
- const buildRunProperties = (attributes) => {
2025
- const runPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'rPr');
2026
- if (attributes && attributes.constructor === Object) {
2027
- Object.keys(attributes).forEach((key) => {
2028
- const options = {};
2029
- if (key === 'color' || key === 'backgroundColor' || key === 'highlightColor') {
2030
- options.color = attributes[key];
2031
- }
2032
- if (key === 'fontSize') {
2033
- options.fontSize = attributes[key];
2034
- }
2035
- const formattingFragment = buildFormatting(key, options);
2036
- if (formattingFragment) {
2037
- runPropertiesFragment.import(formattingFragment);
2038
- }
2039
- });
2040
- }
2041
- runPropertiesFragment.up();
2042
- return runPropertiesFragment;
2043
- };
2044
- const buildRun = async (vNode, attributes, docxDocumentInstance) => {
2045
- const runFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
2046
- const runPropertiesFragment = buildRunProperties(cloneDeep(attributes));
2047
- // case where we have recursive spans representing font changes
2048
- if (isVNode(vNode) && vNode.tagName === 'span') {
2049
- // eslint-disable-next-line no-use-before-define
2050
- return buildRunOrRuns(vNode, attributes, docxDocumentInstance);
2051
- }
2052
- if (isVNode(vNode) &&
2053
- [
2054
- 'strong',
2055
- 'b',
2056
- 'em',
2057
- 'i',
2058
- 'u',
2059
- 'ins',
2060
- 'strike',
2061
- 'del',
2062
- 's',
2063
- 'sub',
2064
- 'sup',
2065
- 'mark',
2066
- 'blockquote',
2067
- 'code',
2068
- 'pre',
2069
- ].includes(vNode.tagName)) {
2070
- const runFragmentsArray = [];
2071
- let vNodes = [vNode];
2072
- // create temp run fragments to split the paragraph into different runs
2073
- let tempAttributes = cloneDeep(attributes);
2074
- let tempRunFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
2075
- while (vNodes.length) {
2076
- const tempVNode = vNodes.shift();
2077
- if (isVText(tempVNode)) {
2078
- const textFragment = buildTextElement(tempVNode.text);
2079
- const tempRunPropertiesFragment = buildRunProperties({ ...attributes, ...tempAttributes });
2080
- tempRunFragment.import(tempRunPropertiesFragment);
2081
- tempRunFragment.import(textFragment);
2082
- runFragmentsArray.push(tempRunFragment);
2083
- // re initialize temp run fragments with new fragment
2084
- tempAttributes = cloneDeep(attributes);
2085
- tempRunFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
2086
- }
2087
- else if (isVNode(tempVNode)) {
2088
- if ([
2089
- 'strong',
2090
- 'b',
2091
- 'em',
2092
- 'i',
2093
- 'u',
2094
- 'ins',
2095
- 'strike',
2096
- 'del',
2097
- 's',
2098
- 'sub',
2099
- 'sup',
2100
- 'mark',
2101
- 'code',
2102
- 'pre',
2103
- ].includes(tempVNode.tagName)) {
2104
- tempAttributes = {};
2105
- switch (tempVNode.tagName) {
2106
- case 'strong':
2107
- case 'b':
2108
- tempAttributes.strong = true;
2109
- break;
2110
- case 'i':
2111
- tempAttributes.i = true;
2112
- break;
2113
- case 'u':
2114
- tempAttributes.u = true;
2115
- break;
2116
- case 'sub':
2117
- tempAttributes.sub = true;
2118
- break;
2119
- case 'sup':
2120
- tempAttributes.sup = true;
2121
- break;
2122
- }
2123
- const formattingFragment = buildFormatting(tempVNode);
2124
- if (formattingFragment) {
2125
- runPropertiesFragment.import(formattingFragment);
2126
- }
2127
- // go a layer deeper if there is a span somewhere in the children
2128
- }
2129
- else if (tempVNode.tagName === 'span') {
2130
- // eslint-disable-next-line no-use-before-define
2131
- const spanFragment = await buildRunOrRuns(tempVNode, { ...attributes, ...tempAttributes }, docxDocumentInstance);
2132
- // if spanFragment is an array, we need to add each fragment to the runFragmentsArray. If the fragment is an array, perform a depth first search on the array to add each fragment to the runFragmentsArray
2133
- if (Array.isArray(spanFragment)) {
2134
- spanFragment.flat(Infinity);
2135
- runFragmentsArray.push(...spanFragment);
2136
- }
2137
- else {
2138
- runFragmentsArray.push(spanFragment);
2139
- }
2140
- // do not slice and concat children since this is already accounted for in the buildRunOrRuns function
2141
- // eslint-disable-next-line no-continue
2142
- continue;
2143
- }
2144
- }
2145
- if (tempVNode.children && tempVNode.children.length) {
2146
- if (tempVNode.children.length > 1) {
2147
- attributes = { ...attributes, ...tempAttributes };
2148
- }
2149
- vNodes = tempVNode.children.slice().concat(vNodes);
2150
- }
2151
- }
2152
- if (runFragmentsArray.length) {
2153
- return runFragmentsArray;
2154
- }
2155
- }
2156
- runFragment.import(runPropertiesFragment);
2157
- if (isVText(vNode)) {
2158
- const textFragment = buildTextElement(vNode.text);
2159
- runFragment.import(textFragment);
2160
- }
2161
- else if (attributes && attributes.type === 'picture') {
2162
- let response = null;
2163
- const base64Uri = decodeURIComponent(vNode.properties.src);
2164
- if (base64Uri) {
2165
- response = docxDocumentInstance.createMediaFile(base64Uri);
2166
- }
2167
- if (response) {
2168
- docxDocumentInstance.zip
2169
- .folder('word')
2170
- .folder('media')
2171
- .file(response.fileNameWithExtension, Buffer.from(response.fileContent, 'base64'), {
2172
- createFolders: false,
2173
- });
2174
- const documentRelsId = docxDocumentInstance.createDocumentRelationships(docxDocumentInstance.relationshipFilename, imageType, `media/${response.fileNameWithExtension}`, internalRelationship);
2175
- attributes.inlineOrAnchored = true;
2176
- attributes.relationshipId = documentRelsId;
2177
- attributes.id = response.id;
2178
- attributes.fileContent = response.fileContent;
2179
- attributes.fileNameWithExtension = response.fileNameWithExtension;
2180
- }
2181
- const { type, inlineOrAnchored, ...otherAttributes } = attributes;
2182
- // eslint-disable-next-line no-use-before-define
2183
- const imageFragment = buildDrawing(inlineOrAnchored, type, otherAttributes);
2184
- runFragment.import(imageFragment);
2185
- }
2186
- else if (isVNode(vNode) && vNode.tagName === 'br') {
2187
- const lineBreakFragment = buildLineBreak();
2188
- runFragment.import(lineBreakFragment);
2189
- }
2190
- runFragment.up();
2191
- return runFragment;
2192
- };
2193
- const buildRunOrRuns = async (vNode, attributes, docxDocumentInstance) => {
2194
- if (isVNode(vNode) && vNode.tagName === 'span') {
2195
- let runFragments = [];
2196
- for (let index = 0; index < vNode.children.length; index++) {
2197
- const childVNode = vNode.children[index];
2198
- const modifiedAttributes = modifiedStyleAttributesBuilder(vNode, attributes);
2199
- const tempRunFragments = await buildRun(childVNode, modifiedAttributes, docxDocumentInstance);
2200
- runFragments = runFragments.concat(Array.isArray(tempRunFragments) ? tempRunFragments : [tempRunFragments]);
2201
- }
2202
- return runFragments;
2203
- }
2204
- else {
2205
- const tempRunFragments = await buildRun(vNode, attributes, docxDocumentInstance);
2206
- return tempRunFragments;
2207
- }
2208
- };
2209
- const buildRunOrHyperLink = async (vNode, attributes, docxDocumentInstance) => {
2210
- if (isVNode(vNode) && vNode.tagName === 'a') {
2211
- const relationshipId = docxDocumentInstance.createDocumentRelationships(docxDocumentInstance.relationshipFilename, hyperlinkType, vNode.properties && vNode.properties.href ? vNode.properties.href : '');
2212
- const hyperlinkFragment = fragment({ namespaceAlias: { w: namespaces.w, r: namespaces.r } })
2213
- .ele('@w', 'hyperlink')
2214
- .att('@r', 'id', `rId${relationshipId}`);
2215
- const modifiedAttributes = { ...attributes };
2216
- modifiedAttributes.hyperlink = true;
2217
- const runFragments = await buildRunOrRuns(vNode.children[0], modifiedAttributes, docxDocumentInstance);
2218
- if (Array.isArray(runFragments)) {
2219
- for (let index = 0; index < runFragments.length; index++) {
2220
- const runFragment = runFragments[index];
2221
- hyperlinkFragment.import(runFragment);
2222
- }
2223
- }
2224
- else {
2225
- hyperlinkFragment.import(runFragments);
2226
- }
2227
- hyperlinkFragment.up();
2228
- return hyperlinkFragment;
2229
- }
2230
- const runFragments = await buildRunOrRuns(vNode, attributes, docxDocumentInstance);
2231
- return runFragments;
2232
- };
2233
- const buildNumberingProperties = (levelId, numberingId) => fragment({ namespaceAlias: { w: namespaces.w } })
2234
- .ele('@w', 'numPr')
2235
- .ele('@w', 'ilvl')
2236
- .att('@w', 'val', String(levelId))
2237
- .up()
2238
- .ele('@w', 'numId')
2239
- .att('@w', 'val', String(numberingId))
2240
- .up()
2241
- .up();
2242
- const buildNumberingInstances = () => fragment({ namespaceAlias: { w: namespaces.w } })
2243
- .ele('@w', 'num')
2244
- .ele('@w', 'abstractNumId')
2245
- .up()
2246
- .up();
2247
- const buildSpacing = (lineSpacing, beforeSpacing, afterSpacing) => {
2248
- const spacingFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'spacing');
2249
- if (lineSpacing) {
2250
- spacingFragment.att('@w', 'line', lineSpacing);
2251
- }
2252
- if (beforeSpacing) {
2253
- spacingFragment.att('@w', 'before', beforeSpacing);
2254
- }
2255
- if (afterSpacing) {
2256
- spacingFragment.att('@w', 'after', afterSpacing);
2257
- }
2258
- spacingFragment.att('@w', 'lineRule', 'auto').up();
2259
- return spacingFragment;
2260
- };
2261
- const buildIndentation = ({ left, right }) => {
2262
- const indentationFragment = fragment({
2263
- namespaceAlias: { w: namespaces.w },
2264
- }).ele('@w', 'ind');
2265
- if (left) {
2266
- indentationFragment.att('@w', 'left', left);
2267
- }
2268
- if (right) {
2269
- indentationFragment.att('@w', 'right', right);
2270
- }
2271
- indentationFragment.up();
2272
- return indentationFragment;
2273
- };
2274
- const buildPStyle = (style = 'Normal') => fragment({ namespaceAlias: { w: namespaces.w } })
2275
- .ele('@w', 'pStyle')
2276
- .att('@w', 'val', style)
2277
- .up();
2278
- const buildHorizontalAlignment = (horizontalAlignment) => {
2279
- if (horizontalAlignment === 'justify') {
2280
- horizontalAlignment = 'both';
2281
- }
2282
- return fragment({ namespaceAlias: { w: namespaces.w } })
2283
- .ele('@w', 'jc')
2284
- .att('@w', 'val', horizontalAlignment)
2285
- .up();
2286
- };
2287
- const buildParagraphBorder = () => {
2288
- const paragraphBorderFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'pBdr');
2289
- const bordersObject = cloneDeep(paragraphBordersObject);
2290
- Object.keys(bordersObject).forEach((borderName) => {
2291
- if (bordersObject[borderName]) {
2292
- const { size, spacing, color } = bordersObject[borderName];
2293
- const borderFragment = buildBorder(borderName, size, spacing, color);
2294
- paragraphBorderFragment.import(borderFragment);
2295
- }
2296
- });
2297
- paragraphBorderFragment.up();
2298
- return paragraphBorderFragment;
2299
- };
2300
- const buildParagraphProperties = (attributes) => {
2301
- const paragraphPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'pPr');
2302
- if (attributes && attributes.constructor === Object) {
2303
- Object.keys(attributes).forEach((key) => {
2304
- switch (key) {
2305
- case 'numbering':
2306
- const { levelId, numberingId } = attributes[key];
2307
- const numberingPropertiesFragment = buildNumberingProperties(levelId, numberingId);
2308
- paragraphPropertiesFragment.import(numberingPropertiesFragment);
2309
- // eslint-disable-next-line no-param-reassign
2310
- delete attributes.numbering;
2311
- break;
2312
- case 'textAlign':
2313
- const horizontalAlignmentFragment = buildHorizontalAlignment(attributes[key]);
2314
- paragraphPropertiesFragment.import(horizontalAlignmentFragment);
2315
- // eslint-disable-next-line no-param-reassign
2316
- delete attributes.textAlign;
2317
- break;
2318
- case 'backgroundColor':
2319
- // Add shading to Paragraph Properties only if display is block
2320
- // Essentially if background color needs to be across the row
2321
- if (attributes.display === 'block') {
2322
- const shadingFragment = buildShading(attributes[key]);
2323
- paragraphPropertiesFragment.import(shadingFragment);
2324
- // FIXME: Inner padding in case of shaded paragraphs.
2325
- const paragraphBorderFragment = buildParagraphBorder();
2326
- paragraphPropertiesFragment.import(paragraphBorderFragment);
2327
- // eslint-disable-next-line no-param-reassign
2328
- delete attributes.backgroundColor;
2329
- }
2330
- break;
2331
- case 'paragraphStyle':
2332
- const pStyleFragment = buildPStyle(attributes.paragraphStyle);
2333
- paragraphPropertiesFragment.import(pStyleFragment);
2334
- delete attributes.paragraphStyle;
2335
- break;
2336
- case 'indentation':
2337
- const indentationFragment = buildIndentation(attributes[key]);
2338
- paragraphPropertiesFragment.import(indentationFragment);
2339
- // eslint-disable-next-line no-param-reassign
2340
- delete attributes.indentation;
2341
- break;
2342
- }
2343
- });
2344
- const spacingFragment = buildSpacing(attributes.lineHeight, attributes.beforeSpacing, attributes.afterSpacing);
2345
- // eslint-disable-next-line no-param-reassign
2346
- delete attributes.lineHeight;
2347
- // eslint-disable-next-line no-param-reassign
2348
- delete attributes.beforeSpacing;
2349
- // eslint-disable-next-line no-param-reassign
2350
- delete attributes.afterSpacing;
2351
- paragraphPropertiesFragment.import(spacingFragment);
2352
- }
2353
- paragraphPropertiesFragment.up();
2354
- return paragraphPropertiesFragment;
2355
- };
2356
- const computeImageDimensions = (vNode, attributes) => {
2357
- const { maximumWidth, originalWidth, originalHeight } = attributes;
2358
- const aspectRatio = originalWidth / originalHeight;
2359
- const maximumWidthInEMU = TWIPToEMU(maximumWidth);
2360
- let originalWidthInEMU = pixelToEMU(originalWidth);
2361
- let originalHeightInEMU = pixelToEMU(originalHeight);
2362
- if (originalWidthInEMU > maximumWidthInEMU) {
2363
- originalWidthInEMU = maximumWidthInEMU;
2364
- originalHeightInEMU = Math.round(originalWidthInEMU / aspectRatio);
2365
- }
2366
- let modifiedHeight;
2367
- let modifiedWidth;
2368
- if (vNode.properties && vNode.properties.style) {
2369
- if (vNode.properties.style.width) {
2370
- if (vNode.properties.style.width !== 'auto') {
2371
- if (pixelRegex.test(vNode.properties.style.width)) {
2372
- modifiedWidth = pixelToEMU(vNode.properties.style.width.match(pixelRegex)[1]);
2373
- }
2374
- else if (percentageRegex.test(vNode.properties.style.width)) {
2375
- const percentageValue = vNode.properties.style.width.match(percentageRegex)[1];
2376
- modifiedWidth = Math.round((percentageValue / 100) * originalWidthInEMU);
2377
- }
2378
- }
2379
- else {
2380
- // eslint-disable-next-line no-lonely-if
2381
- if (vNode.properties.style.height && vNode.properties.style.height === 'auto') {
2382
- modifiedWidth = originalWidthInEMU;
2383
- modifiedHeight = originalHeightInEMU;
2384
- }
2385
- }
2386
- }
2387
- if (vNode.properties.style.height) {
2388
- if (vNode.properties.style.height !== 'auto') {
2389
- if (pixelRegex.test(vNode.properties.style.height)) {
2390
- modifiedHeight = pixelToEMU(vNode.properties.style.height.match(pixelRegex)[1]);
2391
- }
2392
- else if (percentageRegex.test(vNode.properties.style.height)) {
2393
- const percentageValue = vNode.properties.style.width.match(percentageRegex)[1];
2394
- modifiedHeight = Math.round((percentageValue / 100) * originalHeightInEMU);
2395
- if (!modifiedWidth) {
2396
- modifiedWidth = Math.round(modifiedHeight * aspectRatio);
2397
- }
2398
- }
2399
- }
2400
- else {
2401
- // eslint-disable-next-line no-lonely-if
2402
- if (modifiedWidth) {
2403
- if (!modifiedHeight) {
2404
- modifiedHeight = Math.round(modifiedWidth / aspectRatio);
2405
- }
2406
- }
2407
- else {
2408
- modifiedHeight = originalHeightInEMU;
2409
- modifiedWidth = originalWidthInEMU;
2410
- }
2411
- }
2412
- }
2413
- if (modifiedWidth && !modifiedHeight) {
2414
- modifiedHeight = Math.round(modifiedWidth / aspectRatio);
2415
- }
2416
- else if (modifiedHeight && !modifiedWidth) {
2417
- modifiedWidth = Math.round(modifiedHeight * aspectRatio);
2418
- }
2419
- }
2420
- else {
2421
- modifiedWidth = originalWidthInEMU;
2422
- modifiedHeight = originalHeightInEMU;
2423
- }
2424
- // eslint-disable-next-line no-param-reassign
2425
- attributes.width = modifiedWidth;
2426
- // eslint-disable-next-line no-param-reassign
2427
- attributes.height = modifiedHeight;
2428
- };
2429
- const buildParagraph = async (vNode, attributes, docxDocumentInstance) => {
2430
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'p');
2431
- const modifiedAttributes = modifiedStyleAttributesBuilder(vNode, attributes, {
2432
- isParagraph: true,
2433
- });
2434
- const paragraphPropertiesFragment = buildParagraphProperties(modifiedAttributes);
2435
- paragraphFragment.import(paragraphPropertiesFragment);
2436
- if (isVNode(vNode) && vNodeHasChildren(vNode)) {
2437
- if ([
2438
- 'span',
2439
- 'strong',
2440
- 'b',
2441
- 'em',
2442
- 'i',
2443
- 'u',
2444
- 'ins',
2445
- 'strike',
2446
- 'del',
2447
- 's',
2448
- 'sub',
2449
- 'sup',
2450
- 'mark',
2451
- 'a',
2452
- 'code',
2453
- 'pre',
2454
- ].includes(vNode.tagName)) {
2455
- const runOrHyperlinkFragments = await buildRunOrHyperLink(vNode, modifiedAttributes, docxDocumentInstance);
2456
- if (Array.isArray(runOrHyperlinkFragments)) {
2457
- for (let iteratorIndex = 0; iteratorIndex < runOrHyperlinkFragments.length; iteratorIndex++) {
2458
- const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex];
2459
- paragraphFragment.import(runOrHyperlinkFragment);
2460
- }
2461
- }
2462
- else {
2463
- paragraphFragment.import(runOrHyperlinkFragments);
2464
- }
2465
- }
2466
- else if (vNode.tagName === 'blockquote') {
2467
- const runFragmentOrFragments = await buildRun(vNode, attributes);
2468
- if (Array.isArray(runFragmentOrFragments)) {
2469
- for (let index = 0; index < runFragmentOrFragments.length; index++) {
2470
- paragraphFragment.import(runFragmentOrFragments[index]);
2471
- }
2472
- }
2473
- else {
2474
- paragraphFragment.import(runFragmentOrFragments);
2475
- }
2476
- }
2477
- else {
2478
- for (let index = 0; index < vNode.children.length; index++) {
2479
- const childVNode = vNode.children[index];
2480
- if (childVNode.tagName === 'img') {
2481
- let base64String;
2482
- const imageSource = childVNode.properties.src;
2483
- if (isValidUrl(imageSource)) {
2484
- base64String = await imageToBase64(imageSource).catch((error) => {
2485
- // eslint-disable-next-line no-console
2486
- console.warning(`skipping image download and conversion due to ${error}`);
2487
- });
2488
- if (base64String && mimeTypes.lookup(imageSource)) {
2489
- childVNode.properties.src = `data:${mimeTypes.lookup(imageSource)};base64, ${base64String}`;
2490
- }
2491
- else {
2492
- break;
2493
- }
2494
- }
2495
- else {
2496
- // eslint-disable-next-line no-useless-escape, prefer-destructuring
2497
- base64String = imageSource.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)[2];
2498
- }
2499
- const imageBuffer = Buffer.from(decodeURIComponent(base64String), 'base64');
2500
- const imageProperties = sizeOf(imageBuffer);
2501
- modifiedAttributes.maximumWidth =
2502
- modifiedAttributes.maximumWidth || docxDocumentInstance.availableDocumentSpace;
2503
- modifiedAttributes.originalWidth = imageProperties.width;
2504
- modifiedAttributes.originalHeight = imageProperties.height;
2505
- computeImageDimensions(childVNode, modifiedAttributes);
2506
- }
2507
- const runOrHyperlinkFragments = await buildRunOrHyperLink(childVNode, isVNode(childVNode) && childVNode.tagName === 'img'
2508
- ? { ...modifiedAttributes, type: 'picture' }
2509
- : modifiedAttributes, docxDocumentInstance);
2510
- if (Array.isArray(runOrHyperlinkFragments)) {
2511
- for (let iteratorIndex = 0; iteratorIndex < runOrHyperlinkFragments.length; iteratorIndex++) {
2512
- const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex];
2513
- paragraphFragment.import(runOrHyperlinkFragment);
2514
- }
2515
- }
2516
- else {
2517
- paragraphFragment.import(runOrHyperlinkFragments);
2518
- }
2519
- }
2520
- }
2521
- }
2522
- else {
2523
- // In case paragraphs has to be rendered where vText is present. Eg. table-cell
2524
- // Or in case the vNode is something like img
2525
- if (isVNode(vNode) && vNode.tagName === 'img') {
2526
- const imageSource = vNode.properties.src;
2527
- let base64String = imageSource;
2528
- if (isValidUrl(imageSource)) {
2529
- base64String = await imageToBase64(imageSource).catch((error) => {
2530
- // eslint-disable-next-line no-console
2531
- console.warning(`skipping image download and conversion due to ${error}`);
2532
- });
2533
- if (base64String && mimeTypes.lookup(imageSource)) {
2534
- vNode.properties.src = `data:${mimeTypes.lookup(imageSource)};base64, ${base64String}`;
2535
- }
2536
- else {
2537
- paragraphFragment.up();
2538
- return paragraphFragment;
2539
- }
2540
- }
2541
- else {
2542
- // eslint-disable-next-line no-useless-escape, prefer-destructuring
2543
- base64String = base64String.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)[2];
2544
- }
2545
- const imageBuffer = Buffer.from(decodeURIComponent(base64String), 'base64');
2546
- const imageProperties = sizeOf(imageBuffer);
2547
- modifiedAttributes.maximumWidth =
2548
- modifiedAttributes.maximumWidth || docxDocumentInstance.availableDocumentSpace;
2549
- modifiedAttributes.originalWidth = imageProperties.width;
2550
- modifiedAttributes.originalHeight = imageProperties.height;
2551
- computeImageDimensions(vNode, modifiedAttributes);
2552
- }
2553
- const runFragments = await buildRunOrRuns(vNode, modifiedAttributes, docxDocumentInstance);
2554
- if (Array.isArray(runFragments)) {
2555
- for (let index = 0; index < runFragments.length; index++) {
2556
- const runFragment = runFragments[index];
2557
- paragraphFragment.import(runFragment);
2558
- }
2559
- }
2560
- else {
2561
- paragraphFragment.import(runFragments);
2562
- }
2563
- }
2564
- paragraphFragment.up();
2565
- return paragraphFragment;
2566
- };
2567
- const buildGridSpanFragment = (spanValue) => fragment({ namespaceAlias: { w: namespaces.w } })
2568
- .ele('@w', 'gridSpan')
2569
- .att('@w', 'val', spanValue)
2570
- .up();
2571
- const buildTableCellSpacing = (cellSpacing = 0) => fragment({ namespaceAlias: { w: namespaces.w } })
2572
- .ele('@w', 'tblCellSpacing')
2573
- .att('@w', 'w', cellSpacing)
2574
- .att('@w', 'type', 'dxa')
2575
- .up();
2576
- const buildTableCellBorders = (tableCellBorder) => {
2577
- const tableCellBordersFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tcBorders');
2578
- const { color, stroke, ...borders } = tableCellBorder;
2579
- Object.keys(borders).forEach((border) => {
2580
- if (tableCellBorder[border]) {
2581
- const borderFragment = buildBorder(border, tableCellBorder[border], 0, color, stroke);
2582
- tableCellBordersFragment.import(borderFragment);
2583
- }
2584
- });
2585
- tableCellBordersFragment.up();
2586
- return tableCellBordersFragment;
2587
- };
2588
- const buildTableCellWidth = (tableCellWidth) => fragment({ namespaceAlias: { w: namespaces.w } })
2589
- .ele('@w', 'tcW')
2590
- .att('@w', 'w', fixupColumnWidth(tableCellWidth))
2591
- .att('@w', 'type', 'dxa')
2592
- .up();
2593
- const buildTableCellProperties = (attributes) => {
2594
- const tableCellPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tcPr');
2595
- if (attributes && attributes.constructor === Object) {
2596
- Object.keys(attributes).forEach((key) => {
2597
- switch (key) {
2598
- case 'backgroundColor':
2599
- const shadingFragment = buildShading(attributes[key]);
2600
- tableCellPropertiesFragment.import(shadingFragment);
2601
- // eslint-disable-next-line no-param-reassign
2602
- delete attributes.backgroundColor;
2603
- break;
2604
- case 'verticalAlign':
2605
- const verticalAlignmentFragment = buildVerticalAlignment(attributes[key]);
2606
- tableCellPropertiesFragment.import(verticalAlignmentFragment);
2607
- // eslint-disable-next-line no-param-reassign
2608
- delete attributes.verticalAlign;
2609
- break;
2610
- case 'colSpan':
2611
- const gridSpanFragment = buildGridSpanFragment(attributes[key]);
2612
- tableCellPropertiesFragment.import(gridSpanFragment);
2613
- // eslint-disable-next-line no-param-reassign
2614
- delete attributes.colSpan;
2615
- break;
2616
- case 'tableCellBorder':
2617
- const tableCellBorderFragment = buildTableCellBorders(attributes[key]);
2618
- tableCellPropertiesFragment.import(tableCellBorderFragment);
2619
- // eslint-disable-next-line no-param-reassign
2620
- delete attributes.tableCellBorder;
2621
- break;
2622
- case 'rowSpan':
2623
- const verticalMergeFragment = buildVerticalMerge(attributes[key]);
2624
- tableCellPropertiesFragment.import(verticalMergeFragment);
2625
- delete attributes.rowSpan;
2626
- break;
2627
- case 'width':
2628
- const widthFragment = buildTableCellWidth(attributes[key]);
2629
- tableCellPropertiesFragment.import(widthFragment);
2630
- delete attributes.width;
2631
- break;
2632
- }
2633
- });
2634
- }
2635
- tableCellPropertiesFragment.up();
2636
- return tableCellPropertiesFragment;
2637
- };
2638
- const fixupTableCellBorder = (vNode, attributes) => {
2639
- if (Object.prototype.hasOwnProperty.call(vNode.properties.style, 'border')) {
2640
- if (vNode.properties.style.border === 'none' || vNode.properties.style.border === 0) {
2641
- attributes.tableCellBorder = {};
2642
- }
2643
- else {
2644
- // eslint-disable-next-line no-use-before-define
2645
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style.border);
2646
- attributes.tableCellBorder = {
2647
- top: borderSize,
2648
- left: borderSize,
2649
- bottom: borderSize,
2650
- right: borderSize,
2651
- color: borderColor,
2652
- stroke: borderStroke,
2653
- };
2654
- }
2655
- }
2656
- if (vNode.properties.style['border-top'] && vNode.properties.style['border-top'] === '0') {
2657
- attributes.tableCellBorder = {
2658
- ...attributes.tableCellBorder,
2659
- top: 0,
2660
- };
2661
- }
2662
- else if (vNode.properties.style['border-top'] && vNode.properties.style['border-top'] !== '0') {
2663
- // eslint-disable-next-line no-use-before-define
2664
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-top']);
2665
- attributes.tableCellBorder = {
2666
- ...attributes.tableCellBorder,
2667
- top: borderSize,
2668
- color: borderColor,
2669
- stroke: borderStroke,
2670
- };
2671
- }
2672
- if (vNode.properties.style['border-left'] && vNode.properties.style['border-left'] === '0') {
2673
- attributes.tableCellBorder = {
2674
- ...attributes.tableCellBorder,
2675
- left: 0,
2676
- };
2677
- }
2678
- else if (vNode.properties.style['border-left'] &&
2679
- vNode.properties.style['border-left'] !== '0') {
2680
- // eslint-disable-next-line no-use-before-define
2681
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-left']);
2682
- attributes.tableCellBorder = {
2683
- ...attributes.tableCellBorder,
2684
- left: borderSize,
2685
- color: borderColor,
2686
- stroke: borderStroke,
2687
- };
2688
- }
2689
- if (vNode.properties.style['border-bottom'] && vNode.properties.style['border-bottom'] === '0') {
2690
- attributes.tableCellBorder = {
2691
- ...attributes.tableCellBorder,
2692
- bottom: 0,
2693
- };
2694
- }
2695
- else if (vNode.properties.style['border-bottom'] &&
2696
- vNode.properties.style['border-bottom'] !== '0') {
2697
- // eslint-disable-next-line no-use-before-define
2698
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-bottom']);
2699
- attributes.tableCellBorder = {
2700
- ...attributes.tableCellBorder,
2701
- bottom: borderSize,
2702
- color: borderColor,
2703
- stroke: borderStroke,
2704
- };
2705
- }
2706
- if (vNode.properties.style['border-right'] && vNode.properties.style['border-right'] === '0') {
2707
- attributes.tableCellBorder = {
2708
- ...attributes.tableCellBorder,
2709
- right: 0,
2710
- };
2711
- }
2712
- else if (vNode.properties.style['border-right'] &&
2713
- vNode.properties.style['border-right'] !== '0') {
2714
- // eslint-disable-next-line no-use-before-define
2715
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-right']);
2716
- attributes.tableCellBorder = {
2717
- ...attributes.tableCellBorder,
2718
- right: borderSize,
2719
- color: borderColor,
2720
- stroke: borderStroke,
2721
- };
2722
- }
2723
- };
2724
- const buildTableCell = async (vNode, attributes, rowSpanMap, columnIndex, docxDocumentInstance) => {
2725
- const tableCellFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tc');
2726
- let modifiedAttributes = { ...attributes };
2727
- if (isVNode(vNode) && vNode.properties) {
2728
- if (vNode.properties.rowSpan) {
2729
- rowSpanMap.set(columnIndex.index, { rowSpan: vNode.properties.rowSpan - 1, colSpan: 0 });
2730
- modifiedAttributes.rowSpan = 'restart';
2731
- }
2732
- else {
2733
- const previousSpanObject = rowSpanMap.get(columnIndex.index);
2734
- rowSpanMap.set(columnIndex.index,
2735
- // eslint-disable-next-line prefer-object-spread
2736
- Object.assign({}, previousSpanObject, {
2737
- rowSpan: 0,
2738
- colSpan: (previousSpanObject && previousSpanObject.colSpan) || 0,
2739
- }));
2740
- }
2741
- if (vNode.properties.colSpan ||
2742
- (vNode.properties.style && vNode.properties.style['column-span'])) {
2743
- modifiedAttributes.colSpan =
2744
- vNode.properties.colSpan ||
2745
- (vNode.properties.style && vNode.properties.style['column-span']);
2746
- const previousSpanObject = rowSpanMap.get(columnIndex.index);
2747
- rowSpanMap.set(columnIndex.index,
2748
- // eslint-disable-next-line prefer-object-spread
2749
- Object.assign({}, previousSpanObject, {
2750
- colSpan: parseInt(modifiedAttributes.colSpan) || 0,
2751
- }));
2752
- columnIndex.index += parseInt(modifiedAttributes.colSpan) - 1;
2753
- }
2754
- if (vNode.properties.style) {
2755
- modifiedAttributes = {
2756
- ...modifiedAttributes,
2757
- ...modifiedStyleAttributesBuilder(vNode, attributes),
2758
- };
2759
- fixupTableCellBorder(vNode, modifiedAttributes);
2760
- }
2761
- }
2762
- const tableCellPropertiesFragment = buildTableCellProperties(modifiedAttributes);
2763
- tableCellFragment.import(tableCellPropertiesFragment);
2764
- if (vNodeHasChildren(vNode)) {
2765
- for (let index = 0; index < vNode.children.length; index++) {
2766
- const childVNode = vNode.children[index];
2767
- if (isVNode(childVNode) && childVNode.tagName === 'img') {
2768
- const imageFragment = await buildImage(docxDocumentInstance, childVNode, modifiedAttributes.maximumWidth);
2769
- if (imageFragment) {
2770
- tableCellFragment.import(imageFragment);
2771
- }
2772
- }
2773
- else if (isVNode(childVNode) && childVNode.tagName === 'figure') {
2774
- if (vNodeHasChildren(childVNode)) {
2775
- // eslint-disable-next-line no-plusplus
2776
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
2777
- const grandChildVNode = childVNode.children[iteratorIndex];
2778
- if (grandChildVNode.tagName === 'img') {
2779
- const imageFragment = await buildImage(docxDocumentInstance, grandChildVNode, modifiedAttributes.maximumWidth);
2780
- if (imageFragment) {
2781
- tableCellFragment.import(imageFragment);
2782
- }
2783
- }
2784
- }
2785
- }
2786
- }
2787
- else if (isVNode(childVNode) && ['ul', 'ol'].includes(childVNode.tagName)) {
2788
- // render list in table
2789
- if (vNodeHasChildren(childVNode)) {
2790
- await buildList(childVNode, docxDocumentInstance, tableCellFragment);
2791
- }
2792
- }
2793
- else {
2794
- const paragraphFragment = await buildParagraph(childVNode, modifiedAttributes, docxDocumentInstance);
2795
- tableCellFragment.import(paragraphFragment);
2796
- }
2797
- }
2798
- }
2799
- else {
2800
- // TODO: Figure out why building with buildParagraph() isn't working
2801
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
2802
- .ele('@w', 'p')
2803
- .up();
2804
- tableCellFragment.import(paragraphFragment);
2805
- }
2806
- tableCellFragment.up();
2807
- return tableCellFragment;
2808
- };
2809
- const buildRowSpanCell = (rowSpanMap, columnIndex, attributes) => {
2810
- const rowSpanCellFragments = [];
2811
- let spanObject = rowSpanMap.get(columnIndex.index);
2812
- while (spanObject && spanObject.rowSpan) {
2813
- const rowSpanCellFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tc');
2814
- const tableCellPropertiesFragment = buildTableCellProperties({
2815
- ...attributes,
2816
- rowSpan: 'continue',
2817
- colSpan: spanObject.colSpan ? spanObject.colSpan : 0,
2818
- });
2819
- rowSpanCellFragment.import(tableCellPropertiesFragment);
2820
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
2821
- .ele('@w', 'p')
2822
- .up();
2823
- rowSpanCellFragment.import(paragraphFragment);
2824
- rowSpanCellFragment.up();
2825
- rowSpanCellFragments.push(rowSpanCellFragment);
2826
- if (spanObject.rowSpan - 1 === 0) {
2827
- rowSpanMap.delete(columnIndex.index);
2828
- }
2829
- else {
2830
- rowSpanMap.set(columnIndex.index, {
2831
- rowSpan: spanObject.rowSpan - 1,
2832
- colSpan: spanObject.colSpan || 0,
2833
- });
2834
- }
2835
- columnIndex.index += spanObject.colSpan || 1;
2836
- spanObject = rowSpanMap.get(columnIndex.index);
2837
- }
2838
- return rowSpanCellFragments;
2839
- };
2840
- const buildTableRowProperties = (attributes) => {
2841
- const tableRowPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'trPr');
2842
- if (attributes && attributes.constructor === Object) {
2843
- Object.keys(attributes).forEach((key) => {
2844
- switch (key) {
2845
- case 'tableRowHeight':
2846
- const tableRowHeightFragment = buildTableRowHeight(attributes[key]);
2847
- tableRowPropertiesFragment.import(tableRowHeightFragment);
2848
- // eslint-disable-next-line no-param-reassign
2849
- delete attributes.tableRowHeight;
2850
- break;
2851
- case 'rowCantSplit':
2852
- if (attributes.rowCantSplit) {
2853
- const cantSplitFragment = fragment({ namespaceAlias: { w: namespaces.w } })
2854
- .ele('@w', 'cantSplit')
2855
- .up();
2856
- tableRowPropertiesFragment.import(cantSplitFragment);
2857
- // eslint-disable-next-line no-param-reassign
2858
- delete attributes.rowCantSplit;
2859
- }
2860
- break;
2861
- }
2862
- });
2863
- }
2864
- tableRowPropertiesFragment.up();
2865
- return tableRowPropertiesFragment;
2866
- };
2867
- const buildTableRow = async (vNode, attributes, rowSpanMap, docxDocumentInstance) => {
2868
- const tableRowFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tr');
2869
- const modifiedAttributes = { ...attributes };
2870
- if (isVNode(vNode) && vNode.properties) {
2871
- // FIXME: find a better way to get row height from cell style
2872
- if ((vNode.properties.style && vNode.properties.style.height) ||
2873
- (vNode.children[0] &&
2874
- isVNode(vNode.children[0]) &&
2875
- vNode.children[0].properties.style &&
2876
- vNode.children[0].properties.style.height)) {
2877
- modifiedAttributes.tableRowHeight = fixupRowHeight((vNode.properties.style && vNode.properties.style.height) ||
2878
- (vNode.children[0] &&
2879
- isVNode(vNode.children[0]) &&
2880
- vNode.children[0].properties.style &&
2881
- vNode.children[0].properties.style.height
2882
- ? vNode.children[0].properties.style.height
2883
- : undefined));
2884
- }
2885
- if (vNode.properties.style) {
2886
- fixupTableCellBorder(vNode, modifiedAttributes);
2887
- }
2888
- }
2889
- const tableRowPropertiesFragment = buildTableRowProperties(modifiedAttributes);
2890
- tableRowFragment.import(tableRowPropertiesFragment);
2891
- const columnIndex = { index: 0 };
2892
- if (vNodeHasChildren(vNode)) {
2893
- const tableColumns = vNode.children.filter((childVNode) => ['td', 'th'].includes(childVNode.tagName));
2894
- const maximumColumnWidth = docxDocumentInstance.availableDocumentSpace / tableColumns.length;
2895
- // eslint-disable-next-line no-restricted-syntax
2896
- for (const column of tableColumns) {
2897
- const rowSpanCellFragments = buildRowSpanCell(rowSpanMap, columnIndex, modifiedAttributes);
2898
- if (Array.isArray(rowSpanCellFragments)) {
2899
- for (let iteratorIndex = 0; iteratorIndex < rowSpanCellFragments.length; iteratorIndex++) {
2900
- const rowSpanCellFragment = rowSpanCellFragments[iteratorIndex];
2901
- tableRowFragment.import(rowSpanCellFragment);
2902
- }
2903
- }
2904
- const tableCellFragment = await buildTableCell(column, { ...modifiedAttributes, maximumWidth: maximumColumnWidth }, rowSpanMap, columnIndex, docxDocumentInstance);
2905
- columnIndex.index++;
2906
- tableRowFragment.import(tableCellFragment);
2907
- }
2908
- }
2909
- if (columnIndex.index < rowSpanMap.size) {
2910
- const rowSpanCellFragments = buildRowSpanCell(rowSpanMap, columnIndex, modifiedAttributes);
2911
- if (Array.isArray(rowSpanCellFragments)) {
2912
- for (let iteratorIndex = 0; iteratorIndex < rowSpanCellFragments.length; iteratorIndex++) {
2913
- const rowSpanCellFragment = rowSpanCellFragments[iteratorIndex];
2914
- tableRowFragment.import(rowSpanCellFragment);
2915
- }
2916
- }
2917
- }
2918
- tableRowFragment.up();
2919
- return tableRowFragment;
2920
- };
2921
- const buildTableGridCol = (gridWidth) => fragment({ namespaceAlias: { w: namespaces.w } })
2922
- .ele('@w', 'gridCol')
2923
- .att('@w', 'w', String(gridWidth));
2924
- const buildTableGrid = (vNode, attributes) => {
2925
- const tableGridFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblGrid');
2926
- if (vNodeHasChildren(vNode)) {
2927
- const gridColumns = vNode.children.filter((childVNode) => childVNode.tagName === 'col');
2928
- const gridWidth = attributes.maximumWidth / gridColumns.length;
2929
- for (let index = 0; index < gridColumns.length; index++) {
2930
- const tableGridColFragment = buildTableGridCol(gridWidth);
2931
- tableGridFragment.import(tableGridColFragment);
2932
- }
2933
- }
2934
- tableGridFragment.up();
2935
- return tableGridFragment;
2936
- };
2937
- const buildTableGridFromTableRow = (vNode, attributes) => {
2938
- const tableGridFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblGrid');
2939
- if (vNodeHasChildren(vNode)) {
2940
- const numberOfGridColumns = vNode.children.reduce((accumulator, childVNode) => {
2941
- const colSpan = childVNode.properties.colSpan ||
2942
- (childVNode.properties.style && childVNode.properties.style['column-span']);
2943
- return accumulator + (colSpan ? parseInt(colSpan) : 1);
2944
- }, 0);
2945
- const gridWidth = attributes.maximumWidth / numberOfGridColumns;
2946
- for (let index = 0; index < numberOfGridColumns; index++) {
2947
- const tableGridColFragment = buildTableGridCol(gridWidth);
2948
- tableGridFragment.import(tableGridColFragment);
2949
- }
2950
- }
2951
- tableGridFragment.up();
2952
- return tableGridFragment;
2953
- };
2954
- const buildTableBorders = (tableBorder) => {
2955
- const tableBordersFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblBorders');
2956
- const { color, stroke, ...borders } = tableBorder;
2957
- Object.keys(borders).forEach((border) => {
2958
- if (borders[border]) {
2959
- const borderFragment = buildBorder(border, borders[border], 0, color, stroke);
2960
- tableBordersFragment.import(borderFragment);
2961
- }
2962
- });
2963
- tableBordersFragment.up();
2964
- return tableBordersFragment;
2965
- };
2966
- const buildTableWidth = (tableWidth) => fragment({ namespaceAlias: { w: namespaces.w } })
2967
- .ele('@w', 'tblW')
2968
- .att('@w', 'type', 'dxa')
2969
- .att('@w', 'w', String(tableWidth))
2970
- .up();
2971
- const buildCellMargin = (side, margin) => fragment({ namespaceAlias: { w: namespaces.w } })
2972
- .ele('@w', side)
2973
- .att('@w', 'type', 'dxa')
2974
- .att('@w', 'w', String(margin))
2975
- .up();
2976
- const buildTableCellMargins = (margin) => {
2977
- const tableCellMarFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblCellMar');
2978
- ['top', 'bottom'].forEach((side) => {
2979
- const marginFragment = buildCellMargin(side, margin / 2);
2980
- tableCellMarFragment.import(marginFragment);
2981
- });
2982
- ['left', 'right'].forEach((side) => {
2983
- const marginFragment = buildCellMargin(side, margin);
2984
- tableCellMarFragment.import(marginFragment);
2985
- });
2986
- return tableCellMarFragment;
2987
- };
2988
- const buildTableProperties = (attributes) => {
2989
- const tablePropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblPr');
2990
- if (attributes && attributes.constructor === Object) {
2991
- Object.keys(attributes).forEach((key) => {
2992
- switch (key) {
2993
- case 'tableBorder':
2994
- const tableBordersFragment = buildTableBorders(attributes[key]);
2995
- tablePropertiesFragment.import(tableBordersFragment);
2996
- // eslint-disable-next-line no-param-reassign
2997
- delete attributes.tableBorder;
2998
- break;
2999
- case 'tableCellSpacing':
3000
- const tableCellSpacingFragment = buildTableCellSpacing(attributes[key]);
3001
- tablePropertiesFragment.import(tableCellSpacingFragment);
3002
- // eslint-disable-next-line no-param-reassign
3003
- delete attributes.tableCellSpacing;
3004
- break;
3005
- case 'width':
3006
- if (attributes[key]) {
3007
- const tableWidthFragment = buildTableWidth(attributes[key]);
3008
- tablePropertiesFragment.import(tableWidthFragment);
3009
- }
3010
- // eslint-disable-next-line no-param-reassign
3011
- delete attributes.width;
3012
- break;
3013
- }
3014
- });
3015
- }
3016
- const tableCellMarginFragment = buildTableCellMargins(160);
3017
- tablePropertiesFragment.import(tableCellMarginFragment);
3018
- // by default, all tables are center aligned.
3019
- const alignmentFragment = buildHorizontalAlignment('center');
3020
- tablePropertiesFragment.import(alignmentFragment);
3021
- tablePropertiesFragment.up();
3022
- return tablePropertiesFragment;
3023
- };
3024
- const cssBorderParser = (borderString) => {
3025
- let [size, stroke, color] = borderString.split(' ');
3026
- if (pointRegex.test(size)) {
3027
- const matchedParts = size.match(pointRegex);
3028
- // convert point to eighth of a point
3029
- size = pointToEIP(matchedParts[1]);
3030
- }
3031
- else if (pixelRegex.test(size)) {
3032
- const matchedParts = size.match(pixelRegex);
3033
- // convert pixels to eighth of a point
3034
- size = pixelToEIP(matchedParts[1]);
3035
- }
3036
- stroke = stroke && ['dashed', 'dotted', 'double'].includes(stroke) ? stroke : 'single';
3037
- color = color && fixupColorCode(color).toUpperCase();
3038
- return [size, stroke, color];
3039
- };
3040
- const buildTable = async (vNode, attributes, docxDocumentInstance) => {
3041
- const tableFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tbl');
3042
- const modifiedAttributes = { ...attributes };
3043
- if (isVNode(vNode) && vNode.properties) {
3044
- const tableAttributes = vNode.properties.attributes || {};
3045
- const tableStyles = vNode.properties.style || {};
3046
- const tableBorders = {};
3047
- const tableCellBorders = {};
3048
- let [borderSize, borderStrike, borderColor] = [2, 'single', '000000'];
3049
- // eslint-disable-next-line no-restricted-globals
3050
- if (!isNaN(tableAttributes.border)) {
3051
- borderSize = parseInt(tableAttributes.border, 10);
3052
- }
3053
- // css style overrides table border properties
3054
- if (tableStyles.border) {
3055
- const [cssSize, cssStroke, cssColor] = cssBorderParser(tableStyles.border);
3056
- borderSize = cssSize || borderSize;
3057
- borderColor = cssColor || borderColor;
3058
- borderStrike = cssStroke || borderStrike;
3059
- }
3060
- tableBorders.top = borderSize;
3061
- tableBorders.bottom = borderSize;
3062
- tableBorders.left = borderSize;
3063
- tableBorders.right = borderSize;
3064
- tableBorders.stroke = borderStrike;
3065
- tableBorders.color = borderColor;
3066
- if (tableStyles['border-collapse'] === 'collapse') {
3067
- tableBorders.insideV = borderSize;
3068
- tableBorders.insideH = borderSize;
3069
- }
3070
- else {
3071
- tableBorders.insideV = 0;
3072
- tableBorders.insideH = 0;
3073
- tableCellBorders.top = 1;
3074
- tableCellBorders.bottom = 1;
3075
- tableCellBorders.left = 1;
3076
- tableCellBorders.right = 1;
3077
- }
3078
- modifiedAttributes.tableBorder = tableBorders;
3079
- modifiedAttributes.tableCellSpacing = 0;
3080
- if (Object.keys(tableCellBorders).length) {
3081
- modifiedAttributes.tableCellBorder = tableCellBorders;
3082
- }
3083
- let minimumWidth;
3084
- let maximumWidth;
3085
- let width;
3086
- // Calculate minimum width of table
3087
- if (pixelRegex.test(tableStyles['min-width'])) {
3088
- minimumWidth = pixelToTWIP(tableStyles['min-width'].match(pixelRegex)[1]);
3089
- }
3090
- else if (percentageRegex.test(tableStyles['min-width'])) {
3091
- const percentageValue = tableStyles['min-width'].match(percentageRegex)[1];
3092
- minimumWidth = Math.round((percentageValue / 100) * attributes.maximumWidth);
3093
- }
3094
- // Calculate maximum width of table
3095
- if (pixelRegex.test(tableStyles['max-width'])) {
3096
- pixelRegex.lastIndex = 0;
3097
- maximumWidth = pixelToTWIP(tableStyles['max-width'].match(pixelRegex)[1]);
3098
- }
3099
- else if (percentageRegex.test(tableStyles['max-width'])) {
3100
- percentageRegex.lastIndex = 0;
3101
- const percentageValue = tableStyles['max-width'].match(percentageRegex)[1];
3102
- maximumWidth = Math.round((percentageValue / 100) * attributes.maximumWidth);
3103
- }
3104
- // Calculate specified width of table
3105
- if (pixelRegex.test(tableStyles.width)) {
3106
- pixelRegex.lastIndex = 0;
3107
- width = pixelToTWIP(tableStyles.width.match(pixelRegex)[1]);
3108
- }
3109
- else if (percentageRegex.test(tableStyles.width)) {
3110
- percentageRegex.lastIndex = 0;
3111
- const percentageValue = tableStyles.width.match(percentageRegex)[1];
3112
- width = Math.round((percentageValue / 100) * attributes.maximumWidth);
3113
- }
3114
- // If width isn't supplied, we should have min-width as the width.
3115
- if (width) {
3116
- modifiedAttributes.width = width;
3117
- if (maximumWidth) {
3118
- modifiedAttributes.width = Math.min(modifiedAttributes.width, maximumWidth);
3119
- }
3120
- if (minimumWidth) {
3121
- modifiedAttributes.width = Math.max(modifiedAttributes.width, minimumWidth);
3122
- }
3123
- }
3124
- else if (minimumWidth) {
3125
- modifiedAttributes.width = minimumWidth;
3126
- }
3127
- if (modifiedAttributes.width) {
3128
- modifiedAttributes.width = Math.min(modifiedAttributes.width, attributes.maximumWidth);
3129
- }
3130
- }
3131
- const tablePropertiesFragment = buildTableProperties(modifiedAttributes);
3132
- tableFragment.import(tablePropertiesFragment);
3133
- const rowSpanMap = new Map();
3134
- if (vNodeHasChildren(vNode)) {
3135
- for (let index = 0; index < vNode.children.length; index++) {
3136
- const childVNode = vNode.children[index];
3137
- if (childVNode.tagName === 'colgroup') {
3138
- const tableGridFragment = buildTableGrid(childVNode, modifiedAttributes);
3139
- tableFragment.import(tableGridFragment);
3140
- }
3141
- else if (childVNode.tagName === 'thead') {
3142
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
3143
- const grandChildVNode = childVNode.children[iteratorIndex];
3144
- if (grandChildVNode.tagName === 'tr') {
3145
- if (iteratorIndex === 0) {
3146
- const tableGridFragment = buildTableGridFromTableRow(grandChildVNode, modifiedAttributes);
3147
- tableFragment.import(tableGridFragment);
3148
- }
3149
- const tableRowFragment = await buildTableRow(grandChildVNode, modifiedAttributes, rowSpanMap, docxDocumentInstance);
3150
- tableFragment.import(tableRowFragment);
3151
- }
3152
- }
3153
- }
3154
- else if (childVNode.tagName === 'tbody') {
3155
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
3156
- const grandChildVNode = childVNode.children[iteratorIndex];
3157
- if (grandChildVNode.tagName === 'tr') {
3158
- if (iteratorIndex === 0) {
3159
- const tableGridFragment = buildTableGridFromTableRow(grandChildVNode, modifiedAttributes);
3160
- tableFragment.import(tableGridFragment);
3161
- }
3162
- const tableRowFragment = await buildTableRow(grandChildVNode, modifiedAttributes, rowSpanMap, docxDocumentInstance);
3163
- tableFragment.import(tableRowFragment);
3164
- }
3165
- }
3166
- }
3167
- else if (childVNode.tagName === 'tr') {
3168
- if (index === 0) {
3169
- const tableGridFragment = buildTableGridFromTableRow(childVNode, modifiedAttributes);
3170
- tableFragment.import(tableGridFragment);
3171
- }
3172
- const tableRowFragment = await buildTableRow(childVNode, modifiedAttributes, rowSpanMap, docxDocumentInstance);
3173
- tableFragment.import(tableRowFragment);
3174
- }
3175
- }
3176
- }
3177
- tableFragment.up();
3178
- return tableFragment;
3179
- };
3180
- const buildPresetGeometry = () => fragment({ namespaceAlias: { a: namespaces.a } })
3181
- .ele('@a', 'prstGeom')
3182
- .att('prst', 'rect')
3183
- .up();
3184
- const buildExtents = ({ width, height }) => fragment({ namespaceAlias: { a: namespaces.a } })
3185
- .ele('@a', 'ext')
3186
- .att('cx', width)
3187
- .att('cy', height)
3188
- .up();
3189
- const buildOffset = () => fragment({ namespaceAlias: { a: namespaces.a } })
3190
- .ele('@a', 'off')
3191
- .att('x', '0')
3192
- .att('y', '0')
3193
- .up();
3194
- const buildGraphicFrameTransform = (attributes) => {
3195
- const graphicFrameTransformFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'xfrm');
3196
- const offsetFragment = buildOffset();
3197
- graphicFrameTransformFragment.import(offsetFragment);
3198
- const extentsFragment = buildExtents(attributes);
3199
- graphicFrameTransformFragment.import(extentsFragment);
3200
- graphicFrameTransformFragment.up();
3201
- return graphicFrameTransformFragment;
3202
- };
3203
- const buildShapeProperties = (attributes) => {
3204
- const shapeProperties = fragment({ namespaceAlias: { pic: namespaces.pic } }).ele('@pic', 'spPr');
3205
- const graphicFrameTransformFragment = buildGraphicFrameTransform(attributes);
3206
- shapeProperties.import(graphicFrameTransformFragment);
3207
- const presetGeometryFragment = buildPresetGeometry();
3208
- shapeProperties.import(presetGeometryFragment);
3209
- shapeProperties.up();
3210
- return shapeProperties;
3211
- };
3212
- const buildFillRect = () => fragment({ namespaceAlias: { a: namespaces.a } })
3213
- .ele('@a', 'fillRect')
3214
- .up();
3215
- const buildStretch = () => {
3216
- const stretchFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'stretch');
3217
- const fillRectFragment = buildFillRect();
3218
- stretchFragment.import(fillRectFragment);
3219
- stretchFragment.up();
3220
- return stretchFragment;
3221
- };
3222
- const buildSrcRectFragment = () => fragment({ namespaceAlias: { a: namespaces.a } })
3223
- .ele('@a', 'srcRect')
3224
- .att('b', '0')
3225
- .att('l', '0')
3226
- .att('r', '0')
3227
- .att('t', '0')
3228
- .up();
3229
- const buildBinaryLargeImageOrPicture = (relationshipId) => fragment({
3230
- namespaceAlias: { a: namespaces.a, r: namespaces.r },
3231
- })
3232
- .ele('@a', 'blip')
3233
- .att('@r', 'embed', `rId${relationshipId}`)
3234
- // FIXME: possible values 'email', 'none', 'print', 'hqprint', 'screen'
3235
- .att('cstate', 'print')
3236
- .up();
3237
- const buildBinaryLargeImageOrPictureFill = (relationshipId) => {
3238
- const binaryLargeImageOrPictureFillFragment = fragment({
3239
- namespaceAlias: { pic: namespaces.pic },
3240
- }).ele('@pic', 'blipFill');
3241
- const binaryLargeImageOrPictureFragment = buildBinaryLargeImageOrPicture(relationshipId);
3242
- binaryLargeImageOrPictureFillFragment.import(binaryLargeImageOrPictureFragment);
3243
- const srcRectFragment = buildSrcRectFragment();
3244
- binaryLargeImageOrPictureFillFragment.import(srcRectFragment);
3245
- const stretchFragment = buildStretch();
3246
- binaryLargeImageOrPictureFillFragment.import(stretchFragment);
3247
- binaryLargeImageOrPictureFillFragment.up();
3248
- return binaryLargeImageOrPictureFillFragment;
3249
- };
3250
- const buildNonVisualPictureDrawingProperties = () => fragment({ namespaceAlias: { pic: namespaces.pic } })
3251
- .ele('@pic', 'cNvPicPr')
3252
- .up();
3253
- const buildNonVisualDrawingProperties = (pictureId, pictureNameWithExtension, pictureDescription = '') => fragment({ namespaceAlias: { pic: namespaces.pic } })
3254
- .ele('@pic', 'cNvPr')
3255
- .att('id', pictureId)
3256
- .att('name', pictureNameWithExtension)
3257
- .att('descr', pictureDescription)
3258
- .up();
3259
- const buildNonVisualPictureProperties = (pictureId, pictureNameWithExtension, pictureDescription) => {
3260
- const nonVisualPicturePropertiesFragment = fragment({
3261
- namespaceAlias: { pic: namespaces.pic },
3262
- }).ele('@pic', 'nvPicPr');
3263
- // TODO: Handle picture attributes
3264
- const nonVisualDrawingPropertiesFragment = buildNonVisualDrawingProperties(pictureId, pictureNameWithExtension, pictureDescription);
3265
- nonVisualPicturePropertiesFragment.import(nonVisualDrawingPropertiesFragment);
3266
- const nonVisualPictureDrawingPropertiesFragment = buildNonVisualPictureDrawingProperties();
3267
- nonVisualPicturePropertiesFragment.import(nonVisualPictureDrawingPropertiesFragment);
3268
- nonVisualPicturePropertiesFragment.up();
3269
- return nonVisualPicturePropertiesFragment;
3270
- };
3271
- const buildPicture = ({ id, fileNameWithExtension, description, relationshipId, width, height, }) => {
3272
- const pictureFragment = fragment({ namespaceAlias: { pic: namespaces.pic } }).ele('@pic', 'pic');
3273
- const nonVisualPicturePropertiesFragment = buildNonVisualPictureProperties(id, fileNameWithExtension, description);
3274
- pictureFragment.import(nonVisualPicturePropertiesFragment);
3275
- const binaryLargeImageOrPictureFill = buildBinaryLargeImageOrPictureFill(relationshipId);
3276
- pictureFragment.import(binaryLargeImageOrPictureFill);
3277
- const shapeProperties = buildShapeProperties({ width, height });
3278
- pictureFragment.import(shapeProperties);
3279
- pictureFragment.up();
3280
- return pictureFragment;
3281
- };
3282
- const buildGraphicData = (graphicType, attributes) => {
3283
- const graphicDataFragment = fragment({ namespaceAlias: { a: namespaces.a } })
3284
- .ele('@a', 'graphicData')
3285
- .att('uri', 'http://schemas.openxmlformats.org/drawingml/2006/picture');
3286
- if (graphicType === 'picture') {
3287
- const pictureFragment = buildPicture(attributes);
3288
- graphicDataFragment.import(pictureFragment);
3289
- }
3290
- graphicDataFragment.up();
3291
- return graphicDataFragment;
3292
- };
3293
- const buildGraphic = (graphicType, attributes) => {
3294
- const graphicFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'graphic');
3295
- // TODO: Handle drawing type
3296
- const graphicDataFragment = buildGraphicData(graphicType, attributes);
3297
- graphicFragment.import(graphicDataFragment);
3298
- graphicFragment.up();
3299
- return graphicFragment;
3300
- };
3301
- const buildDrawingObjectNonVisualProperties = (pictureId, pictureName) => fragment({ namespaceAlias: { wp: namespaces.wp } })
3302
- .ele('@wp', 'docPr')
3303
- .att('id', pictureId)
3304
- .att('name', pictureName)
3305
- .up();
3306
- const buildWrapSquare = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
3307
- .ele('@wp', 'wrapSquare')
3308
- .att('wrapText', 'bothSides')
3309
- .att('distB', '228600')
3310
- .att('distT', '228600')
3311
- .att('distL', '228600')
3312
- .att('distR', '228600')
3313
- .up();
3314
- // eslint-disable-next-line no-unused-vars
3315
- const buildWrapNone = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
3316
- .ele('@wp', 'wrapNone')
3317
- .up();
3318
- const buildEffectExtentFragment = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
3319
- .ele('@wp', 'effectExtent')
3320
- .att('b', '0')
3321
- .att('l', '0')
3322
- .att('r', '0')
3323
- .att('t', '0')
3324
- .up();
3325
- const buildExtent = ({ width, height }) => fragment({ namespaceAlias: { wp: namespaces.wp } })
3326
- .ele('@wp', 'extent')
3327
- .att('cx', width)
3328
- .att('cy', height)
3329
- .up();
3330
- const buildPositionV = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
3331
- .ele('@wp', 'positionV')
3332
- .att('relativeFrom', 'paragraph')
3333
- .ele('@wp', 'posOffset')
3334
- .txt('19050')
3335
- .up()
3336
- .up();
3337
- const buildPositionH = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
3338
- .ele('@wp', 'positionH')
3339
- .att('relativeFrom', 'column')
3340
- .ele('@wp', 'posOffset')
3341
- .txt('19050')
3342
- .up()
3343
- .up();
3344
- const buildSimplePos = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
3345
- .ele('@wp', 'simplePos')
3346
- .att('x', '0')
3347
- .att('y', '0')
3348
- .up();
3349
- const buildAnchoredDrawing = (graphicType, attributes) => {
3350
- const anchoredDrawingFragment = fragment({ namespaceAlias: { wp: namespaces.wp } })
3351
- .ele('@wp', 'anchor')
3352
- .att('distB', '0')
3353
- .att('distL', '0')
3354
- .att('distR', '0')
3355
- .att('distT', '0')
3356
- .att('relativeHeight', '0')
3357
- .att('behindDoc', 'false')
3358
- .att('locked', 'true')
3359
- .att('layoutInCell', 'true')
3360
- .att('allowOverlap', 'false')
3361
- .att('simplePos', 'false');
3362
- // Even though simplePos isnt supported by Word 2007 simplePos is required.
3363
- const simplePosFragment = buildSimplePos();
3364
- anchoredDrawingFragment.import(simplePosFragment);
3365
- const positionHFragment = buildPositionH();
3366
- anchoredDrawingFragment.import(positionHFragment);
3367
- const positionVFragment = buildPositionV();
3368
- anchoredDrawingFragment.import(positionVFragment);
3369
- const extentFragment = buildExtent({ width: attributes.width, height: attributes.height });
3370
- anchoredDrawingFragment.import(extentFragment);
3371
- const effectExtentFragment = buildEffectExtentFragment();
3372
- anchoredDrawingFragment.import(effectExtentFragment);
3373
- const wrapSquareFragment = buildWrapSquare();
3374
- anchoredDrawingFragment.import(wrapSquareFragment);
3375
- const drawingObjectNonVisualPropertiesFragment = buildDrawingObjectNonVisualProperties(attributes.id, attributes.fileNameWithExtension);
3376
- anchoredDrawingFragment.import(drawingObjectNonVisualPropertiesFragment);
3377
- const graphicFragment = buildGraphic(graphicType, attributes);
3378
- anchoredDrawingFragment.import(graphicFragment);
3379
- anchoredDrawingFragment.up();
3380
- return anchoredDrawingFragment;
3381
- };
3382
- const buildInlineDrawing = (graphicType, attributes) => {
3383
- const inlineDrawingFragment = fragment({ namespaceAlias: { wp: namespaces.wp } })
3384
- .ele('@wp', 'inline')
3385
- .att('distB', '0')
3386
- .att('distL', '0')
3387
- .att('distR', '0')
3388
- .att('distT', '0');
3389
- const extentFragment = buildExtent({ width: attributes.width, height: attributes.height });
3390
- inlineDrawingFragment.import(extentFragment);
3391
- const effectExtentFragment = buildEffectExtentFragment();
3392
- inlineDrawingFragment.import(effectExtentFragment);
3393
- const drawingObjectNonVisualPropertiesFragment = buildDrawingObjectNonVisualProperties(attributes.id, attributes.fileNameWithExtension);
3394
- inlineDrawingFragment.import(drawingObjectNonVisualPropertiesFragment);
3395
- const graphicFragment = buildGraphic(graphicType, attributes);
3396
- inlineDrawingFragment.import(graphicFragment);
3397
- inlineDrawingFragment.up();
3398
- return inlineDrawingFragment;
3399
- };
3400
- const buildDrawing = (inlineOrAnchored = false, graphicType, attributes) => {
3401
- const drawingFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'drawing');
3402
- const inlineOrAnchoredDrawingFragment = inlineOrAnchored
3403
- ? buildInlineDrawing(graphicType, attributes)
3404
- : buildAnchoredDrawing(graphicType, attributes);
3405
- drawingFragment.import(inlineOrAnchoredDrawingFragment);
3406
- drawingFragment.up();
3407
- return drawingFragment;
3408
- };
3409
- // eslint-disable-next-line consistent-return, no-shadow
3410
- const buildImage = async (docxDocumentInstance, vNode, maximumWidth = null) => {
3411
- let response = null;
3412
- let base64Uri = null;
3413
- try {
3414
- const imageSource = vNode.properties.src;
3415
- if (isValidUrl(imageSource)) {
3416
- const base64String = await imageToBase64(imageSource).catch((error) => {
3417
- // eslint-disable-next-line no-console
3418
- console.warning(`skipping image download and conversion due to ${error}`);
3419
- });
3420
- if (base64String) {
3421
- base64Uri = `data:${mimeTypes.lookup(imageSource)};base64, ${base64String}`;
3422
- }
3423
- }
3424
- else {
3425
- base64Uri = decodeURIComponent(vNode.properties.src);
3426
- }
3427
- if (base64Uri) {
3428
- response = docxDocumentInstance.createMediaFile(base64Uri);
3429
- }
3430
- }
3431
- catch (error) {
3432
- // NOOP
3433
- }
3434
- if (response) {
3435
- docxDocumentInstance.zip
3436
- .folder('word')
3437
- .folder('media')
3438
- .file(response.fileNameWithExtension, Buffer.from(response.fileContent, 'base64'), {
3439
- createFolders: false,
3440
- });
3441
- const documentRelsId = docxDocumentInstance.createDocumentRelationships(docxDocumentInstance.relationshipFilename, imageType, `media/${response.fileNameWithExtension}`, internalRelationship);
3442
- const imageBuffer = Buffer.from(response.fileContent, 'base64');
3443
- const imageProperties = sizeOf(imageBuffer);
3444
- const imageFragment = await xmlBuilder.buildParagraph(vNode, {
3445
- type: 'picture',
3446
- inlineOrAnchored: true,
3447
- relationshipId: documentRelsId,
3448
- ...response,
3449
- maximumWidth: maximumWidth || docxDocumentInstance.availableDocumentSpace,
3450
- originalWidth: imageProperties.width,
3451
- originalHeight: imageProperties.height,
3452
- }, docxDocumentInstance);
3453
- return imageFragment;
3454
- }
3455
- };
3456
- const buildList = async (vNode, docxDocumentInstance, xmlFragment) => {
3457
- const listElements = [];
3458
- let vNodeObjects = [
3459
- {
3460
- node: vNode,
3461
- level: 0,
3462
- type: vNode.tagName,
3463
- numberingId: docxDocumentInstance.createNumbering(vNode.tagName, vNode.properties),
3464
- },
3465
- ];
3466
- while (vNodeObjects.length) {
3467
- const tempVNodeObject = vNodeObjects.shift();
3468
- if (isVText(tempVNodeObject.node) ||
3469
- (isVNode(tempVNodeObject.node) && !['ul', 'ol', 'li'].includes(tempVNodeObject.node.tagName))) {
3470
- const paragraphFragment = await xmlBuilder.buildParagraph(tempVNodeObject.node, {
3471
- numbering: { levelId: tempVNodeObject.level, numberingId: tempVNodeObject.numberingId },
3472
- }, docxDocumentInstance);
3473
- xmlFragment.import(paragraphFragment);
3474
- }
3475
- if (tempVNodeObject.node.children &&
3476
- tempVNodeObject.node.children.length &&
3477
- ['ul', 'ol', 'li'].includes(tempVNodeObject.node.tagName)) {
3478
- const tempVNodeObjects = tempVNodeObject.node.children.reduce((accumulator, childVNode) => {
3479
- if (['ul', 'ol'].includes(childVNode.tagName)) {
3480
- accumulator.push({
3481
- node: childVNode,
3482
- level: tempVNodeObject.level + 1,
3483
- type: childVNode.tagName,
3484
- numberingId: docxDocumentInstance.createNumbering(childVNode.tagName, childVNode.properties),
3485
- });
3486
- }
3487
- else {
3488
- // eslint-disable-next-line no-lonely-if
3489
- if (accumulator.length > 0 &&
3490
- isVNode(accumulator[accumulator.length - 1].node) &&
3491
- accumulator[accumulator.length - 1].node.tagName.toLowerCase() === 'p') {
3492
- accumulator[accumulator.length - 1].node.children.push(childVNode);
3493
- }
3494
- else {
3495
- const paragraphVNode = new VNode('p', null,
3496
- // eslint-disable-next-line no-nested-ternary
3497
- isVText(childVNode)
3498
- ? [childVNode]
3499
- : // eslint-disable-next-line no-nested-ternary
3500
- isVNode(childVNode)
3501
- ? childVNode.tagName.toLowerCase() === 'li'
3502
- ? [...childVNode.children]
3503
- : [childVNode]
3504
- : []);
3505
- accumulator.push({
3506
- // eslint-disable-next-line prettier/prettier, no-nested-ternary
3507
- node: isVNode(childVNode)
3508
- ? // eslint-disable-next-line prettier/prettier, no-nested-ternary
3509
- childVNode.tagName.toLowerCase() === 'li'
3510
- ? childVNode
3511
- : childVNode.tagName.toLowerCase() !== 'p'
3512
- ? paragraphVNode
3513
- : childVNode
3514
- : // eslint-disable-next-line prettier/prettier
3515
- paragraphVNode,
3516
- level: tempVNodeObject.level,
3517
- type: tempVNodeObject.type,
3518
- numberingId: tempVNodeObject.numberingId,
3519
- });
3520
- }
3521
- }
3522
- return accumulator;
3523
- }, []);
3524
- vNodeObjects = tempVNodeObjects.concat(vNodeObjects);
3525
- }
3526
- }
3527
- return listElements;
3528
- };
3529
-
3530
- /* eslint-disable no-await-in-loop */
3531
- /* eslint-disable no-case-declarations */
3532
- const convertHTML$1 = HTMLToVDOM({
3533
- VNode: VNode$1,
3534
- VText,
3535
- });
3536
- async function findXMLEquivalent(docxDocumentInstance, vNode, xmlFragment) {
3537
- if (vNode.tagName === 'div' &&
3538
- (vNode.properties.attributes.class === 'page-break' ||
3539
- (vNode.properties.style && vNode.properties.style['page-break-after']))) {
3540
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
3541
- .ele('@w', 'p')
3542
- .ele('@w', 'r')
3543
- .ele('@w', 'br')
3544
- .att('@w', 'type', 'page')
3545
- .up()
3546
- .up()
3547
- .up();
3548
- xmlFragment.import(paragraphFragment);
3549
- return;
3550
- }
3551
- switch (vNode.tagName) {
3552
- case 'h1':
3553
- case 'h2':
3554
- case 'h3':
3555
- case 'h4':
3556
- case 'h5':
3557
- case 'h6':
3558
- const headingFragment = await buildParagraph(vNode, {
3559
- paragraphStyle: `Heading${vNode.tagName[1]}`,
3560
- }, docxDocumentInstance);
3561
- xmlFragment.import(headingFragment);
3562
- return;
3563
- case 'span':
3564
- case 'strong':
3565
- case 'b':
3566
- case 'em':
3567
- case 'i':
3568
- case 'u':
3569
- case 'ins':
3570
- case 'strike':
3571
- case 'del':
3572
- case 's':
3573
- case 'sub':
3574
- case 'sup':
3575
- case 'mark':
3576
- case 'p':
3577
- case 'a':
3578
- case 'blockquote':
3579
- case 'code':
3580
- case 'pre':
3581
- const paragraphFragment = await buildParagraph(vNode, {}, docxDocumentInstance);
3582
- xmlFragment.import(paragraphFragment);
3583
- return;
3584
- case 'figure':
3585
- if (vNodeHasChildren(vNode)) {
3586
- // eslint-disable-next-line no-plusplus
3587
- for (let index = 0; index < vNode.children.length; index++) {
3588
- const childVNode = vNode.children[index];
3589
- if (childVNode.tagName === 'table') {
3590
- const tableFragment = await buildTable(childVNode, {
3591
- maximumWidth: docxDocumentInstance.availableDocumentSpace,
3592
- rowCantSplit: docxDocumentInstance.tableRowCantSplit,
3593
- }, docxDocumentInstance);
3594
- xmlFragment.import(tableFragment);
3595
- // Adding empty paragraph for space after table
3596
- const emptyParagraphFragment = await buildParagraph(null, {});
3597
- xmlFragment.import(emptyParagraphFragment);
3598
- }
3599
- else if (childVNode.tagName === 'img') {
3600
- const imageFragment = await buildImage(docxDocumentInstance, childVNode);
3601
- if (imageFragment) {
3602
- xmlFragment.import(imageFragment);
3603
- }
3604
- }
3605
- }
3606
- }
3607
- return;
3608
- case 'table':
3609
- const tableFragment = await buildTable(vNode, {
3610
- maximumWidth: docxDocumentInstance.availableDocumentSpace,
3611
- rowCantSplit: docxDocumentInstance.tableRowCantSplit,
3612
- }, docxDocumentInstance);
3613
- xmlFragment.import(tableFragment);
3614
- // Adding empty paragraph for space after table
3615
- const emptyParagraphFragment = await buildParagraph(null, {});
3616
- xmlFragment.import(emptyParagraphFragment);
3617
- return;
3618
- case 'ol':
3619
- case 'ul':
3620
- await buildList(vNode, docxDocumentInstance, xmlFragment);
3621
- return;
3622
- case 'img':
3623
- const imageFragment = await buildImage(docxDocumentInstance, vNode);
3624
- if (imageFragment) {
3625
- xmlFragment.import(imageFragment);
3626
- }
3627
- return;
3628
- case 'br':
3629
- const linebreakFragment = await buildParagraph(null, {});
3630
- xmlFragment.import(linebreakFragment);
3631
- return;
3632
- }
3633
- if (vNodeHasChildren(vNode)) {
3634
- // eslint-disable-next-line no-plusplus
3635
- for (let index = 0; index < vNode.children.length; index++) {
3636
- const childVNode = vNode.children[index];
3637
- // eslint-disable-next-line no-use-before-define
3638
- await convertVTreeToXML(docxDocumentInstance, childVNode, xmlFragment);
3639
- }
3640
- }
3641
- }
3642
- // eslint-disable-next-line consistent-return
3643
- async function convertVTreeToXML(docxDocumentInstance, vTree, xmlFragment) {
3644
- if (!vTree) {
3645
- // eslint-disable-next-line no-useless-return
3646
- return '';
3647
- }
3648
- if (Array.isArray(vTree) && vTree.length) {
3649
- // eslint-disable-next-line no-plusplus
3650
- for (let index = 0; index < vTree.length; index++) {
3651
- const vNode = vTree[index];
3652
- await convertVTreeToXML(docxDocumentInstance, vNode, xmlFragment);
3653
- }
3654
- }
3655
- else if (isVNode(vTree)) {
3656
- await findXMLEquivalent(docxDocumentInstance, vTree, xmlFragment);
3657
- }
3658
- else if (isVText(vTree)) {
3659
- buildTextElement(xmlFragment, escape(String(vTree.text)));
3660
- }
3661
- return xmlFragment;
3662
- }
3663
- async function renderDocumentFile(docxDocumentInstance) {
3664
- const vTree = convertHTML$1(docxDocumentInstance.htmlString);
3665
- const xmlFragment = fragment({ namespaceAlias: { w: namespaces.w } });
3666
- const populatedXmlFragment = await convertVTreeToXML(docxDocumentInstance, vTree, xmlFragment);
3667
- return populatedXmlFragment;
3668
- }
3669
-
3670
- /* eslint-disable import/prefer-default-export */
3671
-
3672
- class ListStyleBuilder {
3673
- // defaults is an object passed in from constants.js / numbering with the following properties:
3674
- // defaultOrderedListStyleType: 'decimal' (unless otherwise specified)
3675
- constructor(defaults) {
3676
- this.defaults = defaults || { defaultOrderedListStyleType: 'decimal' };
3677
- }
3678
- // eslint-disable-next-line class-methods-use-this
3679
- getListStyleType(listType) {
3680
- switch (listType) {
3681
- case 'upper-roman':
3682
- return 'upperRoman';
3683
- case 'lower-roman':
3684
- return 'lowerRoman';
3685
- case 'upper-alpha':
3686
- case 'upper-alpha-bracket-end':
3687
- return 'upperLetter';
3688
- case 'lower-alpha':
3689
- case 'lower-alpha-bracket-end':
3690
- return 'lowerLetter';
3691
- case 'decimal':
3692
- case 'decimal-bracket':
3693
- return 'decimal';
3694
- default:
3695
- return this.defaults.defaultOrderedListStyleType;
3696
- }
3697
- }
3698
- getListPrefixSuffix(style, lvl) {
3699
- let listType = this.defaults.defaultOrderedListStyleType;
3700
- if (style && style['list-style-type']) {
3701
- listType = style['list-style-type'];
3702
- }
3703
- switch (listType) {
3704
- case 'upper-roman':
3705
- case 'lower-roman':
3706
- case 'upper-alpha':
3707
- case 'lower-alpha':
3708
- return `%${lvl + 1}.`;
3709
- case 'upper-alpha-bracket-end':
3710
- case 'lower-alpha-bracket-end':
3711
- case 'decimal-bracket-end':
3712
- return `%${lvl + 1})`;
3713
- case 'decimal-bracket':
3714
- return `(%${lvl + 1})`;
3715
- case 'decimal':
3716
- default:
3717
- return `%${lvl + 1}.`;
3718
- }
3719
- }
3720
- }
3721
-
3722
- function generateContentTypesFragments(contentTypesXML, type, objects) {
3723
- if (objects && Array.isArray(objects)) {
3724
- objects.forEach((object) => {
3725
- const contentTypesFragment = fragment({ defaultNamespace: { ele: namespaces.contentTypes } })
3726
- .ele('Override')
3727
- .att('PartName', `/word/${type}${object[`${type}Id`]}.xml`)
3728
- .att('ContentType', `application/vnd.openxmlformats-officedocument.wordprocessingml.${type}+xml`)
3729
- .up();
3730
- contentTypesXML.root().import(contentTypesFragment);
3731
- });
3732
- }
3733
- }
3734
- function generateSectionReferenceXML(documentXML, documentSectionType, objects, isEnabled) {
3735
- if (isEnabled && objects && Array.isArray(objects) && objects.length) {
3736
- const xmlFragment = fragment();
3737
- objects.forEach(({ relationshipId, type }) => {
3738
- const objectFragment = fragment({ namespaceAlias: { w: namespaces.w, r: namespaces.r } })
3739
- .ele('@w', `${documentSectionType}Reference`)
3740
- .att('@r', 'id', `rId${relationshipId}`)
3741
- .att('@w', 'type', type)
3742
- .up();
3743
- xmlFragment.import(objectFragment);
3744
- });
3745
- documentXML.root().first().first().import(xmlFragment);
3746
- }
3747
- }
3748
- function generateXMLString(xmlString) {
3749
- const xmlDocumentString = create({ encoding: 'UTF-8', standalone: true }, xmlString);
3750
- return xmlDocumentString.toString({ prettyPrint: true });
3751
- }
3752
- async function generateSectionXML(vTree, type = 'header') {
3753
- debugger;
3754
- const sectionXML = create({
3755
- encoding: 'UTF-8',
3756
- standalone: true,
3757
- namespaceAlias: {
3758
- a: namespaces.a,
3759
- cdr: namespaces.cdr,
3760
- o: namespaces.o,
3761
- pic: namespaces.pic,
3762
- r: namespaces.r,
3763
- v: namespaces.v,
3764
- ve: namespaces.ve,
3765
- vt: namespaces.vt,
3766
- w: namespaces.w,
3767
- w10: namespaces.w10,
3768
- wp: namespaces.wp,
3769
- wne: namespaces.wne
3770
- },
3771
- }).ele('@w', type === 'header' ? 'hdr' : 'ftr');
3772
- const XMLFragment = fragment();
3773
- await convertVTreeToXML(this, vTree, XMLFragment);
3774
- if (type === 'footer' && XMLFragment.first().node.tagName === 'p' && this.pageNumber) {
3775
- XMLFragment.first().import(fragment({ namespaceAlias: { w: namespaces.w } })
3776
- .ele('@w', 'fldSimple')
3777
- .att('@w', 'instr', 'PAGE')
3778
- .ele('@w', 'r')
3779
- .up()
3780
- .up());
3781
- }
3782
- sectionXML.root().import(XMLFragment);
3783
- const referenceName = type === 'header' ? 'Header' : 'Footer';
3784
- this[`last${referenceName}Id`] += 1;
3785
- return { [`${type}Id`]: this[`last${referenceName}Id`], [`${type}XML`]: sectionXML };
3786
- }
3787
- class DocxDocument {
3788
- constructor(properties) {
3789
- this.zip = properties.zip;
3790
- this.htmlString = properties.htmlString;
3791
- this.orientation = properties.orientation;
3792
- this.pageSize = properties.pageSize || defaultDocumentOptions.pageSize;
3793
- const isPortraitOrientation = this.orientation === defaultOrientation;
3794
- const height = this.pageSize.height ? this.pageSize.height : landscapeHeight;
3795
- const width = this.pageSize.width ? this.pageSize.width : landscapeWidth;
3796
- this.width = isPortraitOrientation ? width : height;
3797
- this.height = isPortraitOrientation ? height : width;
3798
- const marginsObject = properties.margins;
3799
- this.margins =
3800
- // eslint-disable-next-line no-nested-ternary
3801
- marginsObject && Object.keys(marginsObject).length
3802
- ? marginsObject
3803
- : isPortraitOrientation
3804
- ? portraitMargins
3805
- : landscapeMargins;
3806
- this.availableDocumentSpace = this.width - this.margins.left - this.margins.right;
3807
- this.title = properties.title || '';
3808
- this.subject = properties.subject || '';
3809
- this.creator = properties.creator || applicationName;
3810
- this.keywords = properties.keywords || [applicationName];
3811
- this.description = properties.description || '';
3812
- this.lastModifiedBy = properties.lastModifiedBy || applicationName;
3813
- this.revision = properties.revision || 1;
3814
- this.createdAt = properties.createdAt || new Date();
3815
- this.modifiedAt = properties.modifiedAt || new Date();
3816
- this.headerType = properties.headerType || 'default';
3817
- this.header = properties.header || false;
3818
- this.footerType = properties.footerType || 'default';
3819
- this.footer = properties.footer || false;
3820
- this.font = properties.font || defaultFont;
3821
- this.fontSize = properties.fontSize || defaultFontSize;
3822
- this.complexScriptFontSize = properties.complexScriptFontSize || defaultFontSize;
3823
- this.tableRowCantSplit =
3824
- (properties.table && properties.table.row && properties.table.row.cantSplit) || false;
3825
- this.pageNumber = properties.pageNumber || false;
3826
- this.skipFirstHeaderFooter = properties.skipFirstHeaderFooter || false;
3827
- this.lineNumber = properties.lineNumber ? properties.lineNumberOptions : null;
3828
- this.lastNumberingId = 0;
3829
- this.lastMediaId = 0;
3830
- this.lastHeaderId = 0;
3831
- this.lastFooterId = 0;
3832
- this.stylesObjects = [];
3833
- this.numberingObjects = [];
3834
- this.relationshipFilename = documentFileName;
3835
- this.relationships = [{ fileName: documentFileName, lastRelsId: 4, rels: [] }];
3836
- this.mediaFiles = [];
3837
- this.headerObjects = [];
3838
- this.footerObjects = [];
3839
- this.documentXML = null;
3840
- this.generateContentTypesXML = this.generateContentTypesXML.bind(this);
3841
- this.generateDocumentXML = this.generateDocumentXML.bind(this);
3842
- this.generateCoreXML = this.generateCoreXML.bind(this);
3843
- this.generateSettingsXML = this.generateSettingsXML.bind(this);
3844
- this.generateWebSettingsXML = this.generateWebSettingsXML.bind(this);
3845
- this.generateStylesXML = this.generateStylesXML.bind(this);
3846
- this.generateFontTableXML = this.generateFontTableXML.bind(this);
3847
- this.generateThemeXML = this.generateThemeXML.bind(this);
3848
- this.generateNumberingXML = this.generateNumberingXML.bind(this);
3849
- this.generateRelsXML = this.generateRelsXML.bind(this);
3850
- this.createMediaFile = this.createMediaFile.bind(this);
3851
- this.createDocumentRelationships = this.createDocumentRelationships.bind(this);
3852
- this.generateHeaderXML = this.generateHeaderXML.bind(this);
3853
- this.generateFooterXML = this.generateFooterXML.bind(this);
3854
- this.generateSectionXML = generateSectionXML.bind(this);
3855
- this.ListStyleBuilder = new ListStyleBuilder(properties.numbering);
3856
- }
3857
- generateContentTypesXML() {
3858
- const contentTypesXML$1 = create({ encoding: 'UTF-8', standalone: true }, contentTypesXML);
3859
- generateContentTypesFragments(contentTypesXML$1, 'header', this.headerObjects);
3860
- generateContentTypesFragments(contentTypesXML$1, 'footer', this.footerObjects);
3861
- return contentTypesXML$1.toString({ prettyPrint: true });
3862
- }
3863
- generateDocumentXML() {
3864
- const documentXML = create({ encoding: 'UTF-8', standalone: true }, generateDocumentTemplate(this.width, this.height, this.orientation, this.margins));
3865
- // documentXML.root().first().import(this.documentXML);
3866
- generateSectionReferenceXML(documentXML, 'header', this.headerObjects, this.header);
3867
- generateSectionReferenceXML(documentXML, 'footer', this.footerObjects, this.footer);
3868
- if ((this.header || this.footer) && this.skipFirstHeaderFooter) {
3869
- documentXML
3870
- .root()
3871
- .first()
3872
- .first()
3873
- .import(fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'titlePg'));
3874
- }
3875
- if (this.lineNumber) {
3876
- const { countBy, start, restart } = this.lineNumber;
3877
- documentXML
3878
- .root()
3879
- .first()
3880
- .first()
3881
- .import(fragment({ namespaceAlias: { w: namespaces.w } })
3882
- .ele('@w', 'lnNumType')
3883
- .att('@w', 'countBy', countBy)
3884
- .att('@w', 'start', start)
3885
- .att('@w', 'restart', restart));
3886
- }
3887
- return documentXML.toString({ prettyPrint: true });
3888
- }
3889
- generateCoreXML() {
3890
- return generateXMLString(generateCoreXML(this.title, this.subject, this.creator, this.keywords, this.description, this.lastModifiedBy, this.revision, this.createdAt, this.modifiedAt));
3891
- }
3892
- // eslint-disable-next-line class-methods-use-this
3893
- generateSettingsXML() {
3894
- return generateXMLString(settingsXML);
3895
- }
3896
- // eslint-disable-next-line class-methods-use-this
3897
- generateWebSettingsXML() {
3898
- return generateXMLString(webSettingsXML);
3899
- }
3900
- generateStylesXML() {
3901
- return generateXMLString(generateStylesXML(this.font, this.fontSize, this.complexScriptFontSize));
3902
- }
3903
- // eslint-disable-next-line class-methods-use-this
3904
- generateFontTableXML() {
3905
- return generateXMLString(fontTableXML);
3906
- }
3907
- generateThemeXML() {
3908
- return generateXMLString(generateThemeXML(this.font));
3909
- }
3910
- generateNumberingXML() {
3911
- const numberingXML = create({ encoding: 'UTF-8', standalone: true }, generateNumberingXMLTemplate());
3912
- const abstractNumberingFragments = fragment();
3913
- const numberingFragments = fragment();
3914
- this.numberingObjects.forEach(({ numberingId, type, properties }) => {
3915
- const abstractNumberingFragment = fragment({ namespaceAlias: { w: namespaces.w } })
3916
- .ele('@w', 'abstractNum')
3917
- .att('@w', 'abstractNumId', String(numberingId));
3918
- [...Array(8).keys()].forEach((level) => {
3919
- const levelFragment = fragment({ namespaceAlias: { w: namespaces.w } })
3920
- .ele('@w', 'lvl')
3921
- .att('@w', 'ilvl', level)
3922
- .ele('@w', 'start')
3923
- .att('@w', 'val', type === 'ol'
3924
- ? (properties.attributes && properties.attributes['data-start']) || 1
3925
- : '1')
3926
- .up()
3927
- .ele('@w', 'numFmt')
3928
- .att('@w', 'val', type === 'ol'
3929
- ? this.ListStyleBuilder.getListStyleType(properties.style && properties.style['list-style-type'])
3930
- : 'bullet')
3931
- .up()
3932
- .ele('@w', 'lvlText')
3933
- .att('@w', 'val', type === 'ol' ? this.ListStyleBuilder.getListPrefixSuffix(properties.style, level) : '')
3934
- .up()
3935
- .ele('@w', 'lvlJc')
3936
- .att('@w', 'val', 'left')
3937
- .up()
3938
- .ele('@w', 'pPr')
3939
- .ele('@w', 'tabs')
3940
- .ele('@w', 'tab')
3941
- .att('@w', 'val', 'num')
3942
- .att('@w', 'pos', (level + 1) * 720)
3943
- .up()
3944
- .up()
3945
- .ele('@w', 'ind')
3946
- .att('@w', 'left', (level + 1) * 720)
3947
- .att('@w', 'hanging', 360)
3948
- .up()
3949
- .up()
3950
- .up();
3951
- if (type === 'ul') {
3952
- levelFragment.last().import(fragment({ namespaceAlias: { w: namespaces.w } })
3953
- .ele('@w', 'rPr')
3954
- .ele('@w', 'rFonts')
3955
- .att('@w', 'ascii', 'Symbol')
3956
- .att('@w', 'hAnsi', 'Symbol')
3957
- .att('@w', 'hint', 'default')
3958
- .up()
3959
- .up());
3960
- }
3961
- abstractNumberingFragment.import(levelFragment);
3962
- });
3963
- abstractNumberingFragment.up();
3964
- abstractNumberingFragments.import(abstractNumberingFragment);
3965
- numberingFragments.import(fragment({ namespaceAlias: { w: namespaces.w } })
3966
- .ele('@w', 'num')
3967
- .att('@w', 'numId', String(numberingId))
3968
- .ele('@w', 'abstractNumId')
3969
- .att('@w', 'val', String(numberingId))
3970
- .up()
3971
- .up());
3972
- });
3973
- numberingXML.root().import(abstractNumberingFragments);
3974
- numberingXML.root().import(numberingFragments);
3975
- return numberingXML.toString({ prettyPrint: true });
3976
- }
3977
- // eslint-disable-next-line class-methods-use-this
3978
- appendRelationships(xmlFragment, relationships) {
3979
- relationships.forEach(({ relationshipId, type, target, targetMode }) => {
3980
- xmlFragment.import(fragment({ defaultNamespace: { ele: namespaces.relationship } })
3981
- .ele('Relationship')
3982
- .att('Id', `rId${relationshipId}`)
3983
- .att('Type', type)
3984
- .att('Target', target)
3985
- .att('TargetMode', targetMode)
3986
- .up());
3987
- });
3988
- }
3989
- generateRelsXML() {
3990
- const relationshipXMLStrings = this.relationships.map(({ fileName, rels }) => {
3991
- const xmlFragment = create({ encoding: 'UTF-8', standalone: true }, fileName === documentFileName ? documentRelsXML : genericRelsXML);
3992
- this.appendRelationships(xmlFragment.root(), rels);
3993
- return { fileName, xmlString: xmlFragment.toString({ prettyPrint: true }) };
3994
- });
3995
- return relationshipXMLStrings;
3996
- }
3997
- createNumbering(type, properties) {
3998
- this.lastNumberingId += 1;
3999
- this.numberingObjects.push({ numberingId: this.lastNumberingId, type, properties });
4000
- return this.lastNumberingId;
4001
- }
4002
- createMediaFile(base64String) {
4003
- // eslint-disable-next-line no-useless-escape
4004
- const matches = base64String.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
4005
- if (matches.length !== 3) {
4006
- throw new Error('Invalid base64 string');
4007
- }
4008
- const base64FileContent = matches[2];
4009
- // matches array contains file type in base64 format - image/jpeg and base64 stringified data
4010
- const fileExtension = matches[1].match(/\/(.*?)$/)[1] === 'octet-stream' ? 'png' : matches[1].match(/\/(.*?)$/)[1];
4011
- const fileNameWithExtension = `image-${nanoid()}.${fileExtension}`;
4012
- this.lastMediaId += 1;
4013
- return { id: this.lastMediaId, fileContent: base64FileContent, fileNameWithExtension };
4014
- }
4015
- createDocumentRelationships(fileName = 'document', type, target, targetMode = 'External') {
4016
- debugger;
4017
- let relationshipObject = this.relationships.find((relationship) => relationship.fileName === fileName);
4018
- let lastRelsId = 1;
4019
- if (relationshipObject) {
4020
- lastRelsId = relationshipObject.lastRelsId + 1;
4021
- relationshipObject.lastRelsId = lastRelsId;
4022
- }
4023
- else {
4024
- relationshipObject = { fileName, lastRelsId, rels: [] };
4025
- this.relationships.push(relationshipObject);
4026
- }
4027
- let relationshipType;
4028
- switch (type) {
4029
- case hyperlinkType:
4030
- relationshipType = namespaces.hyperlinks;
4031
- break;
4032
- case imageType:
4033
- relationshipType = namespaces.images;
4034
- break;
4035
- case headerType:
4036
- relationshipType = namespaces.headers;
4037
- break;
4038
- case footerType:
4039
- relationshipType = namespaces.footers;
4040
- break;
4041
- case themeType:
4042
- relationshipType = namespaces.themes;
4043
- break;
4044
- }
4045
- relationshipObject.rels.push({
4046
- relationshipId: lastRelsId,
4047
- type: relationshipType,
4048
- target,
4049
- targetMode,
4050
- });
4051
- console.log(fileName);
4052
- console.log(relationshipObject.rels);
4053
- return lastRelsId;
4054
- }
4055
- generateHeaderXML(vTree) {
4056
- return this.generateSectionXML(vTree, 'header');
4057
- }
4058
- generateFooterXML(vTree) {
4059
- return this.generateSectionXML(vTree, 'footer');
4060
- }
4061
- }
4062
-
4063
- const defaultMargins = {
4064
- top: 1440,
4065
- right: 1440,
4066
- bottom: 1440,
4067
- left: 1440,
4068
- header: 720,
4069
- footer: 720,
4070
- gutter: 0,
4071
- };
4072
- const documentTemplate = (width, height, orient, margins) => {
4073
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
4074
- <w:document
4075
- xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
4076
- xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
4077
- xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
4078
- xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
4079
- xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
4080
- xmlns:ns6="http://schemas.openxmlformats.org/schemaLibrary/2006/main"
4081
- xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart"
4082
- xmlns:ns8="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
4083
- xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram"
4084
- xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
4085
- xmlns:ns11="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
4086
- xmlns:dsp="http://schemas.microsoft.com/office/drawing/2008/diagram"
4087
- xmlns:ns13="urn:schemas-microsoft-com:office:excel"
4088
- xmlns:o="urn:schemas-microsoft-com:office:office"
4089
- xmlns:v="urn:schemas-microsoft-com:vml"
4090
- xmlns:w10="urn:schemas-microsoft-com:office:word"
4091
- xmlns:ns17="urn:schemas-microsoft-com:office:powerpoint"
4092
- xmlns:odx="http://opendope.org/xpaths"
4093
- xmlns:odc="http://opendope.org/conditions"
4094
- xmlns:odq="http://opendope.org/questions"
4095
- xmlns:odi="http://opendope.org/components"
4096
- xmlns:odgm="http://opendope.org/SmartArt/DataHierarchy"
4097
- xmlns:ns24="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"
4098
- xmlns:ns25="http://schemas.openxmlformats.org/drawingml/2006/compatibility"
4099
- xmlns:ns26="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas">
4100
- <w:body>
4101
- <w:altChunk r:id="htmlChunk" />
4102
- <w:sectPr>
4103
- <w:pgSz w:w="${width}" w:h="${height}" w:orient="${orient}" />
4104
- <w:pgMar w:top="${margins.top}"
4105
- w:right="${margins.right}"
4106
- w:bottom="${margins.bottom}"
4107
- w:left="${margins.left}"
4108
- w:header="${margins.header}"
4109
- w:footer="${margins.footer}"
4110
- w:gutter="${margins.gutter}"/>
4111
- </w:sectPr>
4112
- </w:body>
4113
- </w:document>
4114
- `;
4115
- };
4116
-
4117
- const mhtDocumentTemplate = (htmlSource, contentParts) => {
4118
- debugger;
4119
- return `MIME-Version: 1.0
4120
- Content-Type: multipart/related;
4121
- type="text/html";
4122
- boundary="----=mhtDocumentPart"
4123
-
4124
-
4125
- ------=mhtDocumentPart
4126
- Content-Type: text/html;
4127
- charset="utf-8"
4128
- Content-Transfer-Encoding: quoted-printable
4129
- Content-Location: file:///C:/fake/document.html
4130
-
4131
- ${htmlSource}
4132
-
4133
- ${contentParts}
4134
-
4135
- ------=mhtDocumentPart--
4136
- `;
4137
- };
4138
-
4139
- const mhtPartTemplate = (contentType, contentEncoding, contentLocation, encodedContent) => {
4140
- return `------=mhtDocumentPart
4141
- Content-Type: ${contentType}
4142
- Content-Transfer-Encoding: ${contentEncoding}
4143
- Content-Location: ${contentLocation}
4144
-
4145
- ${encodedContent}
4146
- `;
4147
- };
4148
-
4149
- function getMHTdocument(htmlSource) {
4150
- debugger;
4151
- const ref = _prepareImageParts(htmlSource);
4152
- const imageContentPartsString = ref.imageContentParts.join('\n');
4153
- htmlSource = ref.htmlSource.replace(/\=/g, '=3D');
4154
- return mhtDocumentTemplate(htmlSource, imageContentPartsString);
4155
- }
4156
- function _prepareImageParts(htmlSource) {
4157
- debugger;
4158
- const imageContentParts = [];
4159
- const inlinedSrcPattern = /"data:(\w+\/\w+);(\w+),(\S+)"/g;
4160
- const inlinedReplacer = (match, contentType, contentEncoding, encodedContent) => {
4161
- const index = imageContentParts.length;
4162
- const extension = contentType.split('/')[1];
4163
- const contentLocation = `file:///C:/fake/image${index}.${extension}`;
4164
- imageContentParts.push(mhtPartTemplate(contentType, contentEncoding, contentLocation, encodedContent));
4165
- return `\"${contentLocation}\"`;
4166
- };
4167
- if (!/<img/g.test(htmlSource)) {
4168
- return { htmlSource, imageContentParts };
4169
- }
4170
- htmlSource = htmlSource.replace(inlinedSrcPattern, inlinedReplacer);
4171
- return { htmlSource, imageContentParts };
4172
- }
4173
-
4174
- const convertHTML = HTMLToVDOM({
4175
- VNode: VNode$1,
4176
- VText,
4177
- });
4178
- const mergeOptions = (options, patch) => ({ ...options, ...patch });
4179
- const fixupFontSize = (fontSize) => {
4180
- let normalizedFontSize;
4181
- if (pointRegex.test(fontSize)) {
4182
- const matchedParts = fontSize.match(pointRegex);
4183
- normalizedFontSize = pointToHIP(matchedParts[1]);
4184
- }
4185
- else if (fontSize) {
4186
- // assuming it is already in HIP
4187
- normalizedFontSize = fontSize;
4188
- }
4189
- else {
4190
- normalizedFontSize = null;
4191
- }
4192
- return normalizedFontSize;
4193
- };
4194
- const normalizeUnits = (dimensioningObject, defaultDimensionsProperty) => {
4195
- let normalizedUnitResult = {};
4196
- if (typeof dimensioningObject === 'object' && dimensioningObject !== null) {
4197
- Object.keys(dimensioningObject).forEach((key) => {
4198
- if (pixelRegex.test(dimensioningObject[key])) {
4199
- const matchedParts = dimensioningObject[key].match(pixelRegex);
4200
- normalizedUnitResult[key] = pixelToTWIP(matchedParts[1]);
4201
- }
4202
- else if (cmRegex.test(dimensioningObject[key])) {
4203
- const matchedParts = dimensioningObject[key].match(cmRegex);
4204
- normalizedUnitResult[key] = cmToTWIP(matchedParts[1]);
4205
- }
4206
- else if (inchRegex.test(dimensioningObject[key])) {
4207
- const matchedParts = dimensioningObject[key].match(inchRegex);
4208
- normalizedUnitResult[key] = inchToTWIP(matchedParts[1]);
4209
- }
4210
- else if (dimensioningObject[key]) {
4211
- normalizedUnitResult[key] = dimensioningObject[key];
4212
- }
4213
- else {
4214
- // incase value is something like 0
4215
- normalizedUnitResult[key] = defaultDimensionsProperty[key];
4216
- }
4217
- });
4218
- }
4219
- else {
4220
- // eslint-disable-next-line no-param-reassign
4221
- normalizedUnitResult = null;
4222
- }
4223
- return normalizedUnitResult;
4224
- };
4225
- const normalizeDocumentOptions = (documentOptions) => {
4226
- const normalizedDocumentOptions = { ...documentOptions };
4227
- Object.keys(documentOptions).forEach((key) => {
4228
- // eslint-disable-next-line default-case
4229
- switch (key) {
4230
- case 'pageSize':
4231
- case 'margins':
4232
- normalizedDocumentOptions[key] = normalizeUnits(documentOptions[key], defaultDocumentOptions[key]);
4233
- break;
4234
- case 'fontSize':
4235
- case 'complexScriptFontSize':
4236
- normalizedDocumentOptions[key] = fixupFontSize(documentOptions[key]);
4237
- break;
4238
- }
4239
- });
4240
- return normalizedDocumentOptions;
4241
- };
4242
- // Ref: https://en.wikipedia.org/wiki/Office_Open_XML_file_formats
4243
- // http://officeopenxml.com/anatomyofOOXML.php
4244
- async function addFilesToContainer(zip, htmlString, suppliedDocumentOptions, headerHTMLString, footerHTMLString) {
4245
- debugger;
4246
- const normalizedDocumentOptions = normalizeDocumentOptions(suppliedDocumentOptions);
4247
- const documentOptions = mergeOptions(defaultDocumentOptions, normalizedDocumentOptions);
4248
- if (documentOptions.header && !headerHTMLString) {
4249
- // eslint-disable-next-line no-param-reassign
4250
- headerHTMLString = defaultHTMLString;
4251
- }
4252
- if (documentOptions.footer && !footerHTMLString) {
4253
- // eslint-disable-next-line no-param-reassign
4254
- footerHTMLString = defaultHTMLString;
4255
- }
4256
- const docxDocument = new DocxDocument({ zip, htmlString, ...documentOptions });
4257
- // Conversion to Word XML happens here
4258
- docxDocument.documentXML = await renderDocumentFile(docxDocument);
4259
- debugger;
4260
- zip
4261
- .folder(relsFolderName)
4262
- .file('.rels', create({ encoding: 'UTF-8', standalone: true }, relsXML).toString({ prettyPrint: true }), { createFolders: false });
4263
- zip.folder('docProps').file('core.xml', docxDocument.generateCoreXML(), {
4264
- createFolders: false,
4265
- });
4266
- if (docxDocument.header && headerHTMLString) {
4267
- const vTree = convertHTML(headerHTMLString);
4268
- docxDocument.relationshipFilename = headerFileName;
4269
- const { headerId, headerXML } = await docxDocument.generateHeaderXML(vTree);
4270
- docxDocument.relationshipFilename = documentFileName;
4271
- const fileNameWithExt = `${headerType}${headerId}.xml`;
4272
- const relationshipId = docxDocument.createDocumentRelationships(docxDocument.relationshipFilename, headerType, fileNameWithExt, internalRelationship);
4273
- zip.folder(wordFolder).file(fileNameWithExt, generateDocumentTemplateHeader.toString({ prettyPrint: true }), {
4274
- createFolders: false,
4275
- });
4276
- docxDocument.headerObjects.push({ headerId, relationshipId, type: docxDocument.headerType });
4277
- }
4278
- if (docxDocument.footer && footerHTMLString) {
4279
- const vTree = convertHTML(footerHTMLString);
4280
- docxDocument.relationshipFilename = footerFileName;
4281
- const { footerId, footerXML } = await docxDocument.generateFooterXML(vTree);
4282
- docxDocument.relationshipFilename = documentFileName;
4283
- const fileNameWithExt = `${footerType}${footerId}.xml`;
4284
- const relationshipId = docxDocument.createDocumentRelationships(docxDocument.relationshipFilename, footerType, fileNameWithExt, internalRelationship);
4285
- console.log(footerXML.toString({ prettyPrint: true }));
4286
- if (suppliedDocumentOptions.pageNumber)
4287
- zip.folder(wordFolder).file(fileNameWithExt, generateDocumentTemplateFooter.toString({ prettyPrint: true }), {
4288
- createFolders: false,
4289
- });
4290
- else
4291
- zip.folder(wordFolder).file(fileNameWithExt, generateDocumentTemplateFooterWithoutPaging.toString({ prettyPrint: true }), {
4292
- createFolders: false,
4293
- });
4294
- docxDocument.footerObjects.push({ footerId, relationshipId, type: docxDocument.footerType });
4295
- }
4296
- const themeFileNameWithExt = `${themeFileName}.xml`;
4297
- docxDocument.createDocumentRelationships(docxDocument.relationshipFilename, themeType, `${themeFolder}/${themeFileNameWithExt}`, internalRelationship);
4298
- zip
4299
- .folder(wordFolder)
4300
- .folder(themeFolder)
4301
- .file(themeFileNameWithExt, docxDocument.generateThemeXML(), {
4302
- createFolders: false,
4303
- });
4304
- zip
4305
- .folder(wordFolder)
4306
- .file('document.xml', docxDocument.generateDocumentXML(), { createFolders: false })
4307
- .file('afchunk.mht', getMHTdocument(htmlString), {
4308
- createFolders: false,
4309
- })
4310
- .file('afchunkheader.mht', getMHTdocument(headerHTMLString), {
4311
- createFolders: false,
4312
- })
4313
- .file('afchunkfooter.mht', getMHTdocument(footerHTMLString), {
4314
- createFolders: false,
4315
- })
4316
- .file('fontTable.xml', docxDocument.generateFontTableXML(), { createFolders: false })
4317
- .file('styles.xml', docxDocument.generateStylesXML(), { createFolders: false })
4318
- .file('numbering.xml', docxDocument.generateNumberingXML(), { createFolders: false })
4319
- .file('settings.xml', docxDocument.generateSettingsXML(), { createFolders: false })
4320
- .file('webSettings.xml', docxDocument.generateWebSettingsXML(), { createFolders: false });
4321
- const relationshipXMLs = docxDocument.generateRelsXML();
4322
- if (relationshipXMLs && Array.isArray(relationshipXMLs)) {
4323
- relationshipXMLs.forEach(({ fileName, xmlString }) => {
4324
- console.log(xmlString);
4325
- zip.folder(wordFolder).folder(relsFolderName).file(`${fileName}.xml.rels`, xmlString, {
4326
- createFolders: false,
4327
- });
4328
- });
4329
- }
4330
- if (relationshipXMLs && Array.isArray(relationshipXMLs)) {
4331
- relationshipXMLs.forEach(({ fileName, xmlString }) => {
4332
- zip.folder(wordFolder).folder(relsFolderName).file(`header1.xml.rels`, xmlString, {
4333
- createFolders: false,
4334
- });
4335
- });
4336
- }
4337
- if (relationshipXMLs && Array.isArray(relationshipXMLs)) {
4338
- relationshipXMLs.forEach(({ fileName, xmlString }) => {
4339
- zip.folder(wordFolder).folder(relsFolderName).file(`footer1.xml.rels`, xmlString, {
4340
- createFolders: false,
4341
- });
4342
- });
4343
- }
4344
- zip.file('[Content_Types].xml', docxDocument.generateContentTypesXML(), { createFolders: false });
4345
- return zip;
4346
- }
4347
-
4348
- /* eslint-disable no-useless-escape */
4349
- const minifyHTMLString = (htmlString) => {
4350
- try {
4351
- if (typeof htmlString === 'string' || htmlString instanceof String) {
4352
- const minifiedHTMLString = htmlString
4353
- .replace(/\n/g, ' ')
4354
- .replace(/\r/g, ' ')
4355
- .replace(/\r\n/g, ' ')
4356
- .replace(/[\t]+\</g, '<')
4357
- .replace(/\>[\t ]+\</g, '><')
4358
- .replace(/\>[\t ]+$/g, '>');
4359
- return minifiedHTMLString;
4360
- }
4361
- throw new Error('invalid html string');
4362
- }
4363
- catch (error) {
4364
- return null;
4365
- }
4366
- };
4367
- async function generateContainer(htmlString, headerHTMLString, documentOptions = {}, footerHTMLString) {
4368
- const zip = new JSZip();
4369
- let contentHTML = htmlString;
4370
- let headerHTML = headerHTMLString;
4371
- let footerHTML = footerHTMLString;
4372
- if (htmlString) {
4373
- contentHTML = minifyHTMLString(contentHTML);
4374
- }
4375
- if (headerHTMLString) {
4376
- headerHTML = minifyHTMLString(headerHTML);
4377
- }
4378
- if (footerHTMLString) {
4379
- footerHTML = minifyHTMLString(footerHTML);
4380
- }
4381
- await addFilesToContainer(zip, contentHTML, documentOptions, headerHTML, footerHTML);
4382
- const buffer = await zip.generateAsync({ type: 'arraybuffer' });
4383
- if (Object.prototype.hasOwnProperty.call(global, 'Buffer')) {
4384
- return Buffer.from(new Uint8Array(buffer));
4385
- }
4386
- if (Object.prototype.hasOwnProperty.call(global, 'Blob')) {
4387
- // eslint-disable-next-line no-undef
4388
- return new Blob([buffer], {
4389
- type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
4390
- });
4391
- }
4392
- throw new Error('Add blob support using a polyfill eg https://github.com/bjornstar/blob-polyfill');
4393
- }
4394
-
4395
- class WordDocumentService {
4396
- async generateWordByteFile(model) {
4397
- let documentOptions = {};
4398
- if (model.options.isLandscape)
4399
- documentOptions.orientation = 'landscape';
4400
- documentOptions.pageSize = {
4401
- width: model.options.pageWidth * 15,
4402
- height: model.options.pageHeight * 15,
4403
- };
4404
- documentOptions.margins = {
4405
- top: model.options.top * 15,
4406
- right: model.options.right * 15,
4407
- bottom: model.options.bottom * 15,
4408
- left: model.options.left * 15,
4409
- header: model.options.top * 15 * 2,
4410
- footer: model.options.bottom * 15 * 2,
4411
- gutter: 0,
4412
- };
4413
- documentOptions.footer = true;
4414
- documentOptions.header = true;
4415
- documentOptions.pageNumber = model.options.showPaging;
4416
- documentOptions.table = { row: { cantSplit: true } };
4417
- var fileBuffer = await generateContainer(model.body, model.header, documentOptions, model.footer);
4418
- return fileBuffer;
4419
- }
4420
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: WordDocumentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4421
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: WordDocumentService, providedIn: 'root' }); }
4422
- }
4423
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: WordDocumentService, decorators: [{
4424
- type: Injectable,
4425
- args: [{
4426
- providedIn: 'root',
4427
- }]
4428
- }] });
4429
-
4430
- class LanguageService {
4431
- constructor(http) {
4432
- this.http = http;
4433
- this.apiUrl = '/api/Language/';
4434
- }
4435
- getLanguages() {
4436
- return this.http.get(this.apiUrl + 'GetAll', null, null);
4437
- }
4438
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LanguageService, deps: [{ token: RequestHandlerService }], target: i0.ɵɵFactoryTarget.Injectable }); }
4439
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LanguageService, providedIn: 'root' }); }
4440
- }
4441
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LanguageService, decorators: [{
4442
- type: Injectable,
4443
- args: [{
4444
- providedIn: 'root',
4445
- }]
4446
- }], ctorParameters: () => [{ type: RequestHandlerService }] });
4447
-
4448
- class SpeechRecognitionService {
4449
- constructor(zone, utilityService) {
4450
- this.zone = zone;
4451
- this.utilityService = utilityService;
4452
- this.isListening = false;
4453
- this.isSupported = false;
4454
- this.language = 'en-US';
4455
- const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
4456
- if (SpeechRecognition) {
4457
- this.recognition = new SpeechRecognition();
4458
- this.recognition.continuous = true;
4459
- this.recognition.interimResults = false;
4460
- this.recognition.maxAlternatives = 1;
4461
- this.isSupported = true;
4462
- }
4463
- }
4464
- startListening(language = this.language) {
4465
- if (!this.isSupported) {
4466
- return throwError(() => new Error('Web Speech API is not supported in this browser.'));
4467
- }
4468
- return new Observable(observer => {
4469
- this.isListening = true;
4470
- this.recognition.lang = language;
4471
- this.recognition.start();
4472
- this.recognition.onresult = (event) => {
4473
- this.zone.run(() => {
4474
- const transcript = event.results[event.results.length - 1][0].transcript;
4475
- observer.next(transcript);
4476
- });
4477
- };
4478
- this.recognition.onspeechend = () => {
4479
- this.stopListening();
4480
- };
4481
- this.recognition.onerror = (event) => {
4482
- this.zone.run(() => {
4483
- if (event.error === 'not-allowed') {
4484
- this.utilityService.notifyErrorMessage(this.utilityService.getResourceValue("MicAccessDenied"));
4485
- observer.error('Microphone access denied by the user.');
4486
- }
4487
- else {
4488
- observer.error(event.error);
4489
- }
4490
- });
4491
- };
4492
- this.recognition.onend = () => {
4493
- this.zone.run(() => {
4494
- if (this.isListening) {
4495
- this.recognition.start(); // Automatically restart
4496
- }
4497
- else {
4498
- observer.complete();
4499
- }
4500
- });
4501
- };
4502
- });
4503
- }
4504
- stopListening() {
4505
- if (this.isSupported) {
4506
- this.isListening = false;
4507
- this.recognition.stop();
4508
- }
4509
- }
4510
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpeechRecognitionService, deps: [{ token: i0.NgZone }, { token: UtilityService }], target: i0.ɵɵFactoryTarget.Injectable }); }
4511
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpeechRecognitionService, providedIn: 'root' }); }
4512
- }
4513
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpeechRecognitionService, decorators: [{
4514
- type: Injectable,
4515
- args: [{
4516
- providedIn: 'root'
4517
- }]
4518
- }], ctorParameters: () => [{ type: i0.NgZone }, { type: UtilityService }] });
4519
-
4520
- class FileLoaderService {
4521
- // environment:any;
4522
- constructor(translate, http) {
4523
- this.translate = translate;
4524
- this.http = http;
4525
- this.availableLanguages = ['en', 'ar']; // Add more languages as needed
4526
- this.translate.addLangs(this.availableLanguages);
4527
- }
4528
- loadEnvironment() {
4529
- return new Promise((resolve, reject) => {
4530
- const script = document.createElement('script');
4531
- script.src = '/assets/config/environment.js';
4532
- script.onload = () => {
4533
- if (window.Environment) {
4534
- Object.assign(environment, window.Environment);
4535
- resolve();
4536
- }
4537
- else {
4538
- reject('Environment variables not found.');
4539
- }
4540
- };
4541
- script.onerror = () => reject('Failed to load environment.js');
4542
- document.head.appendChild(script);
4543
- });
4544
- }
4545
- async preloadTranslations() {
4546
- try {
4547
- const requests = this.availableLanguages.map(async (lang) => {
4548
- const translations = await lastValueFrom(this.http.get(`/assets/i18n/${lang}.json`));
4549
- this.translate.setTranslation(lang, translations, true);
4550
- });
4551
- await Promise.all(requests);
4552
- this.translate.use('en'); // Set default language manually
4553
- }
4554
- catch (error) {
4555
- console.error('Error preloading translations:', error);
4556
- }
4557
- }
4558
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileLoaderService, deps: [{ token: BBSFTranslateService }, { token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
4559
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileLoaderService, providedIn: 'root' }); }
4560
- }
4561
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileLoaderService, decorators: [{
4562
- type: Injectable,
4563
- args: [{
4564
- providedIn: 'root',
4565
- }]
4566
- }], ctorParameters: () => [{ type: BBSFTranslateService }, { type: i1.HttpClient }] });
4567
-
4568
- class AuthService {
4569
- static { this.user = null; }
4570
- get user() {
4571
- if (!this._user) {
4572
- this._user = this.getUserManager();
4573
- }
4574
- return this._user;
4575
- }
4576
- static { this.UserClaims = null; }
4577
- //refresh
4578
- static { this.timers = []; }
4579
- static { this.seconds = 0; }
4580
- constructor(injector, http, environmentService, translateService, router, cookieService, utilityService) {
4581
- this.injector = injector;
4582
- this.http = http;
4583
- this.environmentService = environmentService;
4584
- this.translateService = translateService;
4585
- this.router = router;
4586
- this.cookieService = cookieService;
4587
- this.utilityService = utilityService;
4588
- this.redirectUrl = '';
4589
- this.jwtHelper = new JwtHelperService();
4590
- this.isAuthenticatedSubject = new BehaviorSubject(this.hasToken());
4591
- this.isAuthenticate$ = this.isAuthenticatedSubject.asObservable();
4592
- }
4593
- get TOKEN_KEY() {
4594
- if (!this._TOKEN_KEY) {
4595
- this._TOKEN_KEY = this.environmentService.getCookieName();
4596
- }
4597
- return this._TOKEN_KEY;
4598
- }
4599
- hasToken() {
4600
- const token = this.cookieService.get(this.TOKEN_KEY);
4601
- return token && !this.jwtHelper.isTokenExpired(token);
4602
- }
4603
- getUserManager() {
4604
- const token = this.cookieService.get(this.TOKEN_KEY);
4605
- if (token) {
4606
- if (!this.jwtHelper.isTokenExpired(token))
4607
- this.handleAccessTokenWithoutLanguage(token);
4608
- else
4609
- this.cookieService.delete(this.TOKEN_KEY, '/');
4610
- }
4611
- else {
4612
- AuthService.timers.map(t => clearInterval(t));
4613
- AuthService.timers = [];
4614
- AuthService.user = null;
4615
- this._user = null;
4616
- }
4617
- return AuthService.user;
4618
- }
4619
- getUser() {
4620
- this._user = AuthService.user;
4621
- }
4622
- storUser(User) {
4623
- AuthService.user = this._user = this.user;
4624
- }
4625
- getCurrentUser() {
4626
- return AuthService.user;
4627
- }
4628
- isAuthenticated() {
4629
- AuthService.user = this.user;
4630
- return AuthService.user != null && !this.jwtHelper.isTokenExpired(AuthService.user.access_token);
4631
- }
4632
- isUserInRole(allowedPermission) {
4633
- let selectedPermissionSetID = Number.parseInt(AuthService.user.profile['selectedpermissionsetid']);
4634
- return allowedPermission.includes(selectedPermissionSetID);
4635
- }
4636
- isUserPermissionSetsInRoles(allowedPermission) {
4637
- const permissionSetSIDString = AuthService.user.profile['permissionSetSID'];
4638
- if (!permissionSetSIDString) {
4639
- return false;
4640
- }
4641
- // Split comma-separated string and convert to numbers
4642
- const userPermissionSets = permissionSetSIDString
4643
- .split(',')
4644
- .map(id => Number.parseInt(id.trim()))
4645
- .filter(id => !isNaN(id)); // Filter out invalid numbers
4646
- // Check if any user permission set is in the allowed permissions
4647
- return userPermissionSets.some(permissionSetID => allowedPermission.includes(permissionSetID));
4648
- }
4649
- authorizationHeaderValue() {
4650
- return AuthService.user
4651
- ? `${AuthService.user.token_type} ${AuthService.user.access_token}`
4652
- : '';
4653
- }
4654
- name() {
4655
- return AuthService.user != null ? AuthService.user.profile.given_name : '';
4656
- }
4657
- setUrl(url) {
4658
- localStorage.setItem('redirectUrl', url);
4659
- }
4660
- getUrl() {
4661
- return localStorage.getItem('redirectUrl') ?? "/";
1143
+ getUrl() {
1144
+ return localStorage.getItem('redirectUrl') ?? "/";
4662
1145
  }
4663
1146
  signOut() {
4664
1147
  let isAuthenticated = this.isAuthenticated();
@@ -4803,21 +1286,47 @@ class AuthService {
4803
1286
  window.location.href = logoutUrl;
4804
1287
  return;
4805
1288
  }
4806
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthService, deps: [{ token: i0.Injector }, { token: i1.HttpClient }, { token: EnvironmentService }, { token: BBSFTranslateService }, { token: i1$1.Router }, { token: i4$1.CookieService }, { token: UtilityService }], target: i0.ɵɵFactoryTarget.Injectable }); }
4807
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthService, providedIn: 'root' }); }
1289
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AuthService, deps: [{ token: i0.Injector }, { token: i1.HttpClient }, { token: EnvironmentService }, { token: BBSFTranslateService }, { token: i1$1.Router }, { token: i4$1.CookieService }, { token: UtilityService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1290
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AuthService, providedIn: 'root' }); }
4808
1291
  }
4809
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthService, decorators: [{
1292
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AuthService, decorators: [{
4810
1293
  type: Injectable,
4811
1294
  args: [{
4812
1295
  providedIn: 'root',
4813
1296
  }]
4814
1297
  }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.HttpClient }, { type: EnvironmentService }, { type: BBSFTranslateService }, { type: i1$1.Router }, { type: i4$1.CookieService }, { type: UtilityService }] });
4815
1298
 
1299
+ /**
1300
+ * BBSFUtilitiesModule
1301
+ *
1302
+ * This module provides full backward compatibility by including ALL services and modules
1303
+ * from the original version. Simply import this module to get all functionality.
1304
+ *
1305
+ * For new applications, consider using modular imports via secondary entry points:
1306
+ * - @bnsights/bbsf-utilities/auth - Authentication services
1307
+ * - @bnsights/bbsf-utilities/http - HTTP request handling
1308
+ * - @bnsights/bbsf-utilities/translate - Translation services
1309
+ * - @bnsights/bbsf-utilities/ui - UI services (BlockUI, Toastr, etc.)
1310
+ *
1311
+ * @example
1312
+ * // Backward compatible usage (imports everything):
1313
+ * import { BBSFUtilitiesModule } from '@bnsights/bbsf-utilities';
1314
+ *
1315
+ * @NgModule({
1316
+ * imports: [BBSFUtilitiesModule]
1317
+ * })
1318
+ * export class AppModule { }
1319
+ */
4816
1320
  class BBSFUtilitiesModule {
4817
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BBSFUtilitiesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4818
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: BBSFUtilitiesModule, imports: [CommonModule,
4819
- RouterModule, i1$2.BlockUIModule, i2.ToastrModule] }); }
4820
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BBSFUtilitiesModule, providers: [
1321
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BBSFUtilitiesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1322
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.15", ngImport: i0, type: BBSFUtilitiesModule, imports: [CommonModule,
1323
+ RouterModule, i1$2.BlockUIModule], exports: [
1324
+ // Re-export modules for backward compatibility
1325
+ CommonModule,
1326
+ RouterModule,
1327
+ BlockUIModule] }); }
1328
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BBSFUtilitiesModule, providers: [
1329
+ // All services for backward compatibility
4821
1330
  UtilityService,
4822
1331
  EnvironmentService,
4823
1332
  AuthService,
@@ -4830,13 +1339,17 @@ class BBSFUtilitiesModule {
4830
1339
  ConfigurationService,
4831
1340
  CookieService,
4832
1341
  LanguageService,
4833
- SpeechRecognitionService
1342
+ SpeechRecognitionService,
1343
+ provideToastr()
4834
1344
  ], imports: [CommonModule,
4835
1345
  RouterModule,
4836
- BlockUIModule.forRoot(),
4837
- ToastrModule.forRoot()] }); }
1346
+ BlockUIModule.forRoot(),
1347
+ // Re-export modules for backward compatibility
1348
+ CommonModule,
1349
+ RouterModule,
1350
+ BlockUIModule] }); }
4838
1351
  }
4839
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BBSFUtilitiesModule, decorators: [{
1352
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BBSFUtilitiesModule, decorators: [{
4840
1353
  type: NgModule,
4841
1354
  args: [{
4842
1355
  declarations: [],
@@ -4844,10 +1357,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4844
1357
  CommonModule,
4845
1358
  RouterModule,
4846
1359
  BlockUIModule.forRoot(),
4847
- ToastrModule.forRoot(),
4848
1360
  ],
4849
- exports: [],
1361
+ exports: [
1362
+ // Re-export modules for backward compatibility
1363
+ CommonModule,
1364
+ RouterModule,
1365
+ BlockUIModule,
1366
+ ],
4850
1367
  providers: [
1368
+ // All services for backward compatibility
4851
1369
  UtilityService,
4852
1370
  EnvironmentService,
4853
1371
  AuthService,
@@ -4860,20 +1378,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4860
1378
  ConfigurationService,
4861
1379
  CookieService,
4862
1380
  LanguageService,
4863
- SpeechRecognitionService
1381
+ SpeechRecognitionService,
1382
+ provideToastr()
4864
1383
  ]
4865
1384
  }]
4866
1385
  }] });
4867
1386
 
4868
1387
  /*
4869
1388
  * Public API Surface of @bnsights/bbsf-utilities
1389
+ *
1390
+ * This is the CORE entry point with minimal dependencies.
1391
+ *
1392
+ * For feature-specific services, use secondary entry points:
1393
+ * - @bnsights/bbsf-utilities/auth - Authentication services
1394
+ * - @bnsights/bbsf-utilities/word - Word document generation
1395
+ * - @bnsights/bbsf-utilities/translate - Translation services
1396
+ * - @bnsights/bbsf-utilities/ui - UI services (BlockUI, Toastr, etc.)
1397
+ * - @bnsights/bbsf-utilities/http - HTTP request handling
4870
1398
  */
4871
- //Module
4872
- //#endregion
1399
+ //Module (Note: for backward compatibility - contains ALL providers)
4873
1400
 
4874
1401
  /**
4875
1402
  * Generated bundle index. Do not edit.
4876
1403
  */
4877
1404
 
4878
- export { AppearanceConfigurationService, AuthService, AuthenticationModes, BBSFTranslateService, BBSFUtilitiesModule, ConfigurationService, ControlValidationService, DocumentOptionsModel, EnvironmentService, FileLoaderService, LanguageDTO, LanguageService, MasterLayoutService, RequestHandlerService, RequestOptionsModel, SpeechRecognitionService, StylesBundleService, TranslationResolverService, UtilityService, WordDocumentModel, WordDocumentService, environment };
1405
+ export { AppearanceConfigurationService, AreaModel, AuthService, AuthenticationModes, BBSFTranslateService, BBSFUtilitiesModule, ConfigurationService, ControlValidationService, EnvironmentService, ErrorModel, FileLoaderService, LanguageDTO, LanguageService, MasterLayoutService, RequestHandlerService, RequestOptionsModel, SpeechRecognitionService, StylesBundleService, TranslationResolverService, User, UtilityService, environment };
4879
1406
  //# sourceMappingURL=bnsights-bbsf-utilities.mjs.map