From df6147bb4d7a5470e00a3bed504cb863df8df239 Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Sat, 14 Sep 2024 16:01:15 +0100 Subject: [PATCH] Convert PDF.js code to TypeScript GitOrigin-RevId: 840bc48816d78497131b927522b4f6f7940bb0c4 --- .../file-view/components/file-view-pdf.tsx | 13 +- .../pdf-preview/components/pdf-js-viewer.tsx | 36 ++---- ...-preview-pane.jsx => pdf-preview-pane.tsx} | 7 +- .../{pdf-viewer.jsx => pdf-viewer.tsx} | 0 .../hooks/use-presentation-mode.ts | 9 +- .../features/pdf-preview/util/highlights.js | 10 +- .../pdf-preview/util/pdf-caching-transport.js | 11 +- .../pdf-preview/util/pdf-js-versions.js | 38 ------ .../{pdf-js-wrapper.js => pdf-js-wrapper.ts} | 121 +++++++----------- .../js/features/pdf-preview/util/pdf-js.ts | 40 ++++++ .../visual/visual-widgets/graphics.ts | 14 +- 11 files changed, 135 insertions(+), 164 deletions(-) rename services/web/frontend/js/features/pdf-preview/components/{pdf-preview-pane.jsx => pdf-preview-pane.tsx} (92%) rename services/web/frontend/js/features/pdf-preview/components/{pdf-viewer.jsx => pdf-viewer.tsx} (100%) delete mode 100644 services/web/frontend/js/features/pdf-preview/util/pdf-js-versions.js rename services/web/frontend/js/features/pdf-preview/util/{pdf-js-wrapper.js => pdf-js-wrapper.ts} (64%) create mode 100644 services/web/frontend/js/features/pdf-preview/util/pdf-js.ts diff --git a/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx b/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx index 3efc61a219..5222f2db7b 100644 --- a/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx +++ b/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx @@ -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, }) } diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.tsx b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.tsx index d9813b9a56..0c417d3722 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.tsx +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.tsx @@ -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) { diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-preview-pane.jsx b/services/web/frontend/js/features/pdf-preview/components/pdf-preview-pane.tsx similarity index 92% rename from services/web/frontend/js/features/pdf-preview/components/pdf-preview-pane.jsx rename to services/web/frontend/js/features/pdf-preview/components/pdf-preview-pane.tsx index d0a3e0c3e2..bbbcaafe14 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-preview-pane.jsx +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-preview-pane.tsx @@ -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() diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.jsx b/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.tsx similarity index 100% rename from services/web/frontend/js/features/pdf-preview/components/pdf-viewer.jsx rename to services/web/frontend/js/features/pdf-preview/components/pdf-viewer.tsx diff --git a/services/web/frontend/js/features/pdf-preview/hooks/use-presentation-mode.ts b/services/web/frontend/js/features/pdf-preview/hooks/use-presentation-mode.ts index 85ec44b8b3..3b4a9be364 100644 --- a/services/web/frontend/js/features/pdf-preview/hooks/use-presentation-mode.ts +++ b/services/web/frontend/js/features/pdf-preview/hooks/use-presentation-mode.ts @@ -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) diff --git a/services/web/frontend/js/features/pdf-preview/util/highlights.js b/services/web/frontend/js/features/pdf-preview/util/highlights.js index 04655ee58b..a2da6b2621 100644 --- a/services/web/frontend/js/features/pdf-preview/util/highlights.js +++ b/services/web/frontend/js/features/pdf-preview/util/highlights.js @@ -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 } diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js index 4630b0f77a..5fb7e66f9a 100644 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js +++ b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js @@ -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 diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-js-versions.js b/services/web/frontend/js/features/pdf-preview/util/pdf-js-versions.js deleted file mode 100644 index 649ba2a993..0000000000 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-js-versions.js +++ /dev/null @@ -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() diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js b/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.ts similarity index 64% rename from services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js rename to services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.ts index d482a6b845..2aeea5a6f6 100644 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js +++ b/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.ts @@ -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 + 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((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, 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) } } diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-js.ts b/services/web/frontend/js/features/pdf-preview/util/pdf-js.ts new file mode 100644 index 0000000000..b2e8514d48 --- /dev/null +++ b/services/web/frontend/js/features/pdf-preview/util/pdf-js.ts @@ -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 = {} +) => + 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, + }) diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts index a4f2588516..2480f2235c 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts @@ -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 { - return import('../../../../pdf-preview/util/pdf-js-versions').then( - m => m.default - ) - } }