cbvirtua 1.0.39 → 1.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/pdf.js-2.9.359.zip +0 -0
- package/pdfjs-dist-2.15.349.zip +0 -0
- package/vue-pdf-embed-1/.babelrc +3 -0
- package/vue-pdf-embed-1/.eslintrc +10 -0
- package/vue-pdf-embed-1/.github/workflows/publish-to-npm.yml +20 -0
- package/vue-pdf-embed-1/.husky/pre-commit +4 -0
- package/vue-pdf-embed-1/.lintstagedrc +5 -0
- package/vue-pdf-embed-1/.prettierrc +7 -0
- package/vue-pdf-embed-1/CONTRIBUTING.md +14 -0
- package/vue-pdf-embed-1/LICENSE +21 -0
- package/vue-pdf-embed-1/README.md +156 -0
- package/vue-pdf-embed-1/demo/App.vue +56 -0
- package/vue-pdf-embed-1/demo/index.html +11 -0
- package/vue-pdf-embed-1/demo/main.js +8 -0
- package/vue-pdf-embed-1/jest.config.json +6 -0
- package/vue-pdf-embed-1/package-lock.json +12212 -0
- package/vue-pdf-embed-1/package.json +64 -0
- package/vue-pdf-embed-1/src/index.js +10 -0
- package/vue-pdf-embed-1/src/styles/annotation-layer.css +219 -0
- package/vue-pdf-embed-1/src/styles/text-layer.css +95 -0
- package/vue-pdf-embed-1/src/util.js +67 -0
- package/vue-pdf-embed-1/src/vue-pdf-embed.vue +462 -0
- package/vue-pdf-embed-1/test/.eslintrc +5 -0
- package/vue-pdf-embed-1/test/vue-pdf-embed.test.js +55 -0
- package/vue-pdf-embed-1/types/vue2-pdf-embed.d.ts +34 -0
- package/vue-pdf-embed-1/types/vue3-pdf-embed.d.ts +34 -0
- package/vue-pdf-embed-1/webpack.config.js +77 -0
- package/vue-pdf-embed-1/webpack.dev.config.js +29 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :id="id" class="vue-pdf-embed">
|
|
3
|
+
<div v-for="pageNum in pageNums" :key="pageNum">
|
|
4
|
+
<slot name="before-page" :page="pageNum" />
|
|
5
|
+
|
|
6
|
+
<div :id="id && `${id}-${pageNum}`" class="vue-pdf-embed__page">
|
|
7
|
+
<canvas />
|
|
8
|
+
|
|
9
|
+
<div v-if="textLayer" class="textLayer" />
|
|
10
|
+
|
|
11
|
+
<div v-if="annotationLayer" class="annotationLayer" />
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<slot name="after-page" :page="pageNum" />
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script>
|
|
20
|
+
import * as pdf from 'pdfjs-dist/legacy/build/pdf.js'
|
|
21
|
+
import PdfWorker from 'pdfjs-dist/legacy/build/pdf.worker.js'
|
|
22
|
+
import { PDFLinkService } from 'pdfjs-dist/legacy/web/pdf_viewer.js'
|
|
23
|
+
import {
|
|
24
|
+
addPrintStyles,
|
|
25
|
+
createPrintIframe,
|
|
26
|
+
downloadPdf,
|
|
27
|
+
emptyElement,
|
|
28
|
+
releaseChildCanvases,
|
|
29
|
+
} from './util.js'
|
|
30
|
+
|
|
31
|
+
pdf.GlobalWorkerOptions.workerPort = new PdfWorker()
|
|
32
|
+
|
|
33
|
+
export default {
|
|
34
|
+
name: 'VuePdfEmbed',
|
|
35
|
+
props: {
|
|
36
|
+
/**
|
|
37
|
+
* Whether the annotation layer should be enabled.
|
|
38
|
+
* @values Boolean
|
|
39
|
+
*/
|
|
40
|
+
annotationLayer: Boolean,
|
|
41
|
+
/**
|
|
42
|
+
* Desired page height.
|
|
43
|
+
* @values Number, String
|
|
44
|
+
*/
|
|
45
|
+
height: [Number, String],
|
|
46
|
+
/**
|
|
47
|
+
* Component identifier (inherited by page containers with page number
|
|
48
|
+
* postfixes).
|
|
49
|
+
* @values String
|
|
50
|
+
*/
|
|
51
|
+
id: String,
|
|
52
|
+
/**
|
|
53
|
+
* Path for annotation icons, including trailing slash.
|
|
54
|
+
* @values String
|
|
55
|
+
*/
|
|
56
|
+
imageResourcesPath: String,
|
|
57
|
+
/**
|
|
58
|
+
* Number of the page to display.
|
|
59
|
+
* @values Number
|
|
60
|
+
*/
|
|
61
|
+
page: Number,
|
|
62
|
+
/**
|
|
63
|
+
* Desired page rotation angle.
|
|
64
|
+
* @values Number, String
|
|
65
|
+
*/
|
|
66
|
+
rotation: {
|
|
67
|
+
type: [Number, String],
|
|
68
|
+
default: 0,
|
|
69
|
+
validator(value) {
|
|
70
|
+
if (value % 90 !== 0) {
|
|
71
|
+
throw new Error('Rotation must be 0 or a multiple of 90.')
|
|
72
|
+
}
|
|
73
|
+
return true
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* Desired ratio of canvas size to document size.
|
|
78
|
+
* @values Number
|
|
79
|
+
*/
|
|
80
|
+
scale: Number,
|
|
81
|
+
/**
|
|
82
|
+
* Source of the document to display.
|
|
83
|
+
* @values Object, String, URL, TypedArray
|
|
84
|
+
*/
|
|
85
|
+
source: {
|
|
86
|
+
type: [Object, String, URL, Uint8Array],
|
|
87
|
+
required: true,
|
|
88
|
+
},
|
|
89
|
+
/**
|
|
90
|
+
* Whether the text layer should be enabled.
|
|
91
|
+
* @values Boolean
|
|
92
|
+
*/
|
|
93
|
+
textLayer: Boolean,
|
|
94
|
+
/**
|
|
95
|
+
* Desired page width.
|
|
96
|
+
* @values Number, String
|
|
97
|
+
*/
|
|
98
|
+
width: [Number, String],
|
|
99
|
+
},
|
|
100
|
+
data() {
|
|
101
|
+
return {
|
|
102
|
+
documentLoadingTask: null,
|
|
103
|
+
document: null,
|
|
104
|
+
pageCount: null,
|
|
105
|
+
pageNums: [],
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
computed: {
|
|
109
|
+
linkService() {
|
|
110
|
+
if (!this.document || !this.annotationLayer) {
|
|
111
|
+
return null
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const service = new PDFLinkService()
|
|
115
|
+
service.setDocument(this.document)
|
|
116
|
+
service.setViewer({
|
|
117
|
+
scrollPageIntoView: ({ pageNumber }) => {
|
|
118
|
+
this.$emit('internal-link-clicked', pageNumber)
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
return service
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
created() {
|
|
125
|
+
this.$watch(
|
|
126
|
+
() => [
|
|
127
|
+
this.source,
|
|
128
|
+
this.annotationLayer,
|
|
129
|
+
this.height,
|
|
130
|
+
this.page,
|
|
131
|
+
this.rotation,
|
|
132
|
+
this.textLayer,
|
|
133
|
+
this.width,
|
|
134
|
+
],
|
|
135
|
+
async ([newSource], [oldSource]) => {
|
|
136
|
+
if (newSource !== oldSource) {
|
|
137
|
+
releaseChildCanvases(this.$el)
|
|
138
|
+
await this.load()
|
|
139
|
+
}
|
|
140
|
+
this.render()
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
},
|
|
144
|
+
async mounted() {
|
|
145
|
+
await this.load()
|
|
146
|
+
this.render()
|
|
147
|
+
},
|
|
148
|
+
beforeDestroy() {
|
|
149
|
+
releaseChildCanvases(this.$el)
|
|
150
|
+
if (this.documentLoadingTask?.onPassword) {
|
|
151
|
+
this.documentLoadingTask.onPassword = null
|
|
152
|
+
}
|
|
153
|
+
if (this.documentLoadingTask?.onProgress) {
|
|
154
|
+
this.documentLoadingTask.onProgress = null
|
|
155
|
+
}
|
|
156
|
+
this.document?.destroy()
|
|
157
|
+
},
|
|
158
|
+
beforeUnmount() {
|
|
159
|
+
releaseChildCanvases(this.$el)
|
|
160
|
+
if (this.documentLoadingTask?.onPassword) {
|
|
161
|
+
this.documentLoadingTask.onPassword = null
|
|
162
|
+
}
|
|
163
|
+
if (this.documentLoadingTask?.onProgress) {
|
|
164
|
+
this.documentLoadingTask.onProgress = null
|
|
165
|
+
}
|
|
166
|
+
this.document?.destroy()
|
|
167
|
+
},
|
|
168
|
+
methods: {
|
|
169
|
+
/**
|
|
170
|
+
* Downloads a PDF document.
|
|
171
|
+
*
|
|
172
|
+
* NOTE: Ignored if the document is not loaded.
|
|
173
|
+
*
|
|
174
|
+
* @param {string} filename - Predefined filename to save.
|
|
175
|
+
*/
|
|
176
|
+
async download(filename) {
|
|
177
|
+
if (!this.document) {
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const data = await this.document.getData()
|
|
182
|
+
const metadata = await this.document.getMetadata()
|
|
183
|
+
downloadPdf(data, filename ?? metadata.contentDispositionFilename ?? '')
|
|
184
|
+
},
|
|
185
|
+
/**
|
|
186
|
+
* Returns an array of the actual page width and height based on props and
|
|
187
|
+
* aspect ratio.
|
|
188
|
+
* @param {number} ratio - Page aspect ratio.
|
|
189
|
+
*/
|
|
190
|
+
getPageDimensions(ratio) {
|
|
191
|
+
let width, height
|
|
192
|
+
|
|
193
|
+
if (this.height && !this.width) {
|
|
194
|
+
height = this.height
|
|
195
|
+
width = height / ratio
|
|
196
|
+
} else {
|
|
197
|
+
width = this.width || this.$el.clientWidth
|
|
198
|
+
height = width * ratio
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return [width, height]
|
|
202
|
+
},
|
|
203
|
+
/**
|
|
204
|
+
* Loads a PDF document. Defines a password callback for protected
|
|
205
|
+
* documents.
|
|
206
|
+
*
|
|
207
|
+
* NOTE: Ignored if source property is not provided.
|
|
208
|
+
*/
|
|
209
|
+
async load() {
|
|
210
|
+
if (!this.source) {
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
if (this.source._pdfInfo) {
|
|
216
|
+
this.document = this.source
|
|
217
|
+
} else {
|
|
218
|
+
this.documentLoadingTask = pdf.getDocument(this.source)
|
|
219
|
+
this.documentLoadingTask.onProgress = (progressParams) => {
|
|
220
|
+
this.$emit('progress', progressParams)
|
|
221
|
+
}
|
|
222
|
+
this.documentLoadingTask.onPassword = (callback, reason) => {
|
|
223
|
+
const retry = reason === pdf.PasswordResponses.INCORRECT_PASSWORD
|
|
224
|
+
this.$emit('password-requested', callback, retry)
|
|
225
|
+
}
|
|
226
|
+
this.document = await this.documentLoadingTask.promise
|
|
227
|
+
}
|
|
228
|
+
this.pageCount = this.document.numPages
|
|
229
|
+
this.$emit('loaded', this.document)
|
|
230
|
+
} catch (e) {
|
|
231
|
+
this.document = null
|
|
232
|
+
this.pageCount = null
|
|
233
|
+
this.pageNums = []
|
|
234
|
+
this.$emit('loading-failed', e)
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
/**
|
|
238
|
+
* Prints a PDF document via the browser interface.
|
|
239
|
+
*
|
|
240
|
+
* NOTE: Ignored if the document is not loaded.
|
|
241
|
+
*
|
|
242
|
+
* @param {number} dpi - Print resolution.
|
|
243
|
+
* @param {string} filename - Predefined filename to save.
|
|
244
|
+
* @param {boolean} allPages - Ignore page prop to print all pages.
|
|
245
|
+
*/
|
|
246
|
+
async print(dpi = 300, filename = '', allPages = false) {
|
|
247
|
+
if (!this.document) {
|
|
248
|
+
return
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const printUnits = dpi / 72
|
|
252
|
+
const styleUnits = 96 / 72
|
|
253
|
+
let container, iframe, title
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
container = document.createElement('div')
|
|
257
|
+
container.style.display = 'none'
|
|
258
|
+
window.document.body.appendChild(container)
|
|
259
|
+
iframe = await createPrintIframe(container)
|
|
260
|
+
|
|
261
|
+
const pageNums =
|
|
262
|
+
this.page && !allPages
|
|
263
|
+
? [this.page]
|
|
264
|
+
: [...Array(this.document.numPages + 1).keys()].slice(1)
|
|
265
|
+
|
|
266
|
+
await Promise.all(
|
|
267
|
+
pageNums.map(async (pageNum, i) => {
|
|
268
|
+
const page = await this.document.getPage(pageNum)
|
|
269
|
+
const viewport = page.getViewport({
|
|
270
|
+
scale: 1,
|
|
271
|
+
rotation: 0,
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
if (i === 0) {
|
|
275
|
+
const sizeX = (viewport.width * printUnits) / styleUnits
|
|
276
|
+
const sizeY = (viewport.height * printUnits) / styleUnits
|
|
277
|
+
addPrintStyles(iframe, sizeX, sizeY)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const canvas = document.createElement('canvas')
|
|
281
|
+
canvas.width = viewport.width * printUnits
|
|
282
|
+
canvas.height = viewport.height * printUnits
|
|
283
|
+
container.appendChild(canvas)
|
|
284
|
+
const canvasClone = canvas.cloneNode()
|
|
285
|
+
iframe.contentWindow.document.body.appendChild(canvasClone)
|
|
286
|
+
|
|
287
|
+
await page.render({
|
|
288
|
+
canvasContext: canvas.getContext('2d'),
|
|
289
|
+
intent: 'print',
|
|
290
|
+
transform: [printUnits, 0, 0, printUnits, 0, 0],
|
|
291
|
+
viewport,
|
|
292
|
+
}).promise
|
|
293
|
+
|
|
294
|
+
canvasClone.getContext('2d').drawImage(canvas, 0, 0)
|
|
295
|
+
})
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
if (filename) {
|
|
299
|
+
title = window.document.title
|
|
300
|
+
window.document.title = filename
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
iframe.contentWindow.focus()
|
|
304
|
+
iframe.contentWindow.print()
|
|
305
|
+
} finally {
|
|
306
|
+
if (title) {
|
|
307
|
+
window.document.title = title
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
releaseChildCanvases(container)
|
|
311
|
+
container.parentNode?.removeChild(container)
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
/**
|
|
315
|
+
* Renders the PDF document as canvas element(s) and additional layers.
|
|
316
|
+
*
|
|
317
|
+
* NOTE: Ignored if the document is not loaded.
|
|
318
|
+
*/
|
|
319
|
+
async render() {
|
|
320
|
+
if (!this.document) {
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
this.pageNums = this.page
|
|
326
|
+
? [this.page]
|
|
327
|
+
: [...Array(this.document.numPages + 1).keys()].slice(1)
|
|
328
|
+
|
|
329
|
+
const pageElements = this.$el.getElementsByClassName(
|
|
330
|
+
'vue-pdf-embed__page'
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
await Promise.all(
|
|
334
|
+
this.pageNums.map(async (pageNum, i) => {
|
|
335
|
+
const page = await this.document.getPage(pageNum)
|
|
336
|
+
const pageRotation = this.rotation + page.rotate
|
|
337
|
+
const [canvas, div1, div2] = pageElements[i].children
|
|
338
|
+
const [actualWidth, actualHeight] = this.getPageDimensions(
|
|
339
|
+
(pageRotation / 90) % 2
|
|
340
|
+
? page.view[2] / page.view[3]
|
|
341
|
+
: page.view[3] / page.view[2]
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
canvas.style.width = `${Math.floor(actualWidth)}px`
|
|
345
|
+
canvas.style.height = `${Math.floor(actualHeight)}px`
|
|
346
|
+
|
|
347
|
+
await this.renderPage(page, canvas, actualWidth, pageRotation)
|
|
348
|
+
|
|
349
|
+
if (this.textLayer) {
|
|
350
|
+
await this.renderPageTextLayer(
|
|
351
|
+
page,
|
|
352
|
+
div1,
|
|
353
|
+
actualWidth,
|
|
354
|
+
pageRotation
|
|
355
|
+
)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (this.annotationLayer) {
|
|
359
|
+
await this.renderPageAnnotationLayer(
|
|
360
|
+
page,
|
|
361
|
+
div2 || div1,
|
|
362
|
+
actualWidth,
|
|
363
|
+
pageRotation
|
|
364
|
+
)
|
|
365
|
+
}
|
|
366
|
+
})
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
this.$emit('rendered')
|
|
370
|
+
} catch (e) {
|
|
371
|
+
this.document = null
|
|
372
|
+
this.pageCount = null
|
|
373
|
+
this.pageNums = []
|
|
374
|
+
this.$emit('rendering-failed', e)
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
/**
|
|
378
|
+
* Renders the page content.
|
|
379
|
+
* @param {PDFPageProxy} page - Page proxy.
|
|
380
|
+
* @param {HTMLCanvasElement} canvas - HTML canvas.
|
|
381
|
+
* @param {number} width - Actual page width.
|
|
382
|
+
* @param {number} rotation - Total page rotation.
|
|
383
|
+
*/
|
|
384
|
+
async renderPage(page, canvas, width, rotation) {
|
|
385
|
+
const pageWidth = (rotation / 90) % 2 ? page.view[3] : page.view[2]
|
|
386
|
+
const viewport = page.getViewport({
|
|
387
|
+
scale: this.scale ?? Math.ceil(width / pageWidth) + 1,
|
|
388
|
+
rotation,
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
canvas.width = viewport.width
|
|
392
|
+
canvas.height = viewport.height
|
|
393
|
+
|
|
394
|
+
await page.render({
|
|
395
|
+
canvasContext: canvas.getContext('2d'),
|
|
396
|
+
viewport,
|
|
397
|
+
}).promise
|
|
398
|
+
},
|
|
399
|
+
/**
|
|
400
|
+
* Renders the annotation layer for the specified page.
|
|
401
|
+
* @param {PDFPageProxy} page - Page proxy.
|
|
402
|
+
* @param {HTMLElement} container - HTML container.
|
|
403
|
+
* @param {number} width - Actual page width.
|
|
404
|
+
* @param {number} rotation - Total page rotation.
|
|
405
|
+
*/
|
|
406
|
+
async renderPageAnnotationLayer(page, container, width, rotation) {
|
|
407
|
+
emptyElement(container)
|
|
408
|
+
const pageWidth = (rotation / 90) % 2 ? page.view[3] : page.view[2]
|
|
409
|
+
pdf.AnnotationLayer.render({
|
|
410
|
+
annotations: await page.getAnnotations(),
|
|
411
|
+
div: container,
|
|
412
|
+
linkService: this.linkService,
|
|
413
|
+
page,
|
|
414
|
+
renderInteractiveForms: false,
|
|
415
|
+
viewport: page
|
|
416
|
+
.getViewport({
|
|
417
|
+
scale: width / pageWidth,
|
|
418
|
+
rotation,
|
|
419
|
+
})
|
|
420
|
+
.clone({
|
|
421
|
+
dontFlip: true,
|
|
422
|
+
}),
|
|
423
|
+
imageResourcesPath: this.imageResourcesPath,
|
|
424
|
+
})
|
|
425
|
+
},
|
|
426
|
+
/**
|
|
427
|
+
* Renders the text layer for the specified page.
|
|
428
|
+
* @param {PDFPageProxy} page - Page proxy.
|
|
429
|
+
* @param {HTMLElement} container - HTML container.
|
|
430
|
+
* @param {number} width - Actual page width.
|
|
431
|
+
* @param {number} rotation - Total page rotation.
|
|
432
|
+
*/
|
|
433
|
+
async renderPageTextLayer(page, container, width, rotation) {
|
|
434
|
+
emptyElement(container)
|
|
435
|
+
const pageWidth = (rotation / 90) % 2 ? page.view[3] : page.view[2]
|
|
436
|
+
await pdf.renderTextLayer({
|
|
437
|
+
container,
|
|
438
|
+
textContent: await page.getTextContent(),
|
|
439
|
+
viewport: page.getViewport({
|
|
440
|
+
scale: width / pageWidth,
|
|
441
|
+
rotation,
|
|
442
|
+
}),
|
|
443
|
+
}).promise
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
}
|
|
447
|
+
</script>
|
|
448
|
+
|
|
449
|
+
<style lang="scss">
|
|
450
|
+
@import 'styles/text-layer';
|
|
451
|
+
@import 'styles/annotation-layer';
|
|
452
|
+
|
|
453
|
+
.vue-pdf-embed {
|
|
454
|
+
&__page {
|
|
455
|
+
position: relative;
|
|
456
|
+
|
|
457
|
+
canvas {
|
|
458
|
+
display: block;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
</style>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import VuePdfEmbed from '../src/vue-pdf-embed.vue'
|
|
3
|
+
|
|
4
|
+
HTMLCanvasElement.prototype.getContext = () => {}
|
|
5
|
+
|
|
6
|
+
jest.mock('pdfjs-dist/legacy/build/pdf.worker.js', () => jest.fn())
|
|
7
|
+
|
|
8
|
+
jest.mock('pdfjs-dist/legacy/build/pdf.js', () => ({
|
|
9
|
+
GlobalWorkerOptions: {},
|
|
10
|
+
getDocument: () => ({
|
|
11
|
+
promise: {
|
|
12
|
+
numPages: 5,
|
|
13
|
+
getPage: () => ({
|
|
14
|
+
view: [],
|
|
15
|
+
getViewport: () => ({}),
|
|
16
|
+
render: () => ({}),
|
|
17
|
+
}),
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
}))
|
|
21
|
+
|
|
22
|
+
const Component = Vue.extend(VuePdfEmbed)
|
|
23
|
+
let vm, emitSpy
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
vm = new Component({
|
|
27
|
+
propsData: {
|
|
28
|
+
disableAnnotationLayer: true,
|
|
29
|
+
disableTextLayer: true,
|
|
30
|
+
source: 'SOURCE',
|
|
31
|
+
},
|
|
32
|
+
}).$mount()
|
|
33
|
+
emitSpy = jest.spyOn(vm, '$emit')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('sets correct data', () => {
|
|
37
|
+
expect(vm.document).toBeTruthy()
|
|
38
|
+
expect(vm.pageCount).toBe(5)
|
|
39
|
+
expect(vm.pageNums).toEqual([1, 2, 3, 4, 5])
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('sets page IDs', async () => {
|
|
43
|
+
vm.id = 'ID'
|
|
44
|
+
await vm.$nextTick()
|
|
45
|
+
vm.$el.childNodes.forEach((node, i) => {
|
|
46
|
+
expect(node.id).toEqual(`ID-${i + 1}`)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('emits successful event', async () => {
|
|
51
|
+
await vm.$nextTick()
|
|
52
|
+
expect(emitSpy).lastCalledWith('loaded', expect.anything())
|
|
53
|
+
await vm.$nextTick()
|
|
54
|
+
expect(emitSpy).lastCalledWith('rendered')
|
|
55
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { VueConstructor } from 'vue';
|
|
2
|
+
|
|
3
|
+
export interface VuePdfEmbedProps {
|
|
4
|
+
annotationLayer?: boolean;
|
|
5
|
+
height?: number | string;
|
|
6
|
+
imageResourcesPath?: string;
|
|
7
|
+
page?: number;
|
|
8
|
+
rotation?: number | string;
|
|
9
|
+
source: object | string | URL | Uint8Array;
|
|
10
|
+
textLayer?: boolean;
|
|
11
|
+
width?: number | string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface VuePdfEmbedData {
|
|
15
|
+
document: object | null;
|
|
16
|
+
pageCount: number | null;
|
|
17
|
+
pageNums: number[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface VuePdfEmbedMethods {
|
|
21
|
+
download: (filename?: string) => Promise<void>;
|
|
22
|
+
print: (dpi?: number, filename?: string, allPages?: boolean) => Promise<void>;
|
|
23
|
+
render: () => Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface VuePdfEmbedConstructor extends VueConstructor {
|
|
27
|
+
props: VuePdfEmbedProps;
|
|
28
|
+
data: () => VuePdfEmbedData;
|
|
29
|
+
methods: VuePdfEmbedMethods;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare const VuePdfEmbed: VuePdfEmbedConstructor;
|
|
33
|
+
|
|
34
|
+
export default VuePdfEmbed;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ComputedOptions, DefineComponent, MethodOptions } from 'vue';
|
|
2
|
+
|
|
3
|
+
export interface VuePdfEmbedProps {
|
|
4
|
+
annotationLayer?: boolean;
|
|
5
|
+
height?: number | string;
|
|
6
|
+
imageResourcesPath?: string;
|
|
7
|
+
page?: number;
|
|
8
|
+
rotation?: number | string;
|
|
9
|
+
source: object | string | URL | Uint8Array;
|
|
10
|
+
textLayer?: boolean;
|
|
11
|
+
width?: number | string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface VuePdfEmbedData {
|
|
15
|
+
document: object | null;
|
|
16
|
+
pageCount: number | null;
|
|
17
|
+
pageNums: number[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface VuePdfEmbedMethods extends MethodOptions {
|
|
21
|
+
download: (filename?: string) => Promise<void>;
|
|
22
|
+
print: (dpi?: number, filename?: string, allPages?: boolean) => Promise<void>;
|
|
23
|
+
render: () => Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare const VuePdfEmbed: DefineComponent<
|
|
27
|
+
VuePdfEmbedProps,
|
|
28
|
+
{},
|
|
29
|
+
VuePdfEmbedData,
|
|
30
|
+
ComputedOptions,
|
|
31
|
+
VuePdfEmbedMethods
|
|
32
|
+
>;
|
|
33
|
+
|
|
34
|
+
export default VuePdfEmbed;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const { merge } = require('webpack-merge')
|
|
2
|
+
const CopyPlugin = require('copy-webpack-plugin')
|
|
3
|
+
const TerserPlugin = require('terser-webpack-plugin')
|
|
4
|
+
const { VueLoaderPlugin: Vue2LoaderPlugin } = require('vue-loader')
|
|
5
|
+
const { VueLoaderPlugin: Vue3LoaderPlugin } = require('vue-loader-next')
|
|
6
|
+
|
|
7
|
+
const commonConfig = {
|
|
8
|
+
mode: 'production',
|
|
9
|
+
entry: './src/index.js',
|
|
10
|
+
output: {
|
|
11
|
+
library: {
|
|
12
|
+
name: 'vue-pdf-embed',
|
|
13
|
+
type: 'umd',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
module: {
|
|
17
|
+
rules: [
|
|
18
|
+
{
|
|
19
|
+
test: /\.js$/,
|
|
20
|
+
loader: 'babel-loader',
|
|
21
|
+
exclude: /node_modules/,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
test: /\.vue$/,
|
|
25
|
+
loader: 'vue-loader',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
test: /\.s?css$/,
|
|
29
|
+
use: ['vue-style-loader', 'css-loader', 'sass-loader'],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
test: /\.worker\.js$/,
|
|
33
|
+
loader: 'worker-loader',
|
|
34
|
+
options: {
|
|
35
|
+
inline: 'no-fallback',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
optimization: {
|
|
41
|
+
minimizer: [
|
|
42
|
+
new TerserPlugin({
|
|
43
|
+
extractComments: false,
|
|
44
|
+
terserOptions: {
|
|
45
|
+
format: {
|
|
46
|
+
comments: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
externals: {
|
|
53
|
+
vue: 'vue',
|
|
54
|
+
},
|
|
55
|
+
performance: {
|
|
56
|
+
hints: false,
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = [
|
|
61
|
+
merge(commonConfig, {
|
|
62
|
+
output: {
|
|
63
|
+
clean: true,
|
|
64
|
+
filename: 'vue2-pdf-embed.js',
|
|
65
|
+
},
|
|
66
|
+
plugins: [new Vue2LoaderPlugin()],
|
|
67
|
+
}),
|
|
68
|
+
merge(commonConfig, {
|
|
69
|
+
output: {
|
|
70
|
+
filename: 'vue3-pdf-embed.js',
|
|
71
|
+
},
|
|
72
|
+
plugins: [
|
|
73
|
+
new Vue3LoaderPlugin(),
|
|
74
|
+
new CopyPlugin({ patterns: [{ from: 'types' }] }),
|
|
75
|
+
],
|
|
76
|
+
}),
|
|
77
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { VueLoaderPlugin } = require('vue-loader')
|
|
2
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
mode: 'development',
|
|
6
|
+
entry: './demo/main.js',
|
|
7
|
+
module: {
|
|
8
|
+
rules: [
|
|
9
|
+
{
|
|
10
|
+
test: /\.vue$/,
|
|
11
|
+
use: 'vue-loader',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
test: /\.s?css$/,
|
|
15
|
+
use: ['vue-style-loader', 'css-loader', 'sass-loader'],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
test: /\.worker\.js$/,
|
|
19
|
+
loader: 'worker-loader',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
plugins: [
|
|
24
|
+
new VueLoaderPlugin(),
|
|
25
|
+
new HtmlWebpackPlugin({
|
|
26
|
+
template: './demo/index.html',
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
}
|