├── .browserslistrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── codeql-analysis.yml │ └── publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── build └── rollup.config.js ├── dev ├── serve.js └── serve.vue ├── package-lock.json ├── package.json ├── src ├── Pdfvuer.vue ├── assets │ └── logo.png ├── cmap.js └── entry.js └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | current node 2 | last 2 versions and > 2% 3 | ie > 10 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [arkokoley] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes issue # 2 | 3 | ### Describe the changes you have made in this PR - 4 | 5 | ### Have you updated the readme? 6 | 7 | ### Screenshots of the changes (If any) - 8 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '17 0 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v2 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v1 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v1 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v1 71 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Install dependencies 15 | run: npm install 16 | - name: Build 17 | run: npm run build 18 | - name: Create .npmrc 19 | run: echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" >> ~/.npmrc 20 | env: 21 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 22 | - name: Publish 23 | run: npm publish --new-version ${GITHUB_REF#"refs/tags/"} --no-git-tag-version 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | 7 | # Editor directories and files 8 | .idea 9 | *.suo 10 | *.ntvs* 11 | *.njsproj 12 | *.sln 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Gaurav Koley 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pdfvuer 2 | 3 | > A PDF viewer for Vue using Mozilla's PDF.js 4 | 5 | [![Awesome](https://raw.githubusercontent.com/sindresorhus/awesome/main/media/mentioned-badge.svg)](https://github.com/vuejs/awesome-vue) 6 | [![npm](https://img.shields.io/npm/v/pdfvuer)](https://npmjs.com/package/pdfvuer) 7 | [![npm](https://img.shields.io/npm/dm/pdfvuer)](https://npmjs.com/package/pdfvuer) 8 | [![GitHub Repo stars](https://img.shields.io/github/stars/arkokoley/pdfvuer)](https://github.com/arkokoley/pdfvuer) 9 | [![npm](https://img.shields.io/npm/l/pdfvuer)](https://github.com/arkokoley/pdfvuer/blob/master/LICENSE) 10 | 11 | ## Install 12 | 13 | For Vue 2: 14 | ``` 15 | npm install --save pdfvuer 16 | ``` 17 | 18 | For Vue 3: 19 | ``` 20 | npm i pdfvuer@next --save 21 | ``` 22 | 23 | ## Example - basic 24 | ```vue 25 | 32 | 33 | 43 | ``` 44 | 45 | ## Example - Advanced 46 | 47 | ```vue 48 | 87 | 88 | 176 | 177 | 187 | 188 | ``` 189 | 190 | ## API 191 | 192 | ### Props 193 | 194 | #### :src String / Object - default: '' 195 | The url of the pdf file. `src` may also be a `string|TypedArray|DocumentInitParameters|PDFDataRangeTransport` for more details, see [`PDFJS.getDocument()`](https://github.com/mozilla/pdf.js/blob/8ff1fbe7f819513e7d0023df961e3d223b35aefa/src/display/api.js#L117). 196 | 197 | #### :page Number - default: 1 198 | The page number to display. 199 | 200 | #### :rotate Number - default: 0 201 | The page rotation in degrees, only multiple of 90 are valid. 202 | 203 | #### :scale Number / String - default: 'page-width' - .sync 204 | The scaling factor. By default, the pdf will be scaled to match the page width 205 | with the container width. 206 | When passed value `page-width` and / or using `resize` prop, will send back the scale 207 | computed accordingly via `update:scale` event (use it with `scale.sync="scale"`) 208 | 209 | #### :resize Boolean - default: false 210 | Enable Auto Resizing on window resize. By default, autoresizing is disabled. 211 | 212 | #### :annotation Boolean - default: false 213 | Show the annotations in the pdf. By default, annotation layer is disabled. 214 | 215 | #### :text Boolean - default: true 216 | Show the text layer in the pdf. By default, text layer is enabled. 217 | 218 | ### Events 219 | 220 | #### @numpages Number 221 | The total number of pages of the pdf. 222 | 223 | #### @loading Boolean 224 | The provided PDF's loading state 225 | 226 | #### @error Function 227 | Function handler for errors occurred during loading/drawing PDF source. 228 | 229 | #### @link-clicked Function 230 | Function handler for errors occurred during loading/drawing PDF source. 231 | Example: 232 | ```js 233 | handle_pdf_link: function (params) { 234 | // Scroll to the appropriate place on our page - the Y component of 235 | // params.destArray * (div height / ???), from the bottom of the page div 236 | var page = document.getElementById(String(params.pageNumber)); 237 | page.scrollIntoView(); 238 | } 239 | ``` 240 | 241 | 242 | ### Public static methods 243 | 244 | #### createLoadingTask(src) 245 | * `src`: see `:src` prop 246 | This function creates a PDFJS loading task that can be used and reused as `:src` property. 247 | 248 | ## Public Demo 249 | 250 | Advanced Example - [https://arkokoley.github.io/pdfvuer](https://arkokoley.github.io/pdfvuer) 251 | 252 | [Used in production by Gratia](https://goodwill.zense.co.in/resources/1) 253 | 254 | > Made with :heart: in Bangalore, India 255 | 256 | ## License 257 | MIT © [Gaurav Koley](https://gaurav.koley.in), 2021 258 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | const devPresets = ['@vue/babel-preset-app']; 2 | const buildPresets = ['@babel/preset-env']; 3 | module.exports = { 4 | presets: (process.env.NODE_ENV === 'development' ? devPresets : buildPresets), 5 | }; 6 | -------------------------------------------------------------------------------- /build/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | import vue from 'rollup-plugin-vue'; 5 | import alias from '@rollup/plugin-alias'; 6 | import commonjs from '@rollup/plugin-commonjs'; 7 | import replace from '@rollup/plugin-replace'; 8 | import babel from 'rollup-plugin-babel'; 9 | import { terser } from 'rollup-plugin-terser'; 10 | import minimist from 'minimist'; 11 | import resolve from '@rollup/plugin-node-resolve'; 12 | import nodePolyfills from 'rollup-plugin-node-polyfills'; 13 | // Get browserslist config and remove ie from es build targets 14 | const esbrowserslist = fs.readFileSync('./.browserslistrc') 15 | .toString() 16 | .split('\n') 17 | .filter((entry) => entry && entry.substring(0, 2) !== 'ie'); 18 | 19 | const argv = minimist(process.argv.slice(2)); 20 | 21 | const projectRoot = path.resolve(__dirname, '..'); 22 | 23 | const baseConfig = { 24 | input: 'src/entry.js', 25 | plugins: { 26 | preVue: [ 27 | alias({ 28 | resolve: ['.js', '.jsx', '.ts', '.tsx', '.vue'], 29 | entries: { 30 | '@': path.resolve(projectRoot, 'src'), 31 | }, 32 | }), 33 | ], 34 | replace: { 35 | 'process.env.NODE_ENV': JSON.stringify('production'), 36 | 'process.env.ES_BUILD': JSON.stringify('false'), 37 | }, 38 | vue: { 39 | css: true, 40 | template: { 41 | isProduction: true, 42 | }, 43 | }, 44 | babel: { 45 | exclude: 'node_modules/**', 46 | extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'], 47 | }, 48 | }, 49 | }; 50 | 51 | // ESM/UMD/IIFE shared settings: externals 52 | // Refer to https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency 53 | const external = [ 54 | // list external dependencies, exactly the way it is written in the import statement. 55 | // eg. 'jquery' 56 | 'vue', 57 | ]; 58 | 59 | // UMD/IIFE shared settings: output.globals 60 | // Refer to https://rollupjs.org/guide/en#output-globals for details 61 | const globals = { 62 | // Provide global variable names to replace your external imports 63 | // eg. jquery: '$' 64 | vue: 'Vue', 65 | }; 66 | 67 | // Customize configs for individual targets 68 | const buildFormats = []; 69 | if (!argv.format || argv.format === 'es') { 70 | const esConfig = { 71 | ...baseConfig, 72 | external, 73 | output: { 74 | file: 'dist/pdfvuer.esm.js', 75 | format: 'esm', 76 | exports: 'named', 77 | }, 78 | plugins: [ 79 | resolve(), 80 | replace({ 81 | ...baseConfig.plugins.replace, 82 | 'process.env.ES_BUILD': JSON.stringify('true'), 83 | }), 84 | ...baseConfig.plugins.preVue, 85 | vue(baseConfig.plugins.vue), 86 | babel({ 87 | ...baseConfig.plugins.babel, 88 | presets: [ 89 | [ 90 | '@babel/preset-env', 91 | { 92 | targets: esbrowserslist, 93 | }, 94 | ], 95 | ], 96 | }), 97 | commonjs(), 98 | ], 99 | }; 100 | buildFormats.push(esConfig); 101 | } 102 | 103 | if (!argv.format || argv.format === 'cjs') { 104 | const umdConfig = { 105 | ...baseConfig, 106 | external, 107 | output: { 108 | compact: true, 109 | file: 'dist/pdfvuer.ssr.js', 110 | format: 'cjs', 111 | name: 'Pdfvuer', 112 | exports: 'named', 113 | globals, 114 | }, 115 | plugins: [ 116 | resolve(), 117 | replace(baseConfig.plugins.replace), 118 | ...baseConfig.plugins.preVue, 119 | vue({ 120 | ...baseConfig.plugins.vue, 121 | template: { 122 | ...baseConfig.plugins.vue.template, 123 | optimizeSSR: true, 124 | }, 125 | }), 126 | babel(baseConfig.plugins.babel), 127 | commonjs(), 128 | ], 129 | }; 130 | buildFormats.push(umdConfig); 131 | } 132 | 133 | if (!argv.format || argv.format === 'iife') { 134 | const unpkgConfig = { 135 | ...baseConfig, 136 | external, 137 | output: { 138 | compact: true, 139 | file: 'dist/pdfvuer.min.js', 140 | format: 'iife', 141 | name: 'Pdfvuer', 142 | exports: 'named', 143 | globals, 144 | }, 145 | plugins: [ 146 | resolve(), 147 | replace(baseConfig.plugins.replace), 148 | ...baseConfig.plugins.preVue, 149 | vue(baseConfig.plugins.vue), 150 | babel(baseConfig.plugins.babel), 151 | commonjs(), 152 | nodePolyfills(), 153 | terser({ 154 | output: { 155 | ecma: 5, 156 | }, 157 | }), 158 | ], 159 | }; 160 | buildFormats.push(unpkgConfig); 161 | } 162 | 163 | // Export config 164 | export default buildFormats; 165 | -------------------------------------------------------------------------------- /dev/serve.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Dev from './serve.vue'; 3 | 4 | Vue.config.productionTip = false; 5 | 6 | new Vue({ 7 | render: (h) => h(Dev), 8 | }).$mount('#app'); 9 | -------------------------------------------------------------------------------- /dev/serve.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 155 | 156 | 166 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pdfvuer", 3 | "description": "A PDF viewer for Vue using Mozilla's PDF.js", 4 | "version": "1.10.0", 5 | "author": "Gaurav Koley ", 6 | "license": "MIT", 7 | "homepage": "https://github.com/arkokoley/pdfvuer#pdfvuer", 8 | "bugs": { 9 | "url": "https://github.com/arkokoley/pdfvuer/issues", 10 | "email": "arkokoley@live.in" 11 | }, 12 | "repository": "github:arkokoley/pdfvuer", 13 | "main": "src/Pdfvuer.vue", 14 | "unpkg": "dist/pdfvuer.umd.min.js", 15 | "files": [ 16 | "dist/*", 17 | "src/**/*.vue" 18 | ], 19 | "scripts": { 20 | "serve": "vue-cli-service serve dev/serve.js", 21 | "build": "vue-cli-service build --target lib --name pdfvuer src/Pdfvuer.vue" 22 | }, 23 | "dependencies": { 24 | "es-abstract": "^1.18.0", 25 | "pdfjs-dist": "2.14.305", 26 | "raw-loader": "^0.5.1", 27 | "vue-resize-sensor": "^2.0.0" 28 | }, 29 | "devDependencies": { 30 | "@babel/core": "^7.9.0", 31 | "@babel/preset-env": "^7.9.5", 32 | "@rollup/plugin-alias": "^2.2.0", 33 | "@rollup/plugin-commonjs": "^11.1.0", 34 | "@rollup/plugin-node-resolve": "^8.4.0", 35 | "@rollup/plugin-replace": "^2.3.2", 36 | "@vue/cli-plugin-babel": "^4.5.6", 37 | "@vue/cli-service": "^4.5.6", 38 | "core-js": "3", 39 | "cross-env": "^7.0.2", 40 | "css-loader": "^4.0.0", 41 | "jquery": "^3.5.1", 42 | "minimist": "^1.2.5", 43 | "module": "^1.2.5", 44 | "rollup": "^2.7.3", 45 | "rollup-plugin-babel": "^4.4.0", 46 | "rollup-plugin-node-polyfills": "^0.2.1", 47 | "rollup-plugin-terser": "^5.3.0", 48 | "rollup-plugin-vue": "^6.0.0", 49 | "vue": "^2.6.11", 50 | "vue-template-compiler": "^2.6.11", 51 | "worker-loader": "^3.0.1" 52 | }, 53 | "peerDependencies": { 54 | "pdfjs-dist": "2.14.305", 55 | "vue": "^2.6.11" 56 | }, 57 | "engines": { 58 | "node": ">=10" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Pdfvuer.vue: -------------------------------------------------------------------------------- 1 | 10 | 258 | 259 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arkokoley/pdfvuer/87eca72e3fe2a4e810c387f14e62a0164cd5e079/src/assets/logo.png -------------------------------------------------------------------------------- /src/cmap.js: -------------------------------------------------------------------------------- 1 | import pdfjsLib from 'pdfjs-dist/webpack.js'; 2 | 3 | 4 | // see https://github.com/mozilla/pdf.js/blob/628e70fbb5dea3b9066aa5c34cca70aaafef8db2/src/display/dom_utils.js#L64 5 | 6 | export default function() { 7 | 8 | this.fetch = function(query) { 9 | 10 | return import('raw-loader!pdfjs-dist/cmaps/' + query.name + '.bcmap' /* webpackChunkName: "pdfjs/noprefetch-[request]" */) 11 | .then(function(bcmap) { 12 | 13 | return { 14 | cMapData: bcmap, 15 | compressionType: pdfjsLib.CMapCompressionType.BINARY, 16 | }; 17 | }); 18 | } 19 | } -------------------------------------------------------------------------------- /src/entry.js: -------------------------------------------------------------------------------- 1 | // Import vue component 2 | import component from '@/Pdfvuer.vue'; 3 | 4 | // install function executed by Vue.use() 5 | const install = function installPdfvuer(Vue) { 6 | if (install.installed) return; 7 | install.installed = true; 8 | Vue.component('Pdfvuer', component); 9 | }; 10 | 11 | // Create module definition for Vue.use() 12 | const plugin = { 13 | install, 14 | }; 15 | 16 | // To auto-install on non-es builds, when vue is found 17 | // eslint-disable-next-line no-redeclare 18 | /* global window, global */ 19 | if ('false' === process.env.ES_BUILD) { 20 | let GlobalVue = null; 21 | if (typeof window !== 'undefined') { 22 | GlobalVue = window.Vue; 23 | } else if (typeof global !== 'undefined') { 24 | GlobalVue = global.Vue; 25 | } 26 | if (GlobalVue) { 27 | GlobalVue.use(plugin); 28 | } 29 | } 30 | 31 | // Inject install function into component - allows component 32 | // to be registered via Vue.use() as well as Vue.component() 33 | component.install = install; 34 | 35 | // Export component by default 36 | export default component; 37 | 38 | // It's possible to expose named exports when writing components that can 39 | // also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo'; 40 | // export const RollupDemoDirective = component; 41 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transpileDependencies: [ 3 | 'pdfjs-dist' 4 | ] 5 | } --------------------------------------------------------------------------------