Chore: Remove node-canvas
dependency (#12238)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
This commit is contained in:
parent
50c5139fa6
commit
5b2f409254
@ -1516,6 +1516,7 @@ packages/lib/utils/replaceUnsupportedCharacters.test.js
|
|||||||
packages/lib/utils/replaceUnsupportedCharacters.js
|
packages/lib/utils/replaceUnsupportedCharacters.js
|
||||||
packages/lib/utils/resolvePathWithinDir.test.js
|
packages/lib/utils/resolvePathWithinDir.test.js
|
||||||
packages/lib/utils/resolvePathWithinDir.js
|
packages/lib/utils/resolvePathWithinDir.js
|
||||||
|
packages/lib/utils/types/pdfJs.js
|
||||||
packages/lib/utils/userFetcher.js
|
packages/lib/utils/userFetcher.js
|
||||||
packages/lib/utils/webDAVUtils.test.js
|
packages/lib/utils/webDAVUtils.test.js
|
||||||
packages/lib/utils/webDAVUtils.js
|
packages/lib/utils/webDAVUtils.js
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1490,6 +1490,7 @@ packages/lib/utils/replaceUnsupportedCharacters.test.js
|
|||||||
packages/lib/utils/replaceUnsupportedCharacters.js
|
packages/lib/utils/replaceUnsupportedCharacters.js
|
||||||
packages/lib/utils/resolvePathWithinDir.test.js
|
packages/lib/utils/resolvePathWithinDir.test.js
|
||||||
packages/lib/utils/resolvePathWithinDir.js
|
packages/lib/utils/resolvePathWithinDir.js
|
||||||
|
packages/lib/utils/types/pdfJs.js
|
||||||
packages/lib/utils/userFetcher.js
|
packages/lib/utils/userFetcher.js
|
||||||
packages/lib/utils/webDAVUtils.test.js
|
packages/lib/utils/webDAVUtils.test.js
|
||||||
packages/lib/utils/webDAVUtils.js
|
packages/lib/utils/webDAVUtils.js
|
||||||
|
@ -11,9 +11,6 @@
|
|||||||
},
|
},
|
||||||
"nodejs": "latest",
|
"nodejs": "latest",
|
||||||
"pkg-config": "latest",
|
"pkg-config": "latest",
|
||||||
"pixman": "latest",
|
|
||||||
"cairo.dev": "",
|
|
||||||
"pango.dev": "",
|
|
||||||
"darwin.apple_sdk.frameworks.Foundation": { // satisfies missing CoreText/CoreText.h
|
"darwin.apple_sdk.frameworks.Foundation": { // satisfies missing CoreText/CoreText.h
|
||||||
// https://github.com/NixOS/nixpkgs/blob/master/pkgs/os-specific/darwin/apple-sdk/default.nix
|
// https://github.com/NixOS/nixpkgs/blob/master/pkgs/os-specific/darwin/apple-sdk/default.nix
|
||||||
"version": "",
|
"version": "",
|
||||||
@ -26,7 +23,6 @@
|
|||||||
"excluded_platforms": ["aarch64-darwin", "x86_64-darwin"],
|
"excluded_platforms": ["aarch64-darwin", "x86_64-darwin"],
|
||||||
},
|
},
|
||||||
"git": "latest",
|
"git": "latest",
|
||||||
"giflib": "latest",
|
|
||||||
},
|
},
|
||||||
"shell": {
|
"shell": {
|
||||||
"init_hook": [
|
"init_hook": [
|
||||||
|
@ -10,7 +10,7 @@ const React = require('react');
|
|||||||
|
|
||||||
require('../../jest.base-setup.js')();
|
require('../../jest.base-setup.js')();
|
||||||
|
|
||||||
shimInit({ sharp, nodeSqlite, pdfJs, React, appVersion: () => packageInfo.version });
|
shimInit({ pdfJs, sharp, nodeSqlite, React, appVersion: () => packageInfo.version });
|
||||||
|
|
||||||
global.afterEach(async () => {
|
global.afterEach(async () => {
|
||||||
await afterEachCleanUp();
|
await afterEachCleanUp();
|
||||||
|
@ -88,7 +88,6 @@ describe('OcrService', () => {
|
|||||||
// Use embedded text (skip OCR)
|
// Use embedded text (skip OCR)
|
||||||
['dummy.pdf', 'Dummy PDF file'],
|
['dummy.pdf', 'Dummy PDF file'],
|
||||||
['multi_page__embedded_text.pdf', 'This is a test.\nTesting...\nThis PDF has 3 pages.\nThis is page 3.'],
|
['multi_page__embedded_text.pdf', 'This is a test.\nTesting...\nThis PDF has 3 pages.\nThis is page 3.'],
|
||||||
['multi_page__no_embedded_text.pdf', 'This is a multi-page PDF\nwith no embedded text.\nPage 2: more text.\nThe third page.'],
|
|
||||||
])('should process PDF resources', async (samplePath: string, expectedText: string) => {
|
])('should process PDF resources', async (samplePath: string, expectedText: string) => {
|
||||||
const { resource } = await createNoteAndResource({ path: `${ocrSampleDir}/${samplePath}` });
|
const { resource } = await createNoteAndResource({ path: `${ocrSampleDir}/${samplePath}` });
|
||||||
|
|
||||||
|
@ -6,10 +6,8 @@ import Note from './models/Note';
|
|||||||
import Resource from './models/Resource';
|
import Resource from './models/Resource';
|
||||||
import { basename, fileExtension, safeFileExtension } from './path-utils';
|
import { basename, fileExtension, safeFileExtension } from './path-utils';
|
||||||
import * as fs from 'fs-extra';
|
import * as fs from 'fs-extra';
|
||||||
import * as pdfJsNamespace from 'pdfjs-dist';
|
|
||||||
import { writeFile } from 'fs/promises';
|
import { writeFile } from 'fs/promises';
|
||||||
import { ResourceEntity } from './services/database/types';
|
import { ResourceEntity } from './services/database/types';
|
||||||
import { TextItem } from 'pdfjs-dist/types/src/display/api';
|
|
||||||
import replaceUnsupportedCharacters from './utils/replaceUnsupportedCharacters';
|
import replaceUnsupportedCharacters from './utils/replaceUnsupportedCharacters';
|
||||||
import { FetchBlobOptions } from './types';
|
import { FetchBlobOptions } from './types';
|
||||||
import { fromFile as fileTypeFromFile } from 'file-type';
|
import { fromFile as fileTypeFromFile } from 'file-type';
|
||||||
@ -20,6 +18,7 @@ import * as mimeUtils from './mime-utils';
|
|||||||
import BaseItem from './models/BaseItem';
|
import BaseItem from './models/BaseItem';
|
||||||
import { Size } from '@joplin/utils/types';
|
import { Size } from '@joplin/utils/types';
|
||||||
import { cpus } from 'os';
|
import { cpus } from 'os';
|
||||||
|
import type PdfJs from './utils/types/pdfJs';
|
||||||
const { _ } = require('./locale');
|
const { _ } = require('./locale');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
@ -111,7 +110,7 @@ interface ShimInitOptions {
|
|||||||
electronBridge: any;
|
electronBridge: any;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||||
nodeSqlite: any;
|
nodeSqlite: any;
|
||||||
pdfJs: typeof pdfJsNamespace;
|
pdfJs: PdfJs;
|
||||||
isAppleSilicon?: ()=> boolean;
|
isAppleSilicon?: ()=> boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -823,7 +822,7 @@ function shimInit(options: ShimInitOptions = null) {
|
|||||||
const textContent = await page.getTextContent();
|
const textContent = await page.getTextContent();
|
||||||
|
|
||||||
const strings = textContent.items.map(item => {
|
const strings = textContent.items.map(item => {
|
||||||
const text = (item as TextItem).str ?? '';
|
const text = item.str ?? '';
|
||||||
return text;
|
return text;
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
|
|
||||||
@ -839,32 +838,24 @@ function shimInit(options: ShimInitOptions = null) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
shim.pdfToImages = async (pdfPath: string, outputDirectoryPath: string, options?: CreatePdfFromImagesOptions): Promise<string[]> => {
|
shim.pdfToImages = async (pdfPath: string, outputDirectoryPath: string, options?: CreatePdfFromImagesOptions): Promise<string[]> => {
|
||||||
// We handle both the Electron app and testing framework. Potentially
|
if (typeof HTMLCanvasElement === 'undefined') {
|
||||||
// the same code could be use to support the CLI app.
|
throw new Error('Unsupported -- the Canvas element is required.');
|
||||||
const isTesting = !shim.isElectron();
|
}
|
||||||
|
|
||||||
const createCanvas = () => {
|
const createCanvas = () => {
|
||||||
if (isTesting) {
|
|
||||||
return require('canvas').createCanvas();
|
|
||||||
}
|
|
||||||
return document.createElement('canvas');
|
return document.createElement('canvas');
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
const canvasToBuffer = async (canvas: HTMLCanvasElement): Promise<Buffer> => {
|
||||||
const canvasToBuffer = async (canvas: any): Promise<Buffer> => {
|
|
||||||
const quality = 0.8;
|
const quality = 0.8;
|
||||||
if (isTesting) {
|
const canvasToBlob = async (canvas: HTMLCanvasElement): Promise<Blob> => {
|
||||||
return canvas.toBuffer('image/jpeg', { quality });
|
return new Promise(resolve => {
|
||||||
} else {
|
canvas.toBlob(blob => resolve(blob), 'image/jpg', quality);
|
||||||
const canvasToBlob = async (canvas: HTMLCanvasElement): Promise<Blob> => {
|
});
|
||||||
return new Promise(resolve => {
|
};
|
||||||
canvas.toBlob(blob => resolve(blob), 'image/jpg', quality);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const blob = await canvasToBlob(canvas);
|
const blob = await canvasToBlob(canvas);
|
||||||
return Buffer.from(await blob.arrayBuffer());
|
return Buffer.from(await blob.arrayBuffer());
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const filePrefix = `page_${Date.now()}`;
|
const filePrefix = `page_${Date.now()}`;
|
||||||
@ -879,6 +870,9 @@ function shimInit(options: ShimInitOptions = null) {
|
|||||||
const viewport = page.getViewport({ scale: options?.scaleFactor ?? 2 });
|
const viewport = page.getViewport({ scale: options?.scaleFactor ?? 2 });
|
||||||
const canvas = createCanvas();
|
const canvas = createCanvas();
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
if (!ctx) {
|
||||||
|
throw new Error('Unable to get 2D rendering context from canvas.');
|
||||||
|
}
|
||||||
|
|
||||||
canvas.height = viewport.height;
|
canvas.height = viewport.height;
|
||||||
canvas.width = viewport.width;
|
canvas.width = viewport.width;
|
||||||
|
6
packages/lib/utils/types/pdfJs.js
Normal file
6
packages/lib/utils/types/pdfJs.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
"use strict";
|
||||||
|
// Custom type definitions for pdfjs-dist. packages/lib should avoid depending on
|
||||||
|
// pdfjs-dist directly, since an unpatched version of pdfjs-dist depends on node-canvas,
|
||||||
|
// which makes it more difficult to build Joplin.
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
//# sourceMappingURL=pdfJs.js.map
|
48
packages/lib/utils/types/pdfJs.ts
Normal file
48
packages/lib/utils/types/pdfJs.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
// Custom type definitions for pdfjs-dist. packages/lib should avoid depending on
|
||||||
|
// pdfjs-dist directly, since an unpatched version of pdfjs-dist depends on node-canvas,
|
||||||
|
// which makes it more difficult to build Joplin.
|
||||||
|
|
||||||
|
interface PdfTextContent {
|
||||||
|
items: { str?: string }[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Viewport {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RenderOptions {
|
||||||
|
canvasContext: CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D;
|
||||||
|
viewport: Viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PdfPage {
|
||||||
|
getViewport(options: { scale: number }): Viewport;
|
||||||
|
render(options: RenderOptions): { promise: Promise<void> };
|
||||||
|
getTextContent(): Promise<PdfTextContent>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PdfDocument {
|
||||||
|
numPages: number;
|
||||||
|
getPage(n: number): Promise<PdfPage>;
|
||||||
|
destroy(): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GetDocumentTask {
|
||||||
|
promise: Promise<PdfDocument>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GetDocumentOptions {
|
||||||
|
url: string;
|
||||||
|
useSystemFonts: boolean;
|
||||||
|
// IMPORTANT: Set to false to mitigate CVE-2024-4367.
|
||||||
|
isEvalSupported: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PdfJs {
|
||||||
|
getDocument(options: GetDocumentOptions): GetDocumentTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PdfJs;
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user