You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-12-17 23:27:48 +02:00
Compare commits
94 Commits
v2.11.1
...
desktop-sp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10468c912a | ||
|
|
a6d8478679 | ||
|
|
7f82501a19 | ||
|
|
4973f3c082 | ||
|
|
b83165f9e5 | ||
|
|
7706f9058b | ||
|
|
03222ba1b2 | ||
|
|
d4f49db342 | ||
|
|
40e1b0559e | ||
|
|
738f1decbb | ||
|
|
e5a364d052 | ||
|
|
357a3e2e7b | ||
|
|
af91fd99cc | ||
|
|
3855f60a0d | ||
|
|
079b379e7a | ||
|
|
e23e036677 | ||
|
|
b824ff5457 | ||
|
|
3669a1b5d6 | ||
|
|
b93f9aaf01 | ||
|
|
8679290206 | ||
|
|
4acec5c6c7 | ||
|
|
f1b03453a4 | ||
|
|
7972dd5556 | ||
|
|
4842500f0a | ||
|
|
84c7f28ec5 | ||
|
|
f3eea43d24 | ||
|
|
8babaddbcb | ||
|
|
13cdaabb17 | ||
|
|
a94aa21088 | ||
|
|
6116bed4e3 | ||
|
|
fabd0b4dda | ||
|
|
6b72f86e7b | ||
|
|
02cf546124 | ||
|
|
eecb012d64 | ||
|
|
04e9b40769 | ||
|
|
efdbaeb397 | ||
|
|
46425b920c | ||
|
|
f5be43c2ac | ||
|
|
080541a2fe | ||
|
|
7dc638edf4 | ||
|
|
3b686194d8 | ||
|
|
5c2640f88f | ||
|
|
eca0f92dff | ||
|
|
260fa6c038 | ||
|
|
8ec6bc9138 | ||
|
|
93fa92369b | ||
|
|
bc6c5ab7a7 | ||
|
|
1826625e4f | ||
|
|
20b8fb2719 | ||
|
|
f813e71b29 | ||
|
|
02422a6e31 | ||
|
|
69a34e87f3 | ||
|
|
cbeaa16b61 | ||
|
|
05917ac142 | ||
|
|
0c8de68b80 | ||
|
|
44d93d52d3 | ||
|
|
073bec9e8c | ||
|
|
e6a8c2bea5 | ||
|
|
81c316cd2c | ||
|
|
659c851960 | ||
|
|
572701d9a0 | ||
|
|
66ef37bd4e | ||
|
|
9ddf75604d | ||
|
|
3ed7e1d7e8 | ||
|
|
b2b412105a | ||
|
|
60a3c4f65e | ||
|
|
9645414c17 | ||
|
|
af0136ef39 | ||
|
|
b76586c4fd | ||
|
|
376e4ebde0 | ||
|
|
1439b8787f | ||
|
|
b8854a99be | ||
|
|
6cf02173dc | ||
|
|
4d8a53d8c9 | ||
|
|
7f43718e1d | ||
|
|
690ce637b1 | ||
|
|
4d023e679e | ||
|
|
6e220a978f | ||
|
|
39757cd90e | ||
|
|
5ccbbea757 | ||
|
|
309222c082 | ||
|
|
50f5fe2c91 | ||
|
|
eacae83182 | ||
|
|
403d770b1d | ||
|
|
a481bf1b53 | ||
|
|
0d32570c9e | ||
|
|
f017e99b02 | ||
|
|
a89d64d435 | ||
|
|
3a27086534 | ||
|
|
413c1e41b5 | ||
|
|
8b879464b8 | ||
|
|
97c9bbc1fe | ||
|
|
e5bebef7b2 | ||
|
|
73752c4b3f |
@@ -396,6 +396,7 @@ packages/app-mobile/components/NoteEditor/NoteEditor.js
|
||||
packages/app-mobile/components/NoteEditor/SearchPanel.js
|
||||
packages/app-mobile/components/NoteEditor/SelectionFormatting.js
|
||||
packages/app-mobile/components/NoteEditor/types.js
|
||||
packages/app-mobile/components/NoteList.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileEditor.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.js
|
||||
packages/app-mobile/components/ProfileSwitcher/useProfileConfig.js
|
||||
@@ -405,6 +406,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
|
||||
@@ -710,6 +712,7 @@ packages/lib/services/searchengine/SearchFilter.test.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/filterParser.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
|
||||
packages/lib/services/searchengine/queryBuilder.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/ShareService.test.js
|
||||
@@ -871,6 +874,8 @@ packages/tools/website/updateDownloadPage.js
|
||||
packages/tools/website/updateNews.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/applyTranslations.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/convertLinksToLocale.test.js
|
||||
packages/tools/website/utils/frontMatter.js
|
||||
packages/tools/website/utils/news.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
|
||||
4
.github/scripts/run_ci.sh
vendored
4
.github/scripts/run_ci.sh
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/build-android.yml
vendored
2
.github/workflows/build-android.yml
vendored
@@ -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
|
||||
|
||||
1
.github/workflows/cla.yml
vendored
1
.github/workflows/cla.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
CLAAssistant:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "CLA Assistant"
|
||||
|
||||
1
.github/workflows/close-stale-issues.yml
vendored
1
.github/workflows/close-stale-issues.yml
vendored
@@ -6,6 +6,7 @@ permissions:
|
||||
issues: write
|
||||
jobs:
|
||||
ProcessStaleIssues:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v4
|
||||
|
||||
10
.github/workflows/github-actions-main.yml
vendored
10
.github/workflows/github-actions-main.yml
vendored
@@ -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:
|
||||
@@ -70,7 +71,9 @@ jobs:
|
||||
- uses: olegtarasov/get-tag@v2.1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '18'
|
||||
# We need to pin the version to 18.15, because 18.16+ fails with this error:
|
||||
# https://github.com/facebook/react-native/issues/36440
|
||||
node-version: '18.15.0'
|
||||
|
||||
- name: Install Yarn
|
||||
run: |
|
||||
@@ -92,6 +95,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 +133,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:
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -383,6 +383,7 @@ packages/app-mobile/components/NoteEditor/NoteEditor.js
|
||||
packages/app-mobile/components/NoteEditor/SearchPanel.js
|
||||
packages/app-mobile/components/NoteEditor/SelectionFormatting.js
|
||||
packages/app-mobile/components/NoteEditor/types.js
|
||||
packages/app-mobile/components/NoteList.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileEditor.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.js
|
||||
packages/app-mobile/components/ProfileSwitcher/useProfileConfig.js
|
||||
@@ -392,6 +393,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
|
||||
@@ -697,6 +699,7 @@ packages/lib/services/searchengine/SearchFilter.test.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/filterParser.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
|
||||
packages/lib/services/searchengine/queryBuilder.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/ShareService.test.js
|
||||
@@ -858,6 +861,8 @@ packages/tools/website/updateDownloadPage.js
|
||||
packages/tools/website/updateNews.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/applyTranslations.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/convertLinksToLocale.test.js
|
||||
packages/tools/website/utils/frontMatter.js
|
||||
packages/tools/website/utils/news.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
|
||||
30
.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch
Normal file
30
.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch
Normal 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;
|
||||
@@ -657,6 +657,16 @@ footer .bottom-links-row p {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.language-switcher > button {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: #0557ba;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
WHAT'S NEW PAGE
|
||||
*****************************************************************/
|
||||
|
||||
7
Assets/WebsiteAssets/js/bootstrap5.0.2.bundle.min.js
vendored
Normal file
7
Assets/WebsiteAssets/js/bootstrap5.0.2.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5016
Assets/WebsiteAssets/js/bootstrap5.0.2.js
vendored
5016
Assets/WebsiteAssets/js/bootstrap5.0.2.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -421,7 +421,7 @@
|
||||
</div>
|
||||
|
||||
<script
|
||||
src="{{jsBaseUrl}}/bootstrap5.0.2.min.js"
|
||||
src="{{jsBaseUrl}}/bootstrap5.0.2.bundle.min.js"
|
||||
rel="preload"
|
||||
as="script"
|
||||
></script>
|
||||
|
||||
@@ -85,6 +85,11 @@ https://github.com/laurent22/joplin/blob/dev/{{{sourceMarkdownFile}}}
|
||||
{{> footer}}
|
||||
</div>
|
||||
|
||||
<script
|
||||
src="{{jsBaseUrl}}/bootstrap5.0.2.bundle.min.js"
|
||||
rel="preload"
|
||||
as="script"
|
||||
></script>
|
||||
<script src="{{{assetUrls.js.script}}}"></script>
|
||||
|
||||
{{> analytics}}
|
||||
|
||||
@@ -17,6 +17,21 @@
|
||||
<a href="{{baseUrl}}/help/" class="fw500">Help</a>
|
||||
<a href="{{forumUrl}}" class="fw500">Forum</a>
|
||||
<a href="{{baseUrl}}/cn/" class="fw500">中文</a>
|
||||
|
||||
<!--
|
||||
<div class="dropdown language-switcher">
|
||||
<button class="fw500" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Language
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
|
||||
<li><a class="dropdown-item" href="#">Action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Another action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Something else here</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
-->
|
||||
|
||||
|
||||
{{#showJoplinCloudLinks}}
|
||||
{{> joplinCloudButton}}
|
||||
{{/showJoplinCloudLinks}}
|
||||
|
||||
@@ -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&mtm_kwd=joplinapp&mtm_source=joplinapp-github&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&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&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)
|
||||
|
||||
7
bootstrap.bundle.min.js
vendored
Normal file
7
bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
54
gulpfile.js
54
gulpfile.js
@@ -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);
|
||||
}
|
||||
|
||||
15
package.json
15
package.json
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"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",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Joplin Web Clipper [DEV]",
|
||||
"version": "2.11.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'",
|
||||
|
||||
@@ -126,4 +126,4 @@
|
||||
"react-app"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,21 @@ export default class ElectronAppWrapper {
|
||||
return this.initialCallbackUrl_;
|
||||
}
|
||||
|
||||
private async createSplashScreen() {
|
||||
const splash = new BrowserWindow({
|
||||
width: 500,
|
||||
height: 300,
|
||||
transparent: true,
|
||||
frame: false,
|
||||
alwaysOnTop: true,
|
||||
});
|
||||
|
||||
await splash.loadFile('splash.html');
|
||||
splash.center();
|
||||
|
||||
return splash;
|
||||
}
|
||||
|
||||
public createWindow() {
|
||||
// Set to true to view errors if the application does not start
|
||||
const debugEarlyBugs = this.env_ === 'dev' || this.isDebugMode_;
|
||||
@@ -355,6 +370,12 @@ export default class ElectronAppWrapper {
|
||||
const alreadyRunning = this.ensureSingleInstance();
|
||||
if (alreadyRunning) return;
|
||||
|
||||
const splash = await this.createSplashScreen();
|
||||
|
||||
ipcMain.on('hide-splash', () => {
|
||||
splash.destroy();
|
||||
});
|
||||
|
||||
this.createWindow();
|
||||
|
||||
this.electronApp_.on('before-quit', () => {
|
||||
|
||||
@@ -45,6 +45,7 @@ import libCommands from '@joplin/lib/commands/index';
|
||||
import { homedir } from 'os';
|
||||
import getDefaultPluginsInfo from '@joplin/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo';
|
||||
const electronContextMenu = require('./services/electron-context-menu');
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
// import populateDatabase from '@joplin/lib/services/debug/populateDatabase';
|
||||
|
||||
const commands = mainScreenCommands
|
||||
@@ -489,6 +490,8 @@ class Application extends BaseApplication {
|
||||
void AlarmService.garbageCollect();
|
||||
}, 1000 * 60 * 60);
|
||||
|
||||
ipcRenderer.send('hide-splash');
|
||||
|
||||
if (Setting.value('startMinimized') && Setting.value('showTrayIcon')) {
|
||||
// Keep it hidden
|
||||
} else {
|
||||
|
||||
@@ -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>
|
||||
|
||||
11
packages/app-desktop/build/images/splash-image.svg
Normal file
11
packages/app-desktop/build/images/splash-image.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg id="joplin-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1980 1080" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" style="background-color:#043873">
|
||||
<style><![CDATA[
|
||||
#joplin-icon-s-g1 {animation: joplin-icon-s-g1_c_o 500ms linear 1 normal forwards}@keyframes joplin-icon-s-g1_c_o { 0% {opacity: 0} 100% {opacity: 1}}
|
||||
]]></style>
|
||||
<defs><linearGradient id="joplin-icon-u-path28-fill" x1="4753.95" y1="366.05" x2="366.04" y2="4753.96" spreadMethod="pad" gradientUnits="userSpaceOnUse" gradientTransform="translate(0 0)"><stop id="joplin-icon-u-path28-fill-0" offset="0%" stop-color="#004caf"/><stop id="joplin-icon-u-path28-fill-1" offset="100%" stop-color="#1f95f8"/></linearGradient></defs><g id="joplin-icon-s-g1" transform="translate(.000001 0)" opacity="0"><g id="joplin-icon-s-g2" transform="translate(89.731006 0)"><g id="joplin-icon-s-g3" transform="translate(37.781477 0)"><g id="joplin-icon-s-g4"><g id="joplin-icon-s-g5"><g id="joplin-icon-u-g10" transform="matrix(.8 0 0-.8 335.310601 744.8)"><g id="joplin-icon-u-g12" transform="matrix(.1 0 0 0.1 0 0)"><g id="joplin-icon-u-g14"><g id="joplin-icon-u-g16"><path id="joplin-icon-u-path28" d="M3873.89,0h-2627.78C560.754,0,0,560.75,0,1246.11v2627.77C0,4559.25,560.754,5120,1246.11,5120h2627.78C4559.25,5120,5120,4559.25,5120,3873.88v-2627.77C5120,560.75,4559.25,0,3873.89,0" fill="url(#joplin-icon-u-path28-fill)"/></g></g><path id="joplin-icon-u-path30" d="M3961.59,4435.23h-1391.41c-13.15,0-23.78-10.64-23.78-23.77v-441.84c0-14.87,12.04-26.92,26.92-26.92h190.77c77.16,0,139.73-59.35,146.43-134.77v-302.93-168.77-1607.48-11.39h-.05c.48-16.84-.19-33.4-1.83-49.71-.18-2.38-.5-4.73-.79-7.09-1.1-9.53-2.32-19.01-4.17-28.29-1.01-5.29-2.44-10.44-3.71-15.65-1.71-6.93-3.09-13.97-5.22-20.75-12.58-40.27-32.47-77.62-59.98-110.5-1.01-1.17-2.26-2.25-3.26-3.41-8.39-9.72-17.2-19.19-26.95-28.06-9.84-8.95-20.26-17.27-31.21-25-77.84-55.14-182.61-79.4-299.67-68.2-149.26,14.03-297.34,81.72-417.03,190.62-119.67,108.89-194.08,243.62-209.48,379.41-13.85,121.48,22.55,228.38,102.42,301.05.21.16.4.31.56.48c3.09,2.77,6.49,5.2,9.67,7.87c57.16,47.89,131.67,76.91,216.7,84.91.96.09,1.88.24,2.79.32c8.95.79,18.07,1.15,27.27,1.49c4.81.16,9.56.5,14.44.54c1.62.02,3.16.19,4.78.19c2.9,0,5.91-.38,8.81-.42c13.4-.21,26.9-.76,40.67-1.94c1.74-.14,3.4-.08,5.19-.24c1.27-.13,2.53-.41,3.8-.54c78-7.82,155.23-31.11,228.52-66.4c1.53-.07,3.3-.54,5.51-1.76c22.34-12.34,26.62.9,27.28,9.65v382.24v282.82c0,19.05-13.25,35.9-31.83,39.99-394.76,86.88-782.08-3.55-1055.38-252.34-238.75-217.18-354.24-530.58-316.82-859.79c33.39-293.23,183.91-574.94,423.88-793.33c233.89-212.79,531.69-345.86,838.88-374.801c42.33-3.918,84.86-5.938,126.36-5.938c293.38,0,565.61,100.598,766.54,283.379c190.34,173.3,304.35,411.27,321.08,670.16l1.55,1697.91h.17v453.97h.06v7.92c1.72,80.12,67.05,144.58,147.61,144.58h190.77c14.86,0,26.92,12.05,26.92,26.92v441.84c0,13.13-10.63,23.77-23.78,23.77" fill="#fff"/></g></g></g></g></g></g><text id="joplin-icon-s-text1" dx="0" dy="0" font-family=""joplin-icon:::Montserrat"" font-size="200" font-weight="500" transform="translate(993.43468 610.410935)" fill="#fff" stroke-width="0"><tspan id="joplin-icon-s-tspan1" y="0" font-weight="500" stroke-width="0"><![CDATA[
|
||||
Joplin
|
||||
]]></tspan></text></g>
|
||||
<style><![CDATA[
|
||||
@font-face {font-family: 'joplin-icon:::Montserrat';font-style: normal;font-weight: 500;src: url(data:font/ttf;charset=utf-8;base64,AAEAAAAQAQAABAAAR0RFRgBQABAAAAGcAAAALkdQT1OPgpfEAAADLAAAAMJHU1VCs4qylQAAA/AAAADUT1MvMndNXi0AAALMAAAAYFNUQVTlHMwkAAACNAAAAERjbWFwANwBewAAAngAAABUZ2FzcAAAABAAAAEUAAAACGdseWZFHfZ5AAAExAAAAkhoZWFkGBWy5wAAAfwAAAA2aGhlYQkaAhsAAAF4AAAAJGhtdHgSbwNBAAABzAAAAC5sb2NhA64DMAAAARwAAAAabWF4cAAgALYAAAE4AAAAIG5hbWUw7VuXAAAHDAAAAkpwb3N0/58AMgAAAVgAAAAgcHJlcGgGjIUAAAEMAAAAB7gB/4WwBI0AAAEAAf//AA8AAAAUADEAPQBJAFUAYQCHALkA9gD2AQ0BJAAAAAEAAAAMAFkABwBZAAkAAQAAAAAAAAAAAAAAAAADAAMAAwAAAAAAAP+cADIAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAADyP8FAAAGHv9W/OwF+QABAAAAAAAAAAAAAAAAAAAACwABAAIAHgAAAAAAAAAOAAEAAgAAAAwAAAAMAAEAAAACAAIAAQACAAEABAAIAAEAAAJLACgCAf/3ARcASwEXAFsBFwBQARcAWwKpAFsCewAqAqoAWwENAAAAAADxAOsAAAABAAAACAAAOP9XB18PPPUAAwPoAAAAANYL/kYAAAAA3ZxwxP9W/v0F+QP9AAAABgACAAAAAAAAAAEAAQAIAAIAAAAUAAIAAAAkAAJ3Z2h0AQAAAGl0YWwBEwABAAQAEAABAAAAAAEFAfQAAAADAAEAAgEUAAAAAAABAAAAAAACAAAAAwAAABQAAwABAAAAFAAEAEAAAAAMAAgAAgAEACAASgBpAGwAcP//AAAAIABKAGkAbABu////6f+3/5n/mf+YAAEAAAAAAAAAAAAAAAAABAJyAfQABQAAAooCWAAAAEsCigJYAAABXgAyATYAAAAAAAAAAAAAAACgAAL/QAAgewAAAAAAAAAAVUxBAADAAAD7AgPI/wUAAARVAQ4gAAGXAAAAAAIFArwAAAAgAAMAAQAAAAoAKgA4AANERkxUABRjeXJsABRsYXRuABQABAAAAAD//wABAAAAAWtlcm4ACAAAAAEAAAABAAQAAgAIAAEACAACAEIABAAAAGgAUgAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAIAAQACAAAABAAIAAIAAQABAAgABAADAAAAAgADAAIAAQACAAEAAQAIAAMAAAAAAAAABAABAAIAAgAAAAEAAAAKAHYAtAADREZMVABiY3lybABebGF0bgAUAAAABUFaRSAAQkNSVCAAOktBWiAAMlRBVCAAKlRSSyAAIgAA//8AAQAEAAD//wABAAMAAP//AAEAAgAA//8AAQABAAD//wABAAAAAAAAAAQAAAAA//8AAAAFbG9jbAA4bG9jbAAybG9jbAAsbG9jbAAmbG9jbAAgAAAAAQACAAAAAQABAAAAAQAAAAAAAQADAAAAAQAEAAUADAAMAAwADAAMAAEAAAABAAgAAQAGAAIAAQABAAIAAgAoAAACIwK8AAMABwAAMxEhESUhESEoAfv+VQFb/qUCvP1ERgIwAAH/9//4AZ4CvAAQAAAXIiYnNxYWMzI1ESM1IREUBsM+bCI6HUkseP0BYG8INDFEKCuOAYlX/iV1dP//AEsAAADMAvUCJgADAAAABwAL/18AAAABAFsAAAC7AhIAAwAAMxEzEVtgAhL97v//AFAAAADGAucCJgADAAAABwAK/18AAAABAFsAAAC7AuYAAwAAMxEzEVtgAub9GgABAFsAAAJSAhcAFgAAATIWFhURIxE0JiMiBgYVESMRMxUnNjYBdkFjOGBLRDNMKWBcDxpsAhcyZk7+zwEmTU4oTjr+7wISjyY0OgAAAgAq//oCUQIXAA8AHwAABSImJjU0NjYzMhYWFRQGBicyNjY1NCYmIyIGBhUUFhYBPlB8SEh8UE99R0d9TzNRLi5RMzNQMDBQBkZ7Tk96RUV5UE96RlQuVTg5Uy4uUzk4VS4AAAMAW/8+AoACFwAPABYAJgAABSImJjU0NjYzMhYWFRQGBgURMxUHFxETMjY2NTQmJiMiBgYVFBYWAXRCbUE/bUROeEZGeP6ZXAYKsTNRLy9RMzJRLy9RBj14Wlp4PER5UVF6RLwC1I97e/6xARAuVTg5Uy4uUzk4VS4AAQDxAnEBZwLnAAsAAAEiJjU0NjMyFhUUBgEsGSIiGRkiIgJxIhkZIiIZGSIAAAEA6wJ4AW0C9QALAAABIiY1NDYzMhYVFAYBLBwlJRwcJSQCeCQaGyQjGhslAAAAAAwAlgADAAEECQAAALABBAADAAEECQABACIA4gADAAEECQACAA4A1AADAAEECQADADYAngADAAEECQAEACIA4gADAAEECQAFABoAhAADAAEECQAGACIAYgADAAEECQAOADQALgADAAEECQEAAAwAIgADAAEECQEFAAwAFgADAAEECQETAAwACgADAAEECQEUAAoAAABSAG8AbQBhAG4ASQB0AGEAbABpAGMATQBlAGQAaQB1AG0AVwBlAGkAZwBoAHQAaAB0AHQAcAA6AC8ALwBzAGMAcgBpAHAAdABzAC4AcwBpAGwALgBvAHIAZwAvAE8ARgBMAE0AbwBuAHQAcwBlAHIAcgBhAHQALQBNAGUAZABpAHUAbQBWAGUAcgBzAGkAbwBuACAAOAAuADAAMAAwADgALgAwADAAMAA7AFUATABBADsATQBvAG4AdABzAGUAcgByAGEAdAAtAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIATQBvAG4AdABzAGUAcgByAGEAdAAgAE0AZQBkAGkAdQBtAEMAbwBwAHkAcgBpAGcAaAB0ACAAMgAwADEAMQAgAFQAaABlACAATQBvAG4AdABzAGUAcgByAGEAdAAgAFAAcgBvAGoAZQBjAHQAIABBAHUAdABoAG8AcgBzACAAKABoAHQAdABwAHMAOgAvAC8AZwBpAHQAaAB1AGIALgBjAG8AbQAvAEoAdQBsAGkAZQB0AGEAVQBsAGEALwBNAG8AbgB0AHMAZQByAHIAYQB0ACkAAA==) format('truetype');}
|
||||
]]></style>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
},
|
||||
"build": {
|
||||
"appId": "net.cozic.joplin-desktop",
|
||||
"compression": "maximum",
|
||||
"productName": "Joplin",
|
||||
"npmRebuild": false,
|
||||
"afterSign": "./tools/notarizeMacApp.js",
|
||||
@@ -79,9 +80,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": [
|
||||
{
|
||||
@@ -149,7 +148,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 +164,7 @@
|
||||
"react-datetime": "3.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-redux": "8.0.5",
|
||||
"react-select": "5.7.1",
|
||||
"react-select": "5.7.2",
|
||||
"react-toggle-button": "2.2.0",
|
||||
"react-tooltip": "4.5.1",
|
||||
"redux": "4.2.1",
|
||||
|
||||
12
packages/app-desktop/splash.html
Normal file
12
packages/app-desktop/splash.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>JoplinSplashScreen</title>
|
||||
</head>
|
||||
<body>
|
||||
<img src="./build/images/splash-image.svg" alt="joplin-icon">
|
||||
</body>
|
||||
</html>
|
||||
@@ -150,8 +150,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097685
|
||||
versionName "2.11.0"
|
||||
versionCode 2097687
|
||||
versionName "2.11.2"
|
||||
// ndk {
|
||||
// abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
// }
|
||||
|
||||
@@ -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.`;
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
const React = require('react');
|
||||
const Component = React.Component;
|
||||
const { connect } = require('react-redux');
|
||||
const { FlatList, Text, StyleSheet, Button, View } = require('react-native');
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { FlatList, Text, StyleSheet, Button, View } from 'react-native';
|
||||
import { FolderEntity, NoteEntity } from '@joplin/lib/services/database/types';
|
||||
import { AppState } from '../utils/types';
|
||||
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const { NoteItem } = require('./note-item.js');
|
||||
const time = require('@joplin/lib/time').default;
|
||||
const { themeStyle } = require('./global-style.js');
|
||||
|
||||
class NoteListComponent extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
interface NoteListProps {
|
||||
themeId: string;
|
||||
dispatch: (action: any)=> void;
|
||||
notesSource: string;
|
||||
items: NoteEntity[];
|
||||
folders: FolderEntity[];
|
||||
noteSelectionEnabled?: boolean;
|
||||
selectedFolderId?: string;
|
||||
}
|
||||
|
||||
class NoteListComponent extends Component<NoteListProps> {
|
||||
private rootRef_: FlatList;
|
||||
private styles_: Record<string, StyleSheet.NamedStyles<any>>;
|
||||
|
||||
public constructor(props: NoteListProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
items: [],
|
||||
@@ -21,7 +38,7 @@ class NoteListComponent extends Component {
|
||||
this.createNotebookButton_click = this.createNotebookButton_click.bind(this);
|
||||
}
|
||||
|
||||
styles() {
|
||||
private styles() {
|
||||
const themeId = this.props.themeId;
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
@@ -47,7 +64,7 @@ class NoteListComponent extends Component {
|
||||
return this.styles_[themeId];
|
||||
}
|
||||
|
||||
createNotebookButton_click() {
|
||||
private createNotebookButton_click() {
|
||||
this.props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Folder',
|
||||
@@ -55,34 +72,14 @@ class NoteListComponent extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
filterNotes(notes) {
|
||||
const todoFilter = 'all'; // Setting.value('todoFilter');
|
||||
if (todoFilter === 'all') return notes;
|
||||
|
||||
const now = time.unixMs();
|
||||
const maxInterval = 1000 * 60 * 60 * 24;
|
||||
const notRecentTime = now - maxInterval;
|
||||
|
||||
const output = [];
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
const note = notes[i];
|
||||
if (note.is_todo) {
|
||||
if (todoFilter === 'recent' && note.user_updated_time < notRecentTime && !!note.todo_completed) continue;
|
||||
if (todoFilter === 'nonCompleted' && !!note.todo_completed) continue;
|
||||
}
|
||||
output.push(note);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(newProps) {
|
||||
public UNSAFE_componentWillReceiveProps(newProps: NoteListProps) {
|
||||
// Make sure scroll position is reset when switching from one folder to another or to a tag list.
|
||||
if (this.rootRef_ && newProps.notesSource !== this.props.notesSource) {
|
||||
this.rootRef_.scrollToOffset({ offset: 0, animated: false });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
// `enableEmptySections` is to fix this warning: https://github.com/FaridSafi/react-native-gifted-listview/issues/39
|
||||
|
||||
if (this.props.items.length) {
|
||||
@@ -109,7 +106,7 @@ class NoteListComponent extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
const NoteList = connect(state => {
|
||||
const NoteList = connect((state: AppState) => {
|
||||
return {
|
||||
items: state.notes,
|
||||
folders: state.folders,
|
||||
@@ -119,4 +116,4 @@ const NoteList = connect(state => {
|
||||
};
|
||||
})(NoteListComponent);
|
||||
|
||||
module.exports = { NoteList };
|
||||
export default NoteList;
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
@@ -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', '');
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,7 +2,7 @@ const React = require('react');
|
||||
import { AppState as RNAppState, View, StyleSheet, NativeEventSubscription } from 'react-native';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
import { connect } from 'react-redux';
|
||||
const { NoteList } = require('../note-list.js');
|
||||
import NoteList from '../NoteList';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
import Tag from '@joplin/lib/models/Tag';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
@@ -254,7 +254,7 @@ class NotesScreenComponent extends BaseScreenComponent<any> {
|
||||
return (
|
||||
<View style={rootStyle}>
|
||||
<ScreenHeader title={iconString + title} showBackButton={false} parentComponent={thisComp} sortButton_press={this.sortButton_press} folderPickerOptions={this.folderPickerOptions()} showSearchButton={true} showSideMenuButton={true} />
|
||||
<NoteList style={this.styles().noteList} />
|
||||
<NoteList />
|
||||
{actionButtonComp}
|
||||
<DialogBox
|
||||
ref={(dialogbox: any) => {
|
||||
|
||||
@@ -324,11 +324,11 @@ 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
|
||||
@@ -720,9 +720,9 @@ SPEC CHECKSUMS:
|
||||
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: 9bd5238d3b43d76bbec64aa82c173ac20a4bce9f
|
||||
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"@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",
|
||||
"@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.3",
|
||||
"@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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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_);
|
||||
}
|
||||
|
||||
@@ -431,6 +431,7 @@ describe('services_SearchEngine', () => {
|
||||
['title:abcd efgh', { _: ['efgh'], title: ['abcd'] }],
|
||||
['title:abcd', { title: ['abcd'] }],
|
||||
['"abcd efgh"', { _: ['abcd efgh'] }],
|
||||
['"abcd efgh" ijkl', { _: ['abcd efgh', 'ijkl'] }],
|
||||
['title:abcd title:efgh', { title: ['abcd', 'efgh'] }],
|
||||
];
|
||||
|
||||
|
||||
@@ -5,20 +5,31 @@ import Note from '../../models/Note';
|
||||
import BaseModel from '../../BaseModel';
|
||||
import ItemChangeUtils from '../ItemChangeUtils';
|
||||
import shim from '../../shim';
|
||||
import filterParser from './filterParser';
|
||||
import filterParser, { Term } from './filterParser';
|
||||
import queryBuilder from './queryBuilder';
|
||||
import { ItemChangeEntity, NoteEntity } from '../database/types';
|
||||
const { sprintf } = require('sprintf-js');
|
||||
const { pregQuote, scriptType, removeDiacritics } = require('../../string-utils.js');
|
||||
|
||||
enum SearchType {
|
||||
Auto = 'auto',
|
||||
Basic = 'basic',
|
||||
Nonlatin = 'nonlatin',
|
||||
Fts = 'fts',
|
||||
}
|
||||
|
||||
interface SearchOptions {
|
||||
searchType: SearchType;
|
||||
}
|
||||
|
||||
export default class SearchEngine {
|
||||
|
||||
public static instance_: SearchEngine = null;
|
||||
public static relevantFields = 'id, title, body, user_created_time, user_updated_time, is_todo, todo_completed, todo_due, parent_id, latitude, longitude, altitude, source_url';
|
||||
public static SEARCH_TYPE_AUTO = 'auto';
|
||||
public static SEARCH_TYPE_BASIC = 'basic';
|
||||
public static SEARCH_TYPE_NONLATIN_SCRIPT = 'nonlatin';
|
||||
public static SEARCH_TYPE_FTS = 'fts';
|
||||
public static SEARCH_TYPE_AUTO = SearchType.Auto;
|
||||
public static SEARCH_TYPE_BASIC = SearchType.Basic;
|
||||
public static SEARCH_TYPE_NONLATIN_SCRIPT = SearchType.Nonlatin;
|
||||
public static SEARCH_TYPE_FTS = SearchType.Fts;
|
||||
|
||||
public dispatch: Function = (_o: any) => {};
|
||||
private logger_ = new Logger();
|
||||
@@ -417,7 +428,7 @@ export default class SearchEngine {
|
||||
|
||||
const trimQuotes = (str: string) => str.startsWith('"') ? str.substr(1, str.length - 2) : str;
|
||||
|
||||
let allTerms: any[] = [];
|
||||
let allTerms: Term[] = [];
|
||||
|
||||
try {
|
||||
allTerms = filterParser(query);
|
||||
@@ -429,7 +440,20 @@ export default class SearchEngine {
|
||||
const titleTerms = allTerms.filter(x => x.name === 'title' && !x.negated).map(x => trimQuotes(x.value));
|
||||
const bodyTerms = allTerms.filter(x => x.name === 'body' && !x.negated).map(x => trimQuotes(x.value));
|
||||
|
||||
const terms: any = { _: textTerms, 'title': titleTerms, 'body': bodyTerms };
|
||||
interface ComplexTerm {
|
||||
type: 'regex' | 'text';
|
||||
value: string;
|
||||
scriptType: any;
|
||||
valueRegex?: RegExp;
|
||||
}
|
||||
|
||||
interface Terms {
|
||||
_: (string | ComplexTerm)[];
|
||||
title: (string | ComplexTerm)[];
|
||||
body: (string | ComplexTerm)[];
|
||||
}
|
||||
|
||||
const terms: Terms = { _: textTerms, 'title': titleTerms, 'body': bodyTerms };
|
||||
|
||||
// Filter terms:
|
||||
// - Convert wildcards to regex
|
||||
@@ -438,7 +462,9 @@ export default class SearchEngine {
|
||||
|
||||
let termCount = 0;
|
||||
const keys = [];
|
||||
for (const col in terms) {
|
||||
for (const col2 in terms) {
|
||||
const col = col2 as '_' | 'title' | 'body';
|
||||
|
||||
if (!terms.hasOwnProperty(col)) continue;
|
||||
|
||||
if (!terms[col].length) {
|
||||
@@ -447,7 +473,7 @@ export default class SearchEngine {
|
||||
}
|
||||
|
||||
for (let i = terms[col].length - 1; i >= 0; i--) {
|
||||
const term = terms[col][i];
|
||||
const term = terms[col][i] as string;
|
||||
|
||||
// SQlLite FTS doesn't allow "*" queries and neither shall we
|
||||
if (term === '*') {
|
||||
@@ -468,12 +494,16 @@ export default class SearchEngine {
|
||||
}
|
||||
|
||||
//
|
||||
// The object "allTerms" is used for query construction purposes (this contains all the filter terms)
|
||||
// Since this is used for the FTS match query, we need to normalize text, title and body terms.
|
||||
// Note, we're not normalizing terms like tag because these are matched using SQL LIKE operator and so we must preserve their diacritics.
|
||||
// The object "allTerms" is used for query construction purposes (this
|
||||
// contains all the filter terms) Since this is used for the FTS match
|
||||
// query, we need to normalize text, title and body terms. Note, we're
|
||||
// not normalizing terms like tag because these are matched using SQL
|
||||
// LIKE operator and so we must preserve their diacritics.
|
||||
//
|
||||
// The object "terms" only include text, title, body terms and is used for highlighting.
|
||||
// By not normalizing the text, title, body in "terms", highlighting still works correctly for words with diacritics.
|
||||
// The object "terms" only include text, title, body terms and is used
|
||||
// for highlighting. By not normalizing the text, title, body in
|
||||
// "terms", highlighting still works correctly for words with
|
||||
// diacritics.
|
||||
//
|
||||
|
||||
allTerms = allTerms.map(x => {
|
||||
@@ -521,9 +551,9 @@ export default class SearchEngine {
|
||||
const searchOptions: any = {};
|
||||
|
||||
for (const key of parsedQuery.keys) {
|
||||
if (parsedQuery.terms[key].length === 0) continue;
|
||||
if ((parsedQuery.terms as any)[key].length === 0) continue;
|
||||
|
||||
const term = parsedQuery.terms[key].map((x: any) => x.value).join(' ');
|
||||
const term = (parsedQuery.terms as any)[key].map((x: Term) => x.value).join(' ');
|
||||
if (key === '_') searchOptions.anywherePattern = `*${term}*`;
|
||||
if (key === 'title') searchOptions.titlePattern = `*${term}*`;
|
||||
if (key === 'body') searchOptions.bodyPattern = `*${term}*`;
|
||||
@@ -561,12 +591,13 @@ export default class SearchEngine {
|
||||
return SearchEngine.SEARCH_TYPE_FTS;
|
||||
}
|
||||
|
||||
public async search(searchString: string, options: any = null) {
|
||||
public async search(searchString: string, options: SearchOptions = null) {
|
||||
if (!searchString) return [];
|
||||
|
||||
options = Object.assign({}, {
|
||||
options = {
|
||||
searchType: SearchEngine.SEARCH_TYPE_AUTO,
|
||||
}, options);
|
||||
...options,
|
||||
};
|
||||
|
||||
const searchType = this.determineSearchType_(searchString, options.searchType);
|
||||
const parsedQuery = await this.parseQuery(searchString);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
interface Term {
|
||||
export interface Term {
|
||||
name: string;
|
||||
value: string;
|
||||
negated: boolean;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import gotoAnythingStyleQuery from './gotoAnythingStyleQuery';
|
||||
|
||||
describe('searchengine/gotoAnythingStyleQuery', () => {
|
||||
|
||||
it('should prepare queries', () => {
|
||||
const testCases: [string, string][] = [
|
||||
['hello', 'hello*'],
|
||||
['hello welc', 'hello* welc*'],
|
||||
];
|
||||
|
||||
for (const [input, expected] of testCases) {
|
||||
const actual = gotoAnythingStyleQuery(input);
|
||||
expect(actual).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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}`;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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 = '';
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/tools": "~2.11",
|
||||
"@joplin/utils": "~2.11",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"gh-release-assets": "2.0.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"source-map-support": "0.5.21",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
@@ -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"
|
||||
|
||||
12
packages/tools/gulp/tasks/buildCommandIndexRun.js
Normal file
12
packages/tools/gulp/tasks/buildCommandIndexRun.js
Normal 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);
|
||||
});
|
||||
12
packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js
Normal file
12
packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js
Normal 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
@@ -23,11 +23,9 @@
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"@joplin/utils": "~2.11",
|
||||
"@types/node-fetch": "2.6.2",
|
||||
"@types/yargs": "17.0.20",
|
||||
"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"
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import { readFileSync, readFile, mkdirpSync, writeFileSync, remove, copy, pathExistsSync } from 'fs-extra';
|
||||
import { readFileSync, readFile, mkdirpSync, writeFileSync, remove, copy, pathExistsSync, pathExists } from 'fs-extra';
|
||||
import { rootDir } from '../tool-utils';
|
||||
import { pressCarouselItems } from './utils/pressCarousel';
|
||||
import { getMarkdownIt, loadMustachePartials, markdownToPageHtml, renderMustache } from './utils/render';
|
||||
import { AssetUrls, Env, Partials, PlanPageParams, TemplateParams } from './utils/types';
|
||||
import { AssetUrls, Env, Locale, Partials, PlanPageParams, TemplateParams } from './utils/types';
|
||||
import { createFeatureTableMd, getPlans, loadStripeConfig } from '@joplin/lib/utils/joplinCloud';
|
||||
import { stripOffFrontMatter } from './utils/frontMatter';
|
||||
import { dirname, basename } from 'path';
|
||||
import { readmeFileTitle, replaceGitHubByWebsiteLinks } from './utils/parser';
|
||||
import { extractOpenGraphTags } from './utils/openGraph';
|
||||
import { extractOpenGraphTags, OpenGraphTags } from './utils/openGraph';
|
||||
import { readCredentialFileJson } from '@joplin/lib/utils/credentialFiles';
|
||||
import { getNewsDateString } from './utils/news';
|
||||
import { parsePoFile, parseTranslations, Translations } from '../utils/translation';
|
||||
import { countryCodeOnly, setLocale } from '@joplin/lib/locale';
|
||||
import { setLocale } from '@joplin/lib/locale';
|
||||
import applyTranslations from './utils/applyTranslations';
|
||||
import { loadSponsors } from '../utils/loadSponsors';
|
||||
import convertLinksToLocale from './utils/convertLinksToLocale';
|
||||
|
||||
interface BuildConfig {
|
||||
env: Env;
|
||||
@@ -23,6 +24,12 @@ const buildConfig = readCredentialFileJson<BuildConfig>('website-build.json', {
|
||||
env: Env.Prod,
|
||||
});
|
||||
|
||||
const enGbLocale: Locale = {
|
||||
htmlTranslations: {},
|
||||
lang: 'en-gb',
|
||||
pathPrefix: '',
|
||||
};
|
||||
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const md5File = require('md5-file');
|
||||
@@ -41,7 +48,7 @@ const partialDir = `${websiteAssetDir}/templates/partials`;
|
||||
const discussLink = 'https://discourse.joplinapp.org/c/news/9';
|
||||
|
||||
let tocMd_: string = null;
|
||||
let tocHtml_: string = null;
|
||||
const tocHtml_: Record<string, string> = {};
|
||||
const tocRegex_ = /<!-- TOC -->([^]*)<!-- TOC -->/;
|
||||
function tocMd() {
|
||||
if (tocMd_) return tocMd_;
|
||||
@@ -61,15 +68,17 @@ async function getDonateLinks() {
|
||||
return `<div class="donate-links">\n\n${matches[1].trim()}\n\n</div>`;
|
||||
}
|
||||
|
||||
function tocHtml() {
|
||||
if (tocHtml_) return tocHtml_;
|
||||
function tocHtml(locale: Locale) {
|
||||
if (tocHtml_[locale.lang]) return tocHtml_[locale.lang];
|
||||
const markdownIt = getMarkdownIt();
|
||||
let md = tocMd();
|
||||
md = md.replace(/# Table of contents/, '');
|
||||
md = replaceGitHubByWebsiteLinks(md);
|
||||
tocHtml_ = markdownIt.render(md);
|
||||
tocHtml_ = `<div>${tocHtml_}</div>`;
|
||||
return tocHtml_;
|
||||
md = convertLinksToLocale(md, locale);
|
||||
let output = markdownIt.render(md);
|
||||
output = `<div>${output}</div>`;
|
||||
tocHtml_[locale.lang] = output;
|
||||
return output;
|
||||
}
|
||||
|
||||
const baseUrl = '';
|
||||
@@ -90,14 +99,16 @@ async function getAssetUrls(): Promise<AssetUrls> {
|
||||
};
|
||||
}
|
||||
|
||||
function defaultTemplateParams(assetUrls: AssetUrls): TemplateParams {
|
||||
function defaultTemplateParams(assetUrls: AssetUrls, locale: Locale = null): TemplateParams {
|
||||
if (!locale) locale = enGbLocale;
|
||||
|
||||
return {
|
||||
env: buildConfig.env,
|
||||
baseUrl,
|
||||
imageBaseUrl: `${baseUrl}/images`,
|
||||
cssBaseUrl,
|
||||
jsBaseUrl,
|
||||
tocHtml: tocHtml(),
|
||||
tocHtml: tocHtml(locale),
|
||||
yyyy: (new Date()).getFullYear().toString(),
|
||||
templateHtml: mainTemplateHtml,
|
||||
forumUrl: 'https://discourse.joplinapp.org/',
|
||||
@@ -109,6 +120,7 @@ function defaultTemplateParams(assetUrls: AssetUrls): TemplateParams {
|
||||
},
|
||||
assetUrls,
|
||||
openGraph: null,
|
||||
locale,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -117,7 +129,7 @@ function renderPageToHtml(md: string, targetPath: string, templateParams: Templa
|
||||
md = md.replace(/# Joplin\n/, '');
|
||||
|
||||
templateParams = {
|
||||
...defaultTemplateParams(templateParams.assetUrls),
|
||||
...defaultTemplateParams(templateParams.assetUrls, templateParams.locale),
|
||||
...templateParams,
|
||||
};
|
||||
|
||||
@@ -133,6 +145,7 @@ function renderPageToHtml(md: string, targetPath: string, templateParams: Templa
|
||||
}
|
||||
|
||||
md = replaceGitHubByWebsiteLinks(md);
|
||||
md = convertLinksToLocale(md, templateParams.locale);
|
||||
|
||||
if (templateParams.donateLinksMd) {
|
||||
md = `${templateParams.donateLinksMd}\n\n${md}`;
|
||||
@@ -161,8 +174,8 @@ function renderFileToHtml(sourcePath: string, targetPath: string, templateParams
|
||||
}
|
||||
}
|
||||
|
||||
function makeHomePageMd() {
|
||||
let md = readFileSync(`${rootDir}/README.md`, 'utf8');
|
||||
function makeHomePageMd(readmePath: string) {
|
||||
let md = readFileSync(readmePath, 'utf8');
|
||||
md = md.replace(tocRegex_, '');
|
||||
|
||||
// HACK: GitHub needs the \| or the inline code won't be displayed correctly inside the table,
|
||||
@@ -216,15 +229,20 @@ const updatePageLanguage = (html: string, lang: string): string => {
|
||||
return html.replace('<html lang="en-gb">', `<html lang="${lang}">`);
|
||||
};
|
||||
|
||||
// TODO: Add function that process links and add prefix.
|
||||
|
||||
async function main() {
|
||||
const supportedLocales = {
|
||||
'en_GB': {
|
||||
htmlTranslations: {},
|
||||
lang: 'en-gb',
|
||||
},
|
||||
const supportedLocales: Record<string, Locale> = {
|
||||
'en_GB': enGbLocale,
|
||||
'zh_CN': {
|
||||
htmlTranslations: parseTranslations(await parsePoFile(`${websiteAssetDir}/locales/zh_CN.po`)),
|
||||
lang: 'zh-cn',
|
||||
pathPrefix: 'cn',
|
||||
},
|
||||
'fr_FR': {
|
||||
htmlTranslations: {},
|
||||
lang: 'fr-fr',
|
||||
pathPrefix: 'fr',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -237,34 +255,53 @@ async function main() {
|
||||
const partials = await loadMustachePartials(partialDir);
|
||||
const assetUrls = await getAssetUrls();
|
||||
|
||||
const readmeMd = makeHomePageMd();
|
||||
const donateLinksMd = await getDonateLinks();
|
||||
|
||||
// =============================================================
|
||||
// HELP PAGE
|
||||
// =============================================================
|
||||
|
||||
renderPageToHtml(readmeMd, `${docDir}/help/index.html`, {
|
||||
sourceMarkdownFile: 'README.md',
|
||||
donateLinksMd,
|
||||
partials,
|
||||
sponsors,
|
||||
assetUrls,
|
||||
openGraph: {
|
||||
title: 'Joplin documentation',
|
||||
description: '',
|
||||
url: 'https://joplinapp.org/help/',
|
||||
},
|
||||
});
|
||||
|
||||
// =============================================================
|
||||
// FRONT PAGE
|
||||
// =============================================================
|
||||
|
||||
for (const [localeName, locale] of Object.entries(supportedLocales)) {
|
||||
setLocale(localeName);
|
||||
|
||||
const pathPrefix = localeName !== 'en_GB' ? `/${countryCodeOnly(localeName).toLowerCase()}` : '';
|
||||
const pathPrefix = localeName !== 'en_GB' ? `/${locale.pathPrefix}` : '';
|
||||
|
||||
// =============================================================
|
||||
// HELP PAGE
|
||||
// =============================================================
|
||||
|
||||
let readmePath = `${rootDir}/README.md`;
|
||||
|
||||
let sourceMarkdownFile = 'README.md';
|
||||
let targetDocDir = docDir;
|
||||
|
||||
if (localeName !== 'en_GB') {
|
||||
const possibleSource = `${rootDir}/readme/_i18n/${localeName}/README.md`;
|
||||
if (await pathExists(possibleSource)) {
|
||||
sourceMarkdownFile = possibleSource;
|
||||
readmePath = possibleSource;
|
||||
} else {
|
||||
console.warn(`Cannot find source file: ${possibleSource}`);
|
||||
}
|
||||
|
||||
targetDocDir = `${docDir}/${locale.pathPrefix}`;
|
||||
}
|
||||
|
||||
const readmeMd = makeHomePageMd(readmePath);
|
||||
|
||||
renderPageToHtml(readmeMd, `${targetDocDir}/help/index.html`, {
|
||||
sourceMarkdownFile,
|
||||
donateLinksMd,
|
||||
partials,
|
||||
sponsors,
|
||||
assetUrls,
|
||||
openGraph: {
|
||||
title: 'Joplin documentation',
|
||||
description: '',
|
||||
url: 'https://joplinapp.org/help/',
|
||||
},
|
||||
locale,
|
||||
});
|
||||
|
||||
// =============================================================
|
||||
// FRONT PAGE
|
||||
// =============================================================
|
||||
|
||||
let templateHtml = updatePageLanguage(applyTranslations(frontTemplateHtml, localeName, locale.htmlTranslations), locale.lang);
|
||||
if (localeName === 'zh_CN') templateHtml = templateHtml.replace(/\/plans/g, '/cn/plans');
|
||||
@@ -292,22 +329,16 @@ async function main() {
|
||||
url: 'https://joplinapp.org',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
setLocale('en_GB');
|
||||
|
||||
// =============================================================
|
||||
// PLANS PAGE
|
||||
// =============================================================
|
||||
|
||||
for (const [localeName, locale] of Object.entries(supportedLocales)) {
|
||||
setLocale(localeName);
|
||||
// =============================================================
|
||||
// PLANS PAGE
|
||||
// =============================================================
|
||||
|
||||
const planPageFaqMd = await readFile(`${readmeDir}/faq_joplin_cloud.md`, 'utf8');
|
||||
const planPageFaqHtml = getMarkdownIt().render(planPageFaqMd, {});
|
||||
|
||||
const planPageParams: PlanPageParams = {
|
||||
...defaultTemplateParams(assetUrls),
|
||||
...defaultTemplateParams(assetUrls, locale),
|
||||
partials: translatePartials(partials, localeName, locale.htmlTranslations),
|
||||
templateHtml: applyTranslations(plansTemplateHtml, localeName, locale.htmlTranslations),
|
||||
plans: getPlans(stripeConfig),
|
||||
@@ -318,10 +349,8 @@ async function main() {
|
||||
|
||||
const planPageContentHtml = renderMustache('', planPageParams);
|
||||
|
||||
const pathPrefix = localeName !== 'en_GB' ? `/${countryCodeOnly(localeName).toLowerCase()}` : '';
|
||||
|
||||
const templateParams = {
|
||||
...defaultTemplateParams(assetUrls),
|
||||
...defaultTemplateParams(assetUrls, locale),
|
||||
pageName: 'plans',
|
||||
partials,
|
||||
showToc: false,
|
||||
@@ -342,10 +371,20 @@ async function main() {
|
||||
// Markdown files under /readme
|
||||
// =============================================================
|
||||
|
||||
const mdFiles = glob.sync(`${readmeDir}/**/*.md`).map((f: string) => f.substr(rootDir.length + 1));
|
||||
const sources = [];
|
||||
interface SourceInfo {
|
||||
title: string;
|
||||
donateLinksMd: string;
|
||||
showToc: boolean;
|
||||
openGraph: OpenGraphTags;
|
||||
sourceMarkdownName?: string;
|
||||
sourceMarkdownFile?: string;
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
const makeTargetBasename = (input: string): string => {
|
||||
const mdFiles: string[] = glob.sync(`${readmeDir}/**/*.md`).map((f: string) => f.substr(rootDir.length + 1));
|
||||
const sources: [string, string, SourceInfo][] = [];
|
||||
|
||||
const makeTargetBasename = (input: string, pathPrefix: string): string => {
|
||||
if (isNewsFile(input)) {
|
||||
const filenameNoExt = basename(input, '.md');
|
||||
return `news/${filenameNoExt}/index.html`;
|
||||
@@ -364,34 +403,49 @@ async function main() {
|
||||
|
||||
s = s.replace(/readme\//, '');
|
||||
|
||||
if (pathPrefix) s = `${pathPrefix}/${s}`;
|
||||
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
const makeTargetFilePath = (input: string): string => {
|
||||
return `${docDir}/${makeTargetBasename(input)}`;
|
||||
const makeTargetFilePath = (input: string, pathPrefix: string): string => {
|
||||
return `${docDir}/${makeTargetBasename(input, pathPrefix)}`;
|
||||
};
|
||||
|
||||
const makeTargetUrl = (input: string) => {
|
||||
return `https://joplinapp.org/${makeTargetBasename(input)}`;
|
||||
const makeTargetUrl = (input: string, pathPrefix: string) => {
|
||||
return `https://joplinapp.org/${makeTargetBasename(input, pathPrefix)}`;
|
||||
};
|
||||
|
||||
const newsFilePaths: string[] = [];
|
||||
|
||||
for (const mdFile of mdFiles) {
|
||||
const title = await readmeFileTitle(`${rootDir}/${mdFile}`);
|
||||
const targetFilePath = makeTargetFilePath(mdFile);
|
||||
const openGraph = await extractOpenGraphTags(mdFile, makeTargetUrl(mdFile));
|
||||
if (mdFile.startsWith('readme/_i18n')) continue;
|
||||
|
||||
const isNews = isNewsFile(mdFile);
|
||||
if (isNews) newsFilePaths.push(mdFile);
|
||||
for (const [localeName, locale] of Object.entries(supportedLocales)) {
|
||||
const title = await readmeFileTitle(`${rootDir}/${mdFile}`);
|
||||
const targetFilePath = makeTargetFilePath(mdFile, locale.pathPrefix);
|
||||
const openGraph = await extractOpenGraphTags(mdFile, makeTargetUrl(mdFile, locale.pathPrefix));
|
||||
|
||||
sources.push([mdFile, targetFilePath, {
|
||||
title: title,
|
||||
donateLinksMd: mdFile === 'readme/donate.md' ? '' : donateLinksMd,
|
||||
showToc: mdFile !== 'readme/download.md' && !isNews,
|
||||
openGraph,
|
||||
}]);
|
||||
const isNews = isNewsFile(mdFile);
|
||||
if (isNews) newsFilePaths.push(mdFile);
|
||||
|
||||
let sourceFile = mdFile;
|
||||
|
||||
if (localeName !== 'en_GB') {
|
||||
let temp = mdFile.replace(/readme\//, '');
|
||||
temp = `readme/_i18n/${localeName}/${temp}`;
|
||||
if (await pathExists(temp)) sourceFile = temp;
|
||||
}
|
||||
|
||||
sources.push([sourceFile, targetFilePath, {
|
||||
title: title,
|
||||
donateLinksMd: mdFile === 'readme/donate.md' ? '' : donateLinksMd,
|
||||
showToc: mdFile !== 'readme/download.md' && !isNews,
|
||||
openGraph,
|
||||
locale,
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const source of sources) {
|
||||
@@ -418,7 +472,7 @@ async function main() {
|
||||
});
|
||||
|
||||
await makeNewsFrontPage(newsFilePaths, `${docDir}/news/index.html`, {
|
||||
...defaultTemplateParams(assetUrls),
|
||||
...defaultTemplateParams(assetUrls, null),
|
||||
title: 'What\'s new',
|
||||
pageName: 'news',
|
||||
partials,
|
||||
|
||||
25
packages/tools/website/utils/convertLinksToLocale.test.ts
Normal file
25
packages/tools/website/utils/convertLinksToLocale.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import convertLinksToLocale from './convertLinksToLocale';
|
||||
|
||||
describe('convertLinksToLocale', () => {
|
||||
|
||||
it('should convert links', async () => {
|
||||
const tests: [string, any, string][] = [
|
||||
[
|
||||
'test [link](/help/link)',
|
||||
{ pathPrefix: 'fr' },
|
||||
'test [link](/fr/help/link)',
|
||||
],
|
||||
[
|
||||
'test [link](/help/link) [link2](/link2)',
|
||||
{ pathPrefix: 'fr' },
|
||||
'test [link](/fr/help/link) [link2](/fr/link2)',
|
||||
],
|
||||
];
|
||||
|
||||
for (const [input, locale, expected] of tests) {
|
||||
const actual = convertLinksToLocale(input, locale);
|
||||
expect(actual).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
9
packages/tools/website/utils/convertLinksToLocale.ts
Normal file
9
packages/tools/website/utils/convertLinksToLocale.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Locale } from './types';
|
||||
|
||||
export default (md: string, locale: Locale) => {
|
||||
if (locale.lang === 'en-gb') return md;
|
||||
|
||||
md = md.replace(/\(\//g, `(/${locale.pathPrefix}/`);
|
||||
|
||||
return md;
|
||||
};
|
||||
@@ -7,6 +7,12 @@ export enum Env {
|
||||
Prod = 'prod',
|
||||
}
|
||||
|
||||
export interface Locale {
|
||||
htmlTranslations: Record<string, string>;
|
||||
lang: string;
|
||||
pathPrefix: string;
|
||||
}
|
||||
|
||||
export interface GithubUser {
|
||||
id: string;
|
||||
}
|
||||
@@ -62,6 +68,7 @@ export interface TemplateParams {
|
||||
showBottomLinks?: boolean;
|
||||
openGraph: OpenGraphTags;
|
||||
isNews?: boolean;
|
||||
locale?: Locale;
|
||||
}
|
||||
|
||||
export interface PlanPageParams extends TemplateParams {
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
@@ -19,10 +19,13 @@
|
||||
"author": "",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"execa": "5.1.1"
|
||||
"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"
|
||||
}
|
||||
|
||||
74
readme/_i18n/fr_FR/README.md
Normal file
74
readme/_i18n/fr_FR/README.md
Normal file
@@ -0,0 +1,74 @@
|
||||
<!-- DONATELINKS -->
|
||||
[! [Faire un don via PayPal] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=E8JMYD2LQ8MMA&lc=GB&item_name=Joplin+Development¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) [! [Sponsor sur GitHub] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/GitHub-Badge.svg)](https://github.com/sponsors/laurent22/) [! [Devenez mécène] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Patreon-Badge.svg)](https://www.patreon.com/joplin) [! [Faire un don en utilisant un IBAN] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Donate-IBAN.svg)](https://joplinapp.org/donate/#donations)
|
||||
<!-- DONATELINKS -->
|
||||
|
||||
* * *
|
||||
**TEST ONLY**
|
||||
* * *
|
||||
|
||||
[test link](/spec/e2ee)
|
||||
|
||||
<img width="64" src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/LinuxIcons/256x256.png" align="left" />**Joplin** est une application gratuite et open source de prise de notes et de tâches, qui peut gérer un grand nombre de notes organisées dans des carnets de notes. Les notes sont consultables, peuvent être copiées, balisées et modifiées directement depuis les applications ou depuis votre propre éditeur de texte. Les notes sont au format [Markdown] (#markdown).
|
||||
|
||||
Les notes exportées depuis Evernote [peuvent être importées] (#importing) dans Joplin, y compris le contenu formaté (qui est converti en Markdown), les ressources (images, pièces jointes, etc.) et les métadonnées complètes (géolocalisation, heure de mise à jour, heure de création, etc.). Les fichiers Markdown simples peuvent également être importés.
|
||||
|
||||
Les notes peuvent être [synchronisées] (#synchronisation) en toute sécurité à l'aide du [chiffrement de bout en bout] (#encryption) avec divers services cloud, notamment Nextcloud, Dropbox, OneDrive et [Joplin Cloud] (https://joplinapp.org/plans/).
|
||||
|
||||
La recherche en texte intégral est disponible sur toutes les plateformes pour trouver rapidement les informations dont vous avez besoin. L'application peut être personnalisée à l'aide de plugins et de thèmes, et vous pouvez également créer facilement le vôtre.
|
||||
|
||||
L'application est disponible pour Windows, Linux, macOS, Android et iOS. Un [Web Clipper] (https://github.com/laurent22/joplin/blob/dev/readme/clipper.md), qui permet d'enregistrer des pages Web et des captures d'écran depuis votre navigateur, est également disponible pour [Firefox] (https://addons.mozilla.org/firefox/addon/joplin-web-clipper/) et [Chrome] (https://chrome.google.com/webstore/detail/joplin-web-clipper/alofnhikmmkdbbbgpnglcpdollgjjfek?hl=en-GB).
|
||||
|
||||
<div class="top-screenshot"></div><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/home-top-img.png" style="max-width: 100%; max-height: 35em;">
|
||||
|
||||
# Installation
|
||||
|
||||
Trois types d'applications sont disponibles : pour **bureau** (Windows, macOS et Linux), pour **mobile** (Android et iOS) et pour **terminal** (Windows, macOS, Linux et FreeBSD). Toutes les applications disposent d'interfaces utilisateur similaires et peuvent se synchroniser entre elles.
|
||||
|
||||
## Applications de bureau
|
||||
|
||||
Système d'exploitation | Télécharger
|
||||
---|---
|
||||
Windows (32 et 64 bits) | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-Setup-2.9.17.exe'><img alt='Get it on Windows' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeWindows.png'/></a>
|
||||
MacOS | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-2.9.17.dmg'><img alt='Get it on macOS' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeMacOS.png'/></a>
|
||||
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-2.9.17.AppImage'><img alt='Get it on Linux' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeLinux.png'/></a>
|
||||
|
||||
<a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/JoplinPortable.exe'>**Sous Windows**, vous pouvez également utiliser la version portable.</a> L' [application portable] (https://en.wikipedia.org/wiki/Portable_application) permet d'installer le logiciel sur un appareil portable tel qu'une clé USB. Copiez simplement le fichier JoplinPortable.exe dans n'importe quel répertoire de cette clé USB ; l'application créera alors un répertoire appelé « JoplinProfile » à côté du fichier exécutable.
|
||||
|
||||
**Sous Linux**, la méthode recommandée est d'utiliser le script d'installation suivant car il gérera également l'icône du bureau :
|
||||
|
||||
<pre><code style="word-break: break-all">wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh | bash</code></pre>
|
||||
|
||||
## Applications mobiles
|
||||
|
||||
Système d'exploitation | Télécharger | Alt. Télécharger
|
||||
---|---|---
|
||||
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeAndroid.png'/></a>| ou téléchargez le fichier APK : [64 bits] (https://github.com/laurent22/joplin-android/releases/download/android-v2.9.8/joplin-v2.9.8.apk) [32 bits] ( https://github.com/laurent22/joplin-android/releases/download/android-v2.9.8/joplin-v2.9.8-32bit.apk)
|
||||
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeIOS.png'/></a>| -
|
||||
|
||||
## Application du terminal
|
||||
|
||||
Système d'exploitation | Méthode
|
||||
-----------------|----------------
|
||||
macOS, Linux ou Windows (via [WSL] (https://msdn.microsoft.com/en-us/commandline/wsl/faq?f=255&MSPPError=-2147217396)) | **Important :** Tout d'abord, [installez Node 12+] (https://nodejs.org/en/download/package-manager/). <br/><br/><br><br>`NPM_CONFIG_PREFIX=~/.joplin-bin npm install -g joplin` `sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin `Par défaut, le binaire de l'application sera installé sous <br/> `~/.joplin-bin`. Vous pouvez modifier ce répertoire si nécessaire. Sinon, si vos autorisations npm sont configurées comme décrit [ici] (https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-2-change-npms-default-directory-to-another-directory) (Option 2), il suffit d'exécuter `npm -g install joplin`.
|
||||
|
||||
Pour le démarrer, tapez `joplin`.
|
||||
|
||||
Pour des informations d'utilisation, veuillez consulter la [Documentation complète de l'application Joplin Terminal] (https://joplinapp.org/terminal/).
|
||||
|
||||
## Web Clipper
|
||||
|
||||
Le Web Clipper est une extension de navigateur qui vous permet d'enregistrer des pages Web et des captures d'écran à partir de votre navigateur. Pour plus d'informations sur son installation et son utilisation, consultez la [Page d'aide de Web Clipper] (https://github.com/laurent22/joplin/blob/dev/readme/clipper.md).
|
||||
|
||||
## Distributions alternatives non officielles
|
||||
|
||||
Il existe un certain nombre de distributions alternatives non officielles de Joplin. Si vous ne voulez pas ou ne pouvez pas utiliser appimages ou l'une des autres versions officiellement prises en charge, vous pouvez envisager de les utiliser.
|
||||
|
||||
Cependant, ils sont assortis d'une mise en garde dans la mesure où ils ne sont pas officiellement pris en charge, de sorte que certains problèmes peuvent ne pas être pris en charge par le projet principal. Les demandes d'assistance, les rapports de bogues et les conseils généraux devraient plutôt être adressés aux responsables de ces distributions.
|
||||
|
||||
Une liste de ces distributions gérée par la communauté est disponible ici : [Distributions Joplin non officielles] (https://discourse.joplinapp.org/t/unofficial-alternative-joplin-distributions/23703)
|
||||
|
||||
# Sponsors
|
||||
|
||||
<!-- SPONSORS-ORG -->
|
||||
</a><a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/><a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&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 -->
|
||||
5
readme/_i18n/fr_FR/desktop.md
Normal file
5
readme/_i18n/fr_FR/desktop.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Application de bureau
|
||||
|
||||
<img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/DemoDesktop.png" style="width: 100%">
|
||||
|
||||
Pour des informations générales relatives à toutes les applications, voir aussi [la page de garde](https://joplinapp.org).
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -399,6 +399,70 @@
|
||||
"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
|
||||
},
|
||||
{
|
||||
"name": "Wladefant",
|
||||
"id": 79611093,
|
||||
"comment_id": 1514649134,
|
||||
"created_at": "2023-04-19T12:28:22Z",
|
||||
"repoId": 79162682,
|
||||
"pullRequestNo": 8069
|
||||
},
|
||||
{
|
||||
"name": "DeeJayLSP",
|
||||
"id": 60024671,
|
||||
"comment_id": 1519381301,
|
||||
"created_at": "2023-04-24T04:56:51Z",
|
||||
"repoId": 79162682,
|
||||
"pullRequestNo": 8077
|
||||
}
|
||||
]
|
||||
}
|
||||
19
readme/spec/server_items.md
Normal file
19
readme/spec/server_items.md
Normal 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
39
readme/spec/sync.md
Normal 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)
|
||||
441
readme/stats.md
441
readme/stats.md
@@ -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 |
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user