1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-23 18:53:36 +02:00

Desktop: Resolves #10334: Support URLs in plugin API imaging.createFromPath

This commit is contained in:
Laurent Cozic 2024-04-27 11:35:49 +01:00
parent a0faca0997
commit 034e568d26
5 changed files with 80 additions and 26 deletions

View File

@ -47,6 +47,42 @@ const registerMakeThumbnailCommand = async () => {
await joplin.views.toolbarButtons.create('makeThumbnailButton', 'makeThumbnail', ToolbarButtonLocation.EditorToolbar);
};
const registerMakeThumbnailFromUrlCommand = async () => {
await joplin.commands.register({
name: 'makeThumbnailFromUrl',
execute: async () => {
const urls = [
'https://github.com/laurent22/joplin/blob/dev/Assets/ImageSources/RoundedCornersMac_1024x1024.png?raw=true',
'https://github.com/laurent22/joplin/blob/dev/packages/app-cli/tests/ocr_samples/multi_page__embedded_text.pdf?raw=true',
]
for (const url of urls) {
// ---------------------------------------------------------------
// Create an image from URLs
// ---------------------------------------------------------------
const imageHandle = await joplin.imaging.createFromPath(url);
const resizedImageHandle = await joplin.imaging.resize(imageHandle, { width: 100 });
// ---------------------------------------------------------------
// Convert the image to a resource and add it to the note
// ---------------------------------------------------------------
const newResource = await joplin.imaging.toJpgResource(resizedImageHandle, { title: "Thumbnail" });
await joplin.commands.execute('insertText', '\n![](:/' + newResource.id + ')');
// ---------------------------------------------------------------
// Free up the image objects at the end
// ---------------------------------------------------------------
await joplin.imaging.free(imageHandle);
await joplin.imaging.free(resizedImageHandle);
}
},
});
await joplin.views.toolbarButtons.create('makeThumbnailFromUrlButton', 'makeThumbnailFromUrl', ToolbarButtonLocation.EditorToolbar);
};
const registerInlinePdfCommand = async () => {
await joplin.commands.register({
@ -106,5 +142,6 @@ joplin.plugins.register({
onStart: async function() {
await registerMakeThumbnailCommand();
await registerInlinePdfCommand();
await registerMakeThumbnailFromUrlCommand();
},
});

View File

@ -8,7 +8,9 @@ import BasePlatformImplementation, { Joplin } from '@joplin/lib/services/plugins
import { CreateFromPdfOptions, Implementation as ImagingImplementation } from '@joplin/lib/services/plugins/api/JoplinImaging';
import shim from '@joplin/lib/shim';
import { join } from 'path';
import uuid from '@joplin/lib/uuid';
import uuid, { uuidgen } from '@joplin/lib/uuid';
import { hasProtocol } from '@joplin/utils/url';
import { fileExtension } from '@joplin/utils/path';
const { clipboard, nativeImage } = require('electron');
const packageInfo = require('../../packageInfo');
@ -97,24 +99,33 @@ export default class PlatformImplementation extends BasePlatformImplementation {
await shim.fsDriver().remove(tempDir);
}
};
return {
nativeImage: {
async createFromPath(path: string) {
if (path.toLowerCase().endsWith('.pdf')) {
const images = await createFromPdf(path, { minPage: 1, maxPage: 1 });
createFromPath: async (path: string) => {
let pathToProcess = path;
let ext = fileExtension(path).toLowerCase();
if (images.length === 0) {
// Match the behavior or Electron's nativeImage when reading an invalid image.
return nativeImage.createEmpty();
}
if (hasProtocol(path, ['http', 'https', 'file'])) {
ext = fileExtension((new URL(path)).pathname);
const tempFilePath = `${Setting.value('tempDir')}/${uuidgen()}${ext ? `.${ext}` : ''}`;
await shim.fetchBlob(path, { path: tempFilePath });
pathToProcess = tempFilePath;
}
return images[0];
} else {
return nativeImage.createFromPath(path);
if (ext === 'pdf') {
const images = await createFromPdf(pathToProcess, { minPage: 1, maxPage: 1 });
if (images.length === 0) {
// Match the behavior or Electron's nativeImage when reading an invalid image.
return nativeImage.createEmpty();
}
},
createFromPdf,
return images[0];
} else {
return nativeImage.createFromPath(pathToProcess);
}
},
createFromPdf,
getPdfInfo(path: string) {
return shim.pdfInfo(path);
},

View File

@ -6,7 +6,7 @@
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
TEMP_PATH=~/src/plugin-tests
NEED_COMPILING=1
PLUGIN_PATH=~/src/plugin-abc
PLUGIN_PATH=~/src/joplin/packages/app-cli/tests/support/plugins/imaging
if [[ $NEED_COMPILING == 1 ]]; then
mkdir -p "$TEMP_PATH"
@ -18,7 +18,7 @@ if [[ $NEED_COMPILING == 1 ]]; then
rsync -a --delete "$PLUGIN_PATH/" "$TEMP_PLUGIN_PATH/"
npm install --prefix="$TEMP_PLUGIN_PATH" && yarn start --dev-plugins "$TEMP_PLUGIN_PATH"
NODE_OPTIONS=--openssl-legacy-provider npm install --prefix="$TEMP_PLUGIN_PATH" && yarn start --dev-plugins "$TEMP_PLUGIN_PATH"
else
yarn start --dev-plugins "$PLUGIN_PATH"
fi

View File

@ -3,7 +3,7 @@ import { Implementation as WindowImplementation } from '@joplin/lib/services/plu
import Setting from '@joplin/lib/models/Setting';
import { reg } from '@joplin/lib/registry';
import BasePlatformImplementation, { Joplin } from '@joplin/lib/services/plugins/BasePlatformImplementation';
import { Implementation as ImagingImplementation } from '@joplin/lib/services/plugins/api/JoplinImaging';
import { CreateFromPdfOptions, Implementation as ImagingImplementation } from '@joplin/lib/services/plugins/api/JoplinImaging';
import RNVersionInfo from 'react-native-version-info';
import { _ } from '@joplin/lib/locale';
import shim from '@joplin/lib/shim';
@ -76,7 +76,12 @@ export default class PlatformImplementation extends BasePlatformImplementation {
public get imaging(): ImagingImplementation {
return {
nativeImage: null,
createFromPath: async (_path: string) => {
throw new Error('Not implemented: createFromPath');
},
createFromPdf: (_path: string, _options: CreateFromPdfOptions) => {
throw new Error('Not implemented: createFromPdf');
},
getPdfInfo: async () => {
throw new Error('Not implemented: getPdfInfo');
},

View File

@ -35,12 +35,8 @@ export interface PdfInfo {
}
export interface Implementation {
nativeImage: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
createFromPath: (path: string)=> Promise<any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
createFromPdf: (path: string, options: CreateFromPdfOptions)=> Promise<any[]>;
};
createFromPath: (path: string)=> Promise<unknown>;
createFromPdf: (path: string, options: CreateFromPdfOptions)=> Promise<unknown[]>;
getPdfInfo: (path: string)=> Promise<PdfInfo>;
}
@ -118,8 +114,13 @@ export default class JoplinImaging {
// return this.cacheImage(this.implementation_.nativeImage.createFromBuffer(buffer, options));
// }
/**
* Creates an image from the provided path. Note that images and PDFs are supported. If you
* provide a URL instead of a local path, the file will be downloaded first then converted to an
* image.
*/
public async createFromPath(filePath: string): Promise<Handle> {
return this.cacheImage(await this.implementation_.nativeImage.createFromPath(filePath));
return this.cacheImage(await this.implementation_.createFromPath(filePath));
}
public async createFromResource(resourceId: string): Promise<Handle> {
@ -127,7 +128,7 @@ export default class JoplinImaging {
}
public async createFromPdfPath(path: string, options?: CreateFromPdfOptions): Promise<Handle[]> {
const images = await this.implementation_.nativeImage.createFromPdf(path, options);
const images = await this.implementation_.createFromPdf(path, options);
return images.map(image => this.cacheImage(image));
}