├── .browserslistrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── .storybook ├── main.js ├── manager.js ├── preview.ts └── webpack.config.js ├── .travis.yml ├── LICENSE.md ├── README.md ├── _config.yml ├── babel.config.js ├── jest.config.js ├── package.json ├── rollup.config.js ├── scripts ├── build-docs.sh └── build-lib.sh ├── src ├── components │ ├── index.ts │ └── vue-pdf │ │ ├── index.ts │ │ ├── loading-task.ts │ │ ├── vue-pdf-props.ts │ │ └── vue-pdf.vue ├── shims-vue.d.ts ├── stories │ ├── css │ │ └── page.scss │ ├── utilities │ │ └── template-source.ts │ └── vue-pdf │ │ ├── source-code.ts │ │ └── vue-pdf.stories.ts ├── vue3-pdfjs.cjs-iife.ts └── vue3-pdfjs.ts ├── tsconfig.json ├── tsconfig.lib.types.json └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 10 versions 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | end_of_line = lf 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | max_line_length = 100 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | extends: [ 7 | 'plugin:vue/vue3-essential', 8 | '@vue/airbnb', 9 | '@vue/typescript/recommended', 10 | ], 11 | parserOptions: { 12 | ecmaVersion: 2020, 13 | }, 14 | rules: { 15 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 16 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 17 | }, 18 | overrides: [ 19 | { 20 | files: [ 21 | '**/__tests__/*.{j,t}s?(x)', 22 | '**/tests/unit/**/*.spec.{j,t}s?(x)', 23 | ], 24 | env: { 25 | jest: true, 26 | }, 27 | }, 28 | ], 29 | }; 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist/ 4 | package-lock.json 5 | 6 | 7 | # local env files 8 | .env.local 9 | .env.*.local 10 | 11 | # Log files 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: [ 3 | '../src/**/*.stories.mdx', 4 | '../src/**/*.stories.@(js|jsx|ts|tsx)' 5 | ], 6 | addons: [ 7 | '@storybook/addon-links', 8 | '@storybook/addon-essentials', 9 | '@storybook/addon-actions' 10 | ], 11 | core: { 12 | builder: 'webpack4', 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from "@storybook/addons"; 2 | import { create } from "@storybook/theming/create"; 3 | 4 | const theme = create({ 5 | base: "light", 6 | brandTitle: "Vue 3 PDFJS", 7 | 8 | colorSecondary: '#012d15', 9 | barSelectedColor: '#012d15', 10 | textColor: '#012d15', 11 | }); 12 | 13 | addons.setConfig({ 14 | theme, 15 | }); 16 | -------------------------------------------------------------------------------- /.storybook/preview.ts: -------------------------------------------------------------------------------- 1 | import { Parameters } from '@storybook/vue3'; 2 | import { themes } from '@storybook/theming'; 3 | 4 | // This adds a component that can be used globally in stories 5 | // app.component('GlobalButton', Button); 6 | 7 | export const parameters: Parameters = { 8 | actions: { argTypesRegex: '^on[A-Z].*' }, 9 | controls: { expanded: true }, 10 | previewTabs: { 11 | docs: { 12 | hidden: false, 13 | theme: themes.dark, 14 | } 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = ({config}) => { 4 | config.module.rules.push({ 5 | test: /\.scss$/, 6 | use: [ 7 | require.resolve("vue-style-loader"), 8 | require.resolve("css-loader"), 9 | require.resolve("sass-loader"), 10 | ], 11 | }); 12 | 13 | return config; 14 | }; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: linux 2 | dist: xenial 3 | 4 | language: node_js 5 | 6 | node_js: 7 | - 14 8 | 9 | jobs: 10 | include: 11 | - stage: test 12 | script: npm run test:unit 13 | - stage: build library 14 | script: npm run build:lib 15 | - stage: build docs 16 | script: npm run build-storybook 17 | - stage: deploy docs 18 | script: npm run build 19 | deploy: 20 | provider: pages 21 | skip_cleanup: true 22 | token: $VUE_PDFJS_GITHUB_TRAVIS 23 | keep_history: true 24 | local_dir: dist/docs 25 | on: 26 | branch: main 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020-2021 Randolph Tellis 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | [![Build Status](https://travis-ci.com/randolphtellis/vue3-pdfjs.svg?token=hXpsA9tqveCqkXWMHjxp&branch=main)](https://travis-ci.com/randolphtellis/vue3-pdfjs) [![npm bundle size](https://img.shields.io/bundlephobia/minzip/vue3-pdfjs)](https://bundlephobia.com/result?p=vue3-pdfjs@latest) ![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/vue3-pdfjs) ![npm](https://img.shields.io/npm/dt/vue3-pdfjs) 4 | 5 | ![vue supported version](https://img.shields.io/badge/vue-3.x-brightgreen) [![npm](https://img.shields.io/npm/v/vue3-pdfjs)](https://www.npmjs.com/package/vue3-pdfjs/v/latest) [![NPM](https://img.shields.io/npm/l/vue3-pdfjs)](https://github.com/randolphtellis/vue3-pdfjs/blob/main/LICENSE.md) 6 | 7 | #### DEMO 8 | 9 |
10 | 11 | ## Install 12 | 13 | ```bash 14 | npm i vue3-pdfjs 15 | or 16 | yarn add vue3-pdfjs 17 | ``` 18 | 19 | ## Usage 20 | 21 | ##### Demo code can be found under the docs section here. 22 | 23 | ### Import globally 24 | ```ts 25 | import { createApp } from 'vue' 26 | import App from './App.vue' 27 | import VuePdf from 'vue3-pdfjs' 28 | 29 | const app = createApp(App) 30 | app.use(VuePdf) 31 | app.mount('#app') 32 | ``` 33 | 34 | 35 | 36 | ### Basic Example 37 | 38 | Import components from the `esm` folder to enable tree shaking. 39 | Please note that Mozilla's pdfjs npm package does not export tree-shakeable ES modules. Info here - https://github.com/mozilla/pdf.js/issues/12900 40 | ```ts 41 | 68 | 69 | 72 | ``` 73 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset', 4 | ], 5 | }; 6 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel', 3 | transform: { 4 | '^.+\\.vue$': 'vue-jest', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3-pdfjs", 3 | "description": "PDF Reader for Vue 3 using Mozilla's PDF.js", 4 | "author": { 5 | "name": "Randolph Tellis" 6 | }, 7 | "license": "MIT", 8 | "version": "0.1.6", 9 | "private": false, 10 | "main": "cjs/index.js", 11 | "browser": "vue3-pdfjs.esm.js", 12 | "module": "esm/index.js", 13 | "unpkg": "vue3-pdfjs-browser.min.js", 14 | "types": "vue3-pdfjs.d.ts", 15 | "homepage": "https://github.com/randolphtellis/vue3-pdfjs#readme", 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/randolphtellis/vue3-pdfjs.git" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/randolphtellis/vue3-pdfjs/issues" 22 | }, 23 | "scripts": { 24 | "build:lib": "scripts/build-lib.sh", 25 | "build": "npm run build:lib && npm run build-storybook", 26 | "test:unit": "vue-cli-service test:unit --passWithNoTests", 27 | "lint": "vue-cli-service lint", 28 | "start-publish": "cd dist/lib && npm publish", 29 | "dev": "start-storybook -p 6006", 30 | "build-storybook": "scripts/build-docs.sh" 31 | }, 32 | "dependencies": { 33 | "pdfjs-dist": "^2.10.377", 34 | "vue": "^3.2.19" 35 | }, 36 | "devDependencies": { 37 | "@babel/core": "^7.12.7", 38 | "@rollup/plugin-alias": "^3.1.1", 39 | "@rollup/plugin-babel": "^5.2.1", 40 | "@rollup/plugin-commonjs": "^15.1.0", 41 | "@rollup/plugin-node-resolve": "^9.0.0", 42 | "@rollup/plugin-replace": "^2.3.3", 43 | "@rollup/plugin-url": "^5.0.1", 44 | "@storybook/addon-actions": "^6.3.8", 45 | "@storybook/addon-essentials": "^6.3.8", 46 | "@storybook/addon-links": "^6.3.8", 47 | "@storybook/vue3": "^6.3.8", 48 | "@types/jest": "^24.0.19", 49 | "@types/pdfjs-dist": "^2.7.4", 50 | "@typescript-eslint/eslint-plugin": "^2.33.0", 51 | "@typescript-eslint/parser": "^2.33.0", 52 | "@vue/cli-plugin-babel": "^4.5.13", 53 | "@vue/cli-plugin-eslint": "^4.5.13", 54 | "@vue/cli-plugin-typescript": "^4.5.13", 55 | "@vue/cli-plugin-unit-jest": "^4.5.13", 56 | "@vue/cli-service": "^4.5.13", 57 | "@vue/compiler-sfc": "^3.2.19", 58 | "@vue/eslint-config-airbnb": "^5.0.2", 59 | "@vue/eslint-config-typescript": "^5.0.2", 60 | "@vue/test-utils": "^2.0.0-0", 61 | "autoprefixer": "^9.8.6", 62 | "babel-loader": "^8.2.1", 63 | "cross-env": "^7.0.2", 64 | "eslint": "^6.7.2", 65 | "eslint-plugin-import": "^2.20.2", 66 | "eslint-plugin-vue": "^7.0.0-0", 67 | "minimist": "^1.2.5", 68 | "node-sass": "^4.12.0", 69 | "postcss": "^8.1.4", 70 | "postcss-nested": "^5.0.1", 71 | "postcss-simple-vars": "^6.0.1", 72 | "postcss-url": "^10.0.0", 73 | "rollup": "^2.32.1", 74 | "rollup-plugin-filesize": "^9.0.2", 75 | "rollup-plugin-postcss": "^3.1.8", 76 | "rollup-plugin-terser": "^7.0.2", 77 | "rollup-plugin-typescript2": "^0.28.0", 78 | "rollup-plugin-vue": "^6.0.0-beta.10", 79 | "sass": "^1.27.1", 80 | "sass-loader": "^8.0.2", 81 | "typescript": "^4.4.3", 82 | "vue-jest": "^5.0.0-0", 83 | "vue-loader": "^16.5.0" 84 | }, 85 | "engines": { 86 | "node": ">=10.0.0" 87 | }, 88 | "keywords": [ 89 | "vue 3 pdf viewer", 90 | "vue 3 pdfjs", 91 | "vue 3 mozilla pdfjs", 92 | "vue 3 pdf component" 93 | ] 94 | } 95 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | import vue from "rollup-plugin-vue"; 4 | import pkg from "./package.json"; 5 | import alias from "@rollup/plugin-alias"; 6 | import commonjs from "@rollup/plugin-commonjs"; 7 | import filesize from 'rollup-plugin-filesize'; 8 | import resolve from "@rollup/plugin-node-resolve"; 9 | import replace from "@rollup/plugin-replace"; 10 | import babel from "@rollup/plugin-babel"; 11 | import sass from 'node-sass' 12 | import postCss from "rollup-plugin-postcss" 13 | import autoprefixer from 'autoprefixer' 14 | import url from "@rollup/plugin-url" 15 | import { terser } from "rollup-plugin-terser" 16 | import typescript from 'rollup-plugin-typescript2' 17 | 18 | const projectRoot = path.resolve(__dirname, ".") 19 | 20 | const validPkgName = 'Vue3PDF' 21 | 22 | const libBuildFolder = 'dist/lib' 23 | 24 | // Get browserslist config and remove ie from es build targets 25 | const esbrowserslist = fs.readFileSync('./.browserslistrc') 26 | .toString() 27 | .split('\n') 28 | .filter((entry) => entry && entry.substring(0, 2) !== 'ie'); 29 | 30 | let postVueConfig = [ 31 | // Process only ` 285 | 286 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { DefineComponent } from 'vue' 3 | const component: DefineComponent<{}, {}, any> 4 | export default component 5 | } 6 | 7 | declare module 'pdfjs-dist/legacy/build/pdf.worker.entry'; 8 | declare module 'pdfjs-dist/legacy/web/pdf_viewer'; 9 | -------------------------------------------------------------------------------- /src/stories/css/page.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randolphtellis/vue3-pdfjs/600a3e2c284fb9c819189c31986456e183e42c1d/src/stories/css/page.scss -------------------------------------------------------------------------------- /src/stories/utilities/template-source.ts: -------------------------------------------------------------------------------- 1 | export const templateSourceCode = (templateSource, args, replacing = 'v-bind="$props"') => { 2 | const propToSource = (key, val) => { 3 | const type = typeof val; 4 | switch (type) { 5 | case 'object': 6 | return `:${key}="${JSON.stringify(val)}"\n`; 7 | case 'boolean': 8 | return val ? key + `\n` : ''; 9 | case 'string': 10 | return `${key}="${val}"\n`; 11 | default: 12 | return `:${key}="${val}"\n`; 13 | } 14 | }; 15 | 16 | return templateSource.replace( 17 | replacing, 18 | Object.keys(args) 19 | .map((key) => propToSource(key, args[key])) 20 | .join(' ') 21 | ); 22 | }; -------------------------------------------------------------------------------- /src/stories/vue-pdf/source-code.ts: -------------------------------------------------------------------------------- 1 | export const singleSource = ` 2 | 5 | `; 6 | -------------------------------------------------------------------------------- /src/stories/vue-pdf/vue-pdf.stories.ts: -------------------------------------------------------------------------------- 1 | import '../css/page.scss' 2 | import { Meta } from '@storybook/vue3' 3 | import VuePdf from '../../components/vue-pdf/vue-pdf.vue' 4 | import { templateSourceCode } from '../utilities/template-source' 5 | import { singleSource } from './source-code' 6 | import { actions } from '@storybook/addon-actions' 7 | 8 | export default { 9 | title: 'Pdf Viewer', 10 | component: VuePdf, 11 | argTypes: { 12 | src: { control: { type: 'object', required: true, default: 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf' } } 13 | }, 14 | } as Meta; 15 | 16 | export const Default = (args: any, { argTypes }) => ({ 17 | props: Object.keys(argTypes), 18 | components: { VuePdf }, 19 | setup() { 20 | const action = actions('totalPages', 'pdfLoaded', 'textContent', 'pageLoaded') 21 | return { 22 | args, 23 | action 24 | } 25 | }, 26 | template: ` 27 | 28 | ` 29 | }); 30 | 31 | Default.args = { 32 | src: 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf', 33 | page: 1, 34 | enableTextSelection: true, 35 | enableAnnotations: true 36 | }; 37 | 38 | 39 | Default.parameters = { 40 | docs: { source: { code: templateSourceCode(singleSource, Default.args) } }, 41 | }; 42 | -------------------------------------------------------------------------------- /src/vue3-pdfjs.cjs-iife.ts: -------------------------------------------------------------------------------- 1 | // iife/cjs usage extends esm default export - so import it all 2 | import plugin, * as components from './vue3-pdfjs'; 3 | 4 | // Attach named exports directly to plugin. IIFE/CJS will 5 | // only expose one global var, with component exports exposed as properties of 6 | // that global var (eg. plugin.component) 7 | type NamedExports = Exclude; 8 | type ExtendedPlugin = typeof plugin & NamedExports; 9 | Object.entries(components).forEach(([componentName, component]) => { 10 | if (componentName !== 'default') { 11 | const key = componentName as Exclude; 12 | const val = component as Exclude; 13 | (plugin as ExtendedPlugin)[key] = val; 14 | } 15 | }); 16 | 17 | export default plugin; 18 | -------------------------------------------------------------------------------- /src/vue3-pdfjs.ts: -------------------------------------------------------------------------------- 1 | import { App as Application, Plugin } from 'vue'; 2 | import * as components from './components'; 3 | 4 | const install: Exclude = (app: Application) => { 5 | Object.entries(components).forEach(([componentName, component]) => { 6 | app.component(componentName, component); 7 | }); 8 | }; 9 | 10 | export default install; 11 | 12 | export * from './components'; 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es3", 4 | "module": "ES2015", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env", 16 | "jest" 17 | ], 18 | "paths": { 19 | "@/*": [ 20 | "src/*" 21 | ] 22 | }, 23 | "lib": [ 24 | "es5", 25 | "es6", 26 | "es2016", 27 | "es2017", 28 | "esnext", 29 | "dom", 30 | "dom.iterable", 31 | "scripthost" 32 | ] 33 | }, 34 | "exclude": [ 35 | "node_modules", 36 | "dist", 37 | "src/main.ts", 38 | "src/stories/*", 39 | ], 40 | "include": [ 41 | "src/**/*.ts", 42 | "src/**/*.tsx", 43 | "src/**/*.vue" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /tsconfig.lib.types.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "incremental": true, 5 | "target": "es3", 6 | "module": "ES2015", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "importHelpers": true, 10 | "moduleResolution": "node", 11 | "skipLibCheck": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "sourceMap": true, 15 | "baseUrl": ".", 16 | "types": [ 17 | "webpack-env", 18 | "jest" 19 | ], 20 | "paths": { 21 | "@/*": [ 22 | "src/*" 23 | ] 24 | }, 25 | "lib": [ 26 | "es5", 27 | "es6", 28 | "es2016", 29 | "es2017", 30 | "esnext", 31 | "dom", 32 | "dom.iterable", 33 | "scripthost" 34 | ] 35 | }, 36 | "exclude": [ 37 | "node_modules", 38 | "dist", 39 | "src/main.ts", 40 | "src/stories/*", 41 | ], 42 | "include": [ 43 | "src/**/*.ts", 44 | "src/**/*.tsx", 45 | "src/**/*.vue" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | lintOnSave: false, 3 | outputDir: 'dist/app' 4 | }; 5 | --------------------------------------------------------------------------------