diff --git a/examples/node/domstubs.js b/examples/node/domstubs.js index fcd54c8eab98f..576d615152e30 100644 --- a/examples/node/domstubs.js +++ b/examples/node/domstubs.js @@ -46,6 +46,7 @@ function DOMElement(name) { this.childNodes = []; this.attributes = {}; this.textContent = ''; + this.parentNode = undefined; if (name === 'style') { this.sheet = { @@ -98,6 +99,7 @@ DOMElement.prototype = { var childNodes = this.childNodes; if (childNodes.indexOf(element) === -1) { childNodes.push(element); + element.parentNode = this; } }, @@ -106,6 +108,7 @@ DOMElement.prototype = { newNode.childNodes = this.childNodes; newNode.attributes = this.attributes; newNode.textContent = this.textContent; + newNode.parentNode = undefined; return newNode; }, @@ -124,6 +127,15 @@ DOMElement.prototype = { getSerializer: function DOMElement_getSerializer() { return new DOMElementSerializer(this); + }, + + remove: function DOMElement_remove() { + if (this.parentNode) { + this.parentNode.childNodes = this.parentNode.childNodes.filter( + node => node != this + ); + this.parentNode = undefined; + } } } @@ -244,6 +256,9 @@ Image.prototype = { exports.document = document; exports.Image = Image; +function Blob(blobParts, options) {} +exports.Blob = Blob; + var exported_symbols = Object.keys(exports); exports.setStubs = function(namespace) { diff --git a/examples/typescript/README.md b/examples/typescript/README.md new file mode 100644 index 0000000000000..7527c88a8d675 --- /dev/null +++ b/examples/typescript/README.md @@ -0,0 +1,18 @@ +## Overview + +Example to demonstrate PDF.js library usage with TypeScript. + +## Getting started + +Build project and install the example dependencies: + + $ cd pdf.js + $ npm install + $ gulp dist + $ cd examples/typescript + $ npm install + $ npm test + +## Type declaration file + +TypeScript type declarations are in `external/types/*.d.ts`. These are copied over to the dist/ directory by `gulp dist`. The copy in the `build/dist/` directory is used by these tests. Rerun `gulp dist` or manually copy the file into `build/dist/` after updating declaration files. diff --git a/examples/typescript/package.json b/examples/typescript/package.json new file mode 100644 index 0000000000000..143a51696c683 --- /dev/null +++ b/examples/typescript/package.json @@ -0,0 +1,23 @@ +{ + "name": "pdfjstypestest", + "version": "1.0.0", + "description": "command line tool for analyzing pdfs", + "main": "index.js", + "scripts": { + "test": "jasmine-ts \"src/**/*.spec.ts\"", + "build": "tsc", + "watch": "tsc --watch" + }, + "author": "", + "engines": { + "node": ">=8.0.0" + }, + "dependencies": { + "@types/jasmine": "^2.8.6", + "@types/node": "^8.10.0", + "jasmine-ts": "^0.2.1", + "pdfjs-dist": "../../build/dist", + "typescript": "^2.7.2" + }, + "license": "Apache-2.0" +} diff --git a/examples/typescript/src/jasmine_helper.ts b/examples/typescript/src/jasmine_helper.ts new file mode 100644 index 0000000000000..f90b32d55bb6c --- /dev/null +++ b/examples/typescript/src/jasmine_helper.ts @@ -0,0 +1,88 @@ +/* Copyright 2017 Mozilla Foundation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import "jasmine"; + +// Helper functions that make Jasmine tests more async/await friendly. + +function makeSafeFn(fn?: () => Promise | void) { + return async (done: DoneFn) => { + try { + fn && (await fn()); + done(); + } catch (err) { + done.fail(err); + } + }; +} + +export function expectFieldType(obj: object, field: string, type: string) { + expect(`${field}: ${typeof obj[field]}`).toBe(`${field}: ${type}`); +} + +type callback = () => Promise | void; + +export function test(msg: string, fn?: callback, timeout?: number) { + it(msg, makeSafeFn(fn), timeout); +} + +export let asyncTest = test; + +export function asyncBeforeAll(action: callback, timeout?: number) { + beforeAll(makeSafeFn(action), timeout); +} + +export function asyncAfterAll(action: callback, timeout?: number) { + afterAll(makeSafeFn(action), timeout); +} + +export function asyncBeforeEach(action: callback, timeout?: number) { + beforeEach(makeSafeFn(action), timeout); +} + +export function asyncAfterEach(action: callback, timeout?: number) { + afterEach(makeSafeFn(action), timeout); +} + + +// Utility functions to perform type verification for array types. + +export function expectArray(a: any[], len?: number) { + expect(a).toEqual(jasmine.any(Array)); + if(len) { + expect(a.length).toBe(len); + } +} + +export function expectNumberArray(a: number[], len?: number) { + expectArray(a, len); + expect(typeof a[0]).toBe('number'); +} + +export function expectTypedArray(a: Uint8Array) { + expect(a).toEqual(jasmine.any(Uint8Array)); +} + +export function expectTransform(m: number[]) { + expectNumberArray(m, 6); +} + +export function expectPoint(point: number[]) { + expectNumberArray(point, 2); +} + +export function expectRect(rect: number[]) { + expectNumberArray(rect, 4); +} diff --git a/examples/typescript/src/types.spec.ts b/examples/typescript/src/types.spec.ts new file mode 100644 index 0000000000000..2e1fbb0f4a78c --- /dev/null +++ b/examples/typescript/src/types.spec.ts @@ -0,0 +1,689 @@ +/* Copyright 2017 Mozilla Foundation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import * as fs from 'fs'; +import * as path from 'path'; +import { URL } from 'url'; +import * as pdfjs from 'pdfjs-dist'; +import 'jasmine'; +import { access } from 'fs'; +import { + test, + asyncAfterAll, + asyncAfterEach, + asyncBeforeAll, + asyncBeforeEach, + expectArray, + expectNumberArray, + expectPoint, + expectRect, + expectTransform, + expectTypedArray, + expectFieldType +} from './jasmine_helper'; +import { isArray } from 'util'; +import { PDFDocumentProxy, PageViewport } from 'pdfjs-dist'; +import { setStubs } from '../../node/domstubs.js'; +setStubs(global); + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + +// The purpose of this test is to dynamically verify some of the types the +// TypeScript type definition file external/types/index.d.ts. Therefore the +// specific values returned by API calls is less relevant, and we use `typeof` +// extensively to verify the dynamic types are what is expected from the static +// typing. + +function buildPathToPdf(name: string) { + return '../../test/pdfs/' + name; +} + +async function getPageFromDocument(filename: string) { + const params: pdfjs.DocumentInitParameters = { + url: buildPathToPdf(filename), + verbosity: pdfjs.VerbosityLevel.ERRORS + }; + let doc = await pdfjs.getDocument(params); + let page = await doc!.getPage(1); + return { doc: doc!, page }; +} + +describe('PDFDocumentProxy types', () => { + let doc: pdfjs.PDFDocumentProxy; + + asyncBeforeAll(async () => { + ({ doc } = await getPageFromDocument('basicapi.pdf')); + }); + + test('has numPages', () => { + expectFieldType(doc, 'numPages', 'number'); + }); + + test('get page', async () => { + let page1 = await doc.getPage(1); + expect(page1.pageNumber).toBe(1); + }); + + test('has loading task', () => { + expect(doc.loadingTask).toBeDefined(); + }); + + test('get pdf info', () => { + expectFieldType(doc.pdfInfo, 'fingerprint', 'string'); + expectFieldType(doc.pdfInfo, 'numPages', 'number'); + }); + + test('has fingerprint', () => { + expectFieldType(doc, 'fingerprint', 'string'); + }); + + test('get destinations', async () => { + // The point of the test is to verify these functions exist + let destinations = await doc.getDestinations(); + expect(typeof destinations).toBe('object'); + + let dest = (await doc.getDestination('chapter1'))!; + expectArray(dest); + + expect(await doc.getDestination('nonexistent')).toBeNull(); + }); + + test('get page labels', async () => { + let labels = await doc.getPageLabels(); + expect(labels).toBeNull(); + }); + + test('get page mode', async () => { + let mode = await doc.getPageMode(); + expect(typeof mode).toBe('string'); + }); + + test('get page attachments', async () => { + let attachments = await doc.getAttachments(); + expect(attachments).toBeNull(); + }); + + test('get JavaScript', async () => { + let js = await doc.getJavaScript(); + expect(js).toBeNull(); + }); + + test('get outline', async () => { + let outline = await doc.getOutline(); + let node = outline![0]; + expectFieldType(node, 'title', 'string'); + expectFieldType(node, 'bold', 'boolean'); + expectFieldType(node, 'italic', 'boolean'); + expectTypedArray(node.color); + expectArray(node.dest!); + expect(node.url).toBeNull(); + expectArray(node.items); + }); + + test('metadata', async () => { + let metadata = await doc.getMetadata(); + expectFieldType(metadata.info, 'PDFFormatVersion', 'string'); + expectFieldType(metadata.info, 'IsAcroFormPresent', 'boolean'); + expectFieldType(metadata.info, 'IsXFAPresent', 'boolean'); + expectFieldType(metadata.info, 'Title', 'string'); + expectFieldType(metadata.info, 'Author', 'string'); + expectFieldType(metadata.info, 'Subject', 'undefined'); + expectFieldType(metadata.info, 'Keywords', 'undefined'); + expectFieldType(metadata.info, 'Creator', 'string'); + expectFieldType(metadata.info, 'Producer', 'string'); + expectFieldType(metadata.info, 'CreationDate', 'string'); + expectFieldType(metadata.info, 'ModDate', 'string'); + + let dict = metadata.metadata!; + let all = dict.getAll(); + expect(typeof all['dc:title']).toBe('string'); + expect(typeof dict.get('dc:creator')).toBe('string'); + expect(typeof dict.has('nonexistent')).toBe('boolean'); + }); + + test('get data', async () => { + let data = await doc.getData(); + expectTypedArray(data); + }); + + test('get download info', async () => { + let info = await doc.getDownloadInfo(); + expectFieldType(info, 'length', 'number'); + }); + + test('get stats', async () => { + let stats = await doc.getStats(); + expectArray(stats.fontTypes); + expectArray(stats.streamTypes); + }); + + test('cleanup and destroy', () => { + expect(doc.cleanup).toBeDefined(); + expect(doc.destroy).toBeDefined(); + }); + + asyncAfterAll(async () => { + doc.cleanup(); + await doc.destroy(); + }); +}); + +describe('PDFPageProxy', () => { + let doc: pdfjs.PDFDocumentProxy; + let page: pdfjs.PDFPageProxy; + + asyncBeforeAll(async () => { + ({ doc, page } = await getPageFromDocument('basicapi.pdf')); + }); + + test('pageIndex', () => { + expectFieldType(page, 'pageIndex', 'number'); + }); + test('pageInfo', () => { + expect(page.pageInfo).toBeDefined(); + expectFieldType(page.pageInfo, 'rotate', 'number'); + expectFieldType(page.pageInfo, 'userUnit', 'number'); + expectFieldType(page.pageInfo, 'ref', 'object'); + expectFieldType(page.pageInfo.ref, 'num', 'number'); + expectFieldType(page.pageInfo.ref, 'gen', 'number'); + expectRect(page.pageInfo.view); + }); + test('cleanupAfterRender', () => { + expectFieldType(page, 'cleanupAfterRender', 'boolean'); + }); + test('pendingCleanup', () => { + expectFieldType(page, 'pendingCleanup', 'boolean'); + }); + test('destroyed', () => { + expectFieldType(page, 'destroyed', 'boolean'); + }); + test('intentStates', () => { + expectFieldType(page, 'intentStates', 'object'); + }); + test('pageNumber', () => { + expectFieldType(page, 'pageNumber', 'number'); + }); + test('rotate', () => { + expectFieldType(page, 'rotate', 'number'); + }); + test('ref', () => { + expect(page.ref).toBeDefined(); + expectFieldType(page.ref, 'gen', 'number'); + expectFieldType(page.ref, 'num', 'number'); + }); + test('userUnit', () => { + expectFieldType(page, 'userUnit', 'number'); + }); + test('view', () => { + expectRect(page.view); + }); + + describe('getViewport', () => { + let vp: PageViewport; + + beforeAll(() => { + vp = page.getViewport(1.0); + }); + + test('PageViewport fields', () => { + expectRect(vp.viewBox); + expectFieldType(vp, 'scale', 'number'); + expectFieldType(vp, 'rotation', 'number'); + expectFieldType(vp, 'offsetX', 'number'); + expectFieldType(vp, 'offsetY', 'number'); + expectFieldType(vp, 'width', 'number'); + expectFieldType(vp, 'height', 'number'); + expectFieldType(vp, 'fontScale', 'number'); + expectTransform(vp.transform); + }); + + test('clone', () => { + expect(vp.clone()).toEqual(vp); + expect(vp.clone({ scale: 1, rotation: 0 })).toEqual(vp); + }); + + test('convertToViewportPoint', () => { + expectPoint(vp.convertToViewportPoint(1, 1)); + }); + + test('convertToViewportRectangle', () => { + let r: pdfjs.Rect = [0, 0, 1, 1]; + expectRect(vp.convertToViewportRectangle(r)); + }); + + test('convertToPdfPoint', () => { + expectPoint(vp.convertToPdfPoint(1, 1)); + }); + }); + + // Running render() would require either running in a browser or adding a + // dependency on Node Canvas. Those tests are performed elsewhere, so we + // just do existence checking here. + test('render', () => { + expectFieldType(page, 'render', 'function'); + }); + + test('operator list', async () => { + let ops = await page.getOperatorList(); + expect(typeof ops.fnArray[0]).toBe('number'); + expect(ops.argsArray.length).toBeGreaterThanOrEqual(0); + expect(ops.argsArray[1].length).toBeGreaterThanOrEqual(0); + }); + + test('stream text content', () => { + let stream = page.streamTextContent(); + expect(stream).toBeDefined(); + expect(typeof stream).toBe('object'); + }); + + test('get text content', async () => { + let text = await page.getTextContent(); + expect(text).toBeDefined(); + let item = text.items[0]; + expectFieldType(item, 'str', 'string'); + expectFieldType(item, 'dir', 'string'); + expectFieldType(item, 'fontName', 'string'); + expectFieldType(item, 'height', 'number'); + expectFieldType(item, 'width', 'number'); + expectTransform(item.transform); + + let styles = text.styles[item.fontName]; + expectFieldType(styles, 'ascent', 'number'); + expectFieldType(styles, 'descent', 'number'); + expectFieldType(styles, 'fontFamily', 'string'); + }); + + asyncAfterAll(async () => { + if (doc) { + await doc.destroy(); + } + }); +}); + +describe('PDFPageProxy annotation types', () => { + async function getAnnotationsFrom(filename: string) { + let { doc, page } = await getPageFromDocument(filename); + let annotations = await page.getAnnotations(); + return { doc, annotations }; + } + + test('exist', async () => { + let { doc, annotations } = await getAnnotationsFrom('annotation-line.pdf'); + expect(annotations).toBeDefined(); + doc.destroy(); + }); + + function checkBaseAnnotation(annot: pdfjs.Annotation) { + expectFieldType(annot, 'annotationType', 'number'); + expectFieldType(annot, 'annotationFlags', 'number'); + expectFieldType(annot, 'hasAppearance', 'boolean'); + expectFieldType(annot, 'id', 'string'); + expectTypedArray(annot.color!); + expectFieldType(annot, 'subtype', 'string'); + expectRect(annot.rect); + expectFieldType(annot.borderStyle, 'horizontalCornerRadius', 'number'); + expectFieldType(annot.borderStyle, 'verticalCornerRadius', 'number'); + expectFieldType(annot.borderStyle, 'width', 'number'); + expectFieldType(annot.borderStyle, 'style', 'number'); + expectNumberArray(annot.borderStyle.dashArray); + } + + function checkWidgetAnnotation(widget: pdfjs.types.WidgetAnnotation) { + checkBaseAnnotation(widget); + expectFieldType(widget, 'fieldName', 'string'); + expectFieldType(widget, 'fieldType', 'string'); + expectFieldType(widget, 'fieldFlags', 'number'); + expectFieldType(widget, 'alternativeText', 'string'); + expectFieldType(widget, 'defaultAppearance', 'string'); + expectFieldType(widget, 'readOnly', 'boolean'); + } + + test('text widget', async () => { + let { doc, annotations } = await getAnnotationsFrom( + 'annotation-text-widget.pdf' + ); + annotations.forEach(annotation => { + let widget = annotation as pdfjs.types.TextWidgetAnnotation; + checkWidgetAnnotation(widget); + expectFieldType(widget, 'fieldValue', 'string'); + expectFieldType(widget, 'textAlignment', 'number'); + expectFieldType(widget, 'multiLine', 'boolean'); + if (widget.maxLen !== null) { + expectFieldType(widget, 'maxLen', 'number'); + } + expectFieldType(widget, 'comb', 'boolean'); + }); + doc.destroy(); + }); + + // TODO: Test other annotation types. +}); + +describe('PDFPageProxy PDFObjects type', () => { + function checkPDFObjects(pdfObjs: pdfjs.types.PDFObjects) { + expect(typeof pdfObjs).toBe('object'); + let objs = pdfObjs.objs; + let keys = Object.keys(objs); + // The PDF file ad page loaded should be chosen to have a non-empty objs or + // commonObjs field on PDFPageProxy. + expect(keys.length).toBeGreaterThan(0); + keys.forEach(key => { + expect(typeof key).toBe('string'); + expect(typeof objs[key]).toBe('object'); + }); + } + + test('commonObjs', async () => { + // File specifically chosen to have non-empty page.commonObjs + let { doc, page } = await getPageFromDocument( + 'ShowText-ShadingPattern.pdf' + ); + // Getting the operator list populates page.objs and page.commonObjs + let ops = await page.getOperatorList(); + checkPDFObjects(page.commonObjs); + }); +}); + +describe('SVG types', () => { + let doc: pdfjs.PDFDocumentProxy; + let page: pdfjs.PDFPageProxy; + let svg: pdfjs.SVGGraphics; + + asyncBeforeAll(async () => { + ({ doc, page } = await getPageFromDocument('tracemonkey.pdf')); + svg = new pdfjs.SVGGraphics(page.commonObjs, page.objs); + }); + + test('', async () => { + let ops = await page.getOperatorList(); + let svgElement = await svg.getSVG(ops, page.getViewport(1.0)); + // Hack to get around domstubs.js not being written in TypeScript. + let element = svgElement as any; + expect(element.nodeName).toBe('svg:svg'); + }); +}); + +describe('other pdf.js exports', () => { + test('has expected types for variables', () => { + expectFieldType(pdfjs, 'version', 'string'); + expectFieldType(pdfjs, 'build', 'string'); + }); + + test('has expected types for function arguments and return values', () => { + let o = {}; + expect(typeof pdfjs.shadow(o, 'key', {})).toBe('object'); + expect(typeof pdfjs.createBlob('data', 'text/plain')).toBe('object'); + expect(typeof pdfjs.createObjectURL('', 'text/plain')).toBe('string'); + expect(typeof pdfjs.removeNullCharacters('abc')).toBe('string'); + expect(typeof pdfjs.getFilenameFromUrl('file://foo.pdf')).toBe('string'); + }); + + test('PasswordResponses', () => { + expect(pdfjs.PasswordResponses.NEED_PASSWORD).toBeDefined(); + expect(pdfjs.PasswordResponses.INCORRECT_PASSWORD).toBeDefined(); + }); + + test('InvalidPDFException', () => { + const ex = new pdfjs.InvalidPDFException('message'); + expect(ex).toEqual(jasmine.any(Error)); + expect(ex.message).toBe('message'); + expect(ex.name).toBe('InvalidPDFException'); + }); + + test('MissingPDFException', () => { + const ex = new pdfjs.MissingPDFException('message'); + expect(ex).toEqual(jasmine.any(Error)); + expect(ex.message).toBe('message'); + expect(ex.name).toBe('MissingPDFException'); + }); + + test('UnexpectedResponseException', () => { + const ex = new pdfjs.UnexpectedResponseException('message', 400); + expect(ex).toEqual(jasmine.any(Error)); + expect(ex.message).toBe('message'); + expect(ex.status).toBe(400); + expect(ex.name).toBe('UnexpectedResponseException'); + }); + + test('RenderingCancelledException', () => { + const ex = new pdfjs.RenderingCancelledException('message', 'type'); + expect(ex).toEqual(jasmine.any(Error)); + expect(ex.message).toBe('message'); + expect(ex.type).toBe('type'); + }); + + describe('Util functions', () => { + test('Util', () => { + expect(pdfjs.Util).toBeDefined(); + }); + + test('makeCssRgb', () => { + expect(pdfjs.Util.makeCssRgb(0, 0, 0)).toMatch(/^rgb\(.*\)$/); + }); + + let m1 = [1, 1, 1, 1, 1, 1]; + let m2 = [2, 2, 2, 2, 2, 2]; + + test('transform', () => { + expectTransform(pdfjs.Util.transform(m1, m2)); + }); + + let pt: pdfjs.Point = [0.5, 0.7]; + test('applyTransform', () => { + expectPoint(pdfjs.Util.applyTransform(pt, m1)); + }); + test('applyInverseTransform', () => { + expectPoint(pdfjs.Util.applyInverseTransform(pt, m1)); + }); + + let r: pdfjs.Rect = [0, 0, 1, 1]; + test('getAxialAlignedBoundingBox', () => { + expectRect(pdfjs.Util.getAxialAlignedBoundingBox(r, m1)); + }); + + test('inverseTransform', () => { + expectTransform(pdfjs.Util.inverseTransform(m1)); + }); + + test('singularValueDecompose2dScale', () => { + expectArray(pdfjs.Util.singularValueDecompose2dScale(m1), 2); + }); + + function expectPoint3d(point: number[]) { + expectArray(point, 3); + } + + let m3d = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let p3d: pdfjs.types.Point3d = [2, 2, 2]; + test('apply3dTransform', () => { + expectPoint3d(pdfjs.Util.apply3dTransform(m3d /*? $[0]*/, p3d)); + }); + + test('normalizeRect', () => { + expectRect(pdfjs.Util.normalizeRect(r)); + }); + + describe('intersect', () => { + test('should return a Rect if input rects intersect', () => { + let r1: pdfjs.Rect = [0, 0, 5, 5]; + let r2: pdfjs.Rect = [1, 1, 2, 2]; + + let intersection = pdfjs.Util.intersect(r1, r2); + expectRect(intersection as number[]); + }); + test('should be false if the input rects do not intersect', () => { + let r1: pdfjs.Rect = [0, 0, 0, 0]; + let r2: pdfjs.Rect = [1, 1, 1, 1]; + expect(pdfjs.Util.intersect(r1, r2)).toBe(false); + }); + }); + + test('toRoman', () => { + expect(typeof pdfjs.Util.toRoman(1024, false)).toBe('string'); + }); + + test('appendToArray', () => { + let arr = [0]; + pdfjs.Util.appendToArray(arr, [1]); + expect(arr).toEqual([0, 1]); + }); + + test('prependToArray', () => { + let arr = [0]; + pdfjs.Util.prependToArray(arr, [1]); + expect(arr).toEqual([1, 0]); + }); + + test('extendObj', () => { + let o1 = {}; + let o2 = { foo: 'bar' }; + pdfjs.Util.extendObj(o1, o2); + expect(o1).toEqual(o2); + }); + }); // Util + + test('createPromiseCapability', () => { + let capability = pdfjs.createPromiseCapability(); + expect(capability.promise).toEqual(jasmine.any(Promise)); + expect(capability.resolve).toBeDefined(); + expect(capability.reject).toBeDefined(); + }); + + test('OPS', () => { + expect(pdfjs.OPS.dependency).toBeDefined(); + expect(pdfjs.OPS.setLineWidth).toBeDefined(); + expect(pdfjs.OPS.setLineCap).toBeDefined(); + expect(pdfjs.OPS.setLineJoin).toBeDefined(); + expect(pdfjs.OPS.setMiterLimit).toBeDefined(); + expect(pdfjs.OPS.setDash).toBeDefined(); + expect(pdfjs.OPS.setRenderingIntent).toBeDefined(); + expect(pdfjs.OPS.setFlatness).toBeDefined(); + expect(pdfjs.OPS.setGState).toBeDefined(); + expect(pdfjs.OPS.save).toBeDefined(); + expect(pdfjs.OPS.restore).toBeDefined(); + expect(pdfjs.OPS.transform).toBeDefined(); + expect(pdfjs.OPS.moveTo).toBeDefined(); + expect(pdfjs.OPS.lineTo).toBeDefined(); + expect(pdfjs.OPS.curveTo).toBeDefined(); + expect(pdfjs.OPS.curveTo2).toBeDefined(); + expect(pdfjs.OPS.curveTo3).toBeDefined(); + expect(pdfjs.OPS.closePath).toBeDefined(); + expect(pdfjs.OPS.rectangle).toBeDefined(); + expect(pdfjs.OPS.stroke).toBeDefined(); + expect(pdfjs.OPS.closeStroke).toBeDefined(); + expect(pdfjs.OPS.fill).toBeDefined(); + expect(pdfjs.OPS.eoFill).toBeDefined(); + expect(pdfjs.OPS.fillStroke).toBeDefined(); + expect(pdfjs.OPS.eoFillStroke).toBeDefined(); + expect(pdfjs.OPS.closeFillStroke).toBeDefined(); + expect(pdfjs.OPS.closeEOFillStroke).toBeDefined(); + expect(pdfjs.OPS.endPath).toBeDefined(); + expect(pdfjs.OPS.clip).toBeDefined(); + expect(pdfjs.OPS.eoClip).toBeDefined(); + expect(pdfjs.OPS.beginText).toBeDefined(); + expect(pdfjs.OPS.endText).toBeDefined(); + expect(pdfjs.OPS.setCharSpacing).toBeDefined(); + expect(pdfjs.OPS.setWordSpacing).toBeDefined(); + expect(pdfjs.OPS.setHScale).toBeDefined(); + expect(pdfjs.OPS.setLeading).toBeDefined(); + expect(pdfjs.OPS.setFont).toBeDefined(); + expect(pdfjs.OPS.setTextRenderingMode).toBeDefined(); + expect(pdfjs.OPS.setTextRise).toBeDefined(); + expect(pdfjs.OPS.moveText).toBeDefined(); + expect(pdfjs.OPS.setLeadingMoveText).toBeDefined(); + expect(pdfjs.OPS.setTextMatrix).toBeDefined(); + expect(pdfjs.OPS.nextLine).toBeDefined(); + expect(pdfjs.OPS.showText).toBeDefined(); + expect(pdfjs.OPS.showSpacedText).toBeDefined(); + expect(pdfjs.OPS.nextLineShowText).toBeDefined(); + expect(pdfjs.OPS.nextLineSetSpacingShowText).toBeDefined(); + expect(pdfjs.OPS.setCharWidth).toBeDefined(); + expect(pdfjs.OPS.setCharWidthAndBounds).toBeDefined(); + expect(pdfjs.OPS.setStrokeColorSpace).toBeDefined(); + expect(pdfjs.OPS.setFillColorSpace).toBeDefined(); + expect(pdfjs.OPS.setStrokeColor).toBeDefined(); + expect(pdfjs.OPS.setStrokeColorN).toBeDefined(); + expect(pdfjs.OPS.setFillColor).toBeDefined(); + expect(pdfjs.OPS.setFillColorN).toBeDefined(); + expect(pdfjs.OPS.setStrokeGray).toBeDefined(); + expect(pdfjs.OPS.setFillGray).toBeDefined(); + expect(pdfjs.OPS.setStrokeRGBColor).toBeDefined(); + expect(pdfjs.OPS.setFillRGBColor).toBeDefined(); + expect(pdfjs.OPS.setStrokeCMYKColor).toBeDefined(); + expect(pdfjs.OPS.setFillCMYKColor).toBeDefined(); + expect(pdfjs.OPS.shadingFill).toBeDefined(); + expect(pdfjs.OPS.beginInlineImage).toBeDefined(); + expect(pdfjs.OPS.beginImageData).toBeDefined(); + expect(pdfjs.OPS.endInlineImage).toBeDefined(); + expect(pdfjs.OPS.paintXObject).toBeDefined(); + expect(pdfjs.OPS.markPoint).toBeDefined(); + expect(pdfjs.OPS.markPointProps).toBeDefined(); + expect(pdfjs.OPS.beginMarkedContent).toBeDefined(); + expect(pdfjs.OPS.beginMarkedContentProps).toBeDefined(); + expect(pdfjs.OPS.endMarkedContent).toBeDefined(); + expect(pdfjs.OPS.beginCompat).toBeDefined(); + expect(pdfjs.OPS.endCompat).toBeDefined(); + expect(pdfjs.OPS.paintFormXObjectBegin).toBeDefined(); + expect(pdfjs.OPS.paintFormXObjectEnd).toBeDefined(); + expect(pdfjs.OPS.beginGroup).toBeDefined(); + expect(pdfjs.OPS.endGroup).toBeDefined(); + expect(pdfjs.OPS.beginAnnotations).toBeDefined(); + expect(pdfjs.OPS.endAnnotations).toBeDefined(); + expect(pdfjs.OPS.beginAnnotation).toBeDefined(); + expect(pdfjs.OPS.endAnnotation).toBeDefined(); + expect(pdfjs.OPS.paintJpegXObject).toBeDefined(); + expect(pdfjs.OPS.paintImageMaskXObject).toBeDefined(); + expect(pdfjs.OPS.paintImageMaskXObjectGroup).toBeDefined(); + expect(pdfjs.OPS.paintImageXObject).toBeDefined(); + expect(pdfjs.OPS.paintInlineImageXObject).toBeDefined(); + expect(pdfjs.OPS.paintInlineImageXObjectGroup).toBeDefined(); + expect(pdfjs.OPS.paintImageXObjectRepeat).toBeDefined(); + expect(pdfjs.OPS.paintImageMaskXObjectRepeat).toBeDefined(); + expect(pdfjs.OPS.paintSolidColorImageMask).toBeDefined(); + expect(pdfjs.OPS.constructPath).toBeDefined(); + }); + + test('VerbosityLevel', () => { + expect(pdfjs.VerbosityLevel.ERRORS).toBeDefined(); + expect(pdfjs.VerbosityLevel.INFOS).toBeDefined(); + expect(pdfjs.VerbosityLevel.WARNINGS).toBeDefined(); + }); + + test('UNSUPPORTED_FEATURES', () => { + expect(pdfjs.UNSUPPORTED_FEATURES.font).toBeDefined(); + expect(pdfjs.UNSUPPORTED_FEATURES.forms).toBeDefined(); + expect(pdfjs.UNSUPPORTED_FEATURES.javaScript).toBeDefined(); + expect(pdfjs.UNSUPPORTED_FEATURES.shadingPattern).toBeDefined(); + expect(pdfjs.UNSUPPORTED_FEATURES.smask).toBeDefined(); + expect(pdfjs.UNSUPPORTED_FEATURES.unknown).toBeDefined(); + }); + + test('LinkTarget', () => { + expectFieldType(pdfjs.LinkTarget, 'BLANK', 'number'); + expectFieldType(pdfjs.LinkTarget, 'NONE', 'number'); + expectFieldType(pdfjs.LinkTarget, 'PARENT', 'number'); + expectFieldType(pdfjs.LinkTarget, 'SELF', 'number'); + expectFieldType(pdfjs.LinkTarget, 'TOP', 'number'); + }); + + test('GlobalWorkerOptions', () => { + expect(pdfjs.GlobalWorkerOptions.workerPort).toBeNull(); + expectFieldType(pdfjs.GlobalWorkerOptions, 'workerSrc', 'string'); + }); + + test('apiCompatibilityParams', () => { + expect(pdfjs.apiCompatibilityParams).toBeDefined(); + }); +}); diff --git a/examples/typescript/tsconfig.json b/examples/typescript/tsconfig.json new file mode 100644 index 0000000000000..9a16dc9a16a8f --- /dev/null +++ b/examples/typescript/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "outDir": "build", + "module": "commonjs", + "target": "es6", + "lib": [ + "es6" + ], + "sourceMap": true, + "allowJs": true, + "moduleResolution": "node", + // "rootDir": "src", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true, + // "noUnusedLocals": true, + "strict": true + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "build" + ] +} \ No newline at end of file diff --git a/external/types/core.d.ts b/external/types/core.d.ts new file mode 100644 index 0000000000000..36b59f3113892 --- /dev/null +++ b/external/types/core.d.ts @@ -0,0 +1,231 @@ +/* Copyright 2017 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TypeScript type definitions for PDFJS + +// The _pdfjs namespace is a convenient place for making type +// declarations. The actual exports are at the end of the file, +// and pick symbols from this namespace to export in a shape that +// resembles the API for PDFJS. +declare namespace _pdfjs { + // + // Convenience types + // + + /** + * 6 element transform matrix: [a, b, c, d, e, f] + * The transformation between two coordinate systems can be + * represented by a 3x3 transformation matrix written as follows: + * + * | a b 0 | + * | c d 0 | + * | e f 1 | + * + * The transformation matrix has only six elements that can be changed, + * so it is usually represented by a six element array [a, b, c, d, e, f]. + * + * Coordinate transformations are expressed as matrix multiplications: + * + * | a b 0 | + * [x', y', 1] = [x, y, 1] x | c d 0 | + * | e f 1 | + */ + type Transform = number[]; + + /** + * A generic 3d matrix transform M on a 3-vector [X, Y, Z]: + * + * | a b c | | X | + * | d e f | x | Y | + * | g h i | | Z | + * + * M is assumed to be serialized as a 9 element array [a,b,c,d,e,f,g,h,i], + */ + type Transform3d = number[]; + + // 2 dimensional point [x, y] + type Point = [number, number]; + + // 2 dimensional point object + interface Vertex { + x: number; + y: number; + } + + // 3 dimensional point [x, y, z] + type Point3d = [number, number, number]; + + // Rectangle with 4 elements: [x1, y1, x2, y2] + type Rect = [number, number, number, number]; + + type PageIndex = number; + type PageLabels = string; + + // + // src/core/obj.js + // + interface FileSpec { + filename: string; + content: Uint8Array; + } + + interface Attachments { + [file: string]: FileSpec; + } + + type DestinationTarget = any[]; + + type Destination = { + [destination: string]: any[]; + }; + + // + // src/core/primitives.js + // + interface Ref { + num: number; + gen: number; + } + + // Interning names + interface Name { + name: string; + } + + interface StringMap { + [key: string]: string; + } + + // + // src/core/annotation.js + // + interface Annotation { + annotationFlags: AnnotationFlag; + annotationType: AnnotationType; + borderStyle: AnnotationBorderStyle; + color: Color | null; + hasAppearance: boolean; + id: string; + rect: Rect; + subtype: AnnotationSubtype | null; + + // For popup annotations + hasPopup?: boolean; + title?: string; + contents?: string; + } + + /** + * Contains all data regarding an annotation's border style. + */ + class AnnotationBorderStyle { + width: number; + style: AnnotationBorderStyleType; + dashArray: number[]; + horizontalCornerRadius: number; + verticalCornerRadius: number; + } + + interface WidgetAnnotation extends Annotation { + annotationType: AnnotationType.WIDGET; + fieldName: string; + fieldType: string; + fieldValue: string | string[] | null; + alternativeText: string; + defaultAppearance: string; + fieldFlags: number; + readOnly: boolean; + } + interface TextWidgetAnnotation extends WidgetAnnotation { + fieldValue: string; + textAlignment: number | null; + maxLen: number | null; + multiLine: boolean; + comb: boolean; + } + interface ButtonWidgetAnnotation extends WidgetAnnotation { + checkBox: boolean; + radioButton: boolean; + pushButton: boolean; + fieldValue: string | null; + buttonValue?: string | null; + } + interface ChoiceWidgetAnnotation extends WidgetAnnotation { + options: ChoiceOption[]; + fieldValue: string[]; + combo: boolean; + multiSelect: boolean; + } + interface ChoiceOption { + exportValue: string; + displayValue: string; + } + interface TextAnnotation extends Annotation { + annotationType: AnnotationType.TEXT; + name: string; + } + interface LinkAnnotation extends Annotation { + annotationType: AnnotationType.LINK; + } + interface PopupAnnotation extends Annotation { + annotationType: AnnotationType.POPUP; + parentType: string | null; + parentId: string; + title: string; + contents: string; + color: Color | null; + } + interface LineAnnotation extends Annotation { + annotationType: AnnotationType.LINE; + lineCoordinates: Rect; + } + interface SquareAnnotation extends Annotation { + annotationType: AnnotationType.SQUARE; + } + interface CircleAnnotation extends Annotation { + annotationType: AnnotationType.CIRCLE; + } + interface PolylineAnnotation extends Annotation { + annotationType: AnnotationType.POLYLINE; + vertices: Vertex[]; + } + interface PolygonAnnotation extends Annotation { + annotationType: AnnotationType.POLYGON; + vertices: Vertex[]; + } + interface InkAnnotation extends Annotation { + annotationType: AnnotationType.INK; + inkLists: Vertex[][]; + } + interface HighlightAnnotation extends Annotation { + annotationType: AnnotationType.HIGHLIGHT; + } + interface UnderlineAnnotation extends Annotation { + annotationType: AnnotationType.UNDERLINE; + } + interface SquigglyAnnotation extends Annotation { + annotationType: AnnotationType.SQUIGGLY; + } + interface StrikeOutAnnotation extends Annotation { + annotationType: AnnotationType.STRIKEOUT; + } + interface StampAnnotation extends Annotation { + annotationType: AnnotationType.STAMP; + } + interface FileAttachmentAnnotation extends Annotation { + annotationType: AnnotationType.FILEATTACHMENT; + file: FileSpec; + } +} diff --git a/external/types/display.d.ts b/external/types/display.d.ts new file mode 100644 index 0000000000000..c3bffdabd3528 --- /dev/null +++ b/external/types/display.d.ts @@ -0,0 +1,1049 @@ +/* Copyright 2017 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +declare namespace _pdfjs { + // + // src/display/api.js + // + const version: string; + const build: string; + type Chunk = Uint8Array; + type RangeListener = (begin: number, chunk: Chunk) => void; + type ProgressListener = (loaded: number) => void; + type ProgressiveReadListener = (chunk: Chunk) => void; + + // BUG: LoopbackPort defines terminate(), + // but MessagePort defines stop() ? + interface LoopbackPort extends MessagePort {} + let LoopbackPort: new (defer: boolean) => LoopbackPort; + + /** + * Abstract class to support range requests file loading. + * @class + * @alias PDFDataRangeTransport + * @param {number} length + * @param {Uint8Array} initialData + */ + class PDFDataRangeTransport { + length: number; + initialData: Chunk; + + constructor(length: number, initialData: Chunk); + addRangeListener(listener: RangeListener): void; + addProgressListener(listener: ProgressListener): void; + addProgressiveReadListener(listener: ProgressiveReadListener): void; + onDataRange(begin: number, chunk: Chunk): void; + onDataProgress(loaded: number): void; + onDataProgressiveRead(chunk: Chunk): void; + transportReady(): void; + requestDataRange(begin: number, end: number): void; + abort(): void; + } + + /** + * @typedef {Object} PDFWorkerParameters + * @property {string} name - (optional) The name of the worker. + * @property {Object} port - (optional) The `workerPort`. + * @property {boolean} postMessageTransfers - (optional) Enables transfer usage + * in postMessage for ArrayBuffers. The default value is `true`. + * @property {number} verbosity - (optional) Controls the logging level; the + * constants from {VerbosityLevel} should be used. + */ + interface PDFWorkerParameters { + name?: string; + port?: MessagePort; + postMessageTransfers?: boolean; + verbosity?: VerbosityLevel; + } + + /** + * PDF.js web worker abstraction, it controls instantiation of PDF documents and + * WorkerTransport for them. If creation of a web worker is not possible, + * a "fake" worker will be used instead. + * @class + */ + class PDFWorker { + constructor(params?: PDFWorkerParameters); + name: string; + destroyed: boolean; + postMessageTransfers: boolean; + promise: Promise; + port: MessagePort; + messageHandler: MessageHandler; + destroy(): void; + fromPort(params: PDFWorkerParameters): PDFWorker; + } + + interface DownloadInfo { + length: number; + } + + /** + * Proxy to a PDFDocument in the worker thread. Also, contains commonly used + * properties that can be read synchronously. + * @class + * @alias PDFDocumentProxy + */ + interface PDFDocumentProxy { + loadingTask: PDFDocumentLoadingTask; + pdfInfo: { + encrypted?: boolean; + fingerprint: string; + numPages: number; + }; + + /** + * @return {number} Total number of pages the PDF contains. + */ + numPages: number; + + /** + * @return {string} A unique ID to identify a PDF. Not guaranteed to be + * unique. + */ + fingerprint: string; + + /** + * @param {number} pageNumber The page number to get. The first page is 1. + * @return {Promise} A promise that is resolved with a {@link PDFPageProxy} + * object. + */ + getPage(pageNumber: number): Promise; + + /** + * @param {{num: number, gen: number}} ref The page reference. Must have + * the 'num' and 'gen' properties. + * @return {Promise} A promise that is resolved with the page index that is + * associated with the reference. + */ + getPageIndex(ref: Ref): Promise; + + /** + * @return {Promise} A promise that is resolved with a lookup table for + * mapping named destinations to reference numbers. + * + * This can be slow for large documents: use getDestination instead + */ + getDestinations(): Promise; + + /** + * @param {string} id The named destination to get. + * @return {Promise} A promise that is resolved with all information + * of the given named destination. + */ + getDestination(id: string): Promise; + + /** + * @return {Promise} A promise that is resolved with: + * an Array containing the pageLabels that correspond to the pageIndexes, + * or `null` when no pageLabels are present in the PDF file. + */ + getPageLabels(): Promise; + + /** + * @return {Promise} A promise that is resolved with a {string} containing + * the PageMode name. + */ + getPageMode(): Promise; + + /** + * @return {Promise} A promise that is resolved with a lookup table for + * mapping named attachments to their content. + */ + getAttachments(): Promise; + + /** + * @return {Promise} A promise that is resolved with an {Array} of all the + * JavaScript strings in the name tree, or `null` if no JavaScript exists. + */ + getJavaScript(): Promise; + + /** + * @return {Promise} A promise that is resolved with an {Array} that is a + * tree outline (if it has one) of the PDF. The tree is in the format of: + * [ + * { + * title: string, + * bold: boolean, + * italic: boolean, + * color: rgb Uint8Array, + * dest: dest obj, + * url: string, + * items: array of more items like this + * }, + * ... + * ]. + */ + getOutline(): Promise; + + /** + * @return {Promise} A promise that is resolved with an {Object} that has + * info and metadata properties. Info is an {Object} filled with anything + * available in the information dictionary and similarly metadata is a + * {Metadata} object with information from the metadata section of the PDF. + */ + getMetadata(): Promise; + + /** + * @return {Promise} A promise that is resolved with a TypedArray that has + * the raw data from the PDF. + */ + getData(): Promise; + + /** + * @return {Promise} A promise that is resolved when the document's data + * is loaded. It is resolved with an {Object} that contains the length + * property that indicates size of the PDF data in bytes. + */ + getDownloadInfo(): Promise; + + /** + * @return {Promise} A promise this is resolved with current stats about + * document structures (see {@link PDFDocumentStats}). + */ + getStats(): Promise; + + /** + * Cleans up resources allocated by the document, e.g. created @font-face. + */ + cleanup(): void; + + /** + * Destroys current document instance and terminates worker. + */ + destroy(): Promise; + } + + interface Outline { + title: string; + bold: boolean; + italic: boolean; + color: Color /* rgb */; + dest: Array | null; + unsafeUrl?: string; + url: string | null; + items: Outline[]; + } + + interface MetadataInfo { + PDFFormatVersion?: string; + IsAcroFormPresent?: boolean; + IsXFAPresent?: boolean; + Title?: string; + Author?: string; + Subject?: string; + Keywords?: string; + Creator?: string; + Producer?: string; + CreationDate?: string; + ModDate?: string; + Trapped?: Name; + + // typing for other keys in case this is not a complete list, and for + // forwards compatibility + [key: string]: any; + } + + interface MetadataProxy { + info: MetadataInfo; + metadata: Metadata | null; + } + + /** + * @typedef {Object} PDFDocumentStats + * @property {Array} streamTypes - Used stream types in the document (an item + * is set to true if specific stream ID was used in the document). + * @property {Array} fontTypes - Used font type in the document (an item is set + * to true if specific font ID was used in the document). + */ + interface PDFDocumentStats { + streamTypes: StreamType[]; + fontTypes: FontType[]; + } + + interface PageInfo { + /** + * @return {number} The number of degrees the page is rotated clockwise. + */ + rotate: number; + + /** + * @return {Object} The reference that points to this page. It has 'num' and + * 'gen' properties. + */ + ref: Ref; + + /** + * @return {number} The default size of units in 1/72nds of an inch. + */ + userUnit: number; + + /** + * @return {Array} An array of the visible portion of the PDF page in the + * user space units - [x1, y1, x2, y2]. + */ + view: Rect; + } + + interface OperatorList { + fnArray: OPS[]; + argsArray: any[][]; + lastChunk: boolean; + } + + interface IntentState { + receivingOperatorList: boolean; + displayReadyCapability: PromiseCapability; + operatorList: OperatorList; + // Internal use only + // renderTasks: RenderTask[]; + } + + interface IntentStates { + [intent: string]: IntentState; + } + + /** + * Proxy to a PDFPage in the worker thread. + * @class + * @alias PDFPageProxy + */ + interface PDFPageProxy { + pageIndex: PageIndex; + pageInfo: PageInfo; + commonObjs: PDFObjects; + objs: PDFObjects; + cleanupAfterRender: boolean; + pendingCleanup: boolean; + intentStates: IntentStates; + destroyed: boolean; + + /** + * @return {number} Page number of the page. First page is 1. + */ + pageNumber: number; + + /** + * @return {number} The number of degrees the page is rotated clockwise. + */ + rotate: number; + /** + * @return {Object} The reference that points to this page. It has 'num' and + * 'gen' properties. + */ + ref: Ref; + + /** + * @return {number} The default size of units in 1/72nds of an inch. + */ + userUnit: number; + + /** + * @return {Array} An array of the visible portion of the PDF page in the + * user space units - [x1, y1, x2, y2]. + */ + view: Rect; // Probably define a custom type + + /** + * The size of the current page, converted from PDF units to inches. + * @return {Object} An Object containing the properties: {number} `width` + * and {number} `height`, given in inches. + */ + pageSizeInches: { width: number; height: number }; + + /** + * @param {number} scale The desired scale of the viewport. + * @param {number} rotate Degrees to rotate the viewport. If omitted this + * defaults to the page rotation. + * @param {boolean} dontFlip (optional) If true, axis Y will not be flipped. + * @return {PageViewport} Contains 'width' and 'height' properties + * along with transforms required for rendering. + */ + getViewport(args: { + scale: number; + rotate?: number; + dontFlip?: boolean; + }): PageViewport; + + /** + * @param {GetAnnotationsParameters} params - Annotation parameters. + * @return {Promise} A promise that is resolved with an {Array} of the + * annotation objects. + */ + getAnnotations(params?: GetAnnotationsParameters): Promise; + + /** + * Begins the process of rendering a page to the desired context. + * @param {RenderParameters} params Page render parameters. + * @return {RenderTask} An object that contains the promise, which + * is resolved when the page finishes rendering. + */ + render(params: RenderParameters): RenderTask; + + /** + * @return {Promise} A promise resolved with an {@link PDFOperatorList} + * object that represents page's operator list. + */ + getOperatorList(): Promise; + + /** + * @param {getTextContentParameters} params - getTextContent parameters. + * @return {ReadableStream} ReadableStream to read textContent chunks. + */ + streamTextContent(params?: getTextContentParameters): ReadableStream; + + /** + * @param {getTextContentParameters} params - getTextContent parameters. + * @return {Promise} That is resolved a {@link TextContent} + * object that represent the page text content. + */ + getTextContent(params?: getTextContentParameters): Promise; + + /** + * Cleans up resources allocated by the page. + * @param {boolean} resetStats - (optional) Reset page stats, if enabled. + * The default value is `false`. + */ + cleanup(resetStats?: boolean): void; + } + + type PDFObject = object; + + /** + * A PDF document and page is built of many objects. E.g. there are objects + * for fonts, images, rendering code and such. These objects might get processed + * inside of a worker. The `PDFObjects` implements some basic functions to + * manage these objects. + * @ignore + */ + interface PDFObjects { + objs: { [objId: string]: PDFObject }; + + /** + * If called *without* callback, this returns the data of `objId` but the + * object needs to be resolved. If it isn't, this function throws. + * + * If called *with* a callback, the callback is called with the data of the + * object once the object is resolved. That means, if you call this + * function and the object is already resolved, the callback gets called + * right away. + */ + get(objId: string, callback?: (data: any) => void): any | null; + + /** + * Resolves the object `objId` with optional `data`. + */ + resolve(objId: string, data: any): void; + isResolved(objId: string): boolean; + hasData(objId: string): boolean; + + /** + * Returns the data of `objId` if object exists, null otherwise. + */ + getData(objId: string): any; + clear(): void; + } + + type RenderingIntent = "display" | "print"; + + /** + * Page annotation parameters. + * + * @typedef {Object} GetAnnotationsParameters + * @property {string} intent - Determines the annotations that will be fetched, + * can be either 'display' (viewable annotations) or 'print' + * (printable annotations). + * If the parameter is omitted, all annotations are fetched. + */ + interface GetAnnotationsParameters { + intent: RenderingIntent | undefined; + } + + /** + * @param {Array} color - The color array containing either 0 + * (transparent), 1 (grayscale), 3 (RGB) or + * 4 (CMYK) elements + */ + type Color = Uint8ClampedArray; + + /** + * Page render parameters. + * + * @typedef {Object} RenderParameters + * @property {Object} canvasContext - A 2D context of a DOM Canvas object. + * @property {PageViewport} viewport - Rendering viewport obtained by + * calling of PDFPage.getViewport method. + * @property {string} intent - Rendering intent, can be 'display' or 'print' + * (default value is 'display'). + * @property {boolean} enableWebGL - (optional) Enables WebGL accelerated + * rendering for some operations. The default value is `false`. + * @property {boolean} renderInteractiveForms - (optional) Whether or not + * interactive form elements are rendered in the display + * layer. If so, we do not render them on canvas as well. + * @property {Array} transform - (optional) Additional transform, applied + * just before viewport transform. + * @property {Object} imageLayer - (optional) An object that has beginLayout, + * endLayout and appendImage functions. + * @property {Object} canvasFactory - (optional) The factory that will be used + * when creating canvases. The default value is + * {DOMCanvasFactory}. + * @property {Object} background - (optional) Background to use for the canvas. + * Can use any valid canvas.fillStyle: A DOMString parsed as + * CSS value, a CanvasGradient object (a linear or + * radial gradient) or a CanvasPattern object (a repetitive + * image). The default value is 'rgb(255,255,255)'. + */ + interface RenderParameters { + canvasContext: CanvasRenderingContext2D; + viewport: PageViewport; + intent?: RenderingIntent; + enableWebGL?: boolean; + renderInteractiveForms?: boolean; + transform?: Transform[]; + imageLayer?: ImageLayer; + canvasFactory?: CanvasFactory; + background?: string; + } + + interface RenderTask { + /** + * Promise for rendering task completion. + * @return {Promise} + */ + promise: Promise; + + /** + * Cancels the rendering task. If the task is currently rendering it will + * not be cancelled until graphics pauses with a timeout. The promise that + * this object extends will be rejected when cancelled. + */ + cancel(): void; + + /** + * Registers callbacks to indicate the rendering task completion. + * + * @param {function} onFulfilled The callback for the rendering completion. + * @param {function} onRejected The callback for the rendering failure. + * @return {Promise} A promise that is resolved after the onFulfilled or + * onRejected callback. + */ + then( + onFulfilled?: (value?: void) => R1 | PromiseLike, + onRejected?: (reason?: Error) => R2 | PromiseLike + ): Promise; + } + + /** + * PDF page operator list. + * + * @typedef {Object} PDFOperatorList + * @property {Array} fnArray - Array containing the operator functions. + * @property {Array} argsArray - Array containing the arguments of the + * functions. + */ + interface PDFOperatorList { + fnArray: OPS[]; + argsArray: any[][]; + } + + /** + * Page getTextContent parameters. + * + * @typedef {Object} getTextContentParameters + * @property {boolean} normalizeWhitespace - replaces all occurrences of + * whitespace with standard spaces (0x20). The default value is `false`. + * @property {boolean} disableCombineTextItems - do not attempt to combine + * same line {@link TextItem}'s. The default value is `false`. + */ + interface getTextContentParameters { + normalizeWhitespace?: boolean; + disableCombineTextItems?: boolean; + } + + /** + * Page text content. + * + * @typedef {Object} TextContent + * @property {array} items - array of {@link TextItem} + * @property {Object} styles - {@link TextStyles} objects, indexed by font name. + */ + interface TextContent { + items: TextItem[]; + styles: { [fontName: string]: TextStyles }; + } + + /** + * Page text content part. + * + * @typedef {Object} TextItem + * @property {string} str - text content. + * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'. + * @property {array} transform - transformation matrix. + * @property {number} width - width in device space. + * @property {number} height - height in device space. + * @property {string} fontName - font name used by pdf.js for converted font. + */ + type TextDirection = "ttb" | "ltr" | "rtl"; + interface TextItem { + str: string; + dir: TextDirection; + transform: Transform; + width: number; + height: number; + fontName: string; + } + + /** + * Text style. + * + * @typedef {Object} TextStyle + * @property {number} ascent - font ascent. + * @property {number} descent - font descent. + * @property {boolean} vertical - text is in vertical mode. + * @property {string} fontFamily - possible font family + */ + interface TextStyles { + ascent: number; + descent: number; + vertical?: boolean; + fontFamily: string; + } + + /** + * PDF document loading operation. + * @class + * @alias PDFDocumentLoadingTask + */ + interface PDFDocumentLoadingTask { + /** + * Unique document loading task id -- used in MessageHandlers. + * @type {string} + */ + docId: string; + + /** + * Shows if loading task is destroyed. + * @type {boolean} + */ + destroyed: boolean; + + /** + * Callback to request a password if wrong or no password was provided. + * The callback receives two parameters: function that needs to be called + * with new password and reason (see {PasswordResponses}). + */ + onPassword: passwordCallback | null; + + /** + * 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 {Object} with the properties: {number} loaded and {number} total. + */ + onProgress: documentLoadingProgressCallback | null; + + /** + * Callback to when unsupported feature is used. The callback receives + * an {UNSUPPORTED_FEATURES} argument. + */ + onUnsupportedFeature: unsupportedFeatureCallback | null; + + /** + * @type {Promise} + */ + promise: Promise; + + /** + * Aborts all network requests and destroys worker. + * @return {Promise} A promise that is resolved after destruction activity + * is completed. + */ + destroy(): Promise; + + /** + * Registers callbacks to indicate the document loading completion. + * + * @param {function} onFulfilled The callback for the loading completion. + * @param {function} onRejected The callback for the loading failure. + * @return {Promise} A promise that is resolved after the onFulfilled or + * onRejected callback. + */ + then( + onFulfilled?: (value?: PDFDocumentProxy) => R1 | PromiseLike, + onRejected?: (reason?: Error) => R2 | PromiseLike + ): Promise; + } + + type documentLoadingProgressCallback = ( + documentLoadingProgress: DocumentLoadingProgress + ) => void; + + type passwordCallback = ( + newPassword: (password: string) => void, + reason: PasswordResponses + ) => void; + + type unsupportedFeatureCallback = (feature: UNSUPPORTED_FEATURES) => void; + + interface DocumentLoadingProgress { + loaded: number; + total: number; + } + + interface CMapReaderFactory { + fetch(args: { + name: string; + }): Promise<{ cMapData: Uint8Array; compressionType: CMapCompressionType }>; + } + + /** + * Document initialization / loading parameters object. + * + * @typedef {Object} DocumentInitParameters + * @property {string} url - The URL of the PDF. + * @property {TypedArray|Array|string} data - Binary PDF data. Use typed arrays + * (Uint8Array) to improve the memory usage. If PDF data is BASE64-encoded, + * use atob() to convert it to a binary string first. + * @property {Object} httpHeaders - Basic authentication headers. + * @property {boolean} withCredentials - Indicates whether or not cross-site + * Access-Control requests should be made using credentials such as cookies + * or authorization headers. The default is false. + * @property {string} password - For decrypting password-protected PDFs. + * @property {TypedArray} initialData - A typed array with the first portion or + * all of the pdf data. Used by the extension since some data is already + * loaded before the switch to range requests. + * @property {number} length - The PDF file length. It's used for progress + * reports and range requests operations. + * @property {PDFDataRangeTransport} range + * @property {number} rangeChunkSize - Optional parameter to specify + * maximum number of bytes fetched per range request. The default value is + * 2^16 = 65536. + * @property {PDFWorker} worker - The worker that will be used for the loading + * and parsing of the PDF data. + * @property {boolean} postMessageTransfers - (optional) Enables transfer usage + * in postMessage for ArrayBuffers. The default value is `true`. + * @property {number} verbosity - (optional) Controls the logging level; the + * constants from {VerbosityLevel} should be used. + * @property {string} docBaseUrl - (optional) The base URL of the document, + * used when attempting to recover valid absolute URLs for annotations, and + * outline items, that (incorrectly) only specify relative URLs. + * @property {string} nativeImageDecoderSupport - (optional) Strategy for + * decoding certain (simple) JPEG images in the browser. This is useful for + * environments without DOM image and canvas support, such as e.g. Node.js. + * Valid values are 'decode', 'display' or 'none'; where 'decode' is intended + * for browsers with full image/canvas support, 'display' for environments + * with limited image support through stubs (useful for SVG conversion), + * and 'none' where JPEG images will be decoded entirely by PDF.js. + * The default value is 'decode'. + * @property {string} cMapUrl - (optional) The URL where the predefined + * Adobe CMaps are located. Include trailing slash. + * @property {boolean} cMapPacked - (optional) Specifies if the Adobe CMaps are + * binary packed. + * @property {Object} CMapReaderFactory - (optional) The factory that will be + * used when reading built-in CMap files. Providing a custom factory is useful + * for environments without `XMLHttpRequest` support, such as e.g. Node.js. + * The default value is {DOMCMapReaderFactory}. + * @property {boolean} stopAtErrors - (optional) Reject certain promises, e.g. + * `getOperatorList`, `getTextContent`, and `RenderTask`, when the associated + * PDF data cannot be successfully parsed, instead of attempting to recover + * whatever possible of the data. The default value is `false`. + * @property {number} maxImageSize - (optional) The maximum allowed image size + * in total pixels, i.e. width * height. Images above this value will not be + * rendered. Use -1 for no limit, which is also the default value. + * @property {boolean} isEvalSupported - (optional) Determines if we can eval + * strings as JS. Primarily used to improve performance of font rendering, + * and when parsing PDF functions. The default value is `true`. + * @property {boolean} disableFontFace - (optional) By default fonts are + * converted to OpenType fonts and loaded via font face rules. If disabled, + * fonts will be rendered using a built-in font renderer that constructs the + * glyphs with primitive path commands. The default value is `false`. + * @property {boolean} disableRange - (optional) Disable range request loading + * of PDF files. When enabled, and if the server supports partial content + * requests, then the PDF will be fetched in chunks. + * The default value is `false`. + * @property {boolean} disableStream - (optional) Disable streaming of PDF file + * data. By default PDF.js attempts to load PDFs in chunks. + * The default value is `false`. + * @property {boolean} disableAutoFetch - (optional) Disable pre-fetching of PDF + * file data. When range requests are enabled PDF.js will automatically keep + * fetching more data even if it isn't needed to display the current page. + * The default value is `false`. + * NOTE: It is also necessary to disable streaming, see above, + * in order for disabling of pre-fetching to work correctly. + * @property {boolean} disableCreateObjectURL - (optional) Disable the use of + * `URL.createObjectURL`, for compatibility with older browsers. + * The default value is `false`. + * @property {boolean} pdfBug - (optional) Enables special hooks for debugging + * PDF.js (see `web/debugger.js`). The default value is `false`. + */ + interface DocumentInitParameters { + url?: string; + data?: Uint8Array | ArrayLike | ArrayBufferLike | string; + headers?: Headers; + withCredentials?: boolean; + password?: string; + initialData?: Uint8Array; + length?: number; + range?: PDFDataRangeTransport; + rangeChunkSize?: number; + worker?: PDFWorker; + postMessageTransfers?: boolean; + verbosity?: VerbosityLevel; + docBaseUrl?: string; + nativeImageDecoderSupport?: NativeImageDecoding; + cMapUrl?: string; + cMapPacked?: boolean; + CMapReaderFactory?: CMapReaderFactory; + stopAtErrors?: boolean; + maxImageSize?: number; + isEvalSupported?: boolean; + disableFontFace?: boolean; + disableRange?: boolean; + disableStream?: boolean; + disableAutoFetch?: boolean; + disableCreateObjectURL?: boolean; + pdfBug?: boolean; + } + + /** + * This is the main entry point for loading a PDF and interacting with it. + * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR) + * is used, which means it must follow the same origin rules that any XHR does + * e.g. No cross domain requests without CORS. + * + * @param {string|TypedArray|DocumentInitParameters|PDFDataRangeTransport} src + * Can be a url to where a PDF is located, a typed array (Uint8Array) + * already populated with data or parameter object. + * + * @return {PDFDocumentLoadingTask} + */ + function getDocument( + src: string | Uint8Array | DocumentInitParameters | PDFDataRangeTransport + ): PDFDocumentLoadingTask; + + // + // src/display/api_compatibility.js + // + namespace apiCompatibilityParams { + const userAgent: string; + const isIE: boolean; + const isIOS: boolean; + const isIOSChrome: boolean; + const isSafari: boolean; + const disableCreateObjectURL: boolean | undefined; + const disableRange: boolean | undefined; + const disableStream: boolean | undefined; + } + + // + // src/display/dom_utils.js + // + class RenderingCancelledException extends Error { + type: string; + constructor(msg: string, type: string); + } + + enum LinkTarget {} + + namespace LinkTarget { + const NONE: LinkTarget; // Default value. + const SELF: LinkTarget; + const BLANK: LinkTarget; + const PARENT: LinkTarget; + const TOP: LinkTarget; + } + + /** + * Adds various attributes (href, title, target, rel) to hyperlinks. + * @param {HTMLLinkElement} link - The link element. + * @param {ExternalLinkParameters} params + */ + function addLinkAttributes( + link: HTMLLinkElement, + params: ExternalLinkParameters + ): void; + + // Gets the file name from a given URL. + function getFilenameFromUrl(url: string): string; + + interface CanvasAndContext { + canvas: HTMLCanvasElement; + context: CanvasRenderingContext2D; + } + + interface CanvasFactory { + create(width: number, height: number): CanvasAndContext; + reset(cac: CanvasAndContext, width: number, height: number): void; + destroy(cac: CanvasAndContext): void; + } + + interface DOMCanvasFactory extends CanvasFactory {} + + /** + * Constructor functions, use like `new DomCanvasFactory()` + */ + let DOMCanvasFactory: new () => DOMCanvasFactory; + + /** + * @typedef ExternalLinkParameters + * @typedef {Object} ExternalLinkParameters + * @property {string} url - An absolute URL. + * @property {LinkTarget} target - (optional) The link target. + * The default value is `LinkTarget.NONE`. + * @property {string} rel - (optional) The link relationship. + * The default value is `DEFAULT_LINK_REL`. + */ + interface ExternalLinkParameters { + url: string; + target?: LinkTarget; + rel?: string; + } + + class DOMSVGFactory { + create(width: number, height: number): SVGElement; + createElement(type: string): SVGElement; + } + + // + // src/display/annotation_layer.js + // + + /** + * @typedef {Object} AnnotationLayerParameters + * @property {PageViewport} viewport + * @property {HTMLDivElement} div + * @property {Array} annotations + * @property {PDFPage} page + * @property {IPDFLinkService} linkService + * @property {string} imageResourcesPath - (optional) Path for image resources, + * mainly for annotation icons. Include trailing slash. + * @property {boolean} renderInteractiveForms + */ + interface AnnotationLayerParameters { + viewport: PageViewport; + div: HTMLDivElement; + annotations: Annotation[]; + page: PDFPageProxy; + linkService: IPDFLinkService; + imageResourcesPath?: string; + renderInteractiveForms: boolean; + } + + class AnnotationLayer { + static render(parameters: AnnotationLayerParameters): void; + static update(parameters: AnnotationLayerParameters): void; + } + + // + // src/display/text_layer.js + // + + interface TextLayerRenderTask { + promise: Promise; + cancel(): void; + expandTextDivs(timeout: number): void; + } + + /** + * Text layer render parameters. + * + * @typedef {Object} TextLayerRenderParameters + * @property {TextContent} textContent - (optional) Text content to render + * (the object is returned by the page's getTextContent() method). + * @property {ReadableStream} textContentStream - (optional) Text content + * stream to render (the stream is returned by the page's + * streamTextContent() method). + * @property {HTMLElement} container - HTML element that will contain text runs. + * @property {PageViewport} viewport - The target viewport to properly + * layout the text runs. + * @property {Array} textDivs - (optional) HTML elements that are correspond + * the text items of the textContent input. This is output and shall be + * initially be set to empty array. + * @property {Array} textContentItemsStr - (optional) Strings that correspond + * the `str` property of the text items of textContent input. This is output + * and shall be initially be set to empty array. + * @property {number} timeout - (optional) Delay in milliseconds before + * rendering of the text runs occurs. + * @property {boolean} enhanceTextSelection - (optional) Whether to turn on the + * text selection enhancement. + */ + interface TextLayerRenderParameters { + textContent?: TextContent; + textContentStream?: ReadableStream; + container: HTMLElement; + viewport: PageViewport; + textDivs?: HTMLElement[]; + textContentItemsStr?: string[]; + timeout?: number; + enhanceTextSelection?: boolean; + } + + /** + * Starts rendering of the text layer. + * + * @param {TextLayerRenderParameters} renderParameters + * @returns {TextLayerRenderTask} + */ + function renderTextLayer( + renderParameters: TextLayerRenderParameters + ): TextLayerRenderTask; + + // + // src/display/metadata.js + // + class Metadata { + get(name: string): string | null; + getAll(): StringMap; + has(name: string): boolean; + } + + // + // src/display/svg.js + // + class SVGGraphics { + svgFactory: DOMSVGFactory; + commonObjs: PDFObjects; + objs: PDFObjects; + forceDataSchema: boolean; + embedFonts: boolean; + + constructor(commonObjs: PDFObjects, objs: PDFObjects, forceDataSchema?: boolean); + + getSVG( + operatorList: PDFOperatorList, + viewport: PageViewport + ): Promise; + } + + // + // src/display/worker_options.js + // + namespace GlobalWorkerOptions { + /** + * Defines global port for worker process. Overrides the `workerSrc` option. + * @var {Object} + */ + let workerPort: MessagePort | null; + + /** + * Path and filename of the worker file. Required when workers are enabled in + * development mode. If unspecified in production builds, the worker will be + * loaded based on the location of the `pdf.js` file. + * + * NOTE: The `workerSrc` should always be set in custom applications, in order + * to prevent issues caused by third-party frameworks and libraries. + * @var {string} + */ + let workerSrc: string; + } +} diff --git a/external/types/dom.d.ts b/external/types/dom.d.ts new file mode 100644 index 0000000000000..1ebcd96abb9b7 --- /dev/null +++ b/external/types/dom.d.ts @@ -0,0 +1,21 @@ +// DOM type dependencies. TypeScript will merge these dependencies with DOM +// types if the 'dom' library is included. + +interface MessagePort {} +interface Blob {} +interface URL {} +interface HTMLElement {} +interface HTMLLinkElement {} +interface HTMLCanvasElement {} +interface CanvasRenderingContext2D {} +interface HTMLDivElement {} +interface Headers {} +interface ReadableStream {} +interface SVGElement {} +interface SVGStyleElement {} +interface SVGMaskElement {} +interface SVGGElement {} +interface SVGTSpanElement {} +interface SVGTextElement {} +interface HTMLAnchorElement {} +interface ReadableStream {} diff --git a/external/types/pdf.d.ts b/external/types/pdf.d.ts new file mode 100644 index 0000000000000..7230a51527401 --- /dev/null +++ b/external/types/pdf.d.ts @@ -0,0 +1,109 @@ +/* Copyright 2017 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// +/// +/// +/// +/// + +declare module 'pdfjs-dist' { + // + // src/pdf.js + // + export import build = _pdfjs.build; + export import version = _pdfjs.version; + export import getDocument = _pdfjs.getDocument; + export import LoopbackPort = _pdfjs.LoopbackPort; + export import PDFDataRangeTransport = _pdfjs.PDFDataRangeTransport; + export import PDFWorker = _pdfjs.PDFWorker; + export import renderTextLayer = _pdfjs.renderTextLayer; + export import AnnotationLayer = _pdfjs.AnnotationLayer; + export import createPromiseCapability = _pdfjs.createPromiseCapability; + export import PasswordResponses = _pdfjs.PasswordResponses; + export import InvalidPDFException = _pdfjs.InvalidPDFException; + export import MissingPDFException = _pdfjs.MissingPDFException; + export import SVGGraphics = _pdfjs.SVGGraphics; + export import NativeImageDecoding = _pdfjs.NativeImageDecoding; + export import UnexpectedResponseException = _pdfjs.UnexpectedResponseException; + export import OPS = _pdfjs.OPS; + export import VerbosityLevel = _pdfjs.VerbosityLevel; + export import UNSUPPORTED_FEATURES = _pdfjs.UNSUPPORTED_FEATURES; + export import createValidAbsoluteUrl = _pdfjs.createValidAbsoluteUrl; + export import createObjectURL = _pdfjs.createObjectURL; + export import removeNullCharacters = _pdfjs.removeNullCharacters; + export import shadow = _pdfjs.shadow; + export import createBlob = _pdfjs.createBlob; + export import Util = _pdfjs.Util; + export import RenderingCancelledException = _pdfjs.RenderingCancelledException; + export import getFilenameFromUrl = _pdfjs.getFilenameFromUrl; + export import LinkTarget = _pdfjs.LinkTarget; + export import addLinkAttributes = _pdfjs.addLinkAttributes; + export import GlobalWorkerOptions = _pdfjs.GlobalWorkerOptions; + export import apiCompatibilityParams = _pdfjs.apiCompatibilityParams; + + // + // Convenience types that are used often. + // + export import PDFDocumentProxy = _pdfjs.PDFDocumentProxy; + export import DocumentInitParameters = _pdfjs.DocumentInitParameters; + export import PDFPageProxy = _pdfjs.PDFPageProxy; + export import PDFDocumentLoadingTask = _pdfjs.PDFDocumentLoadingTask; + export import PageIndex = _pdfjs.PageIndex; + export import Outline = _pdfjs.Outline; + export import Transform = _pdfjs.Transform; + export import Point = _pdfjs.Point; + export import Rect = _pdfjs.Rect; + export import PDFObjects = _pdfjs.PDFObjects; + export import PDFOperatorList = _pdfjs.PDFOperatorList; + export import PageViewport = _pdfjs.PageViewport; + export import Annotation = _pdfjs.Annotation; + export import RenderParameters = _pdfjs.RenderParameters; + export import PDFViewerOptions = _pdfjs.PDFViewerOptions; + export import DocumentLoadingProgress = _pdfjs.DocumentLoadingProgress; + + // + // All other types. Warning: this should only be used to access types, not + // functions or variables. + // + export import types = _pdfjs; +} + +declare module 'pdfjs-dist/web/pdf_viewer' { + // + // web/pdf_viewer.component.js + // + export import PDFViewer = _pdfjs.PDFViewer; + export import PDFSinglePageViewer = _pdfjs.PDFSinglePageViewer; + export import PDFPageView = _pdfjs.PDFPageView; + export import PDFLinkService = _pdfjs.PDFLinkService; + export import SimpleLinkService = _pdfjs.SimpleLinkService; + export import TextLayerBuilder = _pdfjs.TextLayerBuilder; + export import DefaultTextLayerFactory = _pdfjs.DefaultTextLayerFactory; + export import AnnotationLayerBuilder = _pdfjs.AnnotationLayerBuilder; + export import DefaultAnnotationLayerFactory = _pdfjs.DefaultAnnotationLayerFactory; + export import PDFHistory = _pdfjs.PDFHistory; + export import PDFFindController = _pdfjs.PDFFindController; + export import EventBus = _pdfjs.EventBus; + export import DownloadManager = _pdfjs.DownloadManager; + export import ProgressBar = _pdfjs.ProgressBar; + export import GenericL10n = _pdfjs.GenericL10n; + export import NullL10n = _pdfjs.NullL10n; +} + +// Webpack version. +declare module 'pdfjs-dist/webpack' { + export * from 'pdfjs-dist'; +} diff --git a/external/types/shared.d.ts b/external/types/shared.d.ts new file mode 100644 index 0000000000000..c5e143722044a --- /dev/null +++ b/external/types/shared.d.ts @@ -0,0 +1,538 @@ +/* Copyright 2017 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +interface HTMLAnchorElement {} +interface ReadableStream {} + +declare namespace _pdfjs { + // + // src/shared/util.js + // + + enum VerbosityLevel {} + namespace VerbosityLevel { + const ERRORS: VerbosityLevel; + const WARNINGS: VerbosityLevel; + const INFOS: VerbosityLevel; + } + + let shadow: typeof Object.defineProperty; + function createBlob(data: any, contentType: string): Blob; + function createObjectURL( + data: any, + contentType: string, + forceDataSchema?: boolean + ): string; + let isLittleEndian: boolean; + function removeNullCharacters(str: string): string; + + class PasswordException extends Error { + constructor(msg: string, code: PasswordResponses); + code: PasswordResponses; + } + + class UnknownErrorException extends Error { + constructor(msg: string, details: string); + details: string; + } + + class UnexpectedResponseException extends Error { + constructor(msg: string, status: number); + status: number; + } + + class InvalidPDFException extends Error { + constructor(msg: string); + } + + class MissingPDFException extends Error { + constructor(msg: string); + } + + interface CloneArgs { + scale: number; + rotation: number; + } + + class PageViewport { + viewBox: Rect; + scale: number; + rotation: number; + offsetX: number; + offsetY: number; + + // creating transform for the following operations: + // translate(-centerX, -centerY), rotate and flip vertically, + // scale, and translate(offsetCanvasX, offsetCanvasY) + transform: Transform; + + width: number; + height: number; + fontScale: number; + + /** + * Clones viewport with additional properties. + * @param args {Object} (optional) If specified, may contain the 'scale' or + * 'rotation' properties to override the corresponding properties in + * the cloned viewport. + * @returns {PageViewport} Cloned viewport. + */ + clone(args?: CloneArgs): PageViewport; + + /** + * Converts PDF point to the viewport coordinates. For examples, useful for + * converting PDF location into canvas pixel coordinates. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the viewport coordinate space. + * @see {@link convertToPdfPoint} + * @see {@link convertToViewportRectangle} + */ + convertToViewportPoint(x: number, y: number): Point; + + /** + * Converts PDF rectangle to the viewport coordinates. + * @param rect {Array} xMin, yMin, xMax and yMax coordinates. + * @returns {Array} Contains corresponding coordinates of the rectangle + * in the viewport coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToViewportRectangle(rect: Rect): Rect; + + /** + * Converts viewport coordinates to the PDF location. For examples, useful + * for converting canvas pixel location into PDF one. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the PDF coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToPdfPoint(x: number, y: number): Point; + } + + /** + * Promise Capability object. + * + * @typedef {Object} PromiseCapability + * @property {Promise} promise - A promise object. + * @property {function} resolve - Fulfills the promise. + * @property {function} reject - Rejects the promise. + */ + interface PromiseCapability { + promise: Promise; + resolve: (val: T) => void; + reject: (reason?: any) => void; + } + + /** + * Creates a promise capability object. + * @alias createPromiseCapability + * + * @return {PromiseCapability} A capability object contains: + * - a Promise, resolve and reject methods. + */ + function createPromiseCapability(): PromiseCapability; + + let Util: { + makeCssRgb(r: number, g: number, b: number): string; + + // Concatenates two transformation matrices together and returns the result. + transform(m1: Transform, m2: Transform): Transform; + + // For 2d affine transforms + applyTransform(p: Point, m: Transform): Point; + applyInverseTransform(p: Point, m: Transform): Point; + + // Applies the transform to the rectangle and finds the minimum axially + // aligned bounding box. + getAxialAlignedBoundingBox(r: Rect, m: Transform): Rect; + inverseTransform(m: Transform): Transform; + + // Apply a generic 3d matrix M on a 3-vector v: + // | a b c | | X | + // | d e f | x | Y | + // | g h i | | Z | + // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], + // with v as [X,Y,Z] + apply3dTransform(m: Transform3d, p: Point3d): Point3d; + + // This calculation uses Singular Value Decomposition. + // The SVD can be represented with formula A = USV. We are interested in the + // matrix S here because it represents the scale values. + // Returns [scale X, scale Y] + singularValueDecompose2dScale(m: Transform): number[]; + + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + normalizeRect(rect: Rect): Rect; + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + intersect(rect1: Rect, rect2: Rect): Rect | false; + + /** + * Converts positive integers to (upper case) Roman numerals. + * @param {integer} number - The number that should be converted. + * @param {boolean} lowerCase - Indicates if the result should be converted + * to lower case letters. The default is false. + * @return {string} The resulting Roman number. + */ + toRoman(number: number, lowerCase: boolean): string; + + // Destructively append second array to first aray + appendToArray(arr1: any[], arr2: any[]): void; + + // Destructively prepent second array to first array + prependToArray(arr1: any[], arr2: any[]): void; + + // Add (key,value) pairs from obj2 to obj1 (overwriting intersecting keys) + extendObj(obj1: object, obj2: object): void; + + loadScript(src: string, callback: undefined | (() => void)): void; + }; + + class MessageHandler { + constructor(sourceName: string, targetName: string, comObj: MessagePort); + sourceName: string; + targetName: string; + comObj: MessagePort; + callbackId: number; + streamId: number; + postMessageTransfers: boolean; + + // TODO: Some fields missing, that appear to be maps. Unclear if they should be exposed. + + on(actionName: string, handler: any, scope: any): void; + + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * @param {String} actionName - Action to call. + * @param {JSON} data - JSON data to send. + * @param {Array} [transfers] - Optional list of transfers/ArrayBuffers + */ + send(actionName: string, data: JSON, transfers: any): void; + + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * Expects that the other side will callback with the response. + * @param {String} actionName - Action to call. + * @param {JSON} data - JSON data to send. + * @param {Array} [transfers] - Optional list of transfers/ArrayBuffers. + * @returns {Promise} Promise to be resolved with response data. + */ + sendWithPromise( + actionName: string, + data: JSON, + transfers: any + ): Promise; + + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * Expect that the other side will callback to signal 'start_complete'. + * @param {String} actionName - Action to call. + * @param {JSON} data - JSON data to send. + * @param {Object} queueingStrategy - strategy to signal backpressure based on + * internal queue. + * @param {Array} [transfers] - Optional list of transfers/ArrayBuffers. + * @return {ReadableStream} ReadableStream to read data in chunks. + */ + sendWithStream( + actionName: string, + data: JSON, + queueingStrategy: object, + transfers: any + ): ReadableStream; + + /** + * Sends raw message to the comObj. + * @private + * @param {Object} message - Raw message. + * @param transfers List of transfers/ArrayBuffers, or undefined. + */ + postMessage(message: object, transfers: any): void; + + destroy(): void; + } + + enum StreamType { + UNKNOWN, + FLATE, + LZW, + DCT, + JPX, + JBIG, + A85, + AHX, + CCF, + RL + } + + enum FontType { + UNKNOWN, + TYPE1, + TYPE1C, + CIDFONTTYPE0, + CIDFONTTYPE0C, + TRUETYPE, + CIDFONTTYPE2, + TYPE3, + OPENTYPE, + TYPE0, + MMTYPE1 + } + + type FontTypeName = + | 'Type1' + | 'CIDFontType0' + | 'OpenType' + | 'TrueType' + | 'CIDFontType2' + | 'MMType1' + | 'Type0'; + + type FontSubTypeName = 'Type1C' | 'CIDFontType0C'; + + interface StatTimer { + // times are recorded as the number of milliseconds + // elapsed since January 1, 1970 00:00:00 UTC + times: { name: string; start: number; end: number }[]; + started: { [name: string]: number }; + enabled: boolean; + } + + // Values are required for this enum to allow for type-specific ADT subclass + // discrimintation. See the Annotation interface and its sub-interfaces. + enum AnnotationType { + TEXT = 1, + LINK = 2, + FREETEXT = 3, + LINE = 4, + SQUARE = 5, + CIRCLE = 6, + POLYGON = 7, + POLYLINE = 8, + HIGHLIGHT = 9, + UNDERLINE = 10, + SQUIGGLY = 11, + STRIKEOUT = 12, + STAMP = 13, + CARET = 14, + INK = 15, + POPUP = 16, + FILEATTACHMENT = 17, + SOUND = 18, + MOVIE = 19, + WIDGET = 20, + SCREEN = 21, + PRINTERMARK = 22, + TRAPNET = 23, + WATERMARK = 24, + THREED = 25, + REDACT = 26 + } + + enum AnnotationFlag { + INVISIBLE, + HIDDEN, + PRINT, + NOZOOM, + NOROTATE, + NOVIEW, + READONLY, + LOCKED, + TOGGLENOVIEW, + LOCKEDCONTENTS + } + + type AnnotationSubtype = + | 'Link' + | 'Text' + | 'Widget' + | 'Popup' + | 'Line' + | 'Square' + | 'Circle' + | 'PolyLine' + | 'Polygon' + | 'Highlight' + | 'Underline' + | 'Squiggly' + | 'StrikeOut' + | 'Stamp' + | 'FileAttachment'; + + enum AnnotationBorderStyleType { + SOLID, + DASHED, + BEVELED, + INSET, + UNDERLINE + } + + interface Image { + objId: string; + left: number; + top: number; + width: number; + height: number; + } + + interface ImageLayer { + beginLayout(): void; + appendImage(image: Image): void; + endLayout(): void; + } + + /** + * Attempts to create a valid absolute URL (utilizing `isValidProtocol`). + * @param {URL|string} url - An absolute, or relative, URL. + * @param {URL|string} baseUrl - An absolute URL. + * @returns Either a valid {URL}, or `null` otherwise. + */ + function createValidAbsoluteUrl( + url: URL | string, + baseUrl: URL | string + ): URL | null; + + enum NativeImageDecoding { + NONE, + DECODE, + DISPLAY + } + + enum CMapCompressionType { + NONE, + BINARY, + STREAM + } + + enum PDFImageKind { + GRAYSCALE_1BPP, + RGB_24BPP, + RGBA_32BPP + } + + enum PasswordResponses { + NEED_PASSWORD, + INCORRECT_PASSWORD + } + + enum UNSUPPORTED_FEATURES { + unknown, + forms, + javaScript, + smask, + shadingPattern, + font + } + + enum OPS { + dependency, + setLineWidth, + setLineCap, + setLineJoin, + setMiterLimit, + setDash, + setRenderingIntent, + setFlatness, + setGState, + save, + restore, + transform, + moveTo, + lineTo, + curveTo, + curveTo2, + curveTo3, + closePath, + rectangle, + stroke, + closeStroke, + fill, + eoFill, + fillStroke, + eoFillStroke, + closeFillStroke, + closeEOFillStroke, + endPath, + clip, + eoClip, + beginText, + endText, + setCharSpacing, + setWordSpacing, + setHScale, + setLeading, + setFont, + setTextRenderingMode, + setTextRise, + moveText, + setLeadingMoveText, + setTextMatrix, + nextLine, + showText, + showSpacedText, + nextLineShowText, + nextLineSetSpacingShowText, + setCharWidth, + setCharWidthAndBounds, + setStrokeColorSpace, + setFillColorSpace, + setStrokeColor, + setStrokeColorN, + setFillColor, + setFillColorN, + setStrokeGray, + setFillGray, + setStrokeRGBColor, + setFillRGBColor, + setStrokeCMYKColor, + setFillCMYKColor, + shadingFill, + beginInlineImage, + beginImageData, + endInlineImage, + paintXObject, + markPoint, + markPointProps, + beginMarkedContent, + beginMarkedContentProps, + endMarkedContent, + beginCompat, + endCompat, + paintFormXObjectBegin, + paintFormXObjectEnd, + beginGroup, + endGroup, + beginAnnotations, + endAnnotations, + beginAnnotation, + endAnnotation, + paintJpegXObject, + paintImageMaskXObject, + paintImageMaskXObjectGroup, + paintImageXObject, + paintInlineImageXObject, + paintInlineImageXObjectGroup, + paintImageXObjectRepeat, + paintImageMaskXObjectRepeat, + paintSolidColorImageMask, + constructPath + } +} diff --git a/external/types/web.d.ts b/external/types/web.d.ts new file mode 100644 index 0000000000000..ca4809a3c7ef8 --- /dev/null +++ b/external/types/web.d.ts @@ -0,0 +1,992 @@ +/* Copyright 2017 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace _pdfjs { + // + // web/interfaces.js + // + + /** + * @interface + */ + class IRenderableView { + /** + * @returns {string} - Unique ID for rendering queue. + */ + renderingId: string; + + /** + * @returns {RenderingStates} + */ + renderingState: RenderingStates; + + /** + * @returns {Promise} Resolved on draw completion. + */ + draw(): Promise; + + resume(): void; + } + + interface IL10n { + /** + * @returns {Promise} - Resolves to the current locale. + */ + getLanguage(): Promise; + + /** + * @returns {Promise} - Resolves to 'rtl' or 'ltr'. + */ + getDirection(): Promise; + + /** + * Translates text identified by the key and adds/formats data using the args + * property bag. If the key was not found, translation falls back to the + * fallback text. + * @param {string} key + * @param {object} args + * @param {string} fallback + * @returns {Promise} + */ + get(key: string, args: StringMap, fallback: string): Promise; + + /** + * Translates HTML element. + * @param {HTMLElement} element + * @returns {Promise} + */ + translate(element: HTMLElement): Promise; + } + + interface IPDFTextLayerFactory { + createTextLayerBuilder( + textLayerDiv: HTMLDivElement, + pageIndex: PageIndex, + viewport: PageViewport, + enhanceTextSelection?: boolean + ): TextLayerBuilder; + } + + interface IPDFAnnotationLayerFactory { + /** + * @param {HTMLDivElement} pageDiv + * @param {PDFPage} pdfPage + * @param {string} imageResourcesPath - (optional) Path for image resources, + * mainly for annotation icons. Include trailing slash. + * @param {boolean} renderInteractiveForms + * @param {IL10n} l10n + * @returns {AnnotationLayerBuilder} + */ + createAnnotationLayerBuilder( + pageDiv: HTMLDivElement, + pdfPage: PDFPageProxy, + imageResourcesPath?: string, + renderInteractiveForms?: boolean, + l10n?: IL10n + ): AnnotationLayerBuilder; + } + + interface IPDFLinkService { + /** + * @returns {number} + */ + page: number; + + /** + * @returns {number} + */ + rotation: number; + + /** + * @param {string|Array} dest - The named, or explicit, PDF destination. + */ + navigateTo(dest: Destination): void; + + /** + * @param {string|Array} dest - The PDF destination object. + * @returns {string} The hyperlink to the PDF object. + */ + getDestinationHash(dest: Destination): string; + + /** + * Prefix the full url on anchor links to make sure that links are resolved + * relative to the current URL instead of the one defined in . + * @param {String} anchor The anchor hash, including the #. + * @returns {string} The hyperlink to the PDF object. + */ + getAnchorUrl(hash: string): string; + + /** + * @param {string} hash + */ + setHash(hash: string): void; + + /** + * @param {string} action + */ + executeNamedAction(action: string): void; + + /** + * @param {Object} params + */ + onFileAttachmentAnnotation(params: { + id: string; + filename: string; + content: any; + }): void; + + /** + * @param {number} pageNum - page number. + * @param {Object} pageRef - reference to the page. + */ + cachePageRef(pageNum: number, pageRef: Ref): void; + } + + // + // web/pdf_link_service.js + // + interface SimpleLinkService extends IPDFLinkService {} + let SimpleLinkService: new () => SimpleLinkService; + + interface PDFLinkService extends IPDFLinkService { + eventBus: EventBus; + baseUrl: string; + pdfDocument: PDFDocumentProxy; + pdfViewer: PDFViewer; + pdfHistory: PDFHistory; + setDocument(pdfDocument: PDFDocumentProxy, baseUrl: string): void; + setViewer(pdfViewer: PDFViewer): void; + setHistory(pdfHistory: PDFHistory): void; + } + + /** + * @typedef {Object} PDFLinkServiceOptions + * @property {EventBus} eventBus - The application event bus. + * @property {number} externalLinkTarget - (optional) Specifies the `target` + * attribute for external links. Must use one of the values from {LinkTarget}. + * Defaults to using no target. + * @property {string} externalLinkRel - (optional) Specifies the `rel` attribute + * for external links. Defaults to stripping the referrer. + */ + interface PDFLinkServiceOptions { + eventBus?: EventBus; + externalLinkTarget?: LinkTarget; + externalLinkRel?: string; + } + + /** + * @param {PDFLinkServiceOptions} options + * Constructor for PDFLinkService + */ + let PDFLinkService: new (options?: PDFLinkServiceOptions) => PDFLinkService; + + // + // web/ui_utils.js + // + + enum TextLayerMode {} + + namespace TextLayerMode { + const DISABLE: TextLayerMode; + const ENABLE: TextLayerMode; + const ENABLE_ENHANCE: TextLayerMode; + } + + /** + * Simple event bus for an application. Listeners are attached using the + * `on` and `off` methods. To raise an event, the `dispatch` method shall be + * used. + */ + class EventBus { + constructor(); + on(eventName: string, listener: (...args: any[]) => void): void; + off(eventName: string, listener: (...args: any[]) => void): void; + dispatch(eventName: string, ...args: any[]): void; + } + + enum RendererType { + CANVAS, + SVG + } + + /** + * No-op implemetation of the localization service. + * @implements {IL10n} + */ + interface NullL10n extends IL10n {} + + class ProgressBar { + visible: boolean; + div: HTMLDivElement; + bar: HTMLElement; // Loading bar element + height: number; + width: number; + units: string; + percent: number; + + constructor( + id: string, + options?: { height?: number; width?: number; units?: string } + ); + setWidth(viewer: HTMLElement | undefined): void; + hide(): void; + show(): void; + } + + // + // web/pdf_rendering_queue.js + // + enum RenderingStates { + INITIAL, + RUNNING, + PAUSED, + FINISHED + } + + /** + * Controls rendering of the views for pages and thumbnails. + */ + class PDFRenderingQueue { + pdfViewer: PDFViewer | null; + pdfThumbnailViewer: PDFThumbnailViewer | null; + highestPriorityPage: PageIndex | null; + idleTimeout: number | null; + printing: boolean; + isThumbnailViewEnabled: boolean; + + constructor(); + + /** + * @param {PDFViewer} pdfViewer + */ + setViewer(pdfViewer: PDFViewer): void; + + /** + * @param {PDFThumbnailViewer} pdfThumbnailViewer + */ + setThumbnailViewer(pdfThumbnailViewer: PDFThumbnailViewer): void; + + /** + * @param {IRenderableView} view + * @returns {boolean} + */ + isHighestPriority(view: IRenderableView): boolean; + + /** + * @param {Object} currentlyVisiblePages + */ + renderHighestPriority(currentlyVisiblePages?: VisiblePages): void; + + /** + * @param {Object} visible + * @param {Array} views + * @param {boolean} scrolledDown + */ + getHighestPriority( + visible: VisiblePages, + views: PDFPageView[], + scrolledDown: boolean + ): PDFPageView; + + /** + * @param {IRenderableView} view + * @returns {boolean} + */ + isViewFinished(view: IRenderableView): boolean; + + /** + * Render a page or thumbnail view. This calls the appropriate function + * based on the views state. If the view is already rendered it will return + * `false`. + * + * @param {IRenderableView} view + */ + renderView(view: IRenderableView): boolean; + } + + // + // web/base_viewer.js + // + + /** + * Simple viewer control to display PDF content/pages. + * @implements {IRenderableView} + */ + class BaseViewer { + /** + * @param {PDFViewerOptions} options + */ + constructor(options: PDFViewerOptions); + + readonly pagesCount: number; + getPageView(index: number): PDFPageView; + + /** + * @param {number} val - The page number. + */ + currentPageNumber: number; + + /** + * @returns {string|null} Returns the current page label, + * or `null` if no page labels exist. + */ + currentPageLabel: string | null; + + /** + * @returns {boolean} true if all {PDFPageView} objects are initialized. + */ + pageViewsReady: boolean; + + /** + * @param {number} val - Scale of the pages in percents. + */ + currentScale: number; + + /** + * @param val - The scale of the pages (in percent or predefined value). + */ + currentScaleValue: string; + + /** + * @param {number} rotation - The rotation of the pages (0, 90, 180, 270). + */ + pagesRotation: number; + + setDocument(pdfDocument: PDFDocumentProxy): void; + + setPageLabels(labels: string[] | null): void; + + /** + * Scrolls page into view. + * @param {ScrollPageIntoViewParameters} params + */ + scrollPageIntoView(params: ScrollPageIntoViewParameters): void; + + update(): void; + containsElement(element: HTMLElement): boolean; + focus(): void; + readonly isInPresentationMode: boolean; + readonly isChangingPresentationMode: boolean; + readonly isHorizontalScrollbarEnabled: boolean; + cleanup(): void; + forceRendering(currentlyVisiblePages?: VisiblePages): boolean; + getPageTextContent(pageIndex: PageIndex): TextContent; + + /** + * @param {HTMLDivElement} textLayerDiv + * @param {number} pageIndex + * @param {PageViewport} viewport + * @returns {TextLayerBuilder} + */ + createTextLayerBuilder( + textLayerDiv: HTMLDivElement, + pageIndex: PageIndex, + viewport: PageViewport, + enhanceTextSelection?: boolean + ): TextLayerBuilder; + + /** + * @param {HTMLDivElement} pageDiv + * @param {PDFPage} pdfPage + * @param {boolean} renderInteractiveForms + * @param {IL10n} l10n + * @returns {AnnotationLayerBuilder} + */ + createAnnotationLayerBuilder( + pageDiv: HTMLDivElement, + pdfPage: PDFPageProxy, + renderInteractiveForms?: boolean, + l10n?: IL10n + ): AnnotationLayerBuilder; + + setFindController(findController: any): void; + + /** + * @returns {boolean} Whether all pages of the PDF document have identical + * widths and heights. + */ + readonly hasEqualPageSizes: boolean; + + /** + * Returns sizes of the pages. + * @returns {Array} Array of objects with width/height/rotation fields. + */ + getPagesOverview(): PageSize[]; + } + + interface PageSize { + width: number; + height: number; + rotation: number; + } + + /** + * @typedef ScrollPageIntoViewParameters + * @property {number} pageNumber - The page number. + * @property {Array} destArray - (optional) The original PDF destination + * array, in the format: + * @property {boolean} allowNegativeOffset - (optional) Allow negative page + * offsets. The default value is `false`. + */ + interface ScrollPageIntoViewParameters { + pageNumber: number; + destArray?: any[]; + allowNegativeOffset?: boolean; + } + + /** + * @typedef {Object} PDFViewerOptions + * @property {HTMLDivElement} container - The container for the viewer element. + * @property {HTMLDivElement} viewer - (optional) The viewer element. + * @property {EventBus} eventBus - The application event bus. + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {DownloadManager} downloadManager - (optional) The download + * manager component. + * @property {PDFRenderingQueue} renderingQueue - (optional) The rendering + * queue object. + * @property {boolean} removePageBorders - (optional) Removes the border shadow + * around the pages. The default value is `false`. + * @property {number} textLayerMode - (optional) Controls if the text layer used + * for selection and searching is created, and if the improved text selection + * behaviour is enabled. The constants from {TextLayerMode} should be used. + * The default value is `TextLayerMode.ENABLE`. + * @property {string} imageResourcesPath - (optional) Path for image resources, + * mainly for annotation icons. Include trailing slash. + * @property {boolean} renderInteractiveForms - (optional) Enables rendering of + * interactive form elements. The default is `false`. + * @property {boolean} enablePrintAutoRotate - (optional) Enables automatic + * rotation of pages whose orientation differ from the first page upon + * printing. The default is `false`. + * @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'. + * @property {boolean} enableWebGL - (optional) Enables WebGL accelerated + * rendering for some operations. The default value is `false`. + * @property {boolean} useOnlyCssZoom - (optional) Enables CSS only zooming. + * The default value is `false`. + * @property {number} maxCanvasPixels - (optional) The maximum supported canvas + * size in total pixels, i.e. width * height. Use -1 for no limit. + * The default value is 4096 * 4096 (16 mega-pixels). + * @property {IL10n} l10n - Localization service. + */ + interface PDFViewerOptions { + container: HTMLDivElement; + viewer?: HTMLDivElement; + eventBus?: EventBus; + linkService?: IPDFLinkService; + downloadManager?: DownloadManager; + renderingQueue?: PDFRenderingQueue; + removePageBorders?: boolean; + textLayerMode?: TextLayerMode; + imageResourcesPath?: string; + renderInteractiveForms?: boolean; + enablePrintAutoRotate?: boolean; + renderer?: RendererType; + enableWebGL?: boolean; + useOnlyCssZoom?: boolean; + maxCanvasPixels?: number; + l10n?: IL10n; + } + + // + // web/text_layer_builder.js + // + + /** + * @typedef {Object} TextLayerBuilderOptions + * @property {HTMLDivElement} textLayerDiv - The text layer container. + * @property {EventBus} eventBus - The application event bus. + * @property {number} pageIndex - The page index. + * @property {PageViewport} viewport - The viewport of the text layer. + * @property {PDFFindController} findController + * @property {boolean} enhanceTextSelection - Option to turn on improved + * text selection. + */ + + interface TextLayerBuilderOptions { + textLayerDiv: HTMLDivElement; + eventBus: EventBus; + pageIndex: PageIndex; + viewport: PageViewport; + findController: PDFFindController; + enhanceTextSelection: boolean; + } + + /** + * The text layer builder provides text selection functionality for the PDF. + * It does this by creating overlay divs over the PDF's text. These divs + * contain text that matches the PDF text they are overlaying. This object + * also provides a way to highlight text that is being searched for. + */ + class TextLayerBuilder { + constructor(arg: TextLayerBuilderOptions); + textLayerDiv: HTMLDivElement; + eventBus: EventBus; + textContent: TextContent | null; + textContentItemsStr: string[]; + textContentStream: ReadableStream | null; + renderingDone: boolean; + pageIdx: PageIndex; + pageNumber: number; + matches: Match[]; + viewport: PageViewport; + textDivs: HTMLDivElement[]; + findController: PDFFindController; + textLayerRenderTask: TextLayerRenderTask | null; + enhanceTextSelection: boolean; + } + + interface TextPosition { + divIdx: number; + offset: number; + } + + interface Match { + begin: TextPosition; + end: TextPosition; + } + + /** + * @implements IPDFTextLayerFactory + */ + class DefaultTextLayerFactory implements IPDFTextLayerFactory { + /** + * @param {HTMLDivElement} textLayerDiv + * @param {number} pageIndex + * @param {PageViewport} viewport + * @param {boolean} enhanceTextSelection + * @returns {TextLayerBuilder} + */ + createTextLayerBuilder( + textLayerDiv: HTMLDivElement, + pageIndex: PageIndex, + viewport: PageViewport, + enhanceTextSelection?: boolean + ): TextLayerBuilder; + } + + // + // web/pdf_find_controller.js + // + + interface PDFFindControllerOptions { + pdfViewer: PDFViewer; + } + + interface FindCommandState { + query: string; + phraseSearch: boolean; + caseSensitive: boolean; + highlightAll: boolean; + findPrevious: boolean; + } + + class PDFFindController { + constructor(options: PDFFindControllerOptions); + reset(): void; + nextMatch(): void; + executeCommand(cmd: string, state: FindCommandState): void; + } + + // + // web/annotation_layer_builder.js + // + /** + * @typedef {Object} AnnotationLayerBuilderOptions + * @property {HTMLDivElement} pageDiv + * @property {PDFPage} pdfPage + * @property {boolean} renderInteractiveForms + * @property {IPDFLinkService} linkService + * @property {DownloadManager} downloadManager + * @property {IL10n} l10n - Localization service. + */ + + interface AnnotationLayerBuilderOptions { + AnnotationLayerBuilderOptions: Object; + pageDiv: HTMLDivElement; + pdfPage: PDFPageProxy; + renderInteractiveForms: boolean; + linkService: IPDFLinkService; + downloadManager: DownloadManager; + l10n: IL10n; + } + + class AnnotationLayerBuilder { + pageDiv: HTMLDivElement; + pdfPage: PDFPageProxy; + linkService: IPDFLinkService; + downloadManager: DownloadManager; + renderInteractiveForms: boolean; + l10n: IL10n; + div: HTMLDivElement | null; + + constructor(options: AnnotationLayerBuilderOptions); + + /** + * @param {PageViewport} viewport + * @param {string} intent (default value is 'display') + */ + render(viewport: PageViewport, intent?: string): void; + + cancel(): void; + hide(): void; + } + + /** + * @implements IPDFAnnotationLayerFactory + */ + class DefaultAnnotationLayerFactory implements IPDFAnnotationLayerFactory { + /** + * @param {HTMLDivElement} pageDiv + * @param {PDFPage} pdfPage + * @param {string} imageResourcesPath - (optional) Path for image resources, + * mainly for annotation icons. Include trailing slash. + * @param {boolean} renderInteractiveForms + * @param {IL10n} l10n + * @returns {AnnotationLayerBuilder} + */ + createAnnotationLayerBuilder( + pageDiv: HTMLDivElement, + pdfPage: PDFPageProxy, + imageResourcesPath?: string, + renderInteractiveForms?: boolean, + l10n?: IL10n + ): AnnotationLayerBuilder; + } + + // + // web/download_manager.js + // + interface DownloadManager { + downloadUrl(url: URL | string, filename: string): void; + downloadData(data: Uint8Array, filename: string, contentType: string): void; + download(blob: Blob, url: URL | string, filename: string): void; + } + + // + // web/pdf_page_view.js + // + interface PageView { + id: number; + x: number; + y: number; + view: PDFPageView; + } + + interface VisiblePages { + first: PDFPageView; + last: PDFPageView; + views: PDFPageView[]; + } + + /** + * @typedef {Object} PDFPageViewOptions + * @property {HTMLDivElement} container - The viewer element. + * @property {EventBus} eventBus - The application event bus. + * @property {number} id - The page unique ID (normally its number). + * @property {number} scale - The page scale display. + * @property {PageViewport} defaultViewport - The page viewport. + * @property {PDFRenderingQueue} renderingQueue - The rendering queue object. + * @property {IPDFTextLayerFactory} textLayerFactory + * @property {number} textLayerMode - (optional) Controls if the text layer used + * for selection and searching is created, and if the improved text selection + * behaviour is enabled. The constants from {TextLayerMode} should be used. + * The default value is `TextLayerMode.ENABLE`. + * @property {IPDFAnnotationLayerFactory} annotationLayerFactory + * @property {string} imageResourcesPath - (optional) Path for image resources, + * mainly for annotation icons. Include trailing slash. + * @property {boolean} renderInteractiveForms - Turns on rendering of + * interactive form elements. The default is `false`. + * @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'. + * @property {boolean} enableWebGL - (optional) Enables WebGL accelerated + * rendering for some operations. The default value is `false`. + * @property {boolean} useOnlyCssZoom - (optional) Enables CSS only zooming. + * The default value is `false`. + * @property {number} maxCanvasPixels - (optional) The maximum supported canvas + * size in total pixels, i.e. width * height. Use -1 for no limit. + * The default value is 4096 * 4096 (16 mega-pixels). + * @property {IL10n} l10n - Localization service. + */ + + interface PDFPageViewOptions { + container: HTMLDivElement; + eventBus: EventBus; + id: PageIndex; + scale: number; + defaultViewport: PageViewport; + renderingQueue: PDFRenderingQueue; + textLayerFactory: IPDFTextLayerFactory; + textLayerMode: TextLayerMode; + annotationLayerFactory: IPDFAnnotationLayerFactory; + imageResourcesPath?: string; + renderInteractiveForms: boolean; + renderer: RendererType; + enableWebGL?: boolean; + useOnlyCssZoom?: boolean; + maxCanvasPixels?: number; + l10n: IL10n; + } + + class PDFPageView { + id: PageIndex; + renderingId: string; + pdfPage: PDFPageProxy | null; + pageLabel: string | null; + rotation: number; + scale: number; + viewport: PageViewport; + pdfPageRotate: number; + hasRestrictedScaling: boolean; + enhanceTextSelection: boolean; + renderInteractiveForms: boolean; + eventBus: EventBus; + renderingQueue: PDFRenderingQueue; + textLayerFactory: IPDFTextLayerFactory; + annotationLayerFactory: IPDFAnnotationLayerFactory; + renderer: RendererType; + l10n: IL10n; + paintTask: RenderTask | null; + paintedViewportMap: WeakMap; + renderingState: RenderingStates; + resume: () => void | null; + error: Error | null; + onBeforeDraw: () => void | null; + onAfterDraw: () => void | null; + annotationLayer: AnnotationLayerBuilder | null; + textLayer: TextLayerBuilder | null; + zoomLayer: any | null; + div: HTMLDivElement; + + constructor(options: PDFPageViewOptions); + setPdfPage(pdfPage: PDFPageProxy): void; + destroy(): void; + reset(keepZoomLayer?: boolean, keepAnnotations?: boolean): void; + update(scale?: number, rotation?: number): void; + cancelRendering(keepAnnotations?: boolean): void; + cssTransform( + target: HTMLCanvasElement | SVGElement, + redrawAnnotations?: boolean + ): void; + width: number; + height: number; + getPagePoint(x: number, y: number): Point; + draw(): Promise; + paintOnCanvas(canvasWrapper: HTMLDivElement): RenderTask; + paintOnSvg(wrapper: HTMLDivElement): RenderTask; + /** + * @param {string|null} label + */ + setPageLabel(label: string | null): void; + } + + // + // web/pdf_viewer.js + // + class PDFViewer extends BaseViewer { + update(): void; + } + + // + // web/pdf_thumbnail_viewer.js + // + + /** + * @typedef {Object} PDFThumbnailViewerOptions + * @property {HTMLDivElement} container - The container for the thumbnail + * elements. + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {PDFRenderingQueue} renderingQueue - The rendering queue object. + * @property {IL10n} l10n - Localization service. + */ + interface PDFThumbnailViewerOptions { + container: HTMLDivElement; + linkService: IPDFLinkService; + renderingQueue: PDFRenderingQueue; + l10n: IL10n; + } + + class PDFThumbnailViewer { + container: HTMLDivElement; + linkService: IPDFLinkService; + renderingQueue: PDFRenderingQueue; + l10n: IL10n; + scroll: { + down: boolean; + lastY: number; + _eventHandler: (evt: any) => void; + }; + + constructor(options: PDFThumbnailViewerOptions); + getThumbnail(index: PageIndex): PDFThumbnailView; + scrollThumbnailIntoView(page: PageIndex): void; + pagesRotation: number; + cleanup(): void; + setDocument(pdfDocument: PDFDocumentProxy): void; + setPageLabels(labels: string[]): void; + forceRendering(): boolean; + } + + /** + * @typedef {Object} PDFThumbnailViewOptions + * @property {HTMLDivElement} container - The viewer element. + * @property {number} id - The thumbnail's unique ID (normally its number). + * @property {PageViewport} defaultViewport - The page viewport. + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {PDFRenderingQueue} renderingQueue - The rendering queue object. + * @property {boolean} disableCanvasToImageConversion - (optional) Don't convert + * the canvas thumbnails to images. This prevents `toDataURL` calls, + * but increases the overall memory usage. The default value is `false`. + * @property {IL10n} l10n - Localization service. + */ + interface PDFThumbnailViewOptions { + container: HTMLDivElement; + id: PageIndex; + defaultViewport: PageViewport; + linkService: IPDFLinkService; + renderingQueue: PDFRenderingQueue; + disableCanvasToImageConversion?: boolean; + l10n: IL10n; + } + + // + // web/pdf_thumbnail_view.js + // + class PDFThumbnailView { + id: PageIndex; + renderingId: string; + pageLabel: string | null; + pdfPage: PDFPageProxy | null; + rotation: number; + viewport: PageViewport; + pdfPageRotate: number; + linkService: IPDFLinkService; + renderingQueue: PDFRenderingQueue; + renderTask: RenderTask | null; + renderingState: RenderingStates; + resume: () => void | null; + disableCanvasToImageConversion: boolean; + pageWidth: number; + pageHeight: number; + pageRatio: number; + canvasWidth: number; + canvasHeight: number; + scale: number; + l10n: IL10n; + + // container > anchor > div.thumbnail[data-page-number=] > ring.thumbnailSelectionRing + anchor: HTMLAnchorElement; + div: HTMLDivElement; + ring: HTMLDivElement; + + constructor(options: PDFThumbnailViewerOptions); + setPdfPage(pdfPage: PDFPageProxy): void; + reset(): void; + update(rotation: number): void; + cancelRendering(): void; + draw(): Promise; + setImage(pageView: PageView): void; + readonly pageId: PageIndex; + setPageLabel(label: string | null): void; + static cleanup(): void; + } + + // + // web/pdf_history.js + // + + /** + * @typedef {Object} PDFHistoryOptions + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {EventBus} eventBus - The application event bus. + */ + interface PDFHistoryOptions { + linkService: IPDFLinkService; + eventBus?: EventBus; + } + + /** + * @typedef {Object} PushParameters + * @property {string} namedDest - (optional) The named destination. If absent, + * a stringified version of `explicitDest` is used. + * @property {Array} explicitDest - The explicit destination array. + * @property {number} pageNumber - The page to which the destination points. + */ + interface PushParameters { + namedDest: string; + explicitDest: Destination[]; + pageNumber: number; + } + + class PDFHistory { + linkService: IPDFLinkService; + eventBus: EventBus; + initialized: boolean; + initialBookmark: string | null; + initialRotation: number | null; + + constructor(options: PDFHistoryOptions); + + /** + * Initialize the history for the PDF document, using either the current + * browser history entry or the document hash, whichever is present. + * @param {string} fingerprint - The PDF document's unique fingerprint. + * @param {boolean} resetHistory - (optional) Reset the browsing history. + */ + initialize(fingerprint: string, resetHistory?: boolean): void; + + /** + * Push an internal destination to the browser history. + * @param {PushParameters} + */ + push(parameters: PushParameters): void; + + /** + * Push the current position to the browser history. + */ + pushCurrentPosition(): void; + + /** + * Go back one step in the browser history. + * NOTE: Avoids navigating away from the document, useful for "named actions". + */ + back(): void; + + /** + * Go forward one step in the browser history. + * NOTE: Avoids navigating away from the document, useful for "named actions". + */ + forward(): void; + + /** + * @returns {boolean} Indicating if the user is currently moving through the + * browser history, useful e.g. for skipping the next 'hashchange' event. + */ + readonly popStateInProgress: boolean; + } + + // + // web/pdf_single_page_viewer.js + // + class PDFSinglePageViewer extends BaseViewer { + constructor(options: PDFViewerOptions); + update(): void; + } + + // + // web/genericl10n.js + // + interface GenericL10n extends IL10n {} + + // Constructor function + let GenericL10n: new (lang: string) => GenericL10n; +} diff --git a/gulpfile.js b/gulpfile.js index 4d37837ddf20f..8671b366d3005 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1253,6 +1253,7 @@ gulp.task('dist-pre', type: 'git', url: DIST_REPO_URL, }, + types: 'types/pdf.d.ts', }; var packageJsonSrc = createStringSource('package.json', JSON.stringify(npmManifest, null, 2)); @@ -1270,6 +1271,8 @@ gulp.task('dist-pre', createStringSource('bower.json', JSON.stringify(bowerManifest, null, 2)); return merge([ + gulp.src('external/types/*.d.ts') + .pipe(gulp.dest(DIST_DIR + 'types/')), gulp.src('external/streams/streams-lib.js', { base: '.', }) .pipe(gulp.dest('build/dist/')), gulp.src('external/url/url-lib.js', { base: '.', }) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000000..d4319f17bd12e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "lib": [ + "es6" + ], + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true, + // "noUnusedLocals": true, + "strict": true + }, + "include": [ + "external/types" + ], + "exclude": [ + "node_modules", + "build" + ] +} \ No newline at end of file