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

Compare commits

..

84 Commits

Author SHA1 Message Date
palerdot
ce097957aa update yarn.lock with patch file info 2023-04-17 12:37:44 +05:30
palerdot
d4731d1c4a fix(android): patch rn-fetch-blob for app sync crash 2023-04-17 11:52:07 +05:30
renovate[bot]
3669a1b5d6 Update dependency react-native-paper to v5.5.2 (#8054)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-16 23:41:05 +00:00
Laurent Cozic
b93f9aaf01 Update terminal.md 2023-04-16 13:13:06 +03:00
renovate[bot]
8679290206 Update dependency react-native-paper to v5.5.1 (#8037)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-14 22:36:08 +00:00
Joplin Bot
4acec5c6c7 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-04-14 18:18:49 +00:00
Joplin Bot
f1b03453a4 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-04-14 12:20:07 +00:00
github-actions[bot]
7972dd5556 @simonla has signed the CLA in laurent22/joplin#8042 2023-04-11 19:03:07 +00:00
Laurent Cozic
4842500f0a Tools: Increase renovate stability days 2023-04-10 13:00:07 +02:00
renovate[bot]
84c7f28ec5 Update dependency react-native-paper to v5.5.0 (#8035)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-10 12:57:53 +02:00
github-actions[bot]
f3eea43d24 @tbjers has signed the CLA in laurent22/joplin#8036 2023-04-10 02:35:07 +00:00
Joplin Bot
8babaddbcb Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-04-09 12:21:18 +00:00
Laurent Cozic
13cdaabb17 Android 2.11.2 2023-04-09 14:07:14 +02:00
renovate[bot]
a94aa21088 Update dependency slugify to v1.6.6 (#8019)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2023-04-09 12:56:05 +01:00
Henry Heino
6116bed4e3 Mobile: Resolve #8022: Editor syntax highlighting was broken (#8023) 2023-04-09 12:55:47 +01:00
Arun Kumar
fabd0b4dda Desktop, Mobile: Fixes #7940: Removed MasterKey from Sync Status report (#8026) 2023-04-09 12:54:48 +01:00
Laurent Cozic
6b72f86e7b Mobile: Security: Prevent bypassing fingerprint lock on certain devices 2023-04-09 11:29:33 +02:00
Joplin Bot
02cf546124 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-04-09 06:17:13 +00:00
renovate[bot]
eecb012d64 Update dependency @react-native-community/netinfo to v9.3.8 (#8033)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-09 03:02:24 +00:00
Laurent Cozic
04e9b40769 Android 2.11.1 2023-04-08 10:51:00 +02:00
Laurent Cozic
efdbaeb397 Mobile: Add log info for biometrics feature 2023-04-08 10:40:53 +02:00
Laurent Cozic
46425b920c Doc: Added some doc about Joplin Server items 2023-04-07 16:49:54 +02:00
Laurent Cozic
f5be43c2ac Doc: Add info about synchronisation process 2023-04-07 16:36:59 +02:00
github-actions[bot]
080541a2fe @Letty has signed the CLA in laurent22/joplin#8029 2023-04-07 10:05:21 +00:00
github-actions[bot]
7dc638edf4 @gitstart has signed the CLA in laurent22/joplin#8024 2023-04-06 21:46:34 +00:00
Laurent Cozic
3b686194d8 Tools: Pass APPLE_APP_SPECIFIC_PASSWORD to CI 2023-04-06 14:02:45 +02:00
Laurent Cozic
5c2640f88f Tools: Simplify root workspace build 2023-04-06 12:11:45 +02:00
Laurent Cozic
eca0f92dff Disable again 2023-04-06 11:46:06 +02:00
Laurent Cozic
260fa6c038 Clipper release v2.11.2 2023-04-06 11:44:55 +02:00
Laurent Cozic
8ec6bc9138 Tools: Simplify dependencies of root package 2023-04-06 11:29:59 +02:00
Laurent Cozic
93fa92369b Tools: Removing packages/tools dependency from root workspace 2023-04-06 11:02:22 +02:00
Laurent Cozic
bc6c5ab7a7 Chore: Make utils package a fixed version again (too many problems otherwise) 2023-04-06 10:02:49 +02:00
Laurent Cozic
1826625e4f lock file 2023-04-05 23:19:25 +02:00
Laurent Cozic
20b8fb2719 Missing package 2023-04-05 22:48:17 +02:00
Laurent Cozic
f813e71b29 Chore: Access utils lib with relative path 2023-04-05 22:35:47 +02:00
Laurent Cozic
02422a6e31 Chore: Access utils lib with relative path 2023-04-05 22:35:46 +02:00
renovate[bot]
69a34e87f3 Update dependency nanoid to v3.3.6 (#7973)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-05 21:16:55 +01:00
Joplin Bot
cbeaa16b61 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-04-05 18:18:02 +00:00
Joplin Bot
05917ac142 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-04-05 12:24:26 +00:00
Laurent Cozic
0c8de68b80 Desktop: Fixed issue with text disappearing within plugin-created zones when searching for text
Ref: https://github.com/joplin/plugin-abc-sheet-music/issues/5
2023-04-04 21:09:58 +02:00
Joplin Bot
44d93d52d3 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-04-04 18:30:09 +00:00
Laurent Cozic
073bec9e8c CI: Trying to fix website builder 2023-04-04 20:16:35 +02:00
Laurent Cozic
e6a8c2bea5 CI: Trying to fix website builder 2023-04-04 19:47:54 +02:00
Laurent Cozic
81c316cd2c CI: Trying to fix website builder 2023-04-04 19:24:03 +02:00
Laurent Cozic
659c851960 CI: Trying to fix website builder 2023-04-04 17:01:34 +02:00
Laurent Cozic
572701d9a0 Tools: Fix website builder 2023-04-04 12:04:42 +02:00
Laurent Cozic
66ef37bd4e Chore: Disable flaky test 2023-04-03 20:42:31 +02:00
Laurent Cozic
9ddf75604d Doc: Remove sponsor 2023-04-03 20:39:31 +02:00
Laurent Cozic
3ed7e1d7e8 Doc: Fix sponsor thumbnails 2023-04-03 20:39:31 +02:00
Laurent Cozic
b2b412105a Merge branch 'release-2.10' into dev 2023-04-03 18:30:55 +02:00
Laurent Cozic
60a3c4f65e lock file 2023-04-03 18:26:04 +02:00
Laurent Cozic
9645414c17 Desktop release v2.10.13 2023-04-03 18:10:54 +02:00
Henry Heino
af0136ef39 All: Fixes #7986: Fix OneDrive sync attempting to call method on null variable (#7987) 2023-04-03 18:09:52 +02:00
Self Not Found
b76586c4fd All: Fixes #7851: Encode the non-ASCII characters in OneDrive URI (#7868) 2023-04-03 18:09:10 +02:00
Laurent Cozic
376e4ebde0 Desktop: Fixed display of installed plugins in About box 2023-04-03 18:01:06 +02:00
renovate[bot]
1439b8787f Update dependency react-native-image-picker to v5.3.1 (#8015)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-03 11:51:02 +01:00
renovate[bot]
b8854a99be Update dependency @lezer/highlight to v1.1.4 (#8014)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-03 10:46:19 +00:00
renovate[bot]
6cf02173dc Update dependency gettext-extractor to v3.7.0 (#8012)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-03 10:56:44 +01:00
renovate[bot]
4d8a53d8c9 Update dependency react-native-image-picker to v5.3.0 (#8010)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-03 10:56:25 +01:00
renovate[bot]
7f43718e1d Update dependency react-select to v5.7.2 (#8009)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-02 07:09:26 +00:00
renovate[bot]
690ce637b1 Update dependency nodemon to v2.0.22 (#8008)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-02 03:42:02 +00:00
renovate[bot]
4d023e679e Update dependency turndown to v7.1.2 (#8006)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-01 16:46:25 +00:00
renovate[bot]
6e220a978f Update dependency jsdom to v21.1.1 (#8007)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-01 16:00:34 +02:00
renovate[bot]
39757cd90e Update dependency sass to v1.59.3 (#8005)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-01 05:46:20 +00:00
renovate[bot]
5ccbbea757 Update dependency react-native-paper to v5.4.1 (#8004)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-31 22:56:15 +00:00
Arun Kumar
309222c082 Desktop: Fixes #8000: Fixed Linux tag display issues (#8002) 2023-03-31 23:13:59 +02:00
renovate[bot]
50f5fe2c91 Update dependency sass to v1.59.2 (#8001)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-31 23:12:25 +02:00
renovate[bot]
eacae83182 Update dependency react-native-paper to v5.4.0 (#7997)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-31 23:12:05 +02:00
Laurent Cozic
403d770b1d Tools: Trying to prevent CI from running on forks 2023-03-30 22:57:58 +01:00
Laurent Cozic
a481bf1b53 Tools: Trying to prevent CI from running on forks 2023-03-30 22:55:14 +01:00
renovate[bot]
0d32570c9e Update dependency fs-extra to v11.1.1 (#7996)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-30 20:11:29 +00:00
Fejby
f017e99b02 All: Translation: Update cs_CZ.po (#7999) 2023-03-30 14:40:05 -04:00
github-actions[bot]
a89d64d435 @Fejby has signed the CLA in laurent22/joplin#7999 2023-03-30 18:21:47 +00:00
github-actions[bot]
3a27086534 @TahaNw has signed the CLA in laurent22/joplin#7998 2023-03-30 17:33:50 +00:00
Laurent Cozic
413c1e41b5 Revert "Chore: Mac binary signing tweaks for embedded plugins (#7988)"
This reverts commit cf4008951d.

Not working.

Ref: https://github.com/laurent22/joplin/issues/7934#issuecomment-1490632038
2023-03-30 18:24:25 +01:00
Henry Heino
8b879464b8 All: Fixes #7986: Fix OneDrive sync attempting to call method on null variable (#7987) 2023-03-30 17:41:29 +01:00
renovate[bot]
97c9bbc1fe Update dependency react-native-paper to v5.3.1 (#7977) 2023-03-30 17:38:18 +01:00
renovate[bot]
e5bebef7b2 Update dependency lint-staged to v13.2.0 (#7994) 2023-03-30 17:38:06 +01:00
renovate[bot]
73752c4b3f Update dependency pg to v8.10.0 (#7978) 2023-03-30 17:37:46 +01:00
Laurent Cozic
dcf7c9838d Desktop release v2.11.1 2023-03-30 17:13:20 +01:00
Laurent Cozic
f325e7694b Chore: Prepare v2.11 2023-03-30 17:13:06 +01:00
Arun Kumar
75d204c9ca Desktop: Resolves #6101: Added export graph button for Mermaid (#7958) 2023-03-30 16:58:48 +01:00
Arun Kumar
cf4008951d Chore: Mac binary signing tweaks for embedded plugins (#7988) 2023-03-30 16:57:22 +01:00
renovate[bot]
d67818d096 Update dependency react-select to v5.7.1 (#7993)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-30 14:30:20 +00:00
73 changed files with 1531 additions and 1071 deletions

View File

@@ -405,6 +405,7 @@ packages/app-mobile/components/SideMenu.js
packages/app-mobile/components/TextInput.js
packages/app-mobile/components/app-nav.js
packages/app-mobile/components/biometrics/BiometricPopup.js
packages/app-mobile/components/biometrics/biometricAuthenticate.js
packages/app-mobile/components/biometrics/sensorInfo.js
packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/getResponsiveValue.test.js

View File

@@ -180,8 +180,8 @@ cd "$ROOT_DIR/packages/app-desktop"
if [[ $GIT_TAG_NAME = v* ]]; then
echo "Step: Building and publishing desktop application..."
cd "$ROOT_DIR/packages/tools"
node bundleDefaultPlugins.js
# cd "$ROOT_DIR/packages/tools"
# node bundleDefaultPlugins.js
cd "$ROOT_DIR/packages/app-desktop"
USE_HARD_LINKS=false yarn run dist
elif [[ $IS_LINUX = 1 ]] && [[ $GIT_TAG_NAME = $SERVER_TAG_PREFIX-* ]]; then

View File

@@ -6,6 +6,7 @@ on: [push, pull_request]
jobs:
pre_job:
if: github.repository == 'laurent22/joplin'
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
@@ -16,6 +17,7 @@ jobs:
concurrent_skipping: 'same_content_newer'
BuildAndroidDebug:
if: github.repository == 'laurent22/joplin'
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: ubuntu-latest

View File

@@ -7,6 +7,7 @@ on:
jobs:
CLAAssistant:
if: github.repository == 'laurent22/joplin'
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"

View File

@@ -6,6 +6,7 @@ permissions:
issues: write
jobs:
ProcessStaleIssues:
if: github.repository == 'laurent22/joplin'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4

View File

@@ -2,6 +2,7 @@ name: Joplin Continuous Integration
on: [push, pull_request]
jobs:
pre_job:
if: github.repository == 'laurent22/joplin'
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
@@ -14,7 +15,7 @@ jobs:
Main:
needs: pre_job
# We always process server or desktop release tags, because they also publish the release
if: needs.pre_job.outputs.should_skip != 'true' || startsWith(github.ref, 'refs/tags/server-v') || startsWith(github.ref, 'refs/tags/v')
if: github.repository == 'laurent22/joplin' && (needs.pre_job.outputs.should_skip != 'true' || startsWith(github.ref, 'refs/tags/server-v') || startsWith(github.ref, 'refs/tags/v'))
runs-on: ${{ matrix.os }}
strategy:
matrix:
@@ -92,6 +93,7 @@ jobs:
APPLE_ASC_PROVIDER: ${{ secrets.APPLE_ASC_PROVIDER }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.APPLE_CSC_LINK }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
@@ -129,7 +131,7 @@ jobs:
ServerDockerImage:
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
if: github.repository == 'laurent22/joplin' && needs.pre_job.outputs.should_skip != 'true'
runs-on: ${{ matrix.os }}
strategy:
matrix:

1
.gitignore vendored
View File

@@ -392,6 +392,7 @@ packages/app-mobile/components/SideMenu.js
packages/app-mobile/components/TextInput.js
packages/app-mobile/components/app-nav.js
packages/app-mobile/components/biometrics/BiometricPopup.js
packages/app-mobile/components/biometrics/biometricAuthenticate.js
packages/app-mobile/components/biometrics/sensorInfo.js
packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/getResponsiveValue.test.js

View File

@@ -0,0 +1,30 @@
diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
index a8abd71833879201e3438b2fa51d712a311c4551..ffe9c2c6dfa5c703ba76b65d94d5dd6784102c19 100644
--- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
+++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
@@ -591,7 +591,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
// ignored.printStackTrace();
}
- RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
+ RNFetchBlobFileResp rnFetchBlobFileResp = new RNFetchBlobFileResp(responseBody);
if(rnFetchBlobFileResp != null && !rnFetchBlobFileResp.isDownloadComplete()){
callback.invoke("Download interrupted.", null);
diff --git a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
index 2470eef612308c15a89dfea5a1f16937469be29f..965f8becc195965907699182c764ec9e51811450 100644
--- a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
+++ b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
@@ -35,6 +35,12 @@ public class RNFetchBlobFileResp extends ResponseBody {
FileOutputStream ofStream;
boolean isEndMarkerReceived;
+ // ref: https://github.com/joltup/rn-fetch-blob/issues/490#issuecomment-990899440
+ public RNFetchBlobFileResp(ResponseBody body) {
+ super();
+ this.originalBody = body;
+ }
+
public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
super();
this.rctContext = ctx;

View File

@@ -64,7 +64,7 @@ A community maintained list of these distributions can be found here: [Unofficia
# Sponsors
<!-- SPONSORS-ORG -->
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://usrigging.com/"><img title="U.S. Ringing Supply" width="256" src="https://joplinapp.org/images/sponsors/RingingSupply.svg"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&amp;mtm_kwd=joplinapp&amp;mtm_source=joplinapp-github&amp;mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a>
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&amp;mtm_kwd=joplinapp&amp;mtm_source=joplinapp-webseite&amp;mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a>
<!-- SPONSORS-ORG -->
* * *
@@ -126,6 +126,7 @@ A community maintained list of these distributions can be found here: [Unofficia
- [Writing a technical spec](https://github.com/laurent22/joplin/blob/dev/readme/technical_spec.md)
- [Desktop application styling](https://github.com/laurent22/joplin/blob/dev/readme/spec/desktop_styling.md)
- [Note History spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/history.md)
- [Synchronisation spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync.md)
- [Sync Lock spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync_lock.md)
- [Synchronous Scroll spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync_scroll.md)
- [Plugin Architecture spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/plugins.md)

View File

@@ -1,26 +1,52 @@
const gulp = require('gulp');
const utils = require('./packages/tools/gulp/utils');
const execa = require('execa');
const { stdout } = require('process');
const execCommand = async (executableName, args, options = null) => {
options = {
showInput: true,
showStdout: true,
showStderr: true,
quiet: false,
...options,
};
if (options.quiet) {
options.showInput = false;
options.showStdout = false;
options.showStderr = false;
}
if (options.showInput) {
stdout.write(`> ${executableName} ${args.join(' ')}\n`);
}
const promise = execa(executableName, args);
if (options.showStdout && promise.stdout) promise.stdout.pipe(process.stdout);
if (options.showStderr && promise.stderr) promise.stderr.pipe(process.stderr);
const result = await promise;
return result.stdout.trim();
};
const tasks = {
updateIgnoredTypeScriptBuild: require('./packages/tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
buildCommandIndex: require('./packages/tools/gulp/tasks/buildCommandIndex'),
completePublishAll: {
fn: async () => {
await utils.execCommandVerbose('git', ['add', '-A']);
await utils.execCommandVerbose('git', ['commit', '-m', 'Releasing sub-packages']);
await execCommand('git', ['add', '-A']);
await execCommand('git', ['commit', '-m', 'Releasing sub-packages']);
// Lerna does some unnecessary auth check that doesn't work with
// automation tokens, thus the --no-verify-access. Automation token
// is still used for access when publishing even with this flag
// (publishing would fail otherwise).
// https://github.com/lerna/lerna/issues/2788
await utils.execCommandVerbose('lerna', ['publish', 'from-package', '-y', '--no-verify-access']);
await execCommand('lerna', ['publish', 'from-package', '-y', '--no-verify-access']);
await utils.execCommandVerbose('yarn', ['install']);
await utils.execCommandVerbose('git', ['add', '-A']);
await utils.execCommandVerbose('git', ['commit', '-m', 'Lock file']);
await execCommand('yarn', ['install']);
await execCommand('git', ['add', '-A']);
await execCommand('git', ['commit', '-m', 'Lock file']);
await utils.execCommandVerbose('git', ['push']);
await execCommand('git', ['push']);
},
},
build: {
@@ -33,12 +59,14 @@ const tasks = {
// faster, especially when having to rebuild after adding a
// dependency.
if (process.env.BUILD_SEQUENCIAL === '1') {
await utils.execCommandVerbose('yarn', ['run', 'buildSequential']);
await execCommand('yarn', ['run', 'buildSequential']);
} else {
await utils.execCommandVerbose('yarn', ['run', 'buildParallel']);
await execCommand('yarn', ['run', 'buildParallel']);
}
},
},
};
utils.registerGulpTasks(gulp, tasks);
for (const taskName in tasks) {
gulp.task(taskName, tasks[taskName].fn);
}

View File

@@ -15,7 +15,7 @@
"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": "gulp buildCommandIndex",
"buildCommandIndex": "node packages/tools/gulp/tasks/buildCommandIndexRun.js",
"buildPluginDoc": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme './Assets/PluginDocTheme/' --readme './Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out ../joplin-website/docs/api/references/plugin_api packages/lib/services/plugins/api/",
"updateMarkdownDoc": "node ./packages/tools/updateMarkdownDoc",
"updateNews": "node ./packages/tools/website/updateNews",
@@ -53,7 +53,7 @@
"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": "gulp updateIgnoredTypeScriptBuild",
"updateIgnored": "node packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js",
"updatePluginTypes": "./packages/generator-joplin/updateTypes.sh",
"watch": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 999 run watch",
"watchWebsite": "nodemon --verbose --watch Assets/WebsiteAssets --watch packages/tools/website --watch packages/tools/website/utils --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\""
@@ -64,6 +64,7 @@
}
},
"devDependencies": {
"@joplin/utils": "~2.11",
"@seiyab/eslint-plugin-react-hooks": "4.5.1-beta.0",
"@typescript-eslint/eslint-plugin": "5.48.2",
"@typescript-eslint/parser": "5.48.2",
@@ -74,12 +75,13 @@
"eslint-plugin-jest": "27.2.1",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.32.0",
"fs-extra": "11.1.0",
"execa": "5.1.1",
"fs-extra": "11.1.1",
"glob": "8.1.0",
"gulp": "4.0.2",
"husky": "3.1.0",
"lerna": "3.22.1",
"lint-staged": "13.1.4",
"lint-staged": "13.2.0",
"madge": "6.0.0",
"npm-package-json-lint": "6.4.0",
"typedoc": "0.17.8",
@@ -89,10 +91,11 @@
"@types/fs-extra": "9.0.13",
"http-server": "14.1.1",
"node-gyp": "9.3.1",
"nodemon": "2.0.21"
"nodemon": "2.0.22"
},
"packageManager": "yarn@3.3.1",
"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-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch",
"rn-fetch-blob@0.12.0": "patch:rn-fetch-blob@npm%3A0.12.0#./.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch"
}
}

View File

@@ -35,19 +35,19 @@
],
"owner": "Laurent Cozic"
},
"version": "2.10.3",
"version": "2.11.0",
"bin": "./main.js",
"engines": {
"node": ">=10.0.0"
},
"dependencies": {
"@joplin/lib": "~2.10",
"@joplin/renderer": "~2.10",
"@joplin/utils": "~2.10",
"@joplin/lib": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/utils": "~2.11",
"aws-sdk": "2.1290.0",
"chalk": "4.1.2",
"compare-version": "0.1.2",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"html-entities": "1.4.0",
"image-type": "3.1.0",
"keytar": "7.9.0",
@@ -70,7 +70,7 @@
"yargs-parser": "21.1.1"
},
"devDependencies": {
"@joplin/tools": "~2.10",
"@joplin/tools": "~2.11",
"@types/fs-extra": "9.0.13",
"@types/jest": "29.2.6",
"@types/node": "18.11.18",

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Joplin Web Clipper [DEV]",
"version": "2.10.0",
"version": "2.11.2",
"description": "Capture and save web pages and screenshots from your browser to Joplin.",
"homepage_url": "https://joplinapp.org",
"content_security_policy": "script-src 'self'; object-src 'self'",

View File

@@ -126,4 +126,4 @@
"react-app"
]
}
}
}

View File

@@ -8,7 +8,5 @@
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

View File

@@ -21,7 +21,7 @@ import checkForUpdates from '../checkForUpdates';
const { connect } = require('react-redux');
import { reg } from '@joplin/lib/registry';
import { ProfileConfig } from '@joplin/lib/services/profileConfig/types';
import PluginService from '@joplin/lib/services/plugins/PluginService';
import PluginService, { PluginSettings } from '@joplin/lib/services/plugins/PluginService';
const packageInfo = require('../packageInfo.js');
const { clipboard } = require('electron');
const Menu = bridge().Menu;
@@ -128,6 +128,7 @@ interface Props {
customCss: string;
locale: string;
profileConfig: ProfileConfig;
pluginSettings: PluginSettings;
}
const commandNames: string[] = menuCommandNames();
@@ -487,7 +488,7 @@ function useMenu(props: Props) {
}
function _showAbout() {
const v = versionInfo(packageInfo, PluginService.instance().plugins);
const v = versionInfo(packageInfo, PluginService.instance().enabledPlugins(props.pluginSettings));
const copyToClipboard = bridge().showMessageBox(v.message, {
icon: `${bridge().electronApp().buildDir()}/icons/128x128.png`,
@@ -930,6 +931,7 @@ function useMenu(props: Props) {
props['spellChecker.languages'],
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
props['spellChecker.enabled'],
props.pluginSettings,
props.customCss,
props.locale,
props.profileConfig,
@@ -985,6 +987,7 @@ const mapStateToProps = (state: AppState) => {
['folders.sortOrder.field']: state.settings['folders.sortOrder.field'],
['notes.sortOrder.reverse']: state.settings['notes.sortOrder.reverse'],
['folders.sortOrder.reverse']: state.settings['folders.sortOrder.reverse'],
pluginSettings: state.settings['plugins.states'],
showNoteCounts: state.settings.showNoteCounts,
uncompletedTodosOnTop: state.settings.uncompletedTodosOnTop,
showCompletedTodos: state.settings.showCompletedTodos,

View File

@@ -3,6 +3,7 @@ import { useCallback, useMemo } from 'react';
import { ResourceInfos } from './types';
import markupLanguageUtils from '../../../utils/markupLanguageUtils';
import Setting from '@joplin/lib/models/Setting';
import shim from '@joplin/lib/shim';
const { themeStyle } = require('@joplin/lib/theme');
import Note from '@joplin/lib/models/Note';
@@ -23,6 +24,7 @@ export interface MarkupToHtmlOptions {
useCustomPdfViewer?: boolean;
noteId?: string;
vendorDir?: string;
platformName?: string;
}
export default function useMarkupToHtml(deps: HookDependencies) {
@@ -40,6 +42,7 @@ export default function useMarkupToHtml(deps: HookDependencies) {
options = {
replaceResourceInternalToExternalLinks: false,
resourceInfos: {},
platformName: shim.platformName(),
...options,
};

View File

@@ -48,6 +48,15 @@ const StyledFoldersHolder = styled.div`
}}
}
`;
const TagsHolder = styled.div`
// linux bug: https://github.com/laurent22/joplin/issues/8000
// solution ref: https://github.com/laurent22/joplin/issues/7506#issuecomment-1447101057
& a.list-item {
${shim.isLinux() && {
opacity: 1,
}}
}
`;
interface Props {
themeId: number;
@@ -738,9 +747,9 @@ const SidebarComponent = (props: Props) => {
tagItemsOrder_.current = result.order;
items.push(
<div className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
<TagsHolder className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
{tagItems}
</div>
</TagsHolder>
);
}

View File

@@ -56,6 +56,19 @@ if (typeof module !== 'undefined') {
const markJsUtils = {};
const isInsideContainer = (node, tagName) => {
if (!node) return false;
tagName = tagName.toLowerCase();
while (node) {
if (node.tagName && node.tagName.toLowerCase() === tagName) return true;
node = node.parentNode;
}
return false;
};
markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
if (typeof keyword === 'string') {
keyword = {
@@ -71,12 +84,13 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
if (isBasicSearch) accuracy = 'partially';
if (keyword.type === 'regex') {
accuracy = 'complementary';
// Remove the trailing wildcard and "accuracy = complementary" will take care of
// highlighting the relevant keywords.
// Remove the trailing wildcard and "accuracy = complementary" will take
// care of highlighting the relevant keywords.
// Known bug: it will also highlight word that contain the term as a suffix for example for "ent*", it will highlight "present"
// which is incorrect (it should only highlight what starts with "ent") but for now will do. Mark.js doesn't have an option
// to tweak this behaviour.
// Known bug: it will also highlight word that contain the term as a
// suffix for example for "ent*", it will highlight "present" which is
// incorrect (it should only highlight what starts with "ent") but for
// now will do. Mark.js doesn't have an option to tweak this behaviour.
value = keyword.value.substr(0, keyword.value.length - 1);
}
@@ -86,6 +100,18 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
{},
{
accuracy: accuracy,
filter: (node, _term, _totalCounter, _counter) => {
// We exclude SVG because it creates a "<mark>" tag inside
// the document, which is not a valid SVG tag. As a result
// the content within that tag disappears.
//
// mark.js has an "exclude" parameter, but it doesn't work
// so we use "filter" instead.
//
// https://github.com/joplin/plugin-abc-sheet-music
if (isInsideContainer(node, 'SVG')) return false;
return true;
},
},
extraOptions
)

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "2.10.12",
"version": "2.11.1",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,
@@ -79,9 +79,7 @@
"icon": "../../Assets/macOs.icns",
"target": "dmg",
"hardenedRuntime": true,
"gatekeeperAssess": false,
"entitlements": "./build-mac/entitlements.mac.inherit.plist",
"entitlementsInherit": "./build-mac/entitlements.mac.inherit.plist",
"extendInfo": {
"CFBundleURLTypes": [
{
@@ -109,7 +107,7 @@
},
"homepage": "https://github.com/laurent22/joplin#readme",
"devDependencies": {
"@joplin/tools": "~2.10",
"@joplin/tools": "~2.11",
"@testing-library/react-hooks": "8.0.1",
"@types/jest": "29.2.6",
"@types/node": "18.11.18",
@@ -138,9 +136,9 @@
"@electron/remote": "2.0.9",
"@fortawesome/fontawesome-free": "5.15.4",
"@joeattardi/emoji-button": "4.6.4",
"@joplin/lib": "~2.10",
"@joplin/pdf-viewer": "~2.10",
"@joplin/renderer": "~2.10",
"@joplin/lib": "~2.11",
"@joplin/pdf-viewer": "~2.11",
"@joplin/renderer": "~2.11",
"async-mutex": "0.4.0",
"codemirror": "5.65.9",
"color": "3.2.1",
@@ -149,7 +147,7 @@
"debounce": "1.2.1",
"electron-window-state": "5.0.3",
"formatcoords": "1.1.3",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"highlight.js": "11.7.0",
"immer": "7.0.15",
"keytar": "7.9.0",
@@ -165,7 +163,7 @@
"react-datetime": "3.2.0",
"react-dom": "18.2.0",
"react-redux": "8.0.5",
"react-select": "5.7.0",
"react-select": "5.7.2",
"react-toggle-button": "2.2.0",
"react-tooltip": "4.5.1",
"redux": "4.2.1",

View File

@@ -150,8 +150,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097685
versionName "2.10.9"
versionCode 2097687
versionName "2.11.2"
// ndk {
// abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
// }

View File

@@ -2,6 +2,7 @@
* @jest-environment jsdom
*/
import { EditorSettings } from '../types';
import { initCodeMirror } from './CodeMirror';
import { themeStyle } from '@joplin/lib/theme';
@@ -9,6 +10,8 @@ import Setting from '@joplin/lib/models/Setting';
import { forceParsing } from '@codemirror/language';
import loadLangauges from './testUtil/loadLanguages';
import { expect, describe, it } from '@jest/globals';
const createEditorSettings = (themeId: number) => {
const themeData = themeStyle(themeId);
@@ -23,6 +26,14 @@ const createEditorSettings = (themeId: number) => {
};
describe('CodeMirror', () => {
// This checks for a regression -- occasionally, when updating packages,
// syntax highlighting in the CodeMirror editor stops working. This is usually
// fixed by
// 1. removing all `@codemirror/` and `@lezer/` dependencies from yarn.lock,
// 2. upgrading all CodeMirror packages to the latest versions in package.json, and
// 3. re-running `yarn install`.
//
// See https://github.com/laurent22/joplin/issues/7253
it('should give headings a different style', async () => {
const headerLineText = '# Testing...';
const initialText = `${headerLineText}\nThis is a test.`;

View File

@@ -2,9 +2,12 @@ const React = require('react');
import Setting from '@joplin/lib/models/Setting';
import { useEffect, useMemo, useState } from 'react';
import { View, Dimensions, Alert, Button } from 'react-native';
import FingerprintScanner from 'react-native-fingerprint-scanner';
import { SensorInfo } from './sensorInfo';
import { _ } from '@joplin/lib/locale';
import Logger from '@joplin/lib/Logger';
import biometricAuthenticate from './biometricAuthenticate';
const logger = Logger.create('BiometricPopup');
interface Props {
themeId: number;
@@ -18,23 +21,31 @@ export default (props: Props) => {
// doesn't work properly, we disable it. We only want the user to enable the
// feature after they've read the description in the config screen.
const [initialPromptDone, setInitialPromptDone] = useState(true); // useState(Setting.value('security.biometricsInitialPromptDone'));
const [display, setDisplay] = useState(!!props.sensorInfo.supportedSensors && (props.sensorInfo.enabled || !initialPromptDone));
const [display, setDisplay] = useState(props.sensorInfo.enabled || !initialPromptDone);
const [tryBiometricsCheck, setTryBiometricsCheck] = useState(initialPromptDone);
logger.info('Render start');
logger.info('initialPromptDone', initialPromptDone);
logger.info('display', display);
logger.info('tryBiometricsCheck', tryBiometricsCheck);
logger.info('props.sensorInfo', props.sensorInfo);
useEffect(() => {
if (!display || !tryBiometricsCheck) return;
const biometricsCheck = async () => {
logger.info('biometricsCheck: start');
try {
await FingerprintScanner.authenticate({ description: _('Verify your identity') });
setTryBiometricsCheck(false);
await biometricAuthenticate();
setDisplay(false);
} catch (error) {
Alert.alert(_('Could not verify your identify'), error.message);
setTryBiometricsCheck(false);
} finally {
FingerprintScanner.release();
Alert.alert(error.message);
}
setTryBiometricsCheck(false);
logger.info('biometricsCheck: end');
};
void biometricsCheck();
@@ -45,6 +56,9 @@ export default (props: Props) => {
if (!display) return;
const complete = (enableBiometrics: boolean) => {
logger.info('complete: start');
logger.info('complete: enableBiometrics:', enableBiometrics);
setInitialPromptDone(true);
Setting.setValue('security.biometricsInitialPromptDone', true);
Setting.setValue('security.biometricsEnabled', enableBiometrics);
@@ -59,6 +73,8 @@ export default (props: Props) => {
type: 'BIOMETRICS_DONE_SET',
value: true,
});
logger.info('complete: end');
};
Alert.alert(
@@ -77,7 +93,7 @@ export default (props: Props) => {
},
]
);
}, [initialPromptDone, props.sensorInfo.supportedSensors, display, props.dispatch]);
}, [initialPromptDone, display, props.dispatch]);
const windowSize = useMemo(() => {
return {
@@ -87,12 +103,18 @@ export default (props: Props) => {
}, []);
useEffect(() => {
logger.info('effect 1: start');
if (!display) {
logger.info('effect 1: display', display);
props.dispatch({
type: 'BIOMETRICS_DONE_SET',
value: true,
});
}
logger.info('effect 1: end');
}, [display, props.dispatch]);
const renderTryAgainButton = () => {

View File

@@ -0,0 +1,28 @@
import Logger from '@joplin/lib/Logger';
import FingerprintScanner, { Errors } from 'react-native-fingerprint-scanner';
import { _ } from '@joplin/lib/locale';
const logger = Logger.create('biometricAuthenticate');
export default async () => {
try {
logger.info('Authenticate...');
await FingerprintScanner.authenticate({ description: _('Verify your identity') });
logger.info('Authenticate done');
} catch (error) {
const errorName = (error as Errors).name;
let errorMessage = error.message;
if (errorName === 'FingerprintScannerNotEnrolled' || errorName === 'FingerprintScannerNotAvailable') {
errorMessage = _('Biometric unlock is not setup on the device. Please set it up in order to unlock Joplin. If the device is on lockout, consider switching it off and on to reset biometrics scanning.');
}
error.message = _('Could not verify your identify: %s', errorMessage);
logger.warn(error);
throw error;
} finally {
FingerprintScanner.release();
}
};

View File

@@ -1,5 +1,7 @@
import Logger from '@joplin/lib/Logger';
import Setting from '@joplin/lib/models/Setting';
import FingerprintScanner from 'react-native-fingerprint-scanner';
const logger = Logger.create('sensorInfo');
export interface SensorInfo {
enabled: boolean;
@@ -12,6 +14,9 @@ export default async (): Promise<SensorInfo> => {
// FingerprintScanner scanner calls, since it seems they can fail and freeze
// the app.
logger.info('Start');
logger.info('security.biometricsEnabled', Setting.value('security.biometricsEnabled'));
if (!Setting.value('security.biometricsEnabled')) {
return {
enabled: false,
@@ -24,7 +29,21 @@ export default async (): Promise<SensorInfo> => {
let supportedSensors = '';
try {
logger.info('Getting isSensorAvailable...');
// Note: If `isSensorAvailable()` doesn't return anything, it seems we
// could assume that biometrics are not setup on the device, and thus we
// can unlock the app. However that's not always correct - on some
// devices (eg Galaxy S22), `isSensorAvailable()` will return nothing if
// the device is on lockout - i.e. if the user gave the wrong
// fingerprint multiple times.
//
// So we definitely can't unlock the app in that case, and it means
// `isSensorAvailable()` is pretty much useless. Instead we ask for
// fingerprint when the user turns on the feature and at that point we
// know if the device supports biometrics or not.
const result = await FingerprintScanner.isSensorAvailable();
logger.info('isSensorAvailable result', result);
supportedSensors = result;
if (result) {
@@ -34,7 +53,7 @@ export default async (): Promise<SensorInfo> => {
}
}
} catch (error) {
console.warn('Could not check for biometrics sensor:', error);
logger.warn('Could not check for biometrics sensor:', error);
Setting.setValue('security.biometricsSupportedSensors', '');
}

View File

@@ -23,6 +23,7 @@ const { themeStyle } = require('../global-style.js');
const shared = require('@joplin/lib/components/shared/config-shared.js');
import SyncTargetRegistry from '@joplin/lib/SyncTargetRegistry';
import { openDocumentTree } from '@joplin/react-native-saf-x';
import biometricAuthenticate from '../biometrics/biometricAuthenticate';
class ConfigScreenComponent extends BaseScreenComponent {
public static navigationOptions(): any {
@@ -463,7 +464,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
<Text key="label" style={this.styles().switchSettingText}>
{label}
</Text>
<Switch key="control" style={this.styles().switchSettingControl} trackColor={{ false: theme.dividerColor }} value={value} onValueChange={(value: any) => updateSettingValue(key, value)} />
<Switch key="control" style={this.styles().switchSettingControl} trackColor={{ false: theme.dividerColor }} value={value} onValueChange={(value: any) => void updateSettingValue(key, value)} />
</View>
{descriptionComp}
</View>
@@ -474,13 +475,39 @@ class ConfigScreenComponent extends BaseScreenComponent {
return !hasDescription ? this.styles().settingContainer : this.styles().settingContainerNoBottomBorder;
}
private async handleSetting(key: string, value: any): Promise<boolean> {
// When the user tries to enable biometrics unlock, we ask for the
// fingerprint or Face ID, and if it's correct we save immediately. If
// it's not, we don't turn on the setting.
if (key === 'security.biometricsEnabled' && !!value) {
try {
await biometricAuthenticate();
shared.updateSettingValue(this, key, value);
await this.saveButton_press();
} catch (error) {
shared.updateSettingValue(this, key, false);
Alert.alert(error.message);
}
return true;
}
if (key === 'security.biometricsEnabled' && !value) {
shared.updateSettingValue(this, key, value);
await this.saveButton_press();
return true;
}
return false;
}
public settingToComponent(key: string, value: any) {
const themeId = this.props.themeId;
const theme = themeStyle(themeId);
const output: any = null;
const updateSettingValue = (key: string, value: any) => {
return shared.updateSettingValue(this, key, value);
const updateSettingValue = async (key: string, value: any) => {
const handled = await this.handleSetting(key, value);
if (!handled) shared.updateSettingValue(this, key, value);
};
const md = Setting.settingMetadata(key);
@@ -517,7 +544,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
fontSize: theme.fontSize,
}}
onValueChange={(itemValue: string) => {
updateSettingValue(key, itemValue);
void updateSettingValue(key, itemValue);
}}
/>
</View>
@@ -553,7 +580,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
</Text>
<View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', flex: 1 }}>
<Text style={this.styles().sliderUnits}>{unitLabel}</Text>
<Slider key="control" style={{ flex: 1 }} step={md.step} minimumValue={minimum} maximumValue={maximum} value={value} onValueChange={value => updateSettingValue(key, value)} />
<Slider key="control" style={{ flex: 1 }} step={md.step} minimumValue={minimum} maximumValue={maximum} value={value} onValueChange={value => void updateSettingValue(key, value)} />
</View>
</View>
);
@@ -577,7 +604,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
<Text key="label" style={this.styles().settingText}>
{md.label()}
</Text>
<TextInput autoCorrect={false} autoComplete="off" selectionColor={theme.textSelectionColor} keyboardAppearance={theme.keyboardAppearance} autoCapitalize="none" key="control" style={this.styles().settingControl} value={value} onChangeText={(value: any) => updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
<TextInput autoCorrect={false} autoComplete="off" selectionColor={theme.textSelectionColor} keyboardAppearance={theme.keyboardAppearance} autoCapitalize="none" key="control" style={this.styles().settingControl} value={value} onChangeText={(value: any) => void updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
</View>
);
} else {

View File

@@ -523,7 +523,7 @@
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 12.10.5;
MARKETING_VERSION = 12.11.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -551,7 +551,7 @@
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 12.10.5;
MARKETING_VERSION = 12.11.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -705,7 +705,7 @@
INFOPLIST_FILE = ShareExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 12.10.5;
MARKETING_VERSION = 12.11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
@@ -736,7 +736,7 @@
INFOPLIST_FILE = ShareExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 12.10.5;
MARKETING_VERSION = 12.11.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -306,7 +306,7 @@ PODS:
- React-jsinspector (0.70.6)
- React-logger (0.70.6):
- glog
- react-native-alarm-notification (2.10.0):
- react-native-alarm-notification (2.11.0):
- React
- react-native-camera (4.2.1):
- React-Core
@@ -316,7 +316,7 @@ PODS:
- React-Core
- react-native-camera/RN (4.2.1):
- React-Core
- react-native-document-picker (8.1.3):
- react-native-document-picker (8.1.4):
- React-Core
- react-native-fingerprint-scanner (6.0.0):
- React
@@ -324,15 +324,15 @@ PODS:
- React-Core
- react-native-get-random-values (1.8.0):
- React-Core
- react-native-image-picker (5.1.0):
- react-native-image-picker (5.3.1):
- React-Core
- react-native-image-resizer (1.4.5):
- React-Core
- react-native-netinfo (9.3.7):
- react-native-netinfo (9.3.8):
- React-Core
- react-native-rsa-native (2.0.5):
- React
- react-native-saf-x (2.10.2):
- react-native-saf-x (2.11.0):
- React-Core
- react-native-safe-area-context (4.5.0):
- RCT-Folly
@@ -714,17 +714,17 @@ SPEC CHECKSUMS:
React-jsiexecutor: b4a65947391c658450151275aa406f2b8263178f
React-jsinspector: 60769e5a0a6d4b32294a2456077f59d0266f9a8b
React-logger: 1623c216abaa88974afce404dc8f479406bbc3a0
react-native-alarm-notification: 0f58eaa37a4188480536fd7ab62db9b1dfba392f
react-native-alarm-notification: 26527410a6162d07a9dc57f4bbc62e94ff48e65d
react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f
react-native-document-picker: 958e2bc82e128be69055be261aeac8d872c8d34c
react-native-document-picker: a9bd26996d1b2e4f412dd186041714c79af381d0
react-native-fingerprint-scanner: ac6656f18c8e45a7459302b84da41a44ad96dbbe
react-native-geolocation: 69f4fd37650b8e7fee91816d395e62dd16f5ab8d
react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a
react-native-image-picker: c33d4e79f0a14a2b66e5065e14946ae63749660b
react-native-image-picker: ec9b713e248760bfa0f879f0715391de4651a7cb
react-native-image-resizer: d9fb629a867335bdc13230ac2a58702bb8c8828f
react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983
react-native-netinfo: fbc23bc2fe217155d85f2f7e0644b1654df8029b
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
react-native-saf-x: db5a33862e7aec0f9f2d4cccfe7264b09b234e2e
react-native-saf-x: 9bd5238d3b43d76bbec64aa82c173ac20a4bce9f
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d
react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261

View File

@@ -2,7 +2,7 @@
"name": "@joplin/app-mobile",
"description": "Joplin for Mobile",
"license": "AGPL-3.0-or-later",
"version": "2.10.0",
"version": "2.11.0",
"private": true,
"scripts": {
"start": "react-native start --reset-cache",
@@ -18,14 +18,14 @@
"postinstall": "jetify && yarn run build"
},
"dependencies": {
"@joplin/lib": "~2.10",
"@joplin/react-native-alarm-notification": "~2.10",
"@joplin/react-native-saf-x": "~2.10",
"@joplin/renderer": "~2.10",
"@joplin/lib": "~2.11",
"@joplin/react-native-alarm-notification": "~2.11",
"@joplin/react-native-saf-x": "~2.11",
"@joplin/renderer": "~2.11",
"@react-native-community/clipboard": "1.5.1",
"@react-native-community/datetimepicker": "6.7.5",
"@react-native-community/geolocation": "2.1.0",
"@react-native-community/netinfo": "9.3.7",
"@react-native-community/netinfo": "9.3.8",
"@react-native-community/push-notification-ios": "1.10.1",
"@react-native-community/slider": "4.4.2",
"assert-browserify": "2.0.0",
@@ -51,10 +51,10 @@
"react-native-fingerprint-scanner": "6.0.0",
"react-native-fs": "2.20.0",
"react-native-get-random-values": "1.8.0",
"react-native-image-picker": "5.1.0",
"react-native-image-picker": "5.3.1",
"react-native-image-resizer": "1.4.5",
"react-native-modal-datetime-picker": "14.0.1",
"react-native-paper": "5.2.0",
"react-native-paper": "5.5.2",
"react-native-popup-menu": "0.16.1",
"react-native-quick-actions": "0.3.13",
"react-native-rsa-native": "2.0.5",
@@ -79,36 +79,36 @@
"devDependencies": {
"@babel/core": "7.16.0",
"@babel/runtime": "7.16.3",
"@codemirror/commands": "6.1.2",
"@codemirror/commands": "6.2.2",
"@codemirror/lang-cpp": "6.0.2",
"@codemirror/lang-html": "6.4.0",
"@codemirror/lang-html": "6.4.3",
"@codemirror/lang-java": "6.0.1",
"@codemirror/lang-javascript": "6.1.1",
"@codemirror/lang-markdown": "6.0.5",
"@codemirror/lang-javascript": "6.1.5",
"@codemirror/lang-markdown": "6.1.0",
"@codemirror/lang-php": "6.0.1",
"@codemirror/lang-rust": "6.0.1",
"@codemirror/language": "6.3.2",
"@codemirror/legacy-modes": "6.3.1",
"@codemirror/search": "6.2.3",
"@codemirror/state": "6.1.4",
"@codemirror/view": "6.7.1",
"@joplin/tools": "~2.10",
"@lezer/highlight": "1.1.3",
"@codemirror/language": "6.6.0",
"@codemirror/legacy-modes": "6.3.2",
"@codemirror/search": "6.3.0",
"@codemirror/state": "6.2.0",
"@codemirror/view": "6.9.3",
"@joplin/tools": "~2.11",
"@lezer/highlight": "1.1.4",
"@types/fs-extra": "9.0.13",
"@types/jest": "29.2.6",
"@types/react-native": "0.70.6",
"@types/react-redux": "7.1.25",
"babel-plugin-module-resolver": "4.1.0",
"execa": "4.1.0",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"gulp": "4.0.2",
"jest": "29.4.3",
"jest-environment-jsdom": "29.4.3",
"jetifier": "2.0.0",
"jsdom": "21.0.0",
"jsdom": "21.1.1",
"md5-file": "5.0.0",
"metro-react-native-babel-preset": "0.72.3",
"nodemon": "2.0.21",
"nodemon": "2.0.22",
"ts-jest": "29.0.5",
"ts-loader": "9.4.2",
"ts-node": "10.9.1",

View File

@@ -501,7 +501,7 @@ async function initialize(dispatch: Function) {
if (Setting.value('env') === 'prod') {
await db.open({ name: getDatabaseName(currentProfile, isSubProfile) });
} else {
await db.open({ name: getDatabaseName(currentProfile, isSubProfile, '-1') });
await db.open({ name: getDatabaseName(currentProfile, isSubProfile, '-3') });
// await db.clearForTesting();
}
@@ -984,6 +984,10 @@ class AppComponent extends React.Component {
const biometricIsEnabled = !!this.state.sensorInfo && this.state.sensorInfo.enabled;
const shouldShowMainContent = !biometricIsEnabled || this.props.biometricsDone;
logger.info('root.biometrics: biometricIsEnabled', biometricIsEnabled);
logger.info('root.biometrics: shouldShowMainContent', shouldShowMainContent);
logger.info('root.biometrics: this.state.sensorInfo', this.state.sensorInfo);
const mainContent = (
<View style={{ flex: 1, backgroundColor: theme.backgroundColor }}>
<SideMenu

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"id": "<%= pluginId %>",
"app_min_version": "2.10",
"app_min_version": "2.11",
"version": "1.0.0",
"name": "<%= pluginName %>",
"description": "<%= pluginDescription %>",

View File

@@ -1,6 +1,6 @@
{
"name": "generator-joplin",
"version": "2.10.0",
"version": "2.11.0",
"description": "Scaffolds out a new Joplin plugin",
"homepage": "https://github.com/laurent22/joplin/tree/dev/packages/generator-joplin",
"author": {
@@ -24,7 +24,7 @@
},
"dependencies": {
"chalk": "2.4.2",
"slugify": "1.6.5",
"slugify": "1.6.6",
"yeoman-generator": "5.8.0",
"yosay": "2.0.2"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/htmlpack",
"version": "2.10.2",
"version": "2.11.0",
"description": "Pack an HTML file and all its linked resources into a single HTML file",
"main": "dist/index.js",
"types": "src/index.ts",
@@ -17,7 +17,7 @@
"@joplin/fork-htmlparser2": "^4.1.43",
"css": "3.0.0",
"datauri": "4.1.0",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"html-entities": "1.4.0"
},
"devDependencies": {

View File

@@ -96,12 +96,14 @@ export default class SyncTargetOneDrive extends BaseSyncTarget {
let context = Setting.value(`sync.${this.syncTargetId()}.context`);
context = context === '' ? null : JSON.parse(context);
let accountProperties = context ? context.accountProperties : null;
const api = this.api();
if (!accountProperties) {
accountProperties = await this.api_.execAccountPropertiesRequest();
accountProperties = await api.execAccountPropertiesRequest();
context ? context.accountProperties = accountProperties : context = { accountProperties: accountProperties };
Setting.setValue(`sync.${this.syncTargetId()}.context`, JSON.stringify(context));
}
this.api_.setAccountProperties(accountProperties);
api.setAccountProperties(accountProperties);
const appDir = await this.api().appDirectory();
// the appDir might contain non-ASCII characters
// /[^\u0021-\u00ff]/ is used in Node.js to detect the unescaped characters.

View File

@@ -1,5 +1,18 @@
const markJsUtils = {};
const isInsideContainer = (node, tagName) => {
if (!node) return false;
tagName = tagName.toLowerCase();
while (node) {
if (node.tagName && node.tagName.toLowerCase() === tagName) return true;
node = node.parentNode;
}
return false;
};
markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
if (typeof keyword === 'string') {
keyword = {
@@ -15,12 +28,13 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
if (isBasicSearch) accuracy = 'partially';
if (keyword.type === 'regex') {
accuracy = 'complementary';
// Remove the trailing wildcard and "accuracy = complementary" will take care of
// highlighting the relevant keywords.
// Remove the trailing wildcard and "accuracy = complementary" will take
// care of highlighting the relevant keywords.
// Known bug: it will also highlight word that contain the term as a suffix for example for "ent*", it will highlight "present"
// which is incorrect (it should only highlight what starts with "ent") but for now will do. Mark.js doesn't have an option
// to tweak this behaviour.
// Known bug: it will also highlight word that contain the term as a
// suffix for example for "ent*", it will highlight "present" which is
// incorrect (it should only highlight what starts with "ent") but for
// now will do. Mark.js doesn't have an option to tweak this behaviour.
value = keyword.value.substr(0, keyword.value.length - 1);
}
@@ -30,6 +44,18 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
{},
{
accuracy: accuracy,
filter: (node, _term, _totalCounter, _counter) => {
// We exclude SVG because it creates a "<mark>" tag inside
// the document, which is not a valid SVG tag. As a result
// the content within that tag disappears.
//
// mark.js has an "exclude" parameter, but it doesn't work
// so we use "filter" instead.
//
// https://github.com/joplin/plugin-abc-sheet-music
if (isInsideContainer(node, 'SVG')) return false;
return true;
},
},
extraOptions
)

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/lib",
"version": "2.10.2",
"version": "2.11.0",
"description": "Joplin Core library",
"author": "Laurent Cozic",
"homepage": "",
@@ -34,11 +34,11 @@
"@joplin/fork-htmlparser2": "^4.1.43",
"@joplin/fork-sax": "^1.2.47",
"@joplin/fork-uslug": "^1.0.8",
"@joplin/htmlpack": "^2.10.2",
"@joplin/renderer": "^2.10.2",
"@joplin/htmlpack": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/turndown": "^4.0.65",
"@joplin/turndown-plugin-gfm": "^1.0.47",
"@joplin/utils": "~2.10",
"@joplin/utils": "~2.11",
"@types/nanoid": "3.0.0",
"async-mutex": "0.4.0",
"base-64": "1.0.0",
@@ -54,7 +54,7 @@
"fast-xml-parser": "3.21.1",
"follow-redirects": "1.15.2",
"form-data": "4.0.0",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"hpagent": "1.2.0",
"html-entities": "1.4.0",
"html-minifier": "4.0.0",
@@ -69,7 +69,7 @@
"moment": "2.29.4",
"multiparty": "4.2.3",
"mustache": "4.2.0",
"nanoid": "3.3.4",
"nanoid": "3.3.6",
"node-fetch": "2.6.7",
"node-notifier": "10.0.1",
"node-persist": "3.1.3",

View File

@@ -110,6 +110,8 @@ export default class ReportService {
let syncedCount = 0;
for (let i = 0; i < BaseItem.syncItemDefinitions_.length; i++) {
const d = BaseItem.syncItemDefinitions_[i];
// ref: https://github.com/laurent22/joplin/issues/7940#issuecomment-1473709148
if (d.className === 'MasterKey') continue;
const ItemClass = BaseItem.getClass(d.className);
const o = {
total: await ItemClass.count(),

View File

@@ -100,6 +100,11 @@ export default class PluginService extends BaseService {
return this.plugins_;
}
public enabledPlugins(pluginSettings: PluginSettings): Plugins {
const enabledPlugins = Object.fromEntries(Object.entries(this.plugins_).filter((p) => this.pluginEnabled(pluginSettings, p[0])));
return enabledPlugins;
}
public get pluginIds(): string[] {
return Object.keys(this.plugins_);
}

View File

@@ -21,6 +21,17 @@ export function credentialDir() {
throw new Error(`Could not find credential directory in any of these paths: ${JSON.stringify(toTry)}`);
}
export const hasCredentialFile = (filename: string) => {
let d = '';
try {
d = credentialDir();
} catch (error) {
return false;
}
return pathExistsSync(`${d}/${filename}`);
};
export function credentialFile(filename: string) {
const rootDir = credentialDir();
const output = `${rootDir}/${filename}`;

View File

@@ -2,8 +2,6 @@ import versionInfo from './versionInfo';
import { reg } from './registry';
import { Plugins } from './services/plugins/PluginService';
import Plugin from './services/plugins/Plugin';
import Setting from './models/Setting';
import { PluginSettings } from './services/plugins/PluginService';
jest.mock('./registry');
@@ -66,10 +64,6 @@ describe('getPluginLists', () => {
const plugins: Plugins = {};
plugins[plugin.manifest.id] = plugin;
const pluginSettings: PluginSettings = {};
pluginSettings[plugin.id] = { enabled: true, deleted: false, hasBeenUpdated: false };
Setting.setValue('plugins.states', pluginSettings);
const v = versionInfo(packageInfo, plugins);
expect(v.body).toMatch(/\n\nPlugin1: 1/);
expect(v.message).toMatch(/\n\nPlugin1: 1/);
@@ -93,12 +87,6 @@ describe('getPluginLists', () => {
plugins[plugin.manifest.id] = plugin;
}
const pluginSettings: PluginSettings = {};
for (const key of Object.keys(plugins)) {
pluginSettings[key] = { enabled: true, deleted: false, hasBeenUpdated: false };
}
Setting.setValue('plugins.states', pluginSettings);
const v = versionInfo(packageInfo, plugins);
expect(v.body).toMatch(/\n\nPlugin1: 1\nPlugin2: 1\nPlugin3: 1/);
@@ -124,12 +112,6 @@ describe('getPluginLists', () => {
plugins[plugin.manifest.id] = plugin;
}
const pluginSettings: PluginSettings = {};
for (const key of Object.keys(plugins)) {
pluginSettings[key] = { enabled: true, deleted: false, hasBeenUpdated: false };
}
Setting.setValue('plugins.states', pluginSettings);
const v = versionInfo(packageInfo, plugins);
const body = '\n';

View File

@@ -2,7 +2,6 @@ import { _ } from './locale';
import Setting from './models/Setting';
import { reg } from './registry';
import { Plugins } from './services/plugins/PluginService';
import PluginService from './services/plugins/PluginService';
interface PluginList {
completeList: string;
@@ -11,16 +10,13 @@ interface PluginList {
function getPluginLists(plugins: Plugins): PluginList {
const pluginList = [];
const pluginSettings = PluginService.instance().unserializePluginSettings(Setting.value('plugins.states'));
const enabledPlugins = Object.fromEntries(Object.entries(plugins).filter((p) => pluginSettings[p[0]] && pluginSettings[p[0]].enabled === true));
if (Object.keys(enabledPlugins).length > 0) {
for (const pluginId in enabledPlugins) {
pluginList.push(`${enabledPlugins[pluginId].manifest.name}: ${enabledPlugins[pluginId].manifest.version}`);
if (Object.keys(plugins).length > 0) {
for (const pluginId in plugins) {
pluginList.push(`${plugins[pluginId].manifest.name}: ${plugins[pluginId].manifest.version}`);
}
}
pluginList.sort();
pluginList.sort(Intl.Collator().compare);
let completeList = '';
let summary = '';

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/pdf-viewer",
"version": "2.10.0",
"version": "2.11.0",
"description": "Provides embedded PDF viewers for Joplin",
"main": "dist/main.js",
"types": "src/main.ts",
@@ -39,7 +39,7 @@
"@fortawesome/fontawesome-svg-core": "6.1.2",
"@fortawesome/free-solid-svg-icons": "6.1.2",
"@fortawesome/react-fontawesome": "0.2.0",
"@joplin/lib": "~2.10",
"@joplin/lib": "~2.11",
"async-mutex": "0.4.0",
"pdfjs-dist": "2.16.105",
"react": "18.2.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/plugin-repo-cli",
"version": "2.10.2",
"version": "2.11.0",
"description": "",
"main": "index.js",
"bin": "./dist/index.js",
@@ -18,10 +18,10 @@
"author": "",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@joplin/lib": "^2.10.2",
"@joplin/tools": "^2.10.2",
"@joplin/utils": "~2.10",
"fs-extra": "11.1.0",
"@joplin/lib": "~2.11",
"@joplin/tools": "~2.11",
"@joplin/utils": "~2.11",
"fs-extra": "11.1.1",
"gh-release-assets": "2.0.1",
"node-fetch": "2.6.7",
"source-map-support": "0.5.21",

View File

@@ -1,7 +1,7 @@
{
"name": "@joplin/react-native-alarm-notification",
"title": "React Native Alarm Notification for Joplin. Forked from https://github.com/emekalites/react-native-alarm-notification",
"version": "2.10.0",
"version": "2.11.0",
"description": "schedule alarm with notification in react-native",
"main": "index.js",
"private": true,

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/react-native-saf-x",
"version": "2.10.2",
"version": "2.11.0",
"description": "a module to help work with scoped storages on android easily",
"main": "src/index",
"react-native": "src/index",

View File

@@ -179,6 +179,8 @@ export interface RuleOptions {
noteId?: string;
vendorDir?: string;
itemIdToUrl?: ItemIdToUrlHandler;
platformName?: string;
}
export default class MdToHtml {

View File

@@ -1,6 +1,8 @@
import { RuleOptions } from '../../MdToHtml';
export default {
assets: function() {
assets: function(theme: any) {
return [
{ name: 'mermaid.min.js' },
{ name: 'mermaid_render.js' },
@@ -12,14 +14,27 @@ export default {
text: '.mermaid { background-color: white; width: 640px; }',
mime: 'text/css',
},
{
inline: true,
// Export button in mermaid graph should be shown only on hovering the mermaid graph
// ref: https://github.com/laurent22/joplin/issues/6101
text: `
.mermaid-export-graph { visibility: hidden; }
.joplin-editable:hover .mermaid-export-graph { visibility: visible; }
.mermaid-export-graph:hover { background-color: ${theme.backgroundColorHover3} !important; }
`.trim(),
mime: 'text/css',
},
];
},
plugin: function(markdownIt: any) {
plugin: function(markdownIt: any, ruleOptions: RuleOptions) {
const defaultRender: Function = markdownIt.renderer.rules.fence || function(tokens: any[], idx: number, options: any, env: any, self: any) {
return self.renderToken(tokens, idx, options, env, self);
};
const exportButtonMarkup = isDesktop(ruleOptions.platformName) ? exportGraphButton(ruleOptions) : '';
markdownIt.renderer.rules.fence = function(tokens: any[], idx: number, options: {}, env: any, self: any) {
const token = tokens[idx];
if (token.info !== 'mermaid') return defaultRender(tokens, idx, options, env, self);
@@ -31,9 +46,49 @@ export default {
return `
<div class="joplin-editable">
<pre class="joplin-source" data-joplin-language="mermaid" data-joplin-source-open="\`\`\`mermaid&#10;" data-joplin-source-close="&#10;\`\`\`&#10;">${contentHtml}</pre>
${exportButtonMarkup}
<pre class="mermaid">${contentHtml}</pre>
</div>
`;
};
},
};
const exportGraphButton = (ruleOptions: RuleOptions) => {
const theme = ruleOptions.theme;
// Clicking on export button manually triggers a right click context menu event
const onClickHandler = `
const target = arguments[0].target;
const button = target.closest("button.mermaid-export-graph");
if (!button) return false;
const $mermaid_elem = button.nextElementSibling;
const rightClickEvent = new PointerEvent("contextmenu", {bubbles: true});
rightClickEvent.target = $mermaid_elem;
$mermaid_elem.dispatchEvent(rightClickEvent);
return false;
`.trim();
const style = `
display: block;
margin-left: auto;
border-radius: ${theme.buttonStyle.borderRadius}px;
font-size: ${theme.fontSize}px;
color: ${theme.color};
background: ${theme.buttonStyle.backgroundColor};
border: ${theme.buttonStyle.border};
`.trim();
return `<button class="mermaid-export-graph" onclick='${onClickHandler}' style="${style}" alt="Export mermaid graph">${downloadIcon()}</button>`;
};
const downloadIcon = () => {
// https://www.svgrepo.com/svg/505363/download
return '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M20 15V18C20 19.1046 19.1046 20 18 20H6C4.89543 20 4 19.1046 4 18L4 15M8 11L12 15M12 15L16 11M12 15V3" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>';
};
const isDesktop = (platformName?: string) => {
if (!platformName) {
return false;
}
return ['darwin', 'linux', 'freebsd', 'win32'].includes(platformName);
};

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/renderer",
"version": "2.10.2",
"version": "2.11.0",
"description": "The Joplin note renderer, used the mobile and desktop application",
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
"main": "index.js",
@@ -29,7 +29,7 @@
"@joplin/fork-htmlparser2": "^4.1.43",
"@joplin/fork-uslug": "^1.0.8",
"font-awesome-filetypes": "2.1.0",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"highlight.js": "11.7.0",
"html-entities": "1.4.0",
"json-stringify-safe": "5.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/server",
"version": "2.10.11",
"version": "2.11.0",
"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",
@@ -23,8 +23,8 @@
"dependencies": {
"@aws-sdk/client-s3": "3.241.0",
"@fortawesome/fontawesome-free": "5.15.4",
"@joplin/lib": "~2.10",
"@joplin/renderer": "~2.10",
"@joplin/lib": "~2.11",
"@joplin/renderer": "~2.11",
"@koa/cors": "3.1.0",
"@types/uuid": "9.0.0",
"bcryptjs": "2.4.3",
@@ -33,7 +33,7 @@
"compare-versions": "3.6.0",
"dayjs": "1.11.7",
"formidable": "2.1.1",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"html-entities": "1.4.0",
"jquery": "3.6.4",
"knex": "2.4.2",
@@ -44,8 +44,8 @@
"node-cron": "3.0.2",
"node-env-file": "0.1.8",
"nodemailer": "6.9.1",
"nodemon": "2.0.21",
"pg": "8.9.0",
"nodemon": "2.0.22",
"pg": "8.10.0",
"pretty-bytes": "5.6.0",
"prettycron": "0.10.0",
"query-string": "7.1.3",
@@ -58,7 +58,7 @@
"zxcvbn": "4.4.2"
},
"devDependencies": {
"@joplin/tools": "~2.10",
"@joplin/tools": "~2.11",
"@rmp135/sql-ts": "1.16.0",
"@types/formidable": "2.0.5",
"@types/fs-extra": "9.0.13",
@@ -74,7 +74,7 @@
"gulp": "4.0.2",
"jest": "29.4.3",
"jest-expect-message": "1.1.3",
"jsdom": "21.0.0",
"jsdom": "21.1.1",
"node-mocks-http": "1.12.2",
"source-map-support": "0.5.21",
"typescript": "4.9.4"

View File

@@ -0,0 +1,12 @@
// Allow running that task "buildCommandIndex" without gulp
const task = require('./buildCommandIndex.js');
const main = async () => {
await task.fn();
};
main().catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,12 @@
// Allow running that task "updateIgnoredTypeScriptBuild" without gulp
const task = require('./updateIgnoredTypeScriptBuild.js');
const main = async () => {
await task.fn();
};
main().catch((error) => {
console.error(error);
process.exit(1);
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/tools",
"version": "2.10.2",
"version": "2.11.0",
"description": "Various tools for Joplin",
"main": "index.js",
"author": "Laurent Cozic",
@@ -20,14 +20,12 @@
},
"license": "AGPL-3.0-or-later",
"dependencies": {
"@joplin/lib": "^2.10.2",
"@joplin/renderer": "^2.10.2",
"@joplin/utils": "~2.10",
"@types/node-fetch": "2.6.2",
"@types/yargs": "17.0.20",
"@joplin/lib": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/utils": "~2.11",
"dayjs": "1.11.7",
"execa": "4.1.0",
"fs-extra": "11.1.0",
"fs-extra": "11.1.1",
"gettext-parser": "6.0.0",
"glob": "8.1.0",
"markdown-it": "13.0.1",
@@ -49,12 +47,14 @@
"@types/jest": "29.2.6",
"@types/mustache": "4.2.2",
"@types/node": "18.11.18",
"gettext-extractor": "3.6.2",
"@types/node-fetch": "2.6.2",
"@types/yargs": "17.0.20",
"gettext-extractor": "3.7.0",
"gulp": "4.0.2",
"html-entities": "1.4.0",
"jest": "29.4.3",
"rss": "1.2.2",
"sass": "1.58.3",
"sass": "1.59.3",
"sqlite3": "5.1.6",
"typescript": "4.9.4"
},

View File

@@ -40,7 +40,7 @@ yarn install
# to change after installation.
git reset --hard
yarn run updateMarkdownDoc
JOPLIN_GITHUB_OAUTH_TOKEN=$JOPLIN_GITHUB_OAUTH_TOKEN yarn run updateMarkdownDoc
yarn run updateNews $DISCOURSE_API_KEY $DISCOURSE_USERNAME
# We commit and push the change. It will be a noop if nothing was actually

View File

@@ -139,6 +139,7 @@ async function main() {
await updatePackageVersion(`${rootDir}/packages/renderer/package.json`, majorMinorVersion, options);
await updatePackageVersion(`${rootDir}/packages/server/package.json`, majorMinorVersion, options);
await updatePackageVersion(`${rootDir}/packages/tools/package.json`, majorMinorVersion, options);
await updatePackageVersion(`${rootDir}/packages/utils/package.json`, majorMinorVersion, options);
if (options.updateVersion) {
await updateGradleVersion(`${rootDir}/packages/app-mobile/android/app/build.gradle`, majorMinorVersion);

View File

@@ -64,11 +64,6 @@
"title": "Serei Network",
"imageName": "SeireiNetwork.png"
},
{
"url": "https://usrigging.com/",
"title": "U.S. Ringing Supply",
"imageName": "RingingSupply.svg"
},
{
"url": "https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-github&mtm_medium=banner",
"urlWebsite": "https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner",
@@ -86,5 +81,11 @@
"imageName": "Grundstueckspreise.png"
}
],
"orgsOld": []
"orgsOld": [
{
"url": "https://usrigging.com/",
"title": "U.S. Ringing Supply",
"imageName": "RingingSupply.svg"
}
]
}

View File

@@ -1,5 +1,5 @@
import * as fs from 'fs-extra';
import { readCredentialFile } from '@joplin/lib/utils/credentialFiles';
import { pathExists, readFile, writeFile, unlink, stat, createWriteStream } from 'fs-extra';
import { hasCredentialFile, readCredentialFile } from '@joplin/lib/utils/credentialFiles';
import { execCommand as execCommand2, commandToString } from '@joplin/utils';
const fetch = require('node-fetch');
@@ -23,7 +23,7 @@ export interface GitHubRelease {
async function insertChangelog(tag: string, changelogPath: string, changelog: string, isPrerelease: boolean, repoTagUrl: string = '') {
repoTagUrl = repoTagUrl || 'https://github.com/laurent22/joplin/releases/tag';
const currentText = await fs.readFile(changelogPath, 'UTF-8');
const currentText = await readFile(changelogPath, 'UTF-8');
const lines = currentText.split('\n');
const beforeLines = [];
@@ -80,7 +80,7 @@ export async function completeReleaseWithChangelog(changelogPath: string, newVer
const newChangelog = await insertChangelog(newTag, changelogPath, changelog, isPreRelease, repoTagUrl);
await fs.writeFile(changelogPath, newChangelog);
await writeFile(changelogPath, newChangelog);
console.info('');
console.info('Verify that the changelog is correct:');
@@ -95,8 +95,8 @@ export async function completeReleaseWithChangelog(changelogPath: string, newVer
async function loadGitHubUsernameCache() {
const path = `${__dirname}/github_username_cache.json`;
if (await fs.pathExists(path)) {
const jsonString = await fs.readFile(path, 'utf8');
if (await pathExists(path)) {
const jsonString = await readFile(path, 'utf8');
return JSON.parse(jsonString);
}
@@ -105,7 +105,7 @@ async function loadGitHubUsernameCache() {
async function saveGitHubUsernameCache(cache: any) {
const path = `${__dirname}/github_username_cache.json`;
await fs.writeFile(path, JSON.stringify(cache));
await writeFile(path, JSON.stringify(cache));
}
// Returns the project root dir
@@ -173,22 +173,21 @@ export function toSystemSlashes(path: string) {
}
export async function setPackagePrivateField(filePath: string, value: any) {
const text = await fs.readFile(filePath, 'utf8');
const text = await readFile(filePath, 'utf8');
const obj = JSON.parse(text);
if (!value) {
delete obj.private;
} else {
obj.private = true;
}
await fs.writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
await writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
}
export async function downloadFile(url: string, targetPath: string) {
const https = require('https');
const fs = require('fs');
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(targetPath);
const file = createWriteStream(targetPath);
https.get(url, (response: any) => {
if (response.statusCode !== 200) reject(new Error(`HTTP error ${response.statusCode}`));
response.pipe(file);
@@ -222,10 +221,8 @@ export function fileSha256(filePath: string) {
}
export async function unlinkForce(filePath: string) {
const fs = require('fs-extra');
try {
await fs.unlink(filePath);
await unlink(filePath);
} catch (error) {
if (error.code === 'ENOENT') return;
throw error;
@@ -233,10 +230,8 @@ export async function unlinkForce(filePath: string) {
}
export function fileExists(filePath: string) {
const fs = require('fs-extra');
return new Promise((resolve, reject) => {
fs.stat(filePath, (error: any) => {
stat(filePath, (error: any) => {
if (!error) {
resolve(true);
} else if (error.code === 'ENOENT') {
@@ -326,7 +321,10 @@ export function patreonOauthToken() {
}
export function githubOauthToken() {
return readCredentialFile('github_oauth_token.txt');
const filename = 'github_oauth_token.txt';
if (hasCredentialFile(filename)) return readCredentialFile(filename);
if (process.env.JOPLIN_GITHUB_OAUTH_TOKEN) return process.env.JOPLIN_GITHUB_OAUTH_TOKEN;
throw new Error(`Cannot get Oauth token. Neither ${filename} nor the env variable JOPLIN_GITHUB_OAUTH_TOKEN are present`);
}
// Note that the GitHub API releases/latest is broken on the joplin-android repo
@@ -422,12 +420,11 @@ export function isMac() {
}
export async function insertContentIntoFile(filePath: string, markerOpen: string, markerClose: string, contentToInsert: string) {
const fs = require('fs-extra');
let content = await fs.readFile(filePath, 'utf-8');
let content = await readFile(filePath, 'utf-8');
// [^]* matches any character including new lines
const regex = new RegExp(`${markerOpen}[^]*?${markerClose}`);
content = content.replace(regex, markerOpen + contentToInsert + markerClose);
await fs.writeFile(filePath, content);
await writeFile(filePath, content);
}
export function dirname(path: string) {

View File

@@ -1,8 +1,7 @@
import { readFile } from 'fs-extra';
import { rootDir } from '@joplin/utils';
import { getRootDir } from '@joplin/utils';
import { fetchWithRetry } from '@joplin/utils/net';
const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`;
import { githubOauthToken } from '../tool-utils';
export interface GithubSponsor {
name: string;
@@ -22,6 +21,7 @@ export interface OrgSponsor {
}
export const loadSponsors = async (): Promise<Sponsors> => {
const sponsorsPath = `${await getRootDir()}/packages/tools/sponsors.json`;
const output: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8'));
output.orgs = output.orgs.map(o => {
@@ -29,8 +29,17 @@ export const loadSponsors = async (): Promise<Sponsors> => {
return o;
});
const oauthToken = await githubOauthToken();
for (const ghSponsor of output.github) {
const userResponse = await fetchWithRetry(`https://api.github.com/users/${ghSponsor.name}`);
const userResponse = await fetchWithRetry(`https://api.github.com/users/${ghSponsor.name}`, {
headers: {
'Content-Type': 'application/json',
'Authorization': `token ${oauthToken}`,
},
});
if (!userResponse.ok) throw new Error(await userResponse.text());
const user = await userResponse.json();
ghSponsor.id = user.id;
}

View File

@@ -11,7 +11,7 @@
"browserify": "14.5.0",
"rollup": "0.50.1",
"standard": "17.0.0",
"turndown": "7.1.1",
"turndown": "7.1.2",
"turndown-attendant": "0.0.3"
},
"files": [

View File

@@ -13,7 +13,7 @@
"dependencies": {
"css": "3.0.0",
"html-entities": "1.4.0",
"jsdom": "21.0.0"
"jsdom": "21.1.1"
},
"devDependencies": {
"browserify": "14.5.0",

View File

@@ -38,7 +38,7 @@ export default async (command: string | string[], options: ExecCommandOptions |
args.splice(0, 1);
const promise = execa(executableName, args);
if (options.showStdout && promise.stdout) promise.stdout.pipe(process.stdout);
if (options.showStderr && promise.stdout) promise.stdout.pipe(process.stderr);
if (options.showStderr && promise.stderr) promise.stderr.pipe(process.stderr);
const result = await promise;
return result.stdout.trim();
};

View File

@@ -2,12 +2,27 @@ import execCommand from './execCommand';
import commandToString from './commandToString';
import splitCommandString from './splitCommandString';
import { dirname } from 'path';
import { pathExists } from 'fs-extra';
const rootDir = dirname(dirname(dirname(__dirname)));
let rootDir_ = '';
const getRootDir = async () => {
if (rootDir_) return rootDir_;
let p = dirname(dirname(dirname(__dirname)));
for (let i = 0; i < 9999; i++) {
if (await pathExists(`${p}/.eslintrc.js`)) {
rootDir_ = p;
return rootDir_;
}
p = dirname(p);
}
throw new Error('Could not find root dir');
};
export {
execCommand,
commandToString,
splitCommandString,
rootDir,
getRootDir,
};

View File

@@ -1,6 +1,7 @@
/* eslint-disable import/prefer-default-export */
import { sleep } from './time';
import fetch from 'node-fetch';
export const fetchWithRetry = async (url: string, opts: any = null) => {
if (!opts) opts = {};

View File

@@ -1,29 +1,32 @@
{
"name": "@joplin/utils",
"version": "2.10.0",
"description": "Utilities for Joplin",
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/utils",
"exports": {
".": "./dist/index.js",
"./net": "./dist/net.js"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"tsc": "tsc --project tsconfig.json",
"watch": "tsc --watch --preserveWatchOutput --project tsconfig.json",
"test": "jest --verbose=false",
"test-ci": "yarn test"
},
"author": "",
"license": "AGPL-3.0-or-later",
"dependencies": {
"execa": "5.1.1"
},
"devDependencies": {
"@types/jest": "29.5.0",
"jest": "29.5.0",
"ts-jest": "29.0.5"
}
"name": "@joplin/utils",
"version": "2.11.0",
"description": "Utilities for Joplin",
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/utils",
"exports": {
".": "./dist/index.js",
"./net": "./dist/net.js"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"tsc": "tsc --project tsconfig.json",
"watch": "tsc --watch --preserveWatchOutput --project tsconfig.json",
"test": "jest --verbose=false",
"test-ci": "yarn test"
},
"author": "",
"license": "AGPL-3.0-or-later",
"dependencies": {
"execa": "5.1.1",
"fs-extra": "11.1.1",
"node-fetch": "2.6.7"
},
"devDependencies": {
"@types/jest": "29.5.0",
"@types/node-fetch": "2.6.2",
"jest": "29.5.0",
"ts-jest": "29.0.5"
}
}

View File

@@ -1,5 +1,15 @@
# Joplin changelog
## [v2.10.13](https://github.com/laurent22/joplin/releases/tag/v2.10.13) (Pre-release) - 2023-04-03T16:53:46Z
- Fixed: Encode the non-ASCII characters in OneDrive URI ([#7868](https://github.com/laurent22/joplin/issues/7868)) ([#7851](https://github.com/laurent22/joplin/issues/7851) by Self Not Found)
- Fixed: Fix OneDrive sync attempting to call method on `null` variable ([#7987](https://github.com/laurent22/joplin/issues/7987)) ([#7986](https://github.com/laurent22/joplin/issues/7986) by Henry Heino)
- Fixed: Fixed display of installed plugins in About box ([376e4eb](https://github.com/laurent22/joplin/commit/376e4eb))
## [v2.10.12](https://github.com/laurent22/joplin/releases/tag/v2.10.12) (Pre-release) - 2023-03-23T12:17:13Z
- Improved: Adjusted New Note and New to-do buttons' breakpoints to happen earlier ([#7961](https://github.com/laurent22/joplin/issues/7961) by [@julien](https://github.com/julien))
## [v2.10.11](https://github.com/laurent22/joplin/releases/tag/v2.10.11) (Pre-release) - 2023-03-17T10:54:02Z
- Fixed: Fixes text wrap on new buttons ([#7938](https://github.com/laurent22/joplin/issues/7938) by [@julien](https://github.com/julien))

View File

@@ -1,5 +1,20 @@
# Joplin Android app changelog
## [android-v2.11.2](https://github.com/laurent22/joplin/releases/tag/android-v2.11.2) (Pre-release) - 2023-04-09T12:04:06Z
- Improved: Resolve #8022: Editor syntax highlighting was broken (#8023) (#8022 by Henry Heino)
- Improved: Updated packages @react-native-community/netinfo (v9.3.8)
- Fixed: Removed `MasterKey` from Sync Status report (#8026) (#7940 by Arun Kumar)
- Security: Prevent bypassing fingerprint lock on certain devices (6b72f86)
## [android-v2.11.1](https://github.com/laurent22/joplin/releases/tag/android-v2.11.1) (Pre-release) - 2023-04-08T08:49:19Z
- New: Add log info for biometrics feature (efdbaeb)
- New: Add setting to enable/disable the markdown toolbar (#7929 by Henry Heino)
- Fixed: Encode the non-ASCII characters in OneDrive URI (#7868) (#7851 by Self Not Found)
- Fixed: Fix OneDrive sync attempting to call method on `null` variable (#7987) (#7986 by Henry Heino)
- Updated packages @lezer/highlight (v1.1.4), fs-extra (v11.1.1), jsdom (v21.1.1), markdown-it-multimd-table (v4.2.1), nanoid (v3.3.6), node-persist (v3.1.3), nodemon (v2.0.22), react-native-document-picker (v8.1.4), react-native-image-picker (v5.3.1), react-native-paper (v5.4.1), react-native-share (v8.2.1), sass (v1.59.3), sqlite3 (v5.1.6), turndown (v7.1.2), yargs (v17.7.1)
## [android-v2.10.9](https://github.com/laurent22/joplin/releases/tag/android-v2.10.9) (Pre-release) - 2023-03-22T18:40:57Z
- Improved: Mark biometrics feature as beta and ensure no call is made if it is not enabled (e44a934)

View File

@@ -399,6 +399,54 @@
"created_at": "2023-03-26T03:40:42Z",
"repoId": 79162682,
"pullRequestNo": 7969
},
{
"name": "TahaNw",
"id": 105979405,
"comment_id": 1490675625,
"created_at": "2023-03-30T17:33:37Z",
"repoId": 79162682,
"pullRequestNo": 7998
},
{
"name": "Fejby",
"id": 73366988,
"comment_id": 1490734071,
"created_at": "2023-03-30T18:21:27Z",
"repoId": 79162682,
"pullRequestNo": 7999
},
{
"name": "gitstart",
"id": 1501599,
"comment_id": 1499665006,
"created_at": "2023-04-06T21:46:22Z",
"repoId": 79162682,
"pullRequestNo": 8024
},
{
"name": "Letty",
"id": 465678,
"comment_id": 1500142614,
"created_at": "2023-04-07T10:04:51Z",
"repoId": 79162682,
"pullRequestNo": 8029
},
{
"name": "tbjers",
"id": 1117052,
"comment_id": 1501316440,
"created_at": "2023-04-10T02:33:42Z",
"repoId": 79162682,
"pullRequestNo": 8036
},
{
"name": "simonla",
"id": 14934570,
"comment_id": 1503950257,
"created_at": "2023-04-11T19:02:23Z",
"repoId": 79162682,
"pullRequestNo": 8042
}
]
}

View File

@@ -0,0 +1,19 @@
# Joplin Server items
To upload an item to Joplin Server:
- Call `PUT /api/items` with the serialized Joplin item. Examples of serialized items are described in `packages/app-cli/tests/support/syncTargetSnapshots`
- That route is in `packages/server/src/routes/api/items.ts`. In there it's going to do some basic processing on the item, and eventually will call `models.item().saveFromRawContent`
- This `saveFromRawContent` is where most of the job is done - it's going to detect what the item is, whether it's a note, notebook, etc. (this is the serialised content, as described above), or a binary file (resource).
- If it's a resource, the content is going to be saved as-is in the database
- If it's an item, it's going to deserialise it because we want to save certain properties separately in the database, such as the parent ID, the type (whether it's a note, notebook, etc.). We save these properties separately purely for performance reasons. Once the properties have been extracted, the rest of the object is serialised back to JSON and saved to the database.
- In the end, the content is saved to the `items` table. The JSON item or the resource binary content will be saved to the `content` field. Other Joplin items properties will be saved to the `jop_*` fields. For example, the ID, the parent ID, whether encryption is enabled, etc.
- `items.jop_id` is the ID as it was generated on the client. `items.id` is the server-side ID. We need two different IDs because we have no way to guarantee that `items.jop_id` is globally unique since it's generated client-side.
- In `ItemModel` there are various utility functions to deal with the content. This is because it may be saved in different places depending on configuration. It can be saved to the `items.content` field in the database, or it can be saved to S3, or to the filesystem. This is why any code that deals with item content must used these utility functions.

39
readme/spec/sync.md Normal file
View File

@@ -0,0 +1,39 @@
# Joplin synchronisation
The Joplin applications are offline first - it means that data is saved locally on the device. In order to have the same data on all the user's devices, we use a synchronisation process. In a nutshell, each device uploads its notes, notebooks, tags, etc. to the server, and also downloads any notes they do not have, or any recent changes. If a note is deleted, it is also deleted from the server, and eventually deleted from each device too.
## Vocabulary
### Clients
The sync clients are the Joplin applications - the desktop, mobile and terminal applications.
### Sync targets
The sync target is the location where the data is going to be saved. It can be for example Joplin Server, a Nextcloud instance, or a WebDAV server.
### Items
The "items" are the notes, notebooks, tags and resources that need to be synced.
## General process
Whenever the user makes a change to an item, it is uploaded to the sync target within a few seconds. Uploading items as soon as possible helps limit conflicts. Because that way, any client that connects to the sync target is more likely to get the latest version of the item.
Additionally, every few minutes, the client is going to poll the server and download the latest changes, and apply them to the local note collection.
## Code architecture
- `packages/lib/Synchronizer.ts`: This file is responsible for the main synchronisation process. It download changes, upload them, and apply any deletion. The class is relatively generic and receive a `SyncTarget` object that handles sync target-specific operations. The synchroniser is also going encrypt and decrypt items if E2EE is enabled.
- `packages/lib/SyncTarget*.ts`: These files are the entry points for the various sync targets. They expose some metadata such as name, description, what options they support, etc. Some may also implement a function to test whether the configuration is working (used from the configuration screen). Finally, the main role of this class is to initialise an instance of a `FileApi`.
- `packages/lib/file-api-driver-*.ts`: Those are the file APIs. They must implement generic file-like operations to create, update, delete or list files. This API is in turn used by the synchroniser to created, update or delete items.
- `packages/lib/*Api.ts`: The `file-api-driver` will call some low-level API to perform its operations. For example `file-api-driver-local` will use the `fs` package to read/write files, `file-api-driver-amazon-s3` will use the AWS API to work with S3. In some cases however such a low-level API is not available - in that case, we usually create an `*Api.ts` file, which is used by the file API driver to perform its operations. For example, there is a `JoplinServerApi.ts`, which is used to connect to Joplin Server.
## See also
- [Synchronisation lock](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync_lock.md)
- [E2EE: Technical spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/e2ee.md)
- [E2EE: Workflow](https://github.com/laurent22/joplin/blob/dev/readme/spec/e2ee/workflow.md)

View File

@@ -1,14 +1,14 @@
---
updated: 2023-03-07T12:23:23Z
updated: 2023-04-04T18:29:53Z
---
# Joplin statistics
| Name | Value |
| ----- | ----- |
| Total Windows downloads | 3,092,822 |
| Total macOs downloads | 1,140,209 |
| Total Linux downloads | 935,001 |
| Total Windows downloads | 3,163,976 |
| Total macOs downloads | 1,156,759 |
| Total Linux downloads | 951,743 |
| Windows % | 60% |
| macOS % | 22% |
| Linux % | 18% |
@@ -17,272 +17,277 @@ updated: 2023-03-07T12:23:23Z
| Version | Date | Windows | macOS | Linux | Total |
| ----- | ----- | ----- | ----- | ----- | ----- |
| [v2.10.8](https://github.com/laurent22/joplin/releases/tag/v2.10.8) (p) | 2023-02-26T12:53:55Z | 2,185 | 413 | 435 | 3,033 |
| [v2.10.7](https://github.com/laurent22/joplin/releases/tag/v2.10.7) (p) | 2023-02-24T10:56:20Z | 783 | 171 | 253 | 1,207 |
| [v2.10.6](https://github.com/laurent22/joplin/releases/tag/v2.10.6) (p) | 2023-02-20T14:00:05Z | 1,568 | 322 | 267 | 2,157 |
| [v2.10.4](https://github.com/laurent22/joplin/releases/tag/v2.10.4) (p) | 2023-01-05T13:09:20Z | 6,722 | 1,272 | 1,713 | 9,707 |
| [v2.10.3](https://github.com/laurent22/joplin/releases/tag/v2.10.3) (p) | 2022-12-31T15:53:23Z | 1,370 | 296 | 324 | 1,990 |
| [v2.10.2](https://github.com/laurent22/joplin/releases/tag/v2.10.2) (p) | 2022-12-18T18:05:08Z | 2,772 | 544 | 600 | 3,916 |
| [v2.9.17](https://github.com/laurent22/joplin/releases/tag/v2.9.17) | 2022-11-15T10:28:37Z | 217,524 | 78,236 | 51,953 | 347,713 |
| [v2.9.12](https://github.com/laurent22/joplin/releases/tag/v2.9.12) (p) | 2022-11-01T17:06:05Z | 9,972 | 585 | 516 | 11,073 |
| [v2.9.11](https://github.com/laurent22/joplin/releases/tag/v2.9.11) (p) | 2022-10-23T16:09:58Z | 2,133 | 509 | 692 | 3,334 |
| [v2.9.4](https://github.com/laurent22/joplin/releases/tag/v2.9.4) (p) | 2022-08-18T16:52:26Z | 7,109 | 1,843 | 2,169 | 11,121 |
| [v2.9.3](https://github.com/laurent22/joplin/releases/tag/v2.9.3) (p) | 2022-08-18T13:11:09Z | 284 | 72 | 248 | 604 |
| [v2.9.2](https://github.com/laurent22/joplin/releases/tag/v2.9.2) (p) | 2022-08-12T18:12:12Z | 1,461 | 429 | 0 | 1,890 |
| [v2.9.1](https://github.com/laurent22/joplin/releases/tag/v2.9.1) (p) | 2022-07-11T09:59:32Z | 6,534 | 1,320 | 1,375 | 9,229 |
| [v2.8.8](https://github.com/laurent22/joplin/releases/tag/v2.8.8) | 2022-05-17T14:48:06Z | 346,174 | 113,440 | 113,323 | 572,937 |
| [v2.8.7](https://github.com/laurent22/joplin/releases/tag/v2.8.7) (p) | 2022-05-06T11:34:27Z | 2,732 | 344 | 372 | 3,448 |
| [v2.8.6](https://github.com/laurent22/joplin/releases/tag/v2.8.6) (p) | 2022-05-03T10:08:25Z | 2,370 | 383 | 305 | 3,058 |
| [v2.8.5](https://github.com/laurent22/joplin/releases/tag/v2.8.5) (p) | 2022-04-27T13:51:50Z | 2,376 | 343 | 323 | 3,042 |
| [v2.8.4](https://github.com/laurent22/joplin/releases/tag/v2.8.4) (p) | 2022-04-19T18:00:09Z | 2,887 | 558 | 304 | 3,749 |
| [v2.8.2](https://github.com/laurent22/joplin/releases/tag/v2.8.2) (p) | 2022-04-14T11:35:45Z | 2,310 | 258 | 240 | 2,808 |
| [v2.7.15](https://github.com/laurent22/joplin/releases/tag/v2.7.15) | 2022-03-17T13:03:23Z | 153,645 | 56,662 | 51,160 | 261,467 |
| [v2.7.14](https://github.com/laurent22/joplin/releases/tag/v2.7.14) | 2022-02-27T11:30:53Z | 32,646 | 16,745 | 4,768 | 54,159 |
| [v2.7.13](https://github.com/laurent22/joplin/releases/tag/v2.7.13) | 2022-02-24T17:42:12Z | 53,053 | 25,695 | 11,683 | 90,431 |
| [v2.7.12](https://github.com/laurent22/joplin/releases/tag/v2.7.12) (p) | 2022-02-14T15:06:14Z | 3,066 | 445 | 437 | 3,948 |
| [v2.7.11](https://github.com/laurent22/joplin/releases/tag/v2.7.11) (p) | 2022-02-12T13:00:02Z | 2,182 | 178 | 141 | 2,501 |
| [v2.7.10](https://github.com/laurent22/joplin/releases/tag/v2.7.10) (p) | 2022-02-11T18:19:09Z | 1,735 | 108 | 64 | 1,907 |
| [v2.7.8](https://github.com/laurent22/joplin/releases/tag/v2.7.8) (p) | 2022-01-19T09:35:27Z | 3,989 | 751 | 802 | 5,542 |
| [v2.7.7](https://github.com/laurent22/joplin/releases/tag/v2.7.7) (p) | 2022-01-18T14:05:07Z | 2,002 | 138 | 115 | 2,255 |
| [v2.7.6](https://github.com/laurent22/joplin/releases/tag/v2.7.6) (p) | 2022-01-17T17:08:28Z | 2,031 | 165 | 92 | 2,288 |
| [v2.6.10](https://github.com/laurent22/joplin/releases/tag/v2.6.10) | 2021-12-19T11:31:16Z | 132,901 | 51,148 | 49,204 | 233,253 |
| [v2.6.9](https://github.com/laurent22/joplin/releases/tag/v2.6.9) | 2021-12-17T11:57:32Z | 17,114 | 9,468 | 3,161 | 29,743 |
| [v2.6.7](https://github.com/laurent22/joplin/releases/tag/v2.6.7) (p) | 2021-12-16T10:47:23Z | 2,189 | 146 | 83 | 2,418 |
| [v2.6.6](https://github.com/laurent22/joplin/releases/tag/v2.6.6) (p) | 2021-12-13T12:31:43Z | 2,221 | 238 | 146 | 2,605 |
| [v2.6.5](https://github.com/laurent22/joplin/releases/tag/v2.6.5) (p) | 2021-12-13T10:07:04Z | 1,532 | 36 | 14 | 1,582 |
| [v2.6.4](https://github.com/laurent22/joplin/releases/tag/v2.6.4) (p) | 2021-12-09T19:53:43Z | 2,267 | 270 | 181 | 2,718 |
| [v2.6.2](https://github.com/laurent22/joplin/releases/tag/v2.6.2) (p) | 2021-11-18T12:19:12Z | 4,044 | 775 | 684 | 5,503 |
| [v2.5.12](https://github.com/laurent22/joplin/releases/tag/v2.5.12) | 2021-11-08T11:07:11Z | 80,306 | 32,472 | 25,187 | 137,965 |
| [v2.5.10](https://github.com/laurent22/joplin/releases/tag/v2.5.10) | 2021-11-01T08:22:42Z | 45,211 | 19,002 | 10,052 | 74,265 |
| [v2.5.8](https://github.com/laurent22/joplin/releases/tag/v2.5.8) | 2021-10-31T11:38:03Z | 14,024 | 6,543 | 2,293 | 22,860 |
| [v2.5.7](https://github.com/laurent22/joplin/releases/tag/v2.5.7) (p) | 2021-10-29T14:47:33Z | 1,853 | 190 | 150 | 2,193 |
| [v2.5.6](https://github.com/laurent22/joplin/releases/tag/v2.5.6) (p) | 2021-10-28T22:03:09Z | 1,873 | 163 | 91 | 2,127 |
| [v2.5.4](https://github.com/laurent22/joplin/releases/tag/v2.5.4) (p) | 2021-10-19T10:10:54Z | 3,352 | 553 | 555 | 4,460 |
| [v2.4.12](https://github.com/laurent22/joplin/releases/tag/v2.4.12) | 2021-10-13T17:24:34Z | 44,911 | 19,952 | 9,762 | 74,625 |
| [v2.5.1](https://github.com/laurent22/joplin/releases/tag/v2.5.1) (p) | 2021-10-02T09:51:58Z | 4,322 | 888 | 928 | 6,138 |
| [v2.4.9](https://github.com/laurent22/joplin/releases/tag/v2.4.9) | 2021-09-29T19:08:58Z | 57,194 | 23,223 | 15,862 | 96,279 |
| [v2.4.8](https://github.com/laurent22/joplin/releases/tag/v2.4.8) (p) | 2021-09-22T19:01:46Z | 8,200 | 1,756 | 516 | 10,472 |
| [v2.4.7](https://github.com/laurent22/joplin/releases/tag/v2.4.7) (p) | 2021-09-19T12:53:22Z | 2,287 | 236 | 191 | 2,714 |
| [v2.4.6](https://github.com/laurent22/joplin/releases/tag/v2.4.6) (p) | 2021-09-09T18:57:17Z | 3,070 | 443 | 502 | 4,015 |
| [v2.4.5](https://github.com/laurent22/joplin/releases/tag/v2.4.5) (p) | 2021-09-06T18:03:28Z | 2,333 | 253 | 207 | 2,793 |
| [v2.4.4](https://github.com/laurent22/joplin/releases/tag/v2.4.4) (p) | 2021-08-30T16:02:51Z | 2,551 | 361 | 342 | 3,254 |
| [v2.4.3](https://github.com/laurent22/joplin/releases/tag/v2.4.3) (p) | 2021-08-28T15:27:32Z | 2,089 | 189 | 161 | 2,439 |
| [v2.4.2](https://github.com/laurent22/joplin/releases/tag/v2.4.2) (p) | 2021-08-27T17:13:21Z | 1,806 | 134 | 76 | 2,016 |
| [v2.4.1](https://github.com/laurent22/joplin/releases/tag/v2.4.1) (p) | 2021-08-21T11:52:30Z | 2,685 | 355 | 320 | 3,360 |
| [v2.3.5](https://github.com/laurent22/joplin/releases/tag/v2.3.5) | 2021-08-17T06:43:30Z | 82,616 | 31,384 | 33,099 | 147,099 |
| [v2.3.3](https://github.com/laurent22/joplin/releases/tag/v2.3.3) | 2021-08-14T09:19:40Z | 16,021 | 6,860 | 4,040 | 26,921 |
| [v2.2.7](https://github.com/laurent22/joplin/releases/tag/v2.2.7) | 2021-08-11T11:03:26Z | 16,247 | 7,497 | 2,575 | 26,319 |
| [v2.2.6](https://github.com/laurent22/joplin/releases/tag/v2.2.6) (p) | 2021-08-09T19:29:20Z | 8,997 | 4,603 | 942 | 14,542 |
| [v2.2.5](https://github.com/laurent22/joplin/releases/tag/v2.2.5) (p) | 2021-08-07T10:35:24Z | 2,416 | 261 | 191 | 2,868 |
| [v2.2.4](https://github.com/laurent22/joplin/releases/tag/v2.2.4) (p) | 2021-08-05T16:42:48Z | 2,088 | 191 | 116 | 2,395 |
| [v2.2.2](https://github.com/laurent22/joplin/releases/tag/v2.2.2) (p) | 2021-07-19T10:28:35Z | 3,993 | 721 | 630 | 5,344 |
| [v2.1.9](https://github.com/laurent22/joplin/releases/tag/v2.1.9) | 2021-07-19T10:28:43Z | 47,484 | 18,780 | 16,750 | 83,014 |
| [v2.2.1](https://github.com/laurent22/joplin/releases/tag/v2.2.1) (p) | 2021-07-09T17:38:25Z | 3,629 | 400 | 376 | 4,405 |
| [v2.1.8](https://github.com/laurent22/joplin/releases/tag/v2.1.8) | 2021-07-03T08:25:16Z | 31,320 | 12,174 | 12,712 | 56,206 |
| [v2.1.7](https://github.com/laurent22/joplin/releases/tag/v2.1.7) | 2021-06-26T19:48:55Z | 14,976 | 6,386 | 3,612 | 24,974 |
| [v2.1.5](https://github.com/laurent22/joplin/releases/tag/v2.1.5) (p) | 2021-06-23T15:08:52Z | 2,444 | 233 | 184 | 2,861 |
| [v2.1.3](https://github.com/laurent22/joplin/releases/tag/v2.1.3) (p) | 2021-06-19T16:32:51Z | 2,557 | 293 | 198 | 3,048 |
| [v2.0.11](https://github.com/laurent22/joplin/releases/tag/v2.0.11) | 2021-06-16T17:55:49Z | 24,643 | 9,241 | 9,817 | 43,701 |
| [v2.0.10](https://github.com/laurent22/joplin/releases/tag/v2.0.10) | 2021-06-16T07:58:29Z | 3,664 | 918 | 374 | 4,956 |
| [v2.0.9](https://github.com/laurent22/joplin/releases/tag/v2.0.9) (p) | 2021-06-12T09:30:30Z | 2,547 | 289 | 875 | 3,711 |
| [v2.0.8](https://github.com/laurent22/joplin/releases/tag/v2.0.8) (p) | 2021-06-10T16:15:08Z | 2,074 | 225 | 574 | 2,873 |
| [v2.10.13](https://github.com/laurent22/joplin/releases/tag/v2.10.13) (p) | 2023-04-03T16:53:46Z | 591 | 150 | 88 | 829 |
| [v2.10.12](https://github.com/laurent22/joplin/releases/tag/v2.10.12) (p) | 2023-03-23T12:17:13Z | 2,251 | 497 | 582 | 3,330 |
| [v2.10.11](https://github.com/laurent22/joplin/releases/tag/v2.10.11) (p) | 2023-03-17T10:54:02Z | 1,643 | 362 | 358 | 2,363 |
| [v2.10.10](https://github.com/laurent22/joplin/releases/tag/v2.10.10) (p) | 2023-03-13T23:16:37Z | 1,130 | 254 | 230 | 1,614 |
| [v2.10.9](https://github.com/laurent22/joplin/releases/tag/v2.10.9) (p) | 2023-03-12T16:16:45Z | 673 | 195 | 211 | 1,079 |
| [v2.10.8](https://github.com/laurent22/joplin/releases/tag/v2.10.8) (p) | 2023-02-26T12:53:55Z | 3,131 | 556 | 683 | 4,370 |
| [v2.10.7](https://github.com/laurent22/joplin/releases/tag/v2.10.7) (p) | 2023-02-24T10:56:20Z | 836 | 173 | 257 | 1,266 |
| [v2.10.6](https://github.com/laurent22/joplin/releases/tag/v2.10.6) (p) | 2023-02-20T14:00:05Z | 1,635 | 324 | 269 | 2,228 |
| [v2.10.4](https://github.com/laurent22/joplin/releases/tag/v2.10.4) (p) | 2023-01-05T13:09:20Z | 6,798 | 1,273 | 1,723 | 9,794 |
| [v2.10.3](https://github.com/laurent22/joplin/releases/tag/v2.10.3) (p) | 2022-12-31T15:53:23Z | 1,424 | 297 | 331 | 2,052 |
| [v2.10.2](https://github.com/laurent22/joplin/releases/tag/v2.10.2) (p) | 2022-12-18T18:05:08Z | 2,831 | 546 | 602 | 3,979 |
| [v2.9.17](https://github.com/laurent22/joplin/releases/tag/v2.9.17) | 2022-11-15T10:28:37Z | 271,015 | 92,781 | 66,682 | 430,478 |
| [v2.9.12](https://github.com/laurent22/joplin/releases/tag/v2.9.12) (p) | 2022-11-01T17:06:05Z | 10,028 | 587 | 518 | 11,133 |
| [v2.9.11](https://github.com/laurent22/joplin/releases/tag/v2.9.11) (p) | 2022-10-23T16:09:58Z | 2,189 | 510 | 694 | 3,393 |
| [v2.9.4](https://github.com/laurent22/joplin/releases/tag/v2.9.4) (p) | 2022-08-18T16:52:26Z | 7,212 | 1,844 | 2,170 | 11,226 |
| [v2.9.3](https://github.com/laurent22/joplin/releases/tag/v2.9.3) (p) | 2022-08-18T13:11:09Z | 289 | 74 | 249 | 612 |
| [v2.9.2](https://github.com/laurent22/joplin/releases/tag/v2.9.2) (p) | 2022-08-12T18:12:12Z | 1,470 | 430 | 0 | 1,900 |
| [v2.9.1](https://github.com/laurent22/joplin/releases/tag/v2.9.1) (p) | 2022-07-11T09:59:32Z | 6,632 | 1,322 | 1,378 | 9,332 |
| [v2.8.8](https://github.com/laurent22/joplin/releases/tag/v2.8.8) | 2022-05-17T14:48:06Z | 346,538 | 113,526 | 113,348 | 573,412 |
| [v2.8.7](https://github.com/laurent22/joplin/releases/tag/v2.8.7) (p) | 2022-05-06T11:34:27Z | 2,841 | 345 | 373 | 3,559 |
| [v2.8.6](https://github.com/laurent22/joplin/releases/tag/v2.8.6) (p) | 2022-05-03T10:08:25Z | 2,472 | 384 | 307 | 3,163 |
| [v2.8.5](https://github.com/laurent22/joplin/releases/tag/v2.8.5) (p) | 2022-04-27T13:51:50Z | 2,495 | 344 | 323 | 3,162 |
| [v2.8.4](https://github.com/laurent22/joplin/releases/tag/v2.8.4) (p) | 2022-04-19T18:00:09Z | 3,002 | 562 | 305 | 3,869 |
| [v2.8.2](https://github.com/laurent22/joplin/releases/tag/v2.8.2) (p) | 2022-04-14T11:35:45Z | 2,421 | 259 | 241 | 2,921 |
| [v2.7.15](https://github.com/laurent22/joplin/releases/tag/v2.7.15) | 2022-03-17T13:03:23Z | 153,851 | 56,676 | 51,167 | 261,694 |
| [v2.7.14](https://github.com/laurent22/joplin/releases/tag/v2.7.14) | 2022-02-27T11:30:53Z | 32,782 | 16,752 | 4,775 | 54,309 |
| [v2.7.13](https://github.com/laurent22/joplin/releases/tag/v2.7.13) | 2022-02-24T17:42:12Z | 53,179 | 25,698 | 11,686 | 90,563 |
| [v2.7.12](https://github.com/laurent22/joplin/releases/tag/v2.7.12) (p) | 2022-02-14T15:06:14Z | 3,182 | 446 | 439 | 4,067 |
| [v2.7.11](https://github.com/laurent22/joplin/releases/tag/v2.7.11) (p) | 2022-02-12T13:00:02Z | 2,295 | 179 | 142 | 2,616 |
| [v2.7.10](https://github.com/laurent22/joplin/releases/tag/v2.7.10) (p) | 2022-02-11T18:19:09Z | 1,852 | 109 | 65 | 2,026 |
| [v2.7.8](https://github.com/laurent22/joplin/releases/tag/v2.7.8) (p) | 2022-01-19T09:35:27Z | 4,097 | 752 | 803 | 5,652 |
| [v2.7.7](https://github.com/laurent22/joplin/releases/tag/v2.7.7) (p) | 2022-01-18T14:05:07Z | 2,129 | 139 | 116 | 2,384 |
| [v2.7.6](https://github.com/laurent22/joplin/releases/tag/v2.7.6) (p) | 2022-01-17T17:08:28Z | 2,138 | 166 | 96 | 2,400 |
| [v2.6.10](https://github.com/laurent22/joplin/releases/tag/v2.6.10) | 2021-12-19T11:31:16Z | 133,095 | 51,156 | 49,215 | 233,466 |
| [v2.6.9](https://github.com/laurent22/joplin/releases/tag/v2.6.9) | 2021-12-17T11:57:32Z | 17,233 | 9,471 | 3,165 | 29,869 |
| [v2.6.7](https://github.com/laurent22/joplin/releases/tag/v2.6.7) (p) | 2021-12-16T10:47:23Z | 2,301 | 148 | 84 | 2,533 |
| [v2.6.6](https://github.com/laurent22/joplin/releases/tag/v2.6.6) (p) | 2021-12-13T12:31:43Z | 2,325 | 239 | 148 | 2,712 |
| [v2.6.5](https://github.com/laurent22/joplin/releases/tag/v2.6.5) (p) | 2021-12-13T10:07:04Z | 1,646 | 37 | 15 | 1,698 |
| [v2.6.4](https://github.com/laurent22/joplin/releases/tag/v2.6.4) (p) | 2021-12-09T19:53:43Z | 2,372 | 271 | 182 | 2,825 |
| [v2.6.2](https://github.com/laurent22/joplin/releases/tag/v2.6.2) (p) | 2021-11-18T12:19:12Z | 4,157 | 776 | 684 | 5,617 |
| [v2.5.12](https://github.com/laurent22/joplin/releases/tag/v2.5.12) | 2021-11-08T11:07:11Z | 80,462 | 32,474 | 25,189 | 138,125 |
| [v2.5.10](https://github.com/laurent22/joplin/releases/tag/v2.5.10) | 2021-11-01T08:22:42Z | 45,346 | 19,006 | 10,056 | 74,408 |
| [v2.5.8](https://github.com/laurent22/joplin/releases/tag/v2.5.8) | 2021-10-31T11:38:03Z | 14,140 | 6,545 | 2,295 | 22,980 |
| [v2.5.7](https://github.com/laurent22/joplin/releases/tag/v2.5.7) (p) | 2021-10-29T14:47:33Z | 1,955 | 190 | 150 | 2,295 |
| [v2.5.6](https://github.com/laurent22/joplin/releases/tag/v2.5.6) (p) | 2021-10-28T22:03:09Z | 1,981 | 163 | 91 | 2,235 |
| [v2.5.4](https://github.com/laurent22/joplin/releases/tag/v2.5.4) (p) | 2021-10-19T10:10:54Z | 3,463 | 553 | 555 | 4,571 |
| [v2.4.12](https://github.com/laurent22/joplin/releases/tag/v2.4.12) | 2021-10-13T17:24:34Z | 45,074 | 19,953 | 9,765 | 74,792 |
| [v2.5.1](https://github.com/laurent22/joplin/releases/tag/v2.5.1) (p) | 2021-10-02T09:51:58Z | 4,439 | 888 | 928 | 6,255 |
| [v2.4.9](https://github.com/laurent22/joplin/releases/tag/v2.4.9) | 2021-09-29T19:08:58Z | 57,319 | 23,225 | 15,864 | 96,408 |
| [v2.4.8](https://github.com/laurent22/joplin/releases/tag/v2.4.8) (p) | 2021-09-22T19:01:46Z | 8,307 | 1,757 | 516 | 10,580 |
| [v2.4.7](https://github.com/laurent22/joplin/releases/tag/v2.4.7) (p) | 2021-09-19T12:53:22Z | 2,405 | 236 | 191 | 2,832 |
| [v2.4.6](https://github.com/laurent22/joplin/releases/tag/v2.4.6) (p) | 2021-09-09T18:57:17Z | 3,171 | 444 | 502 | 4,117 |
| [v2.4.5](https://github.com/laurent22/joplin/releases/tag/v2.4.5) (p) | 2021-09-06T18:03:28Z | 2,437 | 253 | 208 | 2,898 |
| [v2.4.4](https://github.com/laurent22/joplin/releases/tag/v2.4.4) (p) | 2021-08-30T16:02:51Z | 2,656 | 362 | 343 | 3,361 |
| [v2.4.3](https://github.com/laurent22/joplin/releases/tag/v2.4.3) (p) | 2021-08-28T15:27:32Z | 2,189 | 190 | 161 | 2,540 |
| [v2.4.2](https://github.com/laurent22/joplin/releases/tag/v2.4.2) (p) | 2021-08-27T17:13:21Z | 1,910 | 134 | 76 | 2,120 |
| [v2.4.1](https://github.com/laurent22/joplin/releases/tag/v2.4.1) (p) | 2021-08-21T11:52:30Z | 2,788 | 356 | 320 | 3,464 |
| [v2.3.5](https://github.com/laurent22/joplin/releases/tag/v2.3.5) | 2021-08-17T06:43:30Z | 82,757 | 31,387 | 33,102 | 147,246 |
| [v2.3.3](https://github.com/laurent22/joplin/releases/tag/v2.3.3) | 2021-08-14T09:19:40Z | 16,184 | 6,863 | 4,043 | 27,090 |
| [v2.2.7](https://github.com/laurent22/joplin/releases/tag/v2.2.7) | 2021-08-11T11:03:26Z | 16,373 | 7,498 | 2,578 | 26,449 |
| [v2.2.6](https://github.com/laurent22/joplin/releases/tag/v2.2.6) (p) | 2021-08-09T19:29:20Z | 9,115 | 4,604 | 942 | 14,661 |
| [v2.2.5](https://github.com/laurent22/joplin/releases/tag/v2.2.5) (p) | 2021-08-07T10:35:24Z | 2,520 | 261 | 191 | 2,972 |
| [v2.2.4](https://github.com/laurent22/joplin/releases/tag/v2.2.4) (p) | 2021-08-05T16:42:48Z | 2,199 | 191 | 117 | 2,507 |
| [v2.2.2](https://github.com/laurent22/joplin/releases/tag/v2.2.2) (p) | 2021-07-19T10:28:35Z | 4,096 | 721 | 630 | 5,447 |
| [v2.1.9](https://github.com/laurent22/joplin/releases/tag/v2.1.9) | 2021-07-19T10:28:43Z | 47,639 | 18,783 | 16,752 | 83,174 |
| [v2.2.1](https://github.com/laurent22/joplin/releases/tag/v2.2.1) (p) | 2021-07-09T17:38:25Z | 3,738 | 400 | 376 | 4,514 |
| [v2.1.8](https://github.com/laurent22/joplin/releases/tag/v2.1.8) | 2021-07-03T08:25:16Z | 31,465 | 12,176 | 12,714 | 56,355 |
| [v2.1.7](https://github.com/laurent22/joplin/releases/tag/v2.1.7) | 2021-06-26T19:48:55Z | 15,100 | 6,387 | 3,614 | 25,101 |
| [v2.1.5](https://github.com/laurent22/joplin/releases/tag/v2.1.5) (p) | 2021-06-23T15:08:52Z | 2,562 | 233 | 185 | 2,980 |
| [v2.1.3](https://github.com/laurent22/joplin/releases/tag/v2.1.3) (p) | 2021-06-19T16:32:51Z | 2,662 | 294 | 199 | 3,155 |
| [v2.0.11](https://github.com/laurent22/joplin/releases/tag/v2.0.11) | 2021-06-16T17:55:49Z | 24,783 | 9,243 | 9,828 | 43,854 |
| [v2.0.10](https://github.com/laurent22/joplin/releases/tag/v2.0.10) | 2021-06-16T07:58:29Z | 3,805 | 920 | 377 | 5,102 |
| [v2.0.9](https://github.com/laurent22/joplin/releases/tag/v2.0.9) (p) | 2021-06-12T09:30:30Z | 2,658 | 289 | 875 | 3,822 |
| [v2.0.8](https://github.com/laurent22/joplin/releases/tag/v2.0.8) (p) | 2021-06-10T16:15:08Z | 2,179 | 225 | 574 | 2,978 |
| [v2.0.4](https://github.com/laurent22/joplin/releases/tag/v2.0.4) (p) | 2021-06-02T12:54:17Z | 1,607 | 388 | 374 | 2,369 |
| [v2.0.2](https://github.com/laurent22/joplin/releases/tag/v2.0.2) (p) | 2021-05-21T18:07:48Z | 3,814 | 486 | 1,664 | 5,964 |
| [v2.0.1](https://github.com/laurent22/joplin/releases/tag/v2.0.1) (p) | 2021-05-15T13:22:58Z | 874 | 269 | 1,017 | 2,160 |
| [v1.8.5](https://github.com/laurent22/joplin/releases/tag/v1.8.5) | 2021-05-10T11:58:14Z | 39,257 | 16,266 | 19,399 | 74,922 |
| [v1.8.4](https://github.com/laurent22/joplin/releases/tag/v1.8.4) (p) | 2021-05-09T18:05:05Z | 2,062 | 134 | 454 | 2,650 |
| [v1.8.3](https://github.com/laurent22/joplin/releases/tag/v1.8.3) (p) | 2021-05-04T10:38:16Z | 3,064 | 303 | 934 | 4,301 |
| [v1.8.2](https://github.com/laurent22/joplin/releases/tag/v1.8.2) (p) | 2021-04-25T10:50:51Z | 3,311 | 434 | 1,282 | 5,027 |
| [v1.8.1](https://github.com/laurent22/joplin/releases/tag/v1.8.1) (p) | 2021-03-29T10:46:41Z | 4,386 | 823 | 2,450 | 7,659 |
| [v1.7.11](https://github.com/laurent22/joplin/releases/tag/v1.7.11) | 2021-02-03T12:50:01Z | 118,145 | 42,825 | 64,340 | 225,310 |
| [v1.7.10](https://github.com/laurent22/joplin/releases/tag/v1.7.10) | 2021-01-30T13:25:29Z | 14,229 | 4,854 | 4,486 | 23,569 |
| [v2.0.2](https://github.com/laurent22/joplin/releases/tag/v2.0.2) (p) | 2021-05-21T18:07:48Z | 3,947 | 486 | 1,664 | 6,097 |
| [v2.0.1](https://github.com/laurent22/joplin/releases/tag/v2.0.1) (p) | 2021-05-15T13:22:58Z | 874 | 269 | 1,018 | 2,161 |
| [v1.8.5](https://github.com/laurent22/joplin/releases/tag/v1.8.5) | 2021-05-10T11:58:14Z | 39,392 | 16,268 | 19,403 | 75,063 |
| [v1.8.4](https://github.com/laurent22/joplin/releases/tag/v1.8.4) (p) | 2021-05-09T18:05:05Z | 2,160 | 135 | 454 | 2,749 |
| [v1.8.3](https://github.com/laurent22/joplin/releases/tag/v1.8.3) (p) | 2021-05-04T10:38:16Z | 3,161 | 303 | 934 | 4,398 |
| [v1.8.2](https://github.com/laurent22/joplin/releases/tag/v1.8.2) (p) | 2021-04-25T10:50:51Z | 3,427 | 434 | 1,282 | 5,143 |
| [v1.8.1](https://github.com/laurent22/joplin/releases/tag/v1.8.1) (p) | 2021-03-29T10:46:41Z | 4,482 | 824 | 2,450 | 7,756 |
| [v1.7.11](https://github.com/laurent22/joplin/releases/tag/v1.7.11) | 2021-02-03T12:50:01Z | 118,342 | 42,858 | 64,351 | 225,551 |
| [v1.7.10](https://github.com/laurent22/joplin/releases/tag/v1.7.10) | 2021-01-30T13:25:29Z | 14,248 | 4,856 | 4,490 | 23,594 |
| [v1.7.9](https://github.com/laurent22/joplin/releases/tag/v1.7.9) (p) | 2021-01-28T09:50:21Z | 502 | 133 | 498 | 1,133 |
| [v1.7.6](https://github.com/laurent22/joplin/releases/tag/v1.7.6) (p) | 2021-01-27T10:36:05Z | 316 | 93 | 288 | 697 |
| [v1.7.5](https://github.com/laurent22/joplin/releases/tag/v1.7.5) (p) | 2021-01-26T09:53:05Z | 409 | 205 | 454 | 1,068 |
| [v1.7.4](https://github.com/laurent22/joplin/releases/tag/v1.7.4) (p) | 2021-01-22T17:58:38Z | 695 | 204 | 625 | 1,524 |
| [v1.6.8](https://github.com/laurent22/joplin/releases/tag/v1.6.8) | 2021-01-20T18:11:34Z | 20,873 | 7,702 | 7,605 | 36,180 |
| [v1.6.8](https://github.com/laurent22/joplin/releases/tag/v1.6.8) | 2021-01-20T18:11:34Z | 21,011 | 7,704 | 7,607 | 36,322 |
| [v1.7.3](https://github.com/laurent22/joplin/releases/tag/v1.7.3) (p) | 2021-01-20T11:23:50Z | 349 | 77 | 442 | 868 |
| [v1.6.7](https://github.com/laurent22/joplin/releases/tag/v1.6.7) | 2021-01-11T23:20:33Z | 12,696 | 4,637 | 4,543 | 21,876 |
| [v1.6.6](https://github.com/laurent22/joplin/releases/tag/v1.6.6) | 2021-01-09T16:15:31Z | 12,706 | 3,417 | 4,794 | 20,917 |
| [v1.6.5](https://github.com/laurent22/joplin/releases/tag/v1.6.5) (p) | 2021-01-09T01:24:32Z | 2,322 | 77 | 308 | 2,707 |
| [v1.6.7](https://github.com/laurent22/joplin/releases/tag/v1.6.7) | 2021-01-11T23:20:33Z | 12,818 | 4,639 | 4,545 | 22,002 |
| [v1.6.6](https://github.com/laurent22/joplin/releases/tag/v1.6.6) | 2021-01-09T16:15:31Z | 12,712 | 3,419 | 4,797 | 20,928 |
| [v1.6.5](https://github.com/laurent22/joplin/releases/tag/v1.6.5) (p) | 2021-01-09T01:24:32Z | 2,426 | 77 | 308 | 2,811 |
| [v1.6.4](https://github.com/laurent22/joplin/releases/tag/v1.6.4) (p) | 2021-01-07T19:11:32Z | 392 | 78 | 204 | 674 |
| [v1.6.2](https://github.com/laurent22/joplin/releases/tag/v1.6.2) (p) | 2021-01-04T22:34:55Z | 673 | 228 | 590 | 1,491 |
| [v1.5.14](https://github.com/laurent22/joplin/releases/tag/v1.5.14) | 2020-12-30T01:48:46Z | 13,175 | 5,206 | 5,529 | 23,910 |
| [v1.5.14](https://github.com/laurent22/joplin/releases/tag/v1.5.14) | 2020-12-30T01:48:46Z | 13,300 | 5,210 | 5,531 | 24,041 |
| [v1.6.1](https://github.com/laurent22/joplin/releases/tag/v1.6.1) (p) | 2020-12-29T19:37:45Z | 171 | 38 | 168 | 377 |
| [v1.5.13](https://github.com/laurent22/joplin/releases/tag/v1.5.13) | 2020-12-29T18:29:15Z | 646 | 219 | 203 | 1,068 |
| [v1.5.12](https://github.com/laurent22/joplin/releases/tag/v1.5.12) | 2020-12-28T15:14:08Z | 2,417 | 1,769 | 923 | 5,109 |
| [v1.5.11](https://github.com/laurent22/joplin/releases/tag/v1.5.11) | 2020-12-27T19:54:07Z | 14,175 | 4,631 | 4,280 | 23,086 |
| [v1.5.13](https://github.com/laurent22/joplin/releases/tag/v1.5.13) | 2020-12-29T18:29:15Z | 652 | 222 | 205 | 1,079 |
| [v1.5.12](https://github.com/laurent22/joplin/releases/tag/v1.5.12) | 2020-12-28T15:14:08Z | 2,424 | 1,774 | 925 | 5,123 |
| [v1.5.11](https://github.com/laurent22/joplin/releases/tag/v1.5.11) | 2020-12-27T19:54:07Z | 14,182 | 4,634 | 4,282 | 23,098 |
| [v1.5.10](https://github.com/laurent22/joplin/releases/tag/v1.5.10) (p) | 2020-12-26T12:35:36Z | 294 | 107 | 270 | 671 |
| [v1.5.9](https://github.com/laurent22/joplin/releases/tag/v1.5.9) (p) | 2020-12-23T18:01:08Z | 327 | 372 | 411 | 1,110 |
| [v1.5.8](https://github.com/laurent22/joplin/releases/tag/v1.5.8) (p) | 2020-12-20T09:45:19Z | 566 | 165 | 644 | 1,375 |
| [v1.5.7](https://github.com/laurent22/joplin/releases/tag/v1.5.7) (p) | 2020-12-10T12:58:33Z | 889 | 254 | 994 | 2,137 |
| [v1.5.4](https://github.com/laurent22/joplin/releases/tag/v1.5.4) (p) | 2020-12-05T12:07:49Z | 693 | 167 | 635 | 1,495 |
| [v1.4.19](https://github.com/laurent22/joplin/releases/tag/v1.4.19) | 2020-12-01T11:11:16Z | 27,929 | 13,531 | 11,679 | 53,139 |
| [v1.4.18](https://github.com/laurent22/joplin/releases/tag/v1.4.18) | 2020-11-28T12:21:41Z | 11,544 | 3,885 | 3,142 | 18,571 |
| [v1.4.16](https://github.com/laurent22/joplin/releases/tag/v1.4.16) | 2020-11-27T19:40:16Z | 1,493 | 833 | 601 | 2,927 |
| [v1.4.15](https://github.com/laurent22/joplin/releases/tag/v1.4.15) | 2020-11-27T13:25:43Z | 909 | 487 | 276 | 1,672 |
| [v1.4.12](https://github.com/laurent22/joplin/releases/tag/v1.4.12) | 2020-11-23T18:58:07Z | 3,057 | 1,334 | 1,308 | 5,699 |
| [v1.4.11](https://github.com/laurent22/joplin/releases/tag/v1.4.11) (p) | 2020-11-19T23:06:51Z | 3,078 | 161 | 595 | 3,834 |
| [v1.4.10](https://github.com/laurent22/joplin/releases/tag/v1.4.10) (p) | 2020-11-14T09:53:15Z | 647 | 198 | 686 | 1,531 |
| [v1.4.19](https://github.com/laurent22/joplin/releases/tag/v1.4.19) | 2020-12-01T11:11:16Z | 28,051 | 13,536 | 11,682 | 53,269 |
| [v1.4.18](https://github.com/laurent22/joplin/releases/tag/v1.4.18) | 2020-11-28T12:21:41Z | 11,556 | 3,887 | 3,144 | 18,587 |
| [v1.4.16](https://github.com/laurent22/joplin/releases/tag/v1.4.16) | 2020-11-27T19:40:16Z | 1,500 | 836 | 603 | 2,939 |
| [v1.4.15](https://github.com/laurent22/joplin/releases/tag/v1.4.15) | 2020-11-27T13:25:43Z | 919 | 489 | 278 | 1,686 |
| [v1.4.12](https://github.com/laurent22/joplin/releases/tag/v1.4.12) | 2020-11-23T18:58:07Z | 3,066 | 1,336 | 1,310 | 5,712 |
| [v1.4.11](https://github.com/laurent22/joplin/releases/tag/v1.4.11) (p) | 2020-11-19T23:06:51Z | 3,189 | 161 | 595 | 3,945 |
| [v1.4.10](https://github.com/laurent22/joplin/releases/tag/v1.4.10) (p) | 2020-11-14T09:53:15Z | 648 | 198 | 686 | 1,532 |
| [v1.4.9](https://github.com/laurent22/joplin/releases/tag/v1.4.9) (p) | 2020-11-11T14:23:17Z | 839 | 144 | 404 | 1,387 |
| [v1.4.7](https://github.com/laurent22/joplin/releases/tag/v1.4.7) (p) | 2020-11-07T18:23:29Z | 525 | 175 | 517 | 1,217 |
| [v1.3.18](https://github.com/laurent22/joplin/releases/tag/v1.3.18) | 2020-11-06T12:07:02Z | 33,178 | 11,343 | 10,521 | 55,042 |
| [v1.3.17](https://github.com/laurent22/joplin/releases/tag/v1.3.17) (p) | 2020-11-06T11:35:15Z | 50 | 28 | 26 | 104 |
| [v1.4.6](https://github.com/laurent22/joplin/releases/tag/v1.4.6) (p) | 2020-11-05T22:44:12Z | 667 | 96 | 55 | 818 |
| [v1.3.15](https://github.com/laurent22/joplin/releases/tag/v1.3.15) | 2020-11-04T12:22:50Z | 2,587 | 1,303 | 849 | 4,739 |
| [v1.3.11](https://github.com/laurent22/joplin/releases/tag/v1.3.11) (p) | 2020-10-31T13:22:20Z | 701 | 190 | 484 | 1,375 |
| [v1.4.7](https://github.com/laurent22/joplin/releases/tag/v1.4.7) (p) | 2020-11-07T18:23:29Z | 526 | 176 | 517 | 1,219 |
| [v1.3.18](https://github.com/laurent22/joplin/releases/tag/v1.3.18) | 2020-11-06T12:07:02Z | 33,316 | 11,345 | 10,522 | 55,183 |
| [v1.3.17](https://github.com/laurent22/joplin/releases/tag/v1.3.17) (p) | 2020-11-06T11:35:15Z | 52 | 28 | 26 | 106 |
| [v1.4.6](https://github.com/laurent22/joplin/releases/tag/v1.4.6) (p) | 2020-11-05T22:44:12Z | 668 | 97 | 55 | 820 |
| [v1.3.15](https://github.com/laurent22/joplin/releases/tag/v1.3.15) | 2020-11-04T12:22:50Z | 2,597 | 1,306 | 851 | 4,754 |
| [v1.3.11](https://github.com/laurent22/joplin/releases/tag/v1.3.11) (p) | 2020-10-31T13:22:20Z | 703 | 190 | 484 | 1,377 |
| [v1.3.10](https://github.com/laurent22/joplin/releases/tag/v1.3.10) (p) | 2020-10-29T13:27:14Z | 380 | 119 | 319 | 818 |
| [v1.3.9](https://github.com/laurent22/joplin/releases/tag/v1.3.9) (p) | 2020-10-23T16:04:26Z | 841 | 247 | 636 | 1,724 |
| [v1.3.8](https://github.com/laurent22/joplin/releases/tag/v1.3.8) (p) | 2020-10-21T18:46:29Z | 524 | 121 | 333 | 978 |
| [v1.3.9](https://github.com/laurent22/joplin/releases/tag/v1.3.9) (p) | 2020-10-23T16:04:26Z | 843 | 247 | 636 | 1,726 |
| [v1.3.8](https://github.com/laurent22/joplin/releases/tag/v1.3.8) (p) | 2020-10-21T18:46:29Z | 525 | 121 | 333 | 979 |
| [v1.3.7](https://github.com/laurent22/joplin/releases/tag/v1.3.7) (p) | 2020-10-20T11:35:55Z | 298 | 89 | 345 | 732 |
| [v1.3.5](https://github.com/laurent22/joplin/releases/tag/v1.3.5) (p) | 2020-10-17T14:26:35Z | 475 | 137 | 409 | 1,021 |
| [v1.3.3](https://github.com/laurent22/joplin/releases/tag/v1.3.3) (p) | 2020-10-17T10:56:57Z | 123 | 50 | 36 | 209 |
| [v1.3.2](https://github.com/laurent22/joplin/releases/tag/v1.3.2) (p) | 2020-10-11T20:39:49Z | 672 | 187 | 571 | 1,430 |
| [v1.3.1](https://github.com/laurent22/joplin/releases/tag/v1.3.1) (p) | 2020-10-11T15:10:18Z | 86 | 56 | 47 | 189 |
| [v1.2.6](https://github.com/laurent22/joplin/releases/tag/v1.2.6) | 2020-10-09T13:56:59Z | 46,980 | 17,750 | 14,053 | 78,783 |
| [v1.3.1](https://github.com/laurent22/joplin/releases/tag/v1.3.1) (p) | 2020-10-11T15:10:18Z | 87 | 56 | 47 | 190 |
| [v1.2.6](https://github.com/laurent22/joplin/releases/tag/v1.2.6) | 2020-10-09T13:56:59Z | 47,134 | 17,750 | 14,053 | 78,937 |
| [v1.2.4](https://github.com/laurent22/joplin/releases/tag/v1.2.4) (p) | 2020-09-30T07:34:29Z | 823 | 252 | 802 | 1,877 |
| [v1.2.3](https://github.com/laurent22/joplin/releases/tag/v1.2.3) (p) | 2020-09-29T15:13:02Z | 223 | 69 | 84 | 376 |
| [v1.2.2](https://github.com/laurent22/joplin/releases/tag/v1.2.2) (p) | 2020-09-22T20:31:55Z | 1,113 | 210 | 642 | 1,965 |
| [v1.1.4](https://github.com/laurent22/joplin/releases/tag/v1.1.4) | 2020-09-21T11:20:09Z | 27,972 | 13,516 | 7,758 | 49,246 |
| [v1.2.2](https://github.com/laurent22/joplin/releases/tag/v1.2.2) (p) | 2020-09-22T20:31:55Z | 1,113 | 211 | 642 | 1,966 |
| [v1.1.4](https://github.com/laurent22/joplin/releases/tag/v1.1.4) | 2020-09-21T11:20:09Z | 27,996 | 13,516 | 7,758 | 49,270 |
| [v1.1.3](https://github.com/laurent22/joplin/releases/tag/v1.1.3) (p) | 2020-09-17T10:30:37Z | 577 | 156 | 468 | 1,201 |
| [v1.1.2](https://github.com/laurent22/joplin/releases/tag/v1.1.2) (p) | 2020-09-15T12:58:38Z | 383 | 123 | 256 | 762 |
| [v1.1.1](https://github.com/laurent22/joplin/releases/tag/v1.1.1) (p) | 2020-09-11T23:32:47Z | 539 | 203 | 355 | 1,097 |
| [v1.0.245](https://github.com/laurent22/joplin/releases/tag/v1.0.245) | 2020-09-09T12:56:10Z | 22,401 | 10,021 | 5,650 | 38,072 |
| [v1.0.242](https://github.com/laurent22/joplin/releases/tag/v1.0.242) | 2020-09-04T22:00:34Z | 12,836 | 6,429 | 3,027 | 22,292 |
| [v1.0.241](https://github.com/laurent22/joplin/releases/tag/v1.0.241) | 2020-09-04T18:06:00Z | 26,273 | 5,935 | 5,117 | 37,325 |
| [v1.0.239](https://github.com/laurent22/joplin/releases/tag/v1.0.239) (p) | 2020-09-01T21:56:36Z | 928 | 234 | 407 | 1,569 |
| [v1.0.237](https://github.com/laurent22/joplin/releases/tag/v1.0.237) (p) | 2020-08-29T15:38:04Z | 596 | 932 | 345 | 1,873 |
| [v1.0.245](https://github.com/laurent22/joplin/releases/tag/v1.0.245) | 2020-09-09T12:56:10Z | 22,428 | 10,021 | 5,650 | 38,099 |
| [v1.0.242](https://github.com/laurent22/joplin/releases/tag/v1.0.242) | 2020-09-04T22:00:34Z | 12,844 | 6,429 | 3,027 | 22,300 |
| [v1.0.241](https://github.com/laurent22/joplin/releases/tag/v1.0.241) | 2020-09-04T18:06:00Z | 26,296 | 5,944 | 5,117 | 37,357 |
| [v1.0.239](https://github.com/laurent22/joplin/releases/tag/v1.0.239) (p) | 2020-09-01T21:56:36Z | 931 | 234 | 407 | 1,572 |
| [v1.0.237](https://github.com/laurent22/joplin/releases/tag/v1.0.237) (p) | 2020-08-29T15:38:04Z | 596 | 933 | 345 | 1,874 |
| [v1.0.236](https://github.com/laurent22/joplin/releases/tag/v1.0.236) (p) | 2020-08-28T09:16:54Z | 322 | 120 | 110 | 552 |
| [v1.0.235](https://github.com/laurent22/joplin/releases/tag/v1.0.235) (p) | 2020-08-18T22:08:01Z | 2,005 | 498 | 928 | 3,431 |
| [v1.0.234](https://github.com/laurent22/joplin/releases/tag/v1.0.234) (p) | 2020-08-17T23:13:02Z | 620 | 133 | 107 | 860 |
| [v1.0.233](https://github.com/laurent22/joplin/releases/tag/v1.0.233) | 2020-08-01T14:51:15Z | 45,732 | 18,209 | 12,367 | 76,308 |
| [v1.0.235](https://github.com/laurent22/joplin/releases/tag/v1.0.235) (p) | 2020-08-18T22:08:01Z | 2,005 | 499 | 928 | 3,432 |
| [v1.0.234](https://github.com/laurent22/joplin/releases/tag/v1.0.234) (p) | 2020-08-17T23:13:02Z | 622 | 134 | 107 | 863 |
| [v1.0.233](https://github.com/laurent22/joplin/releases/tag/v1.0.233) | 2020-08-01T14:51:15Z | 45,875 | 18,209 | 12,367 | 76,451 |
| [v1.0.232](https://github.com/laurent22/joplin/releases/tag/v1.0.232) (p) | 2020-07-28T22:34:40Z | 661 | 231 | 186 | 1,078 |
| [v1.0.227](https://github.com/laurent22/joplin/releases/tag/v1.0.227) | 2020-07-07T20:44:54Z | 41,306 | 15,290 | 9,647 | 66,243 |
| [v1.0.226](https://github.com/laurent22/joplin/releases/tag/v1.0.226) (p) | 2020-07-04T10:21:26Z | 4,927 | 2,261 | 694 | 7,882 |
| [v1.0.224](https://github.com/laurent22/joplin/releases/tag/v1.0.224) | 2020-06-20T22:26:08Z | 24,974 | 11,015 | 6,014 | 42,003 |
| [v1.0.227](https://github.com/laurent22/joplin/releases/tag/v1.0.227) | 2020-07-07T20:44:54Z | 41,337 | 15,290 | 9,647 | 66,274 |
| [v1.0.226](https://github.com/laurent22/joplin/releases/tag/v1.0.226) (p) | 2020-07-04T10:21:26Z | 4,929 | 2,261 | 694 | 7,884 |
| [v1.0.224](https://github.com/laurent22/joplin/releases/tag/v1.0.224) | 2020-06-20T22:26:08Z | 24,992 | 11,015 | 6,014 | 42,021 |
| [v1.0.223](https://github.com/laurent22/joplin/releases/tag/v1.0.223) (p) | 2020-06-20T11:51:27Z | 194 | 122 | 85 | 401 |
| [v1.0.221](https://github.com/laurent22/joplin/releases/tag/v1.0.221) (p) | 2020-06-20T01:44:20Z | 862 | 215 | 218 | 1,295 |
| [v1.0.220](https://github.com/laurent22/joplin/releases/tag/v1.0.220) | 2020-06-13T18:26:22Z | 32,582 | 9,934 | 6,424 | 48,940 |
| [v1.0.218](https://github.com/laurent22/joplin/releases/tag/v1.0.218) | 2020-06-07T10:43:34Z | 14,561 | 6,983 | 3,131 | 24,675 |
| [v1.0.221](https://github.com/laurent22/joplin/releases/tag/v1.0.221) (p) | 2020-06-20T01:44:20Z | 862 | 216 | 218 | 1,296 |
| [v1.0.220](https://github.com/laurent22/joplin/releases/tag/v1.0.220) | 2020-06-13T18:26:22Z | 32,636 | 9,935 | 6,424 | 48,995 |
| [v1.0.218](https://github.com/laurent22/joplin/releases/tag/v1.0.218) | 2020-06-07T10:43:34Z | 14,564 | 6,983 | 3,132 | 24,679 |
| [v1.0.217](https://github.com/laurent22/joplin/releases/tag/v1.0.217) (p) | 2020-06-06T15:17:27Z | 234 | 105 | 62 | 401 |
| [v1.0.216](https://github.com/laurent22/joplin/releases/tag/v1.0.216) | 2020-05-24T14:21:01Z | 39,493 | 14,306 | 10,191 | 63,990 |
| [v1.0.214](https://github.com/laurent22/joplin/releases/tag/v1.0.214) (p) | 2020-05-21T17:15:15Z | 6,730 | 3,478 | 771 | 10,979 |
| [v1.0.212](https://github.com/laurent22/joplin/releases/tag/v1.0.212) (p) | 2020-05-21T07:48:39Z | 219 | 77 | 55 | 351 |
| [v1.0.211](https://github.com/laurent22/joplin/releases/tag/v1.0.211) (p) | 2020-05-20T08:59:16Z | 309 | 141 | 94 | 544 |
| [v1.0.209](https://github.com/laurent22/joplin/releases/tag/v1.0.209) (p) | 2020-05-17T18:32:51Z | 1,400 | 861 | 154 | 2,415 |
| [v1.0.216](https://github.com/laurent22/joplin/releases/tag/v1.0.216) | 2020-05-24T14:21:01Z | 39,639 | 14,307 | 10,191 | 64,137 |
| [v1.0.214](https://github.com/laurent22/joplin/releases/tag/v1.0.214) (p) | 2020-05-21T17:15:15Z | 6,748 | 3,479 | 771 | 10,998 |
| [v1.0.212](https://github.com/laurent22/joplin/releases/tag/v1.0.212) (p) | 2020-05-21T07:48:39Z | 220 | 77 | 55 | 352 |
| [v1.0.211](https://github.com/laurent22/joplin/releases/tag/v1.0.211) (p) | 2020-05-20T08:59:16Z | 309 | 142 | 94 | 545 |
| [v1.0.209](https://github.com/laurent22/joplin/releases/tag/v1.0.209) (p) | 2020-05-17T18:32:51Z | 1,400 | 861 | 155 | 2,416 |
| [v1.0.207](https://github.com/laurent22/joplin/releases/tag/v1.0.207) (p) | 2020-05-10T16:37:35Z | 1,206 | 272 | 1,024 | 2,502 |
| [v1.0.201](https://github.com/laurent22/joplin/releases/tag/v1.0.201) | 2020-04-15T22:55:13Z | 54,261 | 20,059 | 18,188 | 92,508 |
| [v1.0.200](https://github.com/laurent22/joplin/releases/tag/v1.0.200) | 2020-04-12T12:17:46Z | 9,574 | 4,899 | 1,909 | 16,382 |
| [v1.0.199](https://github.com/laurent22/joplin/releases/tag/v1.0.199) | 2020-04-10T18:41:58Z | 19,606 | 5,896 | 3,798 | 29,300 |
| [v1.0.197](https://github.com/laurent22/joplin/releases/tag/v1.0.197) | 2020-03-30T17:21:22Z | 23,077 | 9,720 | 6,212 | 39,009 |
| [v1.0.195](https://github.com/laurent22/joplin/releases/tag/v1.0.195) | 2020-03-22T19:56:12Z | 19,112 | 7,956 | 4,512 | 31,580 |
| [v1.0.194](https://github.com/laurent22/joplin/releases/tag/v1.0.194) (p) | 2020-03-14T00:00:32Z | 1,292 | 1,391 | 523 | 3,206 |
| [v1.0.193](https://github.com/laurent22/joplin/releases/tag/v1.0.193) | 2020-03-08T08:58:53Z | 28,743 | 10,924 | 7,421 | 47,088 |
| [v1.0.192](https://github.com/laurent22/joplin/releases/tag/v1.0.192) (p) | 2020-03-06T23:27:52Z | 488 | 129 | 95 | 712 |
| [v1.0.201](https://github.com/laurent22/joplin/releases/tag/v1.0.201) | 2020-04-15T22:55:13Z | 54,264 | 20,059 | 18,188 | 92,511 |
| [v1.0.200](https://github.com/laurent22/joplin/releases/tag/v1.0.200) | 2020-04-12T12:17:46Z | 9,576 | 4,899 | 1,909 | 16,384 |
| [v1.0.199](https://github.com/laurent22/joplin/releases/tag/v1.0.199) | 2020-04-10T18:41:58Z | 19,616 | 5,896 | 3,798 | 29,310 |
| [v1.0.197](https://github.com/laurent22/joplin/releases/tag/v1.0.197) | 2020-03-30T17:21:22Z | 23,123 | 9,733 | 6,235 | 39,091 |
| [v1.0.195](https://github.com/laurent22/joplin/releases/tag/v1.0.195) | 2020-03-22T19:56:12Z | 19,115 | 7,957 | 4,512 | 31,584 |
| [v1.0.194](https://github.com/laurent22/joplin/releases/tag/v1.0.194) (p) | 2020-03-14T00:00:32Z | 1,292 | 1,391 | 524 | 3,207 |
| [v1.0.193](https://github.com/laurent22/joplin/releases/tag/v1.0.193) | 2020-03-08T08:58:53Z | 28,746 | 10,924 | 7,421 | 47,091 |
| [v1.0.192](https://github.com/laurent22/joplin/releases/tag/v1.0.192) (p) | 2020-03-06T23:27:52Z | 488 | 130 | 95 | 713 |
| [v1.0.190](https://github.com/laurent22/joplin/releases/tag/v1.0.190) (p) | 2020-03-06T01:22:22Z | 390 | 99 | 92 | 581 |
| [v1.0.189](https://github.com/laurent22/joplin/releases/tag/v1.0.189) (p) | 2020-03-04T17:27:15Z | 359 | 102 | 102 | 563 |
| [v1.0.187](https://github.com/laurent22/joplin/releases/tag/v1.0.187) (p) | 2020-03-01T12:31:06Z | 931 | 242 | 279 | 1,452 |
| [v1.0.179](https://github.com/laurent22/joplin/releases/tag/v1.0.179) | 2020-01-24T22:42:41Z | 71,441 | 28,799 | 22,566 | 122,806 |
| [v1.0.178](https://github.com/laurent22/joplin/releases/tag/v1.0.178) | 2020-01-20T19:06:45Z | 17,606 | 5,971 | 2,596 | 26,173 |
| [v1.0.177](https://github.com/laurent22/joplin/releases/tag/v1.0.177) (p) | 2019-12-30T14:40:40Z | 1,960 | 445 | 713 | 3,118 |
| [v1.0.176](https://github.com/laurent22/joplin/releases/tag/v1.0.176) (p) | 2019-12-14T10:36:44Z | 3,130 | 2,541 | 475 | 6,146 |
| [v1.0.175](https://github.com/laurent22/joplin/releases/tag/v1.0.175) | 2019-12-08T11:48:47Z | 73,522 | 16,968 | 16,589 | 107,079 |
| [v1.0.174](https://github.com/laurent22/joplin/releases/tag/v1.0.174) | 2019-11-12T18:20:58Z | 30,588 | 11,750 | 8,233 | 50,571 |
| [v1.0.173](https://github.com/laurent22/joplin/releases/tag/v1.0.173) | 2019-11-11T08:33:35Z | 5,105 | 2,088 | 752 | 7,945 |
| [v1.0.170](https://github.com/laurent22/joplin/releases/tag/v1.0.170) | 2019-10-13T22:13:04Z | 27,680 | 8,776 | 7,686 | 44,142 |
| [v1.0.169](https://github.com/laurent22/joplin/releases/tag/v1.0.169) | 2019-09-27T18:35:13Z | 17,183 | 5,928 | 3,759 | 26,870 |
| [v1.0.168](https://github.com/laurent22/joplin/releases/tag/v1.0.168) | 2019-09-25T21:21:38Z | 5,339 | 2,280 | 722 | 8,341 |
| [v1.0.167](https://github.com/laurent22/joplin/releases/tag/v1.0.167) | 2019-09-10T08:48:37Z | 16,837 | 5,712 | 3,708 | 26,257 |
| [v1.0.166](https://github.com/laurent22/joplin/releases/tag/v1.0.166) | 2019-09-09T17:35:54Z | 1,965 | 567 | 240 | 2,772 |
| [v1.0.165](https://github.com/laurent22/joplin/releases/tag/v1.0.165) | 2019-08-14T21:46:29Z | 19,052 | 6,986 | 5,471 | 31,509 |
| [v1.0.161](https://github.com/laurent22/joplin/releases/tag/v1.0.161) | 2019-07-13T18:30:00Z | 19,325 | 6,358 | 4,141 | 29,824 |
| [v1.0.160](https://github.com/laurent22/joplin/releases/tag/v1.0.160) | 2019-06-15T00:21:40Z | 30,681 | 7,763 | 8,110 | 46,554 |
| [v1.0.159](https://github.com/laurent22/joplin/releases/tag/v1.0.159) | 2019-06-08T00:00:19Z | 5,204 | 2,186 | 1,157 | 8,547 |
| [v1.0.158](https://github.com/laurent22/joplin/releases/tag/v1.0.158) | 2019-05-27T19:01:18Z | 9,829 | 3,554 | 1,941 | 15,324 |
| [v1.0.157](https://github.com/laurent22/joplin/releases/tag/v1.0.157) | 2019-05-26T17:55:53Z | 2,186 | 851 | 297 | 3,334 |
| [v1.0.153](https://github.com/laurent22/joplin/releases/tag/v1.0.153) (p) | 2019-05-15T06:27:29Z | 857 | 109 | 111 | 1,077 |
| [v1.0.152](https://github.com/laurent22/joplin/releases/tag/v1.0.152) | 2019-05-13T09:08:07Z | 13,883 | 4,442 | 4,066 | 22,391 |
| [v1.0.189](https://github.com/laurent22/joplin/releases/tag/v1.0.189) (p) | 2020-03-04T17:27:15Z | 360 | 102 | 103 | 565 |
| [v1.0.187](https://github.com/laurent22/joplin/releases/tag/v1.0.187) (p) | 2020-03-01T12:31:06Z | 931 | 243 | 279 | 1,453 |
| [v1.0.179](https://github.com/laurent22/joplin/releases/tag/v1.0.179) | 2020-01-24T22:42:41Z | 71,456 | 28,814 | 22,566 | 122,836 |
| [v1.0.178](https://github.com/laurent22/joplin/releases/tag/v1.0.178) | 2020-01-20T19:06:45Z | 17,606 | 5,971 | 2,598 | 26,175 |
| [v1.0.177](https://github.com/laurent22/joplin/releases/tag/v1.0.177) (p) | 2019-12-30T14:40:40Z | 1,961 | 445 | 714 | 3,120 |
| [v1.0.176](https://github.com/laurent22/joplin/releases/tag/v1.0.176) (p) | 2019-12-14T10:36:44Z | 3,130 | 2,541 | 476 | 6,147 |
| [v1.0.175](https://github.com/laurent22/joplin/releases/tag/v1.0.175) | 2019-12-08T11:48:47Z | 73,527 | 16,968 | 16,589 | 107,084 |
| [v1.0.174](https://github.com/laurent22/joplin/releases/tag/v1.0.174) | 2019-11-12T18:20:58Z | 30,596 | 11,756 | 8,234 | 50,586 |
| [v1.0.173](https://github.com/laurent22/joplin/releases/tag/v1.0.173) | 2019-11-11T08:33:35Z | 5,106 | 2,088 | 753 | 7,947 |
| [v1.0.170](https://github.com/laurent22/joplin/releases/tag/v1.0.170) | 2019-10-13T22:13:04Z | 27,687 | 8,782 | 7,689 | 44,158 |
| [v1.0.169](https://github.com/laurent22/joplin/releases/tag/v1.0.169) | 2019-09-27T18:35:13Z | 17,184 | 5,929 | 3,759 | 26,872 |
| [v1.0.168](https://github.com/laurent22/joplin/releases/tag/v1.0.168) | 2019-09-25T21:21:38Z | 5,339 | 2,281 | 722 | 8,342 |
| [v1.0.167](https://github.com/laurent22/joplin/releases/tag/v1.0.167) | 2019-09-10T08:48:37Z | 16,839 | 5,712 | 3,710 | 26,261 |
| [v1.0.166](https://github.com/laurent22/joplin/releases/tag/v1.0.166) | 2019-09-09T17:35:54Z | 1,965 | 568 | 240 | 2,773 |
| [v1.0.165](https://github.com/laurent22/joplin/releases/tag/v1.0.165) | 2019-08-14T21:46:29Z | 19,052 | 6,988 | 5,471 | 31,511 |
| [v1.0.161](https://github.com/laurent22/joplin/releases/tag/v1.0.161) | 2019-07-13T18:30:00Z | 19,327 | 6,358 | 4,142 | 29,827 |
| [v1.0.160](https://github.com/laurent22/joplin/releases/tag/v1.0.160) | 2019-06-15T00:21:40Z | 30,686 | 7,764 | 8,110 | 46,560 |
| [v1.0.159](https://github.com/laurent22/joplin/releases/tag/v1.0.159) | 2019-06-08T00:00:19Z | 5,205 | 2,186 | 1,162 | 8,553 |
| [v1.0.158](https://github.com/laurent22/joplin/releases/tag/v1.0.158) | 2019-05-27T19:01:18Z | 9,831 | 3,555 | 1,942 | 15,328 |
| [v1.0.157](https://github.com/laurent22/joplin/releases/tag/v1.0.157) | 2019-05-26T17:55:53Z | 2,188 | 851 | 297 | 3,336 |
| [v1.0.153](https://github.com/laurent22/joplin/releases/tag/v1.0.153) (p) | 2019-05-15T06:27:29Z | 858 | 110 | 112 | 1,080 |
| [v1.0.152](https://github.com/laurent22/joplin/releases/tag/v1.0.152) | 2019-05-13T09:08:07Z | 13,885 | 4,442 | 4,067 | 22,394 |
| [v1.0.151](https://github.com/laurent22/joplin/releases/tag/v1.0.151) | 2019-05-12T15:14:32Z | 1,962 | 542 | 964 | 3,468 |
| [v1.0.150](https://github.com/laurent22/joplin/releases/tag/v1.0.150) | 2019-05-12T11:27:48Z | 433 | 144 | 77 | 654 |
| [v1.0.148](https://github.com/laurent22/joplin/releases/tag/v1.0.148) (p) | 2019-05-08T19:12:24Z | 136 | 62 | 100 | 298 |
| [v1.0.145](https://github.com/laurent22/joplin/releases/tag/v1.0.145) | 2019-05-03T09:16:53Z | 7,017 | 2,867 | 1,443 | 11,327 |
| [v1.0.143](https://github.com/laurent22/joplin/releases/tag/v1.0.143) | 2019-04-22T10:51:38Z | 11,926 | 3,559 | 2,788 | 18,273 |
| [v1.0.142](https://github.com/laurent22/joplin/releases/tag/v1.0.142) | 2019-04-02T16:44:51Z | 14,765 | 4,574 | 4,735 | 24,074 |
| [v1.0.140](https://github.com/laurent22/joplin/releases/tag/v1.0.140) | 2019-03-10T20:59:58Z | 13,645 | 4,180 | 3,384 | 21,209 |
| [v1.0.139](https://github.com/laurent22/joplin/releases/tag/v1.0.139) (p) | 2019-03-09T10:06:48Z | 128 | 71 | 53 | 252 |
| [v1.0.138](https://github.com/laurent22/joplin/releases/tag/v1.0.138) (p) | 2019-03-03T17:23:00Z | 158 | 95 | 89 | 342 |
| [v1.0.137](https://github.com/laurent22/joplin/releases/tag/v1.0.137) (p) | 2019-03-03T01:12:51Z | 596 | 64 | 89 | 749 |
| [v1.0.145](https://github.com/laurent22/joplin/releases/tag/v1.0.145) | 2019-05-03T09:16:53Z | 7,017 | 2,868 | 1,443 | 11,328 |
| [v1.0.143](https://github.com/laurent22/joplin/releases/tag/v1.0.143) | 2019-04-22T10:51:38Z | 11,926 | 3,560 | 2,788 | 18,274 |
| [v1.0.142](https://github.com/laurent22/joplin/releases/tag/v1.0.142) | 2019-04-02T16:44:51Z | 14,766 | 4,574 | 4,736 | 24,076 |
| [v1.0.140](https://github.com/laurent22/joplin/releases/tag/v1.0.140) | 2019-03-10T20:59:58Z | 13,645 | 4,181 | 3,384 | 21,210 |
| [v1.0.139](https://github.com/laurent22/joplin/releases/tag/v1.0.139) (p) | 2019-03-09T10:06:48Z | 129 | 71 | 53 | 253 |
| [v1.0.138](https://github.com/laurent22/joplin/releases/tag/v1.0.138) (p) | 2019-03-03T17:23:00Z | 159 | 96 | 89 | 344 |
| [v1.0.137](https://github.com/laurent22/joplin/releases/tag/v1.0.137) (p) | 2019-03-03T01:12:51Z | 597 | 64 | 89 | 750 |
| [v1.0.135](https://github.com/laurent22/joplin/releases/tag/v1.0.135) | 2019-02-27T23:36:57Z | 12,636 | 3,965 | 4,084 | 20,685 |
| [v1.0.134](https://github.com/laurent22/joplin/releases/tag/v1.0.134) | 2019-02-27T10:21:44Z | 1,475 | 575 | 224 | 2,274 |
| [v1.0.134](https://github.com/laurent22/joplin/releases/tag/v1.0.134) | 2019-02-27T10:21:44Z | 1,476 | 576 | 224 | 2,276 |
| [v1.0.132](https://github.com/laurent22/joplin/releases/tag/v1.0.132) | 2019-02-26T23:02:05Z | 1,095 | 459 | 100 | 1,654 |
| [v1.0.127](https://github.com/laurent22/joplin/releases/tag/v1.0.127) | 2019-02-14T23:12:48Z | 9,883 | 3,179 | 2,937 | 15,999 |
| [v1.0.126](https://github.com/laurent22/joplin/releases/tag/v1.0.126) (p) | 2019-02-09T19:46:16Z | 938 | 80 | 122 | 1,140 |
| [v1.0.125](https://github.com/laurent22/joplin/releases/tag/v1.0.125) | 2019-01-26T18:14:33Z | 10,296 | 3,565 | 1,708 | 15,569 |
| [v1.0.120](https://github.com/laurent22/joplin/releases/tag/v1.0.120) | 2019-01-10T21:42:53Z | 15,626 | 5,214 | 6,524 | 27,364 |
| [v1.0.127](https://github.com/laurent22/joplin/releases/tag/v1.0.127) | 2019-02-14T23:12:48Z | 9,886 | 3,179 | 2,937 | 16,002 |
| [v1.0.126](https://github.com/laurent22/joplin/releases/tag/v1.0.126) (p) | 2019-02-09T19:46:16Z | 940 | 80 | 122 | 1,142 |
| [v1.0.125](https://github.com/laurent22/joplin/releases/tag/v1.0.125) | 2019-01-26T18:14:33Z | 10,299 | 3,565 | 1,709 | 15,573 |
| [v1.0.120](https://github.com/laurent22/joplin/releases/tag/v1.0.120) | 2019-01-10T21:42:53Z | 15,626 | 5,214 | 6,525 | 27,365 |
| [v1.0.119](https://github.com/laurent22/joplin/releases/tag/v1.0.119) | 2018-12-18T12:40:22Z | 8,913 | 3,270 | 2,020 | 14,203 |
| [v1.0.118](https://github.com/laurent22/joplin/releases/tag/v1.0.118) | 2019-01-11T08:34:13Z | 723 | 256 | 94 | 1,073 |
| [v1.0.117](https://github.com/laurent22/joplin/releases/tag/v1.0.117) | 2018-11-24T12:05:24Z | 16,269 | 4,904 | 6,387 | 27,560 |
| [v1.0.116](https://github.com/laurent22/joplin/releases/tag/v1.0.116) | 2018-11-20T19:09:24Z | 3,831 | 1,130 | 719 | 5,680 |
| [v1.0.117](https://github.com/laurent22/joplin/releases/tag/v1.0.117) | 2018-11-24T12:05:24Z | 16,270 | 4,904 | 6,387 | 27,561 |
| [v1.0.116](https://github.com/laurent22/joplin/releases/tag/v1.0.116) | 2018-11-20T19:09:24Z | 3,876 | 1,130 | 719 | 5,725 |
| [v1.0.115](https://github.com/laurent22/joplin/releases/tag/v1.0.115) | 2018-11-16T16:52:02Z | 3,663 | 1,310 | 807 | 5,780 |
| [v1.0.114](https://github.com/laurent22/joplin/releases/tag/v1.0.114) | 2018-10-24T20:14:10Z | 11,401 | 3,509 | 3,836 | 18,746 |
| [v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 12,178 | 3,354 | 3,688 | 19,220 |
| [v1.0.114](https://github.com/laurent22/joplin/releases/tag/v1.0.114) | 2018-10-24T20:14:10Z | 11,402 | 3,510 | 3,836 | 18,748 |
| [v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 12,185 | 3,361 | 3,688 | 19,234 |
| [v1.0.110](https://github.com/laurent22/joplin/releases/tag/v1.0.110) | 2018-09-29T12:29:21Z | 967 | 419 | 124 | 1,510 |
| [v1.0.109](https://github.com/laurent22/joplin/releases/tag/v1.0.109) | 2018-09-27T18:01:41Z | 2,110 | 713 | 337 | 3,160 |
| [v1.0.108](https://github.com/laurent22/joplin/releases/tag/v1.0.108) (p) | 2018-09-29T18:49:29Z | 36 | 28 | 21 | 85 |
| [v1.0.107](https://github.com/laurent22/joplin/releases/tag/v1.0.107) | 2018-09-16T19:51:07Z | 7,161 | 2,144 | 1,717 | 11,022 |
| [v1.0.106](https://github.com/laurent22/joplin/releases/tag/v1.0.106) | 2018-09-08T15:23:40Z | 4,564 | 1,463 | 323 | 6,350 |
| [v1.0.105](https://github.com/laurent22/joplin/releases/tag/v1.0.105) | 2018-09-05T11:29:36Z | 4,661 | 1,596 | 1,463 | 7,720 |
| [v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 15,076 | 4,710 | 7,371 | 27,157 |
| [v1.0.108](https://github.com/laurent22/joplin/releases/tag/v1.0.108) (p) | 2018-09-29T18:49:29Z | 37 | 29 | 22 | 88 |
| [v1.0.107](https://github.com/laurent22/joplin/releases/tag/v1.0.107) | 2018-09-16T19:51:07Z | 7,161 | 2,145 | 1,717 | 11,023 |
| [v1.0.106](https://github.com/laurent22/joplin/releases/tag/v1.0.106) | 2018-09-08T15:23:40Z | 4,565 | 1,464 | 324 | 6,353 |
| [v1.0.105](https://github.com/laurent22/joplin/releases/tag/v1.0.105) | 2018-09-05T11:29:36Z | 4,663 | 1,598 | 1,463 | 7,724 |
| [v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 15,078 | 4,710 | 7,371 | 27,159 |
| [v1.0.103](https://github.com/laurent22/joplin/releases/tag/v1.0.103) | 2018-06-21T19:38:13Z | 2,060 | 896 | 685 | 3,641 |
| [v1.0.101](https://github.com/laurent22/joplin/releases/tag/v1.0.101) | 2018-06-17T18:35:11Z | 1,316 | 615 | 415 | 2,346 |
| [v1.0.100](https://github.com/laurent22/joplin/releases/tag/v1.0.100) | 2018-06-14T17:41:43Z | 893 | 440 | 252 | 1,585 |
| [v1.0.99](https://github.com/laurent22/joplin/releases/tag/v1.0.99) | 2018-06-10T13:18:23Z | 1,261 | 605 | 386 | 2,252 |
| [v1.0.97](https://github.com/laurent22/joplin/releases/tag/v1.0.97) | 2018-06-09T19:23:34Z | 320 | 163 | 66 | 549 |
| [v1.0.99](https://github.com/laurent22/joplin/releases/tag/v1.0.99) | 2018-06-10T13:18:23Z | 1,262 | 605 | 386 | 2,253 |
| [v1.0.97](https://github.com/laurent22/joplin/releases/tag/v1.0.97) | 2018-06-09T19:23:34Z | 321 | 163 | 66 | 550 |
| [v1.0.96](https://github.com/laurent22/joplin/releases/tag/v1.0.96) | 2018-05-26T16:36:39Z | 2,729 | 1,232 | 1,708 | 5,669 |
| [v1.0.95](https://github.com/laurent22/joplin/releases/tag/v1.0.95) | 2018-05-25T13:04:30Z | 425 | 226 | 130 | 781 |
| [v1.0.94](https://github.com/laurent22/joplin/releases/tag/v1.0.94) | 2018-05-21T20:52:59Z | 1,139 | 594 | 407 | 2,140 |
| [v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1,796 | 1,255 | 768 | 3,819 |
| [v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) | 2018-05-10T14:48:04Z | 832 | 561 | 319 | 1,712 |
| [v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 501 | 242 | 121 | 864 |
| [v1.0.95](https://github.com/laurent22/joplin/releases/tag/v1.0.95) | 2018-05-25T13:04:30Z | 426 | 226 | 130 | 782 |
| [v1.0.94](https://github.com/laurent22/joplin/releases/tag/v1.0.94) | 2018-05-21T20:52:59Z | 1,139 | 595 | 407 | 2,141 |
| [v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1,798 | 1,257 | 768 | 3,823 |
| [v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) | 2018-05-10T14:48:04Z | 833 | 562 | 319 | 1,714 |
| [v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 501 | 243 | 122 | 866 |
| [v1.0.85](https://github.com/laurent22/joplin/releases/tag/v1.0.85) | 2018-05-01T21:08:24Z | 1,658 | 960 | 643 | 3,261 |
| [v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 5,457 | 2,540 | 2,668 | 10,665 |
| [v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 697 | 415 | 132 | 1,244 |
| [v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 5,466 | 2,540 | 2,668 | 10,674 |
| [v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 710 | 415 | 132 | 1,257 |
| [v1.0.81](https://github.com/laurent22/joplin/releases/tag/v1.0.81) | 2018-03-28T08:13:58Z | 1,006 | 607 | 793 | 2,406 |
| [v1.0.79](https://github.com/laurent22/joplin/releases/tag/v1.0.79) | 2018-03-23T18:00:11Z | 935 | 546 | 393 | 1,874 |
| [v1.0.78](https://github.com/laurent22/joplin/releases/tag/v1.0.78) | 2018-03-17T15:27:18Z | 1,316 | 903 | 881 | 3,100 |
| [v1.0.77](https://github.com/laurent22/joplin/releases/tag/v1.0.77) | 2018-03-16T15:12:35Z | 182 | 111 | 54 | 347 |
| [v1.0.79](https://github.com/laurent22/joplin/releases/tag/v1.0.79) | 2018-03-23T18:00:11Z | 935 | 547 | 394 | 1,876 |
| [v1.0.78](https://github.com/laurent22/joplin/releases/tag/v1.0.78) | 2018-03-17T15:27:18Z | 1,316 | 905 | 881 | 3,102 |
| [v1.0.77](https://github.com/laurent22/joplin/releases/tag/v1.0.77) | 2018-03-16T15:12:35Z | 182 | 111 | 55 | 348 |
| [v1.0.72](https://github.com/laurent22/joplin/releases/tag/v1.0.72) | 2018-03-14T09:44:35Z | 415 | 266 | 65 | 746 |
| [v1.0.70](https://github.com/laurent22/joplin/releases/tag/v1.0.70) | 2018-02-28T20:04:30Z | 1,861 | 1,059 | 1,263 | 4,183 |
| [v1.0.67](https://github.com/laurent22/joplin/releases/tag/v1.0.67) | 2018-02-19T22:51:08Z | 1,820 | 615 | 0 | 2,435 |
| [v1.0.66](https://github.com/laurent22/joplin/releases/tag/v1.0.66) | 2018-02-18T23:09:09Z | 332 | 143 | 91 | 566 |
| [v1.0.65](https://github.com/laurent22/joplin/releases/tag/v1.0.65) | 2018-02-17T20:02:25Z | 197 | 135 | 139 | 471 |
| [v1.0.64](https://github.com/laurent22/joplin/releases/tag/v1.0.64) | 2018-02-16T00:58:20Z | 1,089 | 551 | 1,130 | 2,770 |
| [v1.0.63](https://github.com/laurent22/joplin/releases/tag/v1.0.63) | 2018-02-14T19:40:36Z | 306 | 168 | 98 | 572 |
| [v1.0.62](https://github.com/laurent22/joplin/releases/tag/v1.0.62) | 2018-02-12T20:19:58Z | 571 | 308 | 377 | 1,256 |
| [v0.10.61](https://github.com/laurent22/joplin/releases/tag/v0.10.61) | 2018-02-08T18:27:39Z | 975 | 642 | 969 | 2,586 |
| [v1.0.70](https://github.com/laurent22/joplin/releases/tag/v1.0.70) | 2018-02-28T20:04:30Z | 1,863 | 1,059 | 1,263 | 4,185 |
| [v1.0.67](https://github.com/laurent22/joplin/releases/tag/v1.0.67) | 2018-02-19T22:51:08Z | 1,822 | 615 | 0 | 2,437 |
| [v1.0.66](https://github.com/laurent22/joplin/releases/tag/v1.0.66) | 2018-02-18T23:09:09Z | 333 | 143 | 92 | 568 |
| [v1.0.65](https://github.com/laurent22/joplin/releases/tag/v1.0.65) | 2018-02-17T20:02:25Z | 198 | 137 | 139 | 474 |
| [v1.0.64](https://github.com/laurent22/joplin/releases/tag/v1.0.64) | 2018-02-16T00:58:20Z | 1,090 | 551 | 1,130 | 2,771 |
| [v1.0.63](https://github.com/laurent22/joplin/releases/tag/v1.0.63) | 2018-02-14T19:40:36Z | 309 | 168 | 98 | 575 |
| [v1.0.62](https://github.com/laurent22/joplin/releases/tag/v1.0.62) | 2018-02-12T20:19:58Z | 573 | 309 | 378 | 1,260 |
| [v0.10.61](https://github.com/laurent22/joplin/releases/tag/v0.10.61) | 2018-02-08T18:27:39Z | 977 | 644 | 969 | 2,590 |
| [v0.10.60](https://github.com/laurent22/joplin/releases/tag/v0.10.60) | 2018-02-06T13:09:56Z | 727 | 530 | 558 | 1,815 |
| [v0.10.54](https://github.com/laurent22/joplin/releases/tag/v0.10.54) | 2018-01-31T20:21:30Z | 1,824 | 1,468 | 330 | 3,622 |
| [v0.10.52](https://github.com/laurent22/joplin/releases/tag/v0.10.52) | 2018-01-31T19:25:18Z | 51 | 642 | 23 | 716 |
| [v0.10.51](https://github.com/laurent22/joplin/releases/tag/v0.10.51) | 2018-01-28T18:47:02Z | 1,332 | 1,608 | 334 | 3,274 |
| [v0.10.48](https://github.com/laurent22/joplin/releases/tag/v0.10.48) | 2018-01-23T11:19:51Z | 1,968 | 1,760 | 38 | 3,766 |
| [v0.10.47](https://github.com/laurent22/joplin/releases/tag/v0.10.47) | 2018-01-16T17:27:17Z | 1,234 | 1,279 | 73 | 2,586 |
| [v0.10.54](https://github.com/laurent22/joplin/releases/tag/v0.10.54) | 2018-01-31T20:21:30Z | 1,826 | 1,468 | 330 | 3,624 |
| [v0.10.52](https://github.com/laurent22/joplin/releases/tag/v0.10.52) | 2018-01-31T19:25:18Z | 53 | 642 | 23 | 718 |
| [v0.10.51](https://github.com/laurent22/joplin/releases/tag/v0.10.51) | 2018-01-28T18:47:02Z | 1,334 | 1,609 | 334 | 3,277 |
| [v0.10.48](https://github.com/laurent22/joplin/releases/tag/v0.10.48) | 2018-01-23T11:19:51Z | 1,969 | 1,760 | 38 | 3,767 |
| [v0.10.47](https://github.com/laurent22/joplin/releases/tag/v0.10.47) | 2018-01-16T17:27:17Z | 1,236 | 1,280 | 73 | 2,589 |
| [v0.10.43](https://github.com/laurent22/joplin/releases/tag/v0.10.43) | 2018-01-08T10:12:10Z | 3,446 | 2,365 | 1,215 | 7,026 |
| [v0.10.41](https://github.com/laurent22/joplin/releases/tag/v0.10.41) | 2018-01-05T20:38:12Z | 1,041 | 1,556 | 247 | 2,844 |
| [v0.10.40](https://github.com/laurent22/joplin/releases/tag/v0.10.40) | 2018-01-02T23:16:57Z | 1,599 | 1,796 | 344 | 3,739 |
| [v0.10.41](https://github.com/laurent22/joplin/releases/tag/v0.10.41) | 2018-01-05T20:38:12Z | 1,044 | 1,558 | 249 | 2,851 |
| [v0.10.40](https://github.com/laurent22/joplin/releases/tag/v0.10.40) | 2018-01-02T23:16:57Z | 1,599 | 1,797 | 344 | 3,740 |
| [v0.10.39](https://github.com/laurent22/joplin/releases/tag/v0.10.39) | 2017-12-11T21:19:44Z | 5,930 | 4,399 | 3,295 | 13,624 |
| [v0.10.38](https://github.com/laurent22/joplin/releases/tag/v0.10.38) | 2017-12-08T10:12:06Z | 1,055 | 1,240 | 314 | 2,609 |
| [v0.10.37](https://github.com/laurent22/joplin/releases/tag/v0.10.37) | 2017-12-07T19:38:05Z | 272 | 858 | 91 | 1,221 |
| [v0.10.36](https://github.com/laurent22/joplin/releases/tag/v0.10.36) | 2017-12-05T09:34:40Z | 1,022 | 1,370 | 446 | 2,838 |
| [v0.10.35](https://github.com/laurent22/joplin/releases/tag/v0.10.35) | 2017-12-02T15:56:08Z | 1,583 | 1,558 | 752 | 3,893 |
| [v0.10.36](https://github.com/laurent22/joplin/releases/tag/v0.10.36) | 2017-12-05T09:34:40Z | 1,023 | 1,370 | 446 | 2,839 |
| [v0.10.35](https://github.com/laurent22/joplin/releases/tag/v0.10.35) | 2017-12-02T15:56:08Z | 1,583 | 1,559 | 752 | 3,894 |
| [v0.10.34](https://github.com/laurent22/joplin/releases/tag/v0.10.34) | 2017-12-02T14:50:28Z | 97 | 682 | 68 | 847 |
| [v0.10.33](https://github.com/laurent22/joplin/releases/tag/v0.10.33) | 2017-12-02T13:20:39Z | 68 | 673 | 33 | 774 |
| [v0.10.33](https://github.com/laurent22/joplin/releases/tag/v0.10.33) | 2017-12-02T13:20:39Z | 68 | 674 | 33 | 775 |
| [v0.10.31](https://github.com/laurent22/joplin/releases/tag/v0.10.31) | 2017-12-01T09:56:44Z | 899 | 1,466 | 416 | 2,781 |
| [v0.10.30](https://github.com/laurent22/joplin/releases/tag/v0.10.30) | 2017-11-30T20:28:16Z | 728 | 1,382 | 431 | 2,541 |
| [v0.10.28](https://github.com/laurent22/joplin/releases/tag/v0.10.28) | 2017-11-30T01:07:46Z | 1,363 | 1,715 | 886 | 3,964 |
| [v0.10.26](https://github.com/laurent22/joplin/releases/tag/v0.10.26) | 2017-11-29T16:02:17Z | 197 | 715 | 271 | 1,183 |
| [v0.10.25](https://github.com/laurent22/joplin/releases/tag/v0.10.25) | 2017-11-24T14:27:49Z | 155 | 709 | 6,646 | 7,510 |
| [v0.10.23](https://github.com/laurent22/joplin/releases/tag/v0.10.23) | 2017-11-21T19:38:41Z | 142 | 674 | 45 | 861 |
| [v0.10.22](https://github.com/laurent22/joplin/releases/tag/v0.10.22) | 2017-11-20T21:45:57Z | 93 | 661 | 31 | 785 |
| [v0.10.21](https://github.com/laurent22/joplin/releases/tag/v0.10.21) | 2017-11-18T00:53:15Z | 60 | 654 | 25 | 739 |
| [v0.10.20](https://github.com/laurent22/joplin/releases/tag/v0.10.20) | 2017-11-17T17:18:25Z | 50 | 664 | 34 | 748 |
| [v0.10.19](https://github.com/laurent22/joplin/releases/tag/v0.10.19) | 2017-11-20T18:59:48Z | 38 | 664 | 30 | 732 |
| [v0.10.30](https://github.com/laurent22/joplin/releases/tag/v0.10.30) | 2017-11-30T20:28:16Z | 731 | 1,385 | 434 | 2,550 |
| [v0.10.28](https://github.com/laurent22/joplin/releases/tag/v0.10.28) | 2017-11-30T01:07:46Z | 1,365 | 1,718 | 888 | 3,971 |
| [v0.10.26](https://github.com/laurent22/joplin/releases/tag/v0.10.26) | 2017-11-29T16:02:17Z | 199 | 717 | 273 | 1,189 |
| [v0.10.25](https://github.com/laurent22/joplin/releases/tag/v0.10.25) | 2017-11-24T14:27:49Z | 157 | 711 | 6,656 | 7,524 |
| [v0.10.23](https://github.com/laurent22/joplin/releases/tag/v0.10.23) | 2017-11-21T19:38:41Z | 144 | 678 | 47 | 869 |
| [v0.10.22](https://github.com/laurent22/joplin/releases/tag/v0.10.22) | 2017-11-20T21:45:57Z | 95 | 663 | 33 | 791 |
| [v0.10.21](https://github.com/laurent22/joplin/releases/tag/v0.10.21) | 2017-11-18T00:53:15Z | 62 | 656 | 28 | 746 |
| [v0.10.20](https://github.com/laurent22/joplin/releases/tag/v0.10.20) | 2017-11-17T17:18:25Z | 51 | 666 | 37 | 754 |
| [v0.10.19](https://github.com/laurent22/joplin/releases/tag/v0.10.19) | 2017-11-20T18:59:48Z | 40 | 667 | 33 | 740 |

View File

@@ -741,7 +741,7 @@ The following commands are available in [command-line mode](#command-line-mode):
# License
Copyright (c) 2016-2021 Laurent Cozic
Copyright (c) 2016-2023 Laurent Cozic
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@@ -4,13 +4,13 @@
"config:base"
],
"major": {
"stabilityDays": 30,
"stabilityDays": 80,
},
"minor": {
"stabilityDays": 20,
"stabilityDays": 40,
},
"patch": {
"stabilityDays": 10,
"stabilityDays": 20,
},
"prConcurrentLimit": 5,
"prHourlyLimit": 0,
@@ -38,6 +38,7 @@
"@codemirror/search",
"@codemirror/state",
"@codemirror/view",
"@lezer/highlight",
"@fortawesome/fontawesome-svg-core",
"@fortawesome/free-solid-svg-icons",
"@svgr/webpack",

566
yarn.lock

File diff suppressed because it is too large Load Diff