Coder Social home page Coder Social logo

vite-vue3pdf's Introduction

Vite-vue3pdf

Latest Version on NPM Software License npm

The package contains a Vue 3 component to easily display PDF files in Vite.

Note: This project depends on @bundled-es-modules/pdfjs-dist which is currently quite a few versions behind pdfjs-dist

Note: Make sure to manually copy pdf.worker.min.js to public/pdfjs/pdf.worker.js (default) or another location set with worker-src prop. The worker version needs to match the version in package.json

This package pdf.worker.js
0.1.0 2.5.207-rc1
0.2.0 2.16.105-alpha.2

Example - basic

<template>
  <pdf src="./static/relativity.pdf"></pdf>
</template>

<script>
import pdf from '@jbtje/vite-vue3pdf'

export default {
  components: {
    pdf
  }
}
</script>

Install

npm install --save @jbtje/vite-vue3pdf

pdf.worker.js

Copy pdf.worker.min.js to public/pdsjs/pdf.worker.js. Vite-Vue3Pdf will load pdf.worker.js from https://yourdomain.com/pdsjs/pdf.worker.js by default. You can change this path via :worker-src

Demo

Browser support

Same browser support as Vue.js 3 (IE via Babel I guess)

Note

  • since v2.x, the script is exported as esm.
  • This is a copy of Vue-PDF adapted to work with Vue 3

API

Props

:src String / Object - default: ''

The url of the pdf file. src may also be a string|TypedArray|DocumentInitParameters|PDFDataRangeTransport for more details, see PDFJS.getDocument().

:page Number - default: 1

The page number to display.

:rotate Number - default: 0

The page rotation in degrees, only multiple of 90 are valid.

:worker-src String - default: '/pdfjs/pdf.worker.js'

The pdf worker location, relative to '/public' directory.

Events

@password (updatePassword, reason)

  • updatePassword: The function to call with the pdf password.
  • reason: the reason why this function is called 'NEED_PASSWORD' or 'INCORRECT_PASSWORD'

@progress Number

Document loading progress. Range [0, 1].

@loaded

Triggered when the document is loaded.

@pageLoaded Number

Triggered when a page is loaded.

@pageSize Object {width, height}

Triggered when a page is loaded.

@numPages Number

The total number of pages of the pdf.

@error Object

Triggered when an error occurred.

@linkClicked Number

Triggered when an internal link is clicked

Public methods

print(dpi, pageList) * experimental *

  • dpi: the print resolution of the document (try 100).
  • pageList: the list (array) of pages to print.

Public static methods

createLoadingTask(src[, options])

  • src: see :src prop
  • options: an object of options. This function creates a PDFJS loading task that can be used and reused as :src property.
    The loading task is a promise that resolves with the PDFJS pdf document that exposes the num-pages property (see example below).

beware: when the component is destroyed, the object returned by createLoadingTask() become invalid.

Supported options:

  • onPassword: Callback that's called when a password protected PDF is being opened.
  • onProgress: Callback return loading progress.
  • withCredentials: Wheter or not to send cookies in the fetch request.

Examples

Example - current page / page count
<template>
    <div>
        {{currentPage}} / {{pageCount}}
        <pdf
            src="https://cdn.mozilla.net/pdfjs/tracemonkey.pdf"
            @num-pages="pageCount = $event"
            @page-loaded="currentPage = $event"
        ></pdf>
    </div>
</template>

<script>

import pdf from '@jbtje/vite-vue3pdf'

export default {
    components: {
        pdf
    },
    data() {
        return {
            currentPage: 0,
            pageCount: 0,
        }
    }
}

</script>
Example - display multiple pages of the same pdf document
<template>
    <div>
        <pdf
            v-for="i in numPages"
            :key="i"
            :src="src"
            :page="i"
            style="display: inline-block; width: 25%"
        ></pdf>
    </div>
</template>

<script>

import pdf from '@jbtje/vite-vue3pdf'

var loadingTask = pdf.createLoadingTask('https://cdn.mozilla.net/pdfjs/tracemonkey.pdf');

export default {
    components: {
        pdf
    },
    data() {
        return {
            src: loadingTask,
            numPages: undefined,
        }
    },
    mounted() {

        this.src.promise.then(pdf => {

            this.numPages = pdf.numPages;
        });
    }
}

</script>
Example - print all pages
<template>
    <button @click="$refs.myPdfComponent.print()">print</button>
    <pdf ref="myPdfComponent" src="https://cdn.mozilla.net/pdfjs/tracemonkey.pdf"></pdf>
</template>
Example - print multiple pages
<template>
    <button @click="$refs.myPdfComponent.print(100, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])">print</button>
    <pdf ref="myPdfComponent" src="https://cdn.mozilla.net/pdfjs/tracemonkey.pdf"></pdf>
</template>
Example - get text content
<template>
    <div>
        <button
            @click="logContent"
        >
            log content
        </button>
        <pdf
            ref="myPdfComponent"
            src="https://cdn.mozilla.net/pdfjs/tracemonkey.pdf"
        ></pdf>
    </div>
</template>

<script>

import pdf from '@jbtje/vite-vue3pdf'

export default {
    components: {
        pdf
    },
    methods: {
        logContent() {

            this.$refs.myPdfComponent.pdf.forEachPage(function(page) {

                return page.getTextContent()
                .then(function(content) {

                    var text = content.items.map(item => item.str);
                    console.log(text);
                })
            });
        }
    }
}

</script>
Example - complete
<template>
    <div>
        <input type="checkbox" v-model="show">
        <select v-model="src" style="width: 30em">
            <option v-for="item in pdfList" :value="item" v-text="item"></option>
        </select>
        <input v-model.number="page" type="number" style="width: 5em"> /{{numPages}}
        <button @click="rotate += 90">&#x27F3;</button>
        <button @click="rotate -= 90">&#x27F2;</button>
        <button @click="$refs.pdf.print()">print</button>
        <div style="width: 50%">
            <div v-if="loadedRatio > 0 && loadedRatio < 1" style="background-color: green; color: white; text-align: center" :style="{ width: loadedRatio * 100 + '%' }">{{ Math.floor(loadedRatio * 100) }}%</div>
            <pdf v-if="show" ref="pdf" style="border: 1px solid red" :src="src" :page="page" :rotate="rotate" @password="password" @progress="loadedRatio = $event" @error="error" @num-pages="numPages = $event" @link-clicked="page = $event"></pdf>
        </div>
    </div>
</template>
<script>
import pdf from '@jbtje/vite-vue3pdf'

export default {
    components: {
        pdf: pdf
    },
    data () {
        return {
            show: true,
            pdfList: [
                '',
                'https://cdn.mozilla.net/pdfjs/tracemonkey.pdf',
                'https://cdn.rawgit.com/mozilla/pdf.js/c6e8ca86/test/pdfs/freeculture.pdf',
                'https://cdn.rawgit.com/mozilla/pdf.js/c6e8ca86/test/pdfs/annotation-link-text-popup.pdf',
                'https://cdn.rawgit.com/mozilla/pdf.js/c6e8ca86/test/pdfs/calrgb.pdf',
                'https://cdn.rawgit.com/sayanee/angularjs-pdf/68066e85/example/pdf/relativity.protected.pdf',
                'data:application/pdf;base64,JVBERi0xLjUKJbXtrvsKMyAwIG9iago8PCAvTGVuZ3RoIDQgMCBSCiAgIC9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp4nE2NuwoCQQxF+/mK+wMbk5lkHl+wIFislmIhPhYEi10Lf9/MVgZCAufmZAkMppJ6+ZLUuFWsM3ZXxvzpFNaMYjEriqpCtbZSBOsDzw0zjqPHZYtTrEmz4eto7/0K54t7GfegOGCBbBdDH3+y2zsMsVERc9SoRkXORqKGJupS6/9OmMIUfgypJL4KZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCiAgIDEzOAplbmRvYmoKMiAwIG9iago8PAogICAvRXh0R1N0YXRlIDw8CiAgICAgIC9hMCA8PCAvQ0EgMC42MTE5ODcgL2NhIDAuNjExOTg3ID4+CiAgICAgIC9hMSA8PCAvQ0EgMSAvY2EgMSA+PgogICA+Pgo+PgplbmRvYmoKNSAwIG9iago8PCAvVHlwZSAvUGFnZQogICAvUGFyZW50IDEgMCBSCiAgIC9NZWRpYUJveCBbIDAgMCA1OTUuMjc1NTc0IDg0MS44ODk3NzEgXQogICAvQ29udGVudHMgMyAwIFIKICAgL0dyb3VwIDw8CiAgICAgIC9UeXBlIC9Hcm91cAogICAgICAvUyAvVHJhbnNwYXJlbmN5CiAgICAgIC9DUyAvRGV2aWNlUkdCCiAgID4+CiAgIC9SZXNvdXJjZXMgMiAwIFIKPj4KZW5kb2JqCjEgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzCiAgIC9LaWRzIFsgNSAwIFIgXQogICAvQ291bnQgMQo+PgplbmRvYmoKNiAwIG9iago8PCAvQ3JlYXRvciAoY2Fpcm8gMS4xMS4yIChodHRwOi8vY2Fpcm9ncmFwaGljcy5vcmcpKQogICAvUHJvZHVjZXIgKGNhaXJvIDEuMTEuMiAoaHR0cDovL2NhaXJvZ3JhcGhpY3Mub3JnKSkKPj4KZW5kb2JqCjcgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cKICAgL1BhZ2VzIDEgMCBSCj4+CmVuZG9iagp4cmVmCjAgOAowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDA1ODAgMDAwMDAgbiAKMDAwMDAwMDI1MiAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAyMzAgMDAwMDAgbiAKMDAwMDAwMDM2NiAwMDAwMCBuIAowMDAwMDAwNjQ1IDAwMDAwIG4gCjAwMDAwMDA3NzIgMDAwMDAgbiAKdHJhaWxlcgo8PCAvU2l6ZSA4CiAgIC9Sb290IDcgMCBSCiAgIC9JbmZvIDYgMCBSCj4+CnN0YXJ0eHJlZgo4MjQKJSVFT0YK',
            ],
            src:'',
            loadedRatio: 0,
            page: 1,
            numPages: 0,
            rotate: 0,
        }
    },
    methods: {
        password: function(updatePassword, reason) {
            updatePassword(prompt('password is "test"'));
        },
        error: function(err) {

            console.log(err);
        }
    }
}
</script>

Credits

vite-vue3pdf's People

Contributors

jbtje avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

vite-vue3pdf's Issues

Error: No "GlobalWorkerOptions.workerSrc" specified.

This error occurs when using createLoadingTask.

pdf.js?v=3922a56a:15917 Uncaught (in promise) Error: No "GlobalWorkerOptions.workerSrc" specified.
    at get workerSrc [as workerSrc] (pdf.js?v=3922a56a:15917:12)
    at PDFWorker._initialize (pdf.js?v=3922a56a:15757:10)
    at new PDFWorker (pdf.js?v=3922a56a:15730:11)
    at Object.getDocument (pdf.js?v=3922a56a:14676:70)
    at Object.createLoadingTask (pdfjsWrapper.js?v=3922a56a:34:54)

@jbtje/vite-vue3pdf v0.2.0
vite v4.5.0
vue v3.3.6

Fatal error in iOS 15.3 and below

Hi
I have an issue that occurs in browsers in iOS devices (Safari and WebViews), version iOS 15.3 and lower.

TypeError: Ee.split("+").at is not a function. (In 'Ee.split("+").at(-1)', 'Ee.split("+").at' is undefined)

That breaks all other scripts execution.

 - vue3pdf version: 0.2.0
 - vue.js version: 3.2.45
 - vite version: 4.0.0
 - browser version: 15.3 (same a iOS version I guess)
 - OS version: iOS 15.3 and lower

Any chance for quick fix? I tried to go over it but no luck so far, and my deadline for it is just now.
Thanks in advance!

Page-loaded event triggers before file data is available on the canvas

Hi,

We are using your library as we had to upgrade an app from vue2 to vue3 and needed a version of vue-pdf that was compatible.

I am encountering an intermittent issue - It is more noticeable on the firefox browser but it has happened on both chrome and edge also, unfortunately there is no pattern to the issue. We use your library to "view" a PDF data on the canvas and then take snaps (canvas.toDataURL) of this canvas to store as an image each time a page is loaded.

Below is the pdf component that we use in our app

 <div ref="capture" id="pdfPlaceholder" v-if="fileData && fileDataLoadedAndAvailable === true">
    <pdf :src="fileData" :page="pageToShow" worker-src="/tools/vue-claims/pdfjs/pdf.worker.js"
      @num-pages="listenNumPages" @error="handlePDFLoadError" @page-loaded="handlePDFPageLoaded">
    </pdf>
  </div> 

I am noticing intermittently, that page-loaded event is triggered - and I can see the canvas on the screen but it has a height and width of 0 - there is no data on the canvas. Image attached showing blank canvas in the dom.

IMG_1826

Sometimes, on second attempt of the file upload, the canvas will be populated.

We have tried a number of fixes :

  1. A timeout
  2. Checking the fileData (:src) is both available and readable

Is there anyway to re-try the page-loaded step if the data is blank first time around? Is there something we are missing in our setup to make this work consistently?

More info can be provided if needed, any help appreciated. Thanks!

Edit : just to add some more info, on multipage documents - the first canvas might be blank but the subsequent pages are populated in the canvas.

Allow for text selection.

An idea. It would be nice to expose the option to make text selectable. Doesn't seem very hard to implement.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.