@sd-angular/core 19.0.0-beta.81 → 19.0.0-beta.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/sd-angular-core-components-tab-router.mjs +86 -33
- package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-docx.mjs +196 -69
- package/fesm2022/sd-angular-core-services-docx.mjs.map +1 -1
- package/package.json +42 -42
- package/sd-angular-core-19.0.0-beta.83.tgz +0 -0
- package/services/docx/src/lib/docx.service.d.ts +4 -2
- package/services/docx/src/lib/pandoc-core.d.ts +11 -0
- package/sd-angular-core-19.0.0-beta.81.tgz +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable, Pipe, Input, ChangeDetectionStrategy, Component, HostListener, ViewChild, signal, inject, Injector, NgModuleFactory, createNgModule } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/router';
|
|
4
|
-
import { Router, ActivatedRoute, RouterEvent, NavigationEnd } from '@angular/router';
|
|
4
|
+
import { Router, ActivatedRoute, RouterEvent, RoutesRecognized, NavigationEnd } from '@angular/router';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
6
6
|
import { CommonModule } from '@angular/common';
|
|
7
7
|
import * as i3 from '@angular/material/icon';
|
|
@@ -301,16 +301,37 @@ class SdTabRouterOutletComponent {
|
|
|
301
301
|
#injector = inject(Injector);
|
|
302
302
|
#tabRouterService = inject(SdTabRouterService);
|
|
303
303
|
#sdNotifyService = inject(SdNotifyService);
|
|
304
|
+
// Inject để đảm bảo SdTabDecoratorService được khởi tạo (nó register BehaviorSubject
|
|
305
|
+
// tĩnh để @SdTab decorator có thể truy cập SdTabRouterService). Không dùng trực tiếp ở đây.
|
|
304
306
|
#tabDecoratorService = inject(SdTabDecoratorService);
|
|
305
307
|
#rootRoute;
|
|
306
308
|
#subscription = new Subscription();
|
|
309
|
+
// State của navigation hiện tại (replaceTab, switchTab, ...) được capture ở RoutesRecognized
|
|
310
|
+
// và dùng lại ở NavigationEnd. Lý do: tại NavigationEnd, getCurrentNavigation() đã trả về null,
|
|
311
|
+
// còn lastSuccessfulNavigation và window.history.state không đáng tin cậy với mọi case.
|
|
312
|
+
#pendingNavigationState = {};
|
|
307
313
|
constructor() {
|
|
308
314
|
this.#subscription.add(this.#router.events
|
|
309
|
-
.pipe(
|
|
315
|
+
.pipe(
|
|
316
|
+
// Một số event của Angular bọc trong wrapper có .routerEvent → unwrap về RouterEvent gốc.
|
|
317
|
+
map((event) => (event instanceof RouterEvent ? event : event.routerEvent)),
|
|
318
|
+
// Hybrid: cần CẢ HAI event vì mỗi event chứa data khác nhau ở thời điểm khác nhau.
|
|
319
|
+
// - RoutesRecognized: navigation đang in-flight → getCurrentNavigation().extras.state đọc được
|
|
320
|
+
// - NavigationEnd: navigation hoàn tất → routerState.root đã update với route mới (cần cho lazy routes)
|
|
321
|
+
filter(event => event instanceof RoutesRecognized || event instanceof NavigationEnd))
|
|
310
322
|
.subscribe(async (event) => {
|
|
323
|
+
if (event instanceof RoutesRecognized) {
|
|
324
|
+
// Capture state ngay lúc nav còn in-flight. Đây là điểm duy nhất chắc chắn
|
|
325
|
+
// getCurrentNavigation() trả về Navigation object với extras.state nguyên vẹn.
|
|
326
|
+
this.#pendingNavigationState = this.#router.getCurrentNavigation()?.extras?.state ?? {};
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
// NavigationEnd: dùng activatedRoute.snapshot và routerState.root MỚI nhất
|
|
330
|
+
// (chứa route component đã được activate, cả lazy lẫn standalone routes).
|
|
311
331
|
const route = this.#getActivatedRouteSnapshot(this.#activatedRoute.snapshot);
|
|
312
332
|
this.#rootRoute = this.#router.routerState.root;
|
|
313
|
-
await this.#activeRoute(event.urlAfterRedirects || event.url, route);
|
|
333
|
+
await this.#activeRoute(event.urlAfterRedirects || event.url, route, this.#pendingNavigationState);
|
|
334
|
+
this.#pendingNavigationState = {};
|
|
314
335
|
}));
|
|
315
336
|
this.#subscription.add(this.#tabRouterService.actions.subscribe((event) => {
|
|
316
337
|
if (event?.type === 'close') {
|
|
@@ -344,7 +365,7 @@ class SdTabRouterOutletComponent {
|
|
|
344
365
|
this.tabRouterNav?.checkUI();
|
|
345
366
|
}
|
|
346
367
|
};
|
|
347
|
-
#activeRoute = async (fullUrl, route) => {
|
|
368
|
+
#activeRoute = async (fullUrl, route, state = {}) => {
|
|
348
369
|
if (!route?.component)
|
|
349
370
|
return;
|
|
350
371
|
const component = route.component;
|
|
@@ -352,48 +373,58 @@ class SdTabRouterOutletComponent {
|
|
|
352
373
|
const params = { ...(route.params || {}) };
|
|
353
374
|
const data = { ...(route.data || {}) };
|
|
354
375
|
const [url] = fullUrl.split('?');
|
|
376
|
+
// Tab identity = hash(url + queryParams). Cùng key = cùng tab, không tạo lại.
|
|
355
377
|
const key = SdUtilities.hash({ url, queryParams });
|
|
356
378
|
let existedIndex = -1;
|
|
357
379
|
let activatedIndex = -1;
|
|
358
380
|
const currentTabs = this.tabs();
|
|
359
|
-
|
|
381
|
+
// QUAN TRỌNG: scan READ-ONLY, KHÔNG mutate tab.isActive trong loop này.
|
|
382
|
+
//
|
|
383
|
+
// Lý do: NavigationEnd có thể fire nhiều lần cho 1 user-action (do nested outlets,
|
|
384
|
+
// redirect, hoặc Angular internal). Vì #activeRoute là async (await getBestInjector),
|
|
385
|
+
// 2 invocations có thể chạy concurrent và interleave với nhau.
|
|
386
|
+
//
|
|
387
|
+
// Nếu mutate tab.isActive = false ở đây, call thứ 2 sẽ thấy isActive đã bị call 1
|
|
388
|
+
// set false rồi → không tìm thấy active tab → activatedIndex stay -1 → splice bỏ qua
|
|
389
|
+
// → tab cũ không bị remove → xuất hiện duplicate tabs.
|
|
390
|
+
//
|
|
391
|
+
// Cách fix: chỉ ĐỌC isActive, sau đó dùng .map() ở dưới để tạo tab objects mới qua spread.
|
|
392
|
+
for (let i = 0; i < currentTabs.length; i++) {
|
|
393
|
+
const tab = currentTabs[i];
|
|
360
394
|
if (tab.key === key) {
|
|
361
|
-
|
|
362
|
-
existedIndex = index;
|
|
395
|
+
existedIndex = i;
|
|
363
396
|
}
|
|
364
|
-
else {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
this.#tabRouterService.pushEvent(tab, SdTabDeactivated);
|
|
368
|
-
}
|
|
369
|
-
tab.isActive = false;
|
|
397
|
+
else if (tab.isActive) {
|
|
398
|
+
activatedIndex = i;
|
|
399
|
+
this.#tabRouterService.pushEvent(tab, SdTabDeactivated);
|
|
370
400
|
}
|
|
371
|
-
}
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
//
|
|
401
|
+
}
|
|
402
|
+
const replaceTab = state['replaceTab'];
|
|
403
|
+
// Resolve injector phù hợp với route. Cần xử lý 3 trường hợp:
|
|
404
|
+
// - Standalone route (Angular đã set _injector trên routeConfig sau khi activate)
|
|
405
|
+
// - NgModule lazy load (cần createNgModule từ class)
|
|
406
|
+
// - Fallback: root injector
|
|
375
407
|
const getBestInjector = async (snapshot) => {
|
|
376
|
-
//
|
|
408
|
+
// Standalone route: Angular tự lưu environment injector trên routeConfig._injector
|
|
377
409
|
const routeInjector = snapshot._resolvedGui || snapshot.routeConfig?._injector;
|
|
378
410
|
if (routeInjector)
|
|
379
411
|
return routeInjector;
|
|
380
|
-
//
|
|
412
|
+
// NgModule lazy: phải gọi lại loadChildren() để lấy module class rồi createNgModule
|
|
381
413
|
const loadChildren = snapshot.parent?.routeConfig?.loadChildren;
|
|
382
414
|
if (typeof loadChildren === 'function') {
|
|
383
415
|
let loaded = await loadChildren();
|
|
384
|
-
// Unwrap Observable
|
|
385
416
|
if (isObservable(loaded)) {
|
|
386
417
|
loaded = await lastValueFrom(loaded);
|
|
387
418
|
}
|
|
388
|
-
//
|
|
419
|
+
// ES module có thể export default
|
|
389
420
|
if (loaded && typeof loaded === 'object' && 'default' in loaded) {
|
|
390
421
|
loaded = loaded.default;
|
|
391
422
|
}
|
|
392
|
-
//
|
|
423
|
+
// Angular cũ: NgModuleFactory
|
|
393
424
|
if (loaded instanceof NgModuleFactory) {
|
|
394
425
|
return loaded.create(this.#injector).injector;
|
|
395
426
|
}
|
|
396
|
-
//
|
|
427
|
+
// Angular mới: NgModule class. Bọc try/catch vì createNgModule throw nếu không phải NgModule.
|
|
397
428
|
if (typeof loaded === 'function' && !Array.isArray(loaded)) {
|
|
398
429
|
try {
|
|
399
430
|
return createNgModule(loaded, this.#injector).injector;
|
|
@@ -418,21 +449,37 @@ class SdTabRouterOutletComponent {
|
|
|
418
449
|
data,
|
|
419
450
|
tabInfoChanges: new Subject(),
|
|
420
451
|
};
|
|
452
|
+
// Tạo updatedTabs qua spread thay vì mutate (xem lý do ở for loop phía trên).
|
|
453
|
+
// Với tab có isActive không đổi: giữ nguyên reference (tránh trigger ngComponentOutlet
|
|
454
|
+
// re-evaluate không cần thiết). Với tab cần đổi isActive: tạo object mới qua spread,
|
|
455
|
+
// các nested fields (component, injector) vẫn giữ same reference nên component không bị recreate.
|
|
456
|
+
let updatedTabs = currentTabs.map(tab => {
|
|
457
|
+
if (tab.key === key)
|
|
458
|
+
return tab.isActive ? tab : { ...tab, isActive: true };
|
|
459
|
+
return tab.isActive ? { ...tab, isActive: false } : tab;
|
|
460
|
+
});
|
|
461
|
+
// replaceTab: thay vì mở tab mới song song, xoá tab đang active rồi mở tab mới ở cuối.
|
|
462
|
+
// Use case: từ tab "chi tiết" bấm "chỉnh sửa" với replaceTab → tab chi tiết bị xoá,
|
|
463
|
+
// tab chỉnh sửa thay thế (giữ số tab không tăng).
|
|
464
|
+
if (replaceTab && activatedIndex >= 0) {
|
|
465
|
+
updatedTabs = updatedTabs.filter((_, i) => i !== activatedIndex);
|
|
466
|
+
}
|
|
421
467
|
if (existedIndex >= 0) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
468
|
+
// Tab đã tồn tại (cùng url + queryParams) → CHỈ activate, KHÔNG thay tab object.
|
|
469
|
+
// Lý do: thay tab object = đổi reference của tab.injector → ngComponentOutlet recreate
|
|
470
|
+
// component → tab bị "reload" mỗi khi click lại hoặc navigate cùng URL.
|
|
471
|
+
//
|
|
472
|
+
// splice phía trên có thể đã shift index nếu activatedIndex < existedIndex.
|
|
473
|
+
const idx = replaceTab && activatedIndex >= 0 && activatedIndex < existedIndex
|
|
474
|
+
? existedIndex - 1
|
|
475
|
+
: existedIndex;
|
|
476
|
+
this.#tabRouterService.setCurrentTab(updatedTabs[idx]);
|
|
477
|
+
this.#tabRouterService.pushEvent(updatedTabs[idx], SdTabActivated);
|
|
428
478
|
this.tabs.set(updatedTabs);
|
|
429
479
|
}
|
|
430
480
|
else {
|
|
431
|
-
|
|
481
|
+
// Tab chưa tồn tại → thêm mới ở cuối.
|
|
432
482
|
this.#tabRouterService.setCurrentTab(newTab);
|
|
433
|
-
if (activatedIndex >= 0 && replaceTab) {
|
|
434
|
-
updatedTabs.splice(activatedIndex, 1);
|
|
435
|
-
}
|
|
436
483
|
this.tabs.set([...updatedTabs, newTab]);
|
|
437
484
|
if (this.tabs().length > 30) {
|
|
438
485
|
this.#sdNotifyService.warning('Bạn đã mở quá nhiều tab.');
|
|
@@ -440,12 +487,15 @@ class SdTabRouterOutletComponent {
|
|
|
440
487
|
}
|
|
441
488
|
this.tabRouterNav?.checkUI();
|
|
442
489
|
};
|
|
490
|
+
// Lần xuống deepest firstChild để lấy snapshot của route lá (route thực sự render component).
|
|
443
491
|
#getActivatedRouteSnapshot = (snapshot) => {
|
|
444
492
|
let node = snapshot;
|
|
445
493
|
while (node.firstChild)
|
|
446
494
|
node = node.firstChild;
|
|
447
495
|
return node;
|
|
448
496
|
};
|
|
497
|
+
// DFS tìm ActivatedRoute (không phải snapshot) trong tree theo component class.
|
|
498
|
+
// Cần ActivatedRoute thật vì SdOutletInjector sẽ inject nó vào component qua DI.
|
|
449
499
|
#getActivatedRoute = (activatedRoute, component) => {
|
|
450
500
|
if (activatedRoute.component === component)
|
|
451
501
|
return activatedRoute;
|
|
@@ -466,6 +516,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
466
516
|
type: ViewChild,
|
|
467
517
|
args: ['tabRouterNav']
|
|
468
518
|
}] } });
|
|
519
|
+
// Custom Injector cho từng tab: override ActivatedRoute thành route của TAB ĐÓ
|
|
520
|
+
// (không phải route hiện tại của router). Nếu không override, mọi tab sẽ inject ActivatedRoute
|
|
521
|
+
// của route đang active → component cũ trong tab inactive nhận data sai khi user navigate.
|
|
469
522
|
class SdOutletInjector {
|
|
470
523
|
route;
|
|
471
524
|
parentInjector;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-components-tab-router.mjs","sources":["../../../projects/sd-angular/components/tab-router/src/events/tab-router.event.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-router.service.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-decorator.service.ts","../../../projects/sd-angular/components/tab-router/src/pipes/tab-info.pipe.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.html","../../../projects/sd-angular/components/tab-router/src/decorators/tab.decorator.ts","../../../projects/sd-angular/components/tab-router/sd-angular-core-components-tab-router.ts"],"sourcesContent":["import { SdTab } from '../models/tab-router.model';\n\nexport class SdTabBase {\n #tab: SdTab | undefined;\n\n constructor(tab: SdTab | undefined) {\n this.#tab = tab;\n }\n\n get tab(): SdTab | undefined {\n return this.#tab;\n }\n}\n\nexport class SdTabActivated extends SdTabBase {}\n\nexport class SdTabDeactivated extends SdTabBase {}\n\nexport declare type SdTabEvent = SdTabActivated | SdTabDeactivated;\n","import { Injectable, Type } from '@angular/core';\r\nimport { BehaviorSubject } from 'rxjs';\r\nimport { SdTabAction } from '../actions/tab-router.action';\r\nimport { SdTabComponentBuilder } from '../decorators/tab.decorator';\r\nimport { SdTabBase, SdTabEvent } from '../events/tab-router.event';\r\nimport { SdTab } from '../models/tab-router.model';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdTabRouterService {\r\n events = new BehaviorSubject<SdTabEvent>(new SdTabBase(undefined));\r\n actions = new BehaviorSubject<SdTabAction | undefined>(undefined);\r\n builders = new BehaviorSubject<SdTabComponentBuilder[]>([]);\r\n currentTabChanges = new BehaviorSubject<SdTab | undefined>(undefined);\r\n newTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n updateTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n #currentTab: SdTab | undefined = undefined;\r\n #componentBuilders: SdTabComponentBuilder[] = [];\r\n constructor() {}\r\n\r\n addBuilder = (builder: SdTabComponentBuilder) => {\r\n if (!this.#componentBuilders.some(e => e.component === builder.component)) {\r\n this.#componentBuilders.push(builder);\r\n this.builders.next(this.#componentBuilders);\r\n }\r\n };\r\n\r\n get currentTab() {\r\n return this.#currentTab;\r\n }\r\n\r\n get currentKey() {\r\n return this.#currentTab?.key || null;\r\n }\r\n\r\n // select = (tabOrKey: string | SdTab): void => {\r\n // const tab = this.#tabs.find(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key === tabOrKey;\r\n // }\r\n // return e.key === tabOrKey?.key;\r\n // });\r\n // if (tab) {\r\n // this.#currentTab = tab;\r\n // }\r\n // }\r\n\r\n // add = (tab: SdTab): void => {\r\n // if (!tab.key) {\r\n // this.notifyService.notify.warning('Tab key is required');\r\n // }\r\n // if (!tab.component) {\r\n // this.notifyService.notify.warning('Tab component is required');\r\n // }\r\n // const existedTab = this.#tabs.find(e => e.key === tab.key);\r\n // if (!existedTab) {\r\n // this.#tabs.push(tab);\r\n // this.select(tab);\r\n // } else {\r\n // this.select(existedTab);\r\n // }\r\n // }\r\n\r\n // remove = (tabOrKey: string | SdTab): void => {\r\n // this.#tabs = this.#tabs.filter(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key !== tabOrKey;\r\n // }\r\n // return e.key !== tabOrKey?.key;\r\n // });\r\n // }\r\n\r\n setCurrentTab = (tab: SdTab): void => {\r\n this.#currentTab = tab;\r\n this.currentTabChanges.next(tab);\r\n };\r\n\r\n pushEvent = (tab: SdTab, Event: Type<SdTabEvent>) => {\r\n this.events.next(new Event(tab));\r\n };\r\n\r\n setOptions = () => {};\r\n\r\n close = (tab?: SdTab) => {\r\n tab = tab || this.#currentTab;\r\n if (tab) {\r\n this.actions.next({\r\n type: 'close',\r\n tab,\r\n });\r\n }\r\n };\r\n\r\n // Gọi hàm này để thực hiện update tab\r\n updateTab = (tab: SdTab) => {};\r\n}\r\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { SdTabRouterService } from './tab-router.service';\n@Injectable({\n providedIn: 'root',\n})\nexport class SdTabDecoratorService {\n static tabRouterService = new BehaviorSubject<SdTabRouterService | undefined>(undefined);\n constructor(tabRouterService: SdTabRouterService) {\n SdTabDecoratorService.tabRouterService.next(tabRouterService);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { SdTab, SdTabInfo } from '../models/tab-router.model';\nimport { SdTabRouterService } from '../services/tab-router.service';\n@Pipe({\n name: 'sdTabInfo',\n standalone: true,\n})\nexport class SdTabInfoPipe implements PipeTransform {\n constructor(private tabRouterService: SdTabRouterService) {}\n transform(tabInfo: SdTabInfo | undefined | null, tab: SdTab): SdTabInfo {\n if (tabInfo) {\n return tabInfo;\n }\n const builders = this.tabRouterService.builders.getValue();\n const builder = builders.find(e => e.component === tab.component);\n if (builder) {\n const { url, params, queryParams, data } = tab;\n return {\n name: typeof builder.name === 'function' ? builder.name({ url, params, queryParams, data }) : builder.name,\n icon: typeof builder.icon === 'function' ? builder.icon({ url, params, queryParams }) : builder.icon,\n tooltip: typeof builder.tooltip === 'function' ? builder.tooltip({ url, params, queryParams }) : builder.tooltip,\n color: typeof builder.color === 'function' ? builder.color({ url, params, queryParams }) : builder.color,\n };\n }\n return {\n name: tab.url,\n icon: undefined,\n };\n }\n}\n","import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';\r\nimport { Subscription } from 'rxjs';\r\nimport { debounceTime, startWith } from 'rxjs/operators';\r\n\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { SdBadge } from '@sd-angular/core/components/badge';\r\nimport { SdTab, SdTabInfo } from '../../models';\r\nimport { SdTabRouterService } from '../../services/tab-router.service';\r\nimport { Router } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { SdTabInfoPipe } from '../../pipes/tab-info.pipe';\r\n\r\n@Component({\r\n selector: 'sd-tab-router-item',\r\n templateUrl: './tab-router-item.component.html',\r\n styleUrls: ['./tab-router-item.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n standalone: true,\r\n imports: [CommonModule, MatIconModule, SdBadge, SdTabInfoPipe],\r\n})\r\nexport class SdTabRouterItemComponent implements OnInit, OnDestroy {\r\n @Input({ required: true }) tab!: SdTab;\r\n\r\n #subsctiption: Subscription = new Subscription();\r\n tabInfo?: SdTabInfo;\r\n constructor(\r\n private cdRef: ChangeDetectorRef,\r\n private tabRouterService: SdTabRouterService,\r\n private router: Router\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n this.#subsctiption.add(\r\n this.tabRouterService.events.pipe(debounceTime(100)).subscribe(() => {\r\n this.cdRef.markForCheck();\r\n })\r\n );\r\n\r\n this.#subsctiption.add(\r\n this.tab.tabInfoChanges.pipe(startWith(null)).subscribe(tabInfo => {\r\n if (tabInfo) {\r\n this.tabInfo = tabInfo;\r\n this.cdRef.markForCheck();\r\n }\r\n })\r\n );\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.#subsctiption.unsubscribe();\r\n }\r\n\r\n onTabClick = (event: Event) => {\r\n event.preventDefault();\r\n this.router.navigate([this.tab.url], {\r\n queryParams: this.tab.queryParams,\r\n state: { switchTab: true },\r\n });\r\n };\r\n\r\n close = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n };\r\n\r\n onMousedown = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n onMouseup = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n }\r\n };\r\n\r\n #closeTab = async () => {\r\n if (this.tab?.beforeClose) {\r\n //\r\n if (this.tab?.beforeClose()) {\r\n const result = this.tab?.beforeClose();\r\n if (typeof result === 'boolean') {\r\n if (result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n } else {\r\n if (await result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n }\r\n }\r\n } else {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n };\r\n}\r\n","<a\r\n [href]=\"[tab.url]\"\r\n class=\"tab-router__item d-flex align-items-center gap-8\"\r\n [class.tab-router__item--active]=\"tab.isActive\"\r\n (click)=\"onTabClick($event)\"\r\n (mousedown)=\"onMousedown($event)\"\r\n (mouseup)=\"onMouseup($event)\">\r\n @let info = tabInfo | sdTabInfo: tab;\r\n @if (info) {\r\n <sd-badge\r\n style=\"overflow: hidden;white-space: nowrap;\"\r\n [icon]=\"info.icon\"\r\n [title]=\"info.icon\"\r\n [tooltip]=\"info.tooltip || info.name\"\r\n [title]=\"info.name\"\r\n [color]=\"info.color\"\r\n (click)=\"onTabClick($event)\"></sd-badge>\r\n <button\r\n aria-hidden=\"true\"\r\n class=\"tab-router__close d-flex align-items-center justify-content-center ml-auto p-0\"\r\n (click)=\"close($event)\"\r\n (mousedown)=\"$event.stopPropagation()\">\r\n <mat-icon aria-hidden=\"true\" fontIcon=\"close\"></mat-icon>\r\n </button>\r\n }\r\n</a>\r\n","import { CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostListener, Input, ViewChild } from '@angular/core';\n\nimport { SdTab } from '../../models/tab-router.model';\nimport { SdTabRouterItemComponent } from '../tab-router-item/tab-router-item.component';\nimport { CommonModule } from '@angular/common';\n\n@Component({\n selector: 'sd-tab-router-nav',\n templateUrl: './tab-router-nav.component.html',\n styleUrls: ['./tab-router-nav.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, DragDropModule, SdTabRouterItemComponent],\n})\nexport class SdTabRouterNavComponent {\n @ViewChild('tabRouterNav') tabRouterNav?: ElementRef;\n\n @Input() tabs: SdTab[] = [];\n mode: 'default' | 'compact' = 'default';\n\n constructor(\n private cdRef: ChangeDetectorRef,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public elementRef: ElementRef<any>\n ) {}\n\n @HostListener('window:resize', ['$event'])\n onResize(): void {\n this.checkUI();\n }\n\n checkUI = () => {\n const width = this.tabRouterNav?.nativeElement.clientWidth;\n const nameWidth = (width - this.tabs!.length * 68) / this.tabs!.length;\n if (nameWidth <= 20) {\n this.mode = 'compact';\n } else {\n this.mode = 'default';\n }\n this.cdRef.markForCheck();\n };\n\n onDrop = (event: CdkDragDrop<SdTab[]>) => {\n moveItemInArray(this.tabs!, event.previousIndex, event.currentIndex);\n };\n}\n","<div\n #tabRouterNav\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\n [class.d-none]=\"tabs.length > 1\">\n <ng-container *ngFor=\"let tab of tabs\">\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef?.nativeElement\"></sd-tab-router-item>\n </ng-container>\n</div>\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { \n Component, \n Injector, \n OnDestroy, \n Type, \n ViewChild, \n inject, \n signal, \n createNgModule,\n NgModuleFactory\n} from '@angular/core';\nimport {\n ActivatedRoute,\n ActivatedRouteSnapshot,\n NavigationEnd,\n Router,\n RouterEvent,\n} from '@angular/router';\nimport { CommonModule } from '@angular/common';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { Subject, Subscription, isObservable, lastValueFrom } from 'rxjs';\nimport { filter, map } from 'rxjs/operators';\n\nimport { SdNotifyService } from '@sd-angular/core/services/notify';\nimport { SdUtilities } from '@sd-angular/core/utilities';\nimport { SdTabActivated, SdTabDeactivated } from '../../events/tab-router.event';\nimport { SdTabAction } from '../../actions/tab-router.action';\nimport { SdTab } from '../../models';\nimport { SdTabDecoratorService } from '../../services/tab-decorator.service';\nimport { SdTabRouterService } from '../../services/tab-router.service';\nimport { SdTabRouterNavComponent } from '../tab-router-nav/tab-router-nav.component';\n\n@Component({\n selector: 'sd-tab-router-outlet',\n templateUrl: './tab-router-outlet.component.html',\n styleUrls: ['./tab-router-outlet.component.scss'],\n standalone: true,\n imports: [CommonModule, MatIconModule, MatTooltipModule, SdTabRouterNavComponent],\n})\nexport class SdTabRouterOutletComponent implements OnDestroy {\n @ViewChild('tabRouterNav') tabRouterNav?: SdTabRouterNavComponent;\n \n tabs = signal<SdTab[]>([]);\n\n #router = inject(Router);\n #activatedRoute = inject(ActivatedRoute);\n #injector = inject(Injector);\n #tabRouterService = inject(SdTabRouterService);\n #sdNotifyService = inject(SdNotifyService);\n #tabDecoratorService = inject(SdTabDecoratorService);\n\n #rootRoute?: ActivatedRoute;\n #subscription = new Subscription();\n\n constructor() {\n this.#subscription.add(\n this.#router.events\n .pipe(\n map((event: any) => (event instanceof RouterEvent ? event : event.routerEvent)),\n filter(event => event instanceof NavigationEnd)\n )\n .subscribe(async (event: any) => {\n const route = this.#getActivatedRouteSnapshot(this.#activatedRoute.snapshot);\n this.#rootRoute = this.#router.routerState.root;\n await this.#activeRoute(event.urlAfterRedirects || event.url, route);\n })\n );\n\n this.#subscription.add(\n this.#tabRouterService.actions.subscribe((event: SdTabAction | undefined) => {\n if (event?.type === 'close') {\n this.#closeTab(event.tab);\n }\n })\n );\n }\n\n ngOnDestroy(): void {\n this.#subscription.unsubscribe();\n }\n\n tabTrackBy = (index: number, tab: SdTab) => tab.key;\n\n #closeTab = (tab: SdTab) => {\n const currentTabs = this.tabs();\n const { isActive, key: activeKey } = tab;\n \n if (isActive) {\n const activeIndex = currentTabs.findIndex(({ key }) => key === activeKey);\n const nextTab = currentTabs[activeIndex + 1] || currentTabs[activeIndex - 1];\n \n this.tabs.set(currentTabs.filter(({ key }) => key !== activeKey));\n \n if (nextTab) {\n this.#router.navigate([nextTab.url], {\n queryParams: { ...(nextTab.queryParams || {}) },\n state: { switchTab: true },\n });\n } else {\n this.#router.navigateByUrl('/', { state: { switchTab: true } });\n }\n } else {\n this.tabs.set(currentTabs.filter(({ key }) => key !== tab.key));\n this.tabRouterNav?.checkUI();\n }\n };\n\n #activeRoute = async (fullUrl: string, route: ActivatedRouteSnapshot | null) => {\n if (!route?.component) return;\n\n const component = route.component as Type<any>;\n const queryParams = { ...(route.queryParams || {}) };\n const params = { ...(route.params || {}) };\n const data = { ...(route.data || {}) };\n const [url] = fullUrl.split('?');\n const key = SdUtilities.hash({ url, queryParams });\n\n let existedIndex = -1;\n let activatedIndex = -1;\n \n const currentTabs = this.tabs();\n currentTabs.forEach((tab, index) => {\n if (tab.key === key) {\n tab.isActive = true;\n existedIndex = index;\n } else {\n if (tab.isActive) {\n activatedIndex = index;\n this.#tabRouterService.pushEvent(tab, SdTabDeactivated);\n }\n tab.isActive = false;\n }\n });\n\n const currentNavigation = this.#router.getCurrentNavigation();\n const replaceTab = currentNavigation?.extras?.state?.['replaceTab'];\n\n // --- XỬ LÝ INJECTOR VÀ FIX LỖI TYPE TS(2345) ---\n const getBestInjector = async (snapshot: ActivatedRouteSnapshot): Promise<Injector> => {\n // 1. Nếu là Standalone Route, lấy injector từ chính route config (đã được router resolve)\n const routeInjector = (snapshot as any)._resolvedGui || (snapshot as any).routeConfig?._injector;\n if (routeInjector) return routeInjector;\n\n // 2. Xử lý NgModule (Lazy load kiểu cũ)\n const loadChildren = snapshot.parent?.routeConfig?.loadChildren;\n if (typeof loadChildren === 'function') {\n let loaded: any = await loadChildren();\n \n // Unwrap Observable\n if (isObservable(loaded)) {\n loaded = await lastValueFrom(loaded);\n }\n \n // Unwrap Default Export (ES Module)\n if (loaded && typeof loaded === 'object' && 'default' in loaded) {\n loaded = loaded.default;\n }\n\n // Nếu là NgModuleFactory (Angular cũ hơn)\n if (loaded instanceof NgModuleFactory) {\n return loaded.create(this.#injector).injector;\n }\n\n // Nếu là Type (Class NgModule) - Đây là chỗ fix lỗi TS(2345)\n if (typeof loaded === 'function' && !Array.isArray(loaded)) {\n try {\n return createNgModule(loaded, this.#injector).injector;\n } catch {\n return this.#injector;\n }\n }\n }\n return this.#injector;\n };\n\n const finalInjector = await getBestInjector(route);\n const activatedRoute = this.#getActivatedRoute(this.#rootRoute!, component);\n \n const newTab: SdTab = {\n key,\n component,\n injector: new SdOutletInjector(activatedRoute, finalInjector),\n isActive: true,\n url,\n params,\n queryParams,\n data,\n tabInfoChanges: new Subject(),\n };\n\n if (existedIndex >= 0) {\n const updatedTabs = [...currentTabs];\n if (replaceTab && activatedIndex >= 0) {\n updatedTabs.splice(activatedIndex, 1);\n }\n this.#tabRouterService.setCurrentTab(updatedTabs[existedIndex]);\n this.#tabRouterService.pushEvent(updatedTabs[existedIndex], SdTabActivated);\n this.tabs.set(updatedTabs);\n } else {\n const updatedTabs = [...currentTabs];\n this.#tabRouterService.setCurrentTab(newTab);\n if (activatedIndex >= 0 && replaceTab) {\n updatedTabs.splice(activatedIndex, 1);\n }\n this.tabs.set([...updatedTabs, newTab]);\n \n if (this.tabs().length > 30) {\n this.#sdNotifyService.warning('Bạn đã mở quá nhiều tab.');\n }\n }\n \n this.tabRouterNav?.checkUI();\n };\n\n #getActivatedRouteSnapshot = (snapshot: ActivatedRouteSnapshot): ActivatedRouteSnapshot | null => {\n let node = snapshot;\n while (node.firstChild) node = node.firstChild;\n return node;\n };\n\n #getActivatedRoute = (activatedRoute: ActivatedRoute, component: any): ActivatedRoute | null => {\n if (activatedRoute.component === component) return activatedRoute;\n for (const child of activatedRoute.children) {\n const result = this.#getActivatedRoute(child, component);\n if (result) return result;\n }\n return null;\n };\n}\n\nclass SdOutletInjector implements Injector {\n constructor(\n private route: ActivatedRoute | null,\n private parentInjector: Injector\n ) {}\n\n get(token: any, notFoundValue?: any): any {\n if (token === ActivatedRoute) {\n return this.route || notFoundValue;\n }\n return this.parentInjector.get(token, notFoundValue);\n }\n}","<sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n\n<div class=\"tab-router__list\">\n @for (tab of tabs(); track tab.key) {\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\n <div class=\"tab-router__content\">\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\n </div>\n </div>\n } @empty {\n <div class=\"tab-router__empty\">\n </div>\n }\n</div>","import { Type } from '@angular/core';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\nimport { filter, take } from 'rxjs/operators';\r\nimport { SdTabDecoratorService } from '../services/tab-decorator.service';\r\n\r\nexport interface SdTabComponentArgs {\r\n url?: string;\r\n params?: any;\r\n queryParams?: any;\r\n data?: Record<string, any>;\r\n}\r\n\r\nexport declare interface SdTabComponentBuilder {\r\n component: Type<any>;\r\n name: string | ((args: SdTabComponentArgs) => string);\r\n icon?: string | ((args: SdTabComponentArgs) => string);\r\n tooltip?: string | ((args: SdTabComponentArgs) => string);\r\n color?: SdColor | ((args: SdTabComponentArgs) => SdColor);\r\n}\r\n\r\nexport function SdTabComponent<T>(builder: SdTabComponentBuilder) {\r\n return (constructor: T) => {\r\n SdTabDecoratorService.tabRouterService\r\n .pipe(\r\n filter(service => service !== undefined && service !== null),\r\n take(1)\r\n )\r\n .subscribe(service => {\r\n service.addBuilder(builder);\r\n });\r\n };\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.SdTabRouterService"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sd-angular-core-components-tab-router.mjs","sources":["../../../projects/sd-angular/components/tab-router/src/events/tab-router.event.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-router.service.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-decorator.service.ts","../../../projects/sd-angular/components/tab-router/src/pipes/tab-info.pipe.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.html","../../../projects/sd-angular/components/tab-router/src/decorators/tab.decorator.ts","../../../projects/sd-angular/components/tab-router/sd-angular-core-components-tab-router.ts"],"sourcesContent":["import { SdTab } from '../models/tab-router.model';\n\nexport class SdTabBase {\n #tab: SdTab | undefined;\n\n constructor(tab: SdTab | undefined) {\n this.#tab = tab;\n }\n\n get tab(): SdTab | undefined {\n return this.#tab;\n }\n}\n\nexport class SdTabActivated extends SdTabBase {}\n\nexport class SdTabDeactivated extends SdTabBase {}\n\nexport declare type SdTabEvent = SdTabActivated | SdTabDeactivated;\n","import { Injectable, Type } from '@angular/core';\r\nimport { BehaviorSubject } from 'rxjs';\r\nimport { SdTabAction } from '../actions/tab-router.action';\r\nimport { SdTabComponentBuilder } from '../decorators/tab.decorator';\r\nimport { SdTabBase, SdTabEvent } from '../events/tab-router.event';\r\nimport { SdTab } from '../models/tab-router.model';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdTabRouterService {\r\n events = new BehaviorSubject<SdTabEvent>(new SdTabBase(undefined));\r\n actions = new BehaviorSubject<SdTabAction | undefined>(undefined);\r\n builders = new BehaviorSubject<SdTabComponentBuilder[]>([]);\r\n currentTabChanges = new BehaviorSubject<SdTab | undefined>(undefined);\r\n newTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n updateTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n #currentTab: SdTab | undefined = undefined;\r\n #componentBuilders: SdTabComponentBuilder[] = [];\r\n constructor() {}\r\n\r\n addBuilder = (builder: SdTabComponentBuilder) => {\r\n if (!this.#componentBuilders.some(e => e.component === builder.component)) {\r\n this.#componentBuilders.push(builder);\r\n this.builders.next(this.#componentBuilders);\r\n }\r\n };\r\n\r\n get currentTab() {\r\n return this.#currentTab;\r\n }\r\n\r\n get currentKey() {\r\n return this.#currentTab?.key || null;\r\n }\r\n\r\n // select = (tabOrKey: string | SdTab): void => {\r\n // const tab = this.#tabs.find(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key === tabOrKey;\r\n // }\r\n // return e.key === tabOrKey?.key;\r\n // });\r\n // if (tab) {\r\n // this.#currentTab = tab;\r\n // }\r\n // }\r\n\r\n // add = (tab: SdTab): void => {\r\n // if (!tab.key) {\r\n // this.notifyService.notify.warning('Tab key is required');\r\n // }\r\n // if (!tab.component) {\r\n // this.notifyService.notify.warning('Tab component is required');\r\n // }\r\n // const existedTab = this.#tabs.find(e => e.key === tab.key);\r\n // if (!existedTab) {\r\n // this.#tabs.push(tab);\r\n // this.select(tab);\r\n // } else {\r\n // this.select(existedTab);\r\n // }\r\n // }\r\n\r\n // remove = (tabOrKey: string | SdTab): void => {\r\n // this.#tabs = this.#tabs.filter(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key !== tabOrKey;\r\n // }\r\n // return e.key !== tabOrKey?.key;\r\n // });\r\n // }\r\n\r\n setCurrentTab = (tab: SdTab): void => {\r\n this.#currentTab = tab;\r\n this.currentTabChanges.next(tab);\r\n };\r\n\r\n pushEvent = (tab: SdTab, Event: Type<SdTabEvent>) => {\r\n this.events.next(new Event(tab));\r\n };\r\n\r\n setOptions = () => {};\r\n\r\n close = (tab?: SdTab) => {\r\n tab = tab || this.#currentTab;\r\n if (tab) {\r\n this.actions.next({\r\n type: 'close',\r\n tab,\r\n });\r\n }\r\n };\r\n\r\n // Gọi hàm này để thực hiện update tab\r\n updateTab = (tab: SdTab) => {};\r\n}\r\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { SdTabRouterService } from './tab-router.service';\n@Injectable({\n providedIn: 'root',\n})\nexport class SdTabDecoratorService {\n static tabRouterService = new BehaviorSubject<SdTabRouterService | undefined>(undefined);\n constructor(tabRouterService: SdTabRouterService) {\n SdTabDecoratorService.tabRouterService.next(tabRouterService);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { SdTab, SdTabInfo } from '../models/tab-router.model';\nimport { SdTabRouterService } from '../services/tab-router.service';\n@Pipe({\n name: 'sdTabInfo',\n standalone: true,\n})\nexport class SdTabInfoPipe implements PipeTransform {\n constructor(private tabRouterService: SdTabRouterService) {}\n transform(tabInfo: SdTabInfo | undefined | null, tab: SdTab): SdTabInfo {\n if (tabInfo) {\n return tabInfo;\n }\n const builders = this.tabRouterService.builders.getValue();\n const builder = builders.find(e => e.component === tab.component);\n if (builder) {\n const { url, params, queryParams, data } = tab;\n return {\n name: typeof builder.name === 'function' ? builder.name({ url, params, queryParams, data }) : builder.name,\n icon: typeof builder.icon === 'function' ? builder.icon({ url, params, queryParams }) : builder.icon,\n tooltip: typeof builder.tooltip === 'function' ? builder.tooltip({ url, params, queryParams }) : builder.tooltip,\n color: typeof builder.color === 'function' ? builder.color({ url, params, queryParams }) : builder.color,\n };\n }\n return {\n name: tab.url,\n icon: undefined,\n };\n }\n}\n","import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';\r\nimport { Subscription } from 'rxjs';\r\nimport { debounceTime, startWith } from 'rxjs/operators';\r\n\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { SdBadge } from '@sd-angular/core/components/badge';\r\nimport { SdTab, SdTabInfo } from '../../models';\r\nimport { SdTabRouterService } from '../../services/tab-router.service';\r\nimport { Router } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { SdTabInfoPipe } from '../../pipes/tab-info.pipe';\r\n\r\n@Component({\r\n selector: 'sd-tab-router-item',\r\n templateUrl: './tab-router-item.component.html',\r\n styleUrls: ['./tab-router-item.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n standalone: true,\r\n imports: [CommonModule, MatIconModule, SdBadge, SdTabInfoPipe],\r\n})\r\nexport class SdTabRouterItemComponent implements OnInit, OnDestroy {\r\n @Input({ required: true }) tab!: SdTab;\r\n\r\n #subsctiption: Subscription = new Subscription();\r\n tabInfo?: SdTabInfo;\r\n constructor(\r\n private cdRef: ChangeDetectorRef,\r\n private tabRouterService: SdTabRouterService,\r\n private router: Router\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n this.#subsctiption.add(\r\n this.tabRouterService.events.pipe(debounceTime(100)).subscribe(() => {\r\n this.cdRef.markForCheck();\r\n })\r\n );\r\n\r\n this.#subsctiption.add(\r\n this.tab.tabInfoChanges.pipe(startWith(null)).subscribe(tabInfo => {\r\n if (tabInfo) {\r\n this.tabInfo = tabInfo;\r\n this.cdRef.markForCheck();\r\n }\r\n })\r\n );\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.#subsctiption.unsubscribe();\r\n }\r\n\r\n onTabClick = (event: Event) => {\r\n event.preventDefault();\r\n this.router.navigate([this.tab.url], {\r\n queryParams: this.tab.queryParams,\r\n state: { switchTab: true },\r\n });\r\n };\r\n\r\n close = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n };\r\n\r\n onMousedown = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n onMouseup = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n }\r\n };\r\n\r\n #closeTab = async () => {\r\n if (this.tab?.beforeClose) {\r\n //\r\n if (this.tab?.beforeClose()) {\r\n const result = this.tab?.beforeClose();\r\n if (typeof result === 'boolean') {\r\n if (result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n } else {\r\n if (await result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n }\r\n }\r\n } else {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n };\r\n}\r\n","<a\r\n [href]=\"[tab.url]\"\r\n class=\"tab-router__item d-flex align-items-center gap-8\"\r\n [class.tab-router__item--active]=\"tab.isActive\"\r\n (click)=\"onTabClick($event)\"\r\n (mousedown)=\"onMousedown($event)\"\r\n (mouseup)=\"onMouseup($event)\">\r\n @let info = tabInfo | sdTabInfo: tab;\r\n @if (info) {\r\n <sd-badge\r\n style=\"overflow: hidden;white-space: nowrap;\"\r\n [icon]=\"info.icon\"\r\n [title]=\"info.icon\"\r\n [tooltip]=\"info.tooltip || info.name\"\r\n [title]=\"info.name\"\r\n [color]=\"info.color\"\r\n (click)=\"onTabClick($event)\"></sd-badge>\r\n <button\r\n aria-hidden=\"true\"\r\n class=\"tab-router__close d-flex align-items-center justify-content-center ml-auto p-0\"\r\n (click)=\"close($event)\"\r\n (mousedown)=\"$event.stopPropagation()\">\r\n <mat-icon aria-hidden=\"true\" fontIcon=\"close\"></mat-icon>\r\n </button>\r\n }\r\n</a>\r\n","import { CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostListener, Input, ViewChild } from '@angular/core';\n\nimport { SdTab } from '../../models/tab-router.model';\nimport { SdTabRouterItemComponent } from '../tab-router-item/tab-router-item.component';\nimport { CommonModule } from '@angular/common';\n\n@Component({\n selector: 'sd-tab-router-nav',\n templateUrl: './tab-router-nav.component.html',\n styleUrls: ['./tab-router-nav.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, DragDropModule, SdTabRouterItemComponent],\n})\nexport class SdTabRouterNavComponent {\n @ViewChild('tabRouterNav') tabRouterNav?: ElementRef;\n\n @Input() tabs: SdTab[] = [];\n mode: 'default' | 'compact' = 'default';\n\n constructor(\n private cdRef: ChangeDetectorRef,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public elementRef: ElementRef<any>\n ) {}\n\n @HostListener('window:resize', ['$event'])\n onResize(): void {\n this.checkUI();\n }\n\n checkUI = () => {\n const width = this.tabRouterNav?.nativeElement.clientWidth;\n const nameWidth = (width - this.tabs!.length * 68) / this.tabs!.length;\n if (nameWidth <= 20) {\n this.mode = 'compact';\n } else {\n this.mode = 'default';\n }\n this.cdRef.markForCheck();\n };\n\n onDrop = (event: CdkDragDrop<SdTab[]>) => {\n moveItemInArray(this.tabs!, event.previousIndex, event.currentIndex);\n };\n}\n","<div\n #tabRouterNav\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\n [class.d-none]=\"tabs.length > 1\">\n <ng-container *ngFor=\"let tab of tabs\">\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef?.nativeElement\"></sd-tab-router-item>\n </ng-container>\n</div>\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n Component,\n Injector,\n OnDestroy,\n Type,\n ViewChild,\n inject,\n signal,\n createNgModule,\n NgModuleFactory,\n} from '@angular/core';\nimport {\n ActivatedRoute,\n ActivatedRouteSnapshot,\n NavigationEnd,\n Router,\n RouterEvent,\n RoutesRecognized,\n} from '@angular/router';\nimport { CommonModule } from '@angular/common';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { Subject, Subscription, isObservable, lastValueFrom } from 'rxjs';\nimport { filter, map } from 'rxjs/operators';\n\nimport { SdNotifyService } from '@sd-angular/core/services/notify';\nimport { SdUtilities } from '@sd-angular/core/utilities';\nimport { SdTabActivated, SdTabDeactivated } from '../../events/tab-router.event';\nimport { SdTabAction } from '../../actions/tab-router.action';\nimport { SdTab } from '../../models';\nimport { SdTabDecoratorService } from '../../services/tab-decorator.service';\nimport { SdTabRouterService } from '../../services/tab-router.service';\nimport { SdTabRouterNavComponent } from '../tab-router-nav/tab-router-nav.component';\n\n@Component({\n selector: 'sd-tab-router-outlet',\n templateUrl: './tab-router-outlet.component.html',\n styleUrls: ['./tab-router-outlet.component.scss'],\n standalone: true,\n imports: [CommonModule, MatIconModule, MatTooltipModule, SdTabRouterNavComponent],\n})\nexport class SdTabRouterOutletComponent implements OnDestroy {\n @ViewChild('tabRouterNav') tabRouterNav?: SdTabRouterNavComponent;\n\n tabs = signal<SdTab[]>([]);\n\n #router = inject(Router);\n #activatedRoute = inject(ActivatedRoute);\n #injector = inject(Injector);\n #tabRouterService = inject(SdTabRouterService);\n #sdNotifyService = inject(SdNotifyService);\n // Inject để đảm bảo SdTabDecoratorService được khởi tạo (nó register BehaviorSubject\n // tĩnh để @SdTab decorator có thể truy cập SdTabRouterService). Không dùng trực tiếp ở đây.\n #tabDecoratorService = inject(SdTabDecoratorService);\n\n #rootRoute?: ActivatedRoute;\n #subscription = new Subscription();\n\n // State của navigation hiện tại (replaceTab, switchTab, ...) được capture ở RoutesRecognized\n // và dùng lại ở NavigationEnd. Lý do: tại NavigationEnd, getCurrentNavigation() đã trả về null,\n // còn lastSuccessfulNavigation và window.history.state không đáng tin cậy với mọi case.\n #pendingNavigationState: Record<string, any> = {};\n\n constructor() {\n this.#subscription.add(\n this.#router.events\n .pipe(\n // Một số event của Angular bọc trong wrapper có .routerEvent → unwrap về RouterEvent gốc.\n map((event: any) => (event instanceof RouterEvent ? event : event.routerEvent)),\n // Hybrid: cần CẢ HAI event vì mỗi event chứa data khác nhau ở thời điểm khác nhau.\n // - RoutesRecognized: navigation đang in-flight → getCurrentNavigation().extras.state đọc được\n // - NavigationEnd: navigation hoàn tất → routerState.root đã update với route mới (cần cho lazy routes)\n filter(event => event instanceof RoutesRecognized || event instanceof NavigationEnd)\n )\n .subscribe(async (event: any) => {\n if (event instanceof RoutesRecognized) {\n // Capture state ngay lúc nav còn in-flight. Đây là điểm duy nhất chắc chắn\n // getCurrentNavigation() trả về Navigation object với extras.state nguyên vẹn.\n this.#pendingNavigationState = this.#router.getCurrentNavigation()?.extras?.state ?? {};\n return;\n }\n // NavigationEnd: dùng activatedRoute.snapshot và routerState.root MỚI nhất\n // (chứa route component đã được activate, cả lazy lẫn standalone routes).\n const route = this.#getActivatedRouteSnapshot(this.#activatedRoute.snapshot);\n this.#rootRoute = this.#router.routerState.root;\n await this.#activeRoute(event.urlAfterRedirects || event.url, route, this.#pendingNavigationState);\n this.#pendingNavigationState = {};\n })\n );\n\n this.#subscription.add(\n this.#tabRouterService.actions.subscribe((event: SdTabAction | undefined) => {\n if (event?.type === 'close') {\n this.#closeTab(event.tab);\n }\n })\n );\n }\n\n ngOnDestroy(): void {\n this.#subscription.unsubscribe();\n }\n\n tabTrackBy = (index: number, tab: SdTab) => tab.key;\n\n #closeTab = (tab: SdTab) => {\n const currentTabs = this.tabs();\n const { isActive, key: activeKey } = tab;\n\n if (isActive) {\n const activeIndex = currentTabs.findIndex(({ key }) => key === activeKey);\n const nextTab = currentTabs[activeIndex + 1] || currentTabs[activeIndex - 1];\n\n this.tabs.set(currentTabs.filter(({ key }) => key !== activeKey));\n\n if (nextTab) {\n this.#router.navigate([nextTab.url], {\n queryParams: { ...(nextTab.queryParams || {}) },\n state: { switchTab: true },\n });\n } else {\n this.#router.navigateByUrl('/', { state: { switchTab: true } });\n }\n } else {\n this.tabs.set(currentTabs.filter(({ key }) => key !== tab.key));\n this.tabRouterNav?.checkUI();\n }\n };\n\n #activeRoute = async (\n fullUrl: string,\n route: ActivatedRouteSnapshot | null,\n state: Record<string, any> = {}\n ) => {\n if (!route?.component) return;\n\n const component = route.component as Type<any>;\n const queryParams = { ...(route.queryParams || {}) };\n const params = { ...(route.params || {}) };\n const data = { ...(route.data || {}) };\n const [url] = fullUrl.split('?');\n // Tab identity = hash(url + queryParams). Cùng key = cùng tab, không tạo lại.\n const key = SdUtilities.hash({ url, queryParams });\n\n let existedIndex = -1;\n let activatedIndex = -1;\n\n const currentTabs = this.tabs();\n\n // QUAN TRỌNG: scan READ-ONLY, KHÔNG mutate tab.isActive trong loop này.\n //\n // Lý do: NavigationEnd có thể fire nhiều lần cho 1 user-action (do nested outlets,\n // redirect, hoặc Angular internal). Vì #activeRoute là async (await getBestInjector),\n // 2 invocations có thể chạy concurrent và interleave với nhau.\n //\n // Nếu mutate tab.isActive = false ở đây, call thứ 2 sẽ thấy isActive đã bị call 1\n // set false rồi → không tìm thấy active tab → activatedIndex stay -1 → splice bỏ qua\n // → tab cũ không bị remove → xuất hiện duplicate tabs.\n //\n // Cách fix: chỉ ĐỌC isActive, sau đó dùng .map() ở dưới để tạo tab objects mới qua spread.\n for (let i = 0; i < currentTabs.length; i++) {\n const tab = currentTabs[i];\n if (tab.key === key) {\n existedIndex = i;\n } else if (tab.isActive) {\n activatedIndex = i;\n this.#tabRouterService.pushEvent(tab, SdTabDeactivated);\n }\n }\n\n const replaceTab = state['replaceTab'];\n\n // Resolve injector phù hợp với route. Cần xử lý 3 trường hợp:\n // - Standalone route (Angular đã set _injector trên routeConfig sau khi activate)\n // - NgModule lazy load (cần createNgModule từ class)\n // - Fallback: root injector\n const getBestInjector = async (snapshot: ActivatedRouteSnapshot): Promise<Injector> => {\n // Standalone route: Angular tự lưu environment injector trên routeConfig._injector\n const routeInjector = (snapshot as any)._resolvedGui || (snapshot as any).routeConfig?._injector;\n if (routeInjector) return routeInjector;\n\n // NgModule lazy: phải gọi lại loadChildren() để lấy module class rồi createNgModule\n const loadChildren = snapshot.parent?.routeConfig?.loadChildren;\n if (typeof loadChildren === 'function') {\n let loaded: any = await loadChildren();\n\n if (isObservable(loaded)) {\n loaded = await lastValueFrom(loaded);\n }\n\n // ES module có thể export default\n if (loaded && typeof loaded === 'object' && 'default' in loaded) {\n loaded = loaded.default;\n }\n\n // Angular cũ: NgModuleFactory\n if (loaded instanceof NgModuleFactory) {\n return loaded.create(this.#injector).injector;\n }\n\n // Angular mới: NgModule class. Bọc try/catch vì createNgModule throw nếu không phải NgModule.\n if (typeof loaded === 'function' && !Array.isArray(loaded)) {\n try {\n return createNgModule(loaded, this.#injector).injector;\n } catch {\n return this.#injector;\n }\n }\n }\n return this.#injector;\n };\n\n const finalInjector = await getBestInjector(route);\n const activatedRoute = this.#getActivatedRoute(this.#rootRoute!, component);\n\n const newTab: SdTab = {\n key,\n component,\n injector: new SdOutletInjector(activatedRoute, finalInjector),\n isActive: true,\n url,\n params,\n queryParams,\n data,\n tabInfoChanges: new Subject(),\n };\n\n // Tạo updatedTabs qua spread thay vì mutate (xem lý do ở for loop phía trên).\n // Với tab có isActive không đổi: giữ nguyên reference (tránh trigger ngComponentOutlet\n // re-evaluate không cần thiết). Với tab cần đổi isActive: tạo object mới qua spread,\n // các nested fields (component, injector) vẫn giữ same reference nên component không bị recreate.\n let updatedTabs = currentTabs.map(tab => {\n if (tab.key === key) return tab.isActive ? tab : { ...tab, isActive: true };\n return tab.isActive ? { ...tab, isActive: false } : tab;\n });\n\n // replaceTab: thay vì mở tab mới song song, xoá tab đang active rồi mở tab mới ở cuối.\n // Use case: từ tab \"chi tiết\" bấm \"chỉnh sửa\" với replaceTab → tab chi tiết bị xoá,\n // tab chỉnh sửa thay thế (giữ số tab không tăng).\n if (replaceTab && activatedIndex >= 0) {\n updatedTabs = updatedTabs.filter((_, i) => i !== activatedIndex);\n }\n\n if (existedIndex >= 0) {\n // Tab đã tồn tại (cùng url + queryParams) → CHỈ activate, KHÔNG thay tab object.\n // Lý do: thay tab object = đổi reference của tab.injector → ngComponentOutlet recreate\n // component → tab bị \"reload\" mỗi khi click lại hoặc navigate cùng URL.\n //\n // splice phía trên có thể đã shift index nếu activatedIndex < existedIndex.\n const idx = replaceTab && activatedIndex >= 0 && activatedIndex < existedIndex\n ? existedIndex - 1\n : existedIndex;\n this.#tabRouterService.setCurrentTab(updatedTabs[idx]);\n this.#tabRouterService.pushEvent(updatedTabs[idx], SdTabActivated);\n this.tabs.set(updatedTabs);\n } else {\n // Tab chưa tồn tại → thêm mới ở cuối.\n this.#tabRouterService.setCurrentTab(newTab);\n this.tabs.set([...updatedTabs, newTab]);\n\n if (this.tabs().length > 30) {\n this.#sdNotifyService.warning('Bạn đã mở quá nhiều tab.');\n }\n }\n\n this.tabRouterNav?.checkUI();\n };\n\n // Lần xuống deepest firstChild để lấy snapshot của route lá (route thực sự render component).\n #getActivatedRouteSnapshot = (snapshot: ActivatedRouteSnapshot): ActivatedRouteSnapshot | null => {\n let node = snapshot;\n while (node.firstChild) node = node.firstChild;\n return node;\n };\n\n // DFS tìm ActivatedRoute (không phải snapshot) trong tree theo component class.\n // Cần ActivatedRoute thật vì SdOutletInjector sẽ inject nó vào component qua DI.\n #getActivatedRoute = (activatedRoute: ActivatedRoute, component: any): ActivatedRoute | null => {\n if (activatedRoute.component === component) return activatedRoute;\n for (const child of activatedRoute.children) {\n const result = this.#getActivatedRoute(child, component);\n if (result) return result;\n }\n return null;\n };\n}\n\n// Custom Injector cho từng tab: override ActivatedRoute thành route của TAB ĐÓ\n// (không phải route hiện tại của router). Nếu không override, mọi tab sẽ inject ActivatedRoute\n// của route đang active → component cũ trong tab inactive nhận data sai khi user navigate.\nclass SdOutletInjector implements Injector {\n constructor(\n private route: ActivatedRoute | null,\n private parentInjector: Injector\n ) {}\n\n get(token: any, notFoundValue?: any): any {\n if (token === ActivatedRoute) {\n return this.route || notFoundValue;\n }\n return this.parentInjector.get(token, notFoundValue);\n }\n}\n","<sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n\n<div class=\"tab-router__list\">\n @for (tab of tabs(); track tab.key) {\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\n <div class=\"tab-router__content\">\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\n </div>\n </div>\n } @empty {\n <div class=\"tab-router__empty\">\n </div>\n }\n</div>","import { Type } from '@angular/core';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\nimport { filter, take } from 'rxjs/operators';\r\nimport { SdTabDecoratorService } from '../services/tab-decorator.service';\r\n\r\nexport interface SdTabComponentArgs {\r\n url?: string;\r\n params?: any;\r\n queryParams?: any;\r\n data?: Record<string, any>;\r\n}\r\n\r\nexport declare interface SdTabComponentBuilder {\r\n component: Type<any>;\r\n name: string | ((args: SdTabComponentArgs) => string);\r\n icon?: string | ((args: SdTabComponentArgs) => string);\r\n tooltip?: string | ((args: SdTabComponentArgs) => string);\r\n color?: SdColor | ((args: SdTabComponentArgs) => SdColor);\r\n}\r\n\r\nexport function SdTabComponent<T>(builder: SdTabComponentBuilder) {\r\n return (constructor: T) => {\r\n SdTabDecoratorService.tabRouterService\r\n .pipe(\r\n filter(service => service !== undefined && service !== null),\r\n take(1)\r\n )\r\n .subscribe(service => {\r\n service.addBuilder(builder);\r\n });\r\n };\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.SdTabRouterService"],"mappings":"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"}
|
|
@@ -1,18 +1,157 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable } from '@angular/core';
|
|
3
|
-
import
|
|
4
|
-
import { docxToHtml } from '@omer-go/docx-parser-converter-ts';
|
|
3
|
+
import { OpenFile, PreopenDirectory, File as File$1, ConsoleStdout, WASI } from '@bjorn3/browser_wasi_shim';
|
|
5
4
|
import * as i1 from '@sd-angular/core/services/notify';
|
|
5
|
+
import * as i2 from '@sd-angular/core/services/loading';
|
|
6
|
+
|
|
7
|
+
/* Pandoc WASM core logic — adapted from pandoc-wasm/src/core.js
|
|
8
|
+
*
|
|
9
|
+
* This file is a local copy of the environment-agnostic pandoc core.
|
|
10
|
+
* It imports @bjorn3/browser_wasi_shim directly, avoiding the pandoc-wasm
|
|
11
|
+
* package entry points which use top-level await (incompatible with
|
|
12
|
+
* Angular's esbuild/Vite build pipeline).
|
|
13
|
+
*
|
|
14
|
+
* Source: https://github.com/pandoc/pandoc-wasm (GPL-2.0-or-later)
|
|
15
|
+
*/
|
|
16
|
+
// @ts-nocheck
|
|
17
|
+
function createPandocInstance(wasmBinary) {
|
|
18
|
+
const args = ['pandoc.wasm', '+RTS', '-H64m', '-RTS'];
|
|
19
|
+
const env = [];
|
|
20
|
+
const fileSystem = new Map();
|
|
21
|
+
const fds = [
|
|
22
|
+
new OpenFile(new File$1(new Uint8Array(), { readonly: true })),
|
|
23
|
+
ConsoleStdout.lineBuffered((msg) => console.log(`[WASI stdout] ${msg}`)),
|
|
24
|
+
ConsoleStdout.lineBuffered((msg) => console.warn(`[WASI stderr] ${msg}`)),
|
|
25
|
+
new PreopenDirectory('/', fileSystem),
|
|
26
|
+
];
|
|
27
|
+
const options = { debug: false };
|
|
28
|
+
const wasi = new WASI(args, env, fds, options);
|
|
29
|
+
return WebAssembly.instantiate(wasmBinary, {
|
|
30
|
+
wasi_snapshot_preview1: wasi.wasiImport,
|
|
31
|
+
}).then(({ instance }) => {
|
|
32
|
+
wasi.initialize(instance);
|
|
33
|
+
instance.exports.__wasm_call_ctors();
|
|
34
|
+
function memory_data_view() {
|
|
35
|
+
return new DataView(instance.exports.memory.buffer);
|
|
36
|
+
}
|
|
37
|
+
const argc_ptr = instance.exports.malloc(4);
|
|
38
|
+
memory_data_view().setUint32(argc_ptr, args.length, true);
|
|
39
|
+
const argv = instance.exports.malloc(4 * (args.length + 1));
|
|
40
|
+
for (let i = 0; i < args.length; ++i) {
|
|
41
|
+
const arg = instance.exports.malloc(args[i].length + 1);
|
|
42
|
+
new TextEncoder().encodeInto(args[i], new Uint8Array(instance.exports.memory.buffer, arg, args[i].length));
|
|
43
|
+
memory_data_view().setUint8(arg + args[i].length, 0);
|
|
44
|
+
memory_data_view().setUint32(argv + 4 * i, arg, true);
|
|
45
|
+
}
|
|
46
|
+
memory_data_view().setUint32(argv + 4 * args.length, 0, true);
|
|
47
|
+
const argv_ptr = instance.exports.malloc(4);
|
|
48
|
+
memory_data_view().setUint32(argv_ptr, argv, true);
|
|
49
|
+
instance.exports.hs_init_with_rtsopts(argc_ptr, argv_ptr);
|
|
50
|
+
async function addFile(filename, data, readonly) {
|
|
51
|
+
let uint8Array;
|
|
52
|
+
if (typeof data === 'string') {
|
|
53
|
+
uint8Array = new TextEncoder().encode(data);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const buffer = await data.arrayBuffer();
|
|
57
|
+
uint8Array = new Uint8Array(buffer);
|
|
58
|
+
}
|
|
59
|
+
const file = new File$1(uint8Array, { readonly });
|
|
60
|
+
fileSystem.set(filename, file);
|
|
61
|
+
}
|
|
62
|
+
async function convert(options, stdin, files) {
|
|
63
|
+
const opts_str = JSON.stringify(options);
|
|
64
|
+
const encoded = new TextEncoder().encode(opts_str);
|
|
65
|
+
const opts_ptr = instance.exports.malloc(encoded.length);
|
|
66
|
+
new TextEncoder().encodeInto(opts_str, new Uint8Array(instance.exports.memory.buffer, opts_ptr, encoded.length));
|
|
67
|
+
files = { ...files };
|
|
68
|
+
fileSystem.clear();
|
|
69
|
+
const in_file = new File$1(new Uint8Array(), { readonly: true });
|
|
70
|
+
const out_file = new File$1(new Uint8Array(), { readonly: false });
|
|
71
|
+
const err_file = new File$1(new Uint8Array(), { readonly: false });
|
|
72
|
+
const warnings_file = new File$1(new Uint8Array(), { readonly: false });
|
|
73
|
+
fileSystem.set('stdin', in_file);
|
|
74
|
+
fileSystem.set('stdout', out_file);
|
|
75
|
+
fileSystem.set('stderr', err_file);
|
|
76
|
+
fileSystem.set('warnings', warnings_file);
|
|
77
|
+
const knownFiles = new Set(['stdin', 'stdout', 'stderr', 'warnings']);
|
|
78
|
+
for (const filename in files) {
|
|
79
|
+
await addFile(filename, files[filename], true);
|
|
80
|
+
knownFiles.add(filename);
|
|
81
|
+
}
|
|
82
|
+
const outputFileName = options['output-file'] || null;
|
|
83
|
+
const extractMediaPath = options['extract-media'] || null;
|
|
84
|
+
if (outputFileName) {
|
|
85
|
+
await addFile(outputFileName, new Blob(), false);
|
|
86
|
+
knownFiles.add(outputFileName);
|
|
87
|
+
}
|
|
88
|
+
if (extractMediaPath) {
|
|
89
|
+
await addFile(extractMediaPath, new Blob(), false);
|
|
90
|
+
if (extractMediaPath.endsWith('.zip')) {
|
|
91
|
+
knownFiles.add(extractMediaPath);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (stdin) {
|
|
95
|
+
in_file.data = new TextEncoder().encode(stdin);
|
|
96
|
+
}
|
|
97
|
+
instance.exports.convert(opts_ptr, encoded.length);
|
|
98
|
+
if (options['output-file']) {
|
|
99
|
+
const outputFile = fileSystem.get(options['output-file']);
|
|
100
|
+
if (outputFile && outputFile.data && outputFile.data.length > 0) {
|
|
101
|
+
files[options['output-file']] = new Blob([outputFile.data]);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (options['extract-media']) {
|
|
105
|
+
const mediaFile = fileSystem.get(options['extract-media']);
|
|
106
|
+
if (mediaFile && mediaFile.data && mediaFile.data.length > 0) {
|
|
107
|
+
files[options['extract-media']] = new Blob([mediaFile.data], { type: 'application/zip' });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const mediaFiles = {};
|
|
111
|
+
for (const [name, fileData] of fileSystem.entries()) {
|
|
112
|
+
if (!knownFiles.has(name) && fileData && fileData.data && fileData.data.length > 0) {
|
|
113
|
+
const blob = new Blob([fileData.data]);
|
|
114
|
+
files[name] = blob;
|
|
115
|
+
if (name !== outputFileName && name !== extractMediaPath) {
|
|
116
|
+
mediaFiles[name] = blob;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const rawWarnings = new TextDecoder('utf-8', { fatal: true }).decode(warnings_file.data);
|
|
121
|
+
let warnings = [];
|
|
122
|
+
if (rawWarnings) {
|
|
123
|
+
try {
|
|
124
|
+
warnings = JSON.parse(rawWarnings);
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
console.warn('Failed to parse warnings:', e);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
stdout: new TextDecoder('utf-8', { fatal: true }).decode(out_file.data),
|
|
132
|
+
stderr: new TextDecoder('utf-8', { fatal: true }).decode(err_file.data),
|
|
133
|
+
warnings,
|
|
134
|
+
files,
|
|
135
|
+
mediaFiles,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return { convert };
|
|
139
|
+
});
|
|
140
|
+
}
|
|
6
141
|
|
|
7
142
|
class SdDocxService {
|
|
8
143
|
notifyService;
|
|
144
|
+
loadingService;
|
|
9
145
|
#DEFAULT_MAX_SIZE_MB = 50;
|
|
10
146
|
#VALID_EXTENSIONS = ['.doc', '.docx'];
|
|
11
147
|
#ERROR_INVALID_FORMAT = 'Định dạng không hợp lệ. Vui lòng chọn Mẫu có định dạng DOC hoặc DOCX';
|
|
12
148
|
#ERROR_SIZE_EXCEEDED = 'Kích thước tệp mẫu vượt quá tiêu chuẩn hỗ trợ của hệ thống. Vui lòng thử lại';
|
|
149
|
+
#PANDOC_WASM_URL = 'https://pandoc.github.io/pandoc-wasm/pandoc.wasm';
|
|
13
150
|
#fileInput = null;
|
|
14
|
-
|
|
151
|
+
#pandocInstance = null;
|
|
152
|
+
constructor(notifyService, loadingService) {
|
|
15
153
|
this.notifyService = notifyService;
|
|
154
|
+
this.loadingService = loadingService;
|
|
16
155
|
}
|
|
17
156
|
async open(options) {
|
|
18
157
|
return new Promise(resolve => {
|
|
@@ -28,11 +167,21 @@ class SdDocxService {
|
|
|
28
167
|
resolve(null);
|
|
29
168
|
return;
|
|
30
169
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
170
|
+
this.loadingService.start();
|
|
171
|
+
try {
|
|
172
|
+
const result = await this.convertToHtml(file, options);
|
|
173
|
+
resolve(result);
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
console.error('[SdDocxService] DocX conversion error:', error);
|
|
177
|
+
this.notifyService.error('Có lỗi xảy ra khi chuyển đổi file DOCX');
|
|
178
|
+
resolve(null);
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
input.value = '';
|
|
182
|
+
input.removeEventListener('change', handleChange);
|
|
183
|
+
this.loadingService.stop();
|
|
184
|
+
}
|
|
36
185
|
};
|
|
37
186
|
this.#fileInput.addEventListener('change', handleChange, { once: true });
|
|
38
187
|
this.#fileInput.click();
|
|
@@ -48,6 +197,22 @@ class SdDocxService {
|
|
|
48
197
|
this.#fileInput.style.display = 'none';
|
|
49
198
|
document.body.appendChild(this.#fileInput);
|
|
50
199
|
}
|
|
200
|
+
async #getPandocInstance() {
|
|
201
|
+
if (this.#pandocInstance) {
|
|
202
|
+
return this.#pandocInstance;
|
|
203
|
+
}
|
|
204
|
+
console.log('[SdDocxService] Fetching WASM binary from:', this.#PANDOC_WASM_URL);
|
|
205
|
+
const wasmResponse = await fetch(this.#PANDOC_WASM_URL);
|
|
206
|
+
if (!wasmResponse.ok) {
|
|
207
|
+
throw new Error(`Failed to fetch pandoc.wasm: ${wasmResponse.status} ${wasmResponse.statusText}`);
|
|
208
|
+
}
|
|
209
|
+
console.log('[SdDocxService] WASM fetched, size:', wasmResponse.headers.get('content-length'));
|
|
210
|
+
const wasmBinary = await wasmResponse.arrayBuffer();
|
|
211
|
+
console.log('[SdDocxService] WASM binary loaded, bytes:', wasmBinary.byteLength);
|
|
212
|
+
this.#pandocInstance = await createPandocInstance(wasmBinary);
|
|
213
|
+
console.log('[SdDocxService] Pandoc instance created successfully');
|
|
214
|
+
return this.#pandocInstance;
|
|
215
|
+
}
|
|
51
216
|
async convertToHtml(input, options) {
|
|
52
217
|
const opts = {
|
|
53
218
|
validateFormat: true,
|
|
@@ -58,18 +223,20 @@ class SdDocxService {
|
|
|
58
223
|
try {
|
|
59
224
|
let fileName;
|
|
60
225
|
let fileSize;
|
|
61
|
-
let
|
|
226
|
+
let blob;
|
|
62
227
|
if (input instanceof File) {
|
|
63
228
|
fileName = input.name;
|
|
64
229
|
fileSize = input.size;
|
|
65
|
-
|
|
230
|
+
blob = input;
|
|
66
231
|
}
|
|
67
232
|
else if (input instanceof Blob) {
|
|
68
233
|
fileSize = input.size;
|
|
69
|
-
|
|
234
|
+
blob = input;
|
|
70
235
|
}
|
|
71
236
|
else {
|
|
72
|
-
|
|
237
|
+
blob = new Blob([input], {
|
|
238
|
+
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
239
|
+
});
|
|
73
240
|
}
|
|
74
241
|
if (opts.validateFormat && fileName) {
|
|
75
242
|
if (!this.#isValidFormat(fileName)) {
|
|
@@ -84,33 +251,25 @@ class SdDocxService {
|
|
|
84
251
|
return null;
|
|
85
252
|
}
|
|
86
253
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
html
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
catch (omerError) {
|
|
100
|
-
console.log(omerError);
|
|
101
|
-
// Fallback to mammoth if @omer-go fails (e.g., BOM issue)
|
|
102
|
-
console.warn('@omer-go/docx-parser-converter-ts failed, falling back to mammoth:', omerError?.message);
|
|
103
|
-
const result = await mammoth.convertToHtml({ arrayBuffer }, conversionOptions);
|
|
104
|
-
html = result.value;
|
|
105
|
-
messages = result.messages.map(m => m.toString());
|
|
106
|
-
}
|
|
254
|
+
console.log('[SdDocxService] Getting pandoc instance...');
|
|
255
|
+
const pandoc = await this.#getPandocInstance();
|
|
256
|
+
console.log('[SdDocxService] Converting DOCX, blob size:', blob.size);
|
|
257
|
+
const pandocOpts = {
|
|
258
|
+
from: 'docx',
|
|
259
|
+
to: 'html',
|
|
260
|
+
'input-files': ['document.docx'],
|
|
261
|
+
standalone: true,
|
|
262
|
+
'embed-resources': true,
|
|
263
|
+
};
|
|
264
|
+
const result = await pandoc.convert(pandocOpts, null, { 'document.docx': blob });
|
|
265
|
+
console.log('[SdDocxService] Conversion done, stdout length:', result.stdout?.length, 'stderr:', result.stderr);
|
|
107
266
|
return {
|
|
108
|
-
html,
|
|
109
|
-
messages,
|
|
267
|
+
html: result.stdout,
|
|
268
|
+
messages: result.warnings.map((w) => String(w)),
|
|
110
269
|
};
|
|
111
270
|
}
|
|
112
271
|
catch (error) {
|
|
113
|
-
console.error('DocX conversion error:', error);
|
|
272
|
+
console.error('[SdDocxService] DocX conversion error:', error);
|
|
114
273
|
this.notifyService.error('Có lỗi xảy ra khi chuyển đổi file DOCX');
|
|
115
274
|
return null;
|
|
116
275
|
}
|
|
@@ -123,39 +282,7 @@ class SdDocxService {
|
|
|
123
282
|
const lowerCaseName = fileName.toLowerCase();
|
|
124
283
|
return this.#VALID_EXTENSIONS.some(ext => lowerCaseName.endsWith(ext));
|
|
125
284
|
}
|
|
126
|
-
|
|
127
|
-
return new Promise((resolve, reject) => {
|
|
128
|
-
const reader = new FileReader();
|
|
129
|
-
reader.onload = e => {
|
|
130
|
-
const result = e.target?.result;
|
|
131
|
-
if (result) {
|
|
132
|
-
resolve(result);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
reject(new Error('Failed to read file'));
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
reader.onerror = () => reject(reader.error);
|
|
139
|
-
reader.readAsArrayBuffer(file);
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
#blobToArrayBuffer(blob) {
|
|
143
|
-
return new Promise((resolve, reject) => {
|
|
144
|
-
const reader = new FileReader();
|
|
145
|
-
reader.onload = e => {
|
|
146
|
-
const result = e.target?.result;
|
|
147
|
-
if (result) {
|
|
148
|
-
resolve(result);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
reject(new Error('Failed to read blob'));
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
reader.onerror = () => reject(reader.error);
|
|
155
|
-
reader.readAsArrayBuffer(blob);
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocxService, deps: [{ token: i1.SdNotifyService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
285
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocxService, deps: [{ token: i1.SdNotifyService }, { token: i2.SdLoadingService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
159
286
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocxService, providedIn: 'root' });
|
|
160
287
|
}
|
|
161
288
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocxService, decorators: [{
|
|
@@ -163,7 +290,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
163
290
|
args: [{
|
|
164
291
|
providedIn: 'root',
|
|
165
292
|
}]
|
|
166
|
-
}], ctorParameters: () => [{ type: i1.SdNotifyService }] });
|
|
293
|
+
}], ctorParameters: () => [{ type: i1.SdNotifyService }, { type: i2.SdLoadingService }] });
|
|
167
294
|
|
|
168
295
|
/**
|
|
169
296
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-services-docx.mjs","sources":["../../../projects/sd-angular/services/docx/src/lib/docx.service.ts","../../../projects/sd-angular/services/docx/sd-angular-core-services-docx.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport * as mammoth from 'mammoth';\r\nimport { docxToHtml } from '@omer-go/docx-parser-converter-ts';\r\nimport { SdDocxConvertOptions, SdDocxConvertResult } from './docx.model';\r\nimport { SdNotifyService } from '@sd-angular/core/services/notify';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdDocxService {\r\n readonly #DEFAULT_MAX_SIZE_MB = 50;\r\n readonly #VALID_EXTENSIONS = ['.doc', '.docx'];\r\n\r\n readonly #ERROR_INVALID_FORMAT = 'Định dạng không hợp lệ. Vui lòng chọn Mẫu có định dạng DOC hoặc DOCX';\r\n readonly #ERROR_SIZE_EXCEEDED = 'Kích thước tệp mẫu vượt quá tiêu chuẩn hỗ trợ của hệ thống. Vui lòng thử lại';\r\n\r\n #fileInput: HTMLInputElement | null = null;\r\n\r\n constructor(private notifyService: SdNotifyService) {}\r\n\r\n async open(options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null> {\r\n return new Promise(resolve => {\r\n this.#createFileInput();\r\n if (!this.#fileInput) {\r\n resolve(null);\r\n return;\r\n }\r\n\r\n const handleChange = async (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n const file = input.files?.[0];\r\n\r\n if (!file) {\r\n resolve(null);\r\n return;\r\n }\r\n\r\n const result = await this.convertToHtml(file, options);\r\n resolve(result);\r\n\r\n // Cleanup\r\n input.value = '';\r\n input.removeEventListener('change', handleChange);\r\n };\r\n\r\n this.#fileInput.addEventListener('change', handleChange, { once: true });\r\n this.#fileInput.click();\r\n });\r\n }\r\n\r\n #createFileInput(): void {\r\n if (this.#fileInput) {\r\n return;\r\n }\r\n\r\n this.#fileInput = document.createElement('input');\r\n this.#fileInput.type = 'file';\r\n this.#fileInput.accept = '.doc,.docx';\r\n this.#fileInput.style.display = 'none';\r\n document.body.appendChild(this.#fileInput);\r\n }\r\n\r\n async convertToHtml(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null> {\r\n const opts = {\r\n validateFormat: true,\r\n validateSize: true,\r\n maxSizeInMb: this.#DEFAULT_MAX_SIZE_MB,\r\n ...options,\r\n };\r\n\r\n try {\r\n let fileName: string | undefined;\r\n let fileSize: number | undefined;\r\n let arrayBuffer: ArrayBuffer;\r\n\r\n if (input instanceof File) {\r\n fileName = input.name;\r\n fileSize = input.size;\r\n arrayBuffer = await this.#fileToArrayBuffer(input);\r\n } else if (input instanceof Blob) {\r\n fileSize = input.size;\r\n arrayBuffer = await this.#blobToArrayBuffer(input);\r\n } else {\r\n arrayBuffer = input;\r\n }\r\n\r\n if (opts.validateFormat && fileName) {\r\n if (!this.#isValidFormat(fileName)) {\r\n this.notifyService.error(this.#ERROR_INVALID_FORMAT);\r\n return null;\r\n }\r\n }\r\n\r\n if (opts.validateSize && fileSize !== undefined) {\r\n const maxSizeInBytes = opts.maxSizeInMb! * 1024 * 1024;\r\n if (fileSize > maxSizeInBytes) {\r\n this.notifyService.error(this.#ERROR_SIZE_EXCEEDED);\r\n return null;\r\n }\r\n }\r\n\r\n const { validateFormat, validateSize, maxSizeInMb, ...conversionOptions } = opts;\r\n\r\n // Try @omer-go first for better formatting, fallback to mammoth on BOM error\r\n let html: string;\r\n let messages: string[] = [];\r\n try {\r\n html = await docxToHtml(arrayBuffer, {\r\n styleMode: 'inline',\r\n useSemanticTags: true,\r\n fragmentOnly: true,\r\n ...conversionOptions,\r\n });\r\n } catch (omerError: any) {\r\n console.log(omerError);\r\n // Fallback to mammoth if @omer-go fails (e.g., BOM issue)\r\n console.warn('@omer-go/docx-parser-converter-ts failed, falling back to mammoth:', omerError?.message);\r\n const result = await mammoth.convertToHtml({ arrayBuffer }, conversionOptions as any);\r\n html = result.value;\r\n messages = result.messages.map(m => m.toString());\r\n }\r\n\r\n return {\r\n html,\r\n messages,\r\n };\r\n } catch (error) {\r\n console.error('DocX conversion error:', error);\r\n this.notifyService.error('Có lỗi xảy ra khi chuyển đổi file DOCX');\r\n return null;\r\n }\r\n }\r\n\r\n async convertToHtmlString(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<string | null> {\r\n const result = await this.convertToHtml(input, options);\r\n return result?.html ?? null;\r\n }\r\n\r\n #isValidFormat(fileName: string): boolean {\r\n const lowerCaseName = fileName.toLowerCase();\r\n return this.#VALID_EXTENSIONS.some(ext => lowerCaseName.endsWith(ext));\r\n }\r\n\r\n #fileToArrayBuffer(file: File): Promise<ArrayBuffer> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = e => {\r\n const result = e.target?.result as ArrayBuffer;\r\n if (result) {\r\n resolve(result);\r\n } else {\r\n reject(new Error('Failed to read file'));\r\n }\r\n };\r\n reader.onerror = () => reject(reader.error);\r\n reader.readAsArrayBuffer(file);\r\n });\r\n }\r\n\r\n #blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = e => {\r\n const result = e.target?.result as ArrayBuffer;\r\n if (result) {\r\n resolve(result);\r\n } else {\r\n reject(new Error('Failed to read blob'));\r\n }\r\n };\r\n reader.onerror = () => reject(reader.error);\r\n reader.readAsArrayBuffer(blob);\r\n });\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sd-angular-core-services-docx.mjs","sources":["../../../projects/sd-angular/services/docx/src/lib/pandoc-core.ts","../../../projects/sd-angular/services/docx/src/lib/docx.service.ts","../../../projects/sd-angular/services/docx/sd-angular-core-services-docx.ts"],"sourcesContent":["/* Pandoc WASM core logic — adapted from pandoc-wasm/src/core.js\r\n *\r\n * This file is a local copy of the environment-agnostic pandoc core.\r\n * It imports @bjorn3/browser_wasi_shim directly, avoiding the pandoc-wasm\r\n * package entry points which use top-level await (incompatible with\r\n * Angular's esbuild/Vite build pipeline).\r\n *\r\n * Source: https://github.com/pandoc/pandoc-wasm (GPL-2.0-or-later)\r\n */\r\n\r\n// @ts-nocheck\r\nimport {\r\n ConsoleStdout,\r\n File,\r\n OpenFile,\r\n PreopenDirectory,\r\n WASI,\r\n} from '@bjorn3/browser_wasi_shim';\r\n\r\nexport interface PandocConvertResult {\r\n stdout: string;\r\n stderr: string;\r\n warnings: any[];\r\n files: Record<string, any>;\r\n mediaFiles: Record<string, any>;\r\n}\r\n\r\nexport interface PandocInstance {\r\n convert(\r\n options: Record<string, any>,\r\n stdin: string | null,\r\n files: Record<string, Blob | string>\r\n ): Promise<PandocConvertResult>;\r\n}\r\n\r\nexport function createPandocInstance(wasmBinary: ArrayBuffer): Promise<PandocInstance> {\r\n const args = ['pandoc.wasm', '+RTS', '-H64m', '-RTS'];\r\n const env: string[] = [];\r\n const fileSystem = new Map();\r\n const fds = [\r\n new OpenFile(new File(new Uint8Array(), { readonly: true })),\r\n ConsoleStdout.lineBuffered((msg: string) => console.log(`[WASI stdout] ${msg}`)),\r\n ConsoleStdout.lineBuffered((msg: string) => console.warn(`[WASI stderr] ${msg}`)),\r\n new PreopenDirectory('/', fileSystem),\r\n ];\r\n const options = { debug: false };\r\n const wasi = new WASI(args, env, fds, options);\r\n\r\n return WebAssembly.instantiate(wasmBinary, {\r\n wasi_snapshot_preview1: wasi.wasiImport,\r\n }).then(({ instance }: any) => {\r\n wasi.initialize(instance);\r\n instance.exports.__wasm_call_ctors();\r\n\r\n function memory_data_view() {\r\n return new DataView(instance.exports.memory.buffer);\r\n }\r\n\r\n const argc_ptr = instance.exports.malloc(4);\r\n memory_data_view().setUint32(argc_ptr, args.length, true);\r\n const argv = instance.exports.malloc(4 * (args.length + 1));\r\n for (let i = 0; i < args.length; ++i) {\r\n const arg = instance.exports.malloc(args[i].length + 1);\r\n new TextEncoder().encodeInto(\r\n args[i],\r\n new Uint8Array(instance.exports.memory.buffer, arg, args[i].length)\r\n );\r\n memory_data_view().setUint8(arg + args[i].length, 0);\r\n memory_data_view().setUint32(argv + 4 * i, arg, true);\r\n }\r\n memory_data_view().setUint32(argv + 4 * args.length, 0, true);\r\n const argv_ptr = instance.exports.malloc(4);\r\n memory_data_view().setUint32(argv_ptr, argv, true);\r\n\r\n instance.exports.hs_init_with_rtsopts(argc_ptr, argv_ptr);\r\n\r\n async function addFile(filename: string, data: Blob | string, readonly: boolean) {\r\n let uint8Array: Uint8Array;\r\n if (typeof data === 'string') {\r\n uint8Array = new TextEncoder().encode(data);\r\n } else {\r\n const buffer = await data.arrayBuffer();\r\n uint8Array = new Uint8Array(buffer);\r\n }\r\n const file = new File(uint8Array, { readonly });\r\n fileSystem.set(filename, file);\r\n }\r\n\r\n async function convert(\r\n options: Record<string, any>,\r\n stdin: string | null,\r\n files: Record<string, Blob | string>\r\n ): Promise<PandocConvertResult> {\r\n const opts_str = JSON.stringify(options);\r\n const encoded = new TextEncoder().encode(opts_str);\r\n const opts_ptr = instance.exports.malloc(encoded.length);\r\n new TextEncoder().encodeInto(\r\n opts_str,\r\n new Uint8Array(instance.exports.memory.buffer, opts_ptr, encoded.length)\r\n );\r\n\r\n files = { ...files };\r\n\r\n fileSystem.clear();\r\n const in_file = new File(new Uint8Array(), { readonly: true });\r\n const out_file = new File(new Uint8Array(), { readonly: false });\r\n const err_file = new File(new Uint8Array(), { readonly: false });\r\n const warnings_file = new File(new Uint8Array(), { readonly: false });\r\n fileSystem.set('stdin', in_file);\r\n fileSystem.set('stdout', out_file);\r\n fileSystem.set('stderr', err_file);\r\n fileSystem.set('warnings', warnings_file);\r\n\r\n const knownFiles = new Set(['stdin', 'stdout', 'stderr', 'warnings']);\r\n\r\n for (const filename in files) {\r\n await addFile(filename, files[filename], true);\r\n knownFiles.add(filename);\r\n }\r\n\r\n const outputFileName = options['output-file'] || null;\r\n const extractMediaPath = options['extract-media'] || null;\r\n\r\n if (outputFileName) {\r\n await addFile(outputFileName, new Blob(), false);\r\n knownFiles.add(outputFileName);\r\n }\r\n\r\n if (extractMediaPath) {\r\n await addFile(extractMediaPath, new Blob(), false);\r\n if (extractMediaPath.endsWith('.zip')) {\r\n knownFiles.add(extractMediaPath);\r\n }\r\n }\r\n\r\n if (stdin) {\r\n in_file.data = new TextEncoder().encode(stdin);\r\n }\r\n\r\n instance.exports.convert(opts_ptr, encoded.length);\r\n\r\n if (options['output-file']) {\r\n const outputFile = fileSystem.get(options['output-file']);\r\n if (outputFile && outputFile.data && outputFile.data.length > 0) {\r\n files[options['output-file']] = new Blob([outputFile.data]);\r\n }\r\n }\r\n\r\n if (options['extract-media']) {\r\n const mediaFile = fileSystem.get(options['extract-media']);\r\n if (mediaFile && mediaFile.data && mediaFile.data.length > 0) {\r\n files[options['extract-media']] = new Blob([mediaFile.data], { type: 'application/zip' });\r\n }\r\n }\r\n\r\n const mediaFiles: Record<string, Blob> = {};\r\n for (const [name, fileData] of fileSystem.entries()) {\r\n if (!knownFiles.has(name) && fileData && fileData.data && fileData.data.length > 0) {\r\n const blob = new Blob([fileData.data]);\r\n files[name] = blob;\r\n if (name !== outputFileName && name !== extractMediaPath) {\r\n mediaFiles[name] = blob;\r\n }\r\n }\r\n }\r\n\r\n const rawWarnings = new TextDecoder('utf-8', { fatal: true }).decode(warnings_file.data);\r\n let warnings: any[] = [];\r\n if (rawWarnings) {\r\n try {\r\n warnings = JSON.parse(rawWarnings);\r\n } catch (e) {\r\n console.warn('Failed to parse warnings:', e);\r\n }\r\n }\r\n\r\n return {\r\n stdout: new TextDecoder('utf-8', { fatal: true }).decode(out_file.data),\r\n stderr: new TextDecoder('utf-8', { fatal: true }).decode(err_file.data),\r\n warnings,\r\n files,\r\n mediaFiles,\r\n };\r\n }\r\n\r\n return { convert } as PandocInstance;\r\n });\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { SdNotifyService } from '@sd-angular/core/services/notify';\r\nimport { SdLoadingService } from '@sd-angular/core/services/loading';\r\n\r\nimport { SdDocxConvertOptions, SdDocxConvertResult } from './docx.model';\r\nimport { createPandocInstance, PandocInstance } from './pandoc-core';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdDocxService {\r\n readonly #DEFAULT_MAX_SIZE_MB = 50;\r\n readonly #VALID_EXTENSIONS = ['.doc', '.docx'];\r\n\r\n readonly #ERROR_INVALID_FORMAT = 'Định dạng không hợp lệ. Vui lòng chọn Mẫu có định dạng DOC hoặc DOCX';\r\n readonly #ERROR_SIZE_EXCEEDED = 'Kích thước tệp mẫu vượt quá tiêu chuẩn hỗ trợ của hệ thống. Vui lòng thử lại';\r\n\r\n readonly #PANDOC_WASM_URL = 'https://pandoc.github.io/pandoc-wasm/pandoc.wasm';\r\n\r\n #fileInput: HTMLInputElement | null = null;\r\n #pandocInstance: PandocInstance | null = null;\r\n\r\n constructor(\r\n private notifyService: SdNotifyService,\r\n private loadingService: SdLoadingService\r\n ) {}\r\n\r\n async open(options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null> {\r\n return new Promise(resolve => {\r\n this.#createFileInput();\r\n if (!this.#fileInput) {\r\n resolve(null);\r\n return;\r\n }\r\n\r\n const handleChange = async (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n const file = input.files?.[0];\r\n\r\n if (!file) {\r\n resolve(null);\r\n return;\r\n }\r\n\r\n this.loadingService.start();\r\n try {\r\n const result = await this.convertToHtml(file, options);\r\n resolve(result);\r\n } catch (error) {\r\n console.error('[SdDocxService] DocX conversion error:', error);\r\n this.notifyService.error('Có lỗi xảy ra khi chuyển đổi file DOCX');\r\n resolve(null);\r\n } finally {\r\n input.value = '';\r\n input.removeEventListener('change', handleChange);\r\n this.loadingService.stop();\r\n }\r\n };\r\n\r\n this.#fileInput.addEventListener('change', handleChange, { once: true });\r\n this.#fileInput.click();\r\n });\r\n }\r\n\r\n #createFileInput(): void {\r\n if (this.#fileInput) {\r\n return;\r\n }\r\n\r\n this.#fileInput = document.createElement('input');\r\n this.#fileInput.type = 'file';\r\n this.#fileInput.accept = '.doc,.docx';\r\n this.#fileInput.style.display = 'none';\r\n document.body.appendChild(this.#fileInput);\r\n }\r\n\r\n async #getPandocInstance(): Promise<PandocInstance> {\r\n if (this.#pandocInstance) {\r\n return this.#pandocInstance;\r\n }\r\n\r\n console.log('[SdDocxService] Fetching WASM binary from:', this.#PANDOC_WASM_URL);\r\n const wasmResponse = await fetch(this.#PANDOC_WASM_URL);\r\n if (!wasmResponse.ok) {\r\n throw new Error(`Failed to fetch pandoc.wasm: ${wasmResponse.status} ${wasmResponse.statusText}`);\r\n }\r\n console.log('[SdDocxService] WASM fetched, size:', wasmResponse.headers.get('content-length'));\r\n const wasmBinary = await wasmResponse.arrayBuffer();\r\n console.log('[SdDocxService] WASM binary loaded, bytes:', wasmBinary.byteLength);\r\n this.#pandocInstance = await createPandocInstance(wasmBinary);\r\n console.log('[SdDocxService] Pandoc instance created successfully');\r\n return this.#pandocInstance;\r\n }\r\n\r\n async convertToHtml(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null> {\r\n const opts = {\r\n validateFormat: true,\r\n validateSize: true,\r\n maxSizeInMb: this.#DEFAULT_MAX_SIZE_MB,\r\n ...options,\r\n };\r\n\r\n try {\r\n let fileName: string | undefined;\r\n let fileSize: number | undefined;\r\n let blob: Blob;\r\n\r\n if (input instanceof File) {\r\n fileName = input.name;\r\n fileSize = input.size;\r\n blob = input;\r\n } else if (input instanceof Blob) {\r\n fileSize = input.size;\r\n blob = input;\r\n } else {\r\n blob = new Blob([input], {\r\n type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n });\r\n }\r\n\r\n if (opts.validateFormat && fileName) {\r\n if (!this.#isValidFormat(fileName)) {\r\n this.notifyService.error(this.#ERROR_INVALID_FORMAT);\r\n return null;\r\n }\r\n }\r\n\r\n if (opts.validateSize && fileSize !== undefined) {\r\n const maxSizeInBytes = opts.maxSizeInMb! * 1024 * 1024;\r\n if (fileSize > maxSizeInBytes) {\r\n this.notifyService.error(this.#ERROR_SIZE_EXCEEDED);\r\n return null;\r\n }\r\n }\r\n\r\n console.log('[SdDocxService] Getting pandoc instance...');\r\n const pandoc = await this.#getPandocInstance();\r\n console.log('[SdDocxService] Converting DOCX, blob size:', blob.size);\r\n\r\n const pandocOpts: Record<string, any> = {\r\n from: 'docx',\r\n to: 'html',\r\n 'input-files': ['document.docx'],\r\n standalone: true,\r\n 'embed-resources': true,\r\n };\r\n\r\n const result = await pandoc.convert(pandocOpts, null, { 'document.docx': blob });\r\n console.log('[SdDocxService] Conversion done, stdout length:', result.stdout?.length, 'stderr:', result.stderr);\r\n\r\n return {\r\n html: result.stdout,\r\n messages: result.warnings.map((w: any) => String(w)),\r\n };\r\n } catch (error) {\r\n console.error('[SdDocxService] DocX conversion error:', error);\r\n this.notifyService.error('Có lỗi xảy ra khi chuyển đổi file DOCX');\r\n return null;\r\n }\r\n }\r\n\r\n async convertToHtmlString(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<string | null> {\r\n const result = await this.convertToHtml(input, options);\r\n return result?.html ?? null;\r\n }\r\n\r\n #isValidFormat(fileName: string): boolean {\r\n const lowerCaseName = fileName.toLowerCase();\r\n return this.#VALID_EXTENSIONS.some(ext => lowerCaseName.endsWith(ext));\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["File"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-angular/core",
|
|
3
|
-
"version": "19.0.0-beta.
|
|
3
|
+
"version": "19.0.0-beta.83",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
6
6
|
"@angular/core": "^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
"types": "./index.d.ts",
|
|
32
32
|
"default": "./fesm2022/sd-angular-core.mjs"
|
|
33
33
|
},
|
|
34
|
+
"./components": {
|
|
35
|
+
"types": "./components/index.d.ts",
|
|
36
|
+
"default": "./fesm2022/sd-angular-core-components.mjs"
|
|
37
|
+
},
|
|
34
38
|
"./configurations": {
|
|
35
39
|
"types": "./configurations/index.d.ts",
|
|
36
40
|
"default": "./fesm2022/sd-angular-core-configurations.mjs"
|
|
@@ -39,18 +43,14 @@
|
|
|
39
43
|
"types": "./directives/index.d.ts",
|
|
40
44
|
"default": "./fesm2022/sd-angular-core-directives.mjs"
|
|
41
45
|
},
|
|
42
|
-
"./
|
|
43
|
-
"types": "./
|
|
44
|
-
"default": "./fesm2022/sd-angular-core-
|
|
46
|
+
"./handlers": {
|
|
47
|
+
"types": "./handlers/index.d.ts",
|
|
48
|
+
"default": "./fesm2022/sd-angular-core-handlers.mjs"
|
|
45
49
|
},
|
|
46
50
|
"./forms": {
|
|
47
51
|
"types": "./forms/index.d.ts",
|
|
48
52
|
"default": "./fesm2022/sd-angular-core-forms.mjs"
|
|
49
53
|
},
|
|
50
|
-
"./handlers": {
|
|
51
|
-
"types": "./handlers/index.d.ts",
|
|
52
|
-
"default": "./fesm2022/sd-angular-core-handlers.mjs"
|
|
53
|
-
},
|
|
54
54
|
"./interceptors": {
|
|
55
55
|
"types": "./interceptors/index.d.ts",
|
|
56
56
|
"default": "./fesm2022/sd-angular-core-interceptors.mjs"
|
|
@@ -75,13 +75,17 @@
|
|
|
75
75
|
"types": "./components/anchor/index.d.ts",
|
|
76
76
|
"default": "./fesm2022/sd-angular-core-components-anchor.mjs"
|
|
77
77
|
},
|
|
78
|
+
"./components/anchor-v2": {
|
|
79
|
+
"types": "./components/anchor-v2/index.d.ts",
|
|
80
|
+
"default": "./fesm2022/sd-angular-core-components-anchor-v2.mjs"
|
|
81
|
+
},
|
|
78
82
|
"./components/avatar": {
|
|
79
83
|
"types": "./components/avatar/index.d.ts",
|
|
80
84
|
"default": "./fesm2022/sd-angular-core-components-avatar.mjs"
|
|
81
85
|
},
|
|
82
|
-
"./components/
|
|
83
|
-
"types": "./components/
|
|
84
|
-
"default": "./fesm2022/sd-angular-core-components-
|
|
86
|
+
"./components/base": {
|
|
87
|
+
"types": "./components/base/index.d.ts",
|
|
88
|
+
"default": "./fesm2022/sd-angular-core-components-base.mjs"
|
|
85
89
|
},
|
|
86
90
|
"./components/badge": {
|
|
87
91
|
"types": "./components/badge/index.d.ts",
|
|
@@ -91,10 +95,6 @@
|
|
|
91
95
|
"types": "./components/button/index.d.ts",
|
|
92
96
|
"default": "./fesm2022/sd-angular-core-components-button.mjs"
|
|
93
97
|
},
|
|
94
|
-
"./components/base": {
|
|
95
|
-
"types": "./components/base/index.d.ts",
|
|
96
|
-
"default": "./fesm2022/sd-angular-core-components-base.mjs"
|
|
97
|
-
},
|
|
98
98
|
"./components/chart": {
|
|
99
99
|
"types": "./components/chart/index.d.ts",
|
|
100
100
|
"default": "./fesm2022/sd-angular-core-components-chart.mjs"
|
|
@@ -111,6 +111,10 @@
|
|
|
111
111
|
"types": "./components/editor/index.d.ts",
|
|
112
112
|
"default": "./fesm2022/sd-angular-core-components-editor.mjs"
|
|
113
113
|
},
|
|
114
|
+
"./components/modal": {
|
|
115
|
+
"types": "./components/modal/index.d.ts",
|
|
116
|
+
"default": "./fesm2022/sd-angular-core-components-modal.mjs"
|
|
117
|
+
},
|
|
114
118
|
"./components/history": {
|
|
115
119
|
"types": "./components/history/index.d.ts",
|
|
116
120
|
"default": "./fesm2022/sd-angular-core-components-history.mjs"
|
|
@@ -123,10 +127,6 @@
|
|
|
123
127
|
"types": "./components/mini-editor/index.d.ts",
|
|
124
128
|
"default": "./fesm2022/sd-angular-core-components-mini-editor.mjs"
|
|
125
129
|
},
|
|
126
|
-
"./components/modal": {
|
|
127
|
-
"types": "./components/modal/index.d.ts",
|
|
128
|
-
"default": "./fesm2022/sd-angular-core-components-modal.mjs"
|
|
129
|
-
},
|
|
130
130
|
"./components/preview": {
|
|
131
131
|
"types": "./components/preview/index.d.ts",
|
|
132
132
|
"default": "./fesm2022/sd-angular-core-components-preview.mjs"
|
|
@@ -143,6 +143,10 @@
|
|
|
143
143
|
"types": "./components/section/index.d.ts",
|
|
144
144
|
"default": "./fesm2022/sd-angular-core-components-section.mjs"
|
|
145
145
|
},
|
|
146
|
+
"./components/tab-router": {
|
|
147
|
+
"types": "./components/tab-router/index.d.ts",
|
|
148
|
+
"default": "./fesm2022/sd-angular-core-components-tab-router.mjs"
|
|
149
|
+
},
|
|
146
150
|
"./components/side-drawer": {
|
|
147
151
|
"types": "./components/side-drawer/index.d.ts",
|
|
148
152
|
"default": "./fesm2022/sd-angular-core-components-side-drawer.mjs"
|
|
@@ -155,22 +159,18 @@
|
|
|
155
159
|
"types": "./components/view/index.d.ts",
|
|
156
160
|
"default": "./fesm2022/sd-angular-core-components-view.mjs"
|
|
157
161
|
},
|
|
158
|
-
"./forms/autocomplete": {
|
|
159
|
-
"types": "./forms/autocomplete/index.d.ts",
|
|
160
|
-
"default": "./fesm2022/sd-angular-core-forms-autocomplete.mjs"
|
|
161
|
-
},
|
|
162
162
|
"./components/workflow": {
|
|
163
163
|
"types": "./components/workflow/index.d.ts",
|
|
164
164
|
"default": "./fesm2022/sd-angular-core-components-workflow.mjs"
|
|
165
165
|
},
|
|
166
|
-
"./components/upload-file": {
|
|
167
|
-
"types": "./components/upload-file/index.d.ts",
|
|
168
|
-
"default": "./fesm2022/sd-angular-core-components-upload-file.mjs"
|
|
169
|
-
},
|
|
170
166
|
"./forms/checkbox": {
|
|
171
167
|
"types": "./forms/checkbox/index.d.ts",
|
|
172
168
|
"default": "./fesm2022/sd-angular-core-forms-checkbox.mjs"
|
|
173
169
|
},
|
|
170
|
+
"./forms/autocomplete": {
|
|
171
|
+
"types": "./forms/autocomplete/index.d.ts",
|
|
172
|
+
"default": "./fesm2022/sd-angular-core-forms-autocomplete.mjs"
|
|
173
|
+
},
|
|
174
174
|
"./forms/chip": {
|
|
175
175
|
"types": "./forms/chip/index.d.ts",
|
|
176
176
|
"default": "./fesm2022/sd-angular-core-forms-chip.mjs"
|
|
@@ -187,10 +187,6 @@
|
|
|
187
187
|
"types": "./forms/date-range/index.d.ts",
|
|
188
188
|
"default": "./fesm2022/sd-angular-core-forms-date-range.mjs"
|
|
189
189
|
},
|
|
190
|
-
"./forms/input": {
|
|
191
|
-
"types": "./forms/input/index.d.ts",
|
|
192
|
-
"default": "./fesm2022/sd-angular-core-forms-input.mjs"
|
|
193
|
-
},
|
|
194
190
|
"./forms/directives": {
|
|
195
191
|
"types": "./forms/directives/index.d.ts",
|
|
196
192
|
"default": "./fesm2022/sd-angular-core-forms-directives.mjs"
|
|
@@ -203,6 +199,10 @@
|
|
|
203
199
|
"types": "./forms/input-number/index.d.ts",
|
|
204
200
|
"default": "./fesm2022/sd-angular-core-forms-input-number.mjs"
|
|
205
201
|
},
|
|
202
|
+
"./forms/input": {
|
|
203
|
+
"types": "./forms/input/index.d.ts",
|
|
204
|
+
"default": "./fesm2022/sd-angular-core-forms-input.mjs"
|
|
205
|
+
},
|
|
206
206
|
"./forms/label": {
|
|
207
207
|
"types": "./forms/label/index.d.ts",
|
|
208
208
|
"default": "./fesm2022/sd-angular-core-forms-label.mjs"
|
|
@@ -235,14 +235,14 @@
|
|
|
235
235
|
"types": "./modules/authom/index.d.ts",
|
|
236
236
|
"default": "./fesm2022/sd-angular-core-modules-authom.mjs"
|
|
237
237
|
},
|
|
238
|
-
"./modules/keycloak": {
|
|
239
|
-
"types": "./modules/keycloak/index.d.ts",
|
|
240
|
-
"default": "./fesm2022/sd-angular-core-modules-keycloak.mjs"
|
|
241
|
-
},
|
|
242
238
|
"./modules/layout": {
|
|
243
239
|
"types": "./modules/layout/index.d.ts",
|
|
244
240
|
"default": "./fesm2022/sd-angular-core-modules-layout.mjs"
|
|
245
241
|
},
|
|
242
|
+
"./modules/keycloak": {
|
|
243
|
+
"types": "./modules/keycloak/index.d.ts",
|
|
244
|
+
"default": "./fesm2022/sd-angular-core-modules-keycloak.mjs"
|
|
245
|
+
},
|
|
246
246
|
"./modules/permission": {
|
|
247
247
|
"types": "./modules/permission/index.d.ts",
|
|
248
248
|
"default": "./fesm2022/sd-angular-core-modules-permission.mjs"
|
|
@@ -279,14 +279,14 @@
|
|
|
279
279
|
"types": "./services/loading/index.d.ts",
|
|
280
280
|
"default": "./fesm2022/sd-angular-core-services-loading.mjs"
|
|
281
281
|
},
|
|
282
|
-
"./services/storage": {
|
|
283
|
-
"types": "./services/storage/index.d.ts",
|
|
284
|
-
"default": "./fesm2022/sd-angular-core-services-storage.mjs"
|
|
285
|
-
},
|
|
286
282
|
"./services/notify": {
|
|
287
283
|
"types": "./services/notify/index.d.ts",
|
|
288
284
|
"default": "./fesm2022/sd-angular-core-services-notify.mjs"
|
|
289
285
|
},
|
|
286
|
+
"./services/storage": {
|
|
287
|
+
"types": "./services/storage/index.d.ts",
|
|
288
|
+
"default": "./fesm2022/sd-angular-core-services-storage.mjs"
|
|
289
|
+
},
|
|
290
290
|
"./utilities/extensions": {
|
|
291
291
|
"types": "./utilities/extensions/index.d.ts",
|
|
292
292
|
"default": "./fesm2022/sd-angular-core-utilities-extensions.mjs"
|
|
@@ -295,9 +295,9 @@
|
|
|
295
295
|
"types": "./utilities/models/index.d.ts",
|
|
296
296
|
"default": "./fesm2022/sd-angular-core-utilities-models.mjs"
|
|
297
297
|
},
|
|
298
|
-
"./components/
|
|
299
|
-
"types": "./components/
|
|
300
|
-
"default": "./fesm2022/sd-angular-core-components-
|
|
298
|
+
"./components/upload-file": {
|
|
299
|
+
"types": "./components/upload-file/index.d.ts",
|
|
300
|
+
"default": "./fesm2022/sd-angular-core-components-upload-file.mjs"
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
303
|
}
|
|
Binary file
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { SdDocxConvertOptions, SdDocxConvertResult } from './docx.model';
|
|
2
1
|
import { SdNotifyService } from '@sd-angular/core/services/notify';
|
|
2
|
+
import { SdLoadingService } from '@sd-angular/core/services/loading';
|
|
3
|
+
import { SdDocxConvertOptions, SdDocxConvertResult } from './docx.model';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
export declare class SdDocxService {
|
|
5
6
|
#private;
|
|
6
7
|
private notifyService;
|
|
7
|
-
|
|
8
|
+
private loadingService;
|
|
9
|
+
constructor(notifyService: SdNotifyService, loadingService: SdLoadingService);
|
|
8
10
|
open(options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null>;
|
|
9
11
|
convertToHtml(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null>;
|
|
10
12
|
convertToHtmlString(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<string | null>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PandocConvertResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
warnings: any[];
|
|
5
|
+
files: Record<string, any>;
|
|
6
|
+
mediaFiles: Record<string, any>;
|
|
7
|
+
}
|
|
8
|
+
export interface PandocInstance {
|
|
9
|
+
convert(options: Record<string, any>, stdin: string | null, files: Record<string, Blob | string>): Promise<PandocConvertResult>;
|
|
10
|
+
}
|
|
11
|
+
export declare function createPandocInstance(wasmBinary: ArrayBuffer): Promise<PandocInstance>;
|
|
Binary file
|