mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-14 20:40:17 -05:00
Convert PDF.js code to TypeScript
GitOrigin-RevId: 840bc48816d78497131b927522b4f6f7940bb0c4
This commit is contained in:
parent
be45aec5b5
commit
df6147bb4d
11 changed files with 135 additions and 164 deletions
|
@ -15,9 +15,9 @@ const FileViewPdf: FC<{
|
|||
const handleContainer = useCallback(
|
||||
async (element: HTMLDivElement | null) => {
|
||||
if (element) {
|
||||
const { PDFJS } = await import(
|
||||
'../../pdf-preview/util/pdf-js-versions'
|
||||
).then(m => m.default as any)
|
||||
const { loadPdfDocumentFromUrl } = await import(
|
||||
'@/features/pdf-preview/util/pdf-js'
|
||||
)
|
||||
|
||||
// bail out if loading PDF.js took too long
|
||||
if (!mountedRef.current) {
|
||||
|
@ -33,10 +33,7 @@ const FileViewPdf: FC<{
|
|||
return
|
||||
}
|
||||
|
||||
const pdf = await PDFJS.getDocument({
|
||||
url: preview.url,
|
||||
isEvalSupported: false,
|
||||
}).promise
|
||||
const pdf = await loadPdfDocumentFromUrl(preview.url).promise
|
||||
|
||||
// bail out if loading the PDF took too long
|
||||
if (!mountedRef.current) {
|
||||
|
@ -61,7 +58,7 @@ const FileViewPdf: FC<{
|
|||
|
||||
element.append(canvas)
|
||||
page.render({
|
||||
canvasContext: canvas.getContext('2d'),
|
||||
canvasContext: canvas.getContext('2d')!,
|
||||
viewport,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
import {
|
||||
memo,
|
||||
MouseEventHandler,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { debounce, throttle } from 'lodash'
|
||||
import PdfViewerControlsToolbar from './pdf-viewer-controls-toolbar'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
@ -22,6 +15,7 @@ import { debugConsole } from '@/utils/debugging'
|
|||
import { usePdfPreviewContext } from '@/features/pdf-preview/components/pdf-preview-provider'
|
||||
import usePresentationMode from '../hooks/use-presentation-mode'
|
||||
import useMouseWheelZoom from '../hooks/use-mouse-wheel-zoom'
|
||||
import { PDFJS } from '../util/pdf-js'
|
||||
|
||||
type PdfJsViewerProps = {
|
||||
url: string
|
||||
|
@ -70,20 +64,18 @@ function PdfJsViewer({ url, pdfFile }: PdfJsViewerProps) {
|
|||
const handleContainer = useCallback(
|
||||
parent => {
|
||||
if (parent) {
|
||||
const wrapper = new PDFJSWrapper(parent.firstChild)
|
||||
wrapper
|
||||
.init()
|
||||
.then(() => {
|
||||
setPdfJsWrapper(wrapper)
|
||||
})
|
||||
.catch(error => {
|
||||
setLoadingError(true)
|
||||
captureException(error)
|
||||
})
|
||||
let wrapper: PDFJSWrapper | undefined
|
||||
try {
|
||||
wrapper = new PDFJSWrapper(parent.firstChild)
|
||||
setPdfJsWrapper(wrapper)
|
||||
} catch (error) {
|
||||
setLoadingError(true)
|
||||
captureException(error)
|
||||
}
|
||||
|
||||
return () => {
|
||||
setPdfJsWrapper(null)
|
||||
wrapper.destroy()
|
||||
wrapper?.destroy().catch(debugConsole.error)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -180,7 +172,7 @@ function PdfJsViewer({ url, pdfFile }: PdfJsViewerProps) {
|
|||
const handleFetchError = (err: Error) => {
|
||||
if (abortController.signal.aborted) return
|
||||
// The error is already logged at the call-site with additional context.
|
||||
if (err instanceof pdfJsWrapper.PDFJS.MissingPDFException) {
|
||||
if (err instanceof PDFJS.MissingPDFException) {
|
||||
setError('rendering-error-expected')
|
||||
} else {
|
||||
setError('rendering-error')
|
||||
|
@ -254,7 +246,7 @@ function PdfJsViewer({ url, pdfFile }: PdfJsViewerProps) {
|
|||
if (!textLayerDiv.dataset.listeningForDoubleClick) {
|
||||
textLayerDiv.dataset.listeningForDoubleClick = true
|
||||
|
||||
const doubleClickListener: MouseEventHandler = event => {
|
||||
const doubleClickListener = (event: MouseEvent) => {
|
||||
const clickPosition = pdfJsWrapper.clickPosition(
|
||||
event,
|
||||
textLayerDiv.closest('.page').querySelector('canvas'),
|
||||
|
@ -355,7 +347,7 @@ function PdfJsViewer({ url, pdfFile }: PdfJsViewerProps) {
|
|||
|
||||
for (const highlight of highlights) {
|
||||
try {
|
||||
const element = buildHighlightElement(highlight, pdfJsWrapper)
|
||||
const element = buildHighlightElement(highlight, pdfJsWrapper.viewer)
|
||||
elements.push(element)
|
||||
intersectionObserver.observe(element)
|
||||
} catch (error) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { memo, Suspense } from 'react'
|
||||
import { ElementType, memo, Suspense } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import PdfLogsViewer from './pdf-logs-viewer'
|
||||
import PdfViewer from './pdf-viewer'
|
||||
|
@ -10,7 +10,10 @@ import CompileTimeWarningUpgradePrompt from './compile-time-warning-upgrade-prom
|
|||
import { PdfPreviewProvider } from './pdf-preview-provider'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
|
||||
const pdfPreviewPromotions = importOverleafModules('pdfPreviewPromotions')
|
||||
const pdfPreviewPromotions = importOverleafModules('pdfPreviewPromotions') as {
|
||||
import: { default: ElementType }
|
||||
path: string
|
||||
}[]
|
||||
|
||||
function PdfPreviewPane() {
|
||||
const { pdfUrl, hasShortCompileTimeout } = useCompileContext()
|
|
@ -1,6 +1,7 @@
|
|||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import PDFJSWrapper from '../util/pdf-js-wrapper'
|
||||
import { sendMB } from '@/infrastructure/event-tracking'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
|
||||
type StoredPDFState = {
|
||||
scrollMode?: number
|
||||
|
@ -116,7 +117,9 @@ export default function usePresentationMode(
|
|||
sendMB('pdf-viewer-enter-presentation-mode')
|
||||
|
||||
if (pdfJsWrapper) {
|
||||
pdfJsWrapper.container.parentNode.requestFullscreen()
|
||||
pdfJsWrapper.container.parentElement
|
||||
?.requestFullscreen()
|
||||
.catch(debugConsole.error)
|
||||
}
|
||||
}, [pdfJsWrapper])
|
||||
|
||||
|
@ -136,8 +139,8 @@ export default function usePresentationMode(
|
|||
|
||||
const handleExitFullscreen = useCallback(() => {
|
||||
if (pdfJsWrapper) {
|
||||
pdfJsWrapper.viewer.scrollMode = storedState.current.scrollMode
|
||||
pdfJsWrapper.viewer.spreadMode = storedState.current.spreadMode
|
||||
pdfJsWrapper.viewer.scrollMode = storedState.current.scrollMode!
|
||||
pdfJsWrapper.viewer.spreadMode = storedState.current.spreadMode!
|
||||
|
||||
if (storedState.current.currentScaleValue !== undefined) {
|
||||
setScale(storedState.current.currentScaleValue)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
export function buildHighlightElement(highlight, wrapper) {
|
||||
const pageView = wrapper.viewer.getPageView(highlight.page - 1)
|
||||
import { PDFJS } from '@/features/pdf-preview/util/pdf-js'
|
||||
|
||||
export function buildHighlightElement(highlight, viewer) {
|
||||
const pageView = viewer.getPageView(highlight.page - 1)
|
||||
|
||||
const viewport = pageView.viewport
|
||||
|
||||
|
@ -12,7 +14,7 @@ export function buildHighlightElement(highlight, wrapper) {
|
|||
height - highlight.v + 10, // yMax
|
||||
])
|
||||
|
||||
const [left, top, right, bottom] = wrapper.PDFJS.Util.normalizeRect(rect)
|
||||
const [left, top, right, bottom] = PDFJS.Util.normalizeRect(rect)
|
||||
|
||||
const element = document.createElement('div')
|
||||
element.style.left = Math.floor(pageView.div.offsetLeft + left) + 'px'
|
||||
|
@ -27,7 +29,7 @@ export function buildHighlightElement(highlight, wrapper) {
|
|||
element.style.opacity = '0'
|
||||
element.style.transition = 'opacity 1s'
|
||||
|
||||
wrapper.viewer.viewer.append(element)
|
||||
viewer.viewer?.append(element)
|
||||
|
||||
return element
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import OError from '@overleaf/o-error'
|
||||
import { fallbackRequest, fetchRange } from './pdf-caching'
|
||||
import { captureException } from '../../../infrastructure/error-reporter'
|
||||
import { captureException } from '@/infrastructure/error-reporter'
|
||||
import { getPdfCachingMetrics } from './metrics'
|
||||
import {
|
||||
cachedUrlLookupEnabled,
|
||||
|
@ -9,16 +9,17 @@ import {
|
|||
prefetchLargeEnabled,
|
||||
trackPdfDownloadEnabled,
|
||||
} from './pdf-caching-flags'
|
||||
import { isNetworkError } from '../../../utils/isNetworkError'
|
||||
import { isNetworkError } from '@/utils/isNetworkError'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { PDFJS } from './pdf-js'
|
||||
|
||||
// 30 seconds: The shutdown grace period of a clsi pre-emp instance.
|
||||
const STALE_OUTPUT_REQUEST_THRESHOLD_MS = 30 * 1000
|
||||
|
||||
export function generatePdfCachingTransportFactory(PDFJS) {
|
||||
export function generatePdfCachingTransportFactory() {
|
||||
// NOTE: The custom transport can be used for tracking download volume.
|
||||
if (!enablePdfCaching && !trackPdfDownloadEnabled) {
|
||||
return () => null
|
||||
return () => undefined
|
||||
}
|
||||
const usageScore = new Map()
|
||||
const cachedUrls = new Map()
|
||||
|
@ -180,7 +181,7 @@ export function generatePdfCachingTransportFactory(PDFJS) {
|
|||
if (metrics.failedOnce) {
|
||||
// Disable pdf caching once any fetch request failed.
|
||||
// Be trigger-happy here until we reached a stable state of the feature.
|
||||
return null
|
||||
return undefined
|
||||
}
|
||||
// Latency is collected per preview cycle.
|
||||
metrics.latencyComputeMax = 0
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
// To add a new version, copy and adjust one of the `importPDFJS*` functions below,
|
||||
// add the variant to the "switch" statement, and add to `pdfjsVersions` in webpack.config.js
|
||||
|
||||
import 'core-js/stable/global-this' // polyfill for globalThis (used by pdf.js)
|
||||
import 'core-js/stable/promise/all-settled' // polyfill for Promise.allSettled (used by pdf.js)
|
||||
import 'core-js/stable/structured-clone' // polyfill for global.StructuredClone (used by pdf.js)
|
||||
import 'core-js/stable/array/at' // polyfill for Array.prototype.at (used by pdf.js)
|
||||
import { createWorker } from '@/utils/worker'
|
||||
|
||||
async function importPDFJS() {
|
||||
const cMapUrl = '/js/pdfjs-dist/cmaps/'
|
||||
const standardFontDataUrl = '/fonts/pdfjs-dist/'
|
||||
const imageResourcesPath = '/images/pdfjs-dist/'
|
||||
|
||||
// ensure that PDF.js is loaded before importing the viewer
|
||||
const PDFJS = await import('pdfjs-dist/legacy/build/pdf')
|
||||
|
||||
const [PDFJSViewer] = await Promise.all([
|
||||
import('pdfjs-dist/legacy/web/pdf_viewer'),
|
||||
import('pdfjs-dist/legacy/web/pdf_viewer.css'),
|
||||
])
|
||||
|
||||
createWorker(() => {
|
||||
PDFJS.GlobalWorkerOptions.workerPort = new Worker(
|
||||
new URL('pdfjs-dist/legacy/build/pdf.worker.mjs', import.meta.url) // NOTE: .mjs extension
|
||||
)
|
||||
})
|
||||
|
||||
return {
|
||||
PDFJS,
|
||||
PDFJSViewer,
|
||||
cMapUrl,
|
||||
imageResourcesPath,
|
||||
standardFontDataUrl,
|
||||
}
|
||||
}
|
||||
|
||||
export default importPDFJS()
|
|
@ -1,81 +1,70 @@
|
|||
import { captureException } from '../../../infrastructure/error-reporter'
|
||||
import { captureException } from '@/infrastructure/error-reporter'
|
||||
import { generatePdfCachingTransportFactory } from './pdf-caching-transport'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
const disableFontFace = params.get('disable-font-face') === 'true'
|
||||
const disableStream = process.env.NODE_ENV !== 'test'
|
||||
import { PDFJS, loadPdfDocumentFromUrl, imageResourcesPath } from './pdf-js'
|
||||
import {
|
||||
PDFViewer,
|
||||
EventBus,
|
||||
PDFLinkService,
|
||||
LinkTarget,
|
||||
} from 'pdfjs-dist/legacy/web/pdf_viewer.mjs'
|
||||
import 'pdfjs-dist/legacy/web/pdf_viewer.css'
|
||||
|
||||
const DEFAULT_RANGE_CHUNK_SIZE = 128 * 1024 // 128K chunks
|
||||
|
||||
export default class PDFJSWrapper {
|
||||
constructor(container) {
|
||||
this.container = container
|
||||
}
|
||||
private loadDocumentTask: PDFJS.PDFDocumentLoadingTask | undefined
|
||||
|
||||
async init() {
|
||||
const {
|
||||
PDFJS,
|
||||
PDFJSViewer,
|
||||
cMapUrl,
|
||||
imageResourcesPath,
|
||||
standardFontDataUrl,
|
||||
} = await import('./pdf-js-versions').then(m => {
|
||||
return m.default
|
||||
})
|
||||
|
||||
this.PDFJS = PDFJS
|
||||
this.genPdfCachingTransport = generatePdfCachingTransportFactory(PDFJS)
|
||||
this.PDFJSViewer = PDFJSViewer
|
||||
this.cMapUrl = cMapUrl
|
||||
this.standardFontDataUrl = standardFontDataUrl
|
||||
this.imageResourcesPath = imageResourcesPath
|
||||
public readonly viewer: PDFViewer
|
||||
public readonly eventBus: EventBus
|
||||
private readonly linkService: PDFLinkService
|
||||
|
||||
// eslint-disable-next-line no-useless-constructor
|
||||
constructor(public container: HTMLDivElement) {
|
||||
// create the event bus
|
||||
const eventBus = new PDFJSViewer.EventBus()
|
||||
this.eventBus = new EventBus()
|
||||
|
||||
// create the link service
|
||||
const linkService = new PDFJSViewer.PDFLinkService({
|
||||
eventBus,
|
||||
externalLinkTarget: 2,
|
||||
this.linkService = new PDFLinkService({
|
||||
eventBus: this.eventBus,
|
||||
externalLinkTarget: LinkTarget.BLANK,
|
||||
externalLinkRel: 'noopener',
|
||||
})
|
||||
|
||||
// create the localization
|
||||
// const l10n = new PDFJSViewer.GenericL10n('en-GB') // TODO: locale mapping?
|
||||
|
||||
// create the viewer
|
||||
const viewer = new PDFJSViewer.PDFViewer({
|
||||
this.viewer = new PDFViewer({
|
||||
container: this.container,
|
||||
eventBus,
|
||||
eventBus: this.eventBus,
|
||||
imageResourcesPath,
|
||||
linkService,
|
||||
// l10n, // commented out since it currently breaks `aria-label` rendering in pdf pages
|
||||
enableScripting: false, // default is false, but set explicitly to be sure
|
||||
enableXfa: false, // default is false (2021-10-12), but set explicitly to be sure
|
||||
renderInteractiveForms: false,
|
||||
linkService: this.linkService,
|
||||
maxCanvasPixels: 8192 * 8192, // default is 4096 * 4096, increased for better resolution at high zoom levels
|
||||
annotationMode: PDFJS.AnnotationMode?.ENABLE, // enable annotations but not forms
|
||||
annotationEditorMode: PDFJS.AnnotationEditorType?.DISABLE, // disable annotation editing
|
||||
annotationMode: PDFJS.AnnotationMode.ENABLE, // enable annotations but not forms
|
||||
annotationEditorMode: PDFJS.AnnotationEditorType.DISABLE, // disable annotation editing
|
||||
})
|
||||
|
||||
linkService.setViewer(viewer)
|
||||
|
||||
this.eventBus = eventBus
|
||||
this.linkService = linkService
|
||||
this.viewer = viewer
|
||||
this.linkService.setViewer(this.viewer)
|
||||
}
|
||||
|
||||
// load a document from a URL
|
||||
loadDocument({ url, pdfFile, abortController, handleFetchError }) {
|
||||
loadDocument({
|
||||
url,
|
||||
pdfFile,
|
||||
abortController,
|
||||
handleFetchError,
|
||||
}: {
|
||||
url: string
|
||||
pdfFile: Record<string, any>
|
||||
abortController: AbortController
|
||||
handleFetchError: (error: Error) => void
|
||||
}) {
|
||||
// cancel any previous loading task
|
||||
if (this.loadDocumentTask) {
|
||||
this.loadDocumentTask.destroy()
|
||||
this.loadDocumentTask.destroy().catch(debugConsole.error)
|
||||
this.loadDocumentTask = undefined
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const rangeTransport = this.genPdfCachingTransport({
|
||||
return new Promise<PDFJS.PDFDocumentProxy>((resolve, reject) => {
|
||||
const rangeTransport = generatePdfCachingTransportFactory()({
|
||||
url,
|
||||
pdfFile,
|
||||
abortController,
|
||||
|
@ -87,35 +76,25 @@ export default class PDFJSWrapper {
|
|||
// custom range transport. Restore it by bumping the chunk size.
|
||||
rangeChunkSize = pdfFile.size
|
||||
}
|
||||
this.loadDocumentTask = this.PDFJS.getDocument({
|
||||
url,
|
||||
cMapUrl: this.cMapUrl,
|
||||
cMapPacked: true,
|
||||
standardFontDataUrl: this.standardFontDataUrl,
|
||||
disableFontFace,
|
||||
this.loadDocumentTask = loadPdfDocumentFromUrl(url, {
|
||||
rangeChunkSize,
|
||||
disableAutoFetch: true,
|
||||
disableStream,
|
||||
isEvalSupported: false,
|
||||
textLayerMode: 2, // PDFJSViewer.TextLayerMode.ENABLE,
|
||||
range: rangeTransport,
|
||||
})
|
||||
|
||||
this.loadDocumentTask.promise
|
||||
.then(doc => {
|
||||
if (!this.loadDocumentTask) {
|
||||
if (!this.loadDocumentTask || !this.viewer) {
|
||||
return // ignoring the response since loading task has been aborted
|
||||
}
|
||||
|
||||
const previousDoc = this.viewer.pdfDocument
|
||||
|
||||
this.viewer.setDocument(doc)
|
||||
this.linkService.setDocument(doc)
|
||||
resolve(doc)
|
||||
|
||||
if (previousDoc) {
|
||||
previousDoc.cleanup().catch(debugConsole.error)
|
||||
previousDoc.destroy()
|
||||
previousDoc.destroy().catch(debugConsole.error)
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
|
@ -163,7 +142,7 @@ export default class PDFJSWrapper {
|
|||
}
|
||||
|
||||
// get the page and offset of a click event
|
||||
clickPosition(event, canvas, page) {
|
||||
clickPosition(event: MouseEvent, canvas: HTMLCanvasElement, page: number) {
|
||||
if (!canvas) {
|
||||
return
|
||||
}
|
||||
|
@ -205,7 +184,7 @@ export default class PDFJSWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
scrollToPosition(position, scale = null) {
|
||||
scrollToPosition(position: Record<string, any>, scale = null) {
|
||||
const destArray = [
|
||||
null,
|
||||
{
|
||||
|
@ -239,13 +218,9 @@ export default class PDFJSWrapper {
|
|||
this.loadDocumentTask = undefined
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.loadDocumentTask) {
|
||||
this.loadDocumentTask.destroy()
|
||||
this.loadDocumentTask = undefined
|
||||
}
|
||||
if (this.viewer) {
|
||||
this.viewer.destroy()
|
||||
}
|
||||
async destroy() {
|
||||
await this.loadDocumentTask?.destroy().catch(debugConsole.error)
|
||||
this.loadDocumentTask = undefined
|
||||
await this.viewer.pdfDocument?.destroy().catch(debugConsole.error)
|
||||
}
|
||||
}
|
40
services/web/frontend/js/features/pdf-preview/util/pdf-js.ts
Normal file
40
services/web/frontend/js/features/pdf-preview/util/pdf-js.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import 'core-js/stable/global-this' // polyfill for globalThis (used by pdf.js)
|
||||
import 'core-js/stable/promise/all-settled' // polyfill for Promise.allSettled (used by pdf.js)
|
||||
import 'core-js/stable/structured-clone' // polyfill for global.StructuredClone (used by pdf.js)
|
||||
import 'core-js/stable/array/at' // polyfill for Array.prototype.at (used by pdf.js)
|
||||
|
||||
import { createWorker } from '@/utils/worker'
|
||||
import * as PDFJS from 'pdfjs-dist/legacy/build/pdf.mjs'
|
||||
import type { DocumentInitParameters } from 'pdfjs-dist/types/src/display/api'
|
||||
|
||||
export { PDFJS }
|
||||
|
||||
createWorker(() => {
|
||||
PDFJS.GlobalWorkerOptions.workerPort = new Worker(
|
||||
new URL('pdfjs-dist/legacy/build/pdf.worker.mjs', import.meta.url) // NOTE: .mjs extension
|
||||
)
|
||||
})
|
||||
|
||||
export const imageResourcesPath = '/images/pdfjs-dist/'
|
||||
const cMapUrl = '/js/pdfjs-dist/cmaps/'
|
||||
const standardFontDataUrl = '/fonts/pdfjs-dist/'
|
||||
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
const disableFontFace = params.get('disable-font-face') === 'true'
|
||||
const disableStream = process.env.NODE_ENV !== 'test'
|
||||
|
||||
export const loadPdfDocumentFromUrl = (
|
||||
url: string,
|
||||
options: Partial<DocumentInitParameters> = {}
|
||||
) =>
|
||||
PDFJS.getDocument({
|
||||
url,
|
||||
cMapUrl,
|
||||
standardFontDataUrl,
|
||||
disableFontFace,
|
||||
disableAutoFetch: true, // only fetch the data needed for the displayed pages
|
||||
disableStream,
|
||||
isEvalSupported: false,
|
||||
enableXfa: false, // default is false (2021-10-12), but set explicitly to be sure
|
||||
...options,
|
||||
})
|
|
@ -140,14 +140,16 @@ export class GraphicsWidget extends WidgetType {
|
|||
}
|
||||
|
||||
async renderPDF(view: EditorView, canvas: HTMLCanvasElement, url: string) {
|
||||
const { PDFJS } = await this.importPDFJS()
|
||||
const { loadPdfDocumentFromUrl } = await import(
|
||||
'@/features/pdf-preview/util/pdf-js'
|
||||
)
|
||||
|
||||
// bail out if loading PDF.js took too long
|
||||
if (this.destroyed) {
|
||||
return
|
||||
}
|
||||
|
||||
const pdf = await PDFJS.getDocument({ url, isEvalSupported: false }).promise
|
||||
const pdf = await loadPdfDocumentFromUrl(url).promise
|
||||
const page = await pdf.getPage(1)
|
||||
|
||||
// bail out if loading the PDF took too long
|
||||
|
@ -162,16 +164,10 @@ export class GraphicsWidget extends WidgetType {
|
|||
canvas.style.width = width
|
||||
canvas.style.maxWidth = width
|
||||
page.render({
|
||||
canvasContext: canvas.getContext('2d'),
|
||||
canvasContext: canvas.getContext('2d')!,
|
||||
viewport,
|
||||
})
|
||||
this.height = viewport.height
|
||||
view.requestMeasure()
|
||||
}
|
||||
|
||||
async importPDFJS(): Promise<any> {
|
||||
return import('../../../../pdf-preview/util/pdf-js-versions').then(
|
||||
m => m.default
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue