├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .firebaserc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode └── extensions.json ├── LICENSE ├── README.md ├── apps ├── demo-angular │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.ts │ │ │ └── app.module.ts │ │ ├── assets │ │ │ ├── .gitkeep │ │ │ ├── file-sample_100kB.docx │ │ │ ├── file-sample_150kB.pdf │ │ │ ├── file_example_PPTX_250kB.pptx │ │ │ └── file_example_PPT_250kB.ppt │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ └── tsconfig.spec.json └── demo-react │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ ├── app │ │ ├── app.module.scss │ │ ├── app.tsx │ │ ├── logo.svg │ │ └── star.svg │ ├── assets │ │ ├── .gitkeep │ │ ├── file-sample_100kB.docx │ │ ├── file-sample_150kB.pdf │ │ ├── file_example_PPTX_250kB.pptx │ │ └── file_example_PPT_250kB.ppt │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.tsx │ ├── polyfills.ts │ └── styles.scss │ ├── tsconfig.app.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── babel.config.json ├── firebase.json ├── jest.config.ts ├── jest.preset.js ├── libs └── data │ ├── .babelrc │ ├── .eslintrc.json │ ├── README.md │ ├── jest.config.js │ ├── project.json │ ├── src │ ├── index.ts │ └── lib │ │ └── demo-data.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── migrations.json ├── nx.json ├── package-lock.json ├── package.json ├── packages ├── .gitkeep ├── docviewhelper │ ├── .babelrc │ ├── .eslintrc.json │ ├── README.md │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── helper.test.ts │ │ │ ├── helper.ts │ │ │ └── model.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── ngx-doc-viewer │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── README.md │ ├── changelog.md │ ├── jest.config.ts │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── document-viewer.component.html │ │ │ ├── document-viewer.component.ts │ │ │ └── document-viewer.module.ts │ │ └── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ └── tsconfig.spec.json └── react-documents │ ├── .babelrc │ ├── .eslintrc.json │ ├── README.md │ ├── changelog.md │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ ├── index.ts │ └── lib │ │ └── react-documents.tsx │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── tools └── tsconfig.tools.json └── tsconfig.base.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nx/typescript"], 27 | "rules": {} 28 | }, 29 | { 30 | "files": ["*.js", "*.jsx"], 31 | "extends": ["plugin:@nx/javascript"], 32 | "rules": {} 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "angular-doc-viewer", 4 | "demo-angular": "angular-doc-viewer", 5 | "demo-react": "angular-doc-viewer" 6 | }, 7 | "targets": { 8 | "angular-doc-viewer": { 9 | "hosting": { 10 | "demo-angular": [ 11 | "angular-doc-viewer" 12 | ], 13 | "demo-react": [ 14 | "react-documents" 15 | ] 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | .angular 42 | firebase-debug.log 43 | .firebase/*.cache 44 | 45 | .nx/cache -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | 6 | /.nx/cache -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "esbenp.prettier-vscode", 5 | "firsttris.vscode-jest-runner", 6 | "dbaeumer.vscode-eslint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Marcel Hoekstra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Documentviewer 2 | 3 | This component can be used to show several different document types. 4 | 5 | ## Angular 6 | 7 | [ngx-doc-viewer](packages/ngx-doc-viewer) 8 | 9 | ## React 10 | [react-documents](packages/react-documents) 11 | -------------------------------------------------------------------------------- /apps/demo-angular/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /apps/demo-angular/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "documentViewer", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "document-viewer", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/demo-angular/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'demo-angular', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: {}, 7 | coverageDirectory: '../../coverage/packages/demo-angular', 8 | transform: { 9 | '^.+\\.(ts|mjs|js|html)$': [ 10 | 'jest-preset-angular', 11 | { 12 | tsconfig: '/tsconfig.spec.json', 13 | stringifyContentPathRegex: '\\.(html|svg)$', 14 | }, 15 | ], 16 | }, 17 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/serializers/no-ng-attributes', 20 | 'jest-preset-angular/build/serializers/ng-snapshot', 21 | 'jest-preset-angular/build/serializers/html-comment', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /apps/demo-angular/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-angular", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "sourceRoot": "apps/demo-angular/src", 6 | "prefix": "document-viewer", 7 | "targets": { 8 | "build": { 9 | "executor": "@angular-devkit/build-angular:browser", 10 | "outputs": ["{options.outputPath}"], 11 | "options": { 12 | "outputPath": "dist/apps/demo-angular", 13 | "index": "apps/demo-angular/src/index.html", 14 | "main": "apps/demo-angular/src/main.ts", 15 | "polyfills": "apps/demo-angular/src/polyfills.ts", 16 | "tsConfig": "apps/demo-angular/tsconfig.app.json", 17 | "inlineStyleLanguage": "scss", 18 | "assets": [ 19 | "apps/demo-angular/src/favicon.ico", 20 | "apps/demo-angular/src/assets" 21 | ], 22 | "styles": ["apps/demo-angular/src/styles.scss"], 23 | "scripts": [] 24 | }, 25 | "configurations": { 26 | "production": { 27 | "budgets": [ 28 | { 29 | "type": "initial", 30 | "maximumWarning": "500kb", 31 | "maximumError": "1mb" 32 | }, 33 | { 34 | "type": "anyComponentStyle", 35 | "maximumWarning": "2kb", 36 | "maximumError": "4kb" 37 | } 38 | ], 39 | "fileReplacements": [ 40 | { 41 | "replace": "apps/demo-angular/src/environments/environment.ts", 42 | "with": "apps/demo-angular/src/environments/environment.prod.ts" 43 | } 44 | ], 45 | "outputHashing": "all" 46 | }, 47 | "development": { 48 | "buildOptimizer": false, 49 | "optimization": false, 50 | "vendorChunk": true, 51 | "extractLicenses": false, 52 | "sourceMap": true, 53 | "namedChunks": true 54 | } 55 | }, 56 | "defaultConfiguration": "production" 57 | }, 58 | "serve": { 59 | "executor": "@angular-devkit/build-angular:dev-server", 60 | "configurations": { 61 | "production": { 62 | "browserTarget": "demo-angular:build:production" 63 | }, 64 | "development": { 65 | "browserTarget": "demo-angular:build:development" 66 | } 67 | }, 68 | "defaultConfiguration": "development" 69 | }, 70 | "extract-i18n": { 71 | "executor": "@angular-devkit/build-angular:extract-i18n", 72 | "options": { 73 | "browserTarget": "demo-angular:build" 74 | } 75 | }, 76 | "lint": { 77 | "executor": "@nx/eslint:lint", 78 | "options": { 79 | "lintFilePatterns": [ 80 | "apps/demo-angular/src/**/*.ts", 81 | "apps/demo-angular/src/**/*.html" 82 | ] 83 | } 84 | }, 85 | "test": { 86 | "executor": "@nx/jest:jest", 87 | "outputs": ["{workspaceRoot}/coverage/apps/demo-angular"], 88 | "options": { 89 | "jestConfig": "apps/demo-angular/jest.config.ts", 90 | "passWithNoTests": true 91 | } 92 | } 93 | }, 94 | "tags": [] 95 | } 96 | -------------------------------------------------------------------------------- /apps/demo-angular/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 11 |
12 |
13 | 21 | 22 | 28 | 34 | 35 | 36 | 42 | 43 |
44 | 52 |
53 | -------------------------------------------------------------------------------- /apps/demo-angular/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { handleFileUpload, ViewerType } from 'ngx-doc-viewer'; 3 | import { viewers } from '@document-viewer/data'; 4 | @Component({ 5 | selector: 'document-viewer-root', 6 | templateUrl: 'app.component.html', 7 | styles: [], 8 | }) 9 | export class AppComponent { 10 | viewers = viewers; 11 | selectedViewer = this.viewers[0]; 12 | selectedDoc = this.selectedViewer.docs[0]; 13 | 14 | selectViewer(viewerName: ViewerType) { 15 | if (viewerName !== this.selectViewer.name) { 16 | this.selectedViewer = 17 | this.viewers.find((v) => v.name === viewerName) || this.viewers[0]; 18 | this.selectedDoc = this.selectedViewer.docs[0]; 19 | } 20 | } 21 | 22 | getDocExtension(doc: string) { 23 | const splittedDoc = doc.split('.'); 24 | return splittedDoc[splittedDoc.length - 1]; 25 | } 26 | 27 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 28 | async handleFiles(fileInput: any) { 29 | this.selectedDoc = await handleFileUpload(fileInput); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/demo-angular/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { NgxDocViewerModule } from 'ngx-doc-viewer'; 6 | 7 | @NgModule({ 8 | declarations: [AppComponent], 9 | imports: [NgxDocViewerModule, BrowserModule], 10 | providers: [], 11 | bootstrap: [AppComponent], 12 | }) 13 | export class AppModule {} 14 | -------------------------------------------------------------------------------- /apps/demo-angular/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-angular/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/demo-angular/src/assets/file-sample_100kB.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-angular/src/assets/file-sample_100kB.docx -------------------------------------------------------------------------------- /apps/demo-angular/src/assets/file-sample_150kB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-angular/src/assets/file-sample_150kB.pdf -------------------------------------------------------------------------------- /apps/demo-angular/src/assets/file_example_PPTX_250kB.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-angular/src/assets/file_example_PPTX_250kB.pptx -------------------------------------------------------------------------------- /apps/demo-angular/src/assets/file_example_PPT_250kB.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-angular/src/assets/file_example_PPT_250kB.ppt -------------------------------------------------------------------------------- /apps/demo-angular/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/demo-angular/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/demo-angular/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-angular/src/favicon.ico -------------------------------------------------------------------------------- /apps/demo-angular/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DemoAngular 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /apps/demo-angular/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/demo-angular/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | /*************************************************************************************************** 51 | * APPLICATION IMPORTS 52 | */ 53 | -------------------------------------------------------------------------------- /apps/demo-angular/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/demo-angular/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/demo-angular/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [], 6 | "target": "es2020" 7 | }, 8 | "files": ["src/main.ts", "src/polyfills.ts"], 9 | "include": ["src/**/*.d.ts"], 10 | "exclude": ["**/*.test.ts", "**/*.spec.ts", "jest.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /apps/demo-angular/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/demo-angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "strict": true, 19 | "noImplicitOverride": true, 20 | "noPropertyAccessFromIndexSignature": true, 21 | "noImplicitReturns": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "target": "es2020" 24 | }, 25 | "angularCompilerOptions": { 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/demo-angular/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/demo-react/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/react/babel", 5 | { 6 | "runtime": "automatic" 7 | } 8 | ] 9 | ], 10 | "plugins": [] 11 | } 12 | -------------------------------------------------------------------------------- /apps/demo-react/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by: 2 | # 1. autoprefixer to adjust CSS to support the below specified browsers 3 | # 2. babel preset-env to adjust included polyfills 4 | # 5 | # For additional information regarding the format and rule options, please see: 6 | # https://github.com/browserslist/browserslist#queries 7 | # 8 | # If you need to support different browsers in production, you may tweak the list below. 9 | 10 | last 1 Chrome version 11 | last 1 Firefox version 12 | last 2 Edge major versions 13 | last 2 Safari major version 14 | last 2 iOS major versions 15 | Firefox ESR 16 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /apps/demo-react/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:@nx/react", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /apps/demo-react/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'demo-react', 4 | preset: '../../jest.preset.js', 5 | transform: { 6 | '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', 7 | '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], 8 | }, 9 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 10 | coverageDirectory: '../../coverage/apps/demo-react', 11 | }; 12 | -------------------------------------------------------------------------------- /apps/demo-react/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-react", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/demo-react/src", 5 | "projectType": "application", 6 | "targets": { 7 | "build": { 8 | "executor": "@nx/webpack:webpack", 9 | "outputs": ["{options.outputPath}"], 10 | "defaultConfiguration": "production", 11 | "options": { 12 | "compiler": "babel", 13 | "outputPath": "dist/apps/demo-react", 14 | "index": "apps/demo-react/src/index.html", 15 | "baseHref": "/", 16 | "main": "apps/demo-react/src/main.tsx", 17 | "polyfills": "apps/demo-react/src/polyfills.ts", 18 | "tsConfig": "apps/demo-react/tsconfig.app.json", 19 | "assets": [ 20 | "apps/demo-react/src/favicon.ico", 21 | "apps/demo-react/src/assets" 22 | ], 23 | "styles": ["apps/demo-react/src/styles.scss"], 24 | "scripts": [], 25 | "webpackConfig": "@nx/react/plugins/webpack" 26 | }, 27 | "configurations": { 28 | "development": { 29 | "extractLicenses": false, 30 | "optimization": false, 31 | "sourceMap": true, 32 | "vendorChunk": true 33 | }, 34 | "production": { 35 | "fileReplacements": [ 36 | { 37 | "replace": "apps/demo-react/src/environments/environment.ts", 38 | "with": "apps/demo-react/src/environments/environment.prod.ts" 39 | } 40 | ], 41 | "optimization": true, 42 | "outputHashing": "all", 43 | "sourceMap": false, 44 | "namedChunks": false, 45 | "extractLicenses": true, 46 | "vendorChunk": false 47 | } 48 | } 49 | }, 50 | "serve": { 51 | "executor": "@nx/webpack:dev-server", 52 | "defaultConfiguration": "development", 53 | "options": { 54 | "buildTarget": "demo-react:build", 55 | "hmr": true 56 | }, 57 | "configurations": { 58 | "development": { 59 | "buildTarget": "demo-react:build:development" 60 | }, 61 | "production": { 62 | "buildTarget": "demo-react:build:production", 63 | "hmr": false 64 | } 65 | } 66 | }, 67 | "lint": { 68 | "executor": "@nx/eslint:lint", 69 | "outputs": ["{options.outputFile}"], 70 | "options": { 71 | "lintFilePatterns": ["apps/demo-react/**/*.{ts,tsx,js,jsx}"] 72 | } 73 | }, 74 | "test": { 75 | "executor": "@nx/jest:jest", 76 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 77 | "options": { 78 | "jestConfig": "apps/demo-react/jest.config.ts", 79 | "passWithNoTests": true 80 | } 81 | } 82 | }, 83 | "tags": [] 84 | } 85 | -------------------------------------------------------------------------------- /apps/demo-react/src/app/app.module.scss: -------------------------------------------------------------------------------- 1 | .app { 2 | font-family: sans-serif; 3 | min-width: 300px; 4 | max-width: 600px; 5 | margin: 50px auto; 6 | } 7 | -------------------------------------------------------------------------------- /apps/demo-react/src/app/app.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import './app.module.scss'; 3 | import { viewers } from '@document-viewer/data'; 4 | import { DocumentViewer, handleFileUpload, ViewerType } from 'react-documents'; 5 | 6 | export function App() { 7 | const [selectedViewer, setSelectedViewer] = useState(viewers[0]); 8 | const [selectedDoc, setSelectedDoc] = useState(viewers[0].docs[0]); 9 | const [url, setUrl] = useState(''); 10 | 11 | const handleChange = (e: any) => { 12 | setUrl(e.target.value); 13 | }; 14 | 15 | const getDocExtension = (doc: string) => { 16 | const splittedDoc = doc.split('.'); 17 | return splittedDoc[splittedDoc.length - 1]; 18 | }; 19 | 20 | const selectViewer = (viewerName: ViewerType) => { 21 | if (viewerName !== selectViewer.name) { 22 | const viewer = viewers.find((v) => v.name === viewerName); 23 | if (viewer) { 24 | setSelectedViewer(viewer); 25 | setSelectedDoc(viewer.docs[0]); 26 | } 27 | } 28 | }; 29 | 30 | const handleFiles = async (fileInput: any) => { 31 | setSelectedDoc(await handleFileUpload(fileInput)); 32 | }; 33 | 34 | return ( 35 |
36 |
37 | {viewers.map((viewer) => { 38 | return ( 39 | 49 | ); 50 | })} 51 |
52 |
53 | {selectedViewer.docs.map((doc) => { 54 | return ( 55 |
56 | 65 |
66 | ); 67 | })} 68 | {selectedViewer.custom ? ( 69 | <> 70 | 76 | 82 | 83 | ) : null} 84 | {selectedViewer.acceptedUploadTypes ? ( 85 | 91 | ) : null} 92 |
93 | 94 | 102 |
103 | ); 104 | } 105 | 106 | export default App; 107 | -------------------------------------------------------------------------------- /apps/demo-react/src/app/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /apps/demo-react/src/app/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /apps/demo-react/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-react/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/demo-react/src/assets/file-sample_100kB.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-react/src/assets/file-sample_100kB.docx -------------------------------------------------------------------------------- /apps/demo-react/src/assets/file-sample_150kB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-react/src/assets/file-sample_150kB.pdf -------------------------------------------------------------------------------- /apps/demo-react/src/assets/file_example_PPTX_250kB.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-react/src/assets/file_example_PPTX_250kB.pptx -------------------------------------------------------------------------------- /apps/demo-react/src/assets/file_example_PPT_250kB.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-react/src/assets/file_example_PPT_250kB.ppt -------------------------------------------------------------------------------- /apps/demo-react/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/demo-react/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // When building for production, this file is replaced with `environment.prod.ts`. 3 | 4 | export const environment = { 5 | production: false, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/demo-react/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/apps/demo-react/src/favicon.ico -------------------------------------------------------------------------------- /apps/demo-react/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DemoReact 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /apps/demo-react/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import App from './app/app'; 3 | import { createRoot } from 'react-dom/client'; 4 | 5 | const container = document.getElementById('app') as HTMLElement; 6 | const root = createRoot(container); 7 | 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | -------------------------------------------------------------------------------- /apps/demo-react/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. 3 | * 4 | * See: https://github.com/zloirock/core-js#babel 5 | */ 6 | import 'core-js/stable'; 7 | import 'regenerator-runtime/runtime'; 8 | -------------------------------------------------------------------------------- /apps/demo-react/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/demo-react/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [ 6 | "node", 7 | "@nx/react/typings/cssmodule.d.ts", 8 | "@nx/react/typings/image.d.ts" 9 | ] 10 | }, 11 | "files": [ 12 | "../../node_modules/@nx/react/typings/cssmodule.d.ts", 13 | "../../node_modules/@nx/react/typings/image.d.ts" 14 | ], 15 | "exclude": [ 16 | "jest.config.ts", 17 | "src/**/*.spec.ts", 18 | "src/**/*.test.ts", 19 | "src/**/*.spec.tsx", 20 | "src/**/*.test.tsx", 21 | "src/**/*.spec.js", 22 | "src/**/*.test.js", 23 | "src/**/*.spec.jsx", 24 | "src/**/*.test.jsx" 25 | ], 26 | "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] 27 | } 28 | -------------------------------------------------------------------------------- /apps/demo-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react-jsx", 4 | "allowJs": false, 5 | "esModuleInterop": false, 6 | "allowSyntheticDefaultImports": true, 7 | "strict": true 8 | }, 9 | "files": [], 10 | "include": [], 11 | "references": [ 12 | { 13 | "path": "./tsconfig.app.json" 14 | }, 15 | { 16 | "path": "./tsconfig.spec.json" 17 | } 18 | ], 19 | "extends": "../../tsconfig.base.json" 20 | } 21 | -------------------------------------------------------------------------------- /apps/demo-react/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": [ 7 | "jest", 8 | "node", 9 | "@nx/react/typings/cssmodule.d.ts", 10 | "@nx/react/typings/image.d.ts" 11 | ] 12 | }, 13 | "include": [ 14 | "jest.config.ts", 15 | "src/**/*.test.ts", 16 | "src/**/*.spec.ts", 17 | "src/**/*.test.tsx", 18 | "src/**/*.spec.tsx", 19 | "src/**/*.test.js", 20 | "src/**/*.spec.js", 21 | "src/**/*.test.jsx", 22 | "src/**/*.spec.jsx", 23 | "src/**/*.d.ts" 24 | ], 25 | "files": [ 26 | "../../node_modules/@nx/react/typings/cssmodule.d.ts", 27 | "../../node_modules/@nx/react/typings/image.d.ts" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "babelrcRoots": ["*"] 3 | } 4 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": [ 3 | { 4 | "target": "demo-angular", 5 | "public": "dist/apps/demo-angular", 6 | "predeploy": [ 7 | "nx build demo-angular --prod" 8 | ], 9 | "ignore": [ 10 | "firebase.json", 11 | "**/.*", 12 | "**/node_modules/**" 13 | ], 14 | "rewrites": [ 15 | { 16 | "source": "**", 17 | "destination": "/index.html" 18 | } 19 | ] 20 | }, 21 | { 22 | "target": "demo-react", 23 | "public": "dist/apps/demo-react", 24 | "predeploy": [ 25 | "nx build demo-react --prod" 26 | ], 27 | "ignore": [ 28 | "firebase.json", 29 | "**/.*", 30 | "**/node_modules/**" 31 | ], 32 | "rewrites": [ 33 | { 34 | "source": "**", 35 | "destination": "/index.html" 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | const { getJestProjects } = require('@nx/jest'); 2 | 3 | export default { 4 | projects: getJestProjects(), 5 | }; 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { 4 | ...nxPreset, 5 | /* TODO: Update to latest Jest snapshotFormat 6 | * By default Nx has kept the older style of Jest Snapshot formats 7 | * to prevent breaking of any existing tests with snapshots. 8 | * It's recommend you update to the latest format. 9 | * You can do this by removing snapshotFormat property 10 | * and running tests with --update-snapshot flag. 11 | * Example: "nx affected --targets=test --update-snapshot" 12 | * More info: https://jestjs.io/docs/upgrading-to-jest29#snapshot-format 13 | */ 14 | snapshotFormat: { escapeString: true, printBasicPrototype: true }, 15 | }; 16 | -------------------------------------------------------------------------------- /libs/data/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nrwl/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /libs/data/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /libs/data/README.md: -------------------------------------------------------------------------------- 1 | # data 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test data` to execute the unit tests via [Jest](https://jestjs.io). 8 | -------------------------------------------------------------------------------- /libs/data/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'data', 3 | preset: '../../jest.preset.js', 4 | globals: { 5 | 'ts-jest': { 6 | tsconfig: '/tsconfig.spec.json', 7 | }, 8 | }, 9 | transform: { 10 | '^.+\\.[tj]sx?$': 'ts-jest', 11 | }, 12 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 13 | coverageDirectory: '../../coverage/packages/data', 14 | }; 15 | -------------------------------------------------------------------------------- /libs/data/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "data", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/data/src", 5 | "projectType": "library", 6 | "targets": { 7 | "lint": { 8 | "executor": "@nx/eslint:lint", 9 | "outputs": ["{options.outputFile}"], 10 | "options": { 11 | "lintFilePatterns": ["packages/data/**/*.ts"] 12 | } 13 | }, 14 | "test": { 15 | "executor": "@nx/jest:jest", 16 | "outputs": ["{workspaceRoot}/coverage/packages/data"], 17 | "options": { 18 | "jestConfig": "packages/data/jest.config.js", 19 | "passWithNoTests": true 20 | } 21 | } 22 | }, 23 | "tags": [] 24 | } 25 | -------------------------------------------------------------------------------- /libs/data/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/demo-data'; 2 | -------------------------------------------------------------------------------- /libs/data/src/lib/demo-data.ts: -------------------------------------------------------------------------------- 1 | import { ViewerType, getbaseUrl } from 'docviewhelper'; 2 | export const viewers: { 3 | name: ViewerType; 4 | docs: string[]; 5 | custom: boolean; 6 | acceptedUploadTypes: string; 7 | viewerUrl?: string; 8 | }[] = [ 9 | { 10 | name: 'google', 11 | docs: [ 12 | 'https://calibre-ebook.com/downloads/demos/demo.docx', 13 | 'https://go.microsoft.com/fwlink/?LinkID=521962', 14 | 'https://file-examples.com/storage/fe2356939c62607a6a1903b/2017/10/file_example_TIFF_1MB.tiff', 15 | 'https://file-examples.com/storage/fe2356939c62607a6a1903b/2017/10/file-example_PDF_1MB.pdf', 16 | `${getbaseUrl()}/assets/file_example_PPT_250kB.ppt`, 17 | `${getbaseUrl()}/assets/file_example_PPTX_250kB.pptx`, 18 | ], 19 | custom: true, 20 | acceptedUploadTypes: '', 21 | }, 22 | { 23 | name: 'office', 24 | docs: [ 25 | 'https://file-examples-com.github.io/uploads/2017/02/file-sample_100kB.docx', 26 | 'https://file-examples-com.github.io/uploads/2017/02/file_example_XLSX_50.xlsx', 27 | `${getbaseUrl()}/assets/file_example_PPT_250kB.ppt`, 28 | `${getbaseUrl()}/assets/file_example_PPTX_250kB.pptx`, 29 | ], 30 | custom: true, 31 | acceptedUploadTypes: '', 32 | }, 33 | { 34 | name: 'mammoth', 35 | docs: [`${getbaseUrl()}/assets/file-sample_100kB.docx`], 36 | custom: false, 37 | acceptedUploadTypes: 38 | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 39 | }, 40 | { 41 | name: 'pdf', 42 | docs: [`${getbaseUrl()}/assets/file-sample_150kB.pdf`], 43 | custom: false, 44 | acceptedUploadTypes: 'application/pdf', 45 | }, 46 | { 47 | name: 'url', 48 | docs: [ 49 | // eslint-disable-next-line max-len 50 | `https://docs.google.com/document/d/e/2PACX-1vRs3gemrszDinuGJCi_wO2m5XVP1q2SlRhxM8PAUYc3wu9LFsvteny7l6Rkp695-ruhfn3gWXV03yXC/pub?embedded=true`, 51 | ], 52 | custom: true, 53 | acceptedUploadTypes: '', 54 | }, 55 | ]; 56 | -------------------------------------------------------------------------------- /libs/data/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ], 13 | "compilerOptions": { 14 | "forceConsistentCasingInFileNames": true, 15 | "strict": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /libs/data/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "types": [] 7 | }, 8 | "include": ["**/*.ts"], 9 | "exclude": ["**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/data/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.test.ts", 10 | "**/*.spec.ts", 11 | "**/*.test.tsx", 12 | "**/*.spec.tsx", 13 | "**/*.test.js", 14 | "**/*.spec.js", 15 | "**/*.test.jsx", 16 | "**/*.spec.jsx", 17 | "**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "migrations": [ 3 | { 4 | "version": "15.7.0-beta.0", 5 | "description": "Split global configuration files into individual project.json files. This migration has been added automatically to the beginning of your migration set to retroactively make them work with the new version of Nx.", 6 | "cli": "nx", 7 | "implementation": "./src/migrations/update-15-7-0/split-configuration-into-project-json-files", 8 | "package": "@nx/workspace", 9 | "name": "15-7-0-split-configuration-into-project-json-files" 10 | }, 11 | { 12 | "cli": "nx", 13 | "version": "15.8.2-beta.0", 14 | "description": "Updates the nx wrapper.", 15 | "implementation": "./src/migrations/update-15-8-2/update-nxw", 16 | "package": "nx", 17 | "name": "15.8.2-update-nx-wrapper" 18 | }, 19 | { 20 | "cli": "nx", 21 | "version": "16.0.0-beta.0", 22 | "description": "Remove @nrwl/cli.", 23 | "implementation": "./src/migrations/update-16-0-0/remove-nrwl-cli", 24 | "package": "nx", 25 | "name": "16.0.0-remove-nrwl-cli" 26 | }, 27 | { 28 | "cli": "nx", 29 | "version": "16.0.0-beta.9", 30 | "description": "Replace `dependsOn.projects` and `inputs` definitions with new configuration format.", 31 | "implementation": "./src/migrations/update-16-0-0/update-depends-on-to-tokens", 32 | "package": "nx", 33 | "name": "16.0.0-tokens-for-depends-on" 34 | }, 35 | { 36 | "cli": "nx", 37 | "version": "16.0.0-beta.0", 38 | "description": "Replace @nrwl/nx-cloud with nx-cloud", 39 | "implementation": "./src/migrations/update-16-0-0/update-nx-cloud-runner", 40 | "package": "nx", 41 | "name": "16.0.0-update-nx-cloud-runner" 42 | }, 43 | { 44 | "cli": "nx", 45 | "version": "16.2.0-beta.0", 46 | "description": "Remove outputPath from run commands", 47 | "implementation": "./src/migrations/update-16-2-0/remove-run-commands-output-path", 48 | "package": "nx", 49 | "name": "16.2.0-remove-output-path-from-run-commands" 50 | }, 51 | { 52 | "cli": "nx", 53 | "version": "16.6.0-beta.6", 54 | "description": "Prefix outputs with {workspaceRoot}/{projectRoot} if needed", 55 | "implementation": "./src/migrations/update-15-0-0/prefix-outputs", 56 | "package": "nx", 57 | "name": "16.6.0-prefix-outputs" 58 | }, 59 | { 60 | "cli": "nx", 61 | "version": "16.8.0-beta.3", 62 | "description": "Escape $ in env variables", 63 | "implementation": "./src/migrations/update-16-8-0/escape-dollar-sign-env-variables", 64 | "package": "nx", 65 | "name": "16.8.0-escape-dollar-sign-env" 66 | }, 67 | { 68 | "cli": "nx", 69 | "version": "17.0.0-beta.1", 70 | "description": "Updates the default cache directory to .nx/cache", 71 | "implementation": "./src/migrations/update-17-0-0/move-cache-directory", 72 | "package": "nx", 73 | "name": "17.0.0-move-cache-directory" 74 | }, 75 | { 76 | "cli": "nx", 77 | "version": "17.0.0-beta.3", 78 | "description": "Use minimal config for tasksRunnerOptions", 79 | "implementation": "./src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options", 80 | "package": "nx", 81 | "name": "17.0.0-use-minimal-config-for-tasks-runner-options" 82 | }, 83 | { 84 | "version": "17.0.0-rc.1", 85 | "description": "Migration for v17.0.0-rc.1", 86 | "implementation": "./src/migrations/update-17-0-0/rm-default-collection-npm-scope", 87 | "package": "nx", 88 | "name": "rm-default-collection-npm-scope" 89 | }, 90 | { 91 | "version": "15.7.0-beta.0", 92 | "description": "Split global configuration files (e.g., workspace.json) into individual project.json files.", 93 | "cli": "nx", 94 | "implementation": "./src/migrations/update-15-7-0/split-configuration-into-project-json-files", 95 | "package": "@nx/workspace", 96 | "name": "15-7-0-split-configuration-into-project-json-files" 97 | }, 98 | { 99 | "cli": "nx", 100 | "version": "16.0.0-beta.1", 101 | "description": "Replace @nx/workspace with @nx/workspace", 102 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 103 | "package": "@nx/workspace", 104 | "name": "update-16-0-0-add-nx-packages" 105 | }, 106 | { 107 | "version": "16.0.0-beta.4", 108 | "description": "Generates a plugin called 'workspace-plugin' containing your workspace generators.", 109 | "cli": "nx", 110 | "implementation": "./src/migrations/update-16-0-0/move-workspace-generators-to-local-plugin", 111 | "package": "@nx/workspace", 112 | "name": "16-0-0-move-workspace-generators-into-local-plugin" 113 | }, 114 | { 115 | "version": "16.0.0-beta.9", 116 | "description": "Fix .babelrc presets if it contains an invalid entry for @nx/web/babel.", 117 | "cli": "nx", 118 | "implementation": "./src/migrations/update-16-0-0/fix-invalid-babelrc", 119 | "package": "@nx/workspace", 120 | "name": "16-0-0-fix-invalid-babelrc" 121 | }, 122 | { 123 | "cli": "nx", 124 | "version": "15.8.0-beta.0", 125 | "description": "Rename .lib.swcrc to .swcrc for better SWC support throughout the workspace", 126 | "factory": "./src/migrations/update-15-8-0/rename-swcrc-config", 127 | "package": "@nx/js", 128 | "name": "rename-swcrc-config" 129 | }, 130 | { 131 | "cli": "nx", 132 | "version": "16.0.0-beta.1", 133 | "description": "Replace @nx/js with @nx/js", 134 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 135 | "package": "@nx/js", 136 | "name": "update-16-0-0-add-nx-packages" 137 | }, 138 | { 139 | "cli": "nx", 140 | "version": "16.6.0-beta.0", 141 | "description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.", 142 | "factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps", 143 | "package": "@nx/js", 144 | "name": "explicitly-set-projects-to-update-buildable-deps" 145 | }, 146 | { 147 | "cli": "nx", 148 | "version": "16.8.2-beta.0", 149 | "description": "Remove invalid options (strict, noInterop) for ES6 type modules.", 150 | "factory": "./src/migrations/update-16-8-2/update-swcrc", 151 | "package": "@nx/js", 152 | "name": "16-8-2-update-swcrc" 153 | }, 154 | { 155 | "cli": "nx", 156 | "version": "17.0.2", 157 | "description": "Remove deprecated build options", 158 | "implementation": "./src/migrations/update-17-0-0/remove-deprecated-build-options", 159 | "package": "@nx/js", 160 | "name": "update-17-0-0-remove-deprecated-build-options" 161 | }, 162 | { 163 | "cli": "nx", 164 | "version": "16.0.0-beta.1", 165 | "description": "Replace @nx/eslint-plugin with @nx/eslint-plugin", 166 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 167 | "package": "@nx/eslint-plugin", 168 | "name": "update-16-0-0-add-nx-packages" 169 | }, 170 | { 171 | "cli": "nx", 172 | "version": "15.5.0-beta.0", 173 | "description": "Update to Cypress v12. Cypress 12 contains a handful of breaking changes that might causes tests to start failing that nx cannot directly fix. Read more Cypress 12 changes: https://docs.cypress.io/guides/references/migration-guide#Migrating-to-Cypress-12-0.This migration will only run if you are already using Cypress v11.", 174 | "factory": "./src/migrations/update-15-5-0/update-to-cypress-12", 175 | "package": "@nx/cypress", 176 | "name": "update-to-cypress-12" 177 | }, 178 | { 179 | "cli": "nx", 180 | "version": "16.0.0-beta.1", 181 | "description": "Replace @nx/cypress with @nx/cypress", 182 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 183 | "package": "@nx/cypress", 184 | "name": "update-16-0-0-add-nx-packages" 185 | }, 186 | { 187 | "cli": "nx", 188 | "version": "16.2.0-beta.0", 189 | "description": "Normalize tsconfig.cy.json files to be located at '/cypress/tsconfig.json'", 190 | "implementation": "./src/migrations/update-16-2-0/update-cy-tsconfig", 191 | "package": "@nx/cypress", 192 | "name": "update-16-2-0-normalize-tsconfigs" 193 | }, 194 | { 195 | "cli": "nx", 196 | "version": "16.4.0-beta.10", 197 | "description": "Remove tsconfig.e2e.json and add settings to project tsconfig.json. tsConfigs executor option is now deprecated. The project level tsconfig.json file should be used instead.", 198 | "implementation": "./src/migrations/update-16-4-0/tsconfig-sourcemaps", 199 | "package": "@nx/cypress", 200 | "name": "update-16-3-0-remove-old-tsconfigs" 201 | }, 202 | { 203 | "cli": "nx", 204 | "version": "16.8.0-beta.4", 205 | "description": "Update to Cypress v13. Most noteable change is video recording is off by default. This migration will only update if the workspace is already on Cypress v12. https://docs.cypress.io/guides/references/migration-guide#Migrating-to-Cypress-130", 206 | "implementation": "./src/migrations/update-16-8-0/cypress-13", 207 | "package": "@nx/cypress", 208 | "name": "update-16-8-0-cypress-13" 209 | }, 210 | { 211 | "cli": "nx", 212 | "version": "15.7.1-beta.0", 213 | "description": "Add node_modules to root eslint ignore", 214 | "factory": "./src/migrations/update-15-7-1/add-eslint-ignore", 215 | "package": "@nx/eslint", 216 | "name": "add-eslint-ignore" 217 | }, 218 | { 219 | "cli": "nx", 220 | "version": "16.0.0-beta.1", 221 | "description": "Replace @nx/eslint with @nx/eslint", 222 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 223 | "package": "@nx/eslint", 224 | "name": "update-16-0-0-add-nx-packages" 225 | }, 226 | { 227 | "version": "16.8.0", 228 | "description": "update-16-8-0-add-ignored-files", 229 | "implementation": "./src/migrations/update-16-8-0-add-ignored-files/update-16-8-0-add-ignored-files", 230 | "package": "@nx/eslint", 231 | "name": "update-16-8-0-add-ignored-files" 232 | }, 233 | { 234 | "version": "17.0.0-beta.7", 235 | "description": "update-17-0-0-rename-to-eslint", 236 | "implementation": "./src/migrations/update-17-0-0-rename-to-eslint/update-17-0-0-rename-to-eslint", 237 | "package": "@nx/eslint", 238 | "name": "update-17-0-0-rename-to-eslint" 239 | }, 240 | { 241 | "cli": "nx", 242 | "version": "15.5.4-beta.0", 243 | "description": "Update `@nx/web/babel` preset to `@nx/js/babel` for projects that have a .babelrc file.", 244 | "factory": "./src/migrations/update-15-5-4/update-babel-preset", 245 | "package": "@nx/web", 246 | "name": "update-babel-preset" 247 | }, 248 | { 249 | "cli": "nx", 250 | "version": "15.9.1", 251 | "description": "Add @nx/eslint, @nx/cypress, @nx/jest, @nrwl/rollup if they are used", 252 | "factory": "./src/migrations/update-15-9-1/add-dropped-dependencies", 253 | "package": "@nx/web", 254 | "name": "add-dropped-dependencies" 255 | }, 256 | { 257 | "cli": "nx", 258 | "version": "16.0.0-beta.1", 259 | "description": "Replace @nx/web with @nx/web", 260 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 261 | "package": "@nx/web", 262 | "name": "update-16-0-0-add-nx-packages" 263 | }, 264 | { 265 | "cli": "nx", 266 | "version": "16.0.0-beta.4", 267 | "description": "Replace @nx/web executors with @nx/webpack and @nx/rollup", 268 | "implementation": "./src/migrations/update-16-0-0-update-executors/update-16-0-0-update-executors", 269 | "package": "@nx/web", 270 | "name": "update-16-0-0-update-executors" 271 | }, 272 | { 273 | "version": "15.8.0-beta.0", 274 | "cli": "nx", 275 | "description": "Update jest configs to support jest 29 changes (https://jestjs.io/docs/upgrading-to-jest29)", 276 | "factory": "./src/migrations/update-15-8-0/update-configs-jest-29", 277 | "package": "@nx/jest", 278 | "name": "update-configs-jest-29" 279 | }, 280 | { 281 | "version": "15.8.0-beta.0", 282 | "cli": "nx", 283 | "description": "Update jest test files to support jest 29 changes (https://jestjs.io/docs/upgrading-to-jest29)", 284 | "factory": "./src/migrations/update-15-8-0/update-tests-jest-29", 285 | "package": "@nx/jest", 286 | "name": "update-tests-jest-29" 287 | }, 288 | { 289 | "cli": "nx", 290 | "version": "16.0.0-beta.1", 291 | "description": "Replace @nx/jest with @nx/jest", 292 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 293 | "package": "@nx/jest", 294 | "name": "update-16-0-0-add-nx-packages" 295 | }, 296 | { 297 | "cli": "nx", 298 | "version": "16.5.0-beta.2", 299 | "description": "Add test-setup.ts to ignored files in production input", 300 | "implementation": "./src/migrations/update-16-5-0/add-test-setup-to-inputs-ignore", 301 | "package": "@nx/jest", 302 | "name": "add-test-setup-to-inputs-ignore" 303 | }, 304 | { 305 | "cli": "nx", 306 | "version": "15.6.3-beta.0", 307 | "description": "Creates or updates webpack.config.js file with the new options for webpack.", 308 | "factory": "./src/migrations/update-15-6-3/webpack-config-setup", 309 | "package": "@nx/react", 310 | "name": "react-webpack-config-setup" 311 | }, 312 | { 313 | "cli": "nx", 314 | "version": "16.0.0-beta.1", 315 | "description": "Replace @nx/react with @nx/react", 316 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 317 | "package": "@nx/react", 318 | "name": "update-16-0-0-add-nx-packages" 319 | }, 320 | { 321 | "cli": "nx", 322 | "version": "16.2.0-beta.0", 323 | "description": "Remove react-test-renderer from package.json", 324 | "implementation": "./src/migrations/update-16-2-0-remove-package/update-16-2-0-remove-package", 325 | "package": "@nx/react", 326 | "name": "update-16-2-0-remove-package" 327 | }, 328 | { 329 | "cli": "nx", 330 | "version": "16.3.0-beta.2", 331 | "description": "Remove @types/react-router-dom from package.json", 332 | "implementation": "./src/migrations/update-16-3-0/remove-types-react-router-dom-package", 333 | "package": "@nx/react", 334 | "name": "remove-types-react-router-dom" 335 | }, 336 | { 337 | "cli": "nx", 338 | "version": "16.7.0-beta.2", 339 | "description": "Add @babel/core to package.json if @babel/preset-react is present", 340 | "implementation": "./src/migrations/update-16-7-0/add-babel-core", 341 | "package": "@nx/react", 342 | "name": "add-babel-core" 343 | }, 344 | { 345 | "cli": "nx", 346 | "version": "16.7.0-beta.2", 347 | "description": "Add @nx/react types to tsconfig types array", 348 | "implementation": "./src/migrations/update-16-7-0-add-typings/update-16-7-0-add-typings", 349 | "package": "@nx/react", 350 | "name": "update-16-7-0-add-typings" 351 | }, 352 | { 353 | "cli": "nx", 354 | "version": "15.7.0-beta.1", 355 | "description": "Install the required angular-devkit packages as we do not directly depend on them anymore", 356 | "factory": "./src/migrations/update-15-7-0/install-required-packages", 357 | "package": "@nx/angular", 358 | "name": "install-required-packages" 359 | }, 360 | { 361 | "cli": "nx", 362 | "version": "15.5.0-beta.0", 363 | "requires": { 364 | "@angular/core": ">=15.1.0" 365 | }, 366 | "description": "Update the @angular/cli package version to ~15.1.0.", 367 | "factory": "./src/migrations/update-15-5-0/update-angular-cli", 368 | "package": "@nx/angular", 369 | "name": "update-angular-cli-version-15-1-0" 370 | }, 371 | { 372 | "cli": "nx", 373 | "version": "15.8.0-beta.4", 374 | "requires": { 375 | "@angular/core": ">=15.2.0" 376 | }, 377 | "description": "Update the @angular/cli package version to ~15.2.0.", 378 | "factory": "./src/migrations/update-15-8-0/update-angular-cli", 379 | "package": "@nx/angular", 380 | "name": "update-angular-cli-version-15-2-0" 381 | }, 382 | { 383 | "cli": "nx", 384 | "version": "15.9.0-beta.3", 385 | "description": "Update the tsconfig.spec.json to use target es2016 for jest-preset-angular v13", 386 | "factory": "./src/migrations/update-15-9-0/update-testing-tsconfig", 387 | "package": "@nx/angular", 388 | "name": "update-tsconfig-spec-jest" 389 | }, 390 | { 391 | "cli": "nx", 392 | "version": "15.9.0-beta.9", 393 | "description": "Update the file-server executor to use @nx/web:file-server", 394 | "factory": "./src/migrations/update-15-9-0/update-file-server-executor", 395 | "package": "@nx/angular", 396 | "name": "update-file-server-executor" 397 | }, 398 | { 399 | "cli": "nx", 400 | "version": "16.0.0-beta.1", 401 | "description": "Replace the deprecated library generator 'simpleModuleName' option from generator defaults with 'simpleName'", 402 | "factory": "./src/migrations/update-16-0-0/remove-library-generator-simple-module-name-option", 403 | "package": "@nx/angular", 404 | "name": "remove-library-generator-simple-module-name-option" 405 | }, 406 | { 407 | "cli": "nx", 408 | "version": "16.0.0-beta.1", 409 | "description": "Replace @nx/angular with @nx/angular", 410 | "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages", 411 | "package": "@nx/angular", 412 | "name": "update-16-0-0-add-nx-packages" 413 | }, 414 | { 415 | "cli": "nx", 416 | "version": "16.0.0-beta.6", 417 | "description": "Remove protractor as default e2eTestRunner from nxJson and project configurations", 418 | "implementation": "./src/migrations/update-16-0-0/remove-protractor-defaults", 419 | "package": "@nx/angular", 420 | "name": "remove-protractor-defaults-from-generators" 421 | }, 422 | { 423 | "cli": "nx", 424 | "version": "16.0.0-beta.6", 425 | "description": "Remove karma as default unitTestRunner from nxJson and project configurations", 426 | "implementation": "./src/migrations/update-16-0-0/remove-karma-defaults", 427 | "package": "@nx/angular", 428 | "name": "remove-karma-defaults-from-generators" 429 | }, 430 | { 431 | "cli": "nx", 432 | "version": "16.1.0-beta.1", 433 | "requires": { 434 | "@angular/core": ">=15.0.0" 435 | }, 436 | "description": "Remove exported `@angular/platform-server` `renderModule` method. The `renderModule` method is now exported by the Angular CLI.", 437 | "factory": "./src/migrations/update-16-1-0/remove-render-module-platform-server-exports", 438 | "package": "@nx/angular", 439 | "name": "remove-render-module-platform-server-exports" 440 | }, 441 | { 442 | "cli": "nx", 443 | "version": "16.1.0-beta.1", 444 | "requires": { 445 | "@angular/core": ">=16.0.0-rc.4" 446 | }, 447 | "description": "Remove 'ngcc' invocation if exists from the 'postinstall' script in package.json.", 448 | "factory": "./src/migrations/update-16-1-0/remove-ngcc-invocation", 449 | "package": "@nx/angular", 450 | "name": "remove-ngcc-invocation" 451 | }, 452 | { 453 | "cli": "nx", 454 | "version": "16.1.0-beta.1", 455 | "requires": { 456 | "@angular/core": ">=16.0.0-rc.4" 457 | }, 458 | "description": "Extract the app config for standalone apps", 459 | "factory": "./src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap", 460 | "package": "@nx/angular", 461 | "name": "extract-app-config-for-standalone" 462 | }, 463 | { 464 | "cli": "nx", 465 | "version": "16.1.0-beta.1", 466 | "requires": { 467 | "@angular/core": ">=16.0.0-rc.4" 468 | }, 469 | "description": "Update server executors' configuration to disable 'buildOptimizer' for non optimized builds.", 470 | "factory": "./src/migrations/update-16-1-0/update-server-executor-config", 471 | "package": "@nx/angular", 472 | "name": "update-server-executor-config" 473 | }, 474 | { 475 | "cli": "nx", 476 | "version": "16.1.0-beta.1", 477 | "requires": { 478 | "@angular/core": ">=16.0.0" 479 | }, 480 | "description": "Update the @angular/cli package version to ~16.0.0.", 481 | "factory": "./src/migrations/update-16-1-0/update-angular-cli", 482 | "package": "@nx/angular", 483 | "name": "update-angular-cli-version-16-0-0" 484 | }, 485 | { 486 | "cli": "nx", 487 | "version": "16.4.0-beta.6", 488 | "requires": { 489 | "@angular-eslint/eslint-plugin-template": ">=16.0.0" 490 | }, 491 | "description": "Remove the 'accessibility-' prefix from '@angular-eslint/eslint-plugin-template' rules.", 492 | "factory": "./src/migrations/update-16-4-0/rename-angular-eslint-accesibility-rules", 493 | "package": "@nx/angular", 494 | "name": "rename-angular-eslint-accesibility-rules" 495 | }, 496 | { 497 | "cli": "nx", 498 | "version": "16.4.0-beta.11", 499 | "requires": { 500 | "@angular/core": ">=16.1.0" 501 | }, 502 | "description": "Update the @angular/cli package version to ~16.1.0.", 503 | "factory": "./src/migrations/update-16-4-0/update-angular-cli", 504 | "package": "@nx/angular", 505 | "name": "update-angular-cli-version-16-1-0" 506 | }, 507 | { 508 | "cli": "nx", 509 | "version": "16.6.0-beta.0", 510 | "description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.", 511 | "factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps", 512 | "package": "@nx/angular", 513 | "name": "explicitly-set-projects-to-update-buildable-deps" 514 | }, 515 | { 516 | "cli": "nx", 517 | "version": "16.7.0-beta.6", 518 | "requires": { 519 | "@angular/core": ">=16.2.0" 520 | }, 521 | "description": "Update the @angular/cli package version to ~16.2.0.", 522 | "factory": "./src/migrations/update-16-7-0/update-angular-cli", 523 | "package": "@nx/angular", 524 | "name": "update-angular-cli-version-16-2-0" 525 | }, 526 | { 527 | "version": "16.0.0", 528 | "description": "As of Angular v16, the `moduleId` property of `@Component` is deprecated as it no longer has any effect.", 529 | "factory": "./migrations/remove-module-id/bundle", 530 | "package": "@angular/core", 531 | "name": "migration-v16-remove-module-id" 532 | }, 533 | { 534 | "version": "16.0.0", 535 | "description": "In Angular version 15.2, the guard and resolver interfaces (CanActivate, Resolve, etc) were deprecated. This migration removes imports and 'implements' clauses that contain them.", 536 | "factory": "./migrations/guard-and-resolve-interfaces/bundle", 537 | "package": "@angular/core", 538 | "name": "migration-v16-guard-and-resolve-interfaces" 539 | } 540 | ] 541 | } 542 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "nx/presets/core.json", 3 | "affected": { 4 | "defaultBase": "master" 5 | }, 6 | "generators": { 7 | "@nx/angular:application": { 8 | "style": "scss", 9 | "linter": "eslint", 10 | "unitTestRunner": "jest", 11 | "e2eTestRunner": "cypress" 12 | }, 13 | "@nx/angular:library": { 14 | "linter": "eslint", 15 | "unitTestRunner": "jest" 16 | }, 17 | "@nx/angular:component": { 18 | "style": "scss" 19 | }, 20 | "@nx/react": { 21 | "application": { 22 | "style": "scss", 23 | "linter": "eslint", 24 | "bundler": "webpack", 25 | "babel": true 26 | }, 27 | "component": { 28 | "style": "scss" 29 | }, 30 | "library": { 31 | "style": "scss", 32 | "linter": "eslint" 33 | } 34 | } 35 | }, 36 | "defaultProject": "ngx-doc-viewer", 37 | "pluginsConfig": { 38 | "@nx/js": { 39 | "analyzeSourceFiles": true 40 | } 41 | }, 42 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 43 | "targetDefaults": { 44 | "build": { 45 | "cache": true 46 | }, 47 | "lint": { 48 | "cache": true, 49 | "inputs": ["default", "{workspaceRoot}/.eslintrc.json"] 50 | }, 51 | "test": { 52 | "cache": true 53 | }, 54 | "e2e": { 55 | "cache": true 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "document-viewer", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "build:docviewhelper": "nx build docviewhelper", 7 | "build:ngx-doc-viewer": "nx build ngx-doc-viewer --prod", 8 | "build:react-documents": "rimraf ./dist/packages/react-documents && nx build react-documents", 9 | "publish:docviewhelper": "npm run build:docviewhelper && npm publish ./dist/packages/docviewhelper --tag latest", 10 | "publish:react-documents": "npm run build:react-documents && npm publish ./dist/packages/react-documents --tag latest", 11 | "publish:react-documents:next": "npm run build:react-documents && npm publish ./dist/packages/react-documents --tag next", 12 | "publish:ngx-doc-viewer": "npm run build:ngx-doc-viewer && npm publish ./dist/packages/ngx-doc-viewer --tag latest", 13 | "publish:ngx-doc-viewer:next": "npm run build:ngx-doc-viewer && npm publish ./dist/packages/ngx-doc-viewer --tag next", 14 | "start:demo:angular": "nx serve demo-angular --port=4200", 15 | "start:demo:react": "nx serve demo-react --port=4201", 16 | "deploy:demo:angular": "firebase use angular-doc-viewer && firebase deploy --only hosting:demo-angular", 17 | "deploy:demo:react": "firebase use angular-doc-viewer && firebase deploy --only hosting:demo-react" 18 | }, 19 | "private": true, 20 | "devDependencies": { 21 | "@angular-devkit/build-angular": "16.2.9", 22 | "@angular-devkit/schematics": "16.2.9", 23 | "@angular-eslint/eslint-plugin": "16.0.3", 24 | "@angular-eslint/eslint-plugin-template": "16.0.3", 25 | "@angular-eslint/template-parser": "16.0.3", 26 | "@angular/compiler-cli": "16.2.12", 27 | "@angular/language-service": "16.2.12", 28 | "@babel/core": "^7.14.5", 29 | "@babel/preset-react": "^7.14.5", 30 | "@nrwl/js": "17.0.3", 31 | "@nx/angular": "17.0.3", 32 | "@nx/cypress": "17.0.3", 33 | "@nx/eslint": "17.0.3", 34 | "@nx/eslint-plugin": "17.0.3", 35 | "@nx/jest": "17.0.3", 36 | "@nx/js": "17.0.3", 37 | "@nx/react": "17.0.3", 38 | "@nx/rollup": "^17.0.3", 39 | "@nx/web": "17.0.3", 40 | "@nx/workspace": "17.0.3", 41 | "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", 42 | "@schematics/angular": "16.2.9", 43 | "@svgr/webpack": "^6.1.2", 44 | "@testing-library/react": "14.0.0", 45 | "@types/jest": "29.4.4", 46 | "@types/node": "18.14.2", 47 | "@types/react": "18.2.24", 48 | "@types/react-dom": "18.2.9", 49 | "@types/react-router-dom": "5.3.3", 50 | "@typescript-eslint/eslint-plugin": "5.62.0", 51 | "@typescript-eslint/parser": "5.62.0", 52 | "babel-jest": "29.4.3", 53 | "cypress": "^12.2.0", 54 | "eslint": "8.46.0", 55 | "eslint-config-prettier": "9.0.0", 56 | "eslint-plugin-cypress": "2.15.1", 57 | "eslint-plugin-import": "2.27.5", 58 | "eslint-plugin-jsx-a11y": "6.7.1", 59 | "eslint-plugin-react": "7.32.2", 60 | "eslint-plugin-react-hooks": "4.6.0", 61 | "jest": "29.4.3", 62 | "jest-environment-jsdom": "29.4.3", 63 | "jest-preset-angular": "13.1.2", 64 | "ng-packagr": "16.2.3", 65 | "nx": "17.0.3", 66 | "postcss": "8.4.21", 67 | "postcss-import": "14.1.0", 68 | "postcss-preset-env": "7.5.0", 69 | "postcss-url": "10.1.3", 70 | "prettier": "2.6.2", 71 | "react-refresh": "^0.10.0", 72 | "ts-jest": "29.1.1", 73 | "ts-node": "10.9.1", 74 | "typescript": "5.1.6", 75 | "url-loader": "^4.1.1" 76 | }, 77 | "dependencies": { 78 | "@angular-devkit/architect": "0.1602.9", 79 | "@angular-devkit/core": "16.2.9", 80 | "@angular/animations": "16.2.12", 81 | "@angular/common": "16.2.12", 82 | "@angular/compiler": "16.2.12", 83 | "@angular/core": "16.2.12", 84 | "@angular/forms": "16.2.12", 85 | "@angular/platform-browser": "16.2.12", 86 | "@angular/platform-browser-dynamic": "16.2.12", 87 | "@angular/router": "16.2.12", 88 | "core-js": "^3.6.5", 89 | "react": "18.2.0", 90 | "react-dom": "18.2.0", 91 | "react-is": "18.2.0", 92 | "react-router-dom": "6.11.2", 93 | "regenerator-runtime": "0.13.7", 94 | "rxjs": "7.8.1", 95 | "tslib": "^2.3.0", 96 | "zone.js": "0.13.3" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /packages/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marcelh1983/document-viewer/3ca5eb697ea358c7fb62a2dd42e9651f01b5380d/packages/.gitkeep -------------------------------------------------------------------------------- /packages/docviewhelper/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nrwl/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/docviewhelper/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/docviewhelper/README.md: -------------------------------------------------------------------------------- 1 | # docviewer-helper 2 | 3 | This library is created to share helper functions to view documents in as well ngx-doc-viewer and react-documents -------------------------------------------------------------------------------- /packages/docviewhelper/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'docviewer-helper', 4 | preset: '../../../jest.preset.js', 5 | globals: {}, 6 | transform: { 7 | '^.+\\.[tj]sx?$': [ 8 | 'ts-jest', 9 | { 10 | tsconfig: '/tsconfig.spec.json', 11 | }, 12 | ], 13 | }, 14 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 15 | coverageDirectory: '../../../coverage/packages/docviewer/helper', 16 | }; 17 | -------------------------------------------------------------------------------- /packages/docviewhelper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docviewhelper", 3 | "version": "0.0.2", 4 | "license": "MIT", 5 | "description": "Helper for ngx-doc-viewer and react-documents.", 6 | "author": { 7 | "name": "Marcel Hoekstra", 8 | "email": "marcel.hoekstra@outlook.com", 9 | "url": "https://github.com/Marcelh1983/" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/Marcelh1983/document-viewer.git" 14 | }, 15 | "keywords": [ 16 | "ngx-doc-viewer", 17 | "react-documents" 18 | ], 19 | "main": "index.js", 20 | "types": "packages/react-documents/src/index.d.ts", 21 | "bugs": { 22 | "url": "https://github.com/Marcelh1983/document-viewer/issues" 23 | }, 24 | "homepage": "https://github.com/Marcelh1983/document-viewer/tree/main/packages/docviewhelper" 25 | } 26 | -------------------------------------------------------------------------------- /packages/docviewhelper/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docviewhelper", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/docviewhelper/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "@nx/rollup:rollup", 9 | "dependsOn": [ 10 | { 11 | "target": "build", 12 | "dependencies": true 13 | } 14 | ], 15 | "outputs": ["{options.outputPath}"], 16 | "options": { 17 | "outputPath": "dist/packages/docviewhelper", 18 | "tsConfig": "packages/docviewhelper/tsconfig.lib.json", 19 | "project": "packages/docviewhelper/package.json", 20 | "entryFile": "packages/docviewhelper/src/index.ts", 21 | "rollupConfig": "@nx/react/plugins/bundle-rollup", 22 | "compiler": "babel", 23 | "assets": [ 24 | { 25 | "glob": "packages/docviewhelper/README.md", 26 | "input": ".", 27 | "output": "." 28 | } 29 | ] 30 | } 31 | }, 32 | "lint": { 33 | "executor": "@nx/eslint:lint", 34 | "outputs": ["{options.outputFile}"], 35 | "options": { 36 | "lintFilePatterns": ["packages/docviewhelper/**/*.ts"] 37 | } 38 | }, 39 | "test": { 40 | "executor": "@nx/jest:jest", 41 | "outputs": ["{workspaceRoot}/coverage/packages/docviewhelper"], 42 | "options": { 43 | "jestConfig": "packages/docviewhelper/jest.config.ts", 44 | "passWithNoTests": true 45 | } 46 | } 47 | }, 48 | "tags": [] 49 | } 50 | -------------------------------------------------------------------------------- /packages/docviewhelper/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/helper'; 2 | export * from './lib/model'; 3 | -------------------------------------------------------------------------------- /packages/docviewhelper/src/lib/helper.test.ts: -------------------------------------------------------------------------------- 1 | import { getViewerDetails } from './helper'; 2 | 3 | describe(`test url`, () => { 4 | it('works', async () => { 5 | const url = getViewerDetails( 6 | 'http://www.africau.edu/images/default/sample.pdf' 7 | ); 8 | const response = fetch(url.url); 9 | console.log(response); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/docviewhelper/src/lib/helper.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line no-var 2 | declare var mammoth: any; 3 | import { IFrameReloader, ViewerType } from './model'; 4 | 5 | export const fileToArray = (url: string): Promise => { 6 | return new Promise((resolve, reject) => { 7 | try { 8 | const request = new XMLHttpRequest(); 9 | request.open('GET', url, true); 10 | request.responseType = 'blob'; 11 | request.onload = () => { 12 | const reader = new FileReader(); 13 | reader.readAsArrayBuffer(request.response); 14 | reader.onloadend = () => { 15 | resolve(reader.result as ArrayBuffer); 16 | }; 17 | }; 18 | request.send(); 19 | } catch { 20 | reject(`error while retrieving file ${url}.`); 21 | } 22 | }); 23 | }; 24 | 25 | export const timeout = (ms: number) => { 26 | return new Promise(resolve => setTimeout(resolve, ms)); 27 | } 28 | 29 | const reloadIFrame = (iframe: HTMLIFrameElement) => { 30 | if (iframe) { 31 | const url = iframe.src; 32 | iframe.src = 'about:blank'; 33 | setTimeout(() => { 34 | if (iframe) { 35 | iframe.src = url; 36 | }; 37 | }, 100) 38 | 39 | } 40 | }; 41 | 42 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 43 | export const handleFileUpload = (fileInput: any) => { 44 | return new Promise((resolve, reject) => { 45 | if (fileInput.target.files && fileInput.target.files[0]) { 46 | const reader = new FileReader(); 47 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 48 | reader.onload = (e: any) => { 49 | resolve(e.target.result); 50 | }; 51 | reader.readAsDataURL(fileInput.target.files[0]); 52 | } else { 53 | reject('no files selected'); 54 | } 55 | }); 56 | }; 57 | 58 | export const getbaseUrl = (): string => { 59 | const pathArray = window.location.href.split('/'); 60 | const protocol = pathArray[0]; 61 | const host = pathArray[2]; 62 | return protocol + '//' + host; 63 | }; 64 | 65 | 66 | export const getLocation = (href: string) => { 67 | // eslint-disable-next-line no-useless-escape 68 | const match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/); 69 | return match && { 70 | href, 71 | protocol: match[1], 72 | host: match[2], 73 | hostname: match[3], 74 | port: match[4], 75 | pathname: match[5], 76 | search: match[6], 77 | hash: match[7] 78 | } 79 | } 80 | 81 | export const getDocxToHtml = async (url: string) => { 82 | if (!mammoth) { 83 | console.error( 84 | 'Please install mammoth and make sure mammoth.browser.min.js is loaded.' 85 | ); 86 | } 87 | const arrayBuffer = await fileToArray(url); 88 | const resultObject = await mammoth.convertToHtml({ arrayBuffer }); 89 | return resultObject.value; 90 | }; 91 | 92 | export const googleCheckSubscription = (): IFrameReloader => { 93 | let subscription: any = null; 94 | let checkCount = 0; 95 | return { 96 | subscribe: (iframe: HTMLIFrameElement, interval = 3000, maxChecks = 5) => { 97 | if (!iframeIsLoaded(iframe)) { 98 | subscription = setInterval(() => { 99 | checkCount++; 100 | if (checkCount >= maxChecks) { 101 | clearInterval(subscription); 102 | } 103 | reloadIFrame(iframe); 104 | }, interval); 105 | return subscription; 106 | } else { 107 | if (subscription) { 108 | clearInterval(subscription); 109 | } 110 | } 111 | }, 112 | unsubscribe: () => { 113 | if (subscription) { 114 | clearInterval(subscription); 115 | } 116 | }, 117 | }; 118 | }; 119 | 120 | export const iframeIsLoaded = (iframe: HTMLIFrameElement) => { 121 | // its #document when google is returning a 204 122 | // so if contentDocument = null then it's loaded. 123 | let isLoaded = false; 124 | try { 125 | if (!internetExplorer()) { 126 | isLoaded = !iframe?.contentDocument; 127 | } else { 128 | isLoaded = !iframe?.contentWindow?.document; 129 | } 130 | } catch { 131 | // ignore message Blocked a frame with origin "http://..." from accessing a cross-origin frame. 132 | } 133 | return isLoaded; 134 | } 135 | 136 | const internetExplorer = () => 137 | (/MSIE (\d+\.\d+);/.test(navigator.userAgent) || navigator.userAgent.indexOf("Trident/") > -1); 138 | 139 | export const getViewerDetails = ( 140 | url: string, 141 | configuredViewer: ViewerType = 'google', 142 | queryParams = '', 143 | viewerUrl = '' 144 | ) => { 145 | switch (configuredViewer) { 146 | case 'google': 147 | viewerUrl = `https://docs.google.com/gview?url=%URL%&embedded=true`; 148 | break; 149 | case 'office': { 150 | viewerUrl = `https://view.officeapps.live.com/op/embed.aspx?src=%URL%`; 151 | break; 152 | } 153 | case 'pdf': { 154 | viewerUrl = ''; 155 | break; 156 | } 157 | } 158 | const externalViewer = 159 | configuredViewer === 'google' || 160 | configuredViewer === 'office' || 161 | configuredViewer === 'url'; 162 | 163 | const u = url?.indexOf('/') ? encodeURIComponent(url) : url; 164 | let fullUrl = viewerUrl ? viewerUrl.replace('%URL%', u) : url; 165 | if (queryParams && externalViewer && configuredViewer !== 'url') { 166 | const start = queryParams.startsWith('&') ? '' : '&'; 167 | fullUrl = `${fullUrl}${start}${queryParams}`; 168 | } 169 | return { 170 | url: fullUrl, 171 | externalViewer, 172 | }; 173 | }; 174 | 175 | export const replaceLocalUrl = (url: string, overrideLocalhost: string) => { 176 | const loc = getLocation(url); 177 | const locReplace = getLocation(overrideLocalhost); 178 | if (loc && locReplace) { 179 | return url.replace(loc.port ? `${loc.hostname}:${loc.port}` : loc.hostname, 180 | locReplace.port ? `${locReplace.hostname}:${locReplace.port}` : locReplace.hostname); 181 | } 182 | return url; 183 | } 184 | 185 | const getBlobFromUrl = (url: string) => { 186 | return new Promise((resolve, reject) => { 187 | const request = new XMLHttpRequest(); 188 | request.open('GET', url, true); 189 | request.responseType = 'blob'; 190 | request.onload = () => { 191 | resolve(request.response as File); 192 | }; 193 | request.onerror = reject; 194 | request.send(); 195 | }) 196 | } 197 | 198 | 199 | export const uploadToCloud = (fileUrl: string, api: string) => new Promise((resolve, reject) => { 200 | getBlobFromUrl(fileUrl).then(blob => { 201 | const loc = getLocation(fileUrl); 202 | const name = loc?.pathname ? loc?.pathname?.split('/')[loc?.pathname?.split('/').length - 1] : ''; 203 | const formData = new FormData(); 204 | const request = new XMLHttpRequest(); 205 | formData.append('file', blob, name); 206 | request.onreadystatechange = e => { 207 | if (request.readyState === XMLHttpRequest.DONE) { 208 | if (request.status === 200) { 209 | resolve(request.responseText); 210 | } else { 211 | reject(request.responseText); 212 | } 213 | } 214 | }; 215 | request.onerror = reject; 216 | request.open('post', api, true); 217 | request.send(formData); 218 | }); 219 | }); 220 | 221 | export const isLocalFile = (file: string) => { 222 | const loc = getLocation(file); 223 | const hostname = loc?.hostname || ''; 224 | return ( 225 | (['localhost', '127.0.0.1', '', '::1'].includes(hostname)) 226 | || (hostname.startsWith('192.168.')) 227 | || (hostname.startsWith('10.0.')) 228 | || (hostname.endsWith('.local')) 229 | ) 230 | }; -------------------------------------------------------------------------------- /packages/docviewhelper/src/lib/model.ts: -------------------------------------------------------------------------------- 1 | export type ViewerType = 'google' | 'office' | 'mammoth' | 'pdf' | 'url'; 2 | 3 | interface Props { 4 | loaded?: () => void; 5 | url: string; 6 | queryParams?: string; 7 | viewerUrl?: string; 8 | googleCheckInterval?: number; 9 | disableContent?: 'none' | 'all' | 'poput' | 'popout-hide'; 10 | googleCheckContentLoaded?: boolean; 11 | viewer?: ViewerType; 12 | } 13 | 14 | export interface IFrameReloader { 15 | subscribe: ( 16 | iframe: HTMLIFrameElement, 17 | interval?: number, 18 | maxChecks?: number 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | ) => any; 21 | unsubscribe: () => void; 22 | } 23 | 24 | export const defaultProps: Props = { 25 | // eslint-disable-next-line @typescript-eslint/no-empty-function 26 | loaded: () => {}, 27 | disableContent: 'none', 28 | googleCheckContentLoaded: true, 29 | googleCheckInterval: 3000, 30 | queryParams: '', 31 | url: '', 32 | viewer: 'google', 33 | viewerUrl: '', 34 | }; 35 | -------------------------------------------------------------------------------- /packages/docviewhelper/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ], 13 | "compilerOptions": { 14 | "forceConsistentCasingInFileNames": true, 15 | "strict": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/docviewhelper/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "declaration": true, 6 | "types": [] 7 | }, 8 | "include": ["**/*.ts"], 9 | "exclude": ["**/*.spec.ts", "jest.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/docviewhelper/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.test.ts", 10 | "**/*.spec.ts", 11 | "**/*.test.tsx", 12 | "**/*.spec.tsx", 13 | "**/*.test.js", 14 | "**/*.spec.js", 15 | "**/*.test.jsx", 16 | "**/*.spec.jsx", 17 | "**/*.d.ts", 18 | "jest.config.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "documentViewer", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "document-viewer", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/README.md: -------------------------------------------------------------------------------- 1 | # ngx-doc-viewer 2 | 3 | This component can be used to show several different document types in an Angular app. 4 | 5 | Documents that are publicly available can be shown in an iframe using the google or office document viewer. 6 | 7 | Pdf files and word document that are not publicly available can be shown using the mammoth viewer or pdf viewer by passing an objectUrl. 8 | 9 | View demo 10 | 11 | Changes 12 | 13 | ### Install the NPM Module 14 | 15 | ```sh 16 | npm install ngx-doc-viewer --save 17 | ``` 18 | 19 | ### Usage 20 | 21 | #### 1. Import `NgxDocViewerModule` 22 | 23 | ```ts 24 | @NgModule({ 25 | imports: [NgxDocViewerModule], 26 | }) 27 | export class AppModule {} 28 | ``` 29 | 30 | #### 2. Add DocViewer to component: 31 | 32 | ```html 33 | 38 | ``` 39 | 40 | To 41 | 42 | #### API: 43 | 44 | Input: 45 | 46 | - url: document url. 47 | - viewer: google (default), office, mammoth, pdf or url 48 | - viewerUrl: only for viewer: 'url'; location of the document renderer. Only use this option for other viewers then google or office. 49 | - queryParams, e.g. to set language. for google: hl=[lang] e.g. hl=nl 50 | - disableContent: 'none' | 'all' | 'popout' | 'popout-hide' = 'none': 51 | - none: no overlay 52 | - all: adds an overlay to the whole iframe, which makes nothing in the document clickable/selectable 53 | - popout: adds an overlay over googles popout button or office popout and menu which disables just this button/menu but keeps giving the possibility to select text. The popout button is still visible (for google during a few seconds) but not clickable. 54 | - popout-hide: see popup, instead of an transparent overlay a white one. This really hides the button but you'll see a white block while loading for the google viewer. 55 | - overrideLocalhost: documents from the assets folder are not publicly available and therefor won't show in an external viewer (google, office). If the site is already published to public server, then pass that url and if will replace localhost by the other url. Like: overrideLocalhost="https://angular-doc-viewer.firebaseapp.com/" 56 | 57 | There are some issues loading document in the google viewer. See: https://stackoverflow.com/questions/40414039/google-docs-viewer-returning-204-responses-no-longer-working-alternatives. If loading pdf's and Word documents, seems to work now with this hack let me know via a Github issue. 58 | 59 | - googleCheckContentLoaded = true | If true it will check by interval if the content is loaded. 60 | - googleCheckInterval = 3000 | The interval in milliseconds that is checked whether the iframe is loaded. 61 | - googleMaxChecks = 5 | max number of retries 62 | Output: 63 | 64 | - loaded: google only, notifies when iframe is loaded. Can be used to show progress while loading 65 | 66 | ### File type support 67 | 68 | #### office viewer 69 | 70 | .ppt, .pptx, .doc, .docx, .xls and .xlsx 71 | 72 | #### google viewer 73 | 74 | Only files under 25 MB can be previewed with the Google Drive viewer. 75 | 76 | Google Drive viewer helps you preview over 15 different file types, listed below: 77 | 78 | - Text files (.TXT) 79 | - Markup/Code (.CSS, .HTML, .PHP, .C, .CPP, .H, .HPP, .JS) 80 | - Microsoft Word (.DOC and .DOCX) 81 | - Microsoft Excel (.XLS and .XLSX) 82 | - Microsoft PowerPoint (.PPT and .PPTX) 83 | - Adobe Portable Document Format (.PDF) 84 | - Apple Pages (.PAGES) 85 | - Adobe Illustrator (.AI) 86 | - Adobe Photoshop (.PSD) 87 | - Tagged Image File Format (.TIFF) 88 | - Autodesk AutoCad (.DXF) 89 | - Scalable Vector Graphics (.SVG) 90 | - PostScript (.EPS, .PS) 91 | - TrueType (.TTF) 92 | - XML Paper Specification (.XPS) 93 | - Archive file types (.ZIP and .RAR) 94 | 95 | Source 96 | 97 | #### url 98 | 99 | For another external document viewers that should be loaded in an iframe. 100 | 101 | For Google Drive 102 | 103 | ```html 104 | 109 | 110 | ``` 111 | 112 | For the Google Viewer or any other viewer where there is a base url and a parameter for the documentUrl: 113 | 114 | ```html 115 | 121 | 122 | ``` 123 | 124 | ### pdf 125 | 126 | .pdf 127 | 128 | NOTE: PDF's are shown in the embed tag. Browser support is not guaranteed. If you need to be sure the pdf renders on all browsers you better use PDF.js 129 | 130 | ### mammoth 131 | 132 | .docx 133 | 134 | To use mammoth, also add: 135 | 136 | ```sh 137 | npm install mammoth --save 138 | ``` 139 | 140 | and make sure mammoth.browser.min.js is loaded. For the angular/cli you would add the following in angular.json: 141 | 142 | ```json 143 | "scripts": [ 144 | "node_modules/mammoth/mammoth.browser.min.js" 145 | ] 146 | ``` 147 | 148 | ## My other packages 149 | 150 | - ngx-event-handler: advance event handling like click-outside with serval options: [npm](https://www.npmjs.com/package/ngx-event-handler) | [github](https://github.com/Marcelh1983/angular-event-handler) | [demo](https://stackblitz.com/edit/ngx-event-handler) 151 | - ngx-edit-inline: basic inline edit component: [npm](https://www.npmjs.com/package/ngx-edit-inline) | [github](https://github.com/Marcelh1983/angular-inline-edit) | [demo](https://ngx-edit-inline.firebaseapp.com/) 152 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/changelog.md: -------------------------------------------------------------------------------- 1 | # 15.0.1 (12/14/2022) 2 | * update dependencies 3 | * removed console logs 4 | # 2.1.3 (09/07/2022) 5 | * update dependencies 6 | 7 | # 2.1.1 (01/07/2022) 8 | * fixed pdf viewer #37 9 | 10 | # 2.1.0 (01/04/2022) 11 | * upgraded dependencies 12 | * added dependency on docviewhelper which is a new package to be able to share code between react-documents and ngx-doc-viewer 13 | 14 | # 2.0.0 (03/18/2021) 15 | * fix for (sometimes) not showing google documents 16 | * option to override localhost in url, work-around to test assets hosted in the assets folder. 17 | * replaced rx interval to window interval to be independent of rx 18 | * created helpers that also can be used for react version 19 | 20 | # 1.4.0 (11/17/2020) 21 | * upgraded to angular 11 22 | * migrated to eslint 23 | 24 | # 1.3.0 (08/05/2020) 25 | * better way to check if iframe is loaded. Fix for unnecessary reload 26 | * object tag instead of embed thanks to @mediantiba 27 | * upgraded dependencies 28 | 29 | # 1.2.3 (07/22/2020) 30 | * merge fix by @itsLucario for accessing iframe by QueryList (ElementRef instead of HTMLIFrameelement) 31 | 32 | # 1.2.2 (07/21/2020) 33 | * support for multiple iframes 34 | 35 | # 1.2.1 (07/16/2020) 36 | * upgraded packages 37 | * updated broken links in demo project 38 | 39 | # 1.2.0 (06/30/2020) 40 | * upgraded to Angular 10 41 | 42 | # 1.0.5 (04/23/2020) 43 | * added 'url' viewer to support exteral viewers other then google and office 44 | 45 | # 1.0.4 (03/05/2020) 46 | * added option to pass queryParams, e.g. to set language. for google: hl=[lang] e.g. hl=nl 47 | 48 | # 1.0.1 (02/12/2019) 49 | * updated packages 50 | 51 | # 1.0.0 (01/10/2019) 52 | * added support for objectUrls docx and pdf files (docx using mammoth see readme, pdf using embedded viewer) 53 | * added option to add an overlay to disable/hide office popout button and menu. 54 | 55 | # 0.1.27 (01/08/2019) 56 | * added option to add an overlay to disable/hide googles popout button, and/or selecting text. 57 | 58 | # 0.1.26 (01/08/2019) 59 | * fix for error when url is changed from != null to null 60 | 61 | # 0.1.25 (10/25/2019) 62 | * added googleCheckContentLoaded to be able to skip the check if the iframe content is loaded 63 | 64 | # 0.1.21 (10/22/2019) 65 | * support for angular9 66 | 67 | # 0.1.20 (6/12/2019) 68 | * use angular8 69 | * act on viewer change 70 | 71 | # 0.1.19 (5/27/2019) 72 | * if iframe is null initially try to get it while polling if loaded. 73 | * try for 20 seconds to load document 74 | 75 | # 0.1.17 (5/24/2019) 76 | * fixed interval reload check 77 | 78 | # 0.1.16 (5/24/2019) 79 | * fixed wrong import of Event type 80 | 81 | # 0.1.15 (5/20/2019) 82 | * Added loaded event to notify when google iframe is loaded (google only) 83 | * Interval time back to 3000ms 84 | 85 | # 0.1.14 (5/20/2019) 86 | * Google Hack from AfterviewInit to ngOnChanges 87 | 88 | # 0.1.13 (5/20/2019) 89 | * support changing url with ngOnChanges -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'ngx-doc-viewer', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: {}, 7 | coverageDirectory: '../../coverage/packages/ngx-doc-viewer', 8 | transform: { 9 | '^.+\\.(ts|mjs|js|html)$': [ 10 | 'jest-preset-angular', 11 | { 12 | tsconfig: '/tsconfig.spec.json', 13 | stringifyContentPathRegex: '\\.(html|svg)$', 14 | }, 15 | ], 16 | }, 17 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/serializers/no-ng-attributes', 20 | 'jest-preset-angular/build/serializers/ng-snapshot', 21 | 'jest-preset-angular/build/serializers/html-comment', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/packages/ngx-doc-viewer", 4 | "lib": { 5 | "entryFile": "./src/index.ts" 6 | }, 7 | "allowedNonPeerDependencies": [ 8 | "docviewhelper" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-doc-viewer", 3 | "version": "16.0.0", 4 | "private": false, 5 | "license": "MIT", 6 | "description": "Angular document viewer.", 7 | "author": { 8 | "name": "Marcel Hoekstra", 9 | "email": "marcel.hoekstra@outlook.com", 10 | "url": "https://github.com/Marcelh1983/" 11 | }, 12 | "funding": [ 13 | { 14 | "type": "individual", 15 | "url": "https://www.patreon.com/marcelh1983" 16 | }, 17 | { 18 | "type": "individual", 19 | "url": "https://www.buymeacoffee.com/marcelh1983" 20 | } 21 | ], 22 | "homepage": "https://github.com/Marcelh1983/document-viewer/tree/main/packages/ngx-doc-viewer", 23 | "peerDependencies": { 24 | "@angular/core": ">= 10.0.0", 25 | "@angular/platform-browser": ">= 10.0.0", 26 | "@angular/common": ">= 10.0.0" 27 | }, 28 | "dependencies": { 29 | "docviewhelper": ">= 0.0.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-doc-viewer", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "packages/ngx-doc-viewer/src", 6 | "prefix": "document-viewer", 7 | "targets": { 8 | "build": { 9 | "dependsOn": [ 10 | { 11 | "target": "build", 12 | "dependencies": true 13 | } 14 | ], 15 | "executor": "@nx/angular:package", 16 | "outputs": ["{workspaceRoot}/dist/packages/ngx-doc-viewer"], 17 | "options": { 18 | "project": "packages/ngx-doc-viewer/ng-package.json", 19 | "updateBuildableProjectDepsInPackageJson": true 20 | }, 21 | "configurations": { 22 | "production": { 23 | "tsConfig": "packages/ngx-doc-viewer/tsconfig.lib.prod.json" 24 | }, 25 | "development": { 26 | "tsConfig": "packages/ngx-doc-viewer/tsconfig.lib.json" 27 | } 28 | }, 29 | "defaultConfiguration": "production" 30 | }, 31 | "test": { 32 | "executor": "@nx/jest:jest", 33 | "outputs": ["{workspaceRoot}/coverage/packages/ngx-doc-viewer"], 34 | "options": { 35 | "jestConfig": "packages/ngx-doc-viewer/jest.config.ts", 36 | "passWithNoTests": true 37 | } 38 | }, 39 | "lint": { 40 | "executor": "@nx/eslint:lint", 41 | "options": { 42 | "lintFilePatterns": [ 43 | "packages/ngx-doc-viewer/src/**/*.ts", 44 | "packages/ngx-doc-viewer/src/**/*.html" 45 | ] 46 | } 47 | } 48 | }, 49 | "tags": [] 50 | } 51 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/document-viewer.module'; 2 | export * from './lib/document-viewer.component'; 3 | export * from 'docviewhelper'; -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/src/lib/document-viewer.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 10 |

11 | Your browser does not support PDFs. 12 | Download the PDF. 13 |

14 |
15 |
16 | 17 | 25 |
26 |
40 | 48 |
49 |
50 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/src/lib/document-viewer.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | Input, 4 | NgZone, 5 | OnDestroy, 6 | OnChanges, 7 | SimpleChanges, 8 | Output, 9 | ViewChildren, 10 | QueryList, 11 | ElementRef, 12 | AfterViewInit, 13 | } from '@angular/core'; 14 | import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; 15 | import { EventEmitter } from '@angular/core'; 16 | // eslint-disable-next-line @nx/enforce-module-boundaries 17 | import { 18 | getDocxToHtml, 19 | getViewerDetails, 20 | googleCheckSubscription, 21 | iframeIsLoaded, 22 | isLocalFile, 23 | replaceLocalUrl, 24 | IFrameReloader, 25 | } from 'docviewhelper'; 26 | 27 | // eslint-disable-next-line @typescript-eslint/naming-convention 28 | export type viewerType = 'google' | 'office' | 'mammoth' | 'pdf' | 'url'; 29 | @Component({ 30 | // eslint-disable-next-line @angular-eslint/component-selector 31 | selector: 'ngx-doc-viewer', 32 | templateUrl: 'document-viewer.component.html', 33 | styles: [ 34 | ` 35 | :host { 36 | display: block; 37 | } 38 | .container { 39 | width: 100%; 40 | height: 100%; 41 | position: relative; 42 | } 43 | .overlay-popout-google { 44 | width: 40px; 45 | height: 40px; 46 | right: 26px; 47 | top: 11.5px; 48 | position: absolute; 49 | z-index: 1000; 50 | } 51 | .overlay-popout-office { 52 | width: 100px; 53 | height: 20px; 54 | right: 0; 55 | bottom: 0; 56 | position: absolute; 57 | z-index: 1000; 58 | } 59 | .overlay-full { 60 | width: 100%; 61 | height: 100%; 62 | right: 0; 63 | top: 0; 64 | position: absolute; 65 | z-index: 1000; 66 | } 67 | iframe { 68 | width: 100%; 69 | height: 100%; 70 | } 71 | `, 72 | ], 73 | }) 74 | export class NgxDocViewerComponent 75 | implements OnChanges, OnDestroy, AfterViewInit 76 | { 77 | @Output() loaded: EventEmitter = new EventEmitter(); 78 | @Input() url = ''; 79 | @Input() queryParams = ''; 80 | @Input() viewerUrl = ''; 81 | @Input() googleCheckInterval = 3000; 82 | @Input() googleMaxChecks = 5; 83 | @Input() disableContent: 'none' | 'all' | 'popout' | 'popout-hide' = 'none'; 84 | @Input() googleCheckContentLoaded = true; 85 | @Input() viewer: viewerType = 'google'; 86 | @Input() overrideLocalhost = ''; 87 | @ViewChildren('iframe') iframes?: QueryList = undefined; 88 | 89 | public fullUrl?: SafeResourceUrl = undefined; 90 | public externalViewer = false; 91 | public docHtml = ''; 92 | public configuredViewer: viewerType = 'google'; 93 | private checkIFrameSubscription?: IFrameReloader = undefined; 94 | private shouldCheckIframe = false; 95 | 96 | constructor(private domSanitizer: DomSanitizer, private ngZone: NgZone) {} 97 | 98 | ngAfterViewInit(): void { 99 | if (this.shouldCheckIframe) { 100 | const iframe = this.iframes?.first?.nativeElement as HTMLIFrameElement; 101 | if (iframe) { 102 | this.shouldCheckIframe = false; 103 | this.reloadIframe(iframe); 104 | } 105 | } 106 | } 107 | 108 | ngOnDestroy(): void { 109 | if (this.checkIFrameSubscription) { 110 | this.checkIFrameSubscription.unsubscribe(); 111 | } 112 | } 113 | 114 | async ngOnChanges(changes: SimpleChanges): Promise { 115 | if ( 116 | changes && 117 | changes['viewer'] && 118 | (changes['viewer'].firstChange || 119 | changes['viewer'].currentValue !== changes['viewer'].previousValue) 120 | ) { 121 | if ( 122 | this.viewer !== 'google' && 123 | this.viewer !== 'office' && 124 | this.viewer !== 'mammoth' && 125 | this.viewer !== 'pdf' && 126 | this.viewer !== 'url' 127 | ) { 128 | console.error( 129 | `Unsupported viewer: '${this.viewer}'. Supported viewers: google, office, mammoth and pdf` 130 | ); 131 | } 132 | this.configuredViewer = this.viewer; 133 | } 134 | 135 | if ( 136 | (changes['url'] && 137 | changes['url'].currentValue !== changes['url'].previousValue) || 138 | (changes['viewer'] && 139 | changes['viewer'].currentValue !== changes['viewer'].previousValue) || 140 | (changes['viewerUrl'] && 141 | changes['viewerUrl'].currentValue !== 142 | changes['viewerUrl'].previousValue) 143 | ) { 144 | let viewerDetails = getViewerDetails( 145 | this.url, 146 | this.configuredViewer, 147 | this.queryParams, 148 | this.viewerUrl 149 | ); 150 | this.externalViewer = viewerDetails.externalViewer; 151 | if ( 152 | viewerDetails.externalViewer && 153 | this.overrideLocalhost && 154 | isLocalFile(this.url) 155 | ) { 156 | const newUrl = replaceLocalUrl(this.url, this.overrideLocalhost); 157 | viewerDetails = getViewerDetails( 158 | newUrl, 159 | this.configuredViewer, 160 | this.queryParams, 161 | this.viewerUrl 162 | ); 163 | } 164 | this.docHtml = ''; 165 | if (this.checkIFrameSubscription) { 166 | this.checkIFrameSubscription.unsubscribe(); 167 | } 168 | if (!this.url) { 169 | this.fullUrl = undefined; 170 | } else if ( 171 | viewerDetails.externalViewer || 172 | this.configuredViewer === 'url' || 173 | this.configuredViewer === 'pdf' 174 | ) { 175 | this.fullUrl = this.domSanitizer.bypassSecurityTrustResourceUrl( 176 | viewerDetails.url 177 | ); 178 | // see: 179 | // https://stackoverflow.com/questions/40414039/google-docs-viewer-returning-204-responses-no-longer-working-alternatives 180 | // hack to reload iframe if it's not loaded. 181 | // would maybe be better to use view.officeapps.live.com but seems not to work with sas token. 182 | if ( 183 | this.configuredViewer === 'google' && 184 | this.googleCheckContentLoaded 185 | ) { 186 | this.ngZone.runOutsideAngular(() => { 187 | // if it's not loaded after the googleIntervalCheck, then open load again. 188 | const iframe = this.iframes?.first 189 | ?.nativeElement as HTMLIFrameElement; 190 | if (iframe) { 191 | this.reloadIframe(iframe); 192 | } else { 193 | this.shouldCheckIframe = true; 194 | } 195 | }); 196 | } 197 | } else if (this.configuredViewer === 'mammoth') { 198 | this.docHtml = await getDocxToHtml(this.url); 199 | } 200 | } 201 | } 202 | 203 | private reloadIframe(iframe: HTMLIFrameElement) { 204 | this.checkIFrameSubscription = googleCheckSubscription(); 205 | this.checkIFrameSubscription.subscribe( 206 | iframe, 207 | this.googleCheckInterval, 208 | this.googleMaxChecks 209 | ); 210 | } 211 | 212 | iframeLoaded() { 213 | const iframe = this.iframes?.first?.nativeElement as HTMLIFrameElement; 214 | if (iframe && iframeIsLoaded(iframe)) { 215 | this.loaded.emit(undefined); 216 | if (this.checkIFrameSubscription) { 217 | this.checkIFrameSubscription.unsubscribe(); 218 | } 219 | } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/src/lib/document-viewer.module.ts: -------------------------------------------------------------------------------- 1 | import { NgxDocViewerComponent } from './document-viewer.component'; 2 | import { NgModule } from '@angular/core'; 3 | import { CommonModule } from '@angular/common'; 4 | 5 | @NgModule({ 6 | imports: [CommonModule], 7 | declarations: [NgxDocViewerComponent], 8 | exports: [NgxDocViewerComponent], 9 | }) 10 | export class NgxDocViewerModule {} 11 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.lib.prod.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "strict": true, 19 | "noImplicitOverride": true, 20 | "noPropertyAccessFromIndexSignature": true, 21 | "noImplicitReturns": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "target": "es2020" 24 | }, 25 | "angularCompilerOptions": { 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": [ 11 | "src/test-setup.ts", 12 | "**/*.spec.ts", 13 | "**/*.test.ts", 14 | "jest.config.ts" 15 | ], 16 | "include": ["**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | }, 9 | "exclude": ["jest.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/ngx-doc-viewer/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/react-documents/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/react/babel", 5 | { 6 | "runtime": "automatic", 7 | "useBuiltIns": "usage" 8 | } 9 | ] 10 | ], 11 | "plugins": [] 12 | } 13 | -------------------------------------------------------------------------------- /packages/react-documents/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:@nx/react", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/react-documents/README.md: -------------------------------------------------------------------------------- 1 | # react-documents 2 | This component can be used to show several different document types in a React app. 3 | 4 | Documents that are publicly available can be shown in an iframe using the google or office document viewer. 5 | 6 | Pdf files and word document that are not publicly available can be shown using the mammoth viewer or pdf viewer by passing an objectUrl. 7 | 8 | This package is created from [ngx-doc-viewer](https://github.com/Marcelh1983/document-viewer/blob/main/libs/ngx-doc-viewer/) which is the Angular version. 9 | 10 | View demo 11 | 12 | Changes 13 | 14 | ### Install the NPM Module 15 | 16 | ```sh 17 | npm install react-documents --save 18 | ``` 19 | 20 | ### Usage 21 | 22 | #### 1. Add DocViewer to component: 23 | 24 | ```ts 25 | import { DocumentViewer } from 'react-documents'; 26 | ``` 27 | 28 | ```tsx 29 | 35 | 36 | ``` 37 | 38 | To 39 | 40 | #### API: 41 | 42 | Props: 43 | 44 | - url: document url. 45 | - viewer: google (default), office, mammoth, pdf or url 46 | - viewerUrl: only for viewer: 'url'; location of the document renderer. Only use this option for other viewers then google or office. 47 | - queryParams, e.g. to set language. for google: hl=[lang] e.g. hl=nl 48 | - overrideLocalhost: documents from the assets folder are not publicly available and therefor won't show in an external viewer (google, office). If the site is already published to public server, then pass that url and if will replace localhost by the other url. Like: overrideLocalhost="https://react-documents.firebaseapp.com/" 49 | 50 | There are some issues loading document in the google viewer. See: https://stackoverflow.com/questions/40414039/google-docs-viewer-returning-204-responses-no-longer-working-alternatives. If loading pdf's and Word documents, seems to work now with this hack let me know via a Github issue. 51 | 52 | - googleCheckContentLoaded = true | If true it will check by interval if the content is loaded. 53 | - googleCheckInterval = 3000 | The interval in milliseconds that is checked whether the iframe is loaded. 54 | - googleMaxChecks = 5 | max number of retries 55 | Output: 56 | 57 | - loaded: google only, notifies when iframe is loaded. Can be used to show progress while loading 58 | 59 | ### File type support 60 | 61 | #### office viewer 62 | 63 | .ppt, .pptx, .doc, .docx, .xls and .xlsx 64 | 65 | #### google viewer 66 | 67 | Only files under 25 MB can be previewed with the Google Drive viewer. 68 | 69 | Google Drive viewer helps you preview over 15 different file types, listed below: 70 | 71 | - Text files (.TXT) 72 | - Markup/Code (.CSS, .HTML, .PHP, .C, .CPP, .H, .HPP, .JS) 73 | - Microsoft Word (.DOC and .DOCX) 74 | - Microsoft Excel (.XLS and .XLSX) 75 | - Microsoft PowerPoint (.PPT and .PPTX) 76 | - Adobe Portable Document Format (.PDF) 77 | - Apple Pages (.PAGES) 78 | - Adobe Illustrator (.AI) 79 | - Adobe Photoshop (.PSD) 80 | - Tagged Image File Format (.TIFF) 81 | - Autodesk AutoCad (.DXF) 82 | - Scalable Vector Graphics (.SVG) 83 | - PostScript (.EPS, .PS) 84 | - TrueType (.TTF) 85 | - XML Paper Specification (.XPS) 86 | - Archive file types (.ZIP and .RAR) 87 | 88 | Source 89 | 90 | #### url 91 | 92 | For another external document viewers that should be loaded in an iframe. 93 | 94 | For Google Drive 95 | 96 | ```tsx 97 | 102 | 103 | ``` 104 | 105 | For the Google Viewer or any other viewer where there is a base url and a parameter for the documentUrl: 106 | 107 | ```tsx 108 | 113 | 114 | ``` 115 | 116 | ### pdf 117 | 118 | .pdf 119 | 120 | NOTE: PDF's are shown in the embed tag. Browser support is not guaranteed. If you need to be sure the pdf renders on all browsers you better use PDF.js 121 | 122 | ### mammoth 123 | 124 | .docx 125 | 126 | To use mammoth make sure mammoth.browser.min.js is loaded. Can be added in the index.html 127 | ```html 128 | 133 | ``` 134 | 135 | ## My other packages 136 | 137 | - rx-basic-store: simple rx store for react: [npm](https://www.npmjs.com/package/rx-basic-store) | [github](https://github.com/Marcelh1983/rx-basic-store) | [demo](https://rx-basic-store.web.app/) 138 | 139 | -------------------------------------------------------------------------------- /packages/react-documents/changelog.md: -------------------------------------------------------------------------------- 1 | # 1.1.3 (09/07/2022) 2 | * updated dependencies 3 | 4 | # 1.1.1 (01/07/2022) 5 | * added classname and style properties on object tag 6 | 7 | # 1.1.0 (01/04/2022) 8 | * use docviewhelper to share code between ngx-doc-viewer and react-documents 9 | * added classname and style properties 10 | * use default nx build script 11 | 12 | # 1.0.1 (03/20/2021) 13 | * clean up google refresh subscription in useEffect() 14 | 15 | # 1.0.0 (03/19/2021) 16 | * First release, used code from ngx-doc-viewer 17 | -------------------------------------------------------------------------------- /packages/react-documents/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'react-documents', 4 | preset: '../../jest.preset.js', 5 | transform: { 6 | '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], 7 | }, 8 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 9 | coverageDirectory: '../../coverage/packages/react-documents', 10 | }; 11 | -------------------------------------------------------------------------------- /packages/react-documents/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-documents", 3 | "version": "1.3.0", 4 | "license": "MIT", 5 | "description": "React document viewer.", 6 | "author": { 7 | "name": "Marcel Hoekstra", 8 | "email": "marcel.hoekstra@outlook.com", 9 | "url": "https://github.com/Marcelh1983/" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/Marcelh1983/document-viewer.git" 14 | }, 15 | "keywords": [ 16 | "Store", 17 | "RxJs", 18 | "React" 19 | ], 20 | "funding": [ 21 | { 22 | "type": "individual", 23 | "url": "https://www.patreon.com/marcelh1983" 24 | }, 25 | { 26 | "type": "individual", 27 | "url": "https://www.buymeacoffee.com/marcelh1983" 28 | } 29 | ], 30 | "main": "index.js", 31 | "types": "packages/react-documents/src/index.d.ts", 32 | "bugs": { 33 | "url": "https://github.com/Marcelh1983/document-viewer/issues" 34 | }, 35 | "homepage": "https://github.com/Marcelh1983/document-viewer/tree/main/packages/react-documents", 36 | "peerDependencies": { 37 | "react": ">=16.8.0", 38 | "react-dom": ">=16.8.0" 39 | }, 40 | "dependencies": { 41 | "docviewhelper": ">= 0.0.1" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/react-documents/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-documents", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/react-documents/src", 5 | "projectType": "library", 6 | "tags": [], 7 | "targets": { 8 | "build": { 9 | "executor": "@nx/rollup:rollup", 10 | "dependsOn": [ 11 | { 12 | "target": "build", 13 | "dependencies": true 14 | } 15 | ], 16 | "outputs": ["{options.outputPath}"], 17 | "options": { 18 | "outputPath": "dist/packages/react-documents", 19 | "tsConfig": "packages/react-documents/tsconfig.lib.json", 20 | "project": "packages/react-documents/package.json", 21 | "entryFile": "packages/react-documents/src/index.ts", 22 | "external": ["react/jsx-runtime"], 23 | "rollupConfig": "@nx/react/plugins/bundle-rollup", 24 | "compiler": "babel", 25 | "assets": [ 26 | { 27 | "glob": "packages/react-documents/README.md", 28 | "input": ".", 29 | "output": "." 30 | } 31 | ] 32 | } 33 | }, 34 | "lint": { 35 | "executor": "@nx/eslint:lint", 36 | "outputs": ["{options.outputFile}"], 37 | "options": { 38 | "lintFilePatterns": ["packages/react-documents/**/*.{ts,tsx,js,jsx}"] 39 | } 40 | }, 41 | "test": { 42 | "executor": "@nx/jest:jest", 43 | "outputs": ["{workspaceRoot}/coverage/packages/react-documents"], 44 | "options": { 45 | "jestConfig": "packages/react-documents/jest.config.ts", 46 | "passWithNoTests": true 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/react-documents/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/react-documents'; 2 | export * from 'docviewhelper'; -------------------------------------------------------------------------------- /packages/react-documents/src/lib/react-documents.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties, useEffect, useRef, useState } from 'react'; 2 | import { 3 | IFrameReloader, 4 | googleCheckSubscription, 5 | getViewerDetails, 6 | getDocxToHtml, 7 | iframeIsLoaded, 8 | isLocalFile, 9 | replaceLocalUrl 10 | } from 'docviewhelper'; 11 | 12 | export type viewerType = 'google' | 'office' | 'mammoth' | 'pdf' | 'url'; 13 | 14 | interface Props { 15 | loaded?: () => void; 16 | url: string; 17 | queryParams: string; 18 | viewerUrl: string; 19 | googleCheckInterval: number; 20 | googleMaxChecks: number; 21 | googleCheckContentLoaded: boolean; 22 | viewer: viewerType; 23 | overrideLocalhost: string; 24 | style?: CSSProperties | undefined; 25 | className?: string | undefined; 26 | } 27 | 28 | const defaultProps: Props = { 29 | // eslint-disable-next-line @typescript-eslint/no-empty-function 30 | loaded: () => {}, 31 | googleCheckContentLoaded: true, 32 | googleCheckInterval: 3000, 33 | queryParams: '', 34 | url: '', 35 | overrideLocalhost: '', 36 | googleMaxChecks: 5, 37 | viewer: 'google', 38 | viewerUrl: '', 39 | style: { 40 | width: '100%', 41 | height: '100%', 42 | }, 43 | className: '', 44 | }; 45 | 46 | interface State { 47 | url: string; 48 | externalViewer: boolean; 49 | docHtml: { __html: string }; 50 | isSwitching: boolean; 51 | } 52 | 53 | export const DocumentViewer = (inputProps: Partial) => { 54 | const iframeRef = useRef(null); 55 | const [state, setState] = useState({ 56 | url: '', 57 | isSwitching: false, 58 | externalViewer: true, 59 | docHtml: { __html: '' }, 60 | } as State); 61 | const checkIFrameSubscription = useRef(); 62 | const props = useRef(); 63 | 64 | const setNewurl = async (details: { 65 | url: string; 66 | externalViewer: boolean; 67 | }) => { 68 | if (props.current) { 69 | const iframe = iframeRef.current as unknown as HTMLIFrameElement; 70 | if (checkIFrameSubscription && checkIFrameSubscription.current) { 71 | checkIFrameSubscription.current.unsubscribe(); 72 | } 73 | if ( 74 | props.current.viewer === 'google' && 75 | props.current.googleCheckContentLoaded === true 76 | ) { 77 | reloadIframe( 78 | iframe, 79 | details.url, 80 | props.current.googleCheckInterval, 81 | props.current.googleMaxChecks 82 | ); 83 | } 84 | } 85 | }; 86 | 87 | useEffect(() => { 88 | let timerRef: any; 89 | if (state.isSwitching) { 90 | setState((s) => { 91 | return { ...s, isSwitching: false }; 92 | }); 93 | timerRef = setTimeout(() => { 94 | setNewurl({ url: state.url, externalViewer: state.externalViewer }); 95 | }, 500); 96 | } 97 | return () => { 98 | if (timerRef) { 99 | clearTimeout(timerRef); 100 | } 101 | }; 102 | }, [state.isSwitching]); 103 | 104 | useEffect(() => { 105 | props.current = { ...defaultProps, ...inputProps }; 106 | let details = getViewerDetails( 107 | props.current.url, 108 | props.current.viewer, 109 | props.current.queryParams, 110 | props.current.viewerUrl 111 | ); 112 | if ( 113 | details.externalViewer && 114 | props.current.overrideLocalhost && 115 | isLocalFile(props.current.url) 116 | ) { 117 | const newUrl = replaceLocalUrl( 118 | props.current.url, 119 | props.current.overrideLocalhost 120 | ); 121 | details = getViewerDetails( 122 | newUrl, 123 | props.current.viewer, 124 | props.current.queryParams, 125 | props.current.viewerUrl 126 | ); 127 | } 128 | 129 | setState({ 130 | url: details.url, 131 | externalViewer: details.externalViewer, 132 | isSwitching: false, 133 | docHtml: { __html: '' }, 134 | }); 135 | if (iframeRef && iframeRef.current) { 136 | const iframe = iframeRef.current as unknown as HTMLIFrameElement; 137 | if (iframe.src && iframe.src !== `${window.location.protocol}//${window.location.host}/` && iframe.src !== details.url) { 138 | // url of the iframe is changed, set is switching to true to 139 | // remove the iframe and add it later with the new url; 140 | setState((state) => ({ ...state, isSwitching: true })); 141 | } else { 142 | setNewurl(details); 143 | } 144 | } else if (props.current.viewer === 'mammoth') { 145 | const setHtml = async () => { 146 | const docHtml = { __html: await getDocxToHtml(details.url) }; 147 | setState({ 148 | url: '', 149 | docHtml, 150 | isSwitching: false, 151 | externalViewer: false, 152 | }); 153 | }; 154 | setHtml(); 155 | } 156 | return () => { 157 | if (checkIFrameSubscription && checkIFrameSubscription.current) { 158 | checkIFrameSubscription.current.unsubscribe(); 159 | } 160 | }; 161 | }, [inputProps]); 162 | 163 | const reloadIframe = ( 164 | iframe: HTMLIFrameElement, 165 | url: string, 166 | interval: number, 167 | maxChecks: number 168 | ) => { 169 | checkIFrameSubscription.current = googleCheckSubscription(); 170 | checkIFrameSubscription.current.subscribe(iframe, interval, maxChecks); 171 | }; 172 | 173 | const iframeLoaded = () => { 174 | if ( 175 | props.current && 176 | iframeRef && 177 | iframeRef.current !== null && 178 | iframeIsLoaded(iframeRef.current as unknown as HTMLIFrameElement) 179 | ) { 180 | if (props.current.loaded) props.current.loaded(); 181 | if (checkIFrameSubscription.current) { 182 | checkIFrameSubscription.current.unsubscribe(); 183 | } 184 | } 185 | }; 186 | 187 | return state.isSwitching ? null : state.externalViewer ? ( 188 | 200 | ) : props.current?.viewer !== 'pdf' ? ( 201 |
202 | ) : state.url ? ( 203 | 211 |

212 | Your browser does not support PDFs. 213 | Download the PDF. 214 |

215 |
216 | ) : null; 217 | }; 218 | -------------------------------------------------------------------------------- /packages/react-documents/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "files": [], 16 | "include": [], 17 | "references": [ 18 | { 19 | "path": "./tsconfig.lib.json" 20 | }, 21 | { 22 | "path": "./tsconfig.spec.json" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /packages/react-documents/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": ["node"] 6 | }, 7 | "files": [ 8 | "../../node_modules/@nx/react/typings/cssmodule.d.ts", 9 | "../../node_modules/@nx/react/typings/image.d.ts" 10 | ], 11 | "exclude": [ 12 | "**/*.spec.ts", 13 | "**/*.test.ts", 14 | "**/*.spec.tsx", 15 | "**/*.test.tsx", 16 | "**/*.spec.js", 17 | "**/*.test.js", 18 | "**/*.spec.jsx", 19 | "**/*.test.jsx", 20 | "jest.config.ts" 21 | ], 22 | "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] 23 | } 24 | -------------------------------------------------------------------------------- /packages/react-documents/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.test.ts", 10 | "**/*.spec.ts", 11 | "**/*.test.tsx", 12 | "**/*.spec.tsx", 13 | "**/*.test.js", 14 | "**/*.spec.js", 15 | "**/*.test.jsx", 16 | "**/*.spec.jsx", 17 | "**/*.d.ts", 18 | "jest.config.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@document-viewer/data": ["libs/data/src/index.ts"], 19 | "docviewhelper": ["packages/docviewhelper/src/index.ts"], 20 | "ngx-doc-viewer": ["packages/ngx-doc-viewer/src/index.ts"], 21 | "react-documents": ["packages/react-documents/src/index.ts"] 22 | } 23 | }, 24 | "exclude": ["node_modules", "tmp"] 25 | } 26 | --------------------------------------------------------------------------------