first commit
This commit is contained in:
commit
eb2f504652
32490 changed files with 5731109 additions and 0 deletions
21
node_modules/@tato30/vue-pdf/LICENSE
generated
vendored
Normal file
21
node_modules/@tato30/vue-pdf/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022–2023 Aldo Hernandez
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
125
node_modules/@tato30/vue-pdf/README.md
generated
vendored
Normal file
125
node_modules/@tato30/vue-pdf/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
<div align="center">
|
||||
<img width=250 src="./docs/.vuepress/public/logo.png" />
|
||||
<h1>VuePDF</h1>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<a href="https://www.npmjs.com/package/@tato30/vue-pdf" target="_blank">
|
||||
<img src="https://img.shields.io/npm/v/@tato30/vue-pdf?style=flat-square" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/@tato30/vue-pdf" target="_blank" >
|
||||
<img src="https://img.shields.io/npm/dw/@tato30/vue-pdf?style=flat-square" />
|
||||
</a>
|
||||
<a href="./LICENSE">
|
||||
<img src="https://img.shields.io/npm/l/@tato30/vue-pdf?style=flat-square" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
<h2><a href="https://tato30.github.io/VuePDF/">📖Documentation</a></h2>
|
||||
</div>
|
||||
|
||||
## Introduction
|
||||
|
||||
VuePDF is a **Vue 3** component for pdf.js that allows you to flexibly display PDF pages within your project.
|
||||
|
||||
## Installation
|
||||
|
||||
```console
|
||||
npm i @tato30/vue-pdf
|
||||
```
|
||||
|
||||
```console
|
||||
yarn add @tato30/vue-pdf
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { VuePDF, usePDF } from '@tato30/vue-pdf'
|
||||
|
||||
const { pdf, pages, info } = usePDF('document.pdf')
|
||||
|
||||
console.log(`Document has ${pages} pages`)
|
||||
console.log(`Document info: ${info}`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VuePDF :pdf="pdf" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
* [Props](./docs/guide/props.md)
|
||||
* [Events](./docs/guide/events.md)
|
||||
* [Methods](./docs/guide/methods.md)
|
||||
* [Slots](./docs/guide/slots.md)
|
||||
|
||||
|
||||
## Working With Layers
|
||||
|
||||
### Text and Annotations
|
||||
|
||||
This component supports text-selection and annotation-interaction by enabling them with `text-layer` and `annotation-layer` props respectively, but for this layers renders correctly is necessary setting `css` styles, it can be done by importing default styles from `@tato30/vue-pdf/style.css`.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { VuePDF, usePDF } from '@tato30/vue-pdf'
|
||||
import '@tato30/vue-pdf/style.css'
|
||||
|
||||
const { pdf } = usePDF('sample.pdf')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VuePDF :pdf="pdf" text-layer annotation-layer />
|
||||
</template>
|
||||
```
|
||||
|
||||
You can also create your own custom styles and set them in your project, use this examples as guide:
|
||||
|
||||
- [text-layer styles](https://github.com/mozilla/pdf.js/blob/master/web/text_layer_builder.css)
|
||||
- [annotation-layer styles](https://github.com/mozilla/pdf.js/blob/master/web/annotation_layer_builder.css)
|
||||
|
||||
### XFA Forms <badge type="tip" text="v1.7" vertical="middle" />
|
||||
|
||||
XFA forms also can be supported by enabling them from `usePDF`.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { VuePDF, usePDF } from '@tato30/vue-pdf'
|
||||
import '@tato30/vue-pdf/style.css'
|
||||
|
||||
const { pdf } = usePDF({
|
||||
url: '/example_xfa.pdf',
|
||||
enableXfa: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VuePDF :pdf="pdf" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## Server-Side Rendering
|
||||
|
||||
`VuePDF` is a client-side library, so if you are working with SSR frameworks like `nuxt`, surely will throw error during building stage, if that the case, you could wrap library in some "client only" directive or component, also `usePDF` should be wrapped.
|
||||
|
||||
## Contributing
|
||||
|
||||
Any idea, suggestion or contribution to the code or documentation are very welcome.
|
||||
|
||||
```sh
|
||||
# Clone the repository
|
||||
git clone https://github.com/TaTo30/VuePDF.git
|
||||
|
||||
# Change to code folder
|
||||
cd VuePDF
|
||||
|
||||
# Install node_modules
|
||||
npm install
|
||||
|
||||
# Run code with hot reload
|
||||
npm run dev
|
||||
```
|
||||
611
node_modules/@tato30/vue-pdf/dist/index.mjs
generated
vendored
Normal file
611
node_modules/@tato30/vue-pdf/dist/index.mjs
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/@tato30/vue-pdf/dist/index.umd.js
generated
vendored
Normal file
1
node_modules/@tato30/vue-pdf/dist/index.umd.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/@tato30/vue-pdf/dist/style.css
generated
vendored
Normal file
1
node_modules/@tato30/vue-pdf/dist/style.css
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
76
node_modules/@tato30/vue-pdf/dist/types/components/VuePDF.vue.d.ts
generated
vendored
Normal file
76
node_modules/@tato30/vue-pdf/dist/types/components/VuePDF.vue.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import 'pdfjs-dist/web/pdf_viewer.css';
|
||||
import type { AnnotationEventPayload } from './types';
|
||||
declare function reload(): void;
|
||||
declare function cancel(): void;
|
||||
declare function getAnnotationStorage(): import("pdfjs-dist/types/src/display/annotation_storage").AnnotationStorage | undefined;
|
||||
declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
||||
pdf?: import("pdfjs-dist/types/src/display/api").PDFDocumentLoadingTask | undefined;
|
||||
page?: number | undefined;
|
||||
scale?: number | undefined;
|
||||
rotation?: number | undefined;
|
||||
fitParent?: boolean | undefined;
|
||||
textLayer?: boolean | undefined;
|
||||
imageResourcesPath?: string | undefined;
|
||||
hideForms?: boolean | undefined;
|
||||
annotationLayer?: boolean | undefined;
|
||||
annotationsFilter?: string[] | undefined;
|
||||
annotationsMap?: object | undefined;
|
||||
watermarkText?: string | undefined;
|
||||
}>, {
|
||||
page: number;
|
||||
scale: number;
|
||||
}>, {
|
||||
reload: typeof reload;
|
||||
cancel: typeof cancel;
|
||||
getAnnotationStorage: typeof getAnnotationStorage;
|
||||
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
annotation: (payload: AnnotationEventPayload) => void;
|
||||
loaded: (payload: import("pdfjs-dist/types/src/display/display_utils").PageViewport) => void;
|
||||
}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
||||
pdf?: import("pdfjs-dist/types/src/display/api").PDFDocumentLoadingTask | undefined;
|
||||
page?: number | undefined;
|
||||
scale?: number | undefined;
|
||||
rotation?: number | undefined;
|
||||
fitParent?: boolean | undefined;
|
||||
textLayer?: boolean | undefined;
|
||||
imageResourcesPath?: string | undefined;
|
||||
hideForms?: boolean | undefined;
|
||||
annotationLayer?: boolean | undefined;
|
||||
annotationsFilter?: string[] | undefined;
|
||||
annotationsMap?: object | undefined;
|
||||
watermarkText?: string | undefined;
|
||||
}>, {
|
||||
page: number;
|
||||
scale: number;
|
||||
}>>> & {
|
||||
onAnnotation?: ((payload: AnnotationEventPayload) => any) | undefined;
|
||||
onLoaded?: ((payload: import("pdfjs-dist/types/src/display/display_utils").PageViewport) => any) | undefined;
|
||||
}, {
|
||||
scale: number;
|
||||
page: number;
|
||||
}, {}>, {
|
||||
default?(_: {}): any;
|
||||
}>;
|
||||
export default _default;
|
||||
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
||||
type __VLS_TypePropsToRuntimeProps<T> = {
|
||||
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
||||
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
||||
} : {
|
||||
type: import('vue').PropType<T[K]>;
|
||||
required: true;
|
||||
};
|
||||
};
|
||||
type __VLS_WithDefaults<P, D> = {
|
||||
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
||||
default: D[K];
|
||||
}> : P[K];
|
||||
};
|
||||
type __VLS_WithTemplateSlots<T, S> = T & {
|
||||
new (): {
|
||||
$slots: S;
|
||||
};
|
||||
};
|
||||
type __VLS_Prettify<T> = {
|
||||
[K in keyof T]: T[K];
|
||||
} & {};
|
||||
3
node_modules/@tato30/vue-pdf/dist/types/components/index.d.ts
generated
vendored
Normal file
3
node_modules/@tato30/vue-pdf/dist/types/components/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export * from './types';
|
||||
export * from './usePDF';
|
||||
export { default as VuePDF } from './VuePDF.vue';
|
||||
34
node_modules/@tato30/vue-pdf/dist/types/components/layers/AnnotationLayer.vue.d.ts
generated
vendored
Normal file
34
node_modules/@tato30/vue-pdf/dist/types/components/layers/AnnotationLayer.vue.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import type { AnnotationEventPayload } from '../types';
|
||||
declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
|
||||
page?: import("pdfjs-dist/types/src/display/api").PDFPageProxy | undefined;
|
||||
viewport?: import("pdfjs-dist/types/src/display/display_utils").PageViewport | undefined;
|
||||
document?: import("pdfjs-dist/types/src/display/api").PDFDocumentProxy | undefined;
|
||||
filter?: string[] | undefined;
|
||||
map?: object | undefined;
|
||||
imageResourcesPath?: string | undefined;
|
||||
hideForms?: boolean | undefined;
|
||||
enableScripting?: boolean | undefined;
|
||||
}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
annotation: (payload: AnnotationEventPayload) => void;
|
||||
}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
|
||||
page?: import("pdfjs-dist/types/src/display/api").PDFPageProxy | undefined;
|
||||
viewport?: import("pdfjs-dist/types/src/display/display_utils").PageViewport | undefined;
|
||||
document?: import("pdfjs-dist/types/src/display/api").PDFDocumentProxy | undefined;
|
||||
filter?: string[] | undefined;
|
||||
map?: object | undefined;
|
||||
imageResourcesPath?: string | undefined;
|
||||
hideForms?: boolean | undefined;
|
||||
enableScripting?: boolean | undefined;
|
||||
}>>> & {
|
||||
onAnnotation?: ((payload: AnnotationEventPayload) => any) | undefined;
|
||||
}, {}, {}>;
|
||||
export default _default;
|
||||
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
||||
type __VLS_TypePropsToRuntimeProps<T> = {
|
||||
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
||||
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
||||
} : {
|
||||
type: import('vue').PropType<T[K]>;
|
||||
required: true;
|
||||
};
|
||||
};
|
||||
17
node_modules/@tato30/vue-pdf/dist/types/components/layers/TextLayer.vue.d.ts
generated
vendored
Normal file
17
node_modules/@tato30/vue-pdf/dist/types/components/layers/TextLayer.vue.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
|
||||
page?: import("pdfjs-dist/types/src/display/api.js").PDFPageProxy | undefined;
|
||||
viewport?: import("pdfjs-dist/types/src/display/display_utils.js").PageViewport | undefined;
|
||||
}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
|
||||
page?: import("pdfjs-dist/types/src/display/api.js").PDFPageProxy | undefined;
|
||||
viewport?: import("pdfjs-dist/types/src/display/display_utils.js").PageViewport | undefined;
|
||||
}>>>, {}, {}>;
|
||||
export default _default;
|
||||
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
||||
type __VLS_TypePropsToRuntimeProps<T> = {
|
||||
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
||||
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
||||
} : {
|
||||
type: import('vue').PropType<T[K]>;
|
||||
required: true;
|
||||
};
|
||||
};
|
||||
19
node_modules/@tato30/vue-pdf/dist/types/components/layers/XFALayer.vue.d.ts
generated
vendored
Normal file
19
node_modules/@tato30/vue-pdf/dist/types/components/layers/XFALayer.vue.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
|
||||
page?: import("pdfjs-dist/types/src/display/api").PDFPageProxy | undefined;
|
||||
document?: import("pdfjs-dist/types/src/display/api").PDFDocumentProxy | undefined;
|
||||
viewport?: import("pdfjs-dist/types/src/display/display_utils").PageViewport | undefined;
|
||||
}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
|
||||
page?: import("pdfjs-dist/types/src/display/api").PDFPageProxy | undefined;
|
||||
document?: import("pdfjs-dist/types/src/display/api").PDFDocumentProxy | undefined;
|
||||
viewport?: import("pdfjs-dist/types/src/display/display_utils").PageViewport | undefined;
|
||||
}>>>, {}, {}>;
|
||||
export default _default;
|
||||
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
||||
type __VLS_TypePropsToRuntimeProps<T> = {
|
||||
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
||||
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
||||
} : {
|
||||
type: import('vue').PropType<T[K]>;
|
||||
required: true;
|
||||
};
|
||||
};
|
||||
27
node_modules/@tato30/vue-pdf/dist/types/components/types.d.ts
generated
vendored
Normal file
27
node_modules/@tato30/vue-pdf/dist/types/components/types.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import type { PageViewport } from 'pdfjs-dist';
|
||||
import type { OnProgressParameters } from 'pdfjs-dist/types/src/display/api';
|
||||
import type { Metadata } from 'pdfjs-dist/types/src/display/metadata';
|
||||
export type LoadedEventPayload = PageViewport;
|
||||
export interface AnnotationEventPayload {
|
||||
type: string;
|
||||
data: any;
|
||||
}
|
||||
export type OnProgressCallback = (progressData: OnProgressParameters) => void;
|
||||
export type UpdatePasswordFn = (newPassword: string) => void;
|
||||
export type OnPasswordCallback = (updatePassword: UpdatePasswordFn, reason: any) => void;
|
||||
export type OnErrorCallback = (error: any) => void;
|
||||
export interface UsePDFOptions {
|
||||
onProgress?: OnProgressCallback;
|
||||
onPassword?: OnPasswordCallback;
|
||||
onError?: OnErrorCallback;
|
||||
password?: string;
|
||||
}
|
||||
export interface UsePDFInfoMetadata {
|
||||
info: Object;
|
||||
metadata: Metadata;
|
||||
}
|
||||
export interface UsePDFInfo {
|
||||
metadata: UsePDFInfoMetadata;
|
||||
attachments: Record<string, unknown>;
|
||||
javascript: string[] | null;
|
||||
}
|
||||
25
node_modules/@tato30/vue-pdf/dist/types/components/usePDF.d.ts
generated
vendored
Normal file
25
node_modules/@tato30/vue-pdf/dist/types/components/usePDF.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import type { DocumentInitParameters, PDFDataRangeTransport, TypedArray } from 'pdfjs-dist/types/src/display/api';
|
||||
import type { UsePDFInfo, UsePDFOptions } from './types';
|
||||
/**
|
||||
* @typedef {Object} UsePDFParameters
|
||||
* @property {string} password
|
||||
* Document password to unlock content
|
||||
* @property {function} onProgress
|
||||
* Callback to request a password if a wrong or no password was provided. The callback receives two parameters: a function that should be called with the new password, and a reason (see PasswordResponses).
|
||||
* @property {function} onPassword
|
||||
* Callback to be able to monitor the loading progress of the PDF file (necessary to implement e.g. a loading bar). The callback receives an OnProgressParameters argument. if this function is used option.password is ignored
|
||||
* @property {function} onError
|
||||
* Callback to be able to handle errors during loading
|
||||
* */
|
||||
/**
|
||||
*
|
||||
* @param {string | URL | TypedArray | PDFDataRangeTransport | DocumentInitParameters} src
|
||||
* Can be a URL where a PDF file is located, a typed array (Uint8Array) already populated with data, or a parameter object.
|
||||
* @param {UsePDFParameters} options
|
||||
* UsePDF object parameters
|
||||
*/
|
||||
export declare function usePDF(src: string | URL | TypedArray | PDFDataRangeTransport | DocumentInitParameters, options?: UsePDFOptions): {
|
||||
pdf: import("vue").ShallowRef<import("pdfjs-dist/types/src/display/api").PDFDocumentLoadingTask | undefined>;
|
||||
pages: import("vue").ShallowRef<number>;
|
||||
info: import("vue").ShallowRef<{}> | import("vue").ShallowRef<UsePDFInfo>;
|
||||
};
|
||||
5
node_modules/@tato30/vue-pdf/dist/types/components/utils/annotations.d.ts
generated
vendored
Normal file
5
node_modules/@tato30/vue-pdf/dist/types/components/utils/annotations.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import type { PDFDocumentProxy } from 'pdfjs-dist';
|
||||
import type { AnnotationEventPayload } from '../types';
|
||||
declare const EVENTS_TO_HANDLER: string[];
|
||||
declare function annotationEventsHandler(evt: Event, PDFDoc: PDFDocumentProxy, Annotations: Object[]): AnnotationEventPayload | Promise<AnnotationEventPayload | undefined> | undefined;
|
||||
export { EVENTS_TO_HANDLER, annotationEventsHandler, };
|
||||
71
node_modules/@tato30/vue-pdf/dist/types/components/utils/link_service.d.ts
generated
vendored
Normal file
71
node_modules/@tato30/vue-pdf/dist/types/components/utils/link_service.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import type { IPDFLinkService } from 'pdfjs-dist/types/web/interfaces';
|
||||
declare class SimpleLinkService implements IPDFLinkService {
|
||||
externalLinkEnabled: boolean;
|
||||
constructor();
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get pagesCount(): number;
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get page(): number;
|
||||
/**
|
||||
* @param {number} _value
|
||||
*/
|
||||
set page(_value: number);
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get rotation(): number;
|
||||
/**
|
||||
* @param {number} _value
|
||||
*/
|
||||
set rotation(_value: number);
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isInPresentationMode(): boolean;
|
||||
/**
|
||||
* @param {string|Array} _dest - The named, or explicit, PDF destination.
|
||||
*/
|
||||
goToDestination(_dest: string | Array<any>): Promise<void>;
|
||||
/**
|
||||
* @param {number|string} _val - The page number, or page label.
|
||||
*/
|
||||
goToPage(_val: number | string): void;
|
||||
/**
|
||||
* @param {HTMLAnchorElement} link
|
||||
* @param {string} url
|
||||
* @param {boolean} [_newWindow]
|
||||
*/
|
||||
addLinkAttributes(link: HTMLAnchorElement, url: string, _newWindow?: boolean): void;
|
||||
/**
|
||||
* @param _dest - The PDF destination object.
|
||||
* @returns {string} The hyperlink to the PDF object.
|
||||
*/
|
||||
getDestinationHash(_dest: any): string;
|
||||
/**
|
||||
* @param _hash - The PDF parameters/hash.
|
||||
* @returns {string} The hyperlink to the PDF object.
|
||||
*/
|
||||
getAnchorUrl(_hash: any): string;
|
||||
/**
|
||||
* @param {string} _hash
|
||||
*/
|
||||
setHash(_hash: string): void;
|
||||
/**
|
||||
* @param {string} _action
|
||||
*/
|
||||
executeNamedAction(_action: string): void;
|
||||
/**
|
||||
* @param {Object} _action
|
||||
*/
|
||||
executeSetOCGState(_action: object): void;
|
||||
/**
|
||||
* @param {number} _pageNum - page number.
|
||||
* @param {Object} _pageRef - reference to the page.
|
||||
*/
|
||||
cachePageRef(_pageNum: number, _pageRef: object): void;
|
||||
}
|
||||
export { SimpleLinkService };
|
||||
4
node_modules/@tato30/vue-pdf/dist/types/index.d.ts
generated
vendored
Normal file
4
node_modules/@tato30/vue-pdf/dist/types/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import type { Plugin } from 'vue';
|
||||
export declare const VuePDFPlugin: Plugin;
|
||||
export * from './components';
|
||||
export default VuePDFPlugin;
|
||||
69
node_modules/@tato30/vue-pdf/package.json
generated
vendored
Normal file
69
node_modules/@tato30/vue-pdf/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"name": "@tato30/vue-pdf",
|
||||
"version": "1.7.2",
|
||||
"description": "PDF viewer for Vue 3",
|
||||
"author": {
|
||||
"name": "Aldo Hernandez",
|
||||
"url": "https://github.com/TaTo30"
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/TaTo30/VuePDF/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/TaTo30/VuePDF.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/TaTo30/VuePDF/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"pdf",
|
||||
"vue",
|
||||
"viewer"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"require": "./dist/index.umd.js",
|
||||
"import": "./dist/index.mjs",
|
||||
"types": "./dist/types/index.d.ts"
|
||||
},
|
||||
"./**/*.css": "./dist/*.css",
|
||||
"./src/*": "./src/*"
|
||||
},
|
||||
"main": "./dist/index.umd.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "vite --force --config vite.playground.ts",
|
||||
"build": "npm run build:lib && npm run build:dts",
|
||||
"build:lib": "vite build",
|
||||
"build:dts": "vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json",
|
||||
"publish": "npm publish --access public",
|
||||
"publish:beta": "npm publish --tag beta --access public",
|
||||
"preview": "vite preview --port 5050",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix ."
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.33"
|
||||
},
|
||||
"dependencies": {
|
||||
"pdfjs-dist": "3.7.107"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.38.5",
|
||||
"@babel/core": "^7.21.8",
|
||||
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
||||
"@types/node": "^18.16.3",
|
||||
"@vitejs/plugin-vue": "^4.2.1",
|
||||
"@vue/eslint-config-prettier": "^7.1.0",
|
||||
"eslint": "^8.39.0",
|
||||
"typescript": "^4.9.4",
|
||||
"vite": "^4.3.4",
|
||||
"vue": "^3.2.47",
|
||||
"vue-tsc": "^1.6.3"
|
||||
}
|
||||
}
|
||||
256
node_modules/@tato30/vue-pdf/src/components/VuePDF.vue
generated
vendored
Normal file
256
node_modules/@tato30/vue-pdf/src/components/VuePDF.vue
generated
vendored
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
<!-- eslint-disable no-case-declarations -->
|
||||
<script setup lang="ts">
|
||||
import * as PDFJS from 'pdfjs-dist'
|
||||
import { onMounted, ref, toRaw, watch } from 'vue'
|
||||
|
||||
import 'pdfjs-dist/web/pdf_viewer.css'
|
||||
|
||||
import type { PDFDocumentLoadingTask, PDFDocumentProxy, PDFPageProxy, PageViewport, RenderTask } from 'pdfjs-dist'
|
||||
import type { GetViewportParameters, RenderParameters } from 'pdfjs-dist/types/src/display/api'
|
||||
import type { AnnotationEventPayload, LoadedEventPayload } from './types'
|
||||
|
||||
import AnnotationLayer from './layers/AnnotationLayer.vue'
|
||||
import TextLayer from './layers/TextLayer.vue'
|
||||
import XFALayer from './layers/XFALayer.vue'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
pdf?: PDFDocumentLoadingTask
|
||||
page?: number
|
||||
scale?: number
|
||||
rotation?: number
|
||||
fitParent?: boolean
|
||||
textLayer?: boolean
|
||||
imageResourcesPath?: string
|
||||
hideForms?: boolean
|
||||
annotationLayer?: boolean
|
||||
annotationsFilter?: string[]
|
||||
annotationsMap?: object
|
||||
watermarkText?: string
|
||||
}>(), {
|
||||
page: 1,
|
||||
scale: 1,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'annotation', payload: AnnotationEventPayload): void
|
||||
(event: 'loaded', payload: LoadedEventPayload): void
|
||||
}>()
|
||||
|
||||
// Template Refs
|
||||
const container = ref<HTMLSpanElement>()
|
||||
const loadingLayer = ref<HTMLSpanElement>()
|
||||
const loading = ref(false)
|
||||
let renderTask: RenderTask
|
||||
|
||||
// PDF Refs
|
||||
const DocumentProxy = ref<PDFDocumentProxy>()
|
||||
const PageProxy = ref<PDFPageProxy>()
|
||||
const InternalViewport = ref<PageViewport>()
|
||||
|
||||
function emitLoaded(data: LoadedEventPayload) {
|
||||
emit('loaded', data)
|
||||
}
|
||||
|
||||
function emitAnnotation(data: AnnotationEventPayload) {
|
||||
emit('annotation', data)
|
||||
}
|
||||
|
||||
function computeRotation(rotation: number): number {
|
||||
if (!(typeof rotation === 'number' && rotation % 90 === 0))
|
||||
return 0
|
||||
const factor = rotation / 90
|
||||
if (factor > 4)
|
||||
return computeRotation(rotation - 360)
|
||||
else if (factor < 0)
|
||||
return computeRotation(rotation + 360)
|
||||
return rotation
|
||||
}
|
||||
|
||||
function computeScale(page: PDFPageProxy): number {
|
||||
let fscale = props.scale
|
||||
if (props.fitParent) {
|
||||
const parentWidth: number = (container.value!.parentNode! as HTMLElement).clientWidth
|
||||
const scale1Width = page.getViewport({ scale: 1 }).width
|
||||
fscale = parentWidth / scale1Width
|
||||
}
|
||||
return fscale
|
||||
}
|
||||
|
||||
function paintWatermark(canvas: HTMLCanvasElement, baseFontSize = 18, zoomRatio = 1.0) {
|
||||
if (!props.watermarkText)
|
||||
return
|
||||
|
||||
const ctx: CanvasRenderingContext2D | null = canvas.getContext('2d')
|
||||
if (!ctx)
|
||||
return
|
||||
|
||||
ctx.font = `${baseFontSize * zoomRatio}px Trebuchet MS`
|
||||
ctx.fillStyle = 'rgba(211, 210, 211, 0.3)'
|
||||
|
||||
const numWatermarks = 50 // Adjust the number of watermarks as desired
|
||||
|
||||
for (let i = 0; i < numWatermarks; i++) {
|
||||
const x = (i % 5) * (canvas.width / 5) + canvas.width / 10
|
||||
const y = Math.floor(i / 5) * (canvas.height / 5) + canvas.height / 10
|
||||
|
||||
ctx.save()
|
||||
ctx.translate(x, y)
|
||||
ctx.rotate(-(Math.PI / 4))
|
||||
ctx.fillText(props.watermarkText, 0, 0)
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentCanvas(): HTMLCanvasElement | null {
|
||||
let oldCanvas = null
|
||||
container.value?.childNodes.forEach((el) => {
|
||||
if ((el as HTMLElement).tagName === 'CANVAS')
|
||||
oldCanvas = el
|
||||
})
|
||||
return oldCanvas
|
||||
}
|
||||
|
||||
function setupCanvas(viewport: PageViewport): HTMLCanvasElement {
|
||||
let canvas
|
||||
const currentCanvas = getCurrentCanvas()!
|
||||
if (currentCanvas && currentCanvas?.getAttribute('role') === 'main') {
|
||||
canvas = currentCanvas
|
||||
}
|
||||
else {
|
||||
canvas = document.createElement('canvas')
|
||||
canvas.style.display = 'block'
|
||||
canvas.setAttribute('dir', 'ltr')
|
||||
}
|
||||
|
||||
const outputScale = window.devicePixelRatio || 1
|
||||
canvas.width = Math.floor(viewport.width * outputScale)
|
||||
canvas.height = Math.floor(viewport.height * outputScale)
|
||||
|
||||
canvas.style.width = `${Math.floor(viewport.width)}px`
|
||||
canvas.style.height = `${Math.floor(viewport.height)}px`
|
||||
|
||||
// --scale-factor property
|
||||
container.value?.style.setProperty('--scale-factor', `${viewport.scale}`)
|
||||
// Also setting dimension properties for load layer
|
||||
loadingLayer.value!.style.width = `${Math.floor(viewport.width)}px`
|
||||
loadingLayer.value!.style.height = `${Math.floor(viewport.height)}px`
|
||||
loadingLayer.value!.style.top = '0'
|
||||
loadingLayer.value!.style.left = '0'
|
||||
loading.value = true
|
||||
return canvas
|
||||
}
|
||||
|
||||
function cancelRender() {
|
||||
if (renderTask)
|
||||
renderTask.cancel()
|
||||
}
|
||||
|
||||
function renderPage(pageNum: number) {
|
||||
toRaw(DocumentProxy.value)?.getPage(pageNum).then((page) => {
|
||||
cancelRender()
|
||||
|
||||
const defaultViewport = page.getViewport()
|
||||
const viewportParams: GetViewportParameters = {
|
||||
scale: computeScale(page),
|
||||
rotation: computeRotation((props.rotation || 0) + defaultViewport.rotation),
|
||||
}
|
||||
const viewport = page.getViewport(viewportParams)
|
||||
|
||||
const oldCanvas = getCurrentCanvas()
|
||||
const canvas = setupCanvas(viewport)
|
||||
|
||||
const outputScale = window.devicePixelRatio || 1
|
||||
const transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : undefined
|
||||
|
||||
// Render PDF page into canvas context
|
||||
const renderContext: RenderParameters = {
|
||||
canvasContext: canvas.getContext('2d')!,
|
||||
viewport,
|
||||
annotationMode: props.hideForms ? PDFJS.AnnotationMode.ENABLE : PDFJS.AnnotationMode.ENABLE_FORMS,
|
||||
transform,
|
||||
}
|
||||
|
||||
if (canvas?.getAttribute('role') !== 'main') {
|
||||
if (oldCanvas)
|
||||
container.value?.replaceChild(canvas, oldCanvas)
|
||||
}
|
||||
else {
|
||||
canvas.removeAttribute('role')
|
||||
}
|
||||
|
||||
PageProxy.value = page
|
||||
InternalViewport.value = viewport
|
||||
renderTask = page.render(renderContext)
|
||||
renderTask.promise.then(() => {
|
||||
paintWatermark(canvas, 18, viewport.scale)
|
||||
loading.value = false
|
||||
emitLoaded(InternalViewport.value!)
|
||||
}).catch(() => {
|
||||
// render task cancelled
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function initDoc(proxy: PDFDocumentLoadingTask) {
|
||||
proxy.promise.then(async (doc) => {
|
||||
DocumentProxy.value = doc
|
||||
renderPage(props.page)
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => props.pdf, (pdf) => {
|
||||
// for any change in pdf proxy, rework all
|
||||
if (pdf !== undefined)
|
||||
initDoc(pdf)
|
||||
})
|
||||
|
||||
watch(() => [props.scale, props.rotation, props.page, props.hideForms, props.watermarkText], () => {
|
||||
renderPage(props.page)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (props.pdf !== undefined)
|
||||
initDoc(props.pdf)
|
||||
})
|
||||
|
||||
function reload() {
|
||||
renderPage(props.page)
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
cancelRender()
|
||||
}
|
||||
|
||||
function getAnnotationStorage() {
|
||||
const pdf = toRaw(DocumentProxy.value)
|
||||
return pdf?.annotationStorage
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
reload,
|
||||
cancel,
|
||||
getAnnotationStorage,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="container" style="position: relative; display: block; overflow: hidden;">
|
||||
<canvas dir="ltr" style="display: block" role="main" />
|
||||
<AnnotationLayer
|
||||
v-show="annotationLayer"
|
||||
:filter="annotationsFilter!"
|
||||
:map="annotationsMap"
|
||||
:viewport="InternalViewport!"
|
||||
:image-resources-path="imageResourcesPath"
|
||||
:hide-forms="hideForms"
|
||||
:page="PageProxy!"
|
||||
:document="DocumentProxy!"
|
||||
@annotation="emitAnnotation($event)"
|
||||
/>
|
||||
<TextLayer v-show="textLayer" :page="PageProxy!" :viewport="InternalViewport!" />
|
||||
<XFALayer :page="PageProxy!" :viewport="InternalViewport!" :document="DocumentProxy!" />
|
||||
<div v-show="loading" ref="loadingLayer" style="position: absolute;">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
3
node_modules/@tato30/vue-pdf/src/components/index.ts
generated
vendored
Normal file
3
node_modules/@tato30/vue-pdf/src/components/index.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export * from './types'
|
||||
export * from './usePDF'
|
||||
export { default as VuePDF } from './VuePDF.vue'
|
||||
139
node_modules/@tato30/vue-pdf/src/components/layers/AnnotationLayer.vue
generated
vendored
Normal file
139
node_modules/@tato30/vue-pdf/src/components/layers/AnnotationLayer.vue
generated
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
<script setup lang="ts">
|
||||
import * as PDFJS from 'pdfjs-dist'
|
||||
import { onMounted, ref, toRaw, watch } from 'vue'
|
||||
|
||||
import type { PDFDocumentProxy, PDFPageProxy, PageViewport } from 'pdfjs-dist'
|
||||
import type { AnnotationLayerParameters } from 'pdfjs-dist/types/src/display/annotation_layer'
|
||||
|
||||
import { EVENTS_TO_HANDLER, annotationEventsHandler } from '../utils/annotations'
|
||||
import { SimpleLinkService } from '../utils/link_service'
|
||||
|
||||
import type { AnnotationEventPayload } from '../types'
|
||||
|
||||
const props = defineProps<{
|
||||
page?: PDFPageProxy
|
||||
viewport?: PageViewport
|
||||
document?: PDFDocumentProxy
|
||||
filter?: string[]
|
||||
map?: object
|
||||
imageResourcesPath?: string
|
||||
hideForms?: boolean
|
||||
enableScripting?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'annotation', payload: AnnotationEventPayload): void
|
||||
}>()
|
||||
|
||||
const layer = ref<HTMLDivElement>()
|
||||
const annotations = ref<any[]>()
|
||||
|
||||
function annotationsEvents(evt: Event) {
|
||||
const value = annotationEventsHandler(evt, props.document!, annotations.value!)
|
||||
Promise.resolve(value).then((data) => {
|
||||
if (data)
|
||||
emit('annotation', data)
|
||||
})
|
||||
}
|
||||
|
||||
async function getFieldObjects() {
|
||||
const fieldObjects = await toRaw(props.document)?.getFieldObjects()
|
||||
return fieldObjects
|
||||
}
|
||||
|
||||
async function getHasJSActions() {
|
||||
const hasJSActions = await toRaw(props.document)?.hasJSActions()
|
||||
return hasJSActions
|
||||
}
|
||||
|
||||
async function getAnnotations() {
|
||||
const page = props.page
|
||||
|
||||
let annotations = await page?.getAnnotations()
|
||||
if (props.filter) {
|
||||
const filters = props.filter
|
||||
annotations = annotations!.filter((value) => {
|
||||
const subType = value.subtype
|
||||
const fieldType = value.fieldType ? `${subType}.${value.fieldType}` : null
|
||||
return filters?.includes(subType) || (fieldType !== null && filters?.includes(fieldType))
|
||||
})
|
||||
}
|
||||
|
||||
return annotations
|
||||
}
|
||||
|
||||
async function render() {
|
||||
layer.value!.replaceChildren?.()
|
||||
for (const evtHandler of EVENTS_TO_HANDLER)
|
||||
layer.value!.removeEventListener(evtHandler, annotationsEvents)
|
||||
|
||||
const pdf = toRaw(props.document)
|
||||
const page = props.page
|
||||
const viewport = props.viewport
|
||||
|
||||
annotations.value = await getAnnotations()
|
||||
|
||||
// Canvas map for push button widget
|
||||
const canvasMap = new Map<string, HTMLCanvasElement>([])
|
||||
for (const anno of annotations.value!) {
|
||||
if (anno.subtype === 'Widget' && anno.fieldType === 'Btn' && anno.pushButton) {
|
||||
const canvasWidth = anno.rect[2] - anno.rect[0]
|
||||
const canvasHeight = anno.rect[3] - anno.rect[1]
|
||||
const subCanvas = document.createElement('canvas')
|
||||
subCanvas.setAttribute('width', (canvasWidth * viewport!.scale).toString())
|
||||
subCanvas.setAttribute('height', (canvasHeight * viewport!.scale).toString())
|
||||
canvasMap.set(anno.id, subCanvas)
|
||||
}
|
||||
}
|
||||
const annotationStorage = pdf!.annotationStorage
|
||||
if (props.map) {
|
||||
for (const [key, value] of Object.entries(props.map))
|
||||
annotationStorage.setValue(key, value)
|
||||
}
|
||||
const parameters: AnnotationLayerParameters = {
|
||||
annotations: annotations.value!,
|
||||
viewport: viewport!.clone({ dontFlip: true }),
|
||||
linkService: new SimpleLinkService(),
|
||||
annotationCanvasMap: canvasMap,
|
||||
div: layer.value!,
|
||||
annotationStorage,
|
||||
renderForms: !props.hideForms,
|
||||
page: page!,
|
||||
enableScripting: false,
|
||||
hasJSActions: await getHasJSActions(),
|
||||
fieldObjects: await getFieldObjects(),
|
||||
downloadManager: null,
|
||||
imageResourcesPath: props.imageResourcesPath,
|
||||
}
|
||||
PDFJS.AnnotationLayer.render(parameters)
|
||||
|
||||
for (const evtHandler of EVENTS_TO_HANDLER)
|
||||
layer.value!.addEventListener(evtHandler, annotationsEvents)
|
||||
}
|
||||
|
||||
watch(() => props.viewport, () => {
|
||||
if (props.page && props.viewport && layer.value)
|
||||
render()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (props.page && props.viewport && layer.value)
|
||||
render()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="layer" class="annotationLayer" style="display: block;" />
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.annotationLayer {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/* Make annotation sections available over text layer */
|
||||
.annotationLayer section {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
</style>
|
||||
66
node_modules/@tato30/vue-pdf/src/components/layers/TextLayer.vue
generated
vendored
Normal file
66
node_modules/@tato30/vue-pdf/src/components/layers/TextLayer.vue
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<script setup lang="ts">
|
||||
import * as PDFJS from 'pdfjs-dist'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
|
||||
import type { PDFPageProxy, PageViewport } from 'pdfjs-dist'
|
||||
import type { TextLayerRenderParameters } from 'pdfjs-dist/types/src/display/text_layer'
|
||||
|
||||
const props = defineProps<{
|
||||
page?: PDFPageProxy
|
||||
viewport?: PageViewport
|
||||
}>()
|
||||
|
||||
const layer = ref<HTMLDivElement>()
|
||||
const endContent = ref<HTMLDivElement>()
|
||||
|
||||
function render() {
|
||||
layer.value!.replaceChildren?.()
|
||||
|
||||
const page = props.page
|
||||
const viewport = props.viewport
|
||||
|
||||
const textStream = page?.streamTextContent({ includeMarkedContent: true, disableNormalization: true })
|
||||
const parameters: TextLayerRenderParameters = {
|
||||
textContentSource: textStream!,
|
||||
viewport: viewport!,
|
||||
container: layer.value!,
|
||||
isOffscreenCanvasSupported: true,
|
||||
textDivs: [],
|
||||
textDivProperties: new WeakMap(),
|
||||
}
|
||||
|
||||
const task = PDFJS.renderTextLayer(parameters)
|
||||
task.promise.then(() => {
|
||||
const endOfContent = document.createElement('div')
|
||||
endOfContent.className = 'endOfContent'
|
||||
layer.value?.appendChild(endOfContent)
|
||||
endContent.value = endOfContent
|
||||
})
|
||||
}
|
||||
|
||||
function onMouseDown() {
|
||||
if (!endContent.value)
|
||||
return
|
||||
endContent.value.classList.add('active')
|
||||
}
|
||||
|
||||
function onMouseUp() {
|
||||
if (!endContent.value)
|
||||
return
|
||||
endContent.value.classList.remove('active')
|
||||
}
|
||||
|
||||
watch(() => props.viewport, (_) => {
|
||||
if (props.page && props.viewport && layer.value)
|
||||
render()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (props.page && props.viewport && layer.value)
|
||||
render()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="layer" class="textLayer" style="display: block;" @mousedown="onMouseDown" @mouseup="onMouseUp" />
|
||||
</template>
|
||||
58
node_modules/@tato30/vue-pdf/src/components/layers/XFALayer.vue
generated
vendored
Normal file
58
node_modules/@tato30/vue-pdf/src/components/layers/XFALayer.vue
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<script setup lang="ts">
|
||||
import * as PDFJS from 'pdfjs-dist'
|
||||
import { onMounted, ref, toRaw, watch } from 'vue'
|
||||
|
||||
import type { PDFDocumentProxy, PDFPageProxy, PageViewport } from 'pdfjs-dist'
|
||||
import type { XfaLayerParameters } from 'pdfjs-dist/types/src/display/xfa_layer'
|
||||
|
||||
import { SimpleLinkService } from '../utils/link_service'
|
||||
|
||||
const props = defineProps<{
|
||||
page?: PDFPageProxy
|
||||
document?: PDFDocumentProxy
|
||||
viewport?: PageViewport
|
||||
}>()
|
||||
|
||||
const layer = ref<HTMLDivElement>()
|
||||
|
||||
async function render() {
|
||||
layer.value!.replaceChildren?.()
|
||||
|
||||
const pdf = toRaw(props.document)
|
||||
const page = props.page
|
||||
const viewport = props.viewport
|
||||
|
||||
if (pdf!.isPureXfa) {
|
||||
const xfaHTML = await page!.getXfa()
|
||||
const parameters: XfaLayerParameters = {
|
||||
div: layer.value!,
|
||||
viewport: viewport!.clone({ dontFlip: true }),
|
||||
linkService: new SimpleLinkService(),
|
||||
annotationStorage: pdf?.annotationStorage,
|
||||
xfaHtml: xfaHTML!,
|
||||
}
|
||||
PDFJS.XfaLayer.render(parameters)
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.viewport, (_) => {
|
||||
if (props.page && props.viewport && layer.value)
|
||||
render()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (props.page && props.viewport && layer.value)
|
||||
render()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="layer" style="display: block;" />
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/* Make this layer over other layers */
|
||||
.xfaLayer {
|
||||
z-index: 5;
|
||||
}
|
||||
</style>
|
||||
33
node_modules/@tato30/vue-pdf/src/components/types.ts
generated
vendored
Normal file
33
node_modules/@tato30/vue-pdf/src/components/types.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import type { PageViewport } from 'pdfjs-dist'
|
||||
import type { OnProgressParameters } from 'pdfjs-dist/types/src/display/api'
|
||||
import type { Metadata } from 'pdfjs-dist/types/src/display/metadata'
|
||||
|
||||
export type LoadedEventPayload = PageViewport
|
||||
|
||||
export interface AnnotationEventPayload {
|
||||
type: string
|
||||
data: any
|
||||
}
|
||||
|
||||
export type OnProgressCallback = (progressData: OnProgressParameters) => void
|
||||
export type UpdatePasswordFn = (newPassword: string) => void
|
||||
export type OnPasswordCallback = (updatePassword: UpdatePasswordFn, reason: any) => void
|
||||
export type OnErrorCallback = (error: any) => void
|
||||
|
||||
export interface UsePDFOptions {
|
||||
onProgress?: OnProgressCallback
|
||||
onPassword?: OnPasswordCallback
|
||||
onError?: OnErrorCallback
|
||||
password?: string
|
||||
}
|
||||
|
||||
export interface UsePDFInfoMetadata {
|
||||
info: Object
|
||||
metadata: Metadata
|
||||
}
|
||||
|
||||
export interface UsePDFInfo {
|
||||
metadata: UsePDFInfoMetadata
|
||||
attachments: Record<string, unknown>
|
||||
javascript: string[] | null
|
||||
}
|
||||
86
node_modules/@tato30/vue-pdf/src/components/usePDF.ts
generated
vendored
Normal file
86
node_modules/@tato30/vue-pdf/src/components/usePDF.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import * as PDFJS from 'pdfjs-dist'
|
||||
import PDFWorker from 'pdfjs-dist/build/pdf.worker.min?url'
|
||||
import { shallowRef } from 'vue'
|
||||
|
||||
import type { PDFDocumentLoadingTask } from 'pdfjs-dist'
|
||||
import type { DocumentInitParameters, PDFDataRangeTransport, TypedArray } from 'pdfjs-dist/types/src/display/api'
|
||||
import type { OnPasswordCallback, UsePDFInfo, UsePDFOptions } from './types'
|
||||
|
||||
// Could not find a way to make this work with vite, importing the worker entry bundle the whole worker to the the final output
|
||||
// https://erindoyle.dev/using-pdfjs-with-vite/
|
||||
// PDFJS.GlobalWorkerOptions.workerSrc = PDFWorker
|
||||
function configWorker(wokerSrc: string) {
|
||||
PDFJS.GlobalWorkerOptions.workerSrc = wokerSrc
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} UsePDFParameters
|
||||
* @property {string} password
|
||||
* Document password to unlock content
|
||||
* @property {function} onProgress
|
||||
* Callback to request a password if a wrong or no password was provided. The callback receives two parameters: a function that should be called with the new password, and a reason (see PasswordResponses).
|
||||
* @property {function} onPassword
|
||||
* Callback to be able to monitor the loading progress of the PDF file (necessary to implement e.g. a loading bar). The callback receives an OnProgressParameters argument. if this function is used option.password is ignored
|
||||
* @property {function} onError
|
||||
* Callback to be able to handle errors during loading
|
||||
* */
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string | URL | TypedArray | PDFDataRangeTransport | DocumentInitParameters} src
|
||||
* Can be a URL where a PDF file is located, a typed array (Uint8Array) already populated with data, or a parameter object.
|
||||
* @param {UsePDFParameters} options
|
||||
* UsePDF object parameters
|
||||
*/
|
||||
export function usePDF(src: string | URL | TypedArray | PDFDataRangeTransport | DocumentInitParameters, options: UsePDFOptions = {
|
||||
onProgress: undefined,
|
||||
onPassword: undefined,
|
||||
onError: undefined,
|
||||
password: '',
|
||||
}) {
|
||||
if (!PDFJS.GlobalWorkerOptions?.workerSrc)
|
||||
configWorker(PDFWorker)
|
||||
|
||||
const pdf = shallowRef<PDFDocumentLoadingTask>()
|
||||
const pages = shallowRef(0)
|
||||
const info = shallowRef<UsePDFInfo | {}>({})
|
||||
|
||||
const loadingTask = PDFJS.getDocument(src)
|
||||
if (options.onProgress)
|
||||
loadingTask.onProgress = options.onProgress
|
||||
|
||||
if (options.onPassword) {
|
||||
loadingTask.onPassword = options.onPassword
|
||||
}
|
||||
else if (options.password) {
|
||||
const onPassword: OnPasswordCallback = (updatePassword, _) => {
|
||||
updatePassword(options.password ?? '')
|
||||
}
|
||||
loadingTask.onPassword = onPassword
|
||||
}
|
||||
|
||||
loadingTask.promise.then(async (doc) => {
|
||||
pdf.value = doc.loadingTask
|
||||
pages.value = doc.numPages
|
||||
|
||||
const metadata = await doc.getMetadata()
|
||||
const attachments = (await doc.getAttachments()) as Record<string, unknown>
|
||||
const javascript = await doc.getJavaScript()
|
||||
|
||||
info.value = {
|
||||
metadata,
|
||||
attachments,
|
||||
javascript,
|
||||
}
|
||||
}, (error) => {
|
||||
// PDF loading error
|
||||
if (typeof options.onError === 'function')
|
||||
options.onError(error)
|
||||
})
|
||||
|
||||
return {
|
||||
pdf,
|
||||
pages,
|
||||
info,
|
||||
}
|
||||
}
|
||||
213
node_modules/@tato30/vue-pdf/src/components/utils/annotations.ts
generated
vendored
Normal file
213
node_modules/@tato30/vue-pdf/src/components/utils/annotations.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable no-case-declarations */
|
||||
import type { PDFDocumentProxy } from 'pdfjs-dist'
|
||||
import type { RefProxy } from 'pdfjs-dist/types/src/display/api'
|
||||
import type { AnnotationEventPayload } from '../types'
|
||||
|
||||
interface PopupArgs {
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
interface LinkAnnotation {
|
||||
dest: Array<any> | string
|
||||
url: string
|
||||
unsafeurl: string
|
||||
}
|
||||
|
||||
const INTERNAL_LINK = 'internal-link'
|
||||
const LINK = 'link'
|
||||
const FILE_ATTACHMENT = 'file-attachment'
|
||||
const FORM_TEXT = 'form-text'
|
||||
const FORM_SELECT = 'form-select'
|
||||
const FORM_CHECKBOX = 'form-checkbox'
|
||||
const FORM_RADIO = 'form-radio'
|
||||
const FORM_BUTTON = 'form-button'
|
||||
|
||||
const EVENTS_TO_HANDLER = ['click', 'dblclick', 'mouseover', 'input', 'change']
|
||||
|
||||
function getAnnotationsByKey(key: string, value: any, annotations: Object[]): any[] {
|
||||
const result = []
|
||||
if (annotations) {
|
||||
for (const annotation of annotations) {
|
||||
type Key = keyof typeof annotation
|
||||
if (annotation[key as Key] === value)
|
||||
result.push(annotation)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function buildAnnotationData(type: string, data: any): AnnotationEventPayload {
|
||||
return { type, data }
|
||||
}
|
||||
|
||||
function inputAnnotation(inputEl: any, args?: any) {
|
||||
switch (inputEl.type) {
|
||||
case 'textarea':
|
||||
case 'text':
|
||||
return buildAnnotationData(FORM_TEXT, {
|
||||
fieldName: inputEl.name,
|
||||
value: inputEl.value,
|
||||
})
|
||||
case 'select-one':
|
||||
case 'select-multiple':
|
||||
const options = []
|
||||
for (const opt of inputEl.options) {
|
||||
options.push({
|
||||
value: opt.value,
|
||||
label: opt.label,
|
||||
})
|
||||
}
|
||||
const selected = []
|
||||
for (const opt of inputEl.selectedOptions) {
|
||||
selected.push({
|
||||
value: opt.value,
|
||||
label: opt.label,
|
||||
})
|
||||
}
|
||||
return buildAnnotationData(FORM_SELECT, {
|
||||
fieldName: inputEl.name,
|
||||
value: selected,
|
||||
options,
|
||||
})
|
||||
case 'checkbox':
|
||||
return buildAnnotationData(FORM_CHECKBOX, {
|
||||
fieldName: inputEl.name,
|
||||
checked: inputEl.checked,
|
||||
})
|
||||
case 'radio':
|
||||
return buildAnnotationData(FORM_RADIO, {
|
||||
fieldName: inputEl.name,
|
||||
...args,
|
||||
})
|
||||
case 'button':
|
||||
return buildAnnotationData(FORM_BUTTON, {
|
||||
fieldName: inputEl.name,
|
||||
...args,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function fileAnnotation(annotation: any) {
|
||||
return buildAnnotationData(FILE_ATTACHMENT, annotation.file)
|
||||
}
|
||||
|
||||
async function linkAnnotation(annotation: {
|
||||
dest?: any
|
||||
url?: string
|
||||
unsafeUrl?: string
|
||||
}, PDFDoc: PDFDocumentProxy) {
|
||||
if (annotation.dest) {
|
||||
// Get referenced page number of internal link
|
||||
if (typeof annotation.dest === 'string') {
|
||||
return buildAnnotationData(INTERNAL_LINK, {
|
||||
referencedPage: Number(annotation.dest.substring(1, annotation.dest.length)),
|
||||
offset: null,
|
||||
})
|
||||
}
|
||||
else {
|
||||
const pageIndex = await PDFDoc.getPageIndex(annotation.dest[0] as RefProxy)
|
||||
return buildAnnotationData(INTERNAL_LINK, {
|
||||
referencedPage: pageIndex + 1,
|
||||
offset: {
|
||||
left: annotation.dest[2],
|
||||
bottom: annotation.dest[3],
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
else if (annotation.url) {
|
||||
return buildAnnotationData(LINK, {
|
||||
url: annotation.url,
|
||||
unsafeUrl: annotation.unsafeUrl,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function mergePopupArgs(annotation: HTMLElement) {
|
||||
for (const spanElement of annotation.getElementsByTagName('span')) {
|
||||
let content = spanElement.textContent
|
||||
const args = JSON.parse(spanElement.dataset.l10nArgs ?? '{}') as PopupArgs
|
||||
if (content) {
|
||||
for (const key in args)
|
||||
content = content.replace(`{{${key}}}`, args[key])
|
||||
}
|
||||
spanElement.textContent = content
|
||||
}
|
||||
}
|
||||
|
||||
// Use this function to handle annotation events
|
||||
function annotationEventsHandler(evt: Event, PDFDoc: PDFDocumentProxy, Annotations: Object[]) {
|
||||
let annotation = (evt.target as HTMLInputElement).parentNode! as HTMLElement
|
||||
|
||||
// annotations are <section> elements if div returned find in child nodes the section element
|
||||
if (annotation.tagName === 'DIV')
|
||||
annotation = annotation.firstChild! as HTMLElement
|
||||
|
||||
if (annotation.className === 'linkAnnotation' && evt.type === 'click') {
|
||||
const id: string | undefined = annotation.dataset?.annotationId
|
||||
if (id)
|
||||
return linkAnnotation(getAnnotationsByKey('id', id, Annotations)[0] as LinkAnnotation, PDFDoc)
|
||||
}
|
||||
else if (annotation.className.includes('popupAnnotation') || annotation.className.includes('textAnnotation')) {
|
||||
mergePopupArgs(annotation)
|
||||
}
|
||||
else if (annotation.className.includes('fileAttachmentAnnotation')) {
|
||||
mergePopupArgs(annotation)
|
||||
const id = annotation.dataset.annotationId
|
||||
if (id && evt.type === 'dblclick')
|
||||
return fileAnnotation(getAnnotationsByKey('id', id, Annotations)[0])
|
||||
}
|
||||
else if (annotation.className.includes('textWidgetAnnotation') && evt.type === 'input') {
|
||||
let inputElement: HTMLInputElement | HTMLTextAreaElement = annotation.getElementsByTagName('input')[0]
|
||||
if (!inputElement)
|
||||
inputElement = annotation.getElementsByTagName('textarea')[0]
|
||||
return inputAnnotation(inputElement)
|
||||
}
|
||||
else if (annotation.className.includes('choiceWidgetAnnotation') && evt.type === 'input') {
|
||||
return inputAnnotation(annotation.getElementsByTagName('select')[0])
|
||||
}
|
||||
else if (annotation.className.includes('buttonWidgetAnnotation checkBox') && evt.type === 'change') {
|
||||
return inputAnnotation(annotation.getElementsByTagName('input')[0])
|
||||
}
|
||||
else if (annotation.className.includes('buttonWidgetAnnotation radioButton') && evt.type === 'change') {
|
||||
const id = annotation.dataset.annotationId
|
||||
if (id) {
|
||||
const anno = getAnnotationsByKey('id', id, Annotations)[0]
|
||||
const radioOptions = []
|
||||
for (const radioAnnotations of getAnnotationsByKey('fieldName', anno.fieldName, Annotations)) {
|
||||
if (radioAnnotations.buttonValue)
|
||||
radioOptions.push(radioAnnotations.buttonValue)
|
||||
}
|
||||
return inputAnnotation(annotation.getElementsByTagName('input')[0], {
|
||||
value: anno.buttonValue,
|
||||
defaultValue: anno.fieldValue,
|
||||
options: radioOptions,
|
||||
})
|
||||
}
|
||||
}
|
||||
else if (annotation.className.includes('buttonWidgetAnnotation pushButton') && evt.type === 'click') {
|
||||
const id = annotation.dataset.annotationId
|
||||
if (id) {
|
||||
const anno = getAnnotationsByKey('id', id, Annotations)[0]
|
||||
if (!anno.resetForm) {
|
||||
return inputAnnotation(
|
||||
{ name: anno.fieldName, type: 'button' },
|
||||
{ actions: anno.actions, reset: false },
|
||||
)
|
||||
}
|
||||
else {
|
||||
return inputAnnotation(
|
||||
{ name: anno.fieldName, type: 'button' },
|
||||
{ actions: anno.actions, reset: true },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
EVENTS_TO_HANDLER,
|
||||
annotationEventsHandler,
|
||||
}
|
||||
103
node_modules/@tato30/vue-pdf/src/components/utils/link_service.ts
generated
vendored
Normal file
103
node_modules/@tato30/vue-pdf/src/components/utils/link_service.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import type { IPDFLinkService } from 'pdfjs-dist/types/web/interfaces'
|
||||
|
||||
class SimpleLinkService implements IPDFLinkService {
|
||||
externalLinkEnabled: boolean
|
||||
|
||||
constructor() {
|
||||
this.externalLinkEnabled = true
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get pagesCount() {
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get page() {
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} _value
|
||||
*/
|
||||
set page(_value: number) {}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get rotation() {
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} _value
|
||||
*/
|
||||
set rotation(_value: number) {}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isInPresentationMode() {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string|Array} _dest - The named, or explicit, PDF destination.
|
||||
*/
|
||||
async goToDestination(_dest: string | Array<any>) {}
|
||||
|
||||
/**
|
||||
* @param {number|string} _val - The page number, or page label.
|
||||
*/
|
||||
goToPage(_val: number | string) {}
|
||||
|
||||
/**
|
||||
* @param {HTMLAnchorElement} link
|
||||
* @param {string} url
|
||||
* @param {boolean} [_newWindow]
|
||||
*/
|
||||
addLinkAttributes(link: HTMLAnchorElement, url: string, _newWindow = false) { }
|
||||
|
||||
/**
|
||||
* @param _dest - The PDF destination object.
|
||||
* @returns {string} The hyperlink to the PDF object.
|
||||
*/
|
||||
getDestinationHash(_dest: any): string {
|
||||
return '#'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _hash - The PDF parameters/hash.
|
||||
* @returns {string} The hyperlink to the PDF object.
|
||||
*/
|
||||
getAnchorUrl(_hash: any): string {
|
||||
return '#'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} _hash
|
||||
*/
|
||||
setHash(_hash: string) {}
|
||||
|
||||
/**
|
||||
* @param {string} _action
|
||||
*/
|
||||
executeNamedAction(_action: string) {}
|
||||
|
||||
/**
|
||||
* @param {Object} _action
|
||||
*/
|
||||
executeSetOCGState(_action: object) {}
|
||||
|
||||
/**
|
||||
* @param {number} _pageNum - page number.
|
||||
* @param {Object} _pageRef - reference to the page.
|
||||
*/
|
||||
cachePageRef(_pageNum: number, _pageRef: object) {}
|
||||
}
|
||||
|
||||
export { SimpleLinkService }
|
||||
20
node_modules/@tato30/vue-pdf/src/env.d.ts
generated
vendored
Normal file
20
node_modules/@tato30/vue-pdf/src/env.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
declare module "*?worker" {
|
||||
const workerConstructor: {
|
||||
new(): Worker
|
||||
};
|
||||
export default workerConstructor;
|
||||
}
|
||||
|
||||
declare module "*?url" {
|
||||
const url: string;
|
||||
export default url;
|
||||
}
|
||||
|
||||
declare module "*?worker&url" {
|
||||
const workerUrl: string;
|
||||
export default workerUrl;
|
||||
}
|
||||
|
||||
declare module "pdfjs-dist/build/pdf" {
|
||||
export * from 'pdfjs-dist'
|
||||
}
|
||||
12
node_modules/@tato30/vue-pdf/src/index.ts
generated
vendored
Normal file
12
node_modules/@tato30/vue-pdf/src/index.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import type { Plugin } from 'vue'
|
||||
import VuePDF from './components/VuePDF.vue'
|
||||
|
||||
export const VuePDFPlugin: Plugin = {
|
||||
install(Vue) {
|
||||
Vue.component(VuePDF.name, VuePDF)
|
||||
},
|
||||
}
|
||||
|
||||
export * from './components'
|
||||
|
||||
export default VuePDFPlugin
|
||||
Loading…
Add table
Add a link
Reference in a new issue