mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop: Fixes #5693: Opening a file with ctrl and click leads to an error in the Rich Text editor
This commit is contained in:
parent
73737ce776
commit
0e11273c45
@ -23,9 +23,9 @@
|
|||||||
"dependencyTree": "madge",
|
"dependencyTree": "madge",
|
||||||
"generateDatabaseTypes": "node packages/tools/generate-database-types",
|
"generateDatabaseTypes": "node packages/tools/generate-database-types",
|
||||||
"linkChecker": "linkchecker https://joplinapp.org",
|
"linkChecker": "linkchecker https://joplinapp.org",
|
||||||
"linter-ci": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
|
"linter-ci": "eslint --resolve-plugins-relative-to . --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||||
"linter-precommit": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --fix --ext .js --ext .jsx --ext .ts --ext .tsx",
|
"linter-precommit": "eslint --resolve-plugins-relative-to . --fix --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||||
"linter": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
|
"linter": "eslint --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||||
"postinstall": "npm run bootstrap --no-ci && npm run build",
|
"postinstall": "npm run bootstrap --no-ci && npm run build",
|
||||||
"publishAll": "git pull && npm run build && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
|
"publishAll": "git pull && npm run build && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
|
||||||
"releaseAndroid": "npm run build && export PATH=\"/usr/local/opt/openjdk@11/bin:$PATH\" && node packages/tools/release-android.js",
|
"releaseAndroid": "npm run build && export PATH=\"/usr/local/opt/openjdk@11/bin:$PATH\" && node packages/tools/release-android.js",
|
||||||
|
@ -7,12 +7,12 @@ const bridge = require('@electron/remote').require('./bridge').default;
|
|||||||
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
||||||
import htmlUtils from '@joplin/lib/htmlUtils';
|
import htmlUtils from '@joplin/lib/htmlUtils';
|
||||||
import Logger from '@joplin/lib/Logger';
|
import Logger from '@joplin/lib/Logger';
|
||||||
|
const { fileUriToPath } = require('@joplin/lib/urlUtils');
|
||||||
const joplinRendererUtils = require('@joplin/renderer').utils;
|
const joplinRendererUtils = require('@joplin/renderer').utils;
|
||||||
const { clipboard } = require('electron');
|
const { clipboard } = require('electron');
|
||||||
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
|
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
|
||||||
const md5 = require('md5');
|
const md5 = require('md5');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const uri2path = require('file-uri-to-path');
|
|
||||||
|
|
||||||
const logger = Logger.create('resourceHandling');
|
const logger = Logger.create('resourceHandling');
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ export async function processPastedHtml(html: string) {
|
|||||||
if (!mappedResources[imageSrc]) {
|
if (!mappedResources[imageSrc]) {
|
||||||
try {
|
try {
|
||||||
if (imageSrc.startsWith('file')) {
|
if (imageSrc.startsWith('file')) {
|
||||||
const imageFilePath = path.normalize(uri2path(imageSrc));
|
const imageFilePath = path.normalize(fileUriToPath(imageSrc));
|
||||||
const resourceDirPath = path.normalize(Setting.value('resourceDir'));
|
const resourceDirPath = path.normalize(Setting.value('resourceDir'));
|
||||||
|
|
||||||
if (imageFilePath.startsWith(resourceDirPath)) {
|
if (imageFilePath.startsWith(resourceDirPath)) {
|
||||||
|
@ -4,12 +4,12 @@ import contextMenu, { openItemById } from './contextMenu';
|
|||||||
import { _ } from '@joplin/lib/locale';
|
import { _ } from '@joplin/lib/locale';
|
||||||
import CommandService from '@joplin/lib/services/CommandService';
|
import CommandService from '@joplin/lib/services/CommandService';
|
||||||
import PostMessageService from '@joplin/lib/services/PostMessageService';
|
import PostMessageService from '@joplin/lib/services/PostMessageService';
|
||||||
|
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
||||||
|
import { reg } from '@joplin/lib/registry';
|
||||||
const bridge = require('@electron/remote').require('./bridge').default;
|
const bridge = require('@electron/remote').require('./bridge').default;
|
||||||
const { urlDecode } = require('@joplin/lib/string-utils');
|
const { urlDecode } = require('@joplin/lib/string-utils');
|
||||||
const urlUtils = require('@joplin/lib/urlUtils');
|
const urlUtils = require('@joplin/lib/urlUtils');
|
||||||
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
const { fileUriToPath } = require('@joplin/lib/urlUtils');
|
||||||
import { reg } from '@joplin/lib/registry';
|
|
||||||
const uri2path = require('file-uri-to-path');
|
|
||||||
|
|
||||||
export default function useMessageHandler(scrollWhenReady: any, setScrollWhenReady: Function, editorRef: any, setLocalSearchResultCount: Function, dispatch: Function, formNote: FormNote) {
|
export default function useMessageHandler(scrollWhenReady: any, setScrollWhenReady: Function, editorRef: any, setLocalSearchResultCount: Function, dispatch: Function, formNote: FormNote) {
|
||||||
return useCallback(async (event: any) => {
|
return useCallback(async (event: any) => {
|
||||||
@ -17,7 +17,7 @@ export default function useMessageHandler(scrollWhenReady: any, setScrollWhenRea
|
|||||||
const args = event.args;
|
const args = event.args;
|
||||||
const arg0 = args && args.length >= 1 ? args[0] : null;
|
const arg0 = args && args.length >= 1 ? args[0] : null;
|
||||||
|
|
||||||
// if (msg !== 'percentScroll') console.info(`Got ipc-message: ${msg}`, arg0);
|
if (msg !== 'percentScroll') console.info(`Got ipc-message: ${msg}`, arg0);
|
||||||
|
|
||||||
if (msg.indexOf('error:') === 0) {
|
if (msg.indexOf('error:') === 0) {
|
||||||
const s = msg.split(':');
|
const s = msg.split(':');
|
||||||
@ -58,7 +58,7 @@ export default function useMessageHandler(scrollWhenReady: any, setScrollWhenRea
|
|||||||
// shell.openPath seems to work with file:// urls on Windows,
|
// shell.openPath seems to work with file:// urls on Windows,
|
||||||
// but doesn't on macOS, so we need to convert it to a path
|
// but doesn't on macOS, so we need to convert it to a path
|
||||||
// before passing it to openPath.
|
// before passing it to openPath.
|
||||||
const decodedPath = uri2path(urlDecode(msg));
|
const decodedPath = fileUriToPath(urlDecode(msg));
|
||||||
require('electron').shell.openPath(decodedPath);
|
require('electron').shell.openPath(decodedPath);
|
||||||
} else {
|
} else {
|
||||||
require('electron').shell.openExternal(msg);
|
require('electron').shell.openExternal(msg);
|
||||||
|
468
packages/app-desktop/package-lock.json
generated
468
packages/app-desktop/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -146,7 +146,6 @@
|
|||||||
"countable": "^3.0.1",
|
"countable": "^3.0.1",
|
||||||
"debounce": "^1.2.0",
|
"debounce": "^1.2.0",
|
||||||
"electron-window-state": "^4.1.1",
|
"electron-window-state": "^4.1.1",
|
||||||
"file-uri-to-path": "^2.0.0",
|
|
||||||
"formatcoords": "^1.1.3",
|
"formatcoords": "^1.1.3",
|
||||||
"fs-extra": "^5.0.0",
|
"fs-extra": "^5.0.0",
|
||||||
"highlight.js": "^10.2.1",
|
"highlight.js": "^10.2.1",
|
||||||
|
15
packages/lib/package-lock.json
generated
15
packages/lib/package-lock.json
generated
@ -21,7 +21,7 @@
|
|||||||
"diff-match-patch": "^1.0.4",
|
"diff-match-patch": "^1.0.4",
|
||||||
"es6-promise-pool": "^2.5.0",
|
"es6-promise-pool": "^2.5.0",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"file-uri-to-path": "^1.0.0",
|
"file-uri-to-path": "^2.0.0",
|
||||||
"follow-redirects": "^1.2.4",
|
"follow-redirects": "^1.2.4",
|
||||||
"form-data": "^2.1.4",
|
"form-data": "^2.1.4",
|
||||||
"fs-extra": "^5.0.0",
|
"fs-extra": "^5.0.0",
|
||||||
@ -2955,8 +2955,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/file-uri-to-path": {
|
"node_modules/file-uri-to-path": {
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
@ -10668,8 +10672,9 @@
|
|||||||
"integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw=="
|
"integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw=="
|
||||||
},
|
},
|
||||||
"file-uri-to-path": {
|
"file-uri-to-path": {
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg=="
|
||||||
},
|
},
|
||||||
"fill-range": {
|
"fill-range": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
"diff-match-patch": "^1.0.4",
|
"diff-match-patch": "^1.0.4",
|
||||||
"es6-promise-pool": "^2.5.0",
|
"es6-promise-pool": "^2.5.0",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"file-uri-to-path": "^1.0.0",
|
"file-uri-to-path": "^2.0.0",
|
||||||
"follow-redirects": "^1.2.4",
|
"follow-redirects": "^1.2.4",
|
||||||
"form-data": "^2.1.4",
|
"form-data": "^2.1.4",
|
||||||
"fs-extra": "^5.0.0",
|
"fs-extra": "^5.0.0",
|
||||||
|
@ -25,7 +25,7 @@ const urlUtils = require('../../../urlUtils.js');
|
|||||||
const ArrayUtils = require('../../../ArrayUtils.js');
|
const ArrayUtils = require('../../../ArrayUtils.js');
|
||||||
const { mimeTypeFromHeaders } = require('../../../net-utils');
|
const { mimeTypeFromHeaders } = require('../../../net-utils');
|
||||||
const { fileExtension, safeFileExtension, safeFilename, filename } = require('../../../path-utils');
|
const { fileExtension, safeFileExtension, safeFilename, filename } = require('../../../path-utils');
|
||||||
const uri2path = require('file-uri-to-path');
|
const { fileUriToPath } = require('../../../urlUtils');
|
||||||
const { MarkupToHtml } = require('@joplin/renderer');
|
const { MarkupToHtml } = require('@joplin/renderer');
|
||||||
const { ErrorNotFound } = require('../utils/errors');
|
const { ErrorNotFound } = require('../utils/errors');
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ async function downloadImage(url: string /* , allowFileProtocolImages */) {
|
|||||||
} else if (urlUtils.urlProtocol(url).toLowerCase() === 'file:') {
|
} else if (urlUtils.urlProtocol(url).toLowerCase() === 'file:') {
|
||||||
// Can't think of any reason to disallow this at this point
|
// Can't think of any reason to disallow this at this point
|
||||||
// if (!allowFileProtocolImages) throw new Error('For security reasons, this URL with file:// protocol cannot be downloaded');
|
// if (!allowFileProtocolImages) throw new Error('For security reasons, this URL with file:// protocol cannot be downloaded');
|
||||||
const localPath = uri2path(url);
|
const localPath = fileUriToPath(url);
|
||||||
await shim.fsDriver().copy(localPath, imagePath);
|
await shim.fsDriver().copy(localPath, imagePath);
|
||||||
} else {
|
} else {
|
||||||
const response = await shim.fetchBlob(url, { path: imagePath, maxRetry: 1 });
|
const response = await shim.fetchBlob(url, { path: imagePath, maxRetry: 1 });
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const { rtrimSlashes } = require('./path-utils');
|
const { rtrimSlashes } = require('./path-utils');
|
||||||
const { urlDecode } = require('./string-utils');
|
const { urlDecode } = require('./string-utils');
|
||||||
|
const fileUriToPath = require('file-uri-to-path');
|
||||||
|
|
||||||
const urlUtils = {};
|
const urlUtils = {};
|
||||||
|
|
||||||
@ -105,4 +106,34 @@ urlUtils.objectToQueryString = function(query) {
|
|||||||
return queryString;
|
return queryString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
urlUtils.fileUriToPath = (path) => {
|
||||||
|
const output = fileUriToPath(path);
|
||||||
|
|
||||||
|
// The file-uri-to-path module converts Windows path such as
|
||||||
|
//
|
||||||
|
// file://c:/autoexec.bat => \\c:\autoexec.bat
|
||||||
|
//
|
||||||
|
// Probably because a file:// that starts with only two slashes is not
|
||||||
|
// quite valid. If we use three slashes, it works:
|
||||||
|
//
|
||||||
|
// file:///c:/autoexec.bat => c:\autoexec.bat
|
||||||
|
//
|
||||||
|
// However there are various places in the app where we can find
|
||||||
|
// paths with only two slashes because paths are often constructed
|
||||||
|
// as `file://${resourcePath}` - which works in all OSes except
|
||||||
|
// Windows.
|
||||||
|
//
|
||||||
|
// So here we introduce a special case - if we detect that we have
|
||||||
|
// an invalid Windows path that starts with \\x:, we just remove
|
||||||
|
// the first two backslashes.
|
||||||
|
//
|
||||||
|
// https://github.com/laurent22/joplin/issues/5693
|
||||||
|
|
||||||
|
if (output.match(/^\\\\[a-zA-Z]:/)) {
|
||||||
|
return output.substr(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = urlUtils;
|
module.exports = urlUtils;
|
||||||
|
@ -71,4 +71,13 @@ describe('urlUtils', function() {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should convert a file URI to a file path', (async () => {
|
||||||
|
// This function is a wrapper around the file-uri-to-path module,
|
||||||
|
// with a fix for the Windows paths. We assume that the wrapped
|
||||||
|
// function works so we don't test everything, only the cases
|
||||||
|
// specific to our wrapper.
|
||||||
|
expect(urlUtils.fileUriToPath('file://c:/not/quite/right')).toBe('c:\\not\\quite\\right');
|
||||||
|
expect(urlUtils.fileUriToPath('file:///d:/better')).toBe('d:\\better');
|
||||||
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user