ng2-pdfjs-viewer 25.0.11 → 25.0.13

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/README.md CHANGED
@@ -219,16 +219,32 @@ Add PDF.js assets to your `angular.json`:
219
219
 
220
220
  #### Nginx Configuration
221
221
 
222
- For production deployments using nginx, you may need to configure MIME types for PDF.js ES modules (`.mjs` files):
222
+ For production deployments using nginx, configure MIME types for PDF.js ES modules:
223
223
 
224
224
  ```nginx
225
225
  # Add to your nginx.conf or site configuration
226
226
  types {
227
227
  application/javascript js mjs;
228
+ text/plain ftl;
228
229
  }
229
230
  ```
230
231
 
231
- **Why this is needed**: PDF.js v5+ uses `.mjs` files (ES modules). Without proper MIME type configuration, nginx serves these files with incorrect content-type headers, causing the PDF viewer to crash during loading in production environments.
232
+ #### IIS Configuration (Windows Server)
233
+
234
+ For production deployments using IIS, add to your `web.config`:
235
+
236
+ ```xml
237
+ <configuration>
238
+ <system.webServer>
239
+ <staticContent>
240
+ <mimeMap fileExtension=".mjs" mimeType="application/javascript" />
241
+ <mimeMap fileExtension=".ftl" mimeType="text/plain" />
242
+ </staticContent>
243
+ </system.webServer>
244
+ </configuration>
245
+ ```
246
+
247
+ **Why this is needed**: PDF.js v5+ uses `.mjs` files (ES modules) and `.ftl` files (localization). Without proper MIME type configuration, web servers serve these files with incorrect content-type headers, causing the PDF viewer to crash during loading in production environments.
232
248
 
233
249
  ### Angular Version Support
234
250
 
@@ -923,6 +939,18 @@ This project is licensed under the **Apache License 2.0 + Commons Clause License
923
939
  <div align="center">
924
940
 
925
941
 
942
+ ## 🔒 Security
943
+
944
+ I take security of this library seriously. If you discover a security vulnerability, please report it privately:
945
+
946
+ - **🔒 Private Reporting**: [Security Policy](https://github.com/intbot/ng2-pdfjs-viewer/security/policy)
947
+ - **📧 Email**: [codehippie1@gmail.com](mailto:codehippie1@gmail.com)
948
+ - **⚠️ Please do NOT** report security issues through public GitHub issues
949
+
950
+ For security best practices and vulnerability reporting guidelines, see our [Security Policy](https://github.com/intbot/ng2-pdfjs-viewer/security/policy).
951
+
952
+ ---
953
+
926
954
  [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue?logo=github)](https://github.com/intbot/ng2-pdfjs-viewer)
927
955
  [![NPM](https://img.shields.io/badge/NPM-Package-red?logo=npm)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
928
956
  [![Angular](https://img.shields.io/badge/Angular-Component-green?logo=angular)](https://angular.dev/overview)
@@ -477,6 +477,15 @@ class PdfJsViewerComponent {
477
477
  ...this.errorTemplateData,
478
478
  };
479
479
  }
480
+ // Helper method to get iframe CSS classes
481
+ getIframeClasses() {
482
+ const classes = ['ng2-pdfjs-viewer-iframe'];
483
+ // Add border class if iframeBorder is set and not "0"
484
+ if (this.iframeBorder && this.iframeBorder !== "0" && this.iframeBorder !== 0) {
485
+ classes.push('has-border');
486
+ }
487
+ return classes.join(' ');
488
+ }
480
489
  // Error template button actions
481
490
  reloadViewer() {
482
491
  this.refresh();
@@ -1885,15 +1894,12 @@ class PdfJsViewerComponent {
1885
1894
  }
1886
1895
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: PdfJsViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1887
1896
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.6", type: PdfJsViewerComponent, isStandalone: false, selector: "ng2-pdfjs-viewer", inputs: { viewerId: "viewerId", viewerFolder: "viewerFolder", externalWindow: "externalWindow", target: "target", showSpinner: "showSpinner", downloadFileName: "downloadFileName", locale: "locale", useOnlyCssZoom: "useOnlyCssZoom", diagnosticLogs: "diagnosticLogs", showOpenFile: "showOpenFile", showAnnotations: "showAnnotations", showDownload: "showDownload", showViewBookmark: "showViewBookmark", showPrint: "showPrint", showFullScreen: "showFullScreen", showFind: "showFind", downloadOnLoad: "downloadOnLoad", printOnLoad: "printOnLoad", rotateCW: "rotateCW", rotateCCW: "rotateCCW", showLastPageOnLoad: "showLastPageOnLoad", namedDest: "namedDest", errorOverride: "errorOverride", errorAppend: "errorAppend", errorMessage: "errorMessage", urlValidation: "urlValidation", customSecurityTpl: "customSecurityTpl", theme: "theme", primaryColor: "primaryColor", backgroundColor: "backgroundColor", pageBorderColor: "pageBorderColor", pageSpacing: "pageSpacing", toolbarColor: "toolbarColor", textColor: "textColor", borderRadius: "borderRadius", customCSS: "customCSS", cspNonce: "cspNonce", iframeTitle: "iframeTitle", customSpinnerTpl: "customSpinnerTpl", spinnerClass: "spinnerClass", customErrorTpl: "customErrorTpl", errorClass: "errorClass", showToolbarLeft: "showToolbarLeft", showToolbarMiddle: "showToolbarMiddle", showToolbarRight: "showToolbarRight", showSecondaryToolbarToggle: "showSecondaryToolbarToggle", showSidebar: "showSidebar", showSidebarLeft: "showSidebarLeft", showSidebarRight: "showSidebarRight", toolbarDensity: "toolbarDensity", sidebarWidth: "sidebarWidth", toolbarPosition: "toolbarPosition", sidebarPosition: "sidebarPosition", responsiveBreakpoint: "responsiveBreakpoint", controlVisibility: "controlVisibility", autoActions: "autoActions", errorHandling: "errorHandling", viewerConfig: "viewerConfig", themeConfig: "themeConfig", groupVisibility: "groupVisibility", layoutConfig: "layoutConfig", startDownload: "startDownload", startPrint: "startPrint", openFile: "openFile", download: "download", print: "print", fullScreen: "fullScreen", find: "find", viewBookmark: "viewBookmark", lastPage: "lastPage", externalWindowOptions: "externalWindowOptions", iframeBorder: "iframeBorder", zoom: "zoom", rotation: "rotation", cursor: "cursor", scroll: "scroll", spread: "spread", pageMode: "pageMode", page: "page", pdfSrc: "pdfSrc" }, outputs: { onBeforePrint: "onBeforePrint", onAfterPrint: "onAfterPrint", onDocumentLoad: "onDocumentLoad", onPageChange: "onPageChange", onScaleChange: "onScaleChange", onRotationChange: "onRotationChange", onDocumentError: "onDocumentError", onDocumentInit: "onDocumentInit", onPagesInit: "onPagesInit", onPresentationModeChanged: "onPresentationModeChanged", onOpenFile: "onOpenFile", onFind: "onFind", onUpdateFindMatchesCount: "onUpdateFindMatchesCount", onMetadataLoaded: "onMetadataLoaded", onOutlineLoaded: "onOutlineLoaded", onPageRendered: "onPageRendered", onAnnotationLayerRendered: "onAnnotationLayerRendered", onBookmarkClick: "onBookmarkClick", onIdle: "onIdle", zoomChange: "zoomChange", cursorChange: "cursorChange", scrollChange: "scrollChange", spreadChange: "spreadChange", pageModeChange: "pageModeChange" }, viewQueries: [{ propertyName: "iframe", first: true, predicate: ["iframe"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `
1888
- <div
1889
- class="ng2-pdfjs-viewer-container"
1890
- style="position:relative;width:100%;height:100%;"
1891
- >
1897
+ <div class="ng2-pdfjs-viewer-container">
1892
1898
  <iframe
1893
1899
  [title]="iframeTitle || 'PDF document viewer'"
1894
1900
  [hidden]="externalWindow || (!externalWindow && !pdfSrc)"
1895
1901
  sandbox="allow-forms allow-scripts allow-same-origin allow-modals"
1896
- [style.border]="iframeBorder"
1902
+ [class]="getIframeClasses()"
1897
1903
  #iframe
1898
1904
  width="100%"
1899
1905
  height="100%"
@@ -1903,18 +1909,15 @@ class PdfJsViewerComponent {
1903
1909
  class="ng2-pdfjs-loading-overlay"
1904
1910
  *ngIf="showSpinner && isLoading && !externalWindow"
1905
1911
  [ngClass]="spinnerClass"
1906
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.6);backdrop-filter:saturate(120%) blur(1px);"
1907
1912
  >
1908
1913
  <ng-container
1909
1914
  *ngIf="customSpinnerTpl; else defaultSpinner"
1910
1915
  [ngTemplateOutlet]="customSpinnerTpl"
1911
1916
  ></ng-container>
1912
1917
  <ng-template #defaultSpinner>
1913
- <div style="text-align:center;">
1914
- <div
1915
- style="display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite;"
1916
- ></div>
1917
- <div style="margin-top:16px;color:#666;font-size:16px;">
1918
+ <div class="ng2-pdfjs-spinner-content">
1919
+ <div class="ng2-pdfjs-spinner-icon"></div>
1920
+ <div class="ng2-pdfjs-spinner-text">
1918
1921
  Loading PDF...
1919
1922
  </div>
1920
1923
  </div>
@@ -1925,7 +1928,6 @@ class PdfJsViewerComponent {
1925
1928
  class="ng2-pdfjs-error-overlay"
1926
1929
  *ngIf="errorOverride && hasError && !externalWindow"
1927
1930
  [ngClass]="errorClass"
1928
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.9);backdrop-filter:saturate(120%) blur(1px);"
1929
1931
  >
1930
1932
  <ng-container
1931
1933
  *ngIf="customErrorTpl; else defaultError"
@@ -1933,36 +1935,31 @@ class PdfJsViewerComponent {
1933
1935
  [ngTemplateOutletContext]="getErrorTemplateData()"
1934
1936
  ></ng-container>
1935
1937
  <ng-template #defaultError>
1936
- <div style="text-align:center;max-width:400px;padding:20px;">
1937
- <div style="font-size:48px;color:#f44336;margin-bottom:16px;">
1938
+ <div class="ng2-pdfjs-error-content">
1939
+ <div class="ng2-pdfjs-error-icon">
1938
1940
  ⚠️
1939
1941
  </div>
1940
- <div
1941
- style="color:#333;font-size:18px;font-weight:500;margin-bottom:8px;"
1942
- >
1942
+ <div class="ng2-pdfjs-error-title">
1943
1943
  Error Loading PDF
1944
1944
  </div>
1945
- <div style="color:#666;font-size:14px;line-height:1.4;">
1945
+ <div class="ng2-pdfjs-error-message">
1946
1946
  {{ currentErrorMessage }}
1947
1947
  </div>
1948
1948
  </div>
1949
1949
  </ng-template>
1950
1950
  </div>
1951
1951
  </div>
1952
- `, isInline: true, styles: [".ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
1952
+ `, isInline: true, styles: [".ng2-pdfjs-viewer-container{position:relative;width:100%;height:100%}.ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-spinner-content{text-align:center}.ng2-pdfjs-spinner-icon{display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite}.ng2-pdfjs-spinner-text{margin-top:16px;color:#666;font-size:16px}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-content{text-align:center;max-width:400px;padding:20px}.ng2-pdfjs-error-icon{font-size:48px;color:#f44336;margin-bottom:16px}.ng2-pdfjs-error-title{color:#333;font-size:18px;font-weight:500;margin-bottom:8px}.ng2-pdfjs-error-message{color:#666;font-size:14px;line-height:1.4}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ng2-pdfjs-viewer-iframe{border:0}.ng2-pdfjs-viewer-iframe.has-border{border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
1953
1953
  }
1954
1954
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: PdfJsViewerComponent, decorators: [{
1955
1955
  type: Component,
1956
1956
  args: [{ selector: "ng2-pdfjs-viewer", standalone: false, template: `
1957
- <div
1958
- class="ng2-pdfjs-viewer-container"
1959
- style="position:relative;width:100%;height:100%;"
1960
- >
1957
+ <div class="ng2-pdfjs-viewer-container">
1961
1958
  <iframe
1962
1959
  [title]="iframeTitle || 'PDF document viewer'"
1963
1960
  [hidden]="externalWindow || (!externalWindow && !pdfSrc)"
1964
1961
  sandbox="allow-forms allow-scripts allow-same-origin allow-modals"
1965
- [style.border]="iframeBorder"
1962
+ [class]="getIframeClasses()"
1966
1963
  #iframe
1967
1964
  width="100%"
1968
1965
  height="100%"
@@ -1972,18 +1969,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1972
1969
  class="ng2-pdfjs-loading-overlay"
1973
1970
  *ngIf="showSpinner && isLoading && !externalWindow"
1974
1971
  [ngClass]="spinnerClass"
1975
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.6);backdrop-filter:saturate(120%) blur(1px);"
1976
1972
  >
1977
1973
  <ng-container
1978
1974
  *ngIf="customSpinnerTpl; else defaultSpinner"
1979
1975
  [ngTemplateOutlet]="customSpinnerTpl"
1980
1976
  ></ng-container>
1981
1977
  <ng-template #defaultSpinner>
1982
- <div style="text-align:center;">
1983
- <div
1984
- style="display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite;"
1985
- ></div>
1986
- <div style="margin-top:16px;color:#666;font-size:16px;">
1978
+ <div class="ng2-pdfjs-spinner-content">
1979
+ <div class="ng2-pdfjs-spinner-icon"></div>
1980
+ <div class="ng2-pdfjs-spinner-text">
1987
1981
  Loading PDF...
1988
1982
  </div>
1989
1983
  </div>
@@ -1994,7 +1988,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1994
1988
  class="ng2-pdfjs-error-overlay"
1995
1989
  *ngIf="errorOverride && hasError && !externalWindow"
1996
1990
  [ngClass]="errorClass"
1997
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.9);backdrop-filter:saturate(120%) blur(1px);"
1998
1991
  >
1999
1992
  <ng-container
2000
1993
  *ngIf="customErrorTpl; else defaultError"
@@ -2002,23 +1995,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
2002
1995
  [ngTemplateOutletContext]="getErrorTemplateData()"
2003
1996
  ></ng-container>
2004
1997
  <ng-template #defaultError>
2005
- <div style="text-align:center;max-width:400px;padding:20px;">
2006
- <div style="font-size:48px;color:#f44336;margin-bottom:16px;">
1998
+ <div class="ng2-pdfjs-error-content">
1999
+ <div class="ng2-pdfjs-error-icon">
2007
2000
  ⚠️
2008
2001
  </div>
2009
- <div
2010
- style="color:#333;font-size:18px;font-weight:500;margin-bottom:8px;"
2011
- >
2002
+ <div class="ng2-pdfjs-error-title">
2012
2003
  Error Loading PDF
2013
2004
  </div>
2014
- <div style="color:#666;font-size:14px;line-height:1.4;">
2005
+ <div class="ng2-pdfjs-error-message">
2015
2006
  {{ currentErrorMessage }}
2016
2007
  </div>
2017
2008
  </div>
2018
2009
  </ng-template>
2019
2010
  </div>
2020
2011
  </div>
2021
- `, styles: [".ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
2012
+ `, styles: [".ng2-pdfjs-viewer-container{position:relative;width:100%;height:100%}.ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-spinner-content{text-align:center}.ng2-pdfjs-spinner-icon{display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite}.ng2-pdfjs-spinner-text{margin-top:16px;color:#666;font-size:16px}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-content{text-align:center;max-width:400px;padding:20px}.ng2-pdfjs-error-icon{font-size:48px;color:#f44336;margin-bottom:16px}.ng2-pdfjs-error-title{color:#333;font-size:18px;font-weight:500;margin-bottom:8px}.ng2-pdfjs-error-message{color:#666;font-size:14px;line-height:1.4}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ng2-pdfjs-viewer-iframe{border:0}.ng2-pdfjs-viewer-iframe.has-border{border:1px solid #ccc}\n"] }]
2022
2013
  }], propDecorators: { iframe: [{
2023
2014
  type: ViewChild,
2024
2015
  args: ["iframe", { static: true }]