mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Merge branch 'release-2.12' into dev
This commit is contained in:
commit
13b7e3657b
@ -133,6 +133,7 @@ packages/app-desktop/gui/ClipperConfigScreen.js
|
|||||||
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
|
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
|
||||||
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
|
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
|
||||||
packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
||||||
|
packages/app-desktop/gui/ConfigScreen/controls/MissingPasswordHelpLink.js
|
||||||
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
|
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
|
||||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
||||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -119,6 +119,7 @@ packages/app-desktop/gui/ClipperConfigScreen.js
|
|||||||
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
|
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
|
||||||
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
|
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
|
||||||
packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
||||||
|
packages/app-desktop/gui/ConfigScreen/controls/MissingPasswordHelpLink.js
|
||||||
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
|
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
|
||||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
||||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
],
|
],
|
||||||
"owner": "Laurent Cozic"
|
"owner": "Laurent Cozic"
|
||||||
},
|
},
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"bin": "./main.js",
|
"bin": "./main.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
|
@ -21,8 +21,7 @@ import getDefaultPluginsInfo from '@joplin/lib/services/plugins/defaultPlugins/d
|
|||||||
import JoplinCloudConfigScreen from '../JoplinCloudConfigScreen';
|
import JoplinCloudConfigScreen from '../JoplinCloudConfigScreen';
|
||||||
import ToggleAdvancedSettingsButton from './controls/ToggleAdvancedSettingsButton';
|
import ToggleAdvancedSettingsButton from './controls/ToggleAdvancedSettingsButton';
|
||||||
import shouldShowMissingPasswordWarning from '@joplin/lib/components/shared/config/shouldShowMissingPasswordWarning';
|
import shouldShowMissingPasswordWarning from '@joplin/lib/components/shared/config/shouldShowMissingPasswordWarning';
|
||||||
import shim from '@joplin/lib/shim';
|
import MacOSMissingPasswordHelpLink from './controls/MissingPasswordHelpLink';
|
||||||
import StyledLink from '../style/StyledLink';
|
|
||||||
const { KeymapConfigScreen } = require('../KeymapConfig/KeymapConfigScreen');
|
const { KeymapConfigScreen } = require('../KeymapConfig/KeymapConfigScreen');
|
||||||
|
|
||||||
const settingKeyToControl: any = {
|
const settingKeyToControl: any = {
|
||||||
@ -190,25 +189,14 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
|||||||
// saved yet).
|
// saved yet).
|
||||||
const matchesSavedTarget = settings['sync.target'] === this.props.settings['sync.target'];
|
const matchesSavedTarget = settings['sync.target'] === this.props.settings['sync.target'];
|
||||||
if (matchesSavedTarget && shouldShowMissingPasswordWarning(settings['sync.target'], settings)) {
|
if (matchesSavedTarget && shouldShowMissingPasswordWarning(settings['sync.target'], settings)) {
|
||||||
const openMissingPasswordFAQ = () =>
|
|
||||||
bridge().openExternal('https://joplinapp.org/faq#why-did-my-sync-and-encryption-passwords-disappear-after-updating-joplin');
|
|
||||||
|
|
||||||
const macInfoLink = (
|
|
||||||
<StyledLink href="#"
|
|
||||||
onClick={openMissingPasswordFAQ}
|
|
||||||
style={theme.linkStyle}
|
|
||||||
>
|
|
||||||
{_('Help')}
|
|
||||||
</StyledLink>
|
|
||||||
);
|
|
||||||
|
|
||||||
// The FAQ section related to missing passwords is specific to MacOS/ARM -- only show it
|
|
||||||
// in that case.
|
|
||||||
const showMacInfoLink = shim.isMac() && process.arch === 'arm64';
|
|
||||||
|
|
||||||
settingComps.push(
|
settingComps.push(
|
||||||
<p key='missing-password-warning' style={warningStyle}>
|
<p key='missing-password-warning' style={warningStyle}>
|
||||||
{_('Warning: Missing password.')}{' '}{showMacInfoLink ? macInfoLink : null}
|
{_('%s: Missing password.', _('Warning'))}
|
||||||
|
{' '}
|
||||||
|
<MacOSMissingPasswordHelpLink
|
||||||
|
theme={theme}
|
||||||
|
text={_('Help')}
|
||||||
|
/>
|
||||||
</p>,
|
</p>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import shim from '@joplin/lib/shim';
|
||||||
|
import bridge from '../../../services/bridge';
|
||||||
|
import StyledLink from '../../style/StyledLink';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
theme: any;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const openMissingPasswordFAQ = () =>
|
||||||
|
bridge().openExternal('https://joplinapp.org/faq#why-did-my-sync-and-encryption-passwords-disappear-after-updating-joplin');
|
||||||
|
|
||||||
|
// A link to a specific part of the FAQ related to passwords being cleared when upgrading
|
||||||
|
// to a MacOS/ARM release.
|
||||||
|
const MacOSMissingPasswordHelpLink: React.FunctionComponent<Props> = props => {
|
||||||
|
const macInfoLink = (
|
||||||
|
<StyledLink href="#"
|
||||||
|
onClick={openMissingPasswordFAQ}
|
||||||
|
style={props.theme.linkStyle}
|
||||||
|
>
|
||||||
|
{props.text}
|
||||||
|
</StyledLink>
|
||||||
|
);
|
||||||
|
|
||||||
|
// The FAQ section related to missing passwords is specific to MacOS/ARM -- only show it
|
||||||
|
// in that case.
|
||||||
|
const newArchitectureReleasedRecently = Date.now() <= Date.UTC(2023, 11); // 11 = December
|
||||||
|
const showMacInfoLink = shim.isMac() && process.arch === 'arm64' && newArchitectureReleasedRecently;
|
||||||
|
|
||||||
|
return showMacInfoLink ? macInfoLink : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MacOSMissingPasswordHelpLink;
|
@ -17,6 +17,7 @@ import Setting from '@joplin/lib/models/Setting';
|
|||||||
import CommandService from '@joplin/lib/services/CommandService';
|
import CommandService from '@joplin/lib/services/CommandService';
|
||||||
import { PublicPrivateKeyPair } from '@joplin/lib/services/e2ee/ppk';
|
import { PublicPrivateKeyPair } from '@joplin/lib/services/e2ee/ppk';
|
||||||
import ToggleAdvancedSettingsButton from '../ConfigScreen/controls/ToggleAdvancedSettingsButton';
|
import ToggleAdvancedSettingsButton from '../ConfigScreen/controls/ToggleAdvancedSettingsButton';
|
||||||
|
import MacOSMissingPasswordHelpLink from '../ConfigScreen/controls/MissingPasswordHelpLink';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
themeId: any;
|
themeId: any;
|
||||||
@ -252,7 +253,16 @@ const EncryptionConfigScreen = (props: Props) => {
|
|||||||
const buttonTitle = CommandService.instance().label('openMasterPasswordDialog');
|
const buttonTitle = CommandService.instance().label('openMasterPasswordDialog');
|
||||||
|
|
||||||
const needPasswordMessage = !needMasterPassword ? null : (
|
const needPasswordMessage = !needMasterPassword ? null : (
|
||||||
<p className="needpassword">{_('Your password is needed to decrypt some of your data.')}<br/>{_('Please click on "%s" to proceed, or set the passwords in the "%s" list below.', buttonTitle, _('Encryption keys'))}</p>
|
<p className="needpassword">
|
||||||
|
{_('Your password is needed to decrypt some of your data.')}
|
||||||
|
<br/>
|
||||||
|
{_('Please click on "%s" to proceed, or set the passwords in the "%s" list below.', buttonTitle, _('Encryption keys'))}
|
||||||
|
<br/>
|
||||||
|
<MacOSMissingPasswordHelpLink
|
||||||
|
theme={theme}
|
||||||
|
text={_('%s: Missing password', _('Help'))}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3,7 +3,8 @@ import shim from '@joplin/lib/shim';
|
|||||||
import { _ } from '@joplin/lib/locale';
|
import { _ } from '@joplin/lib/locale';
|
||||||
import bridge from '../../../services/bridge';
|
import bridge from '../../../services/bridge';
|
||||||
import { openItemById } from '../../NoteEditor/utils/contextMenu';
|
import { openItemById } from '../../NoteEditor/utils/contextMenu';
|
||||||
const { parseResourceUrl, urlProtocol, fileUriToPath } = require('@joplin/lib/urlUtils');
|
const { parseResourceUrl, urlProtocol } = require('@joplin/lib/urlUtils');
|
||||||
|
import { fileUriToPath } from '@joplin/utils/url';
|
||||||
const { urlDecode } = require('@joplin/lib/string-utils');
|
const { urlDecode } = require('@joplin/lib/string-utils');
|
||||||
|
|
||||||
export const declaration: CommandDeclaration = {
|
export const declaration: CommandDeclaration = {
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
|
import Setting from '@joplin/lib/models/Setting';
|
||||||
import { processPastedHtml } from './resourceHandling';
|
import { processPastedHtml } from './resourceHandling';
|
||||||
|
|
||||||
describe('resourceHandling', () => {
|
describe('resourceHandling', () => {
|
||||||
it('should sanitize pasted HTML', async () => {
|
it('should sanitize pasted HTML', async () => {
|
||||||
|
Setting.setConstant('resourceDir', '/home/.config/joplin/resources');
|
||||||
|
|
||||||
const testCases = [
|
const testCases = [
|
||||||
['Test: <style onload="evil()"></style>', 'Test: <style></style>'],
|
['Test: <style onload="evil()"></style>', 'Test: <style></style>'],
|
||||||
['<a href="javascript: alert()">test</a>', '<a href="#">test</a>'],
|
['<a href="javascript: alert()">test</a>', '<a href="#">test</a>'],
|
||||||
|
['<a href="file:///home/.config/joplin/resources/test.pdf">test</a>', '<a href="file:///home/.config/joplin/resources/test.pdf">test</a>'],
|
||||||
|
['<a href="file:///etc/passwd">evil.pdf</a>', '<a href="#">evil.pdf</a>'],
|
||||||
['<script >evil()</script>', ''],
|
['<script >evil()</script>', ''],
|
||||||
['<script>evil()</script>', ''],
|
['<script>evil()</script>', ''],
|
||||||
[
|
[
|
||||||
|
@ -8,7 +8,7 @@ import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
|||||||
import htmlUtils from '@joplin/lib/htmlUtils';
|
import htmlUtils from '@joplin/lib/htmlUtils';
|
||||||
import rendererHtmlUtils, { extractHtmlBody } from '@joplin/renderer/htmlUtils';
|
import rendererHtmlUtils, { extractHtmlBody } from '@joplin/renderer/htmlUtils';
|
||||||
import Logger from '@joplin/utils/Logger';
|
import Logger from '@joplin/utils/Logger';
|
||||||
const { fileUriToPath } = require('@joplin/lib/urlUtils');
|
import { fileUriToPath } from '@joplin/utils/url';
|
||||||
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;
|
||||||
@ -179,6 +179,8 @@ export async function processPastedHtml(html: string) {
|
|||||||
return extractHtmlBody(rendererHtmlUtils.sanitizeHtml(
|
return extractHtmlBody(rendererHtmlUtils.sanitizeHtml(
|
||||||
htmlUtils.replaceImageUrls(html, (src: string) => {
|
htmlUtils.replaceImageUrls(html, (src: string) => {
|
||||||
return mappedResources[src];
|
return mappedResources[src];
|
||||||
}),
|
}), {
|
||||||
|
allowedFilePrefixes: [Setting.value('resourceDir')],
|
||||||
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/app-desktop",
|
"name": "@joplin/app-desktop",
|
||||||
"version": "2.12.11",
|
"version": "2.12.14",
|
||||||
"description": "Joplin for Desktop",
|
"description": "Joplin for Desktop",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/fork-htmlparser2",
|
"name": "@joplin/fork-htmlparser2",
|
||||||
"description": "Fast & forgiving HTML/XML/RSS parser",
|
"description": "Fast & forgiving HTML/XML/RSS parser",
|
||||||
"version": "4.1.45",
|
"version": "4.1.46",
|
||||||
"author": "Felix Boehm <me@feedic.com>",
|
"author": "Felix Boehm <me@feedic.com>",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "@joplin/fork-sax",
|
"name": "@joplin/fork-sax",
|
||||||
"description": "An evented streaming XML parser in JavaScript",
|
"description": "An evented streaming XML parser in JavaScript",
|
||||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||||
"version": "1.2.49",
|
"version": "1.2.50",
|
||||||
"main": "lib/sax.js",
|
"main": "lib/sax.js",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/fork-uslug",
|
"name": "@joplin/fork-uslug",
|
||||||
"version": "1.0.10",
|
"version": "1.0.11",
|
||||||
"description": "A permissive slug generator that works with unicode.",
|
"description": "A permissive slug generator that works with unicode.",
|
||||||
"author": "Jeremy Selier <jerem.selier@gmail.com>",
|
"author": "Jeremy Selier <jerem.selier@gmail.com>",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "generate-plugin-doc",
|
"name": "generate-plugin-doc",
|
||||||
"packageManager": "yarn@3.6.0",
|
"packageManager": "yarn@3.6.0",
|
||||||
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"buildPluginDoc_": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme '../../Assets/PluginDocTheme/' --readme '../../Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out ../../../joplin-website/docs/api/references/plugin_api ../lib/services/plugins/api/"
|
"buildPluginDoc_": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme '../../Assets/PluginDocTheme/' --readme '../../Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out ../../../joplin-website/docs/api/references/plugin_api ../lib/services/plugins/api/"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/htmlpack",
|
"name": "@joplin/htmlpack",
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"description": "Pack an HTML file and all its linked resources into a single HTML file",
|
"description": "Pack an HTML file and all its linked resources into a single HTML file",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
@ -14,7 +14,7 @@
|
|||||||
"author": "Laurent Cozic",
|
"author": "Laurent Cozic",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@joplin/fork-htmlparser2": "^4.1.45",
|
"@joplin/fork-htmlparser2": "^4.1.46",
|
||||||
"css": "3.0.0",
|
"css": "3.0.0",
|
||||||
"datauri": "4.1.0",
|
"datauri": "4.1.0",
|
||||||
"fs-extra": "11.1.1",
|
"fs-extra": "11.1.1",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/lib",
|
"name": "@joplin/lib",
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"description": "Joplin Core library",
|
"description": "Joplin Core library",
|
||||||
"author": "Laurent Cozic",
|
"author": "Laurent Cozic",
|
||||||
"homepage": "",
|
"homepage": "",
|
||||||
@ -31,14 +31,14 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "3.296.0",
|
"@aws-sdk/client-s3": "3.296.0",
|
||||||
"@aws-sdk/s3-request-presigner": "3.296.0",
|
"@aws-sdk/s3-request-presigner": "3.296.0",
|
||||||
"@joplin/fork-htmlparser2": "^4.1.44",
|
"@joplin/fork-htmlparser2": "^4.1.46",
|
||||||
"@joplin/fork-sax": "^1.2.48",
|
"@joplin/fork-sax": "^1.2.50",
|
||||||
"@joplin/fork-uslug": "^1.0.9",
|
"@joplin/fork-uslug": "^1.0.11",
|
||||||
"@joplin/htmlpack": "~2.12",
|
"@joplin/htmlpack": "^2.12.1",
|
||||||
"@joplin/renderer": "~2.12",
|
"@joplin/renderer": "^2.12.1",
|
||||||
"@joplin/turndown": "^4.0.66",
|
"@joplin/turndown": "^4.0.68",
|
||||||
"@joplin/turndown-plugin-gfm": "^1.0.48",
|
"@joplin/turndown-plugin-gfm": "^1.0.50",
|
||||||
"@joplin/utils": "~2.12",
|
"@joplin/utils": "^2.12.1",
|
||||||
"@types/nanoid": "3.0.0",
|
"@types/nanoid": "3.0.0",
|
||||||
"async-mutex": "0.4.0",
|
"async-mutex": "0.4.0",
|
||||||
"base-64": "1.0.0",
|
"base-64": "1.0.0",
|
||||||
|
@ -24,9 +24,9 @@ import * as ArrayUtils from '../../../ArrayUtils';
|
|||||||
import Logger from '@joplin/utils/Logger';
|
import Logger from '@joplin/utils/Logger';
|
||||||
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 { fileUriToPath } = require('../../../urlUtils');
|
|
||||||
const { MarkupToHtml } = require('@joplin/renderer');
|
const { MarkupToHtml } = require('@joplin/renderer');
|
||||||
const { ErrorNotFound } = require('../utils/errors');
|
const { ErrorNotFound } = require('../utils/errors');
|
||||||
|
import { fileUriToPath } from '@joplin/utils/url';
|
||||||
|
|
||||||
const logger = Logger.create('routes/notes');
|
const logger = Logger.create('routes/notes');
|
||||||
|
|
||||||
|
@ -105,101 +105,4 @@ urlUtils.objectToQueryString = function(query) {
|
|||||||
return queryString;
|
return queryString;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is a modified version of the file-uri-to-path package:
|
|
||||||
//
|
|
||||||
// - It removes the dependency to the "path" package, which wouldn't work with
|
|
||||||
// React Native.
|
|
||||||
//
|
|
||||||
// - It always returns paths with forward slashes "/". This is normally handled
|
|
||||||
// properly everywhere.
|
|
||||||
//
|
|
||||||
// - Adds the "platform" parameter to optionall return paths with "\" for win32
|
|
||||||
function fileUriToPath_(uri, platform) {
|
|
||||||
const sep = '/';
|
|
||||||
|
|
||||||
if (
|
|
||||||
typeof uri !== 'string' ||
|
|
||||||
uri.length <= 7 ||
|
|
||||||
uri.substring(0, 7) !== 'file://'
|
|
||||||
) {
|
|
||||||
throw new TypeError(
|
|
||||||
'must pass in a file:// URI to convert to a file path',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const rest = decodeURI(uri.substring(7));
|
|
||||||
const firstSlash = rest.indexOf('/');
|
|
||||||
let host = rest.substring(0, firstSlash);
|
|
||||||
let path = rest.substring(firstSlash + 1);
|
|
||||||
|
|
||||||
// 2. Scheme Definition
|
|
||||||
// As a special case, <host> can be the string "localhost" or the empty
|
|
||||||
// string; this is interpreted as "the machine from which the URL is
|
|
||||||
// being interpreted".
|
|
||||||
if (host === 'localhost') {
|
|
||||||
host = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host) {
|
|
||||||
host = sep + sep + host;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3.2 Drives, drive letters, mount points, file system root
|
|
||||||
// Drive letters are mapped into the top of a file URI in various ways,
|
|
||||||
// depending on the implementation; some applications substitute
|
|
||||||
// vertical bar ("|") for the colon after the drive letter, yielding
|
|
||||||
// "file:///c|/tmp/test.txt". In some cases, the colon is left
|
|
||||||
// unchanged, as in "file:///c:/tmp/test.txt". In other cases, the
|
|
||||||
// colon is simply omitted, as in "file:///c/tmp/test.txt".
|
|
||||||
path = path.replace(/^(.+)\|/, '$1:');
|
|
||||||
|
|
||||||
// for Windows, we need to invert the path separators from what a URI uses
|
|
||||||
// if (sep === '\\') {
|
|
||||||
// path = path.replace(/\//g, '\\');
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (/^.+:/.test(path)) {
|
|
||||||
// has Windows drive at beginning of path
|
|
||||||
} else {
|
|
||||||
// unix path…
|
|
||||||
path = sep + path;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform === 'win32') {
|
|
||||||
return (host + path).replace(/\//g, '\\');
|
|
||||||
} else {
|
|
||||||
return host + path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
urlUtils.fileUriToPath = (path, platform = 'linux') => {
|
|
||||||
const output = fileUriToPath_(path, platform);
|
|
||||||
|
|
||||||
// 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,30 +71,4 @@ describe('urlUtils', () => {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should convert a file URI to a file path', (async () => {
|
|
||||||
// Tests imported from https://github.com/TooTallNate/file-uri-to-path/tree/master/test
|
|
||||||
const testCases = {
|
|
||||||
'file://host/path': '//host/path',
|
|
||||||
'file://localhost/etc/fstab': '/etc/fstab',
|
|
||||||
'file:///etc/fstab': '/etc/fstab',
|
|
||||||
'file:///c:/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
|
||||||
'file://localhost/c|/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
|
||||||
'file:///c|/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
|
||||||
'file://localhost/c:/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
|
||||||
'file://hostname/path/to/the%20file.txt': '//hostname/path/to/the file.txt',
|
|
||||||
'file:///c:/path/to/the%20file.txt': 'c:/path/to/the file.txt',
|
|
||||||
'file:///C:/Documents%20and%20Settings/davris/FileSchemeURIs.doc': 'C:/Documents and Settings/davris/FileSchemeURIs.doc',
|
|
||||||
'file:///C:/caf%C3%A9/%C3%A5r/d%C3%BCnn/%E7%89%9B%E9%93%83/Ph%E1%BB%9F/%F0%9F%98%B5.exe': 'C:/café/år/dünn/牛铃/Phở/😵.exe',
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const [input, expected] of Object.entries(testCases)) {
|
|
||||||
const actual = urlUtils.fileUriToPath(input);
|
|
||||||
expect(actual).toBe(expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(urlUtils.fileUriToPath('file://c:/not/quite/right')).toBe('c:/not/quite/right');
|
|
||||||
expect(urlUtils.fileUriToPath('file:///d:/better')).toBe('d:/better');
|
|
||||||
expect(urlUtils.fileUriToPath('file:///c:/AUTOEXEC.BAT', 'win32')).toBe('c:\\AUTOEXEC.BAT');
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/plugin-repo-cli",
|
"name": "@joplin/plugin-repo-cli",
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"bin": "./dist/index.js",
|
"bin": "./dist/index.js",
|
||||||
@ -18,9 +18,9 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@joplin/lib": "~2.12",
|
"@joplin/lib": "^2.12.1",
|
||||||
"@joplin/tools": "~2.12",
|
"@joplin/tools": "^2.12.1",
|
||||||
"@joplin/utils": "~2.12",
|
"@joplin/utils": "^2.12.1",
|
||||||
"fs-extra": "11.1.1",
|
"fs-extra": "11.1.1",
|
||||||
"gh-release-assets": "2.0.1",
|
"gh-release-assets": "2.0.1",
|
||||||
"node-fetch": "2.6.7",
|
"node-fetch": "2.6.7",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/react-native-saf-x",
|
"name": "@joplin/react-native-saf-x",
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"description": "a module to help work with scoped storages on android easily",
|
"description": "a module to help work with scoped storages on android easily",
|
||||||
"main": "src/index",
|
"main": "src/index",
|
||||||
"react-native": "src/index",
|
"react-native": "src/index",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const Entities = require('html-entities').AllHtmlEntities;
|
const Entities = require('html-entities').AllHtmlEntities;
|
||||||
const htmlentities = new Entities().encode;
|
const htmlentities = new Entities().encode;
|
||||||
|
import { fileUriToPath } from '@joplin/utils/url';
|
||||||
const htmlparser2 = require('@joplin/fork-htmlparser2');
|
const htmlparser2 = require('@joplin/fork-htmlparser2');
|
||||||
|
|
||||||
// [\s\S] instead of . for multiline matching
|
// [\s\S] instead of . for multiline matching
|
||||||
@ -31,7 +32,8 @@ const selfClosingElements = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
interface SanitizeHtmlOptions {
|
interface SanitizeHtmlOptions {
|
||||||
addNoMdConvClass: boolean;
|
addNoMdConvClass?: boolean;
|
||||||
|
allowedFilePrefixes?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const attributesHtml = (attr: Record<string, string>) => {
|
export const attributesHtml = (attr: Record<string, string>) => {
|
||||||
@ -157,20 +159,36 @@ class HtmlUtils {
|
|||||||
.replace(/</g, '<');
|
.replace(/</g, '<');
|
||||||
}
|
}
|
||||||
|
|
||||||
private isAcceptedUrl(url: string): boolean {
|
private isAcceptedUrl(url: string, allowedFilePrefixes: string[]): boolean {
|
||||||
url = url.toLowerCase();
|
url = url.toLowerCase();
|
||||||
return url.startsWith('https://') ||
|
if (url.startsWith('https://') ||
|
||||||
url.startsWith('http://') ||
|
url.startsWith('http://') ||
|
||||||
url.startsWith('mailto://') ||
|
url.startsWith('mailto://') ||
|
||||||
// We also allow anchors but only with a specific set of a characters.
|
// We also allow anchors but only with a specific set of a characters.
|
||||||
// Fixes https://github.com/laurent22/joplin/issues/8286
|
// Fixes https://github.com/laurent22/joplin/issues/8286
|
||||||
!!url.match(/^#[a-zA-Z0-9-]+$/);
|
!!url.match(/^#[a-zA-Z0-9-]+$/)) return true;
|
||||||
|
|
||||||
|
if (url.startsWith('file://')) {
|
||||||
|
// We need to do a case insensitive comparison because the URL we
|
||||||
|
// get appears to be converted to lowercase somewhere. To be
|
||||||
|
// completely sure, we make it lowercase explicitely.
|
||||||
|
const filePath = fileUriToPath(url).toLowerCase();
|
||||||
|
for (const filePrefix of allowedFilePrefixes) {
|
||||||
|
if (filePath.startsWith(filePrefix.toLowerCase())) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sanitizeHtml(html: string, options: SanitizeHtmlOptions = null) {
|
public sanitizeHtml(html: string, options: SanitizeHtmlOptions = null) {
|
||||||
options = { // If true, adds a "jop-noMdConv" class to all the tags.
|
options = {
|
||||||
|
// If true, adds a "jop-noMdConv" class to all the tags.
|
||||||
// It can be used afterwards to restore HTML tags in Markdown.
|
// It can be used afterwards to restore HTML tags in Markdown.
|
||||||
addNoMdConvClass: false, ...options };
|
addNoMdConvClass: false,
|
||||||
|
allowedFilePrefixes: [],
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
const output: string[] = [];
|
const output: string[] = [];
|
||||||
|
|
||||||
@ -247,7 +265,7 @@ class HtmlUtils {
|
|||||||
// particular we want to exclude `javascript:` URLs. This
|
// particular we want to exclude `javascript:` URLs. This
|
||||||
// applies to A tags, and also AREA ones but to be safe we don't
|
// applies to A tags, and also AREA ones but to be safe we don't
|
||||||
// filter on the tag name and process all HREF attributes.
|
// filter on the tag name and process all HREF attributes.
|
||||||
if ('href' in attrs && !this.isAcceptedUrl(attrs['href'])) {
|
if ('href' in attrs && !this.isAcceptedUrl(attrs['href'], options.allowedFilePrefixes)) {
|
||||||
attrs['href'] = '#';
|
attrs['href'] = '#';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/renderer",
|
"name": "@joplin/renderer",
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"description": "The Joplin note renderer, used the mobile and desktop application",
|
"description": "The Joplin note renderer, used the mobile and desktop application",
|
||||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
|
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
@ -26,8 +26,9 @@
|
|||||||
"typescript": "5.1.3"
|
"typescript": "5.1.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@joplin/fork-htmlparser2": "^4.1.44",
|
"@joplin/fork-htmlparser2": "^4.1.46",
|
||||||
"@joplin/fork-uslug": "^1.0.9",
|
"@joplin/fork-uslug": "^1.0.11",
|
||||||
|
"@joplin/utils": "~2.12",
|
||||||
"font-awesome-filetypes": "2.1.0",
|
"font-awesome-filetypes": "2.1.0",
|
||||||
"fs-extra": "11.1.1",
|
"fs-extra": "11.1.1",
|
||||||
"highlight.js": "11.8.0",
|
"highlight.js": "11.8.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/tools",
|
"name": "@joplin/tools",
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"description": "Various tools for Joplin",
|
"description": "Various tools for Joplin",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": "Laurent Cozic",
|
"author": "Laurent Cozic",
|
||||||
@ -20,9 +20,9 @@
|
|||||||
},
|
},
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@joplin/lib": "~2.12",
|
"@joplin/lib": "^2.12.1",
|
||||||
"@joplin/renderer": "~2.12",
|
"@joplin/renderer": "^2.12.1",
|
||||||
"@joplin/utils": "~2.12",
|
"@joplin/utils": "^2.12.1",
|
||||||
"compare-versions": "3.6.0",
|
"compare-versions": "3.6.0",
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
"execa": "4.1.0",
|
"execa": "4.1.0",
|
||||||
@ -42,7 +42,7 @@
|
|||||||
"yargs": "17.7.2"
|
"yargs": "17.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@joplin/fork-htmlparser2": "^4.1.44",
|
"@joplin/fork-htmlparser2": "^4.1.46",
|
||||||
"@rmp135/sql-ts": "1.18.0",
|
"@rmp135/sql-ts": "1.18.0",
|
||||||
"@types/fs-extra": "11.0.1",
|
"@types/fs-extra": "11.0.1",
|
||||||
"@types/jest": "29.5.3",
|
"@types/jest": "29.5.3",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"version": "1.0.49",
|
"version": "1.0.50",
|
||||||
"author": "Dom Christie",
|
"author": "Dom Christie",
|
||||||
"main": "lib/turndown-plugin-gfm.cjs.js",
|
"main": "lib/turndown-plugin-gfm.cjs.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/turndown",
|
"name": "@joplin/turndown",
|
||||||
"description": "A library that converts HTML to Markdown",
|
"description": "A library that converts HTML to Markdown",
|
||||||
"version": "4.0.67",
|
"version": "4.0.68",
|
||||||
"author": "Dom Christie",
|
"author": "Dom Christie",
|
||||||
"main": "lib/turndown.cjs.js",
|
"main": "lib/turndown.cjs.js",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/utils",
|
"name": "@joplin/utils",
|
||||||
"version": "2.12.0",
|
"version": "2.12.1",
|
||||||
"description": "Utilities for Joplin",
|
"description": "Utilities for Joplin",
|
||||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/utils",
|
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/utils",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./dist/index.js",
|
".": "./dist/index.js",
|
||||||
"./net": "./dist/net.js",
|
|
||||||
"./fs": "./dist/fs.js",
|
|
||||||
"./env": "./dist/env.js",
|
"./env": "./dist/env.js",
|
||||||
"./types": "./dist/types.js",
|
"./fs": "./dist/fs.js",
|
||||||
"./time": "./dist/time.js",
|
|
||||||
"./html": "./dist/html.js",
|
"./html": "./dist/html.js",
|
||||||
|
"./net": "./dist/net.js",
|
||||||
|
"./time": "./dist/time.js",
|
||||||
|
"./types": "./dist/types.js",
|
||||||
|
"./url": "./dist/url.js",
|
||||||
"./Logger": "./dist/Logger.js"
|
"./Logger": "./dist/Logger.js"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
31
packages/utils/url.test.ts
Normal file
31
packages/utils/url.test.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { fileUriToPath } from './url';
|
||||||
|
|
||||||
|
describe('utils/url', () => {
|
||||||
|
|
||||||
|
it('should convert a file URI to a file path', (async () => {
|
||||||
|
// Tests imported from https://github.com/TooTallNate/file-uri-to-path/tree/master/test
|
||||||
|
const testCases = {
|
||||||
|
'file://host/path': '//host/path',
|
||||||
|
'file://localhost/etc/fstab': '/etc/fstab',
|
||||||
|
'file:///etc/fstab': '/etc/fstab',
|
||||||
|
'file:///c:/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
||||||
|
'file://localhost/c|/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
||||||
|
'file:///c|/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
||||||
|
'file://localhost/c:/WINDOWS/clock.avi': 'c:/WINDOWS/clock.avi',
|
||||||
|
'file://hostname/path/to/the%20file.txt': '//hostname/path/to/the file.txt',
|
||||||
|
'file:///c:/path/to/the%20file.txt': 'c:/path/to/the file.txt',
|
||||||
|
'file:///C:/Documents%20and%20Settings/davris/FileSchemeURIs.doc': 'C:/Documents and Settings/davris/FileSchemeURIs.doc',
|
||||||
|
'file:///C:/caf%C3%A9/%C3%A5r/d%C3%BCnn/%E7%89%9B%E9%93%83/Ph%E1%BB%9F/%F0%9F%98%B5.exe': 'C:/café/år/dünn/牛铃/Phở/😵.exe',
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [input, expected] of Object.entries(testCases)) {
|
||||||
|
const actual = fileUriToPath(input);
|
||||||
|
expect(actual).toBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(fileUriToPath('file://c:/not/quite/right')).toBe('c:/not/quite/right');
|
||||||
|
expect(fileUriToPath('file:///d:/better')).toBe('d:/better');
|
||||||
|
expect(fileUriToPath('file:///c:/AUTOEXEC.BAT', 'win32')).toBe('c:\\AUTOEXEC.BAT');
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
98
packages/utils/url.ts
Normal file
98
packages/utils/url.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* eslint-disable import/prefer-default-export */
|
||||||
|
|
||||||
|
// This is a modified version of the file-uri-to-path package:
|
||||||
|
//
|
||||||
|
// - It removes the dependency to the "path" package, which wouldn't work with
|
||||||
|
// React Native.
|
||||||
|
//
|
||||||
|
// - It always returns paths with forward slashes "/". This is normally handled
|
||||||
|
// properly everywhere.
|
||||||
|
//
|
||||||
|
// - Adds the "platform" parameter to optionall return paths with "\" for win32
|
||||||
|
function fileUriToPath_(uri: string, platform: string) {
|
||||||
|
const sep = '/';
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof uri !== 'string' ||
|
||||||
|
uri.length <= 7 ||
|
||||||
|
uri.substring(0, 7) !== 'file://'
|
||||||
|
) {
|
||||||
|
throw new TypeError(
|
||||||
|
'must pass in a file:// URI to convert to a file path',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rest = decodeURI(uri.substring(7));
|
||||||
|
const firstSlash = rest.indexOf('/');
|
||||||
|
let host = rest.substring(0, firstSlash);
|
||||||
|
let path = rest.substring(firstSlash + 1);
|
||||||
|
|
||||||
|
// 2. Scheme Definition
|
||||||
|
// As a special case, <host> can be the string "localhost" or the empty
|
||||||
|
// string; this is interpreted as "the machine from which the URL is
|
||||||
|
// being interpreted".
|
||||||
|
if (host === 'localhost') {
|
||||||
|
host = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host) {
|
||||||
|
host = sep + sep + host;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.2 Drives, drive letters, mount points, file system root
|
||||||
|
// Drive letters are mapped into the top of a file URI in various ways,
|
||||||
|
// depending on the implementation; some applications substitute
|
||||||
|
// vertical bar ("|") for the colon after the drive letter, yielding
|
||||||
|
// "file:///c|/tmp/test.txt". In some cases, the colon is left
|
||||||
|
// unchanged, as in "file:///c:/tmp/test.txt". In other cases, the
|
||||||
|
// colon is simply omitted, as in "file:///c/tmp/test.txt".
|
||||||
|
path = path.replace(/^(.+)\|/, '$1:');
|
||||||
|
|
||||||
|
// for Windows, we need to invert the path separators from what a URI uses
|
||||||
|
// if (sep === '\\') {
|
||||||
|
// path = path.replace(/\//g, '\\');
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (/^.+:/.test(path)) {
|
||||||
|
// has Windows drive at beginning of path
|
||||||
|
} else {
|
||||||
|
// unix path…
|
||||||
|
path = sep + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform === 'win32') {
|
||||||
|
return (host + path).replace(/\//g, '\\');
|
||||||
|
} else {
|
||||||
|
return host + path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fileUriToPath = (path: string, platform = 'linux') => {
|
||||||
|
const output = fileUriToPath_(path, platform);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
};
|
@ -1,5 +1,14 @@
|
|||||||
# Joplin terminal app changelog
|
# Joplin terminal app changelog
|
||||||
|
|
||||||
|
## [cli-v2.12.1](https://github.com/laurent22/joplin/releases/tag/cli-v2.12.1) - 2023-08-23T12:53:19Z
|
||||||
|
|
||||||
|
- New: Add support for share permissions (#8491)
|
||||||
|
- Improved: Allow importing Evernote task lists (#8440 by Rob Moffat)
|
||||||
|
- Improved: Rotating log files (#8376) (#5521 by [@hubert](https://github.com/hubert))
|
||||||
|
- Improved: Updated packages @rmp135/sql-ts (v1.18.0), buildTools, clean-html (v2), dayjs (v1.11.9), domhandler (v5), gettext-parser (v7.0.1), glob (v10.3.3), highlight.js (v11.8.0), jsdom (v22.1.0), sass (v1.63.6), sharp (v0.32.3), standard (v17.1.0), word-wrap (v1.2.4)
|
||||||
|
- Improved: WebDAV: Show a more descriptive error message when the password is empty (#8477) (#8466 by Henry Heino)
|
||||||
|
- Security: Prevent XSS when passing specially encoded string to a link (57b4198)
|
||||||
|
|
||||||
## [cli-v2.11.1](https://github.com/laurent22/joplin/releases/tag/cli-v2.11.1) - 2023-06-27T09:28:01Z
|
## [cli-v2.11.1](https://github.com/laurent22/joplin/releases/tag/cli-v2.11.1) - 2023-06-27T09:28:01Z
|
||||||
|
|
||||||
- Improved: Updated packages aws, buildTools, domutils (v3.1.0), fs-extra (v11.1.1), jsdom (v21.1.2), markdown-it-multimd-table (v4.2.2), nanoid (v3.3.6), node-persist (v3.1.3), open (v8.4.2), reselect (v4.1.8), sass (v1.62.1), sharp (v0.32.1), sqlite3 (v5.1.6), tar (v6.1.15), turndown (v7.1.2), yargs (v17.7.2)
|
- Improved: Updated packages aws, buildTools, domutils (v3.1.0), fs-extra (v11.1.1), jsdom (v21.1.2), markdown-it-multimd-table (v4.2.2), nanoid (v3.3.6), node-persist (v3.1.3), open (v8.4.2), reselect (v4.1.8), sass (v1.62.1), sharp (v0.32.1), sqlite3 (v5.1.6), tar (v6.1.15), turndown (v7.1.2), yargs (v17.7.2)
|
||||||
|
57
yarn.lock
57
yarn.lock
@ -4626,7 +4626,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/fork-htmlparser2@^4.1.44, @joplin/fork-htmlparser2@^4.1.45, @joplin/fork-htmlparser2@workspace:packages/fork-htmlparser2":
|
"@joplin/fork-htmlparser2@^4.1.46, @joplin/fork-htmlparser2@workspace:packages/fork-htmlparser2":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/fork-htmlparser2@workspace:packages/fork-htmlparser2"
|
resolution: "@joplin/fork-htmlparser2@workspace:packages/fork-htmlparser2"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4647,7 +4647,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/fork-sax@^1.2.48, @joplin/fork-sax@workspace:packages/fork-sax":
|
"@joplin/fork-sax@^1.2.50, @joplin/fork-sax@workspace:packages/fork-sax":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/fork-sax@workspace:packages/fork-sax"
|
resolution: "@joplin/fork-sax@workspace:packages/fork-sax"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4656,7 +4656,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/fork-uslug@^1.0.9, @joplin/fork-uslug@workspace:packages/fork-uslug":
|
"@joplin/fork-uslug@^1.0.11, @joplin/fork-uslug@workspace:packages/fork-uslug":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/fork-uslug@workspace:packages/fork-uslug"
|
resolution: "@joplin/fork-uslug@workspace:packages/fork-uslug"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4666,11 +4666,11 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/htmlpack@workspace:packages/htmlpack, @joplin/htmlpack@~2.12":
|
"@joplin/htmlpack@^2.12.1, @joplin/htmlpack@workspace:packages/htmlpack":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/htmlpack@workspace:packages/htmlpack"
|
resolution: "@joplin/htmlpack@workspace:packages/htmlpack"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@joplin/fork-htmlparser2": ^4.1.45
|
"@joplin/fork-htmlparser2": ^4.1.46
|
||||||
"@types/fs-extra": 11.0.1
|
"@types/fs-extra": 11.0.1
|
||||||
css: 3.0.0
|
css: 3.0.0
|
||||||
datauri: 4.1.0
|
datauri: 4.1.0
|
||||||
@ -4679,20 +4679,20 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/lib@workspace:packages/lib, @joplin/lib@~2.12":
|
"@joplin/lib@^2.12.1, @joplin/lib@workspace:packages/lib, @joplin/lib@~2.12":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/lib@workspace:packages/lib"
|
resolution: "@joplin/lib@workspace:packages/lib"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@aws-sdk/client-s3": 3.296.0
|
"@aws-sdk/client-s3": 3.296.0
|
||||||
"@aws-sdk/s3-request-presigner": 3.296.0
|
"@aws-sdk/s3-request-presigner": 3.296.0
|
||||||
"@joplin/fork-htmlparser2": ^4.1.44
|
"@joplin/fork-htmlparser2": ^4.1.46
|
||||||
"@joplin/fork-sax": ^1.2.48
|
"@joplin/fork-sax": ^1.2.50
|
||||||
"@joplin/fork-uslug": ^1.0.9
|
"@joplin/fork-uslug": ^1.0.11
|
||||||
"@joplin/htmlpack": ~2.12
|
"@joplin/htmlpack": ^2.12.1
|
||||||
"@joplin/renderer": ~2.12
|
"@joplin/renderer": ^2.12.1
|
||||||
"@joplin/turndown": ^4.0.66
|
"@joplin/turndown": ^4.0.68
|
||||||
"@joplin/turndown-plugin-gfm": ^1.0.48
|
"@joplin/turndown-plugin-gfm": ^1.0.50
|
||||||
"@joplin/utils": ~2.12
|
"@joplin/utils": ^2.12.1
|
||||||
"@types/fs-extra": 11.0.1
|
"@types/fs-extra": 11.0.1
|
||||||
"@types/jest": 29.5.3
|
"@types/jest": 29.5.3
|
||||||
"@types/js-yaml": 4.0.5
|
"@types/js-yaml": 4.0.5
|
||||||
@ -4796,9 +4796,9 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/plugin-repo-cli@workspace:packages/plugin-repo-cli"
|
resolution: "@joplin/plugin-repo-cli@workspace:packages/plugin-repo-cli"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@joplin/lib": ~2.12
|
"@joplin/lib": ^2.12.1
|
||||||
"@joplin/tools": ~2.12
|
"@joplin/tools": ^2.12.1
|
||||||
"@joplin/utils": ~2.12
|
"@joplin/utils": ^2.12.1
|
||||||
"@types/fs-extra": 11.0.1
|
"@types/fs-extra": 11.0.1
|
||||||
"@types/jest": 29.5.3
|
"@types/jest": 29.5.3
|
||||||
"@types/node": 18.16.18
|
"@types/node": 18.16.18
|
||||||
@ -4847,12 +4847,13 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/renderer@workspace:packages/renderer, @joplin/renderer@~2.12":
|
"@joplin/renderer@^2.12.1, @joplin/renderer@workspace:packages/renderer, @joplin/renderer@~2.12":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/renderer@workspace:packages/renderer"
|
resolution: "@joplin/renderer@workspace:packages/renderer"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@joplin/fork-htmlparser2": ^4.1.44
|
"@joplin/fork-htmlparser2": ^4.1.46
|
||||||
"@joplin/fork-uslug": ^1.0.9
|
"@joplin/fork-uslug": ^1.0.11
|
||||||
|
"@joplin/utils": ~2.12
|
||||||
"@types/jest": 29.5.3
|
"@types/jest": 29.5.3
|
||||||
"@types/node": 18.16.18
|
"@types/node": 18.16.18
|
||||||
font-awesome-filetypes: 2.1.0
|
font-awesome-filetypes: 2.1.0
|
||||||
@ -4945,14 +4946,14 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/tools@workspace:packages/tools, @joplin/tools@~2.12":
|
"@joplin/tools@^2.12.1, @joplin/tools@workspace:packages/tools, @joplin/tools@~2.12":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/tools@workspace:packages/tools"
|
resolution: "@joplin/tools@workspace:packages/tools"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@joplin/fork-htmlparser2": ^4.1.44
|
"@joplin/fork-htmlparser2": ^4.1.46
|
||||||
"@joplin/lib": ~2.12
|
"@joplin/lib": ^2.12.1
|
||||||
"@joplin/renderer": ~2.12
|
"@joplin/renderer": ^2.12.1
|
||||||
"@joplin/utils": ~2.12
|
"@joplin/utils": ^2.12.1
|
||||||
"@rmp135/sql-ts": 1.18.0
|
"@rmp135/sql-ts": 1.18.0
|
||||||
"@types/fs-extra": 11.0.1
|
"@types/fs-extra": 11.0.1
|
||||||
"@types/jest": 29.5.3
|
"@types/jest": 29.5.3
|
||||||
@ -4988,7 +4989,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/turndown-plugin-gfm@^1.0.48, @joplin/turndown-plugin-gfm@workspace:packages/turndown-plugin-gfm":
|
"@joplin/turndown-plugin-gfm@^1.0.50, @joplin/turndown-plugin-gfm@workspace:packages/turndown-plugin-gfm":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/turndown-plugin-gfm@workspace:packages/turndown-plugin-gfm"
|
resolution: "@joplin/turndown-plugin-gfm@workspace:packages/turndown-plugin-gfm"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5000,7 +5001,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/turndown@^4.0.66, @joplin/turndown@workspace:packages/turndown":
|
"@joplin/turndown@^4.0.68, @joplin/turndown@workspace:packages/turndown":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/turndown@workspace:packages/turndown"
|
resolution: "@joplin/turndown@workspace:packages/turndown"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5017,7 +5018,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@joplin/utils@workspace:packages/utils, @joplin/utils@~2.12":
|
"@joplin/utils@^2.12.1, @joplin/utils@workspace:packages/utils, @joplin/utils@~2.12":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@joplin/utils@workspace:packages/utils"
|
resolution: "@joplin/utils@workspace:packages/utils"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
Loading…
Reference in New Issue
Block a user