Commit 26a12c9f authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Migrate pdf-metadata module to TS

parent 3b6697e8
...@@ -121,7 +121,7 @@ function elementContentRect(element: Element) { ...@@ -121,7 +121,7 @@ function elementContentRect(element: Element) {
function* textNodesInRect( function* textNodesInRect(
root: Element, root: Element,
rect: DOMRect, rect: DOMRect,
shouldVisit: (el: Element) => boolean = () => true shouldVisit: (el: Element) => boolean
): Generator<Text> { ): Generator<Text> {
let node: Node | null = root.firstChild; let node: Node | null = root.firstChild;
while (node) { while (node) {
......
import type { PDFViewerApplication } from '../../types/pdfjs';
import { normalizeURI } from '../util/url'; import { normalizeURI } from '../util/url';
/** type Link = { href: string };
* @typedef {import('../../types/pdfjs').PDFViewerApplication} PDFViewerApplication
*/
/** type Metadata = {
* @typedef Link /** The document title */
* @prop {string} href title: string;
*/ /** Array of URIs associated with this document */
link: Link[];
/** /**
* @typedef Metadata * The fingerprint of this PDF. This is referred to as the "File Identifier"
* @prop {string} title - The document title * in the PDF spec. It may be a hash of part of the content if the PDF file
* @prop {Link[]} link - Array of URIs associated with this document * does not have a File Identifier.
* @prop {string} documentFingerprint - The fingerprint of this PDF. This is
* referred to as the "File Identifier" in the PDF spec. It may be a hash of
* part of the content if the PDF file does not have a File Identifier.
* *
* PDFs may have two file identifiers. The first is the "original" identifier * PDFs may have two file identifiers. The first is the "original" identifier
* which is not supposed to change if the file is updated and the second * which is not supposed to change if the file is updated and the second
* one is the "last modified" identifier. This property is the original * one is the "last modified" identifier. This property is the original
* identifier. * identifier.
*/ */
documentFingerprint: string;
};
/** /**
* Wait for a PDFViewerApplication to be initialized. * Wait for a PDFViewerApplication to be initialized.
*
* @param {PDFViewerApplication} app
* @return {Promise<void>}
*/ */
function pdfViewerInitialized(app) { function pdfViewerInitialized(app: PDFViewerApplication): Promise<void> {
// `initializedPromise` was added in PDF.js v2.4.456. // `initializedPromise` was added in PDF.js v2.4.456.
// See https://github.com/mozilla/pdf.js/pull/11607. In earlier versions the // See https://github.com/mozilla/pdf.js/pull/11607. In earlier versions the
// `initialized` property can be queried. // `initialized` property can be queried.
...@@ -65,14 +61,15 @@ function pdfViewerInitialized(app) { ...@@ -65,14 +61,15 @@ function pdfViewerInitialized(app) {
* }) * })
*/ */
export class PDFMetadata { export class PDFMetadata {
private _loaded: Promise<PDFViewerApplication>;
/** /**
* Construct a `PDFMetadata` that returns URIs/metadata associated with a * Construct a `PDFMetadata` that returns URIs/metadata associated with a
* given PDF viewer. * given PDF viewer.
* *
* @param {PDFViewerApplication} app - The `PDFViewerApplication` global from PDF.js * @param app - The `PDFViewerApplication` global from PDF.js
*/ */
constructor(app) { constructor(app: PDFViewerApplication) {
/** @type {Promise<PDFViewerApplication>} */
this._loaded = pdfViewerInitialized(app).then(() => { this._loaded = pdfViewerInitialized(app).then(() => {
// Check if document has already loaded. // Check if document has already loaded.
if (app.downloadComplete) { if (app.downloadComplete) {
...@@ -115,10 +112,8 @@ export class PDFMetadata { ...@@ -115,10 +112,8 @@ export class PDFMetadata {
* *
* If the PDF is currently loading, the returned promise resolves once loading * If the PDF is currently loading, the returned promise resolves once loading
* is complete. * is complete.
*
* @return {Promise<string>}
*/ */
getUri() { getUri(): Promise<string> {
return this._loaded.then(app => { return this._loaded.then(app => {
let uri = getPDFURL(app); let uri = getPDFURL(app);
if (!uri) { if (!uri) {
...@@ -133,10 +128,8 @@ export class PDFMetadata { ...@@ -133,10 +128,8 @@ export class PDFMetadata {
* *
* If the PDF is currently loading, the returned promise resolves once loading * If the PDF is currently loading, the returned promise resolves once loading
* is complete. * is complete.
*
* @return {Promise<Metadata>}
*/ */
async getMetadata() { async getMetadata(): Promise<Metadata> {
const app = await this._loaded; const app = await this._loaded;
const { const {
info: documentInfo, info: documentInfo,
...@@ -157,7 +150,7 @@ export class PDFMetadata { ...@@ -157,7 +150,7 @@ export class PDFMetadata {
// This logic is similar to how PDF.js sets `document.title`. // This logic is similar to how PDF.js sets `document.title`.
let title; let title;
if (metadata?.has('dc:title') && metadata.get('dc:title') !== 'Untitled') { if (metadata?.has('dc:title') && metadata.get('dc:title') !== 'Untitled') {
title = /** @type {string} */ (metadata.get('dc:title')); title = metadata.get('dc:title');
} else if (documentInfo?.Title) { } else if (documentInfo?.Title) {
title = documentInfo.Title; title = documentInfo.Title;
} else if (contentDispositionFilename) { } else if (contentDispositionFilename) {
...@@ -183,32 +176,24 @@ export class PDFMetadata { ...@@ -183,32 +176,24 @@ export class PDFMetadata {
/** /**
* Get the fingerprint/file identifier of the currently loaded PDF. * Get the fingerprint/file identifier of the currently loaded PDF.
*
* @param {PDFViewerApplication} app
*/ */
function getFingerprint(app) { function getFingerprint(app: PDFViewerApplication): string {
if (Array.isArray(app.pdfDocument.fingerprints)) { if (Array.isArray(app.pdfDocument.fingerprints)) {
return app.pdfDocument.fingerprints[0]; return app.pdfDocument.fingerprints[0];
} else { } else {
return /** @type {string} */ (app.pdfDocument.fingerprint); return app.pdfDocument.fingerprint!;
} }
} }
/** /**
* Generate a URI from a PDF fingerprint suitable for storing as the main * Generate a URI from a PDF fingerprint suitable for storing as the main
* or associated URI of an annotation. * or associated URI of an annotation.
*
* @param {string} fingerprint
*/ */
function fingerprintToURN(fingerprint) { function fingerprintToURN(fingerprint: string) {
return `urn:x-pdf:${fingerprint}`; return `urn:x-pdf:${fingerprint}`;
} }
/** function getPDFURL(app: PDFViewerApplication): string | null {
* @param {PDFViewerApplication} app
* @return {string|null} - Valid URL string or `null`
*/
function getPDFURL(app) {
if (!app.url) { if (!app.url) {
return null; return null;
} }
...@@ -227,11 +212,8 @@ function getPDFURL(app) { ...@@ -227,11 +212,8 @@ function getPDFURL(app) {
/** /**
* Return the last component of the path part of a URL. * Return the last component of the path part of a URL.
*
* @param {string} url - A valid URL string
* @return {string}
*/ */
function filenameFromURL(url) { function filenameFromURL(url: string): string {
const parsed = new URL(url); const parsed = new URL(url);
const pathSegments = parsed.pathname.split('/'); const pathSegments = parsed.pathname.split('/');
return pathSegments[pathSegments.length - 1]; return pathSegments[pathSegments.length - 1];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment