mirror of
https://github.com/laurent22/joplin.git
synced 2024-11-27 08:21:03 +02:00
parent
a6caa357c8
commit
eb82ae87ca
@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { useState, useEffect, useCallback, useRef, forwardRef, useImperativeHandle } from 'react';
|
||||
import { ScrollOptions, ScrollOptionTypes, EditorCommand, NoteBodyEditorProps } from '../../utils/types';
|
||||
import { resourcesStatus, commandAttachFileToBody, handlePasteEvent } from '../../utils/resourceHandling';
|
||||
import { resourcesStatus, commandAttachFileToBody, handlePasteEvent, processPastedHtml } from '../../utils/resourceHandling';
|
||||
import useScroll from './utils/useScroll';
|
||||
import styles_ from './styles';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
@ -1032,6 +1032,14 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
// HACK: TinyMCE doesn't add an undo step when pasting, for unclear reasons
|
||||
// so we manually add it here. We also can't do it immediately it seems, or
|
||||
// else nothing is added to the stack, so do it on the next frame.
|
||||
|
||||
const pastedHtml = clipboard.readHTML();
|
||||
if (pastedHtml) {
|
||||
event.preventDefault();
|
||||
const modifiedHtml = await processPastedHtml(pastedHtml);
|
||||
editor.insertContent(modifiedHtml);
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(() => editor.undoManager.add());
|
||||
onChangeHandler();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ const bridge = require('electron').remote.require('./bridge').default;
|
||||
const Menu = bridge().Menu;
|
||||
const MenuItem = bridge().MenuItem;
|
||||
import Resource from '@joplin/lib/models/Resource';
|
||||
import { processPastedHtml } from './resourceHandling';
|
||||
const fs = require('fs-extra');
|
||||
const { clipboard } = require('electron');
|
||||
const { toSystemSlashes } = require('@joplin/lib/path-utils');
|
||||
@ -112,7 +113,13 @@ export function menuItems(): ContextMenuItems {
|
||||
paste: {
|
||||
label: _('Paste'),
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
const content = clipboard.readHTML() ? clipboard.readHTML() : clipboard.readText();
|
||||
const pastedHtml = clipboard.readHTML();
|
||||
let content = pastedHtml ? pastedHtml : clipboard.readText();
|
||||
|
||||
if (pastedHtml) {
|
||||
content = await processPastedHtml(pastedHtml);
|
||||
}
|
||||
|
||||
options.insertContent(content);
|
||||
},
|
||||
isActive: (_itemType: ContextMenuItemType, options: ContextMenuOptions) => !options.isReadOnly && (!!clipboard.readText() || !!clipboard.readHTML()),
|
||||
|
@ -6,10 +6,13 @@ import Resource from '@joplin/lib/models/Resource';
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
import htmlUtils from '@joplin/lib/htmlUtils';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
const joplinRendererUtils = require('@joplin/renderer').utils;
|
||||
const { clipboard } = require('electron');
|
||||
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
|
||||
const md5 = require('md5');
|
||||
const path = require('path');
|
||||
|
||||
export async function handleResourceDownloadMode(noteBody: string) {
|
||||
if (noteBody && Setting.value('sync.resourceDownloadMode') === 'auto') {
|
||||
@ -125,3 +128,44 @@ export async function handlePasteEvent(event: any) {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
export async function processPastedHtml(html: string) {
|
||||
const allImageUrls: string[] = [];
|
||||
const mappedResources: Record<string, string> = {};
|
||||
|
||||
htmlUtils.replaceImageUrls(html, (src: string) => {
|
||||
allImageUrls.push(src);
|
||||
});
|
||||
|
||||
for (const imageSrc of allImageUrls) {
|
||||
if (!mappedResources[imageSrc]) {
|
||||
try {
|
||||
if (imageSrc.startsWith('file')) {
|
||||
const imageFilePath = path.normalize(imageSrc.substr(7));
|
||||
const resourceDirPath = path.normalize(Setting.value('resourceDir'));
|
||||
|
||||
if (imageFilePath.startsWith(resourceDirPath)) {
|
||||
mappedResources[imageSrc] = imageSrc;
|
||||
} else {
|
||||
const createdResource = await shim.createResourceFromPath(imageFilePath);
|
||||
mappedResources[imageSrc] = `file://${Resource.fullPath(createdResource)}`;
|
||||
}
|
||||
} else {
|
||||
const filePath = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}`;
|
||||
await shim.fetchBlob(imageSrc, { path: filePath });
|
||||
const createdResource = await shim.createResourceFromPath(filePath);
|
||||
await shim.fsDriver().remove(filePath);
|
||||
mappedResources[imageSrc] = `file://${Resource.fullPath(createdResource)}`;
|
||||
}
|
||||
} catch (err) {
|
||||
const logger = Logger.create('resourceHandling');
|
||||
logger.warn(`Error creating a resource for ${imageSrc}.`, err);
|
||||
mappedResources[imageSrc] = imageSrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return htmlUtils.replaceImageUrls(html, (src: string) => {
|
||||
return mappedResources[src];
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user