1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-30 20:39:46 +02:00

Compare commits

...

27 Commits

Author SHA1 Message Date
Laurent Cozic
dce8bced15 Server v2.13.3 2023-11-01 16:30:12 +00:00
Laurent Cozic
a9719307af lock files 2023-11-01 16:29:04 +00:00
Laurent Cozic
0c8b475736 Server: Automatically restarts the server when it crashes, with exponentiel back-off 2023-11-01 16:28:45 +00:00
Laurent Cozic
dbd3db873f Fix ts error 2023-11-01 16:25:46 +00:00
Laurent Cozic
073781da92 Chore: Fixed attachFile method 2023-11-01 14:58:21 +00:00
Laurent Cozic
7d87d0b394 Chore: Remove postinstall step from editor package 2023-11-01 14:54:48 +00:00
renovate[bot]
0cb2a3a385 Update eslint (#9184)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-01 10:48:09 +00:00
renovate[bot]
c1e970a703 Update dependency @react-native-community/datetimepicker to v7.6.1 (#9181)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-01 07:16:07 +00:00
renovate[bot]
17831bf87a Update electron (#9183)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-01 03:32:57 +00:00
Joplin Bot
a93c558479 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-11-01 00:41:29 +00:00
Laurent Cozic
13b09aa9a4 Doc: Set Data API link position 2023-10-31 20:39:52 +00:00
Joplin Bot
703fe35121 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-10-31 18:18:53 +00:00
Laurent Cozic
a7dddaf2c4 Desktop: Allow attaching a file from the Markdown editor for HTML notes 2023-10-31 16:53:47 +00:00
Laurent Cozic
a95a66104d Doc: Fixed desktop changelog generation 2023-10-31 15:59:58 +00:00
Laurent Cozic
dd47571dff Plugins: Add support for showOpenDialog method 2023-10-31 15:30:05 +00:00
Laurent Cozic
0a2c3b3a91 Doc: Add config screen link to E2EE doc 2023-10-31 15:30:04 +00:00
Henry Heino
694ca6480e Desktop: Resolves #8742: Prompt to restart in safe mode on renderer process hang/crash (#9153) 2023-10-31 15:05:28 +00:00
Henry Heino
86b00d0a2b Mobile: Resolves #9134: Image editor: Allow loading from save when the image editor is reloaded in the background (#9135) 2023-10-31 14:57:26 +00:00
Laurent Cozic
b8c26b2ef3 Doc: Fixed Crowdin translation build 2023-10-31 14:06:54 +00:00
renovate[bot]
3343c2b0aa Update dependency sass to v1.68.0 (#9177)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-31 12:28:51 +00:00
Joplin Bot
f9c60bd47b Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-10-31 11:47:05 +00:00
Piotr Narel
71d2256fb7 All: Translation: Update pl_PL.po (#9174) 2023-10-31 07:46:36 -04:00
Laurent Cozic
66fe2f9390 Doc: Add support for localisation using Crowdin 2023-10-31 11:32:55 +00:00
renovate[bot]
3fe473cdd3 Update dependency @types/js-yaml to v4.0.7 (#9173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-31 06:53:03 +00:00
Joplin Bot
3255f4d63b Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-10-31 00:40:05 +00:00
Laurent Cozic
66036c2027 Desktop release v2.13.4 2023-10-30 22:50:51 +00:00
Laurent Cozic
3b98060c27 Android 2.13.5 2023-10-30 22:50:30 +00:00
76 changed files with 2982 additions and 2498 deletions

View File

@@ -415,6 +415,8 @@ packages/app-desktop/utils/checkForUpdatesUtils.test.js
packages/app-desktop/utils/checkForUpdatesUtils.js
packages/app-desktop/utils/checkForUpdatesUtilsTestData.js
packages/app-desktop/utils/markupLanguageUtils.js
packages/app-desktop/utils/restartInSafeModeFromMain.test.js
packages/app-desktop/utils/restartInSafeModeFromMain.js
packages/app-mobile/PluginAssetsLoader.js
packages/app-mobile/components/ActionButton.js
packages/app-mobile/components/BackButtonDialogBox.js
@@ -902,6 +904,7 @@ packages/lib/themes/type.js
packages/lib/time.js
packages/lib/utils/credentialFiles.js
packages/lib/utils/joplinCloud.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/userFetcher.js
packages/lib/utils/webDAVUtils.test.js
packages/lib/utils/webDAVUtils.js

4
.gitignore vendored
View File

@@ -51,6 +51,7 @@ lerna-debug.log
.env
docs/**/*.mustache
.idea
/readme/i18n
# Yarn stuff
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
@@ -396,6 +397,8 @@ packages/app-desktop/utils/checkForUpdatesUtils.test.js
packages/app-desktop/utils/checkForUpdatesUtils.js
packages/app-desktop/utils/checkForUpdatesUtilsTestData.js
packages/app-desktop/utils/markupLanguageUtils.js
packages/app-desktop/utils/restartInSafeModeFromMain.test.js
packages/app-desktop/utils/restartInSafeModeFromMain.js
packages/app-mobile/PluginAssetsLoader.js
packages/app-mobile/components/ActionButton.js
packages/app-mobile/components/BackButtonDialogBox.js
@@ -883,6 +886,7 @@ packages/lib/themes/type.js
packages/lib/time.js
packages/lib/utils/credentialFiles.js
packages/lib/utils/joplinCloud.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/userFetcher.js
packages/lib/utils/webDAVUtils.test.js
packages/lib/utils/webDAVUtils.js

File diff suppressed because one or more lines are too long

View File

@@ -6,7 +6,7 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
yarnPath: .yarn/releases/yarn-3.6.3.cjs
yarnPath: .yarn/releases/yarn-3.6.4.cjs
logFilters:

View File

@@ -71,7 +71,7 @@ EXPOSE ${APP_PORT}
# https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#handling-kernel-signals
WORKDIR /home/$user/packages/server
ENTRYPOINT ["tini", "--"]
CMD ["node", "dist/app.js"]
CMD ["yarn", "start-prod"]
# Build-time metadata
# https://github.com/opencontainers/image-spec/blob/master/annotations.md

23
crowdin.yml Normal file
View File

@@ -0,0 +1,23 @@
project_id: '624298'
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
files:
- source: /readme/**/*
translation: /readme/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%
ignore:
- /readme/_i18n
- /readme/i18n
- /readme/about/changelog
- /readme/about/stats.md
- /readme/api
- /readme/dev
- /readme/news
- /readme/cla.md
- /readme/connection_check.md
- /readme/privacy.md
- /**/*.yml
- /**/*.json
- /**/*.png
- /**/*.jpg

View File

@@ -182,6 +182,11 @@
"docs/images/flags": true,
"lerna-debug.log": true,
"node_modules/": true,
"packages/doc-builder/build": true,
"packages/doc-builder/help": true,
"packages/doc-builder/news": true,
"packages/doc-builder/i18n": true,
"readme/i18n": true,
"packages/app-cli/**/*.*~": true,
"packages/app-cli/**/*.mo": true,
"packages/app-cli/**/build/": true,

View File

@@ -12,31 +12,34 @@
"node": ">=16"
},
"scripts": {
"buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 --topological run build && yarn run tsc",
"buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn run tsc",
"buildApiDoc": "yarn workspace joplin start apidoc ../../readme/api/references/rest_api.md",
"buildCommandIndex": "node packages/tools/gulp/tasks/buildCommandIndexRun.js",
"buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 --topological run build && yarn run tsc",
"buildPluginDoc": "cd packages/generate-plugin-doc && yarn run buildPluginDoc_",
"updateMarkdownDoc": "node ./packages/tools/updateMarkdownDoc",
"updateNews": "node ./packages/tools/website/updateNews",
"postPreReleasesToForum": "node ./packages/tools/postPreReleasesToForum",
"buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn run tsc",
"buildServerDocker": "node packages/tools/buildServerDocker.js",
"buildSettingJsonSchema": "yarn workspace joplin start settingschema ../../../joplin-website/docs/schema/settings.json",
"buildTranslations": "node packages/tools/build-translation.js",
"buildWebsiteTranslations": "node packages/tools/website/buildTranslations.js",
"buildWebsite": "node ./packages/tools/website/processDocs.js --env prod && node ./packages/tools/website/build.js && yarn run buildPluginDoc && yarn run buildSettingJsonSchema",
"checkLibPaths": "node ./packages/tools/checkLibPaths.js",
"buildWebsiteTranslations": "node packages/tools/website/buildTranslations.js",
"checkIgnoredFiles": "node ./packages/tools/checkIgnoredFiles.js",
"checkLibPaths": "node ./packages/tools/checkLibPaths.js",
"circularDependencyCheck": "madge --warning --circular --extensions js ./",
"clean": "npm run clean --workspaces --if-present && node packages/tools/clean && yarn cache clean",
"crowdin": "crowdin",
"crowdinDownload": "crowdin download",
"crowdinUpload": "crowdin upload",
"cspell": "cspell",
"dependencyTree": "madge",
"generateDatabaseTypes": "node packages/tools/generate-database-types",
"linkChecker": "linkchecker https://joplinapp.org",
"linter-ci": "eslint --resolve-plugins-relative-to . --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
"linter-interactive": "eslint-interactive --resolve-plugins-relative-to . --fix --quiet --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": "eslint --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
"linter-interactive": "eslint-interactive --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
"packageJsonLint": "node ./packages/tools/packageJsonLint.js",
"postinstall": "gulp build",
"postPreReleasesToForum": "node ./packages/tools/postPreReleasesToForum",
"publishAll": "git pull && yarn run buildParallel && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
"releaseAndroid": "PATH=\"/usr/local/opt/openjdk@11/bin:$PATH\" node packages/tools/release-android.js",
"releaseAndroidClean": "node packages/tools/release-android.js",
@@ -47,15 +50,15 @@
"releasePluginGenerator": "node packages/tools/release-plugin-generator.js",
"releasePluginRepoCli": "node packages/tools/release-plugin-repo-cli.js",
"releaseServer": "node packages/tools/release-server.js",
"cspell": "cspell",
"setupNewRelease": "node ./packages/tools/setupNewRelease",
"spellcheck": "node packages/tools/spellcheck.js",
"tagServerLatest": "node packages/tools/tagServerLatest.js",
"buildServerDocker": "node packages/tools/buildServerDocker.js",
"setupNewRelease": "node ./packages/tools/setupNewRelease",
"test-ci": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test-ci",
"test": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test",
"tsc": "yarn workspaces foreach --parallel --verbose --interlaced run tsc",
"updateIgnored": "node packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js",
"updateMarkdownDoc": "node ./packages/tools/updateMarkdownDoc",
"updateNews": "node ./packages/tools/website/updateNews",
"updatePluginTypes": "./packages/generator-joplin/updateTypes.sh",
"watch": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 999 run watch",
"watchWebsite": "nodemon --delay 1 --watch Assets/WebsiteAssets --watch packages/tools/website --watch packages/tools/website/utils --watch packages/doc-builder/build --ext md,ts,js,mustache,css,tsx,gif,png,svg --exec \"node packages/tools/website/build.js && http-server --port 8077 ../joplin-website/docs -a localhost\""
@@ -66,15 +69,16 @@
}
},
"devDependencies": {
"@crowdin/cli": "3",
"@joplin/utils": "~2.12",
"@seiyab/eslint-plugin-react-hooks": "4.5.1-beta.0",
"@typescript-eslint/eslint-plugin": "6.0.0",
"@typescript-eslint/parser": "6.0.0",
"@typescript-eslint/eslint-plugin": "6.7.2",
"@typescript-eslint/parser": "6.7.2",
"cspell": "5.21.2",
"eslint": "8.47.0",
"eslint": "8.49.0",
"eslint-interactive": "10.8.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-jest": "27.2.3",
"eslint-plugin-jest": "27.4.0",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.33.2",
"execa": "5.1.1",
@@ -86,20 +90,20 @@
"lint-staged": "13.3.0",
"madge": "6.1.0",
"npm-package-json-lint": "7.0.0",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"dependencies": {
"@types/fs-extra": "11.0.2",
"eslint-plugin-github": "4.9.2",
"eslint-plugin-github": "4.10.0",
"http-server": "14.1.1",
"node-gyp": "9.4.0",
"nodemon": "3.0.1"
},
"packageManager": "yarn@3.6.3",
"packageManager": "yarn@3.6.4",
"resolutions": {
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch",
"react-native-vosk@0.1.12": "patch:react-native-vosk@npm%3A0.1.12#./.yarn/patches/react-native-vosk-npm-0.1.12-76b1caaae8.patch",
"eslint": "patch:eslint@8.47.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
"eslint": "patch:eslint@8.49.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
"app-builder-lib@24.4.0": "patch:app-builder-lib@npm%3A24.4.0#./.yarn/patches/app-builder-lib-npm-24.4.0-05322ff057.patch",
"react-native@0.71.10": "patch:react-native@npm%3A0.71.10#./.yarn/patches/react-native-animation-fix/react-native-npm-0.71.10-f9c32562d8.patch"
}

View File

@@ -57,6 +57,10 @@ class Command extends BaseCommand {
const lines = [];
lines.push('---');
lines.push('sidebar_position: 2');
lines.push('---');
lines.push('');
lines.push('# Joplin Data API');
lines.push('');
lines.push('This API is available when the clipper server is running. It provides access to the notes, notebooks, tags and other Joplin object via a REST API. Plugins can also access this API even when the clipper server is not running.');

View File

@@ -52,7 +52,7 @@ export default class PluginRunner extends BasePluginRunner {
this.activeSandboxCalls_[callId] = true;
const promise = executeSandboxCall(pluginId, sandbox, `joplin.${path}`, mapEventHandlersToIds(args, this.eventHandlers_), this.eventHandler);
// eslint-disable-next-line promise/prefer-await-to-then -- Old code before rule was applied
promise.finally(() => {
void promise.finally(() => {
delete this.activeSandboxCalls_[callId];
});
return promise;

View File

@@ -72,12 +72,12 @@
"devDependencies": {
"@joplin/tools": "~2.13",
"@types/fs-extra": "11.0.2",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/node": "18.17.19",
"@types/proper-lockfile": "^4.1.2",
"gulp": "4.0.2",
"jest": "29.6.4",
"jest": "29.7.0",
"temp": "0.9.4",
"typescript": "5.1.6"
"typescript": "5.2.2"
}
}

View File

@@ -66,8 +66,10 @@ describe('MdToHtml', () => {
actualHtml,
'--------------------------------- Raw:',
actualHtml.split('\n'),
'--------------------------------- Expected:',
'--------------------------------- Expected (Lines)',
expectedHtml.split('\n'),
'--------------------------------- Expected (Text)',
expectedHtml,
'--------------------------------------------',
'',
];

View File

@@ -0,0 +1,7 @@
<p><a href=":/62d16d1c1e28418da6624fa8742a7ed0" class="jop-noMdConv">Resource link</a></p>
<p><a href="https://example.com/ok" class="jop-noMdConv">ok</a></p>
<p><a href="http://example.com/ok" class="jop-noMdConv">ok</a></p>
<p><a href="mailto:name@email.com" class="jop-noMdConv">ok</a></p>
<p><a href="joplin://62d16d1c1e28418da6624fa8742a7ed0" class="jop-noMdConv">ok</a></p>
<p><a href="#" class="jop-noMdConv">not ok</a></p>
<p><a href="#" class="jop-noMdConv">not ok</a></p>

View File

@@ -0,0 +1,13 @@
<a href=":/62d16d1c1e28418da6624fa8742a7ed0">Resource link</a>
<a href="https://example.com/ok">ok</a>
<a href="http://example.com/ok">ok</a>
<a href="mailto:name@email.com">ok</a>
<a href="joplin://62d16d1c1e28418da6624fa8742a7ed0">ok</a>
<a href="file:///etc/passwd">not ok</a>
<a href="data://blabla">not ok</a>

View File

@@ -9,7 +9,10 @@ const url = require('url');
const path = require('path');
const { dirname } = require('@joplin/lib/path-utils');
const fs = require('fs-extra');
const { ipcMain } = require('electron');
import { dialog, ipcMain } from 'electron';
import { _ } from '@joplin/lib/locale';
import restartInSafeModeFromMain from './utils/restartInSafeModeFromMain';
interface RendererProcessQuitReply {
canClose: boolean;
@@ -34,7 +37,7 @@ export default class ElectronAppWrapper {
private pluginWindows_: PluginWindows = {};
private initialCallbackUrl_: string = null;
public constructor(electronApp: any, env: string, profilePath: string, isDebugMode: boolean, initialCallbackUrl: string) {
public constructor(electronApp: any, env: string, profilePath: string|null, isDebugMode: boolean, initialCallbackUrl: string) {
this.electronApp_ = electronApp;
this.env_ = env;
this.isDebugMode_ = isDebugMode;
@@ -66,6 +69,42 @@ export default class ElectronAppWrapper {
return this.initialCallbackUrl_;
}
// Call when the app fails in a significant way.
//
// Assumes that the renderer process may be in an invalid state and so cannot
// be accessed.
public async handleAppFailure(errorMessage: string, canIgnore: boolean, isTesting?: boolean) {
const buttons = [];
buttons.push(_('Quit'));
const exitIndex = 0;
if (canIgnore) {
buttons.push(_('Ignore'));
}
const restartIndex = buttons.length;
buttons.push(_('Restart in safe mode'));
const { response } = await dialog.showMessageBox({
message: _('An error occurred: %s', errorMessage),
buttons,
});
if (response === restartIndex) {
await restartInSafeModeFromMain();
// A hung renderer seems to prevent the process from exiting completely.
// In this case, crashing the renderer allows the window to close.
//
// Also only run this if not testing (crashing the renderer breaks automated
// tests).
if (this.win_ && !this.win_.webContents.isCrashed() && !isTesting) {
this.win_.webContents.forcefullyCrashRenderer();
}
} else if (response === exitIndex) {
process.exit(1);
}
}
public createWindow() {
// Set to true to view errors if the application does not start
const debugEarlyBugs = this.env_ === 'dev' || this.isDebugMode_;
@@ -121,6 +160,20 @@ export default class ElectronAppWrapper {
this.win_.setPosition(primaryDisplayWidth / 2 - windowWidth, primaryDisplayHeight / 2 - windowHeight);
}
this.win_.webContents.on('unresponsive', async () => {
await this.handleAppFailure(_('Window unresponsive.'), true);
});
this.win_.webContents.on('render-process-gone', async _event => {
await this.handleAppFailure('Renderer process gone.', false);
});
this.win_.webContents.on('did-fail-load', async event => {
if ((event as any).isMainFrame) {
await this.handleAppFailure('Renderer process failed to load', false);
}
});
void this.win_.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',

View File

@@ -136,7 +136,11 @@ function CodeMirror(props: NoteBodyEditorProps, ref: ForwardedRef<NoteBodyEditor
editorRef.current.insertAtCursor(cmd.value.markdownTags.join('\n'));
} else if (cmd.value.type === 'files') {
const pos = cursorPositionToTextOffset(editorRef.current.getCursor(), props.content);
const newBody = await commandAttachFileToBody(props.content, cmd.value.paths, { createFileURL: !!cmd.value.createFileURL, position: pos });
const newBody = await commandAttachFileToBody(props.content, cmd.value.paths, {
createFileURL: !!cmd.value.createFileURL,
position: pos,
markupLanguage: props.contentMarkupLanguage,
});
editorRef.current.updateBody(newBody);
} else {
reg.logger().warn('CodeMirror: unsupported drop item: ', cmd);
@@ -214,7 +218,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: ForwardedRef<NoteBodyEditor
const cursor = editorRef.current.getCursor();
const pos = cursorPositionToTextOffset(cursor, props.content);
const newBody = await commandAttachFileToBody(props.content, null, { position: pos });
const newBody = await commandAttachFileToBody(props.content, null, { position: pos, markupLanguage: props.contentMarkupLanguage });
if (newBody) editorRef.current.updateBody(newBody);
},
textNumberedList: () => {
@@ -255,7 +259,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: ForwardedRef<NoteBodyEditor
},
};
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
}, [props.content, props.visiblePanes, addListItem, wrapSelectionWithStrings, setEditorPercentScroll, setViewerPercentScroll, resetScroll]);
}, [props.content, props.visiblePanes, props.contentMarkupLanguage, addListItem, wrapSelectionWithStrings, setEditorPercentScroll, setViewerPercentScroll, resetScroll]);
const onEditorPaste = useCallback(async (event: any = null) => {
const resourceMds = await getResourcesFromPasteEvent(event);

View File

@@ -151,6 +151,7 @@ const CodeMirror = (props: NoteBodyEditorProps, ref: ForwardedRef<NoteBodyEditor
editorCopyText, editorCutText, editorPaste,
editorContent: props.content,
visiblePanes: props.visiblePanes,
contentMarkupLanguage: props.contentMarkupLanguage,
});
useImperativeHandle(ref, () => {

View File

@@ -7,6 +7,7 @@ import dialogs from '../../../../dialogs';
import { EditorCommandType } from '@joplin/editor/types';
import Logger from '@joplin/utils/Logger';
import CodeMirrorControl from '@joplin/editor/CodeMirror/CodeMirrorControl';
import { MarkupLanguage } from '@joplin/renderer';
const logger = Logger.create('CodeMirror 6 commands');
@@ -40,6 +41,7 @@ interface Props {
selectionRange: { from: number; to: number };
visiblePanes: string[];
contentMarkupLanguage: MarkupLanguage;
}
const useEditorCommands = (props: Props) => {
@@ -57,7 +59,7 @@ const useEditorCommands = (props: Props) => {
editorRef.current.insertText(cmd.markdownTags.join('\n'));
} else if (cmd.type === 'files') {
const pos = props.selectionRange.from;
const newBody = await commandAttachFileToBody(props.editorContent, cmd.paths, { createFileURL: !!cmd.createFileURL, position: pos });
const newBody = await commandAttachFileToBody(props.editorContent, cmd.paths, { createFileURL: !!cmd.createFileURL, position: pos, markupLanguage: props.contentMarkupLanguage });
editorRef.current.updateBody(newBody);
} else {
logger.warn('CodeMirror: unsupported drop item: ', cmd);
@@ -92,7 +94,7 @@ const useEditorCommands = (props: Props) => {
insertText: (value: any) => editorRef.current.insertText(value),
attachFile: async () => {
const newBody = await commandAttachFileToBody(
props.editorContent, null, { position: props.selectionRange.from },
props.editorContent, null, { position: props.selectionRange.from, markupLanguage: props.contentMarkupLanguage },
);
if (newBody) {
editorRef.current.updateBody(newBody);
@@ -129,7 +131,7 @@ const useEditorCommands = (props: Props) => {
}, [
props.visiblePanes, props.editorContent, props.editorCopyText, props.editorCutText, props.editorPaste,
props.selectionRange,
props.contentMarkupLanguage,
props.webviewRef, editorRef,
]);
};

View File

@@ -2,9 +2,14 @@ import { CommandDeclaration } from '@joplin/lib/services/CommandService';
import { _ } from '@joplin/lib/locale';
import { joplinCommandToTinyMceCommands } from './NoteBody/TinyMCE/utils/joplinCommandToTinyMceCommands';
const workWithHtmlNotes = [
'attachFile',
];
export const enabledCondition = (commandName: string) => {
const markdownEditorOnly = !Object.keys(joplinCommandToTinyMceCommands).includes(commandName);
return `(!modalDialogVisible || gotoAnythingVisible) ${markdownEditorOnly ? '&& markdownEditorPaneVisible' : ''} && oneNoteSelected && noteIsMarkdown && !noteIsReadOnly`;
const noteMustBeMarkdown = !workWithHtmlNotes.includes(commandName);
return `(!modalDialogVisible || gotoAnythingVisible) ${markdownEditorOnly ? '&& markdownEditorPaneVisible' : ''} && oneNoteSelected ${noteMustBeMarkdown ? '&& noteIsMarkdown' : ''} && !noteIsReadOnly`;
};
const declarations: CommandDeclaration[] = [

View File

@@ -9,6 +9,7 @@ import htmlUtils from '@joplin/lib/htmlUtils';
import rendererHtmlUtils, { extractHtmlBody } from '@joplin/renderer/htmlUtils';
import Logger from '@joplin/utils/Logger';
import { fileUriToPath } from '@joplin/utils/url';
import { MarkupLanguage } from '@joplin/renderer';
const joplinRendererUtils = require('@joplin/renderer').utils;
const { clipboard } = require('electron');
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
@@ -62,6 +63,7 @@ export async function commandAttachFileToBody(body: string, filePaths: string[]
options = {
createFileURL: false,
position: 0,
markupLanguage: MarkupLanguage.Markdown,
...options,
};
@@ -79,6 +81,7 @@ export async function commandAttachFileToBody(body: string, filePaths: string[]
const newBody = await shim.attachFileToNoteBody(body, filePath, options.position, {
createFileURL: options.createFileURL,
resizeLargeImages: Setting.value('imageResizing'),
markupLanguage: options.markupLanguage,
});
if (!newBody) {

View File

@@ -2,6 +2,9 @@ import { test, expect } from './util/test';
import MainScreen from './models/MainScreen';
import activateMainMenuItem from './util/activateMainMenuItem';
import SettingsScreen from './models/SettingsScreen';
import { _electron as electron } from '@playwright/test';
import { writeFile } from 'fs-extra';
import { join } from 'path';
test.describe('main', () => {
@@ -121,4 +124,23 @@ test.describe('main', () => {
expect(await nextExternalUrlPromise).toBe(linkHref);
});
test('should start in safe mode if profile-dir/force-safe-mode-on-next-start exists', async ({ profileDirectory }) => {
await writeFile(join(profileDirectory, 'force-safe-mode-on-next-start'), 'true', 'utf8');
// We need to write to the force-safe-mode file before opening the Electron app.
// Open the app ourselves:
const startupArgs = [
'main.js', '--env', 'dev', '--profile', profileDirectory,
];
const electronApp = await electron.launch({ args: startupArgs });
const mainWindow = await electronApp.firstWindow();
const safeModeDisableLink = mainWindow.getByText('Disable safe mode and restart');
await safeModeDisableLink.waitFor();
await expect(safeModeDisableLink).toBeInViewport();
await electronApp.close();
});
});

View File

@@ -6,6 +6,7 @@ import uuid from '@joplin/lib/uuid';
type JoplinFixtures = {
profileDirectory: string;
electronApp: ElectronApplication;
mainWindow: Page;
};
@@ -20,19 +21,26 @@ export const test = base.extend<JoplinFixtures>({
// See https://github.com/microsoft/playwright/issues/8798
//
// eslint-disable-next-line no-empty-pattern
electronApp: async ({ }, use) => {
profileDirectory: async ({ }, use) => {
const profilePath = resolve(join(dirname(__dirname), 'test-profile'));
const profileSubdir = join(profilePath, uuid.createNano());
await mkdirp(profileSubdir);
const startupArgs = ['main.js', '--env', 'dev', '--profile', profileSubdir];
await use(profileSubdir);
await remove(profileSubdir);
},
electronApp: async ({ profileDirectory }, use) => {
const startupArgs = [
'main.js', '--env', 'dev', '--profile', profileDirectory,
];
const electronApp = await electron.launch({ args: startupArgs });
await use(electronApp);
await electronApp.firstWindow();
await electronApp.close();
await remove(profileSubdir);
},
mainWindow: async ({ electronApp }, use) => {

View File

@@ -31,117 +31,122 @@ const React = require('react');
const nodeSqlite = require('sqlite3');
const initLib = require('@joplin/lib/initLib').default;
if (bridge().env() === 'dev') {
const newConsole = function(oldConsole) {
const output = {};
const fnNames = ['assert', 'clear', 'context', 'count', 'countReset', 'debug', 'dir', 'dirxml', 'error', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'memory', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 'timeLog', 'timeStamp', 'trace', 'warn'];
for (const fnName of fnNames) {
if (fnName === 'warn') {
output.warn = function(...text) {
const s = [...text].join('');
// React spams the console with walls of warnings even outside of strict mode, and even after having renamed
// unsafe methods to UNSAFE_xxxx, so we need to hack the console to remove them...
if (s.indexOf('Warning: componentWillReceiveProps has been renamed, and is not recommended for use') === 0) return;
if (s.indexOf('Warning: componentWillUpdate has been renamed, and is not recommended for use.') === 0) return;
oldConsole.warn(...text);
};
} else {
output[fnName] = function(...text) {
return oldConsole[fnName](...text);
};
const main = async () => {
if (bridge().env() === 'dev') {
const newConsole = function(oldConsole) {
const output = {};
const fnNames = ['assert', 'clear', 'context', 'count', 'countReset', 'debug', 'dir', 'dirxml', 'error', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'memory', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 'timeLog', 'timeStamp', 'trace', 'warn'];
for (const fnName of fnNames) {
if (fnName === 'warn') {
output.warn = function(...text) {
const s = [...text].join('');
// React spams the console with walls of warnings even outside of strict mode, and even after having renamed
// unsafe methods to UNSAFE_xxxx, so we need to hack the console to remove them...
if (s.indexOf('Warning: componentWillReceiveProps has been renamed, and is not recommended for use') === 0) return;
if (s.indexOf('Warning: componentWillUpdate has been renamed, and is not recommended for use.') === 0) return;
oldConsole.warn(...text);
};
} else {
output[fnName] = function(...text) {
return oldConsole[fnName](...text);
};
}
}
}
return output;
}(window.console);
return output;
}(window.console);
window.console = newConsole;
}
window.console = newConsole;
}
// eslint-disable-next-line no-console
console.info(`Environment: ${bridge().env()}`);
// eslint-disable-next-line no-console
console.info(`Environment: ${bridge().env()}`);
const fsDriver = new FsDriverNode();
Logger.fsDriver_ = fsDriver;
Resource.fsDriver_ = fsDriver;
EncryptionService.fsDriver_ = fsDriver;
FileApiDriverLocal.fsDriver_ = fsDriver;
const fsDriver = new FsDriverNode();
Logger.fsDriver_ = fsDriver;
Resource.fsDriver_ = fsDriver;
EncryptionService.fsDriver_ = fsDriver;
FileApiDriverLocal.fsDriver_ = fsDriver;
// That's not good, but it's to avoid circular dependency issues
// in the BaseItem class.
BaseItem.loadClass('Note', Note);
BaseItem.loadClass('Folder', Folder);
BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);
// That's not good, but it's to avoid circular dependency issues
// in the BaseItem class.
BaseItem.loadClass('Note', Note);
BaseItem.loadClass('Folder', Folder);
BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);
Setting.setConstant('appId', `net.cozic.joplin${bridge().env() === 'dev' ? 'dev' : ''}-desktop`);
Setting.setConstant('appType', 'desktop');
Setting.setConstant('appId', `net.cozic.joplin${bridge().env() === 'dev' ? 'dev' : ''}-desktop`);
Setting.setConstant('appType', 'desktop');
// eslint-disable-next-line no-console
console.info(`appId: ${Setting.value('appId')}`);
// eslint-disable-next-line no-console
console.info(`appType: ${Setting.value('appType')}`);
// eslint-disable-next-line no-console
console.info(`appId: ${Setting.value('appId')}`);
// eslint-disable-next-line no-console
console.info(`appType: ${Setting.value('appType')}`);
let keytar;
try {
keytar = shim.platformSupportsKeyChain() ? require('keytar') : null;
} catch (error) {
console.error('Cannot load keytar - keychain support will be disabled', error);
keytar = null;
}
let keytar;
try {
keytar = shim.platformSupportsKeyChain() ? require('keytar') : null;
} catch (error) {
console.error('Cannot load keytar - keychain support will be disabled', error);
keytar = null;
}
function appVersion() {
const p = require('./packageInfo.js');
return p.version;
}
function appVersion() {
const p = require('./packageInfo.js');
return p.version;
}
shimInit({
keytar,
React,
appVersion,
electronBridge: bridge(),
nodeSqlite,
});
shimInit({
keytar,
React,
appVersion,
electronBridge: bridge(),
nodeSqlite,
});
// Disable drag and drop of links inside application (which would
// open it as if the whole app was a browser)
document.addEventListener('dragover', event => event.preventDefault());
document.addEventListener('drop', event => event.preventDefault());
// Disable drag and drop of links inside application (which would
// open it as if the whole app was a browser)
document.addEventListener('dragover', event => event.preventDefault());
document.addEventListener('drop', event => event.preventDefault());
// Disable middle-click (which would open a new browser window, but we don't want this)
document.addEventListener('auxclick', event => event.preventDefault());
// Disable middle-click (which would open a new browser window, but we don't want this)
document.addEventListener('auxclick', event => event.preventDefault());
// Each link (rendered as a button or list item) has its own custom click event
// so disable the default. In particular this will disable Ctrl+Clicking a link
// which would open a new browser window.
document.addEventListener('click', (event) => {
// We don't apply this to labels and inputs because it would break
// checkboxes. Such a global event handler is probably not a good idea
// anyway but keeping it for now, as it doesn't seem to break anything else.
// https://github.com/facebook/react/issues/13477#issuecomment-489274045
if (['LABEL', 'INPUT'].includes(event.target.nodeName)) return;
// Each link (rendered as a button or list item) has its own custom click event
// so disable the default. In particular this will disable Ctrl+Clicking a link
// which would open a new browser window.
document.addEventListener('click', (event) => {
// We don't apply this to labels and inputs because it would break
// checkboxes. Such a global event handler is probably not a good idea
// anyway but keeping it for now, as it doesn't seem to break anything else.
// https://github.com/facebook/react/issues/13477#issuecomment-489274045
if (['LABEL', 'INPUT'].includes(event.target.nodeName)) return;
event.preventDefault();
});
event.preventDefault();
});
const logger = new Logger();
Logger.initializeGlobalLogger(logger);
initLib(logger);
const logger = new Logger();
Logger.initializeGlobalLogger(logger);
initLib(logger);
app().start(bridge().processArgv()).then((result) => {
if (!result || !result.action) {
const startResult = await app().start(bridge().processArgv());
if (!startResult || !startResult.action) {
require('./gui/Root');
} else if (result.action === 'upgradeSyncTarget') {
} else if (startResult.action === 'upgradeSyncTarget') {
require('./gui/Root_UpgradeSyncTarget');
}
}).catch((error) => {
const env = bridge().env();
};
main().catch((error) => {
const env = bridge().env();
console.error(error);
let errorMessage;
if (error.code === 'flagError') {
bridge().showErrorMessageBox(error.message);
errorMessage = error.message;
} else {
// If something goes wrong at this stage we don't have a console or a log file
// so display the error in a message box.
@@ -150,13 +155,12 @@ app().start(bridge().processArgv()).then((result) => {
if (error.lineNumber) msg.push(error.lineNumber);
if (error.stack) msg.push(error.stack);
if (env === 'dev') {
console.error(error);
} else {
bridge().showErrorMessageBox(msg.join('\n\n'));
}
errorMessage = msg.join('\n\n');
}
// In dev, we leave the app open as debug statements in the console can be useful
if (env !== 'dev') bridge().electronApp().exit(1);
// In dev, we give the option to leave the app open as debug statements in the
// console can be useful
const canIgnore = env === 'dev';
bridge().electronApp().handleAppFailure(errorMessage, canIgnore);
});

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "2.13.3",
"version": "2.13.4",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,
@@ -119,21 +119,21 @@
"@joplin/tools": "~2.13",
"@playwright/test": "1.38.1",
"@testing-library/react-hooks": "8.0.1",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/node": "18.17.19",
"@types/react": "18.2.31",
"@types/react-redux": "7.1.27",
"@types/styled-components": "5.1.28",
"electron": "25.9.0",
"electron-builder": "24.4.0",
"electron": "25.9.1",
"electron-builder": "24.6.4",
"glob": "10.3.10",
"gulp": "4.0.2",
"jest": "29.6.4",
"jest-environment-jsdom": "29.6.4",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"js-sha512": "0.8.0",
"nan": "2.18.0",
"react-test-renderer": "18.2.0",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"optionalDependencies": {
"7zip-bin-linux": "^1.0.1",
@@ -142,7 +142,7 @@
},
"dependencies": {
"@electron/notarize": "2.1.0",
"@electron/remote": "2.0.11",
"@electron/remote": "2.0.12",
"@fortawesome/fontawesome-free": "5.15.4",
"@joeattardi/emoji-button": "4.6.4",
"@joplin/editor": "~2.13",

View File

@@ -57,9 +57,12 @@ export default class PlatformImplementation extends BasePlatformImplementation {
this.joplin_ = {
views: {
dialogs: {
showMessageBox: async function(message: string) {
showMessageBox: async (message: string) => {
return bridge().showMessageBox(message);
},
showOpenDialog: async (options) => {
return bridge().showOpenDialog(options);
},
},
},
};

View File

@@ -0,0 +1,45 @@
let currentProfileDirectory: string;
jest.doMock('../bridge', () => ({
// Mock the bridge functions used by restartInSafeModeFromMain
// to remove the dependency on Electron.
default: () => ({
restart: jest.fn(),
processArgv: () => [
// The argument parser expects the first two arguments to
// be the path to NodeJS and the second to be the main filename.
process.argv[0], __filename,
// Only the following arguments are used.
'--profile', currentProfileDirectory,
],
env: () => 'dev',
}),
}));
import { mkdtemp, readFile, remove } from 'fs-extra';
import restartInSafeModeFromMain from './restartInSafeModeFromMain';
import { tmpdir } from 'os';
import { join } from 'path';
import { safeModeFlagFilename } from '@joplin/lib/BaseApplication';
describe('restartInSafeModeFromMain', () => {
beforeEach(async () => {
currentProfileDirectory = await mkdtemp(join(tmpdir(), 'safemode-restart-test'));
});
afterEach(async () => {
await remove(currentProfileDirectory);
});
test('should create a safe mode flag file', async () => {
await restartInSafeModeFromMain();
const safeModeFlagFilepath = join(
currentProfileDirectory, safeModeFlagFilename,
);
expect(await readFile(safeModeFlagFilepath, 'utf8')).toBe('true');
});
});

View File

@@ -0,0 +1,33 @@
import Setting from '@joplin/lib/models/Setting';
import bridge from '../bridge';
import processStartFlags from '@joplin/lib/utils/processStartFlags';
import BaseApplication, { safeModeFlagFilename } from '@joplin/lib/BaseApplication';
import initProfile from '@joplin/lib/services/profileConfig/initProfile';
import { writeFile } from 'fs-extra';
import { join } from 'path';
const restartInSafeModeFromMain = async () => {
// Only set constants here -- the main process doesn't have easy access (without loading
// a large amount of other code) to the database.
const appName = `joplin${bridge().env() === 'dev' ? 'dev' : ''}-desktop`;
Setting.setConstant('appId', `net.cozic.${appName}`);
Setting.setConstant('appType', 'desktop');
Setting.setConstant('appName', appName);
// Load just enough for us to write a file in the profile directory
const { shimInit } = require('@joplin/lib/shim-init-node.js');
shimInit({});
const startFlags = await processStartFlags(bridge().processArgv());
const rootProfileDir = BaseApplication.determineProfileDir(startFlags.matched);
const { profileDir } = await initProfile(rootProfileDir);
// We can't access the database, so write to a file instead.
const safeModeFlagFile = join(profileDir, safeModeFlagFilename);
await writeFile(safeModeFlagFile, 'true', 'utf8');
bridge().restart();
};
export default restartInSafeModeFromMain;

View File

@@ -110,8 +110,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097724
versionName "2.13.4"
versionCode 2097725
versionName "2.13.5"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

View File

@@ -16,11 +16,13 @@ const logger = Logger.create('ImageEditor');
type OnSaveCallback = (svgData: string)=> void;
type OnCancelCallback = ()=> void;
// Returns the empty string to load from a template.
type LoadInitialSVGCallback = ()=> Promise<string>;
interface Props {
themeId: number;
loadInitialSVGData: LoadInitialSVGCallback|null;
loadInitialSVGData: LoadInitialSVGCallback;
onSave: OnSaveCallback;
onExit: OnCancelCallback;
}

View File

@@ -727,7 +727,7 @@ class NoteScreenComponent extends BaseScreenComponent {
resource = await Resource.save(resource, { isNew: true });
const resourceTag = Resource.markdownTag(resource);
const resourceTag = Resource.markupTag(resource);
const newNote = { ...this.state.note };
@@ -815,12 +815,7 @@ class NoteScreenComponent extends BaseScreenComponent {
private drawPicture_onPress = async () => {
// Create a new empty drawing and attach it now.
const resource = await this.attachNewDrawing('');
this.setState({
showImageEditor: true,
loadImageEditorData: null,
imageEditorResource: resource,
});
await this.editDrawing(resource);
};
private async updateDrawing(svgData: string) {

View File

@@ -381,10 +381,16 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Joplin/Pods-Joplin-frameworks.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-Glog/glog.framework/glog",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
);
runOnlyForDeploymentPostprocessing = 0;

View File

@@ -1,5 +1,6 @@
PODS:
- boost (1.76.0)
- CocoaAsyncSocket (7.6.5)
- DoubleConversion (1.1.6)
- FBLazyVector (0.71.10)
- FBReactNativeSpec (0.71.10):
@@ -9,6 +10,67 @@ PODS:
- React-Core (= 0.71.10)
- React-jsi (= 0.71.10)
- ReactCommon/turbomodule/core (= 0.71.10)
- Flipper (0.125.0):
- Flipper-Folly (~> 2.6)
- Flipper-RSocket (~> 1.4)
- Flipper-Boost-iOSX (1.76.0.1.11)
- Flipper-DoubleConversion (3.2.0.1)
- Flipper-Fmt (7.1.7)
- Flipper-Folly (2.6.10):
- Flipper-Boost-iOSX
- Flipper-DoubleConversion
- Flipper-Fmt (= 7.1.7)
- Flipper-Glog
- libevent (~> 2.1.12)
- OpenSSL-Universal (= 1.1.1100)
- Flipper-Glog (0.5.0.5)
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.4.3):
- Flipper-Folly (~> 2.6)
- FlipperKit (0.125.0):
- FlipperKit/Core (= 0.125.0)
- FlipperKit/Core (0.125.0):
- Flipper (~> 0.125.0)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- SocketRocket (~> 0.6.0)
- FlipperKit/CppBridge (0.125.0):
- Flipper (~> 0.125.0)
- FlipperKit/FBCxxFollyDynamicConvert (0.125.0):
- Flipper-Folly (~> 2.6)
- FlipperKit/FBDefines (0.125.0)
- FlipperKit/FKPortForwarding (0.125.0):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.125.0)
- FlipperKit/FlipperKitLayoutHelpers (0.125.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- FlipperKit/FlipperKitLayoutIOSDescriptors (0.125.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutHelpers
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutPlugin (0.125.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutHelpers
- FlipperKit/FlipperKitLayoutIOSDescriptors
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.125.0)
- FlipperKit/FlipperKitNetworkPlugin (0.125.0):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.125.0):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.125.0):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.125.0):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- fmt (6.2.1)
- glog (0.3.5)
- hermes-engine (0.71.10):
@@ -19,6 +81,7 @@ PODS:
- JoplinCommonShareExtension
- React
- libevent (2.1.12)
- OpenSSL-Universal (1.1.1100)
- RCT-Folly (2021.07.22.00):
- boost
- DoubleConversion
@@ -398,7 +461,7 @@ PODS:
- React-Core
- RNCPushNotificationIOS (1.11.0):
- React-Core
- RNDateTimePicker (7.6.0):
- RNDateTimePicker (7.6.1):
- React-Core
- RNDeviceInfo (10.11.0):
- React-Core
@@ -425,19 +488,44 @@ PODS:
- RNZipArchive/Core (6.1.0):
- React-Core
- SSZipArchive (~> 2.2)
- SocketRocket (0.6.0)
- SSZipArchive (2.4.3)
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- Flipper (= 0.125.0)
- Flipper-Boost-iOSX (= 1.76.0.1.11)
- Flipper-DoubleConversion (= 3.2.0.1)
- Flipper-Fmt (= 7.1.7)
- Flipper-Folly (= 2.6.10)
- Flipper-Glog (= 0.5.0.5)
- Flipper-PeerTalk (= 0.0.4)
- Flipper-RSocket (= 1.4.3)
- FlipperKit (= 0.125.0)
- FlipperKit/Core (= 0.125.0)
- FlipperKit/CppBridge (= 0.125.0)
- FlipperKit/FBCxxFollyDynamicConvert (= 0.125.0)
- FlipperKit/FBDefines (= 0.125.0)
- FlipperKit/FKPortForwarding (= 0.125.0)
- FlipperKit/FlipperKitHighlightOverlay (= 0.125.0)
- FlipperKit/FlipperKitLayoutPlugin (= 0.125.0)
- FlipperKit/FlipperKitLayoutTextSearchable (= 0.125.0)
- FlipperKit/FlipperKitNetworkPlugin (= 0.125.0)
- FlipperKit/FlipperKitReactPlugin (= 0.125.0)
- FlipperKit/FlipperKitUserDefaultsPlugin (= 0.125.0)
- FlipperKit/SKIOSNetworkPlugin (= 0.125.0)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
- JoplinCommonShareExtension (from `ShareExtension`)
- JoplinRNShareExtension (from `ShareExtension`)
- libevent (~> 2.1.12)
- OpenSSL-Universal (= 1.1.1100)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
@@ -445,6 +533,7 @@ DEPENDENCIES:
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
- React-Codegen (from `build/generated/ios`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
@@ -500,9 +589,22 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- CocoaAsyncSocket
- Flipper
- Flipper-Boost-iOSX
- Flipper-DoubleConversion
- Flipper-Fmt
- Flipper-Folly
- Flipper-Glog
- Flipper-PeerTalk
- Flipper-RSocket
- FlipperKit
- fmt
- libevent
- OpenSSL-Universal
- SocketRocket
- SSZipArchive
- YogaKit
EXTERNAL SOURCES:
boost:
@@ -640,15 +742,26 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: 57d2868c099736d80fcd648bf211b4431e51a558
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
FBLazyVector: ddb55c55295ea51ed98aa7e2e08add2f826309d5
FBReactNativeSpec: 90fc1a90b4b7a171e0a7c20ea426c1bf6ce4399c
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30
Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b
Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3
Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
hermes-engine: d27603b55a48402501ad1928c05411dae9cd6b85
JoplinCommonShareExtension: a8b60b02704d85a7305627912c0240e94af78db7
JoplinRNShareExtension: 485f3e6dad83b7b77f1572eabc249f869ee55c02
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
RCTRequired: 8ef706f91e2b643cd32c26a57700b5f24fab0585
RCTTypeSafety: 5fbddd8eb9242b91ac0d901c01da3673f358b1b7
@@ -695,7 +808,7 @@ SPEC CHECKSUMS:
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495
RNCPushNotificationIOS: 64218f3c776c03d7408284a819b2abfda1834bc8
RNDateTimePicker: ccd988deb223cbb2e669e157ec576c2c6217128c
RNDateTimePicker: 8fb39263b721223e095248acaf6f406d5b7f6713
RNDeviceInfo: bf8a32acbcb875f568217285d1793b0e8588c974
RNExitApp: 00036cabe7bacbb413d276d5520bf74ba39afa6a
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
@@ -706,9 +819,11 @@ SPEC CHECKSUMS:
RNShare: 32e97adc8d8c97d4a26bcdd3c45516882184f8b6
RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9
RNZipArchive: ef9451b849c45a29509bf44e65b788829ab07801
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
Yoga: e7ea9e590e27460d28911403b894722354d73479
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: 3b2cace838120977b5b54871752c9dddf5a11cea
COCOAPODS: 1.12.1
COCOAPODS: 1.14.2

View File

@@ -26,7 +26,7 @@
"@joplin/renderer": "~2.13",
"@joplin/utils": "~2.13",
"@react-native-community/clipboard": "1.5.1",
"@react-native-community/datetimepicker": "7.6.0",
"@react-native-community/datetimepicker": "7.6.1",
"@react-native-community/geolocation": "3.1.0",
"@react-native-community/netinfo": "9.4.1",
"@react-native-community/push-notification-ios": "1.11.0",
@@ -94,18 +94,18 @@
"@testing-library/react-native": "12.3.0",
"@tsconfig/react-native": "2.0.2",
"@types/fs-extra": "11.0.2",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/react": "18.2.31",
"@types/react-native": "0.70.6",
"@types/react-redux": "7.1.27",
"@types/tar-stream": "2.2.3",
"babel-jest": "29.6.4",
"babel-jest": "29.7.0",
"babel-plugin-module-resolver": "4.1.0",
"execa": "4.1.0",
"fs-extra": "11.1.1",
"gulp": "4.0.2",
"jest": "29.6.4",
"jest-environment-jsdom": "29.6.4",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"jetifier": "2.0.0",
"js-draw": "1.5.0",
"jsdom": "22.1.0",
@@ -117,7 +117,7 @@
"ts-jest": "29.1.1",
"ts-loader": "9.4.4",
"ts-node": "10.9.1",
"typescript": "5.1.6",
"typescript": "5.2.2",
"uglify-js": "3.17.4",
"webpack": "5.74.0"
}

View File

@@ -8,11 +8,12 @@
.docusaurus
.cache-loader
# Docs are auto-generated using processDoc.js
# Folders that are auto-generated using processDocs.js
/docs
/help
/blog
/news
/i18n
# Misc
.DS_Store

View File

@@ -27,7 +27,7 @@ const config = {
// to replace "en" with "zh-Hans".
i18n: {
defaultLocale: 'en',
locales: ['en'],
locales: ['en', 'fr'],
},
plugins: [
@@ -116,6 +116,10 @@ const config = {
className: 'navbar-custom-buttons sponsor-button',
target: '_self',
},
{
type: 'localeDropdown',
position: 'right',
},
],
},
footer: {

View File

@@ -6,7 +6,6 @@
"scripts": {
"tsc": "tsc --project tsconfig.json",
"watch": "tsc --watch --preserveWatchOutput --project tsconfig.json",
"postinstall": "yarn run tsc",
"test": "jest",
"test-ci": "yarn test"
},
@@ -17,14 +16,14 @@
"devDependencies": {
"@joplin/lib": "~2.13",
"@testing-library/react-hooks": "8.0.1",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/react": "18.2.31",
"@types/react-redux": "7.1.27",
"@types/styled-components": "5.1.28",
"jest": "29.6.3",
"jest-environment-jsdom": "29.6.3",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"ts-jest": "29.1.1",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"dependencies": {
"@codemirror/autocomplete": "6.9.2",

View File

@@ -45,16 +45,16 @@
"entities": "2.2.0"
},
"devDependencies": {
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/node": "18.17.19",
"@typescript-eslint/eslint-plugin": "6.0.0",
"@typescript-eslint/parser": "6.0.0",
"@typescript-eslint/eslint-plugin": "6.7.2",
"@typescript-eslint/parser": "6.7.2",
"coveralls": "3.1.1",
"eslint": "8.47.0",
"jest": "29.6.4",
"prettier": "3.0.0",
"eslint": "8.49.0",
"jest": "29.7.0",
"prettier": "3.0.3",
"ts-jest": "29.1.1",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"jest": {
"preset": "ts-jest",

View File

@@ -43,6 +43,12 @@ export default class JoplinViewsDialogs {
* Displays a message box with OK/Cancel buttons. Returns the button index that was clicked - "0" for OK and "1" for "Cancel"
*/
showMessageBox(message: string): Promise<number>;
/**
* Displays a dialog to select a file or a directory. Same options and
* output as
* https://www.electronjs.org/docs/latest/api/dialog#dialogshowopendialogbrowserwindow-options
*/
showOpenDialog(options: any): Promise<any>;
/**
* Sets the dialog HTML content
*/

View File

@@ -1,5 +1,5 @@
import { Size } from './types';
type ListRendererDatabaseDependency = 'folder.created_time' | 'folder.encryption_applied' | 'folder.encryption_cipher_text' | 'folder.icon' | 'folder.id' | 'folder.is_shared' | 'folder.master_key_id' | 'folder.parent_id' | 'folder.share_id' | 'folder.title' | 'folder.updated_time' | 'folder.user_created_time' | 'folder.user_updated_time' | 'folder.type_' | 'note.altitude' | 'note.application_data' | 'note.author' | 'note.body' | 'note.conflict_original_id' | 'note.created_time' | 'note.encryption_applied' | 'note.encryption_cipher_text' | 'note.id' | 'note.is_conflict' | 'note.is_shared' | 'note.is_todo' | 'note.latitude' | 'note.longitude' | 'note.markup_language' | 'note.master_key_id' | 'note.order' | 'note.parent_id' | 'note.share_id' | 'note.source' | 'note.source_application' | 'note.source_url' | 'note.title' | 'note.todo_completed' | 'note.todo_due' | 'note.updated_time' | 'note.user_created_time' | 'note.user_data' | 'note.user_updated_time' | 'note.type_';
type ListRendererDatabaseDependency = 'folder.created_time' | 'folder.encryption_applied' | 'folder.encryption_cipher_text' | 'folder.icon' | 'folder.id' | 'folder.is_shared' | 'folder.master_key_id' | 'folder.parent_id' | 'folder.share_id' | 'folder.title' | 'folder.updated_time' | 'folder.user_created_time' | 'folder.user_data' | 'folder.user_updated_time' | 'folder.type_' | 'note.altitude' | 'note.application_data' | 'note.author' | 'note.body' | 'note.conflict_original_id' | 'note.created_time' | 'note.encryption_applied' | 'note.encryption_cipher_text' | 'note.id' | 'note.is_conflict' | 'note.is_shared' | 'note.is_todo' | 'note.latitude' | 'note.longitude' | 'note.markup_language' | 'note.master_key_id' | 'note.order' | 'note.parent_id' | 'note.share_id' | 'note.source' | 'note.source_application' | 'note.source_url' | 'note.title' | 'note.todo_completed' | 'note.todo_due' | 'note.updated_time' | 'note.user_created_time' | 'note.user_data' | 'note.user_updated_time' | 'note.type_';
export declare enum ItemFlow {
TopToBottom = "topToBottom",
LeftToRight = "leftToRight"

View File

@@ -3,7 +3,7 @@
import { Size } from './types';
// AUTO-GENERATED by generate-database-type
type ListRendererDatabaseDependency = 'folder.created_time' | 'folder.encryption_applied' | 'folder.encryption_cipher_text' | 'folder.icon' | 'folder.id' | 'folder.is_shared' | 'folder.master_key_id' | 'folder.parent_id' | 'folder.share_id' | 'folder.title' | 'folder.updated_time' | 'folder.user_created_time' | 'folder.user_updated_time' | 'folder.type_' | 'note.altitude' | 'note.application_data' | 'note.author' | 'note.body' | 'note.conflict_original_id' | 'note.created_time' | 'note.encryption_applied' | 'note.encryption_cipher_text' | 'note.id' | 'note.is_conflict' | 'note.is_shared' | 'note.is_todo' | 'note.latitude' | 'note.longitude' | 'note.markup_language' | 'note.master_key_id' | 'note.order' | 'note.parent_id' | 'note.share_id' | 'note.source' | 'note.source_application' | 'note.source_url' | 'note.title' | 'note.todo_completed' | 'note.todo_due' | 'note.updated_time' | 'note.user_created_time' | 'note.user_data' | 'note.user_updated_time' | 'note.type_';
type ListRendererDatabaseDependency = 'folder.created_time' | 'folder.encryption_applied' | 'folder.encryption_cipher_text' | 'folder.icon' | 'folder.id' | 'folder.is_shared' | 'folder.master_key_id' | 'folder.parent_id' | 'folder.share_id' | 'folder.title' | 'folder.updated_time' | 'folder.user_created_time' | 'folder.user_data' | 'folder.user_updated_time' | 'folder.type_' | 'note.altitude' | 'note.application_data' | 'note.author' | 'note.body' | 'note.conflict_original_id' | 'note.created_time' | 'note.encryption_applied' | 'note.encryption_cipher_text' | 'note.id' | 'note.is_conflict' | 'note.is_shared' | 'note.is_todo' | 'note.latitude' | 'note.longitude' | 'note.markup_language' | 'note.master_key_id' | 'note.order' | 'note.parent_id' | 'note.share_id' | 'note.source' | 'note.source_application' | 'note.source_url' | 'note.title' | 'note.todo_completed' | 'note.todo_due' | 'note.updated_time' | 'note.user_created_time' | 'note.user_data' | 'note.user_updated_time' | 'note.type_';
// AUTO-GENERATED by generate-database-type
export enum ItemFlow {

View File

@@ -29,7 +29,7 @@
"yosay": "2.0.2"
},
"devDependencies": {
"jest": "29.6.4"
"jest": "29.7.0"
},
"repository": "https://github.com/laurent22/generator-joplin",
"license": "AGPL-3.0-or-later",

View File

@@ -6,7 +6,7 @@ import BaseService from './services/BaseService';
import reducer, { getNotesParent, serializeNotesParent, setStore, State } from './reducer';
import KeychainServiceDriver from './services/keychain/KeychainServiceDriver.node';
import KeychainServiceDriverDummy from './services/keychain/KeychainServiceDriver.dummy';
import { _, setLocale } from './locale';
import { setLocale } from './locale';
import KvStore from './services/KvStore';
import SyncTargetJoplinServer from './SyncTargetJoplinServer';
import SyncTargetOneDrive from './SyncTargetOneDrive';
@@ -26,8 +26,7 @@ import time from './time';
import BaseSyncTarget from './BaseSyncTarget';
const reduxSharedMiddleware = require('./components/shared/reduxSharedMiddleware');
const os = require('os');
const fs = require('fs-extra');
import JoplinError from './JoplinError';
import fs = require('fs-extra');
const EventEmitter = require('events');
const syswidecas = require('./vendor/syswide-cas');
import SyncTargetRegistry from './SyncTargetRegistry';
@@ -60,6 +59,8 @@ import { ProfileConfig } from './services/profileConfig/types';
import initProfile from './services/profileConfig/initProfile';
import { parseShareCache } from './services/share/reducer';
import RotatingLogs from './RotatingLogs';
import { join } from 'path';
import processStartFlags, { MatchedStartFlags } from './utils/processStartFlags';
const appLogger: LoggerWrapper = Logger.create('App');
@@ -70,6 +71,7 @@ interface StartOptions {
keychainEnabled?: boolean;
setupGlobalLogger?: boolean;
}
export const safeModeFlagFilename = 'force-safe-mode-on-next-start';
export default class BaseApplication {
@@ -163,154 +165,15 @@ export default class BaseApplication {
// Handles the initial flags passed to main script and
// returns the remaining args.
private async handleStartFlags_(argv: string[], setDefaults = true) {
const matched: any = {};
argv = argv.slice(0);
argv.splice(0, 2); // First arguments are the node executable, and the node JS file
const flags = await processStartFlags(argv, setDefaults);
while (argv.length) {
const arg = argv[0];
const nextArg = argv.length >= 2 ? argv[1] : null;
if (arg === '--profile') {
if (!nextArg) throw new JoplinError(_('Usage: %s', '--profile <dir-path>'), 'flagError');
matched.profileDir = nextArg;
argv.splice(0, 2);
continue;
}
if (arg === '--no-welcome') {
matched.welcomeDisabled = true;
argv.splice(0, 1);
continue;
}
if (arg === '--env') {
if (!nextArg) throw new JoplinError(_('Usage: %s', '--env <dev|prod>'), 'flagError');
matched.env = nextArg;
argv.splice(0, 2);
continue;
}
if (arg === '--is-demo') {
Setting.setConstant('isDemo', true);
argv.splice(0, 1);
continue;
}
if (arg === '--safe-mode') {
matched.isSafeMode = true;
argv.splice(0, 1);
continue;
}
if (arg === '--open-dev-tools') {
Setting.setConstant('flagOpenDevTools', true);
argv.splice(0, 1);
continue;
}
if (arg === '--debug') {
// Currently only handled by ElectronAppWrapper (isDebugMode property)
argv.splice(0, 1);
continue;
}
if (arg === '--update-geolocation-disabled') {
Note.updateGeolocationEnabled_ = false;
argv.splice(0, 1);
continue;
}
if (arg === '--stack-trace-enabled') {
this.showStackTraces_ = true;
argv.splice(0, 1);
continue;
}
if (arg === '--log-level') {
if (!nextArg) throw new JoplinError(_('Usage: %s', '--log-level <none|error|warn|info|debug>'), 'flagError');
matched.logLevel = Logger.levelStringToId(nextArg);
argv.splice(0, 2);
continue;
}
if (arg.indexOf('-psn') === 0) {
// Some weird flag passed by macOS - can be ignored.
// https://github.com/laurent22/joplin/issues/480
// https://stackoverflow.com/questions/10242115
argv.splice(0, 1);
continue;
}
if (arg === '--enable-logging') {
// Electron-specific flag used for debugging - ignore it
argv.splice(0, 1);
continue;
}
if (arg === '--dev-plugins') {
Setting.setConstant('startupDevPlugins', nextArg.split(',').map(p => p.trim()));
argv.splice(0, 2);
continue;
}
if (arg.indexOf('--remote-debugging-port=') === 0) {
// Electron-specific flag used for debugging - ignore it. Electron expects this flag in '--x=y' form, a single string.
argv.splice(0, 1);
continue;
}
if (arg === '--no-sandbox') {
// Electron-specific flag for running the app without chrome-sandbox
// Allows users to use it as a workaround for the electron+AppImage issue
// https://github.com/laurent22/joplin/issues/2246
argv.splice(0, 1);
continue;
}
if (arg.indexOf('--user-data-dir=') === 0) {
// Electron-specific flag. Allows users to run the app with chromedriver.
argv.splice(0, 1);
continue;
}
if (arg.indexOf('--enable-features=') === 0) {
// Electron-specific flag - ignore it
// Allows users to run the app on native wayland
argv.splice(0, 1);
continue;
}
if (arg.indexOf('--ozone-platform=') === 0) {
// Electron-specific flag - ignore it
// Allows users to run the app on native wayland
argv.splice(0, 1);
continue;
}
if (arg === '--disable-smooth-scrolling') {
// Electron-specific flag - ignore it
// Allows users to disable smooth scrolling
argv.splice(0, 1);
continue;
}
if (arg.length && arg[0] === '-') {
throw new JoplinError(_('Unknown flag: %s', arg), 'flagError');
} else {
break;
}
}
if (setDefaults) {
if (!matched.logLevel) matched.logLevel = Logger.LEVEL_INFO;
if (!matched.env) matched.env = 'prod';
if (!matched.devPlugins) matched.devPlugins = [];
if (flags.matched.showStackTraces) {
this.showStackTraces_ = true;
}
return {
matched: matched,
argv: argv,
matched: flags.matched,
argv: flags.argv,
};
}
@@ -725,7 +588,7 @@ export default class BaseApplication {
return flags.matched;
}
public determineProfileDir(initArgs: any) {
public static determineProfileDir(initArgs: MatchedStartFlags) {
let output = '';
if (initArgs.profileDir) {
@@ -773,7 +636,7 @@ export default class BaseApplication {
// https://immerjs.github.io/immer/docs/freezing
setAutoFreeze(initArgs.env === 'dev');
const rootProfileDir = this.determineProfileDir(initArgs);
const rootProfileDir = BaseApplication.determineProfileDir(initArgs);
const { profileDir, profileConfig, isSubProfile } = await initProfile(rootProfileDir);
this.profileConfig_ = profileConfig;
@@ -863,6 +726,13 @@ export default class BaseApplication {
Setting.setValue('isSafeMode', true);
}
const safeModeFlagFile = join(profileDir, safeModeFlagFilename);
if (await fs.pathExists(safeModeFlagFile) && fs.readFileSync(safeModeFlagFile, 'utf8') === 'true') {
appLogger.info(`Safe mode enabled because of file: ${safeModeFlagFile}`);
Setting.setValue('isSafeMode', true);
fs.removeSync(safeModeFlagFile);
}
if (Setting.value('firstStart')) {
const locale = shim.detectAndSetLocale(Setting);
reg.logger().info(`First start: detected locale as ${locale}`);

View File

@@ -16,6 +16,8 @@ import itemCanBeEncrypted from './utils/itemCanBeEncrypted';
import { getEncryptionEnabled } from '../services/synchronizer/syncInfoUtils';
import ShareService from '../services/share/ShareService';
import { SaveOptions } from './utils/types';
import { MarkupLanguage } from '@joplin/renderer';
import { htmlentities } from '@joplin/utils/html';
export default class Resource extends BaseItem {
@@ -231,18 +233,28 @@ export default class Resource extends BaseItem {
return { path: encryptedPath, resource: resourceCopy };
}
public static markdownTag(resource: any) {
public static markupTag(resource: any, markupLanguage: MarkupLanguage = MarkupLanguage.Markdown) {
let tagAlt = resource.alt ? resource.alt : resource.title;
if (!tagAlt) tagAlt = '';
const lines = [];
if (Resource.isSupportedImageMimeType(resource.mime)) {
lines.push('![');
lines.push(markdownUtils.escapeTitleText(tagAlt));
lines.push(`](:/${resource.id})`);
if (markupLanguage === MarkupLanguage.Markdown) {
lines.push('![');
lines.push(markdownUtils.escapeTitleText(tagAlt));
lines.push(`](:/${resource.id})`);
} else {
const altHtml = tagAlt ? `alt="${htmlentities(tagAlt)}"` : '';
lines.push(`<img src=":/${resource.id}" ${altHtml}/>`);
}
} else {
lines.push('[');
lines.push(markdownUtils.escapeTitleText(tagAlt));
lines.push(`](:/${resource.id})`);
if (markupLanguage === MarkupLanguage.Markdown) {
lines.push('[');
lines.push(markdownUtils.escapeTitleText(tagAlt));
lines.push(`](:/${resource.id})`);
} else {
const altHtml = tagAlt ? `alt="${htmlentities(tagAlt)}"` : '';
lines.push(`<a href=":/${resource.id}" ${altHtml}>${htmlentities(tagAlt ? tagAlt : resource.id)}</a>`);
}
}
return lines.join('');
}
@@ -444,7 +456,7 @@ export default class Resource extends BaseItem {
await Note.save({
title: _('Attachment conflict: "%s"', resource.title),
body: _('There was a [conflict](%s) on the attachment below.\n\n%s', 'https://joplinapp.org/help/apps/conflict', Resource.markdownTag(conflictResource)),
body: _('There was a [conflict](%s) on the attachment below.\n\n%s', 'https://joplinapp.org/help/apps/conflict', Resource.markupTag(conflictResource)),
parent_id: await this.resourceConflictFolderId(),
}, { changeSource: ItemChange.SOURCE_SYNC });
}

View File

@@ -17,16 +17,16 @@
},
"devDependencies": {
"@types/fs-extra": "11.0.2",
"@types/jest": "29.5.4",
"@types/js-yaml": "4.0.6",
"@types/jest": "29.5.5",
"@types/js-yaml": "4.0.7",
"@types/node": "18.17.19",
"@types/node-rsa": "1.1.2",
"@types/react": "18.2.31",
"@types/uuid": "9.0.5",
"clean-html": "1.5.0",
"jest": "29.6.4",
"jest": "29.7.0",
"sharp": "0.32.6",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"dependencies": {
"@aws-sdk/client-s3": "3.296.0",

View File

@@ -63,7 +63,7 @@ describe('services/ResourceService', () => {
await service.indexNoteResources();
await Note.save({ id: note2.id, body: Resource.markdownTag(resource1) });
await Note.save({ id: note2.id, body: Resource.markupTag(resource1) });
await service.indexNoteResources();

View File

@@ -7,6 +7,7 @@ import { Implementation as ImagingImplementation } from './api/JoplinImaging';
export interface JoplinViewsDialogs {
showMessageBox(message: string): Promise<number>;
showOpenDialog(options: any): Promise<any>;
}
export interface JoplinViews {

View File

@@ -5,6 +5,7 @@ import createViewHandle from '../utils/createViewHandle';
import WebviewController, { ContainerType } from '../WebviewController';
import { ButtonSpec, ViewHandle, DialogResult } from './types';
import { _ } from '../../../locale';
import { JoplinViewsDialogs as JoplinViewsDialogsImplementation } from '../BasePlatformImplementation';
/**
* Allows creating and managing dialogs. A dialog is modal window that
@@ -39,7 +40,7 @@ export default class JoplinViewsDialogs {
private store: any;
private plugin: Plugin;
private implementation_: any;
private implementation_: JoplinViewsDialogsImplementation;
public constructor(implementation: any, plugin: Plugin, store: any) {
this.store = store;
@@ -73,6 +74,15 @@ export default class JoplinViewsDialogs {
return this.implementation_.showMessageBox(`${_('(In plugin: %s)', this.plugin.manifest.name)}\n\n${message}`);
}
/**
* Displays a dialog to select a file or a directory. Same options and
* output as
* https://www.electronjs.org/docs/latest/api/dialog#dialogshowopendialogbrowserwindow-options
*/
public async showOpenDialog(options: any): Promise<any> {
return this.implementation_.showOpenDialog(options);
}
/**
* Sets the dialog HTML content
*/

View File

@@ -332,7 +332,7 @@ function shimInit(options = null) {
};
shim.attachFileToNoteBody = async function(noteBody, filePath, position = null, options = null) {
options = { createFileURL: false, ...options };
options = { createFileURL: false, markupLanguage: 1, ...options };
const { basename } = require('path');
const { escapeTitleText } = require('./markdownUtils').default;
@@ -353,7 +353,7 @@ function shimInit(options = null) {
if (noteBody && position) newBody.push(noteBody.substr(0, position));
if (!options.createFileURL) {
newBody.push(Resource.markdownTag(resource));
newBody.push(Resource.markupTag(resource, options.markupLanguage));
} else {
const filename = escapeTitleText(basename(filePath)); // to get same filename as standard drag and drop
const fileURL = `[${filename}](${toFileProtocolPath(filePath)})`;
@@ -366,6 +366,8 @@ function shimInit(options = null) {
};
shim.attachFileToNote = async function(note, filePath, position = null, options = null) {
if (!options) options = {};
if (note.markup_language) options.markupLanguage = note.markup_language;
const newBody = await shim.attachFileToNoteBody(note.body, filePath, position, options);
if (!newBody) return null;

View File

@@ -0,0 +1,174 @@
import Logger, { LogLevel } from '@joplin/utils/Logger';
import JoplinError from '../JoplinError';
import { _ } from '../locale';
import Setting from '../models/Setting';
import Note from '../models/Note';
export interface MatchedStartFlags {
profileDir?: string;
welcomeDisabled?: boolean;
env?: string;
isSafeMode?: boolean;
showStackTraces?: boolean;
logLevel?: LogLevel;
devPlugins?: string[];
}
// Handles the initial flags passed to main script and
// returns the remaining args.
const processStartFlags = async (argv: string[], setDefaults = true) => {
const matched: MatchedStartFlags = {};
argv = argv.slice(0);
argv.splice(0, 2); // First arguments are the node executable, and the node JS file
while (argv.length) {
const arg = argv[0];
const nextArg = argv.length >= 2 ? argv[1] : null;
if (arg === '--profile') {
if (!nextArg) throw new JoplinError(_('Usage: %s', '--profile <dir-path>'), 'flagError');
matched.profileDir = nextArg;
argv.splice(0, 2);
continue;
}
if (arg === '--no-welcome') {
matched.welcomeDisabled = true;
argv.splice(0, 1);
continue;
}
if (arg === '--env') {
if (!nextArg) throw new JoplinError(_('Usage: %s', '--env <dev|prod>'), 'flagError');
matched.env = nextArg;
argv.splice(0, 2);
continue;
}
if (arg === '--is-demo') {
Setting.setConstant('isDemo', true);
argv.splice(0, 1);
continue;
}
if (arg === '--safe-mode') {
matched.isSafeMode = true;
argv.splice(0, 1);
continue;
}
if (arg === '--open-dev-tools') {
Setting.setConstant('flagOpenDevTools', true);
argv.splice(0, 1);
continue;
}
if (arg === '--debug') {
// Currently only handled by ElectronAppWrapper (isDebugMode property)
argv.splice(0, 1);
continue;
}
if (arg === '--update-geolocation-disabled') {
Note.updateGeolocationEnabled_ = false;
argv.splice(0, 1);
continue;
}
if (arg === '--stack-trace-enabled') {
matched.showStackTraces = true;
argv.splice(0, 1);
continue;
}
if (arg === '--log-level') {
if (!nextArg) throw new JoplinError(_('Usage: %s', '--log-level <none|error|warn|info|debug>'), 'flagError');
matched.logLevel = Logger.levelStringToId(nextArg);
argv.splice(0, 2);
continue;
}
if (arg.indexOf('-psn') === 0) {
// Some weird flag passed by macOS - can be ignored.
// https://github.com/laurent22/joplin/issues/480
// https://stackoverflow.com/questions/10242115
argv.splice(0, 1);
continue;
}
if (arg === '--enable-logging') {
// Electron-specific flag used for debugging - ignore it
argv.splice(0, 1);
continue;
}
if (arg === '--dev-plugins') {
matched.devPlugins = nextArg.split(',').map(p => p.trim());
Setting.setConstant('startupDevPlugins', matched.devPlugins);
argv.splice(0, 2);
continue;
}
if (arg.indexOf('--remote-debugging-port=') === 0) {
// Electron-specific flag used for debugging - ignore it. Electron expects this flag in '--x=y' form, a single string.
argv.splice(0, 1);
continue;
}
if (arg === '--no-sandbox') {
// Electron-specific flag for running the app without chrome-sandbox
// Allows users to use it as a workaround for the electron+AppImage issue
// https://github.com/laurent22/joplin/issues/2246
argv.splice(0, 1);
continue;
}
if (arg.indexOf('--user-data-dir=') === 0) {
// Electron-specific flag. Allows users to run the app with chromedriver.
argv.splice(0, 1);
continue;
}
if (arg.indexOf('--enable-features=') === 0) {
// Electron-specific flag - ignore it
// Allows users to run the app on native wayland
argv.splice(0, 1);
continue;
}
if (arg.indexOf('--ozone-platform=') === 0) {
// Electron-specific flag - ignore it
// Allows users to run the app on native wayland
argv.splice(0, 1);
continue;
}
if (arg === '--disable-smooth-scrolling') {
// Electron-specific flag - ignore it
// Allows users to disable smooth scrolling
argv.splice(0, 1);
continue;
}
if (arg.length && arg[0] === '-') {
throw new JoplinError(_('Unknown flag: %s', arg), 'flagError');
} else {
break;
}
}
if (setDefaults) {
if (!matched.logLevel) matched.logLevel = Logger.LEVEL_INFO;
if (!matched.env) matched.env = 'prod';
if (!matched.devPlugins) matched.devPlugins = [];
}
return {
matched: matched,
argv: argv,
};
};
export default processStartFlags;

View File

@@ -27,7 +27,7 @@ module.exports = {
{
"id": "25b656aac0564d1a91ab98295aa3cc58",
"title": "3. Synchronising your notes",
"body": "# Synchronising your notes\n\nJoplin allows you to synchronise your data using various file hosting services. The supported cloud services are the following:\n\n## Setting up Joplin Cloud synchronisation\n\n[Joplin Cloud](https://joplinapp.org/plans/) is a web service specifically designed for Joplin. Besides synchronising your data, it also allows you to publish a note to the internet, or share a notebook with your friends, family or colleagues. Joplin Cloud, compared to other services, also features a number of performance improvements allowing for faster synchronisation.\n\nTo use it, go to the config screen, then to the Synchronisation section. In the list of sync target, select \"Joplin Cloud\". Enter your email and password, and you're ready to use Joplin Cloud.\n\n## Setting up Dropbox synchronisation\n\nSelect \"Dropbox\" as the synchronisation target in the config screen. Then, to initiate the synchronisation process, click on the \"Synchronise\" button in the sidebar and follow the instructions.\n\n## Setting up Nextcloud synchronisation\n\nNextcloud is a self-hosted, private cloud solution. To set it up, go to the config screen and select Nextcloud as the synchronisation target. Then input the WebDAV URL (to get it, go to your Nextcloud page, click on Settings in the bottom left corner of the page and copy the URL). Note that it has to be the **full URL**, so for example if you want the notes to be under `/Joplin`, the URL would be something like `https://example.com/remote.php/webdav/Joplin` (note that \"/Joplin\" part). And **make sure to create the \"/Joplin\" directory in Nextcloud**. Finally set the username and password. If it does not work, please [see this explanation](https://github.com/laurent22/joplin/issues/61#issuecomment-373282608) for more details.\n\n## Setting up OneDrive or WebDAV synchronisation\n\nOneDrive and WebDAV are also supported as synchronisation services. Please see [the synchronisation documentation](https://github.com/laurent22/joplin#synchronisation) for more information.\n\n## Using End-To-End Encryption\n\nJoplin supports end-to-end encryption (E2EE) on all the applications. E2EE is a system where only the owner of the data can read it. It prevents potential eavesdroppers - including telecom providers, internet providers, and even the developers of Joplin from being able to access the data. Please see the [End-To-End Encryption Tutorial](https://joplinapp.org/help/apps/sync/e2ee) for more information about this feature and how to enable it.\n",
"body": "# Synchronising your notes\n\nJoplin allows you to synchronise your data using various file hosting services. The supported cloud services are the following:\n\n## Setting up Joplin Cloud synchronisation\n\n[Joplin Cloud](https://joplinapp.org/plans/) is a web service specifically designed for Joplin. Besides synchronising your data, it also allows you to publish a note to the internet, or share a notebook with your friends, family or colleagues. Joplin Cloud, compared to other services, also features a number of performance improvements allowing for faster synchronisation.\n\nTo use it, go to the config screen, then to the Synchronisation section. In the list of sync targets, select \"Joplin Cloud\". Enter your email and password, and you're ready to use Joplin Cloud.\n\n## Setting up Dropbox synchronisation\n\nSelect \"Dropbox\" as the synchronisation target in the config screen. Then, to initiate the synchronisation process, click on the \"Synchronise\" button in the sidebar and follow the instructions.\n\n## Setting up Nextcloud synchronisation\n\nNextcloud is a self-hosted, private cloud solution. To set it up, go to the config screen and select Nextcloud as the synchronisation target. Then input the WebDAV URL (to get it, go to your Nextcloud page, click on Settings in the bottom left corner of the page and copy the URL). Note that it has to be the **full URL**, so for example if you want the notes to be under `/Joplin`, the URL would be something like `https://example.com/remote.php/webdav/Joplin` (note that \"/Joplin\" part). And **make sure to create the \"/Joplin\" directory in Nextcloud**. Finally set the username and password. If it does not work, please [see this explanation](https://github.com/laurent22/joplin/issues/61#issuecomment-373282608) for more details.\n\n## Setting up OneDrive or WebDAV synchronisation\n\nOneDrive and WebDAV are also supported as synchronisation services. Please see [the synchronisation documentation](https://github.com/laurent22/joplin#synchronisation) for more information.\n\n## Using End-To-End Encryption\n\nJoplin supports end-to-end encryption (E2EE) on all the applications. E2EE is a system where only the owner of the data can read it. It prevents potential eavesdroppers - including telecom providers, internet providers, and even the developers of Joplin from being able to access the data. Please see the [End-To-End Encryption Tutorial](https://joplinapp.org/help/apps/sync/e2ee) for more information about this feature and how to enable it.\n",
"resources": {},
"parent_id": "9bb5d498aba74cc6a047cfdc841e82a1"
},

View File

@@ -19,19 +19,19 @@
"author": "Joplin",
"license": "AGPL-3.0-or-later",
"devDependencies": {
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/pdfjs-dist": "2.10.378",
"@types/react": "18.2.31",
"@types/react-dom": "18.2.14",
"@types/styled-components": "5.1.28",
"babel-jest": "29.6.4",
"babel-jest": "29.7.0",
"css-loader": "6.8.1",
"jest": "29.6.4",
"jest-environment-jsdom": "29.6.4",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"style-loader": "3.3.3",
"ts-jest": "29.1.1",
"ts-loader": "9.4.4",
"typescript": "5.1.6",
"typescript": "5.2.2",
"webpack": "5.74.0",
"webpack-cli": "4.10.0"
},

View File

@@ -29,11 +29,11 @@
},
"devDependencies": {
"@types/fs-extra": "11.0.2",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/node": "18.17.19",
"jest": "29.6.4",
"jest": "29.7.0",
"source-map-loader": "4.0.1",
"typescript": "5.1.6",
"typescript": "5.2.2",
"webpack": "5.65.0",
"webpack-cli": "4.10.0"
},

View File

@@ -47,7 +47,7 @@
"@types/react-native": "0.64.19",
"react": "18.2.0",
"react-native": "0.70.6",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"peerDependencies": {
"react": "*",

View File

@@ -159,12 +159,14 @@ class HtmlUtils {
.replace(/</g, '&lt;');
}
// This is tested in sanitize_links.md
private isAcceptedUrl(url: string, allowedFilePrefixes: string[]): boolean {
url = url.toLowerCase();
if (url.startsWith('https://') ||
url.startsWith('http://') ||
url.startsWith('mailto://') ||
url.startsWith('mailto:') ||
url.startsWith('joplin://') ||
!!url.match(/:\/[0-9a-zA-Z]{32}/) ||
// We also allow anchors but only with a specific set of a characters.
// Fixes https://github.com/laurent22/joplin/issues/8286
!!url.match(/^#[a-zA-Z0-9-]+$/)) return true;

View File

@@ -19,12 +19,12 @@
"author": "",
"license": "AGPL-3.0-or-later",
"devDependencies": {
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/node": "18.17.19",
"jest": "29.6.4",
"jest-environment-jsdom": "29.6.4",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"ts-jest": "29.1.1",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"dependencies": {
"@joplin/fork-htmlparser2": "^4.1.46",

View File

@@ -1,10 +1,10 @@
{
"name": "@joplin/server",
"version": "2.13.2",
"version": "2.13.3",
"private": true,
"scripts": {
"start-dev": "yarn run build && JOPLIN_IS_TESTING=1 nodemon --config nodemon.json --ext ts,js,mustache,css,tsx dist/app.js --env dev",
"start-dev-no-watch": "node dist/app.js --env dev",
"start-prod": "pm2 kill && pm2 start --no-daemon --exp-backoff-restart-delay=1000 dist/app.js",
"rebuild": "yarn run clean && yarn run build && yarn run tsc",
"build": "gulp build",
"devCreateDb": "node dist/app.js --env dev --create-db",
@@ -47,6 +47,7 @@
"nodemailer": "6.9.6",
"nodemon": "3.0.1",
"pg": "8.11.3",
"pm2": "5.3.0",
"pretty-bytes": "5.6.0",
"prettycron": "0.10.0",
"query-string": "7.1.3",
@@ -64,7 +65,7 @@
"@types/bcryptjs": "2.4.5",
"@types/formidable": "3.4.3",
"@types/fs-extra": "11.0.2",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/jest-expect-message": "1.0.4",
"@types/jsdom": "21.1.3",
"@types/koa": "2.13.9",
@@ -74,11 +75,11 @@
"@types/yargs": "17.0.28",
"@types/zxcvbn": "4.4.2",
"gulp": "4.0.2",
"jest": "29.6.4",
"jest": "29.7.0",
"jest-expect-message": "1.1.3",
"jsdom": "22.1.0",
"node-mocks-http": "1.13.0",
"source-map-support": "0.5.21",
"typescript": "5.1.6"
"typescript": "5.2.2"
}
}

View File

@@ -24,6 +24,10 @@ describe('build-release-stats', () => {
'list (#8825) (#8194 by [@CptMeetKat](https://github.com/CptMeetKat))',
'list ([#8825](https://github.com/laurent22/joplin/issues/8825)) ([#8194](https://github.com/laurent22/joplin/issues/8194) by [@CptMeetKat](https://github.com/CptMeetKat))',
],
[
'- Improved: Support for plural translations (#9033)',
'- Improved: Support for plural translations ([#9033](https://github.com/laurent22/joplin/issues/9033))',
],
];
for (const [input, expected] of testCases) {

View File

@@ -64,7 +64,7 @@ function downloadCounts(release: GitHubRelease) {
}
export const replaceGitHubInternalLinks = (body: string) => {
body = body.replace(/#(\d+)(.{2})/g, (_match: string, v1: string, v2: string) => {
body = body.replace(/#(\d+)(.{1,2}|)/g, (_match: string, v1: string, v2: string) => {
if (v2.startsWith('](')) {
// The issue number is already a link, so skip it
return `#${v1}${v2}`;

View File

@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 "
"|| n%100>14) ? 1 : 2);\n"
"X-Generator: Poedit 3.4\n"
"X-Generator: Poedit 3.4.1\n"
#: packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.tsx:618
msgid "- Camera: to allow taking a picture and attaching it to a note."
@@ -138,9 +138,8 @@ msgstr "%d notatki spełniają wzór. Usunąć je?"
#: packages/app-desktop/gui/NoteListControls/NoteListControls.tsx:253
#: packages/app-desktop/gui/NoteListControls/NoteListControls.tsx:263
#, fuzzy
msgid "%s"
msgstr "(%s)"
msgstr "%s"
#: packages/app-desktop/gui/MainScreen/commands/duplicateNote.ts:18
msgid "%s - Copy"
@@ -205,9 +204,8 @@ msgstr "%s: %s"
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.tsx:194
#: packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx:263
#, fuzzy
msgid "%s: Missing password."
msgstr "Główne hasło"
msgstr "%s: Brak hasła."
#: packages/app-cli/app/command-tag.js:14
msgid ""
@@ -374,14 +372,12 @@ msgid "Always"
msgstr "Zawsze"
#: packages/lib/models/Setting.ts:1121
#, fuzzy
msgid "Always ask"
msgstr "Zawsze"
msgstr "Zawsze pytaj"
#: packages/lib/models/Setting.ts:1122
#, fuzzy
msgid "Always resize"
msgstr "Zawsze"
msgstr "Zmień rozmiar"
#: packages/app-cli/app/command-mv.js:36
msgid ""
@@ -632,9 +628,8 @@ msgid "Cannot copy note to \"%s\" notebook"
msgstr "Nie można skopiować notatki do notatnika \"%s\""
#: packages/app-mobile/components/screens/Notes.tsx:165
#, fuzzy
msgid "Cannot create a new note: %s"
msgstr "Tworzy nową notatkę."
msgstr "Nie można utworzyć notatki: %s"
#: packages/app-cli/app/command-attach.js:21
#: packages/app-cli/app/command-cat.js:25 packages/app-cli/app/command-cp.js:24
@@ -1155,9 +1150,8 @@ msgid "Creates a new to-do."
msgstr "Tworzy nowe zadanie."
#: packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx:112
#, fuzzy
msgid "Creating new note..."
msgstr "Tworzenie nowego %s..."
msgstr "Tworzenie nowej notatki..."
#: packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx:112
#, fuzzy
@@ -1287,9 +1281,8 @@ msgstr ""
"Usuń dane lokalne i pobierz je ponownie z miejsca docelowego synchronizacji"
#: packages/app-desktop/gui/MainScreen/commands/deleteNote.ts:8
#, fuzzy
msgid "Delete note"
msgstr "Usunąć notatkę?"
msgstr "Usuń notatkę"
#: packages/lib/models/Note.ts:778
msgid "Delete note \"%s\"?"
@@ -1301,9 +1294,8 @@ msgid "Delete note?"
msgstr "Usunąć notatkę?"
#: packages/app-desktop/gui/MainScreen/commands/deleteFolder.ts:9
#, fuzzy
msgid "Delete notebook"
msgstr "Usunąć notatkę?"
msgstr "Usuń notatnik"
#: packages/app-desktop/gui/MainScreen/commands/deleteFolder.ts:20
#: packages/app-mobile/components/side-menu-content.tsx:163
@@ -1330,9 +1322,8 @@ msgid "Delete plugin \"%s\"?"
msgstr "Usunąć wtyczkę \"%s\"?"
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:102
#, fuzzy
msgid "Delete profile \"%s\""
msgstr "Usunąć notatkę \"%s\"?"
msgstr "Usuń profil “%s”"
#: packages/app-mobile/components/ScreenHeader.tsx:438
#, fuzzy
@@ -1595,9 +1586,8 @@ msgid "Duplicate line"
msgstr "Duplikuj wiersz"
#: packages/app-mobile/components/ScreenHeader.tsx:456
#, fuzzy
msgid "Duplicate selected notes"
msgstr "Duplikuj wiersz"
msgstr "Duplikuj zaznaczone"
#: packages/app-cli/app/command-cp.js:13
msgid ""
@@ -2913,7 +2903,7 @@ msgstr "N"
#: packages/lib/models/Setting.ts:1123
msgid "Never resize"
msgstr ""
msgstr "Nie zmieniaj rozmiaru"
#: packages/app-desktop/gui/MainScreen/commands/newNote.ts:8
#: packages/app-desktop/gui/NoteListControls/NoteListControls.tsx:121
@@ -3049,9 +3039,8 @@ msgid "Not generated"
msgstr "Nie wygenerowano"
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:91
#, fuzzy
msgid "Not now"
msgstr "Zrób to teraz"
msgstr "Nie teraz"
#: packages/app-desktop/gui/NoteListControls/NoteListControls.tsx:120
#: packages/app-desktop/gui/NoteListControls/NoteListControls.tsx:142
@@ -3507,9 +3496,8 @@ msgid "Privacy Policy"
msgstr "Polityka Prywatności"
#: packages/lib/utils/joplinCloud.ts:364
#, fuzzy
msgid "Pro"
msgstr "Profil"
msgstr "Pro"
#: packages/server/src/services/TaskService.ts:26
msgid "Process failed payment subscriptions"
@@ -3528,9 +3516,8 @@ msgid "Profile"
msgstr "Profil"
#: packages/app-mobile/components/ProfileSwitcher/ProfileEditor.tsx:96
#, fuzzy
msgid "Profile name"
msgstr "Nazwa profilu:"
msgstr "Nazwa profilu"
#: packages/app-desktop/gui/MainScreen/commands/addProfile.ts:17
msgid "Profile name:"
@@ -3541,18 +3528,16 @@ msgid "Profile Version: %s"
msgstr "Wersja profilu: %s"
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:156
#, fuzzy
msgid "Profiles"
msgstr "Profil"
msgstr "Profile"
#: packages/app-mobile/components/screens/Note.tsx:1170
msgid "Properties"
msgstr "Właściwości"
#: packages/lib/models/Setting.ts:1543
#, fuzzy
msgid "Proxy enabled"
msgstr "Aktywowano"
msgstr "Proxy włączone"
#: packages/lib/models/Setting.ts:1565
msgid "Proxy timeout (seconds)"
@@ -3560,7 +3545,7 @@ msgstr ""
#: packages/lib/models/Setting.ts:1553
msgid "Proxy URL"
msgstr ""
msgstr "Adres URL serwera proxy"
#: packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx:238
msgid "Public-private key pair:"
@@ -3828,9 +3813,8 @@ msgid "Save changes"
msgstr "Zapisz zmiany"
#: packages/app-mobile/components/NoteEditor/ImageEditor/ImageEditor.tsx:99
#, fuzzy
msgid "Save changes?"
msgstr "Zapisz zmiany"
msgstr "Zapis zmiany?"
#: packages/lib/models/Setting.ts:1024
msgid "Save geo-location with notes"
@@ -4391,9 +4375,8 @@ msgid "Take photo"
msgstr "Wykonaj zdjęcie"
#: packages/app-mobile/components/NoteEditor/MarkdownToolbar/MarkdownToolbar.tsx:97
#, fuzzy
msgid "Task list"
msgstr "Zadania"
msgstr "Lista zadań"
#: packages/server/src/services/MustacheService.ts:125
#: packages/server/src/services/MustacheService.ts:279
@@ -4979,9 +4962,8 @@ msgid "Tools"
msgstr "Narzędzia"
#: packages/server/src/routes/admin/users.ts:149
#, fuzzy
msgid "Total Size"
msgstr "Rozmiar rzeczywisty"
msgstr "Łączny rozmiar"
#: packages/lib/services/ReportService.ts:285
msgid "Total: %d/%d"
@@ -4994,9 +4976,8 @@ msgstr "Spróbuj ponownie"
#: packages/lib/utils/joplinCloud.ts:357 packages/lib/utils/joplinCloud.ts:379
#: packages/lib/utils/joplinCloud.ts:401
#, fuzzy
msgid "Try it now"
msgstr "Zrób to teraz"
msgstr "Wypróbuj teraz"
#: packages/app-cli/app/command-help.js:71
msgid ""
@@ -5288,11 +5269,12 @@ msgstr ""
"wyświetlone (limit: %s)."
#: packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.tsx:100
#, fuzzy
msgid ""
"Warnings:\n"
"%s"
msgstr "Uwaga"
msgstr ""
"Uwaga:\n"
"%s"
#: packages/lib/models/Setting.ts:2604 packages/lib/utils/joplinCloud.ts:166
msgid "Web Clipper"
@@ -5337,9 +5319,8 @@ msgstr ""
"naciśnij `mn`."
#: packages/lib/WelcomeUtils.ts:63
#, fuzzy
msgid "Welcome!"
msgstr "Witaj"
msgstr "Witaj!"
#: packages/lib/models/Setting.ts:1100
msgid "When creating a new note:"

View File

@@ -46,7 +46,7 @@
"@joplin/fork-htmlparser2": "^4.1.46",
"@rmp135/sql-ts": "1.18.0",
"@types/fs-extra": "11.0.2",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/js-yaml": "4.0.8",
"@types/markdown-it": "13.0.2",
"@types/mustache": "4.2.3",
@@ -56,13 +56,13 @@
"gettext-extractor": "3.8.0",
"gulp": "4.0.2",
"html-entities": "1.4.0",
"jest": "29.6.4",
"jest": "29.7.0",
"js-yaml": "4.1.0",
"rss": "1.2.2",
"sass": "1.67.0",
"sass": "1.68.0",
"sqlite3": "5.1.6",
"style-to-js": "1.1.8",
"typescript": "5.1.6"
"typescript": "5.2.2"
},
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
}

View File

@@ -1 +1 @@
{"processedReleases":{"v2.13.1":true,"v2.13.2":true,"v2.13.3":true}}
{"processedReleases":{"v2.13.1":true,"v2.13.2":true,"v2.13.3":true,"v2.13.4":true}}

View File

@@ -40,11 +40,11 @@ yarn install
# to change after installation.
git reset --hard
JOPLIN_GITHUB_OAUTH_TOKEN=$JOPLIN_GITHUB_OAUTH_TOKEN yarn run updateMarkdownDoc
JOPLIN_GITHUB_OAUTH_TOKEN=$JOPLIN_GITHUB_OAUTH_TOKEN yarn updateMarkdownDoc
# Automatically update certain forum posts
yarn run updateNews $DISCOURSE_API_KEY $DISCOURSE_USERNAME
yarn run postPreReleasesToForum $DISCOURSE_API_KEY $DISCOURSE_USERNAME
yarn updateNews $DISCOURSE_API_KEY $DISCOURSE_USERNAME
yarn postPreReleasesToForum $DISCOURSE_API_KEY $DISCOURSE_USERNAME
# We commit and push the change. It will be a noop if nothing was actually
# changed
@@ -67,7 +67,8 @@ git checkout master
git pull --rebase
cd "$JOPLIN_ROOT_DIR"
yarn run buildWebsite
CROWDIN_PERSONAL_TOKEN="$CROWDIN_PERSONAL_TOKEN" yarn crowdinDownload
yarn buildWebsite
cd "$JOPLIN_WEBSITE_ROOT_DIR"
git add -A

View File

@@ -1,5 +1,5 @@
import { readFile } from 'fs/promises';
import { processMarkdownDoc } from './processDocs';
import { processMarkdownDoc, processUrls } from './processDocs';
import { basename } from 'path';
import { readdirSync } from 'fs';
@@ -47,4 +47,34 @@ ${actual}`);
expect(actual).toBe(expected);
});
test.each([
[
'',
'',
],
[
'[synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/joplin_cloud.md)',
'[synchronisation set to Joplin Cloud](/help/apps/sync/joplin_cloud)',
],
[
'The notes can be securely [synchronised](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/index.md) using [end-to-end encryption](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/e2ee.md)',
'The notes can be securely [synchronised](/help/apps/sync) using [end-to-end encryption](/help/apps/sync/e2ee)',
],
[
'The notes can be securely [synchronised](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/index.md) using [end-to-end encryption](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/e2ee.md)',
'The notes can be securely [synchronised](/help/apps/sync) using [end-to-end encryption](/help/apps/sync/e2ee)',
],
[
'[Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md)',
'[Configuration screen](/help/apps/config_screen) [Configuration screen](/help/apps/config_screen)',
],
[
'In [command-line mode](https://github.com/laurent22/joplin/blob/dev/readme/apps/terminal.md#command-line-mode), type `import --format md /path/to/file.md`',
'In [command-line mode](/help/apps/terminal#command-line-mode), type `import --format md /path/to/file.md`',
],
])('should process URLs', (input, expected) => {
const actual = processUrls(input);
expect(actual).toBe(expected);
});
});

View File

@@ -313,10 +313,10 @@ const resolveBlockQuotes = (output: string): string => {
return newOutput.join('\n');
};
const processUrls = (md: string) => {
export const processUrls = (md: string) => {
md = md
.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*)\/index\.md/g, '/help/$1')
.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*)\.md/g, '/help/$1');
.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*?)\/index\.md/g, '/help/$1')
.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*?)\.md/g, '/help/$1');
return md;
};
@@ -479,6 +479,7 @@ async function main() {
await processDocFiles(readmeDir, destHelpDir, [
`${readmeDir}/_i18n`,
`${readmeDir}/i18n`,
`${readmeDir}/cla.md`,
`${readmeDir}/download.md`,
`${readmeDir}/faq_joplin_cloud.md`,
@@ -495,6 +496,14 @@ async function main() {
await processDocFiles(`${readmeDir}/news`, newsDestDir, [], newsContext);
await deleteUnprocessedFiles(newsDestDir, newsContext.processedFiles);
if (await pathExists(`${readmeDir}/i18n`)) {
const localeContext: Context = { donateLinks };
await processDocFiles(`${readmeDir}/i18n`, `${docBuilderDir}/i18n`, [], localeContext);
await deleteUnprocessedFiles(`${docBuilderDir}/i18n`, localeContext.processedFiles);
} else {
console.info('i18n folder is missing - skipping it');
}
await copyFile(`${rootDir}/Assets/WebsiteAssets/images`, `${docBuilderDir}/static/images`);
if (config.docusaurusBuildEnabled) {

View File

@@ -37,9 +37,9 @@
},
"devDependencies": {
"@types/fs-extra": "11.0.2",
"@types/jest": "29.5.4",
"@types/jest": "29.5.5",
"@types/node-fetch": "2.6.6",
"jest": "29.6.4",
"jest": "29.7.0",
"ts-jest": "29.1.1"
}
}

View File

@@ -1,5 +1,11 @@
# Joplin Android Changelog
## [android-v2.13.5](https://github.com/laurent22/joplin/releases/tag/android-v2.13.5) (Pre-release) - 2023-10-30T22:49:19Z
- Improved: Allow searching by note ID or using a callback URL (3667bf3)
- Improved: Updated packages @react-native-community/datetimepicker (v7.6.0), react-native-device-info (v10.11.0), react-native-webview (v13.6.2)
- Fixed: Beta editor: Fix image timestamps not updated after editing (#9176) (#9175 by Henry Heino)
## [android-v2.13.4](https://github.com/laurent22/joplin/releases/tag/android-v2.13.4) (Pre-release) - 2023-10-24T18:29:09Z
- Improved: Allow modifying a resource metadata only when synchronising (#9114)

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,11 @@
# Joplin Server Changelog
## [server-v2.13.3](https://github.com/laurent22/joplin/releases/tag/server-v2.13.3) - 2023-11-01T16:29:32Z
- Improved: Automatically restarts the server when it crashes, with exponentiel back-off (0c8b475)
- Improved: Improve parsing of uploaded content and error handling (db88dfc)
- Improved: Updated packages katex (v0.16.9), nodemailer (v6.9.6), react, sass (v1.68.0)
## [server-v2.13.2](https://github.com/laurent22/joplin/releases/tag/server-v2.13.2) - 2023-10-19T19:49:44Z
- Improved: Significantly improve sync performances, especially when there are many changes (5986710)

View File

@@ -1,14 +1,14 @@
---
updated: 2023-10-01T00:44:28Z
updated: 2023-11-01T00:41:03Z
---
# Joplin statistics
| Name | Value |
| ----- | ----- |
| Total Windows downloads | 3,848,348 |
| Total macOs downloads | 1,426,311 |
| Total Linux downloads | 1,072,442 |
| Total Windows downloads | 3,975,213 |
| Total macOs downloads | 1,467,083 |
| Total Linux downloads | 1,093,632 |
| Windows % | 61% |
| macOS % | 22% |
| Linux % | 17% |
@@ -17,216 +17,220 @@ updated: 2023-10-01T00:44:28Z
| Version | Date | Windows | macOS | Linux | Total |
| ----- | ----- | ----- | ----- | ----- | ----- |
| [v2.12.18](https://github.com/laurent22/joplin/releases/tag/v2.12.18) | 2023-09-22T14:37:24Z | 45,693 | 19,552 | 6,704 | 71,949 |
| [v2.12.17](https://github.com/laurent22/joplin/releases/tag/v2.12.17) | 2023-09-14T21:54:52Z | 44,918 | 20,617 | 6,588 | 72,123 |
| [v2.13.1](https://github.com/laurent22/joplin/releases/tag/v2.13.1) (p) | 2023-09-13T09:31:50Z | 1,158 | 342 | 495 | 1,995 |
| [v2.12.16](https://github.com/laurent22/joplin/releases/tag/v2.12.16) | 2023-09-11T22:33:37Z | 26,929 | 14,567 | 2,368 | 43,864 |
| [v2.12.15](https://github.com/laurent22/joplin/releases/tag/v2.12.15) | 2023-08-27T11:35:39Z | 61,059 | 27,743 | 8,065 | 96,867 |
| [v2.12.12](https://github.com/laurent22/joplin/releases/tag/v2.12.12) (p) | 2023-08-19T22:44:56Z | 1,446 | 371 | 418 | 2,235 |
| [v2.12.10](https://github.com/laurent22/joplin/releases/tag/v2.12.10) (p) | 2023-07-30T18:25:58Z | 6,264 | 3,787 | 898 | 10,949 |
| [v2.12.9](https://github.com/laurent22/joplin/releases/tag/v2.12.9) (p) | 2023-07-25T16:06:08Z | 1,085 | 355 | 316 | 1,756 |
| [v2.12.7](https://github.com/laurent22/joplin/releases/tag/v2.12.7) (p) | 2023-07-13T12:55:31Z | 1,931 | 635 | 576 | 3,142 |
| [v2.12.5](https://github.com/laurent22/joplin/releases/tag/v2.12.5) (p) | 2023-07-12T15:03:46Z | 726 | 129 | 126 | 981 |
| [v2.12.4](https://github.com/laurent22/joplin/releases/tag/v2.12.4) (p) | 2023-07-07T22:36:53Z | 1,028 | 414 | 207 | 1,649 |
| [v2.12.3](https://github.com/laurent22/joplin/releases/tag/v2.12.3) (p) | 2023-07-07T10:16:55Z | 336 | 166 | 82 | 584 |
| [v2.11.11](https://github.com/laurent22/joplin/releases/tag/v2.11.11) | 2023-06-23T15:16:37Z | 183,714 | 67,095 | 38,624 | 289,433 |
| [v2.11.9](https://github.com/laurent22/joplin/releases/tag/v2.11.9) (p) | 2023-06-06T16:23:27Z | 2,278 | 568 | 739 | 3,585 |
| [v2.11.6](https://github.com/laurent22/joplin/releases/tag/v2.11.6) (p) | 2023-05-31T20:13:08Z | 1,140 | 427 | 333 | 1,900 |
| [v2.11.5](https://github.com/laurent22/joplin/releases/tag/v2.11.5) (p) | 2023-05-28T00:41:40Z | 998 | 298 | 275 | 1,571 |
| [v2.10.19](https://github.com/laurent22/joplin/releases/tag/v2.10.19) | 2023-05-17T12:25:41Z | 120,560 | 48,283 | 22,411 | 191,254 |
| [v2.11.4](https://github.com/laurent22/joplin/releases/tag/v2.11.4) (p) | 2023-05-16T10:02:21Z | 1,063 | 461 | 405 | 1,929 |
| [v2.11.3](https://github.com/laurent22/joplin/releases/tag/v2.11.3) (p) | 2023-05-16T09:09:57Z | 83 | 34 | 33 | 150 |
| [v2.10.18](https://github.com/laurent22/joplin/releases/tag/v2.10.18) | 2023-05-09T13:27:43Z | 54,130 | 24,222 | 6,743 | 85,095 |
| [v2.10.17](https://github.com/laurent22/joplin/releases/tag/v2.10.17) | 2023-05-08T17:27:28Z | 17,158 | 11,497 | 876 | 29,531 |
| [v2.10.16](https://github.com/laurent22/joplin/releases/tag/v2.10.16) | 2023-04-27T09:27:45Z | 7,782 | 4,231 | 772 | 12,785 |
| [v2.13.4](https://github.com/laurent22/joplin/releases/tag/v2.13.4) (p) | 2023-10-31T00:01:00Z | 474 | 105 | 83 | 662 |
| [v2.13.3](https://github.com/laurent22/joplin/releases/tag/v2.13.3) (p) | 2023-10-24T09:25:33Z | 1,248 | 266 | 279 | 1,793 |
| [v2.12.19](https://github.com/laurent22/joplin/releases/tag/v2.12.19) | 2023-10-21T09:39:18Z | 57,537 | 22,634 | 7,874 | 88,045 |
| [v2.13.2](https://github.com/laurent22/joplin/releases/tag/v2.13.2) (p) | 2023-10-06T17:00:07Z | 1,998 | 495 | 688 | 3,181 |
| [v2.12.18](https://github.com/laurent22/joplin/releases/tag/v2.12.18) | 2023-09-22T14:37:24Z | 104,990 | 36,402 | 18,546 | 159,938 |
| [v2.12.17](https://github.com/laurent22/joplin/releases/tag/v2.12.17) | 2023-09-14T21:54:52Z | 45,354 | 20,683 | 6,604 | 72,641 |
| [v2.13.1](https://github.com/laurent22/joplin/releases/tag/v2.13.1) (p) | 2023-09-13T09:31:50Z | 1,315 | 415 | 618 | 2,348 |
| [v2.12.16](https://github.com/laurent22/joplin/releases/tag/v2.12.16) | 2023-09-11T22:33:37Z | 27,075 | 14,626 | 2,420 | 44,121 |
| [v2.12.15](https://github.com/laurent22/joplin/releases/tag/v2.12.15) | 2023-08-27T11:35:39Z | 61,288 | 27,816 | 8,084 | 97,188 |
| [v2.12.12](https://github.com/laurent22/joplin/releases/tag/v2.12.12) (p) | 2023-08-19T22:44:56Z | 1,473 | 374 | 418 | 2,265 |
| [v2.12.10](https://github.com/laurent22/joplin/releases/tag/v2.12.10) (p) | 2023-07-30T18:25:58Z | 6,279 | 3,788 | 900 | 10,967 |
| [v2.12.9](https://github.com/laurent22/joplin/releases/tag/v2.12.9) (p) | 2023-07-25T16:06:08Z | 1,095 | 356 | 316 | 1,767 |
| [v2.12.7](https://github.com/laurent22/joplin/releases/tag/v2.12.7) (p) | 2023-07-13T12:55:31Z | 1,956 | 643 | 580 | 3,179 |
| [v2.12.5](https://github.com/laurent22/joplin/releases/tag/v2.12.5) (p) | 2023-07-12T15:03:46Z | 795 | 133 | 132 | 1,060 |
| [v2.12.4](https://github.com/laurent22/joplin/releases/tag/v2.12.4) (p) | 2023-07-07T22:36:53Z | 1,030 | 415 | 207 | 1,652 |
| [v2.12.3](https://github.com/laurent22/joplin/releases/tag/v2.12.3) (p) | 2023-07-07T10:16:55Z | 347 | 169 | 84 | 600 |
| [v2.11.11](https://github.com/laurent22/joplin/releases/tag/v2.11.11) | 2023-06-23T15:16:37Z | 184,055 | 67,121 | 38,664 | 289,840 |
| [v2.11.9](https://github.com/laurent22/joplin/releases/tag/v2.11.9) (p) | 2023-06-06T16:23:27Z | 2,280 | 568 | 739 | 3,587 |
| [v2.11.6](https://github.com/laurent22/joplin/releases/tag/v2.11.6) (p) | 2023-05-31T20:13:08Z | 1,143 | 427 | 334 | 1,904 |
| [v2.11.5](https://github.com/laurent22/joplin/releases/tag/v2.11.5) (p) | 2023-05-28T00:41:40Z | 998 | 299 | 275 | 1,572 |
| [v2.10.19](https://github.com/laurent22/joplin/releases/tag/v2.10.19) | 2023-05-17T12:25:41Z | 120,710 | 48,289 | 22,418 | 191,417 |
| [v2.11.4](https://github.com/laurent22/joplin/releases/tag/v2.11.4) (p) | 2023-05-16T10:02:21Z | 1,064 | 461 | 405 | 1,930 |
| [v2.11.3](https://github.com/laurent22/joplin/releases/tag/v2.11.3) (p) | 2023-05-16T09:09:57Z | 88 | 34 | 33 | 155 |
| [v2.10.18](https://github.com/laurent22/joplin/releases/tag/v2.10.18) | 2023-05-09T13:27:43Z | 54,241 | 24,223 | 6,744 | 85,208 |
| [v2.10.17](https://github.com/laurent22/joplin/releases/tag/v2.10.17) | 2023-05-08T17:27:28Z | 17,238 | 11,498 | 877 | 29,613 |
| [v2.10.16](https://github.com/laurent22/joplin/releases/tag/v2.10.16) | 2023-04-27T09:27:45Z | 7,801 | 4,235 | 772 | 12,808 |
| [v2.10.15](https://github.com/laurent22/joplin/releases/tag/v2.10.15) (p) | 2023-04-26T22:02:16Z | 357 | 132 | 54 | 543 |
| [v2.10.13](https://github.com/laurent22/joplin/releases/tag/v2.10.13) (p) | 2023-04-03T16:53:46Z | 3,452 | 823 | 1,075 | 5,350 |
| [v2.10.12](https://github.com/laurent22/joplin/releases/tag/v2.10.12) (p) | 2023-03-23T12:17:13Z | 2,425 | 514 | 602 | 3,541 |
| [v2.10.11](https://github.com/laurent22/joplin/releases/tag/v2.10.11) (p) | 2023-03-17T10:54:02Z | 1,798 | 379 | 380 | 2,557 |
| [v2.10.10](https://github.com/laurent22/joplin/releases/tag/v2.10.10) (p) | 2023-03-13T23:16:37Z | 1,295 | 274 | 251 | 1,820 |
| [v2.10.9](https://github.com/laurent22/joplin/releases/tag/v2.10.9) (p) | 2023-03-12T16:16:45Z | 836 | 211 | 291 | 1,338 |
| [v2.10.8](https://github.com/laurent22/joplin/releases/tag/v2.10.8) (p) | 2023-02-26T12:53:55Z | 3,303 | 571 | 868 | 4,742 |
| [v2.10.7](https://github.com/laurent22/joplin/releases/tag/v2.10.7) (p) | 2023-02-24T10:56:20Z | 965 | 187 | 275 | 1,427 |
| [v2.10.6](https://github.com/laurent22/joplin/releases/tag/v2.10.6) (p) | 2023-02-20T14:00:05Z | 1,785 | 337 | 284 | 2,406 |
| [v2.10.5](https://github.com/laurent22/joplin/releases/tag/v2.10.5) | 2023-01-16T15:00:53Z | 312 | 81 | 285 | 678 |
| [v2.10.4](https://github.com/laurent22/joplin/releases/tag/v2.10.4) (p) | 2023-01-05T13:09:20Z | 6,982 | 1,298 | 1,806 | 10,086 |
| [v2.10.3](https://github.com/laurent22/joplin/releases/tag/v2.10.3) (p) | 2022-12-31T15:53:23Z | 1,570 | 309 | 405 | 2,284 |
| [v2.10.2](https://github.com/laurent22/joplin/releases/tag/v2.10.2) (p) | 2022-12-18T18:05:08Z | 2,983 | 576 | 629 | 4,188 |
| [v2.9.17](https://github.com/laurent22/joplin/releases/tag/v2.9.17) | 2022-11-15T10:28:37Z | 332,712 | 108,726 | 83,219 | 524,657 |
| [v2.9.12](https://github.com/laurent22/joplin/releases/tag/v2.9.12) (p) | 2022-11-01T17:06:05Z | 10,181 | 606 | 534 | 11,321 |
| [v2.9.11](https://github.com/laurent22/joplin/releases/tag/v2.9.11) (p) | 2022-10-23T16:09:58Z | 2,339 | 525 | 711 | 3,575 |
| [v2.9.4](https://github.com/laurent22/joplin/releases/tag/v2.9.4) (p) | 2022-08-18T16:52:26Z | 7,374 | 1,858 | 2,186 | 11,418 |
| [v2.9.3](https://github.com/laurent22/joplin/releases/tag/v2.9.3) (p) | 2022-08-18T13:11:09Z | 333 | 86 | 264 | 683 |
| [v2.10.13](https://github.com/laurent22/joplin/releases/tag/v2.10.13) (p) | 2023-04-03T16:53:46Z | 3,458 | 823 | 1,075 | 5,356 |
| [v2.10.12](https://github.com/laurent22/joplin/releases/tag/v2.10.12) (p) | 2023-03-23T12:17:13Z | 2,430 | 514 | 602 | 3,546 |
| [v2.10.11](https://github.com/laurent22/joplin/releases/tag/v2.10.11) (p) | 2023-03-17T10:54:02Z | 1,803 | 379 | 380 | 2,562 |
| [v2.10.10](https://github.com/laurent22/joplin/releases/tag/v2.10.10) (p) | 2023-03-13T23:16:37Z | 1,303 | 274 | 251 | 1,828 |
| [v2.10.9](https://github.com/laurent22/joplin/releases/tag/v2.10.9) (p) | 2023-03-12T16:16:45Z | 842 | 211 | 292 | 1,345 |
| [v2.10.8](https://github.com/laurent22/joplin/releases/tag/v2.10.8) (p) | 2023-02-26T12:53:55Z | 3,308 | 571 | 869 | 4,748 |
| [v2.10.7](https://github.com/laurent22/joplin/releases/tag/v2.10.7) (p) | 2023-02-24T10:56:20Z | 971 | 187 | 275 | 1,433 |
| [v2.10.6](https://github.com/laurent22/joplin/releases/tag/v2.10.6) (p) | 2023-02-20T14:00:05Z | 1,790 | 337 | 284 | 2,411 |
| [v2.10.5](https://github.com/laurent22/joplin/releases/tag/v2.10.5) | 2023-01-16T15:00:53Z | 318 | 87 | 286 | 691 |
| [v2.10.4](https://github.com/laurent22/joplin/releases/tag/v2.10.4) (p) | 2023-01-05T13:09:20Z | 6,987 | 1,298 | 1,806 | 10,091 |
| [v2.10.3](https://github.com/laurent22/joplin/releases/tag/v2.10.3) (p) | 2022-12-31T15:53:23Z | 1,572 | 309 | 405 | 2,286 |
| [v2.10.2](https://github.com/laurent22/joplin/releases/tag/v2.10.2) (p) | 2022-12-18T18:05:08Z | 2,990 | 578 | 629 | 4,197 |
| [v2.9.17](https://github.com/laurent22/joplin/releases/tag/v2.9.17) | 2022-11-15T10:28:37Z | 332,857 | 108,737 | 83,243 | 524,837 |
| [v2.9.12](https://github.com/laurent22/joplin/releases/tag/v2.9.12) (p) | 2022-11-01T17:06:05Z | 10,186 | 606 | 534 | 11,326 |
| [v2.9.11](https://github.com/laurent22/joplin/releases/tag/v2.9.11) (p) | 2022-10-23T16:09:58Z | 2,344 | 525 | 748 | 3,617 |
| [v2.9.4](https://github.com/laurent22/joplin/releases/tag/v2.9.4) (p) | 2022-08-18T16:52:26Z | 7,379 | 1,859 | 2,187 | 11,425 |
| [v2.9.3](https://github.com/laurent22/joplin/releases/tag/v2.9.3) (p) | 2022-08-18T13:11:09Z | 333 | 86 | 265 | 684 |
| [v2.9.2](https://github.com/laurent22/joplin/releases/tag/v2.9.2) (p) | 2022-08-12T18:12:12Z | 1,515 | 443 | 0 | 1,958 |
| [v2.9.1](https://github.com/laurent22/joplin/releases/tag/v2.9.1) (p) | 2022-07-11T09:59:32Z | 6,793 | 1,335 | 1,392 | 9,520 |
| [v2.8.8](https://github.com/laurent22/joplin/releases/tag/v2.8.8) | 2022-05-17T14:48:06Z | 348,007 | 114,224 | 113,453 | 575,684 |
| [v2.8.7](https://github.com/laurent22/joplin/releases/tag/v2.8.7) (p) | 2022-05-06T11:34:27Z | 3,178 | 360 | 389 | 3,927 |
| [v2.8.6](https://github.com/laurent22/joplin/releases/tag/v2.8.6) (p) | 2022-05-03T10:08:25Z | 2,805 | 399 | 323 | 3,527 |
| [v2.8.5](https://github.com/laurent22/joplin/releases/tag/v2.8.5) (p) | 2022-04-27T13:51:50Z | 2,867 | 366 | 348 | 3,581 |
| [v2.8.4](https://github.com/laurent22/joplin/releases/tag/v2.8.4) (p) | 2022-04-19T18:00:09Z | 3,376 | 585 | 322 | 4,283 |
| [v2.8.2](https://github.com/laurent22/joplin/releases/tag/v2.8.2) (p) | 2022-04-14T11:35:45Z | 2,780 | 275 | 259 | 3,314 |
| [v2.7.15](https://github.com/laurent22/joplin/releases/tag/v2.7.15) | 2022-03-17T13:03:23Z | 154,600 | 56,749 | 51,223 | 262,572 |
| [v2.7.14](https://github.com/laurent22/joplin/releases/tag/v2.7.14) | 2022-02-27T11:30:53Z | 33,171 | 16,771 | 4,791 | 54,733 |
| [v2.7.13](https://github.com/laurent22/joplin/releases/tag/v2.7.13) | 2022-02-24T17:42:12Z | 53,589 | 25,718 | 11,705 | 91,012 |
| [v2.7.12](https://github.com/laurent22/joplin/releases/tag/v2.7.12) (p) | 2022-02-14T15:06:14Z | 3,546 | 460 | 459 | 4,465 |
| [v2.7.11](https://github.com/laurent22/joplin/releases/tag/v2.7.11) (p) | 2022-02-12T13:00:02Z | 2,677 | 192 | 157 | 3,026 |
| [v2.7.10](https://github.com/laurent22/joplin/releases/tag/v2.7.10) (p) | 2022-02-11T18:19:09Z | 2,204 | 121 | 80 | 2,405 |
| [v2.7.8](https://github.com/laurent22/joplin/releases/tag/v2.7.8) (p) | 2022-01-19T09:35:27Z | 4,439 | 766 | 819 | 6,024 |
| [v2.7.7](https://github.com/laurent22/joplin/releases/tag/v2.7.7) (p) | 2022-01-18T14:05:07Z | 2,521 | 152 | 131 | 2,804 |
| [v2.7.6](https://github.com/laurent22/joplin/releases/tag/v2.7.6) (p) | 2022-01-17T17:08:28Z | 2,463 | 178 | 110 | 2,751 |
| [v2.6.10](https://github.com/laurent22/joplin/releases/tag/v2.6.10) | 2021-12-19T11:31:16Z | 133,965 | 51,183 | 49,257 | 234,405 |
| [v2.6.9](https://github.com/laurent22/joplin/releases/tag/v2.6.9) | 2021-12-17T11:57:32Z | 17,636 | 9,490 | 3,180 | 30,306 |
| [v2.6.7](https://github.com/laurent22/joplin/releases/tag/v2.6.7) (p) | 2021-12-16T10:47:23Z | 2,657 | 160 | 99 | 2,916 |
| [v2.6.6](https://github.com/laurent22/joplin/releases/tag/v2.6.6) (p) | 2021-12-13T12:31:43Z | 2,665 | 253 | 162 | 3,080 |
| [v2.6.5](https://github.com/laurent22/joplin/releases/tag/v2.6.5) (p) | 2021-12-13T10:07:04Z | 1,996 | 48 | 28 | 2,072 |
| [v2.6.4](https://github.com/laurent22/joplin/releases/tag/v2.6.4) (p) | 2021-12-09T19:53:43Z | 2,714 | 286 | 197 | 3,197 |
| [v2.6.2](https://github.com/laurent22/joplin/releases/tag/v2.6.2) (p) | 2021-11-18T12:19:12Z | 4,513 | 788 | 698 | 5,999 |
| [v2.5.12](https://github.com/laurent22/joplin/releases/tag/v2.5.12) | 2021-11-08T11:07:11Z | 81,095 | 32,497 | 25,213 | 138,805 |
| [v2.5.10](https://github.com/laurent22/joplin/releases/tag/v2.5.10) | 2021-11-01T08:22:42Z | 45,777 | 19,034 | 10,081 | 74,892 |
| [v2.5.8](https://github.com/laurent22/joplin/releases/tag/v2.5.8) | 2021-10-31T11:38:03Z | 14,503 | 6,562 | 2,309 | 23,374 |
| [v2.5.7](https://github.com/laurent22/joplin/releases/tag/v2.5.7) (p) | 2021-10-29T14:47:33Z | 2,270 | 201 | 162 | 2,633 |
| [v2.5.6](https://github.com/laurent22/joplin/releases/tag/v2.5.6) (p) | 2021-10-28T22:03:09Z | 2,309 | 174 | 105 | 2,588 |
| [v2.5.4](https://github.com/laurent22/joplin/releases/tag/v2.5.4) (p) | 2021-10-19T10:10:54Z | 3,804 | 565 | 570 | 4,939 |
| [v2.4.12](https://github.com/laurent22/joplin/releases/tag/v2.4.12) | 2021-10-13T17:24:34Z | 45,601 | 19,972 | 9,779 | 75,352 |
| [v2.5.1](https://github.com/laurent22/joplin/releases/tag/v2.5.1) (p) | 2021-10-02T09:51:58Z | 4,811 | 901 | 942 | 6,654 |
| [v2.4.9](https://github.com/laurent22/joplin/releases/tag/v2.4.9) | 2021-09-29T19:08:58Z | 57,722 | 23,246 | 15,888 | 96,856 |
| [v2.4.8](https://github.com/laurent22/joplin/releases/tag/v2.4.8) (p) | 2021-09-22T19:01:46Z | 8,668 | 1,770 | 532 | 10,970 |
| [v2.4.7](https://github.com/laurent22/joplin/releases/tag/v2.4.7) (p) | 2021-09-19T12:53:22Z | 2,759 | 250 | 204 | 3,213 |
| [v2.4.6](https://github.com/laurent22/joplin/releases/tag/v2.4.6) (p) | 2021-09-09T18:57:17Z | 3,525 | 456 | 516 | 4,497 |
| [v2.4.5](https://github.com/laurent22/joplin/releases/tag/v2.4.5) (p) | 2021-09-06T18:03:28Z | 2,780 | 268 | 221 | 3,269 |
| [v2.4.4](https://github.com/laurent22/joplin/releases/tag/v2.4.4) (p) | 2021-08-30T16:02:51Z | 2,982 | 374 | 356 | 3,712 |
| [v2.4.3](https://github.com/laurent22/joplin/releases/tag/v2.4.3) (p) | 2021-08-28T15:27:32Z | 2,511 | 202 | 175 | 2,888 |
| [v2.4.2](https://github.com/laurent22/joplin/releases/tag/v2.4.2) (p) | 2021-08-27T17:13:21Z | 2,236 | 146 | 88 | 2,470 |
| [v2.4.1](https://github.com/laurent22/joplin/releases/tag/v2.4.1) (p) | 2021-08-21T11:52:30Z | 3,122 | 368 | 333 | 3,823 |
| [v2.3.5](https://github.com/laurent22/joplin/releases/tag/v2.3.5) | 2021-08-17T06:43:30Z | 83,279 | 31,408 | 33,119 | 147,806 |
| [v2.3.3](https://github.com/laurent22/joplin/releases/tag/v2.3.3) | 2021-08-14T09:19:40Z | 16,759 | 6,880 | 4,056 | 27,695 |
| [v2.2.7](https://github.com/laurent22/joplin/releases/tag/v2.2.7) | 2021-08-11T11:03:26Z | 16,773 | 7,519 | 2,594 | 26,886 |
| [v2.2.6](https://github.com/laurent22/joplin/releases/tag/v2.2.6) (p) | 2021-08-09T19:29:20Z | 9,503 | 4,616 | 955 | 15,074 |
| [v2.2.5](https://github.com/laurent22/joplin/releases/tag/v2.2.5) (p) | 2021-08-07T10:35:24Z | 2,858 | 274 | 204 | 3,336 |
| [v2.2.4](https://github.com/laurent22/joplin/releases/tag/v2.2.4) (p) | 2021-08-05T16:42:48Z | 2,524 | 204 | 130 | 2,858 |
| [v2.2.2](https://github.com/laurent22/joplin/releases/tag/v2.2.2) (p) | 2021-07-19T10:28:35Z | 4,411 | 733 | 644 | 5,788 |
| [v2.1.9](https://github.com/laurent22/joplin/releases/tag/v2.1.9) | 2021-07-19T10:28:43Z | 48,163 | 18,807 | 16,803 | 83,773 |
| [v2.2.1](https://github.com/laurent22/joplin/releases/tag/v2.2.1) (p) | 2021-07-09T17:38:25Z | 4,068 | 412 | 390 | 4,870 |
| [v2.1.8](https://github.com/laurent22/joplin/releases/tag/v2.1.8) | 2021-07-03T08:25:16Z | 31,920 | 12,195 | 12,728 | 56,843 |
| [v2.1.7](https://github.com/laurent22/joplin/releases/tag/v2.1.7) | 2021-06-26T19:48:55Z | 15,479 | 6,405 | 3,627 | 25,511 |
| [v2.1.5](https://github.com/laurent22/joplin/releases/tag/v2.1.5) (p) | 2021-06-23T15:08:52Z | 2,909 | 246 | 198 | 3,353 |
| [v2.1.3](https://github.com/laurent22/joplin/releases/tag/v2.1.3) (p) | 2021-06-19T16:32:51Z | 3,002 | 306 | 212 | 3,520 |
| [v2.0.11](https://github.com/laurent22/joplin/releases/tag/v2.0.11) | 2021-06-16T17:55:49Z | 25,181 | 9,270 | 9,866 | 44,317 |
| [v2.0.10](https://github.com/laurent22/joplin/releases/tag/v2.0.10) | 2021-06-16T07:58:29Z | 4,188 | 940 | 391 | 5,519 |
| [v2.0.9](https://github.com/laurent22/joplin/releases/tag/v2.0.9) (p) | 2021-06-12T09:30:30Z | 2,921 | 301 | 889 | 4,111 |
| [v2.0.8](https://github.com/laurent22/joplin/releases/tag/v2.0.8) (p) | 2021-06-10T16:15:08Z | 2,446 | 237 | 588 | 3,271 |
| [v2.9.1](https://github.com/laurent22/joplin/releases/tag/v2.9.1) (p) | 2022-07-11T09:59:32Z | 6,799 | 1,335 | 1,393 | 9,527 |
| [v2.8.8](https://github.com/laurent22/joplin/releases/tag/v2.8.8) | 2022-05-17T14:48:06Z | 348,230 | 114,232 | 113,469 | 575,931 |
| [v2.8.7](https://github.com/laurent22/joplin/releases/tag/v2.8.7) (p) | 2022-05-06T11:34:27Z | 3,224 | 360 | 389 | 3,973 |
| [v2.8.6](https://github.com/laurent22/joplin/releases/tag/v2.8.6) (p) | 2022-05-03T10:08:25Z | 2,849 | 399 | 324 | 3,572 |
| [v2.8.5](https://github.com/laurent22/joplin/releases/tag/v2.8.5) (p) | 2022-04-27T13:51:50Z | 2,913 | 367 | 348 | 3,628 |
| [v2.8.4](https://github.com/laurent22/joplin/releases/tag/v2.8.4) (p) | 2022-04-19T18:00:09Z | 3,423 | 585 | 322 | 4,330 |
| [v2.8.2](https://github.com/laurent22/joplin/releases/tag/v2.8.2) (p) | 2022-04-14T11:35:45Z | 2,826 | 275 | 259 | 3,360 |
| [v2.7.15](https://github.com/laurent22/joplin/releases/tag/v2.7.15) | 2022-03-17T13:03:23Z | 154,671 | 56,750 | 51,229 | 262,650 |
| [v2.7.14](https://github.com/laurent22/joplin/releases/tag/v2.7.14) | 2022-02-27T11:30:53Z | 33,223 | 16,771 | 4,791 | 54,785 |
| [v2.7.13](https://github.com/laurent22/joplin/releases/tag/v2.7.13) | 2022-02-24T17:42:12Z | 53,641 | 25,718 | 11,705 | 91,064 |
| [v2.7.12](https://github.com/laurent22/joplin/releases/tag/v2.7.12) (p) | 2022-02-14T15:06:14Z | 3,596 | 460 | 463 | 4,519 |
| [v2.7.11](https://github.com/laurent22/joplin/releases/tag/v2.7.11) (p) | 2022-02-12T13:00:02Z | 2,720 | 192 | 157 | 3,069 |
| [v2.7.10](https://github.com/laurent22/joplin/releases/tag/v2.7.10) (p) | 2022-02-11T18:19:09Z | 2,249 | 121 | 80 | 2,450 |
| [v2.7.8](https://github.com/laurent22/joplin/releases/tag/v2.7.8) (p) | 2022-01-19T09:35:27Z | 4,487 | 766 | 819 | 6,072 |
| [v2.7.7](https://github.com/laurent22/joplin/releases/tag/v2.7.7) (p) | 2022-01-18T14:05:07Z | 2,567 | 152 | 131 | 2,850 |
| [v2.7.6](https://github.com/laurent22/joplin/releases/tag/v2.7.6) (p) | 2022-01-17T17:08:28Z | 2,508 | 178 | 110 | 2,796 |
| [v2.6.10](https://github.com/laurent22/joplin/releases/tag/v2.6.10) | 2021-12-19T11:31:16Z | 134,089 | 51,183 | 49,263 | 234,535 |
| [v2.6.9](https://github.com/laurent22/joplin/releases/tag/v2.6.9) | 2021-12-17T11:57:32Z | 17,691 | 9,490 | 3,180 | 30,361 |
| [v2.6.7](https://github.com/laurent22/joplin/releases/tag/v2.6.7) (p) | 2021-12-16T10:47:23Z | 2,701 | 160 | 99 | 2,960 |
| [v2.6.6](https://github.com/laurent22/joplin/releases/tag/v2.6.6) (p) | 2021-12-13T12:31:43Z | 2,716 | 253 | 162 | 3,131 |
| [v2.6.5](https://github.com/laurent22/joplin/releases/tag/v2.6.5) (p) | 2021-12-13T10:07:04Z | 2,045 | 48 | 28 | 2,121 |
| [v2.6.4](https://github.com/laurent22/joplin/releases/tag/v2.6.4) (p) | 2021-12-09T19:53:43Z | 2,761 | 286 | 197 | 3,244 |
| [v2.6.2](https://github.com/laurent22/joplin/releases/tag/v2.6.2) (p) | 2021-11-18T12:19:12Z | 4,558 | 788 | 698 | 6,044 |
| [v2.5.12](https://github.com/laurent22/joplin/releases/tag/v2.5.12) | 2021-11-08T11:07:11Z | 81,183 | 32,497 | 25,216 | 138,896 |
| [v2.5.10](https://github.com/laurent22/joplin/releases/tag/v2.5.10) | 2021-11-01T08:22:42Z | 45,822 | 19,035 | 10,081 | 74,938 |
| [v2.5.8](https://github.com/laurent22/joplin/releases/tag/v2.5.8) | 2021-10-31T11:38:03Z | 14,553 | 6,563 | 2,309 | 23,425 |
| [v2.5.7](https://github.com/laurent22/joplin/releases/tag/v2.5.7) (p) | 2021-10-29T14:47:33Z | 2,313 | 201 | 162 | 2,676 |
| [v2.5.6](https://github.com/laurent22/joplin/releases/tag/v2.5.6) (p) | 2021-10-28T22:03:09Z | 2,354 | 174 | 105 | 2,633 |
| [v2.5.4](https://github.com/laurent22/joplin/releases/tag/v2.5.4) (p) | 2021-10-19T10:10:54Z | 3,849 | 565 | 570 | 4,984 |
| [v2.4.12](https://github.com/laurent22/joplin/releases/tag/v2.4.12) | 2021-10-13T17:24:34Z | 45,685 | 19,972 | 9,779 | 75,436 |
| [v2.5.1](https://github.com/laurent22/joplin/releases/tag/v2.5.1) (p) | 2021-10-02T09:51:58Z | 4,861 | 901 | 942 | 6,704 |
| [v2.4.9](https://github.com/laurent22/joplin/releases/tag/v2.4.9) | 2021-09-29T19:08:58Z | 57,767 | 23,247 | 15,888 | 96,902 |
| [v2.4.8](https://github.com/laurent22/joplin/releases/tag/v2.4.8) (p) | 2021-09-22T19:01:46Z | 8,711 | 1,770 | 532 | 11,013 |
| [v2.4.7](https://github.com/laurent22/joplin/releases/tag/v2.4.7) (p) | 2021-09-19T12:53:22Z | 2,809 | 250 | 204 | 3,263 |
| [v2.4.6](https://github.com/laurent22/joplin/releases/tag/v2.4.6) (p) | 2021-09-09T18:57:17Z | 3,573 | 456 | 516 | 4,545 |
| [v2.4.5](https://github.com/laurent22/joplin/releases/tag/v2.4.5) (p) | 2021-09-06T18:03:28Z | 2,825 | 270 | 221 | 3,316 |
| [v2.4.4](https://github.com/laurent22/joplin/releases/tag/v2.4.4) (p) | 2021-08-30T16:02:51Z | 3,030 | 374 | 356 | 3,760 |
| [v2.4.3](https://github.com/laurent22/joplin/releases/tag/v2.4.3) (p) | 2021-08-28T15:27:32Z | 2,556 | 202 | 175 | 2,933 |
| [v2.4.2](https://github.com/laurent22/joplin/releases/tag/v2.4.2) (p) | 2021-08-27T17:13:21Z | 2,284 | 146 | 88 | 2,518 |
| [v2.4.1](https://github.com/laurent22/joplin/releases/tag/v2.4.1) (p) | 2021-08-21T11:52:30Z | 3,172 | 368 | 333 | 3,873 |
| [v2.3.5](https://github.com/laurent22/joplin/releases/tag/v2.3.5) | 2021-08-17T06:43:30Z | 83,355 | 31,412 | 33,120 | 147,887 |
| [v2.3.3](https://github.com/laurent22/joplin/releases/tag/v2.3.3) | 2021-08-14T09:19:40Z | 16,858 | 6,881 | 4,057 | 27,796 |
| [v2.2.7](https://github.com/laurent22/joplin/releases/tag/v2.2.7) | 2021-08-11T11:03:26Z | 16,830 | 7,519 | 2,594 | 26,943 |
| [v2.2.6](https://github.com/laurent22/joplin/releases/tag/v2.2.6) (p) | 2021-08-09T19:29:20Z | 9,550 | 4,616 | 955 | 15,121 |
| [v2.2.5](https://github.com/laurent22/joplin/releases/tag/v2.2.5) (p) | 2021-08-07T10:35:24Z | 2,902 | 274 | 204 | 3,380 |
| [v2.2.4](https://github.com/laurent22/joplin/releases/tag/v2.2.4) (p) | 2021-08-05T16:42:48Z | 2,569 | 204 | 130 | 2,903 |
| [v2.2.2](https://github.com/laurent22/joplin/releases/tag/v2.2.2) (p) | 2021-07-19T10:28:35Z | 4,460 | 733 | 644 | 5,837 |
| [v2.1.9](https://github.com/laurent22/joplin/releases/tag/v2.1.9) | 2021-07-19T10:28:43Z | 48,246 | 18,808 | 16,803 | 83,857 |
| [v2.2.1](https://github.com/laurent22/joplin/releases/tag/v2.2.1) (p) | 2021-07-09T17:38:25Z | 4,113 | 413 | 390 | 4,916 |
| [v2.1.8](https://github.com/laurent22/joplin/releases/tag/v2.1.8) | 2021-07-03T08:25:16Z | 31,994 | 12,195 | 12,728 | 56,917 |
| [v2.1.7](https://github.com/laurent22/joplin/releases/tag/v2.1.7) | 2021-06-26T19:48:55Z | 15,524 | 6,405 | 3,627 | 25,556 |
| [v2.1.5](https://github.com/laurent22/joplin/releases/tag/v2.1.5) (p) | 2021-06-23T15:08:52Z | 2,958 | 247 | 198 | 3,403 |
| [v2.1.3](https://github.com/laurent22/joplin/releases/tag/v2.1.3) (p) | 2021-06-19T16:32:51Z | 3,049 | 306 | 212 | 3,567 |
| [v2.0.11](https://github.com/laurent22/joplin/releases/tag/v2.0.11) | 2021-06-16T17:55:49Z | 25,216 | 9,270 | 9,870 | 44,356 |
| [v2.0.10](https://github.com/laurent22/joplin/releases/tag/v2.0.10) | 2021-06-16T07:58:29Z | 4,243 | 940 | 391 | 5,574 |
| [v2.0.9](https://github.com/laurent22/joplin/releases/tag/v2.0.9) (p) | 2021-06-12T09:30:30Z | 2,955 | 301 | 889 | 4,145 |
| [v2.0.8](https://github.com/laurent22/joplin/releases/tag/v2.0.8) (p) | 2021-06-10T16:15:08Z | 2,480 | 238 | 588 | 3,306 |
| [v2.0.4](https://github.com/laurent22/joplin/releases/tag/v2.0.4) (p) | 2021-06-02T12:54:17Z | 1,633 | 400 | 388 | 2,421 |
| [v2.0.2](https://github.com/laurent22/joplin/releases/tag/v2.0.2) (p) | 2021-05-21T18:07:48Z | 4,292 | 498 | 1,677 | 6,467 |
| [v2.0.2](https://github.com/laurent22/joplin/releases/tag/v2.0.2) (p) | 2021-05-21T18:07:48Z | 4,342 | 498 | 1,677 | 6,517 |
| [v2.0.1](https://github.com/laurent22/joplin/releases/tag/v2.0.1) (p) | 2021-05-15T13:22:58Z | 902 | 281 | 1,032 | 2,215 |
| [v1.8.5](https://github.com/laurent22/joplin/releases/tag/v1.8.5) | 2021-05-10T11:58:14Z | 39,886 | 16,290 | 19,421 | 75,597 |
| [v1.8.4](https://github.com/laurent22/joplin/releases/tag/v1.8.4) (p) | 2021-05-09T18:05:05Z | 2,411 | 147 | 468 | 3,026 |
| [v1.8.3](https://github.com/laurent22/joplin/releases/tag/v1.8.3) (p) | 2021-05-04T10:38:16Z | 3,414 | 317 | 948 | 4,679 |
| [v1.8.2](https://github.com/laurent22/joplin/releases/tag/v1.8.2) (p) | 2021-04-25T10:50:51Z | 3,697 | 446 | 1,296 | 5,439 |
| [v1.8.1](https://github.com/laurent22/joplin/releases/tag/v1.8.1) (p) | 2021-03-29T10:46:41Z | 4,728 | 836 | 2,462 | 8,026 |
| [v1.7.11](https://github.com/laurent22/joplin/releases/tag/v1.7.11) | 2021-02-03T12:50:01Z | 118,936 | 42,912 | 64,387 | 226,235 |
| [v1.7.10](https://github.com/laurent22/joplin/releases/tag/v1.7.10) | 2021-01-30T13:25:29Z | 14,356 | 4,873 | 4,512 | 23,741 |
| [v1.8.5](https://github.com/laurent22/joplin/releases/tag/v1.8.5) | 2021-05-10T11:58:14Z | 39,958 | 16,290 | 19,421 | 75,669 |
| [v1.8.4](https://github.com/laurent22/joplin/releases/tag/v1.8.4) (p) | 2021-05-09T18:05:05Z | 2,446 | 147 | 468 | 3,061 |
| [v1.8.3](https://github.com/laurent22/joplin/releases/tag/v1.8.3) (p) | 2021-05-04T10:38:16Z | 3,446 | 317 | 948 | 4,711 |
| [v1.8.2](https://github.com/laurent22/joplin/releases/tag/v1.8.2) (p) | 2021-04-25T10:50:51Z | 3,731 | 446 | 1,296 | 5,473 |
| [v1.8.1](https://github.com/laurent22/joplin/releases/tag/v1.8.1) (p) | 2021-03-29T10:46:41Z | 4,763 | 836 | 2,462 | 8,061 |
| [v1.7.11](https://github.com/laurent22/joplin/releases/tag/v1.7.11) | 2021-02-03T12:50:01Z | 119,022 | 42,916 | 64,387 | 226,325 |
| [v1.7.10](https://github.com/laurent22/joplin/releases/tag/v1.7.10) | 2021-01-30T13:25:29Z | 14,364 | 4,873 | 4,513 | 23,750 |
| [v1.7.9](https://github.com/laurent22/joplin/releases/tag/v1.7.9) (p) | 2021-01-28T09:50:21Z | 524 | 144 | 510 | 1,178 |
| [v1.7.6](https://github.com/laurent22/joplin/releases/tag/v1.7.6) (p) | 2021-01-27T10:36:05Z | 338 | 104 | 300 | 742 |
| [v1.7.5](https://github.com/laurent22/joplin/releases/tag/v1.7.5) (p) | 2021-01-26T09:53:05Z | 431 | 216 | 466 | 1,113 |
| [v1.7.4](https://github.com/laurent22/joplin/releases/tag/v1.7.4) (p) | 2021-01-22T17:58:38Z | 717 | 215 | 637 | 1,569 |
| [v1.6.8](https://github.com/laurent22/joplin/releases/tag/v1.6.8) | 2021-01-20T18:11:34Z | 21,475 | 7,724 | 7,622 | 36,821 |
| [v1.7.4](https://github.com/laurent22/joplin/releases/tag/v1.7.4) (p) | 2021-01-22T17:58:38Z | 718 | 215 | 637 | 1,570 |
| [v1.6.8](https://github.com/laurent22/joplin/releases/tag/v1.6.8) | 2021-01-20T18:11:34Z | 21,528 | 7,724 | 7,622 | 36,874 |
| [v1.7.3](https://github.com/laurent22/joplin/releases/tag/v1.7.3) (p) | 2021-01-20T11:23:50Z | 371 | 88 | 455 | 914 |
| [v1.6.7](https://github.com/laurent22/joplin/releases/tag/v1.6.7) | 2021-01-11T23:20:33Z | 13,187 | 4,658 | 4,565 | 22,410 |
| [v1.6.7](https://github.com/laurent22/joplin/releases/tag/v1.6.7) | 2021-01-11T23:20:33Z | 13,244 | 4,658 | 4,565 | 22,467 |
| [v1.6.6](https://github.com/laurent22/joplin/releases/tag/v1.6.6) | 2021-01-09T16:15:31Z | 12,748 | 3,435 | 4,809 | 20,992 |
| [v1.6.5](https://github.com/laurent22/joplin/releases/tag/v1.6.5) (p) | 2021-01-09T01:24:32Z | 2,681 | 88 | 320 | 3,089 |
| [v1.6.5](https://github.com/laurent22/joplin/releases/tag/v1.6.5) (p) | 2021-01-09T01:24:32Z | 2,714 | 88 | 320 | 3,122 |
| [v1.6.4](https://github.com/laurent22/joplin/releases/tag/v1.6.4) (p) | 2021-01-07T19:11:32Z | 414 | 89 | 216 | 719 |
| [v1.6.2](https://github.com/laurent22/joplin/releases/tag/v1.6.2) (p) | 2021-01-04T22:34:55Z | 695 | 239 | 602 | 1,536 |
| [v1.5.14](https://github.com/laurent22/joplin/releases/tag/v1.5.14) | 2020-12-30T01:48:46Z | 13,674 | 5,227 | 5,544 | 24,445 |
| [v1.5.14](https://github.com/laurent22/joplin/releases/tag/v1.5.14) | 2020-12-30T01:48:46Z | 13,728 | 5,227 | 5,544 | 24,499 |
| [v1.6.1](https://github.com/laurent22/joplin/releases/tag/v1.6.1) (p) | 2020-12-29T19:37:45Z | 193 | 49 | 180 | 422 |
| [v1.5.13](https://github.com/laurent22/joplin/releases/tag/v1.5.13) | 2020-12-29T18:29:15Z | 689 | 237 | 221 | 1,147 |
| [v1.5.12](https://github.com/laurent22/joplin/releases/tag/v1.5.12) | 2020-12-28T15:14:08Z | 2,460 | 1,790 | 937 | 5,187 |
| [v1.5.11](https://github.com/laurent22/joplin/releases/tag/v1.5.11) | 2020-12-27T19:54:07Z | 14,223 | 4,652 | 4,297 | 23,172 |
| [v1.5.12](https://github.com/laurent22/joplin/releases/tag/v1.5.12) | 2020-12-28T15:14:08Z | 2,460 | 1,791 | 937 | 5,188 |
| [v1.5.11](https://github.com/laurent22/joplin/releases/tag/v1.5.11) | 2020-12-27T19:54:07Z | 14,224 | 4,653 | 4,298 | 23,175 |
| [v1.5.10](https://github.com/laurent22/joplin/releases/tag/v1.5.10) (p) | 2020-12-26T12:35:36Z | 316 | 118 | 282 | 716 |
| [v1.5.9](https://github.com/laurent22/joplin/releases/tag/v1.5.9) (p) | 2020-12-23T18:01:08Z | 350 | 383 | 423 | 1,156 |
| [v1.5.8](https://github.com/laurent22/joplin/releases/tag/v1.5.8) (p) | 2020-12-20T09:45:19Z | 588 | 176 | 656 | 1,420 |
| [v1.5.7](https://github.com/laurent22/joplin/releases/tag/v1.5.7) (p) | 2020-12-10T12:58:33Z | 911 | 265 | 1,006 | 2,182 |
| [v1.5.4](https://github.com/laurent22/joplin/releases/tag/v1.5.4) (p) | 2020-12-05T12:07:49Z | 715 | 178 | 647 | 1,540 |
| [v1.4.19](https://github.com/laurent22/joplin/releases/tag/v1.4.19) | 2020-12-01T11:11:16Z | 28,340 | 13,572 | 11,703 | 53,615 |
| [v1.4.19](https://github.com/laurent22/joplin/releases/tag/v1.4.19) | 2020-12-01T11:11:16Z | 28,374 | 13,578 | 11,703 | 53,655 |
| [v1.4.18](https://github.com/laurent22/joplin/releases/tag/v1.4.18) | 2020-11-28T12:21:41Z | 11,636 | 3,905 | 3,156 | 18,697 |
| [v1.4.16](https://github.com/laurent22/joplin/releases/tag/v1.4.16) | 2020-11-27T19:40:16Z | 1,541 | 856 | 615 | 3,012 |
| [v1.4.15](https://github.com/laurent22/joplin/releases/tag/v1.4.15) | 2020-11-27T13:25:43Z | 962 | 508 | 290 | 1,760 |
| [v1.4.12](https://github.com/laurent22/joplin/releases/tag/v1.4.12) | 2020-11-23T18:58:07Z | 3,103 | 1,365 | 1,322 | 5,790 |
| [v1.4.11](https://github.com/laurent22/joplin/releases/tag/v1.4.11) (p) | 2020-11-19T23:06:51Z | 3,456 | 184 | 607 | 4,247 |
| [v1.4.10](https://github.com/laurent22/joplin/releases/tag/v1.4.10) (p) | 2020-11-14T09:53:15Z | 679 | 222 | 698 | 1,599 |
| [v1.4.11](https://github.com/laurent22/joplin/releases/tag/v1.4.11) (p) | 2020-11-19T23:06:51Z | 3,490 | 184 | 607 | 4,281 |
| [v1.4.10](https://github.com/laurent22/joplin/releases/tag/v1.4.10) (p) | 2020-11-14T09:53:15Z | 680 | 222 | 698 | 1,600 |
| [v1.4.9](https://github.com/laurent22/joplin/releases/tag/v1.4.9) (p) | 2020-11-11T14:23:17Z | 864 | 168 | 416 | 1,448 |
| [v1.4.7](https://github.com/laurent22/joplin/releases/tag/v1.4.7) (p) | 2020-11-07T18:23:29Z | 550 | 199 | 529 | 1,278 |
| [v1.3.18](https://github.com/laurent22/joplin/releases/tag/v1.3.18) | 2020-11-06T12:07:02Z | 33,687 | 11,375 | 10,536 | 55,598 |
| [v1.3.18](https://github.com/laurent22/joplin/releases/tag/v1.3.18) | 2020-11-06T12:07:02Z | 33,740 | 11,375 | 10,536 | 55,651 |
| [v1.3.17](https://github.com/laurent22/joplin/releases/tag/v1.3.17) (p) | 2020-11-06T11:35:15Z | 76 | 53 | 38 | 167 |
| [v1.4.6](https://github.com/laurent22/joplin/releases/tag/v1.4.6) (p) | 2020-11-05T22:44:12Z | 695 | 120 | 67 | 882 |
| [v1.3.15](https://github.com/laurent22/joplin/releases/tag/v1.3.15) | 2020-11-04T12:22:50Z | 2,639 | 1,335 | 865 | 4,839 |
| [v1.3.11](https://github.com/laurent22/joplin/releases/tag/v1.3.11) (p) | 2020-10-31T13:22:20Z | 730 | 213 | 496 | 1,439 |
| [v1.3.10](https://github.com/laurent22/joplin/releases/tag/v1.3.10) (p) | 2020-10-29T13:27:14Z | 405 | 142 | 331 | 878 |
| [v1.3.9](https://github.com/laurent22/joplin/releases/tag/v1.3.9) (p) | 2020-10-23T16:04:26Z | 868 | 271 | 648 | 1,787 |
| [v1.3.9](https://github.com/laurent22/joplin/releases/tag/v1.3.9) (p) | 2020-10-23T16:04:26Z | 869 | 271 | 648 | 1,788 |
| [v1.3.8](https://github.com/laurent22/joplin/releases/tag/v1.3.8) (p) | 2020-10-21T18:46:29Z | 550 | 144 | 345 | 1,039 |
| [v1.3.7](https://github.com/laurent22/joplin/releases/tag/v1.3.7) (p) | 2020-10-20T11:35:55Z | 323 | 112 | 357 | 792 |
| [v1.3.5](https://github.com/laurent22/joplin/releases/tag/v1.3.5) (p) | 2020-10-17T14:26:35Z | 502 | 161 | 421 | 1,084 |
| [v1.3.3](https://github.com/laurent22/joplin/releases/tag/v1.3.3) (p) | 2020-10-17T10:56:57Z | 148 | 73 | 48 | 269 |
| [v1.3.2](https://github.com/laurent22/joplin/releases/tag/v1.3.2) (p) | 2020-10-11T20:39:49Z | 698 | 210 | 583 | 1,491 |
| [v1.3.1](https://github.com/laurent22/joplin/releases/tag/v1.3.1) (p) | 2020-10-11T15:10:18Z | 112 | 79 | 59 | 250 |
| [v1.2.6](https://github.com/laurent22/joplin/releases/tag/v1.2.6) | 2020-10-09T13:56:59Z | 47,616 | 17,778 | 14,072 | 79,466 |
| [v1.2.6](https://github.com/laurent22/joplin/releases/tag/v1.2.6) | 2020-10-09T13:56:59Z | 47,688 | 17,778 | 14,072 | 79,538 |
| [v1.2.4](https://github.com/laurent22/joplin/releases/tag/v1.2.4) (p) | 2020-09-30T07:34:29Z | 849 | 276 | 814 | 1,939 |
| [v1.2.3](https://github.com/laurent22/joplin/releases/tag/v1.2.3) (p) | 2020-09-29T15:13:02Z | 249 | 92 | 97 | 438 |
| [v1.2.2](https://github.com/laurent22/joplin/releases/tag/v1.2.2) (p) | 2020-09-22T20:31:55Z | 1,139 | 235 | 654 | 2,028 |
| [v1.1.4](https://github.com/laurent22/joplin/releases/tag/v1.1.4) | 2020-09-21T11:20:09Z | 28,106 | 13,542 | 7,775 | 49,423 |
| [v1.1.4](https://github.com/laurent22/joplin/releases/tag/v1.1.4) | 2020-09-21T11:20:09Z | 28,132 | 13,542 | 7,775 | 49,449 |
| [v1.1.3](https://github.com/laurent22/joplin/releases/tag/v1.1.3) (p) | 2020-09-17T10:30:37Z | 605 | 180 | 480 | 1,265 |
| [v1.1.2](https://github.com/laurent22/joplin/releases/tag/v1.1.2) (p) | 2020-09-15T12:58:38Z | 412 | 146 | 268 | 826 |
| [v1.1.1](https://github.com/laurent22/joplin/releases/tag/v1.1.1) (p) | 2020-09-11T23:32:47Z | 582 | 226 | 366 | 1,174 |
| [v1.0.245](https://github.com/laurent22/joplin/releases/tag/v1.0.245) | 2020-09-09T12:56:10Z | 22,650 | 10,049 | 5,667 | 38,366 |
| [v1.0.242](https://github.com/laurent22/joplin/releases/tag/v1.0.242) | 2020-09-04T22:00:34Z | 12,875 | 6,453 | 3,039 | 22,367 |
| [v1.0.241](https://github.com/laurent22/joplin/releases/tag/v1.0.241) | 2020-09-04T18:06:00Z | 26,478 | 5,973 | 5,133 | 37,584 |
| [v1.1.1](https://github.com/laurent22/joplin/releases/tag/v1.1.1) (p) | 2020-09-11T23:32:47Z | 583 | 226 | 366 | 1,175 |
| [v1.0.245](https://github.com/laurent22/joplin/releases/tag/v1.0.245) | 2020-09-09T12:56:10Z | 22,689 | 10,049 | 5,667 | 38,405 |
| [v1.0.242](https://github.com/laurent22/joplin/releases/tag/v1.0.242) | 2020-09-04T22:00:34Z | 12,876 | 6,453 | 3,039 | 22,368 |
| [v1.0.241](https://github.com/laurent22/joplin/releases/tag/v1.0.241) | 2020-09-04T18:06:00Z | 26,507 | 5,973 | 5,133 | 37,613 |
| [v1.0.239](https://github.com/laurent22/joplin/releases/tag/v1.0.239) (p) | 2020-09-01T21:56:36Z | 957 | 258 | 419 | 1,634 |
| [v1.0.237](https://github.com/laurent22/joplin/releases/tag/v1.0.237) (p) | 2020-08-29T15:38:04Z | 622 | 956 | 357 | 1,935 |
| [v1.0.236](https://github.com/laurent22/joplin/releases/tag/v1.0.236) (p) | 2020-08-28T09:16:54Z | 347 | 143 | 122 | 612 |
| [v1.0.235](https://github.com/laurent22/joplin/releases/tag/v1.0.235) (p) | 2020-08-18T22:08:01Z | 2,030 | 522 | 940 | 3,492 |
| [v1.0.234](https://github.com/laurent22/joplin/releases/tag/v1.0.234) (p) | 2020-08-17T23:13:02Z | 659 | 157 | 119 | 935 |
| [v1.0.233](https://github.com/laurent22/joplin/releases/tag/v1.0.233) | 2020-08-01T14:51:15Z | 46,231 | 18,233 | 12,379 | 76,843 |
| [v1.0.234](https://github.com/laurent22/joplin/releases/tag/v1.0.234) (p) | 2020-08-17T23:13:02Z | 663 | 157 | 119 | 939 |
| [v1.0.233](https://github.com/laurent22/joplin/releases/tag/v1.0.233) | 2020-08-01T14:51:15Z | 46,281 | 18,233 | 12,379 | 76,893 |
| [v1.0.232](https://github.com/laurent22/joplin/releases/tag/v1.0.232) (p) | 2020-07-28T22:34:40Z | 688 | 255 | 198 | 1,141 |
| [v1.0.227](https://github.com/laurent22/joplin/releases/tag/v1.0.227) | 2020-07-07T20:44:54Z | 41,463 | 15,314 | 9,662 | 66,439 |
| [v1.0.227](https://github.com/laurent22/joplin/releases/tag/v1.0.227) | 2020-07-07T20:44:54Z | 41,487 | 15,314 | 9,662 | 66,463 |
| [v1.0.226](https://github.com/laurent22/joplin/releases/tag/v1.0.226) (p) | 2020-07-04T10:21:26Z | 4,955 | 2,285 | 706 | 7,946 |
| [v1.0.224](https://github.com/laurent22/joplin/releases/tag/v1.0.224) | 2020-06-20T22:26:08Z | 25,086 | 11,039 | 6,026 | 42,151 |
| [v1.0.224](https://github.com/laurent22/joplin/releases/tag/v1.0.224) | 2020-06-20T22:26:08Z | 25,102 | 11,039 | 6,026 | 42,167 |
| [v1.0.223](https://github.com/laurent22/joplin/releases/tag/v1.0.223) (p) | 2020-06-20T11:51:27Z | 220 | 146 | 97 | 463 |
| [v1.0.221](https://github.com/laurent22/joplin/releases/tag/v1.0.221) (p) | 2020-06-20T01:44:20Z | 888 | 239 | 231 | 1,358 |
| [v1.0.220](https://github.com/laurent22/joplin/releases/tag/v1.0.220) | 2020-06-13T18:26:22Z | 32,764 | 9,960 | 6,437 | 49,161 |
| [v1.0.220](https://github.com/laurent22/joplin/releases/tag/v1.0.220) | 2020-06-13T18:26:22Z | 32,772 | 9,960 | 6,437 | 49,169 |
| [v1.0.218](https://github.com/laurent22/joplin/releases/tag/v1.0.218) | 2020-06-07T10:43:34Z | 14,600 | 7,007 | 3,146 | 24,753 |
| [v1.0.217](https://github.com/laurent22/joplin/releases/tag/v1.0.217) (p) | 2020-06-06T15:17:27Z | 259 | 128 | 76 | 463 |
| [v1.0.216](https://github.com/laurent22/joplin/releases/tag/v1.0.216) | 2020-05-24T14:21:01Z | 39,994 | 14,339 | 10,207 | 64,540 |
| [v1.0.214](https://github.com/laurent22/joplin/releases/tag/v1.0.214) (p) | 2020-05-21T17:15:15Z | 6,855 | 3,502 | 784 | 11,141 |
| [v1.0.216](https://github.com/laurent22/joplin/releases/tag/v1.0.216) | 2020-05-24T14:21:01Z | 40,055 | 14,339 | 10,207 | 64,601 |
| [v1.0.214](https://github.com/laurent22/joplin/releases/tag/v1.0.214) (p) | 2020-05-21T17:15:15Z | 6,882 | 3,502 | 784 | 11,168 |
| [v1.0.212](https://github.com/laurent22/joplin/releases/tag/v1.0.212) (p) | 2020-05-21T07:48:39Z | 244 | 102 | 68 | 414 |
| [v1.0.211](https://github.com/laurent22/joplin/releases/tag/v1.0.211) (p) | 2020-05-20T08:59:16Z | 333 | 166 | 108 | 607 |
| [v1.0.209](https://github.com/laurent22/joplin/releases/tag/v1.0.209) (p) | 2020-05-17T18:32:51Z | 1,426 | 885 | 168 | 2,479 |
| [v1.0.207](https://github.com/laurent22/joplin/releases/tag/v1.0.207) (p) | 2020-05-10T16:37:35Z | 1,230 | 296 | 1,038 | 2,564 |
| [v1.0.201](https://github.com/laurent22/joplin/releases/tag/v1.0.201) | 2020-04-15T22:55:13Z | 54,301 | 20,084 | 18,203 | 92,588 |
| [v1.0.200](https://github.com/laurent22/joplin/releases/tag/v1.0.200) | 2020-04-12T12:17:46Z | 9,606 | 4,924 | 1,924 | 16,454 |
| [v1.0.199](https://github.com/laurent22/joplin/releases/tag/v1.0.199) | 2020-04-10T18:41:58Z | 19,703 | 5,920 | 3,815 | 29,438 |
| [v1.0.197](https://github.com/laurent22/joplin/releases/tag/v1.0.197) | 2020-03-30T17:21:22Z | 23,319 | 9,837 | 6,385 | 39,541 |
| [v1.0.195](https://github.com/laurent22/joplin/releases/tag/v1.0.195) | 2020-03-22T19:56:12Z | 19,146 | 7,982 | 4,526 | 31,654 |
| [v1.0.194](https://github.com/laurent22/joplin/releases/tag/v1.0.194) (p) | 2020-03-14T00:00:32Z | 1,316 | 1,418 | 538 | 3,272 |
| [v1.0.199](https://github.com/laurent22/joplin/releases/tag/v1.0.199) | 2020-04-10T18:41:58Z | 19,710 | 5,920 | 3,819 | 29,449 |
| [v1.0.197](https://github.com/laurent22/joplin/releases/tag/v1.0.197) | 2020-03-30T17:21:22Z | 23,336 | 9,844 | 6,403 | 39,583 |
| [v1.0.195](https://github.com/laurent22/joplin/releases/tag/v1.0.195) | 2020-03-22T19:56:12Z | 19,146 | 7,982 | 4,527 | 31,655 |
| [v1.0.194](https://github.com/laurent22/joplin/releases/tag/v1.0.194) (p) | 2020-03-14T00:00:32Z | 1,316 | 1,418 | 539 | 3,273 |
| [v1.0.193](https://github.com/laurent22/joplin/releases/tag/v1.0.193) | 2020-03-08T08:58:53Z | 28,782 | 10,952 | 7,436 | 47,170 |
| [v1.0.192](https://github.com/laurent22/joplin/releases/tag/v1.0.192) (p) | 2020-03-06T23:27:52Z | 513 | 154 | 109 | 776 |
| [v1.0.190](https://github.com/laurent22/joplin/releases/tag/v1.0.190) (p) | 2020-03-06T01:22:22Z | 418 | 124 | 105 | 647 |
| [v1.0.189](https://github.com/laurent22/joplin/releases/tag/v1.0.189) (p) | 2020-03-04T17:27:15Z | 387 | 128 | 116 | 631 |
| [v1.0.187](https://github.com/laurent22/joplin/releases/tag/v1.0.187) (p) | 2020-03-01T12:31:06Z | 959 | 267 | 293 | 1,519 |
| [v1.0.179](https://github.com/laurent22/joplin/releases/tag/v1.0.179) | 2020-01-24T22:42:41Z | 71,538 | 28,913 | 22,581 | 123,032 |
| [v1.0.178](https://github.com/laurent22/joplin/releases/tag/v1.0.178) | 2020-01-20T19:06:45Z | 17,638 | 5,997 | 2,612 | 26,247 |
| [v1.0.192](https://github.com/laurent22/joplin/releases/tag/v1.0.192) (p) | 2020-03-06T23:27:52Z | 514 | 154 | 109 | 777 |
| [v1.0.190](https://github.com/laurent22/joplin/releases/tag/v1.0.190) (p) | 2020-03-06T01:22:22Z | 419 | 124 | 105 | 648 |
| [v1.0.189](https://github.com/laurent22/joplin/releases/tag/v1.0.189) (p) | 2020-03-04T17:27:15Z | 388 | 128 | 116 | 632 |
| [v1.0.187](https://github.com/laurent22/joplin/releases/tag/v1.0.187) (p) | 2020-03-01T12:31:06Z | 960 | 267 | 293 | 1,520 |
| [v1.0.179](https://github.com/laurent22/joplin/releases/tag/v1.0.179) | 2020-01-24T22:42:41Z | 71,550 | 28,925 | 22,581 | 123,056 |
| [v1.0.178](https://github.com/laurent22/joplin/releases/tag/v1.0.178) | 2020-01-20T19:06:45Z | 17,639 | 5,997 | 2,612 | 26,248 |
| [v1.0.177](https://github.com/laurent22/joplin/releases/tag/v1.0.177) (p) | 2019-12-30T14:40:40Z | 1,991 | 470 | 736 | 3,197 |
| [v1.0.176](https://github.com/laurent22/joplin/releases/tag/v1.0.176) (p) | 2019-12-14T10:36:44Z | 3,155 | 2,567 | 489 | 6,211 |
| [v1.0.175](https://github.com/laurent22/joplin/releases/tag/v1.0.175) | 2019-12-08T11:48:47Z | 73,587 | 16,996 | 16,604 | 107,187 |
| [v1.0.174](https://github.com/laurent22/joplin/releases/tag/v1.0.174) | 2019-11-12T18:20:58Z | 30,659 | 11,781 | 8,247 | 50,687 |
| [v1.0.173](https://github.com/laurent22/joplin/releases/tag/v1.0.173) | 2019-11-11T08:33:35Z | 5,134 | 2,113 | 766 | 8,013 |
| [v1.0.170](https://github.com/laurent22/joplin/releases/tag/v1.0.170) | 2019-10-13T22:13:04Z | 27,754 | 8,811 | 7,707 | 44,272 |
| [v1.0.169](https://github.com/laurent22/joplin/releases/tag/v1.0.169) | 2019-09-27T18:35:13Z | 17,216 | 5,953 | 3,772 | 26,941 |
| [v1.0.168](https://github.com/laurent22/joplin/releases/tag/v1.0.168) | 2019-09-25T21:21:38Z | 5,370 | 2,306 | 737 | 8,413 |
| [v1.0.167](https://github.com/laurent22/joplin/releases/tag/v1.0.167) | 2019-09-10T08:48:37Z | 16,897 | 5,737 | 3,724 | 26,358 |
| [v1.0.175](https://github.com/laurent22/joplin/releases/tag/v1.0.175) | 2019-12-08T11:48:47Z | 73,596 | 16,996 | 16,604 | 107,196 |
| [v1.0.174](https://github.com/laurent22/joplin/releases/tag/v1.0.174) | 2019-11-12T18:20:58Z | 30,664 | 11,783 | 8,247 | 50,694 |
| [v1.0.173](https://github.com/laurent22/joplin/releases/tag/v1.0.173) | 2019-11-11T08:33:35Z | 5,135 | 2,113 | 766 | 8,014 |
| [v1.0.170](https://github.com/laurent22/joplin/releases/tag/v1.0.170) | 2019-10-13T22:13:04Z | 27,758 | 8,811 | 7,707 | 44,276 |
| [v1.0.169](https://github.com/laurent22/joplin/releases/tag/v1.0.169) | 2019-09-27T18:35:13Z | 17,218 | 5,953 | 3,772 | 26,943 |
| [v1.0.168](https://github.com/laurent22/joplin/releases/tag/v1.0.168) | 2019-09-25T21:21:38Z | 5,371 | 2,306 | 738 | 8,415 |
| [v1.0.167](https://github.com/laurent22/joplin/releases/tag/v1.0.167) | 2019-09-10T08:48:37Z | 16,899 | 5,737 | 3,724 | 26,360 |
| [v1.0.166](https://github.com/laurent22/joplin/releases/tag/v1.0.166) | 2019-09-09T17:35:54Z | 1,994 | 593 | 254 | 2,841 |
| [v1.0.165](https://github.com/laurent22/joplin/releases/tag/v1.0.165) | 2019-08-14T21:46:29Z | 19,082 | 7,013 | 5,485 | 31,580 |
| [v1.0.161](https://github.com/laurent22/joplin/releases/tag/v1.0.161) | 2019-07-13T18:30:00Z | 19,361 | 6,383 | 4,156 | 29,900 |
| [v1.0.160](https://github.com/laurent22/joplin/releases/tag/v1.0.160) | 2019-06-15T00:21:40Z | 30,743 | 7,789 | 8,126 | 46,658 |
| [v1.0.159](https://github.com/laurent22/joplin/releases/tag/v1.0.159) | 2019-06-08T00:00:19Z | 5,238 | 2,212 | 1,208 | 8,658 |
| [v1.0.161](https://github.com/laurent22/joplin/releases/tag/v1.0.161) | 2019-07-13T18:30:00Z | 19,365 | 6,383 | 4,156 | 29,904 |
| [v1.0.160](https://github.com/laurent22/joplin/releases/tag/v1.0.160) | 2019-06-15T00:21:40Z | 30,747 | 7,789 | 8,126 | 46,662 |
| [v1.0.159](https://github.com/laurent22/joplin/releases/tag/v1.0.159) | 2019-06-08T00:00:19Z | 5,238 | 2,212 | 1,215 | 8,665 |
| [v1.0.158](https://github.com/laurent22/joplin/releases/tag/v1.0.158) | 2019-05-27T19:01:18Z | 9,861 | 3,580 | 1,956 | 15,397 |
| [v1.0.157](https://github.com/laurent22/joplin/releases/tag/v1.0.157) | 2019-05-26T17:55:53Z | 2,216 | 875 | 310 | 3,401 |
| [v1.0.153](https://github.com/laurent22/joplin/releases/tag/v1.0.153) (p) | 2019-05-15T06:27:29Z | 884 | 135 | 126 | 1,145 |
@@ -236,7 +240,7 @@ updated: 2023-10-01T00:44:28Z
| [v1.0.148](https://github.com/laurent22/joplin/releases/tag/v1.0.148) (p) | 2019-05-08T19:12:24Z | 161 | 89 | 115 | 365 |
| [v1.0.145](https://github.com/laurent22/joplin/releases/tag/v1.0.145) | 2019-05-03T09:16:53Z | 7,046 | 2,893 | 1,457 | 11,396 |
| [v1.0.143](https://github.com/laurent22/joplin/releases/tag/v1.0.143) | 2019-04-22T10:51:38Z | 11,957 | 3,584 | 2,801 | 18,342 |
| [v1.0.142](https://github.com/laurent22/joplin/releases/tag/v1.0.142) | 2019-04-02T16:44:51Z | 14,802 | 4,602 | 4,752 | 24,156 |
| [v1.0.142](https://github.com/laurent22/joplin/releases/tag/v1.0.142) | 2019-04-02T16:44:51Z | 14,803 | 4,602 | 4,752 | 24,157 |
| [v1.0.140](https://github.com/laurent22/joplin/releases/tag/v1.0.140) | 2019-03-10T20:59:58Z | 13,676 | 4,205 | 3,398 | 21,279 |
| [v1.0.139](https://github.com/laurent22/joplin/releases/tag/v1.0.139) (p) | 2019-03-09T10:06:48Z | 155 | 97 | 66 | 318 |
| [v1.0.138](https://github.com/laurent22/joplin/releases/tag/v1.0.138) (p) | 2019-03-03T17:23:00Z | 184 | 122 | 103 | 409 |
@@ -244,9 +248,9 @@ updated: 2023-10-01T00:44:28Z
| [v1.0.135](https://github.com/laurent22/joplin/releases/tag/v1.0.135) | 2019-02-27T23:36:57Z | 12,667 | 3,990 | 4,100 | 20,757 |
| [v1.0.134](https://github.com/laurent22/joplin/releases/tag/v1.0.134) | 2019-02-27T10:21:44Z | 1,504 | 600 | 238 | 2,342 |
| [v1.0.132](https://github.com/laurent22/joplin/releases/tag/v1.0.132) | 2019-02-26T23:02:05Z | 1,124 | 485 | 114 | 1,723 |
| [v1.0.127](https://github.com/laurent22/joplin/releases/tag/v1.0.127) | 2019-02-14T23:12:48Z | 9,944 | 3,205 | 2,951 | 16,100 |
| [v1.0.127](https://github.com/laurent22/joplin/releases/tag/v1.0.127) | 2019-02-14T23:12:48Z | 9,948 | 3,205 | 2,951 | 16,104 |
| [v1.0.126](https://github.com/laurent22/joplin/releases/tag/v1.0.126) (p) | 2019-02-09T19:46:16Z | 966 | 106 | 135 | 1,207 |
| [v1.0.125](https://github.com/laurent22/joplin/releases/tag/v1.0.125) | 2019-01-26T18:14:33Z | 10,336 | 3,590 | 1,722 | 15,648 |
| [v1.0.125](https://github.com/laurent22/joplin/releases/tag/v1.0.125) | 2019-01-26T18:14:33Z | 10,339 | 3,590 | 1,722 | 15,651 |
| [v1.0.120](https://github.com/laurent22/joplin/releases/tag/v1.0.120) | 2019-01-10T21:42:53Z | 15,658 | 5,240 | 6,538 | 27,436 |
| [v1.0.119](https://github.com/laurent22/joplin/releases/tag/v1.0.119) | 2018-12-18T12:40:22Z | 8,954 | 3,294 | 2,035 | 14,283 |
| [v1.0.118](https://github.com/laurent22/joplin/releases/tag/v1.0.118) | 2019-01-11T08:34:13Z | 753 | 280 | 108 | 1,141 |
@@ -254,14 +258,14 @@ updated: 2023-10-01T00:44:28Z
| [v1.0.116](https://github.com/laurent22/joplin/releases/tag/v1.0.116) | 2018-11-20T19:09:24Z | 4,031 | 1,156 | 734 | 5,921 |
| [v1.0.115](https://github.com/laurent22/joplin/releases/tag/v1.0.115) | 2018-11-16T16:52:02Z | 3,691 | 1,335 | 821 | 5,847 |
| [v1.0.114](https://github.com/laurent22/joplin/releases/tag/v1.0.114) | 2018-10-24T20:14:10Z | 11,432 | 3,534 | 3,850 | 18,816 |
| [v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 12,267 | 3,424 | 3,702 | 19,393 |
| [v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 12,275 | 3,431 | 3,702 | 19,408 |
| [v1.0.110](https://github.com/laurent22/joplin/releases/tag/v1.0.110) | 2018-09-29T12:29:21Z | 997 | 443 | 138 | 1,578 |
| [v1.0.109](https://github.com/laurent22/joplin/releases/tag/v1.0.109) | 2018-09-27T18:01:41Z | 2,139 | 738 | 351 | 3,228 |
| [v1.0.108](https://github.com/laurent22/joplin/releases/tag/v1.0.108) (p) | 2018-09-29T18:49:29Z | 61 | 54 | 35 | 150 |
| [v1.0.107](https://github.com/laurent22/joplin/releases/tag/v1.0.107) | 2018-09-16T19:51:07Z | 7,190 | 2,169 | 1,730 | 11,089 |
| [v1.0.106](https://github.com/laurent22/joplin/releases/tag/v1.0.106) | 2018-09-08T15:23:40Z | 4,593 | 1,489 | 337 | 6,419 |
| [v1.0.105](https://github.com/laurent22/joplin/releases/tag/v1.0.105) | 2018-09-05T11:29:36Z | 4,692 | 1,626 | 1,478 | 7,796 |
| [v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 15,117 | 4,735 | 7,387 | 27,239 |
| [v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 15,117 | 4,735 | 7,388 | 27,240 |
| [v1.0.103](https://github.com/laurent22/joplin/releases/tag/v1.0.103) | 2018-06-21T19:38:13Z | 2,089 | 920 | 699 | 3,708 |
| [v1.0.101](https://github.com/laurent22/joplin/releases/tag/v1.0.101) | 2018-06-17T18:35:11Z | 1,345 | 641 | 430 | 2,416 |
| [v1.0.100](https://github.com/laurent22/joplin/releases/tag/v1.0.100) | 2018-06-14T17:41:43Z | 923 | 469 | 267 | 1,659 |
@@ -270,15 +274,15 @@ updated: 2023-10-01T00:44:28Z
| [v1.0.96](https://github.com/laurent22/joplin/releases/tag/v1.0.96) | 2018-05-26T16:36:39Z | 2,762 | 1,257 | 1,732 | 5,751 |
| [v1.0.95](https://github.com/laurent22/joplin/releases/tag/v1.0.95) | 2018-05-25T13:04:30Z | 456 | 252 | 154 | 862 |
| [v1.0.94](https://github.com/laurent22/joplin/releases/tag/v1.0.94) | 2018-05-21T20:52:59Z | 1,169 | 621 | 432 | 2,222 |
| [v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1,826 | 1,310 | 793 | 3,929 |
| [v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1,827 | 1,315 | 793 | 3,935 |
| [v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) | 2018-05-10T14:48:04Z | 847 | 587 | 345 | 1,779 |
| [v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 532 | 274 | 149 | 955 |
| [v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 532 | 275 | 149 | 956 |
| [v1.0.85](https://github.com/laurent22/joplin/releases/tag/v1.0.85) | 2018-05-01T21:08:24Z | 1,675 | 986 | 668 | 3,329 |
| [v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 5,522 | 2,567 | 2,691 | 10,780 |
| [v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 5,530 | 2,567 | 2,691 | 10,788 |
| [v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 723 | 440 | 155 | 1,318 |
| [v1.0.81](https://github.com/laurent22/joplin/releases/tag/v1.0.81) | 2018-03-28T08:13:58Z | 1,020 | 632 | 817 | 2,469 |
| [v1.0.79](https://github.com/laurent22/joplin/releases/tag/v1.0.79) | 2018-03-23T18:00:11Z | 948 | 573 | 418 | 1,939 |
| [v1.0.78](https://github.com/laurent22/joplin/releases/tag/v1.0.78) | 2018-03-17T15:27:18Z | 1,329 | 932 | 904 | 3,165 |
| [v1.0.78](https://github.com/laurent22/joplin/releases/tag/v1.0.78) | 2018-03-17T15:27:18Z | 1,329 | 933 | 904 | 3,166 |
| [v1.0.77](https://github.com/laurent22/joplin/releases/tag/v1.0.77) | 2018-03-16T15:12:35Z | 197 | 138 | 78 | 413 |
| [v1.0.72](https://github.com/laurent22/joplin/releases/tag/v1.0.72) | 2018-03-14T09:44:35Z | 428 | 290 | 88 | 806 |
| [v1.0.70](https://github.com/laurent22/joplin/releases/tag/v1.0.70) | 2018-02-28T20:04:30Z | 1,882 | 1,086 | 1,287 | 4,255 |
@@ -287,7 +291,7 @@ updated: 2023-10-01T00:44:28Z
| [v1.0.65](https://github.com/laurent22/joplin/releases/tag/v1.0.65) | 2018-02-17T20:02:25Z | 218 | 162 | 151 | 531 |
| [v1.0.64](https://github.com/laurent22/joplin/releases/tag/v1.0.64) | 2018-02-16T00:58:20Z | 1,110 | 577 | 1,143 | 2,830 |
| [v1.0.63](https://github.com/laurent22/joplin/releases/tag/v1.0.63) | 2018-02-14T19:40:36Z | 331 | 194 | 111 | 636 |
| [v1.0.62](https://github.com/laurent22/joplin/releases/tag/v1.0.62) | 2018-02-12T20:19:58Z | 591 | 337 | 391 | 1,319 |
| [v1.0.62](https://github.com/laurent22/joplin/releases/tag/v1.0.62) | 2018-02-12T20:19:58Z | 592 | 337 | 391 | 1,320 |
| [v0.10.61](https://github.com/laurent22/joplin/releases/tag/v0.10.61) | 2018-02-08T18:27:39Z | 1,001 | 672 | 983 | 2,656 |
| [v0.10.60](https://github.com/laurent22/joplin/releases/tag/v0.10.60) | 2018-02-06T13:09:56Z | 743 | 556 | 571 | 1,870 |
| [v0.10.54](https://github.com/laurent22/joplin/releases/tag/v0.10.54) | 2018-01-31T20:21:30Z | 1,847 | 1,496 | 344 | 3,687 |
@@ -309,9 +313,9 @@ updated: 2023-10-01T00:44:28Z
| [v0.10.30](https://github.com/laurent22/joplin/releases/tag/v0.10.30) | 2017-11-30T20:28:16Z | 750 | 1,422 | 448 | 2,620 |
| [v0.10.28](https://github.com/laurent22/joplin/releases/tag/v0.10.28) | 2017-11-30T01:07:46Z | 1,387 | 1,753 | 901 | 4,041 |
| [v0.10.26](https://github.com/laurent22/joplin/releases/tag/v0.10.26) | 2017-11-29T16:02:17Z | 221 | 750 | 287 | 1,258 |
| [v0.10.25](https://github.com/laurent22/joplin/releases/tag/v0.10.25) | 2017-11-24T14:27:49Z | 177 | 745 | 6,690 | 7,612 |
| [v0.10.25](https://github.com/laurent22/joplin/releases/tag/v0.10.25) | 2017-11-24T14:27:49Z | 177 | 745 | 6,695 | 7,617 |
| [v0.10.23](https://github.com/laurent22/joplin/releases/tag/v0.10.23) | 2017-11-21T19:38:41Z | 164 | 708 | 60 | 932 |
| [v0.10.22](https://github.com/laurent22/joplin/releases/tag/v0.10.22) | 2017-11-20T21:45:57Z | 113 | 694 | 45 | 852 |
| [v0.10.21](https://github.com/laurent22/joplin/releases/tag/v0.10.21) | 2017-11-18T00:53:15Z | 79 | 687 | 40 | 806 |
| [v0.10.20](https://github.com/laurent22/joplin/releases/tag/v0.10.20) | 2017-11-17T17:18:25Z | 69 | 698 | 49 | 816 |
| [v0.10.19](https://github.com/laurent22/joplin/releases/tag/v0.10.19) | 2017-11-20T18:59:48Z | 64 | 700 | 46 | 810 |
| [v0.10.19](https://github.com/laurent22/joplin/releases/tag/v0.10.19) | 2017-11-20T18:59:48Z | 64 | 700 | 47 | 811 |

View File

@@ -1,3 +1,7 @@
---
sidebar_position: 2
---
# Joplin Data API
This API is available when the clipper server is running. It provides access to the notes, notebooks, tags and other Joplin object via a REST API. Plugins can also access this API even when the clipper server is not running.

View File

@@ -10,13 +10,13 @@ This feature is available for Pro and Teams members.
### Desktop
To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and locate to the Joplin Cloud tab. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/welcome/3_synchronising_your_notes.md#setting-up-joplin-cloud-synchronisation)
To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and locate to the Joplin Cloud tab. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/joplin_cloud.md)
<img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/email_to_note/desktop.png" width="80%"/>
### Mobile
To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and find the Joplin Cloud section. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/welcome/3_synchronising_your_notes.md#setting-up-joplin-cloud-synchronisation)
To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and find the Joplin Cloud section. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/joplin_cloud.md)
<img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/email_to_note/mobile.png" width="50%"/>

View File

@@ -21,10 +21,13 @@ In the **terminal application**, in [command-line mode](https://github.com/laure
Joplin can import notes from plain Markdown file. You can either import a complete directory of Markdown files or individual files.
In the **desktop application**:
* **File import**: Go to File > Import > MD - Markdown (file) and select the Markdown file. This file will then be imported to the currently selected Notebook.
* **Directory import**: Go to File > Import > MD - Markdown (directory) and select the top level of the directory that is being imported. Directory (folder) structure will be preserved in the Notebook > Subnotebook > Note structure within Joplin.
In the **terminal application**, in [command-line mode](https://github.com/laurent22/joplin/blob/dev/readme/apps/terminal.md#command-line-mode), type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`.
In the **terminal application**, in [command-line mode](https://github.com/laurent22/joplin/blob/dev/readme/apps/terminal.md#command-line-mode):
Type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`.
### Importing from other applications

View File

@@ -12,7 +12,7 @@ Due to the decentralised nature of Joplin, E2EE needs to be manually enabled on
To enable it, please follow these steps:
1. On your first device (eg. on the desktop application), go to the Encryption Config screen and click "Enable encryption"
1. On your first device (eg. on the desktop application), go to the Encryption [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and click "Enable encryption"
2. Input your password. This is the Master Key password which will be used to encrypt all your notes. Make sure you do not forget it since, for security reason, it cannot be recovered.
3. Now you need to synchronise all your notes so that they are sent encrypted to the sync target (eg. to OneDrive, Nextcloud, etc.). Wait for any synchronisation that might be in progress and click on "Synchronise".
4. Wait for this synchronisation operation to complete. Since all the data needs to be re-sent (encrypted) to the sync target, it may take a long time, especially if you have many notes and resources. Note that even if synchronisation seems stuck, most likely it is still running - do not cancel it and simply let it run over night if needed.

View File

@@ -0,0 +1,5 @@
# Joplin Cloud synchronisation
[Joplin Cloud](https://joplinapp.org/plans/) is a web service specifically designed for Joplin. Besides synchronising your data, it also allows you to publish a note to the internet, or share a notebook with your friends, family or colleagues. Joplin Cloud, compared to other services, also features a number of performance improvements allowing for faster synchronisation.
To use it, go to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md), then to the Synchronisation section. In the list of sync targets, select "Joplin Cloud". Enter your email and password, and you're ready to use Joplin Cloud.

View File

@@ -6,7 +6,7 @@ Joplin allows you to synchronise your data using various file hosting services.
[Joplin Cloud](https://joplinapp.org/plans/) is a web service specifically designed for Joplin. Besides synchronising your data, it also allows you to publish a note to the internet, or share a notebook with your friends, family or colleagues. Joplin Cloud, compared to other services, also features a number of performance improvements allowing for faster synchronisation.
To use it, go to the config screen, then to the Synchronisation section. In the list of sync target, select "Joplin Cloud". Enter your email and password, and you're ready to use Joplin Cloud.
To use it, go to the config screen, then to the Synchronisation section. In the list of sync targets, select "Joplin Cloud". Enter your email and password, and you're ready to use Joplin Cloud.
## Setting up Dropbox synchronisation

2147
yarn.lock

File diff suppressed because it is too large Load Diff