1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-12-23 23:33:01 +02:00

Compare commits

..

4 Commits

Author SHA1 Message Date
Laurent Cozic
87045a7b60 notarization script 2020-11-29 00:53:17 +00:00
Laurent Cozic
35242b9735 Merge branch 'dev' into mac_notarization 2020-11-29 00:23:13 +00:00
Laurent Cozic
0fcb6441de notarize 2020-11-29 00:18:39 +00:00
Laurent Cozic
8fbd1ae21a notarization 2020-11-27 20:42:23 +00:00
59 changed files with 496 additions and 4774 deletions

View File

@@ -46,7 +46,6 @@ packages/app-mobile/ios
packages/app-mobile/locales
packages/app-mobile/node_modules
packages/app-mobile/pluginAssets/
packages/app-mobile/lib/rnInjectedJs/
packages/lib/assets/
packages/lib/rnInjectedJs/
packages/lib/vendor/
@@ -86,9 +85,6 @@ packages/app-cli/tests/models_Note.js.map
packages/app-cli/tests/models_Setting.d.ts
packages/app-cli/tests/models_Setting.js
packages/app-cli/tests/models_Setting.js.map
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.d.ts
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js.map
packages/app-cli/tests/services/plugins/sandboxProxy.d.ts
packages/app-cli/tests/services/plugins/sandboxProxy.js
packages/app-cli/tests/services/plugins/sandboxProxy.js.map
@@ -1127,9 +1123,6 @@ packages/lib/services/plugins/utils/executeSandboxCall.js.map
packages/lib/services/plugins/utils/loadContentScripts.d.ts
packages/lib/services/plugins/utils/loadContentScripts.js
packages/lib/services/plugins/utils/loadContentScripts.js.map
packages/lib/services/plugins/utils/makeListener.d.ts
packages/lib/services/plugins/utils/makeListener.js
packages/lib/services/plugins/utils/makeListener.js.map
packages/lib/services/plugins/utils/manifestFromObject.d.ts
packages/lib/services/plugins/utils/manifestFromObject.js
packages/lib/services/plugins/utils/manifestFromObject.js.map

6
.gitignore vendored
View File

@@ -77,9 +77,6 @@ packages/app-cli/tests/models_Note.js.map
packages/app-cli/tests/models_Setting.d.ts
packages/app-cli/tests/models_Setting.js
packages/app-cli/tests/models_Setting.js.map
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.d.ts
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js.map
packages/app-cli/tests/services/plugins/sandboxProxy.d.ts
packages/app-cli/tests/services/plugins/sandboxProxy.js
packages/app-cli/tests/services/plugins/sandboxProxy.js.map
@@ -1118,9 +1115,6 @@ packages/lib/services/plugins/utils/executeSandboxCall.js.map
packages/lib/services/plugins/utils/loadContentScripts.d.ts
packages/lib/services/plugins/utils/loadContentScripts.js
packages/lib/services/plugins/utils/loadContentScripts.js.map
packages/lib/services/plugins/utils/makeListener.d.ts
packages/lib/services/plugins/utils/makeListener.js
packages/lib/services/plugins/utils/makeListener.js.map
packages/lib/services/plugins/utils/manifestFromObject.d.ts
packages/lib/services/plugins/utils/manifestFromObject.js
packages/lib/services/plugins/utils/manifestFromObject.js.map

View File

@@ -1,5 +1,5 @@
# Only build tags (Doesn't work - doesn't build anything)
if: tag IS present OR type = pull_request OR branch = dev
if: tag IS present OR type = pull_request
rvm: 2.3.3
@@ -15,30 +15,21 @@ branches:
matrix:
include:
- os: osx
osx_image: xcode12
osx_image: xcode9.0
language: node_js
node_js: "12"
cache:
npm: false
# Cache was disabled because when changing from node_js 10 to node_js 12
# it was still using build files from Node 10 when building SQLite which
# was making it fail. Might be ok to re-enable later on, although it doesn't
# make build that much faster.
#
# env:
# - ELECTRON_CACHE=$HOME/.cache/electron
# - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
node_js: "10"
env:
- ELECTRON_CACHE=$HOME/.cache/electron
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
- os: linux
sudo: required
dist: trusty
language: node_js
node_js: "12"
cache:
npm: false
# env:
# - ELECTRON_CACHE=$HOME/.cache/electron
# - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
node_js: "10"
env:
- ELECTRON_CACHE=$HOME/.cache/electron
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
# cache:
# directories:
@@ -74,7 +65,7 @@ script:
# Run test units.
# Only do it for pull requests because Travis randomly fails to run them
# and that would break the desktop release.
if [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" = "dev" ]; then
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
npm run test-ci
testResult=$?
if [ $testResult -ne 0 ]; then

View File

@@ -20,9 +20,9 @@ Three types of applications are available: for the **desktop** (Windows, macOS a
Operating System | Download | Alternative
-----------------|--------|-------------------
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/Joplin-Setup-1.4.18.exe'><img alt='Get it on Windows' width="134px" src='https://joplinapp.org/images/BadgeWindows.png'/></a> | Or get the <a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/JoplinPortable.exe'>Portable version</a><br><br>The [portable application](https://en.wikipedia.org/wiki/Portable_application) allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called "JoplinProfile" next to the executable file.
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/Joplin-1.4.18.dmg'><img alt='Get it on macOS' width="134px" src='https://joplinapp.org/images/BadgeMacOS.png'/></a> | You can also use Homebrew (unsupported): `brew cask install joplin`
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/Joplin-1.4.18.AppImage'><img alt='Get it on Linux' width="134px" src='https://joplinapp.org/images/BadgeLinux.png'/></a> | An Arch Linux package (unsupported) [is also available](#terminal-application).<br><br>If it works with your distribution (it has been tested on Ubuntu, Fedora, and Mint; the desktop environments supported are GNOME, KDE, Xfce, MATE, LXQT, LXDE, Unity, Cinnamon, Deepin and Pantheon), the recommended way is to use this script as it will handle the desktop icon too:<br><br> `wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh \| bash`
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/Joplin-Setup-1.3.18.exe'><img alt='Get it on Windows' width="134px" src='https://joplinapp.org/images/BadgeWindows.png'/></a> | Or get the <a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/JoplinPortable.exe'>Portable version</a><br><br>The [portable application](https://en.wikipedia.org/wiki/Portable_application) allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called "JoplinProfile" next to the executable file.
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/Joplin-1.3.18.dmg'><img alt='Get it on macOS' width="134px" src='https://joplinapp.org/images/BadgeMacOS.png'/></a> | You can also use Homebrew (unsupported): `brew cask install joplin`
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/Joplin-1.3.18.AppImage'><img alt='Get it on Linux' width="134px" src='https://joplinapp.org/images/BadgeLinux.png'/></a> | An Arch Linux package (unsupported) [is also available](#terminal-application).<br><br>If it works with your distribution (it has been tested on Ubuntu, Fedora, and Mint; the desktop environments supported are GNOME, KDE, Xfce, MATE, LXQT, LXDE, Unity, Cinnamon, Deepin and Pantheon), the recommended way is to use this script as it will handle the desktop icon too:<br><br> `wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh \| bash`
## Mobile applications
@@ -64,8 +64,7 @@ The Web Clipper is a browser extension that allows you to save web pages and scr
| :---: | :---: | :---: |
| <img width="50" src="https://avatars0.githubusercontent.com/u/6979755?s=96&v=4"/></br>[Devon Zuegel](https://github.com/devonzuegel) | <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[小西 孝宗](https://github.com/konishi-t) | <img width="50" src="https://avatars2.githubusercontent.com/u/215668?s=96&v=4"/></br>[Alexander van der Berg](https://github.com/avanderberg)
| <img width="50" src="https://avatars0.githubusercontent.com/u/1168659?s=96&v=4"/></br>[Nicholas Head](https://github.com/nicholashead) | <img width="50" src="https://avatars2.githubusercontent.com/u/1439535?s=96&v=4"/></br>[Frank Bloise](https://github.com/fbloise) | <img width="50" src="https://avatars2.githubusercontent.com/u/15859362?s=96&v=4"/></br>[Thomas Broussard](https://github.com/thomasbroussard)
| <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[Brandon Johnson](https://github.com/dbrandonjohnson) | <img width="50" src="https://avatars1.githubusercontent.com/u/3061769?s=96&v=4"/></br>[@cnagy](https://github.com/c-nagy) | <img width="50" src="https://avatars3.githubusercontent.com/u/53228972?s=96&v=4"/></br>[clmntsl](https://github.com/clmntsl)
| <img width="50" src="https://avatars1.githubusercontent.com/u/29300939?s=96&v=4"/></br>[mcejp](https://github.com/mcejp)
| <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[Brandon Johnson](https://github.com/dbrandonjohnson) | <img width="50" src="https://avatars1.githubusercontent.com/u/3061769?s=96&v=4"/></br>[@cnagy](https://github.com/c-nagy) |
<!-- TOC -->
# Table of contents

View File

@@ -418,10 +418,10 @@ https://github.com/laurent22/joplin/blob/dev/readme/api/overview.md
<li>Create a module to export or import data into Joplin</li>
<li>Define new settings and setting sections, and get/set them from the plugin</li>
<li>Create a new Markdown plugin to render custom markup.</li>
<li>Create an editor plugin to modify, at a low-level, the behaviour of the Markdown editor (CodeMirror)</li>
<li>Create an editor plugin to modify low-level the behaviour of the Markdown editor (CodeMirror)</li>
</ul>
<p>To get started with the plugin API, check the <a href="https://joplinapp.org/api/get_started/plugins/">Get Started</a> page or have a look at the <a href="https://joplinapp.org/api/tutorials/toc_plugin/">TOC tutorial</a>.</p>
<p>Once you are familiar with the API, you can have a look at the <a href="https://joplinapp.org/api/references/plugin_api/classes/joplin.html">plugin API reference</a> for a detailed documentation about each supported feature.</p>
<p>Once you are familiar with the API, you can have a look at the <a href="https://joplinapp.org/api/get_started/plugins/">plugin API reference</a> for a detailed documentation about each supported feature.</p>
<div class="bottom-links">
<a href="https://github.com/laurent22/joplin/blob/dev/readme/api/overview.md">

File diff suppressed because one or more lines are too long

View File

@@ -155,8 +155,7 @@
</div>
<p>Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules
(eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported.</p>
<p><a href="https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script">View the renderer demo plugin</a>
<a href="https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script">View the editor demo plugin</a></p>
<p><a href="https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script">View the demo plugin</a></p>
</div>
<h4 class="tsd-parameters-title">Parameters</h4>
<ul class="tsd-parameters">

View File

@@ -86,41 +86,6 @@
<div class="tsd-signature tsd-kind-icon">Code<wbr>Mirror<wbr>Plugin<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> = &quot;codeMirrorPlugin&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Registers a new CodeMirror plugin, which should follow the template below.</p>
</div>
<pre><code class="language-javascript"><span class="hljs-built_in">module</span>.exports = {
<span class="hljs-attr">default</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">context</span>) </span>{
<span class="hljs-keyword">return</span> {
<span class="hljs-attr">plugin</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">CodeMirror</span>) </span>{
<span class="hljs-comment">// ...</span>
},
<span class="hljs-attr">codeMirrorResources</span>: [],
<span class="hljs-attr">codeMirrorOptions</span>: {
<span class="hljs-comment">// ...</span>
},
<span class="hljs-attr">assets</span>: {
<span class="hljs-comment">// ...</span>
},
}
}
}</code></pre>
<ul>
<li><p>The <code>context</code> argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate.</p>
</li>
<li><p>The <code>plugin</code> key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed.</p>
</li>
<li><p>The <code>codeMirrorResources</code> key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want&#39;s to enable clojure highlighting in code blocks. <code>codeMirrorResources</code> would be set to <code>[&#39;mode/clojure/clojure&#39;]</code>.</p>
</li>
<li><p>The <code>codeMirrorOptions</code> key contains all the <a href="https://codemirror.net/doc/manual.html#config">CodeMirror</a> options that will be set or changed by this plugin. New options can alse be declared via <a href="https://codemirror.net/doc/manual.html#defineOption"><code>CodeMirror.defineOption</code></a>, and then have their value set here. For example, a plugin that enables line numbers would set <code>codeMirrorOptions</code> to <code>{&#39;lineNumbers&#39;: true}</code>.</p>
</li>
<li><p>Using the <strong>optional</strong> <code>assets</code> key you may specify <strong>only</strong> CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin <a href="https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts">Mermaid plugin</a> to see how the data should be structured.</p>
</li>
</ul>
<p>One of the <code>plugin</code>, <code>codeMirrorResources</code>, or <code>codeMirrorOptions</code> keys must be provided for the plugin to be valid. Having multiple or all provided is also okay.</p>
<p>See the <a href="https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script">demo plugin</a> for an example of all these keys being used in one plugin.</p>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="markdownitplugin" class="tsd-anchor"></a>

View File

@@ -121,12 +121,6 @@
<li class="tsd-kind-type-alias"><a href="globals.html#viewhandle" class="tsd-kind-icon">View<wbr>Handle</a></li>
</ul>
</section>
<section class="tsd-index-section ">
<h3>Variables</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-variable"><a href="globals.html#logger" class="tsd-kind-icon">logger</a></li>
</ul>
</section>
</div>
</section>
</section>
@@ -162,16 +156,6 @@
</aside>
</section>
</section>
<section class="tsd-panel-group tsd-member-group ">
<h2>Variables</h2>
<section class="tsd-panel tsd-member tsd-kind-variable">
<a name="logger" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagConst">Const</span> logger</h3>
<div class="tsd-signature tsd-kind-icon">logger<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">LoggerWrapper</span><span class="tsd-signature-symbol"> = Logger.create(&#x27;joplin.plugins&#x27;)</span></div>
<aside class="tsd-sources">
</aside>
</section>
</section>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<!--

View File

@@ -84,6 +84,7 @@
<h3>Properties</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="exportoptions.html#format" class="tsd-kind-icon">format</a></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="exportoptions.html#modulepath" class="tsd-kind-icon">module<wbr>Path</a></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="exportoptions.html#path" class="tsd-kind-icon">path</a></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="exportoptions.html#sourcefolderids" class="tsd-kind-icon">source<wbr>Folder<wbr>Ids</a></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="exportoptions.html#sourcenoteids" class="tsd-kind-icon">source<wbr>Note<wbr>Ids</a></li>
@@ -102,6 +103,13 @@
<aside class="tsd-sources">
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
<a name="modulepath" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagOptional">Optional</span> module<wbr>Path</h3>
<div class="tsd-signature tsd-kind-icon">module<wbr>Path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
<aside class="tsd-sources">
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
<a name="path" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagOptional">Optional</span> path</h3>
@@ -230,6 +238,9 @@
<li class=" tsd-kind-property tsd-parent-kind-interface">
<a href="exportoptions.html#format" class="tsd-kind-icon">format</a>
</li>
<li class=" tsd-kind-property tsd-parent-kind-interface">
<a href="exportoptions.html#modulepath" class="tsd-kind-icon">module<wbr>Path</a>
</li>
<li class=" tsd-kind-property tsd-parent-kind-interface">
<a href="exportoptions.html#path" class="tsd-kind-icon">path</a>
</li>

View File

@@ -399,98 +399,6 @@ https://github.com/laurent22/joplin/blob/dev/readme/changelog.md
<div class="main">
<h1>Joplin changelog<a name="joplin-changelog" href="#joplin-changelog" class="heading-anchor">🔗</a></h1>
<h2><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.18">v1.4.18</a> - 2020-11-28T12:21:41Z<a name="v1-4-18-https-github-com-laurent22-joplin-releases-tag-v1-4-18-2020-11-28t12-21-41z" href="#v1-4-18-https-github-com-laurent22-joplin-releases-tag-v1-4-18-2020-11-28t12-21-41z" class="heading-anchor">🔗</a></h2>
<ul>
<li>Fixed: Fixed notifications on macOS</li>
<li>Fixed: Re-enabled ASAR packing to improve startup time</li>
</ul>
<h2><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.16">v1.4.16</a> - 2020-11-27T19:40:16Z<a name="v1-4-16-https-github-com-laurent22-joplin-releases-tag-v1-4-16-2020-11-27t19-40-16z" href="#v1-4-16-https-github-com-laurent22-joplin-releases-tag-v1-4-16-2020-11-27t19-40-16z" class="heading-anchor">🔗</a></h2>
<ul>
<li>Fixed: Fix sorting by title in a case insensitive way</li>
<li>Fixed: Fixed spell checker crash when no language is selected</li>
</ul>
<h2><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.15">v1.4.15</a> - 2020-11-27T13:25:43Z<a name="v1-4-15-https-github-com-laurent22-joplin-releases-tag-v1-4-15-2020-11-27t13-25-43z" href="#v1-4-15-https-github-com-laurent22-joplin-releases-tag-v1-4-15-2020-11-27t13-25-43z" class="heading-anchor">🔗</a></h2>
<ul>
<li>Fixed: Notifications on macOS</li>
<li>Fixed: Fixed potential crash when watching note files or resources</li>
<li>Fixed: Prevents crash when invalid spell checker language is selected, and provide fallback for invalid language codes (<a href="https://github.com/laurent22/joplin/issues/4146">#4146</a>)</li>
<li>Plugins: Fixed webview postMessage call</li>
</ul>
<h2><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.12">v1.4.12</a> - 2020-11-23T18:58:07Z<a name="v1-4-12-https-github-com-laurent22-joplin-releases-tag-v1-4-12-2020-11-23t18-58-07z" href="#v1-4-12-https-github-com-laurent22-joplin-releases-tag-v1-4-12-2020-11-23t18-58-07z" class="heading-anchor">🔗</a></h2>
<p><strong>Breaking Changes:</strong></p>
<ul>
<li>If you use the Clipper API, please note that there are a few breaking changes in this version. See this link for more information: <a href="https://github.com/laurent22/joplin/pull/3983">https://github.com/laurent22/joplin/pull/3983</a></li>
<li>Plugins: <code>joplin.views.dialogs.open()</code> now returns an object instead of the button ID that was clicked. So for example instead of getting just <code>&quot;ok&quot;</code>, you will get <code>{ &quot;id&quot;: &quot;ok&quot; }</code>. This is to allow adding form data to that object.</li>
</ul>
<p><strong>Deprecated:</strong></p>
<p>The following features are deprecated. It will still work for now but please update your code:</p>
<ul>
<li>Plugins: All <code>create()</code> functions under <code>joplin.views</code> now take a <code>viewId</code> as a first parameter.</li>
<li>Plugins: <code>MenuItemLocation.Context</code> is deprecated and is now an alias for <code>MenuItemLocation.NoteListContextMenu</code></li>
<li>Plugins: The <code>app_min_version</code> manifest property is now required. If not provided it will assume v14.</li>
<li>Plugins: The <code>id</code> manifest property is now required. If not set, it will be the plugin filename or directory.</li>
</ul>
<p>Plugin doc has been updated with some info about the <a href="https://joplinapp.org/api/references/plugin_api/classes/joplin.html">development process</a>.</p>
<ul>
<li>New: Add {{bowm}} and {{bows}} - Beginning Of Week (Monday/Sunday) (<a href="https://github.com/laurent22/joplin/issues/4023">#4023</a> by Helmut K. C. Tessarek)</li>
<li>New: Add config screen to add, remove or enable, disable plugins</li>
<li>New: Add option to toggle spellchecking for the markdown editor (<a href="https://github.com/laurent22/joplin/issues/4109">#4109</a> by <a href="https://github.com/CalebJohn">@CalebJohn</a>)</li>
<li>New: Added toolbar button to switch spell checker language</li>
<li>New: Adds spell checker support for Rich Text editor (<a href="https://github.com/laurent22/joplin/issues/3974">#3974</a>)</li>
<li>New: Allow customising application layout</li>
<li>New: Api: Added ability to watch resource file</li>
<li>New: Api: Added way to get the notes associated with a resource</li>
<li>New: API: Adds ability to paginate data (<a href="https://github.com/laurent22/joplin/issues/3983">#3983</a>)</li>
<li>New: Plugins: Add command &quot;editorSetText&quot; for desktop app</li>
<li>New: Plugins: Add support for editor context menu</li>
<li>New: Plugins: Add support for external CodeMirror plugins (<a href="https://github.com/laurent22/joplin/issues/4015">#4015</a> by <a href="https://github.com/CalebJohn">@CalebJohn</a>)</li>
<li>New: Plugins: Add support for JPL archive format</li>
<li>New: Plugins: Added command to export folders and notes</li>
<li>New: Plugins: Added support app_min_version property and made it required</li>
<li>Fixed: Api: Fix note and resource association end points</li>
<li>Fixed: Display note count for conflict folder, and display notes even if they are completed to-dos (<a href="https://github.com/laurent22/joplin/issues/3997">#3997</a>)</li>
<li>Fixed: Fix crash due to React when trying to upgrade sync target (<a href="https://github.com/laurent22/joplin/issues/4098">#4098</a>)</li>
<li>Fixed: Fix drag and drop behaviour to &quot;copy&quot; instead of &quot;move&quot; (<a href="https://github.com/laurent22/joplin/issues/4031">#4031</a> by <a href="https://github.com/CalebJohn">@CalebJohn</a>)</li>
<li>Fixed: Fix handling of certain keys in shortcut editor (<a href="https://github.com/laurent22/joplin/issues/4022">#4022</a> by Helmut K. C. Tessarek)</li>
<li>Fixed: Fix handling of new line escaping when using external edit</li>
<li>Fixed: Fix size of search bar area when notebook is empty</li>
<li>Fixed: Fixed importing certain ENEX files that contain invalid dates</li>
<li>Fixed: Fixed inconsistent note list state when using search (<a href="https://github.com/laurent22/joplin/issues/3904">#3904</a>)</li>
<li>Fixed: Fixed issue when a newly created note would be automatically moved to the wrong folder on save (<a href="https://github.com/laurent22/joplin/issues/4038">#4038</a>)</li>
<li>Fixed: Fixed issue with note being saved after word has been replaced by spell checker</li>
<li>Fixed: Fixed links imported from ENEX as HTML (<a href="https://github.com/laurent22/joplin/issues/4119">#4119</a>)</li>
<li>Fixed: Fixed Markdown rendering when code highlighting is disabled</li>
<li>Fixed: Fixed note list overflow when resized very small</li>
<li>Fixed: Fixed text editor button tooltips</li>
<li>Fixed: Plugins: Fix crash when path includes trailing slash</li>
<li>Fixed: Plugins: Fixed issue with dialog being empty in some cases</li>
<li>Fixed: Plugins: Fixed issue with toolbar button key not being unique</li>
<li>Fixed: Prevent log from filling up when certain external editors trigger many watch events (<a href="https://github.com/laurent22/joplin/issues/4011">#4011</a>)</li>
<li>Fixed: Regression: Fix application name</li>
<li>Fixed: Regression: Fix exporting to HTML and PDF</li>
<li>Fixed: Regression: Fixed external edit file watching</li>
<li>Fixed: Resource links could not be opened from Rich Text editor on Linux (<a href="https://github.com/laurent22/joplin/issues/4073">#4073</a>)</li>
<li>Fixed: Tags could not be selected in some cases (<a href="https://github.com/laurent22/joplin/issues/3876">#3876</a>)</li>
<li>Improved: Allow exporting conflict notes (<a href="https://github.com/laurent22/joplin/issues/4095">#4095</a>)</li>
<li>Improved: Allow lowercase filters when doing search</li>
<li>Improved: Api: Always include 'has_more' field for paginated data</li>
<li>Improved: Api: Make sure pagination sort options are respected for search and other requests</li>
<li>Improved: Attempt to fix Outlook drag and drop on Markdown editor (<a href="https://github.com/laurent22/joplin/issues/4093">#4093</a> by <a href="https://github.com/CalebJohn">@CalebJohn</a>)</li>
<li>Improved: Change Markdown rendering to align with CommonMark spec (<a href="https://github.com/laurent22/joplin/issues/3839">#3839</a>)</li>
<li>Improved: Disable spell checker on config and search input fields</li>
<li>Improved: Disabled the auto update option in linux (<a href="https://github.com/laurent22/joplin/issues/4102">#4102</a>) (<a href="https://github.com/laurent22/joplin/issues/4096">#4096</a> by Anshuman Pandey)</li>
<li>Improved: Make Markdown editor selection more visible in Dark mode</li>
<li>Improved: Optimized resizing window</li>
<li>Improved: Plugins: Allow retrieving form values from dialogs</li>
<li>Improved: Plugins: Force plugin devtool dialog to be detached</li>
<li>Improved: Plugins: Make sure &quot;replaceSelection&quot; command can be undone in Rich Text editor</li>
<li>Improved: Plugins: Provides selected notes when triggering a command from the note list context menu</li>
<li>Improved: Plugins: Rename command &quot;editorSetText&quot; to &quot;editor.setText&quot;</li>
<li>Improved: Prevent lines from shifting in Markdown Editor when Scrollbar appears (<a href="https://github.com/laurent22/joplin/issues/4110">#4110</a> by <a href="https://github.com/CalebJohn">@CalebJohn</a>)</li>
<li>Improved: Put title bar and toolbar button over two lines when window size is below 800px</li>
<li>Improved: Refresh sidebar and notes when moving note outside of conflict folder</li>
<li>Improved: Upgrade to Electron 10</li>
</ul>
<h2><a href="https://github.com/laurent22/joplin/releases/tag/v1.3.18">v1.3.18</a> - 2020-11-06T12:07:02Z<a name="v1-3-18-https-github-com-laurent22-joplin-releases-tag-v1-3-18-2020-11-06t12-07-02z" href="#v1-3-18-https-github-com-laurent22-joplin-releases-tag-v1-3-18-2020-11-06t12-07-02z" class="heading-anchor">🔗</a></h2>
<ul>
<li>Regression: Random crash when syncing due to undefined tags (<a href="https://github.com/laurent22/joplin/issues/4051">#4051</a>)</li>

View File

@@ -399,14 +399,6 @@ https://github.com/laurent22/joplin/blob/dev/readme/changelog_cli.md
<div class="main">
<h1>Joplin terminal app changelog<a name="joplin-terminal-app-changelog" href="#joplin-terminal-app-changelog" class="heading-anchor">🔗</a></h1>
<h2><a href="https://github.com/laurent22/joplin/releases/tag/cli-v1.4.9">cli-v1.4.9</a> - 2020-11-26T15:00:37Z<a name="cli-v1-4-9-https-github-com-laurent22-joplin-releases-tag-cli-v1-4-9-2020-11-26t15-00-37z" href="#cli-v1-4-9-https-github-com-laurent22-joplin-releases-tag-cli-v1-4-9-2020-11-26t15-00-37z" class="heading-anchor">🔗</a></h2>
<ul>
<li>Improved: Allow exporting conflict notes (#4095)</li>
<li>Improved: Allow lowercase filters when doing search</li>
<li>Improved: Refresh sidebar and notes when moving note outside of conflict folder</li>
<li>Fixed: Fix handling of new line escaping when using external edit</li>
<li>Fixed: Fixed importing certain ENEX files that contain invalid dates</li>
</ul>
<h2><a href="https://github.com/laurent22/joplin/releases/tag/cli-v1.4.3">cli-v1.4.3</a> - 2020-11-06T21:19:29Z<a name="cli-v1-4-3-https-github-com-laurent22-joplin-releases-tag-cli-v1-4-3-2020-11-06t21-19-29z" href="#cli-v1-4-3-https-github-com-laurent22-joplin-releases-tag-cli-v1-4-3-2020-11-06t21-19-29z" class="heading-anchor">🔗</a></h2>
<p>IMPORTANT: If you use the web API, please note that there are a few breaking changes in this release. See here for more information: <a href="https://github.com/laurent22/joplin/pull/3983#issue-509624899">https://github.com/laurent22/joplin/pull/3983#issue-509624899</a></p>
<ul>

View File

@@ -400,39 +400,21 @@ https://github.com/laurent22/joplin/blob/dev/readme/donate.md
<div class="main">
<h1>Support Joplin development<a name="support-joplin-development" href="#support-joplin-development" class="heading-anchor">🔗</a></h1>
<p>Donations to Joplin support the development of the project. Developing quality applications mostly takes time, but there are also some expenses, such as digital certificates to sign the applications, app store fees, hosting, etc. Most of all, your donation will make it possible to keep up the current development standards.</p>
<h2>Donations<a name="donations" href="#donations" class="heading-anchor">🔗</a></h2>
<table>
<thead>
<tr>
<th>Platform</th>
<th>Link</th>
</tr>
</thead>
<tbody>
<tr>
<td>Paypal</td>
<td><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=E8JMYD2LQ8MMA&amp;lc=GB&amp;item_name=Joplin+Development&amp;currency_code=EUR&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"><img src="https://joplinapp.org/images/badges/Donate-PayPal-green.svg" alt="Donate on PayPal"></a></td>
</tr>
<tr>
<td>GitHub Sponsor</td>
<td><a href="https://github.com/sponsors/laurent22/"><img src="https://joplinapp.org/images/badges/GitHub-Badge.svg" alt="Sponsor on GitHub"></a></td>
</tr>
<tr>
<td>Patreon</td>
<td><a href="https://www.patreon.com/joplin"><img src="https://joplinapp.org/images/badges/Patreon-Badge.svg" alt="Become a patron"></a></td>
</tr>
<tr>
<td>Bank Transfer</td>
<td><strong>IBAN:</strong> FR76 4061 8803 5200 0400 7415 938<br><strong>BIC/SWIFT:</strong> BOUS FRPP XXX</td>
</tr>
</tbody>
</table>
<h2>PayPal<a name="paypal" href="#paypal" class="heading-anchor">🔗</a></h2>
<p>To donate via PayPal, please follow this link:</p>
<p><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=E8JMYD2LQ8MMA&amp;lc=GB&amp;item_name=Joplin+Development&amp;currency_code=EUR&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"><img src="https://joplinapp.org/images/badges/Donate-PayPal-green.svg" alt="Donate on PayPal"></a></p>
<h2>GitHub Sponsor<a name="github-sponsor" href="#github-sponsor" class="heading-anchor">🔗</a></h2>
<p>Or follow this link to become a GitHub Sponsor:</p>
<p><a href="https://github.com/sponsors/laurent22/"><img src="https://joplinapp.org/images/badges/GitHub-Badge.svg" alt="Sponsor on GitHub"></a></p>
<h2>Patreon<a name="patreon" href="#patreon" class="heading-anchor">🔗</a></h2>
<p>Alternatively you may support the project on Patreon:</p>
<p><a href="https://www.patreon.com/joplin"><img src="https://joplinapp.org/images/badges/Patreon-Badge.svg" alt="Become a patron"></a></p>
<h2>Other way to support the development<a name="other-way-to-support-the-development" href="#other-way-to-support-the-development" class="heading-anchor">🔗</a></h2>
<p>Finally, there are other ways to support the development of Joplin:</p>
<ul>
<li>Consider rating the app on <a href="https://play.google.com/store/apps/details?id=net.cozic.joplin&amp;utm_source=GitHub&amp;utm_campaign=README&amp;pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1">Google Play</a> or <a href="https://itunes.apple.com/us/app/joplin/id1315599797">App Store</a>.</li>
<li>Vote for or review the app on <a href="https://alternativeto.net/software/joplin/">alternativeTo</a> or <a href="https://www.producthunt.com/posts/joplin">Product Hunt</a>.</li>
<li><a href="https://joplinapp.org/#localisation">Create or update a translation</a>.</li>
<li>Vote for or review the app on <a href="https://alternativeto.net/software/joplin/">alternativeTo</a> or <a href="https://www.producthunt.com/posts/joplin">Product Hunt</a>.</li>
</ul>
<div class="bottom-links">

View File

@@ -419,17 +419,17 @@ https://github.com/laurent22/joplin/blob/dev/README.md
<tbody>
<tr>
<td>Windows (32 and 64-bit)</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/Joplin-Setup-1.4.18.exe'><img alt='Get it on Windows' width="134px" src='https://joplinapp.org/images/BadgeWindows.png'/></a></td>
<td>Or get the <a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/JoplinPortable.exe'>Portable version</a><br><br>The <a href="https://en.wikipedia.org/wiki/Portable_application">portable application</a> allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called &quot;JoplinProfile&quot; next to the executable file.</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/Joplin-Setup-1.3.18.exe'><img alt='Get it on Windows' width="134px" src='https://joplinapp.org/images/BadgeWindows.png'/></a></td>
<td>Or get the <a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/JoplinPortable.exe'>Portable version</a><br><br>The <a href="https://en.wikipedia.org/wiki/Portable_application">portable application</a> allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called &quot;JoplinProfile&quot; next to the executable file.</td>
</tr>
<tr>
<td>macOS</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/Joplin-1.4.18.dmg'><img alt='Get it on macOS' width="134px" src='https://joplinapp.org/images/BadgeMacOS.png'/></a></td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/Joplin-1.3.18.dmg'><img alt='Get it on macOS' width="134px" src='https://joplinapp.org/images/BadgeMacOS.png'/></a></td>
<td>You can also use Homebrew (unsupported): <code>brew cask install joplin</code></td>
</tr>
<tr>
<td>Linux</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.4.18/Joplin-1.4.18.AppImage'><img alt='Get it on Linux' width="134px" src='https://joplinapp.org/images/BadgeLinux.png'/></a></td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.3.18/Joplin-1.3.18.AppImage'><img alt='Get it on Linux' width="134px" src='https://joplinapp.org/images/BadgeLinux.png'/></a></td>
<td>An Arch Linux package (unsupported) <a href="#terminal-application">is also available</a>.<br><br>If it works with your distribution (it has been tested on Ubuntu, Fedora, and Mint; the desktop environments supported are GNOME, KDE, Xfce, MATE, LXQT, LXDE, Unity, Cinnamon, Deepin and Pantheon), the recommended way is to use this script as it will handle the desktop icon too:<br><br> <code>wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh | bash</code></td>
</tr>
</tbody>
@@ -447,7 +447,7 @@ https://github.com/laurent22/joplin/blob/dev/README.md
<tr>
<td>Android</td>
<td><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://joplinapp.org/images/BadgeAndroid.png'/></a></td>
<td>or download the APK file: <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.4.11/joplin-v1.4.11.apk">64-bit</a> <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.4.11/joplin-v1.4.11-32bit.apk">32-bit</a></td>
<td>or download the APK file: <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.3.13/joplin-v1.3.13.apk">64-bit</a> <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.3.13/joplin-v1.3.13-32bit.apk">32-bit</a></td>
</tr>
<tr>
<td>iOS</td>
@@ -856,40 +856,15 @@ Eg. <code>:search -- &quot;-tag:tag1&quot;</code>.</p>
<p>Donations to Joplin support the development of the project. Developing quality applications mostly takes time, but there are also some expenses, such as digital certificates to sign the applications, app store fees, hosting, etc. Most of all, your donation will make it possible to keep up the current development standard.</p>
<p>Please see the <a href="https://joplinapp.org/donate/">donation page</a> for information on how to support the development of Joplin.</p>
<h1>Community<a name="community" href="#community" class="heading-anchor">🔗</a></h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://discourse.joplinapp.org/">Support Forum</a></td>
<td>This is the main place for general discussion about Joplin, user support, software development questions, and to discuss new features. Also where the latest beta versions are released and discussed.</td>
</tr>
<tr>
<td><a href="https://www.reddit.com/r/joplinapp/">Sub-reddit</a></td>
<td>Also a good place to get help</td>
</tr>
<tr>
<td><a href="https://discordapp.com/invite/d2HMPwE">Discord server</a></td>
<td>Our chat server</td>
</tr>
<tr>
<td><a href="https://www.patreon.com/joplin">Patreon page</a></td>
<td>The latest news are often posted there</td>
</tr>
<tr>
<td><a href="https://mastodon.social/@joplinapp">Mastodon feed</a></td>
<td>Follow us on Mastodon</td>
</tr>
<tr>
<td><a href="https://twitter.com/joplinapp">Twitter feed</a></td>
<td>Follow us on Twitter</td>
</tr>
</tbody>
</table>
<ul>
<li>For general discussion about Joplin, user support, software development questions, and to discuss new features, go to the <a href="https://discourse.joplinapp.org/">Joplin Forum</a>. It is possible to login with your GitHub account.</li>
<li>Also see here for information about <a href="https://discourse.joplinapp.org/c/news">the latest releases and general news</a>.</li>
<li>For bug reports go to the <a href="https://github.com/laurent22/joplin/issues">GitHub Issue Tracker</a>. Please follow the template accordingly.</li>
<li>Feature requests must not be opened on GitHub unless they have been discussed and accepted on the forum.</li>
<li>The latest news are posted <a href="https://www.patreon.com/joplin">on the Patreon page</a>.</li>
<li>You can also follow us on <a rel="me" href="https://mastodon.social/@joplinapp">the Mastodon feed</a> or <a href="https://twitter.com/joplinapp">the Twitter feed</a>.</li>
<li>You can join the live community on <a href="https://discordapp.com/invite/d2HMPwE">the JoplinApp discord server</a> to get help with Joplin or to discuss anything Joplin related.</li>
</ul>
<h1>Contributing<a name="contributing" href="#contributing" class="heading-anchor">🔗</a></h1>
<p>Please see the guide for information on how to contribute to the development of Joplin: <a href="https://github.com/laurent22/joplin/blob/dev/CONTRIBUTING.md">https://github.com/laurent22/joplin/blob/dev/CONTRIBUTING.md</a></p>
<h1>Localisation<a name="localisation" href="#localisation" class="heading-anchor">🔗</a></h1>

View File

@@ -409,15 +409,15 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<tbody>
<tr>
<td>Total Windows downloads</td>
<td>1,121,074</td>
<td>1,096,772</td>
</tr>
<tr>
<td>Total macOs downloads</td>
<td>434,816</td>
<td>425,802</td>
</tr>
<tr>
<td>Total Linux downloads</td>
<td>318,581</td>
<td>310,292</td>
</tr>
<tr>
<td>Windows %</td>
@@ -446,148 +446,116 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
</thead>
<tbody>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.18">v1.4.18</a></td>
<td>2020-11-28T12:21:41Z</td>
<td>3,390</td>
<td>1,584</td>
<td>1,141</td>
<td>6,115</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.16">v1.4.16</a></td>
<td>2020-11-27T19:40:16Z</td>
<td>1,333</td>
<td>798</td>
<td>573</td>
<td>2,704</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.15">v1.4.15</a></td>
<td>2020-11-27T13:25:43Z</td>
<td>808</td>
<td>465</td>
<td>248</td>
<td>1,521</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.4.12">v1.4.12</a></td>
<td>2020-11-23T18:58:07Z</td>
<td>2,807</td>
<td>1,278</td>
<td>1,256</td>
<td>5,341</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.3.18">v1.3.18</a></td>
<td>2020-11-06T12:07:02Z</td>
<td>29,861</td>
<td>11,217</td>
<td>10,451</td>
<td>51,529</td>
<td>14,764</td>
<td>6,490</td>
<td>5,476</td>
<td>26,730</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.3.15">v1.3.15</a></td>
<td>2020-11-04T12:22:50Z</td>
<td>2,155</td>
<td>1,270</td>
<td>826</td>
<td>4,251</td>
<td>2,133</td>
<td>1,260</td>
<td>824</td>
<td>4,217</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.2.6">v1.2.6</a></td>
<td>2020-10-09T13:56:59Z</td>
<td>43,519</td>
<td>17,667</td>
<td>14,004</td>
<td>75,190</td>
<td>43,408</td>
<td>17,645</td>
<td>13,992</td>
<td>75,045</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.1.4">v1.1.4</a></td>
<td>2020-09-21T11:20:09Z</td>
<td>27,413</td>
<td>13,460</td>
<td>7,696</td>
<td>48,569</td>
<td>27,403</td>
<td>13,458</td>
<td>7,694</td>
<td>48,555</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.245">v1.0.245</a></td>
<td>2020-09-09T12:56:10Z</td>
<td>20,791</td>
<td>9,964</td>
<td>5,618</td>
<td>36,373</td>
<td>20,771</td>
<td>9,961</td>
<td>5,617</td>
<td>36,349</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.242">v1.0.242</a></td>
<td>2020-09-04T22:00:34Z</td>
<td>12,309</td>
<td>6,396</td>
<td>12,301</td>
<td>6,394</td>
<td>3,007</td>
<td>21,712</td>
<td>21,702</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.241">v1.0.241</a></td>
<td>2020-09-04T18:06:00Z</td>
<td>23,078</td>
<td>5,689</td>
<td>4,961</td>
<td>33,728</td>
<td>23,069</td>
<td>5,684</td>
<td>4,959</td>
<td>33,712</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.233">v1.0.233</a></td>
<td>2020-08-01T14:51:15Z</td>
<td>42,344</td>
<td>18,156</td>
<td>42,195</td>
<td>18,151</td>
<td>12,344</td>
<td>72,844</td>
<td>72,690</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.227">v1.0.227</a></td>
<td>2020-07-07T20:44:54Z</td>
<td>40,163</td>
<td>15,240</td>
<td>9,611</td>
<td>65,014</td>
<td>40,135</td>
<td>15,235</td>
<td>9,610</td>
<td>64,980</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.224">v1.0.224</a></td>
<td>2020-06-20T22:26:08Z</td>
<td>24,711</td>
<td>10,980</td>
<td>24,705</td>
<td>10,977</td>
<td>5,999</td>
<td>41,690</td>
<td>41,681</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.220">v1.0.220</a></td>
<td>2020-06-13T18:26:22Z</td>
<td>31,522</td>
<td>9,890</td>
<td>31,510</td>
<td>9,887</td>
<td>6,407</td>
<td>47,819</td>
<td>47,804</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.218">v1.0.218</a></td>
<td>2020-06-07T10:43:34Z</td>
<td>14,498</td>
<td>6,948</td>
<td>14,488</td>
<td>6,946</td>
<td>2,950</td>
<td>24,396</td>
<td>24,384</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.216">v1.0.216</a></td>
<td>2020-05-24T14:21:01Z</td>
<td>36,541</td>
<td>14,240</td>
<td>36,371</td>
<td>14,235</td>
<td>10,169</td>
<td>60,950</td>
<td>60,775</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.201">v1.0.201</a></td>
<td>2020-04-15T22:55:13Z</td>
<td>52,539</td>
<td>20,035</td>
<td>18,168</td>
<td>90,742</td>
<td>52,378</td>
<td>20,032</td>
<td>18,167</td>
<td>90,577</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.200">v1.0.200</a></td>
@@ -600,106 +568,106 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.199">v1.0.199</a></td>
<td>2020-04-10T18:41:58Z</td>
<td>19,248</td>
<td>19,239</td>
<td>5,878</td>
<td>3,783</td>
<td>28,909</td>
<td>28,900</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.197">v1.0.197</a></td>
<td>2020-03-30T17:21:22Z</td>
<td>22,073</td>
<td>9,507</td>
<td>5,618</td>
<td>37,198</td>
<td>22,062</td>
<td>9,506</td>
<td>5,610</td>
<td>37,178</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.195">v1.0.195</a></td>
<td>2020-03-22T19:56:12Z</td>
<td>18,867</td>
<td>18,860</td>
<td>7,942</td>
<td>4,502</td>
<td>31,311</td>
<td>31,304</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.193">v1.0.193</a></td>
<td>2020-03-08T08:58:53Z</td>
<td>28,598</td>
<td>28,595</td>
<td>10,895</td>
<td>7,356</td>
<td>46,849</td>
<td>46,846</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.179">v1.0.179</a></td>
<td>2020-01-24T22:42:41Z</td>
<td>70,962</td>
<td>28,472</td>
<td>22,494</td>
<td>121,928</td>
<td>70,959</td>
<td>28,467</td>
<td>22,491</td>
<td>121,917</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.178">v1.0.178</a></td>
<td>2020-01-20T19:06:45Z</td>
<td>17,527</td>
<td>17,526</td>
<td>5,956</td>
<td>2,579</td>
<td>26,062</td>
<td>26,061</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.175">v1.0.175</a></td>
<td>2019-12-08T11:48:47Z</td>
<td>72,026</td>
<td>16,856</td>
<td>16,481</td>
<td>105,363</td>
<td>71,981</td>
<td>16,855</td>
<td>16,478</td>
<td>105,314</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.174">v1.0.174</a></td>
<td>2019-11-12T18:20:58Z</td>
<td>30,390</td>
<td>11,689</td>
<td>8,217</td>
<td>50,296</td>
<td>30,388</td>
<td>11,688</td>
<td>8,216</td>
<td>50,292</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.173">v1.0.173</a></td>
<td>2019-11-11T08:33:35Z</td>
<td>5,060</td>
<td>2,072</td>
<td>5,058</td>
<td>2,071</td>
<td>740</td>
<td>7,872</td>
<td>7,869</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.170">v1.0.170</a></td>
<td>2019-10-13T22:13:04Z</td>
<td>27,375</td>
<td>8,739</td>
<td>27,372</td>
<td>8,737</td>
<td>7,668</td>
<td>43,782</td>
<td>43,777</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.169">v1.0.169</a></td>
<td>2019-09-27T18:35:13Z</td>
<td>17,083</td>
<td>5,916</td>
<td>17,081</td>
<td>5,915</td>
<td>3,750</td>
<td>26,749</td>
<td>26,746</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.168">v1.0.168</a></td>
<td>2019-09-25T21:21:38Z</td>
<td>5,323</td>
<td>2,267</td>
<td>2,265</td>
<td>714</td>
<td>8,304</td>
<td>8,302</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.167">v1.0.167</a></td>
<td>2019-09-10T08:48:37Z</td>
<td>16,779</td>
<td>5,699</td>
<td>3,701</td>
<td>26,179</td>
<td>3,700</td>
<td>26,178</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.166">v1.0.166</a></td>
@@ -712,370 +680,370 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.165">v1.0.165</a></td>
<td>2019-08-14T21:46:29Z</td>
<td>18,876</td>
<td>18,875</td>
<td>6,968</td>
<td>5,460</td>
<td>31,304</td>
<td>31,303</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.161">v1.0.161</a></td>
<td>2019-07-13T18:30:00Z</td>
<td>19,274</td>
<td>19,272</td>
<td>6,348</td>
<td>4,133</td>
<td>29,755</td>
<td>29,753</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.160">v1.0.160</a></td>
<td>2019-06-15T00:21:40Z</td>
<td>30,463</td>
<td>30,459</td>
<td>7,742</td>
<td>8,099</td>
<td>46,304</td>
<td>8,098</td>
<td>46,299</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.159">v1.0.159</a></td>
<td>2019-06-08T00:00:19Z</td>
<td>5,190</td>
<td>2,175</td>
<td>5,189</td>
<td>2,174</td>
<td>1,105</td>
<td>8,470</td>
<td>8,468</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.158">v1.0.158</a></td>
<td>2019-05-27T19:01:18Z</td>
<td>9,810</td>
<td>3,536</td>
<td>9,809</td>
<td>3,534</td>
<td>1,934</td>
<td>15,280</td>
<td>15,277</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.157">v1.0.157</a></td>
<td>2019-05-26T17:55:53Z</td>
<td>2,173</td>
<td>842</td>
<td>841</td>
<td>289</td>
<td>3,304</td>
<td>3,303</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.152">v1.0.152</a></td>
<td>2019-05-13T09:08:07Z</td>
<td>13,862</td>
<td>4,424</td>
<td>13,861</td>
<td>4,423</td>
<td>4,060</td>
<td>22,346</td>
<td>22,344</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.151">v1.0.151</a></td>
<td>2019-05-12T15:14:32Z</td>
<td>1,950</td>
<td>1,948</td>
<td>530</td>
<td>956</td>
<td>3,436</td>
<td>955</td>
<td>3,433</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.150">v1.0.150</a></td>
<td>2019-05-12T11:27:48Z</td>
<td>418</td>
<td>129</td>
<td>67</td>
<td>614</td>
<td>66</td>
<td>613</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.145">v1.0.145</a></td>
<td>2019-05-03T09:16:53Z</td>
<td>7,003</td>
<td>2,859</td>
<td>7,000</td>
<td>2,858</td>
<td>1,434</td>
<td>11,296</td>
<td>11,292</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.143">v1.0.143</a></td>
<td>2019-04-22T10:51:38Z</td>
<td>11,912</td>
<td>3,548</td>
<td>2,777</td>
<td>18,237</td>
<td>11,911</td>
<td>3,546</td>
<td>2,776</td>
<td>18,233</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.142">v1.0.142</a></td>
<td>2019-04-02T16:44:51Z</td>
<td>14,650</td>
<td>4,558</td>
<td>14,649</td>
<td>4,557</td>
<td>4,724</td>
<td>23,932</td>
<td>23,930</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.140">v1.0.140</a></td>
<td>2019-03-10T20:59:58Z</td>
<td>13,622</td>
<td>4,166</td>
<td>3,178</td>
<td>20,966</td>
<td>3,172</td>
<td>20,960</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.135">v1.0.135</a></td>
<td>2019-02-27T23:36:57Z</td>
<td>12,486</td>
<td>3,954</td>
<td>4,074</td>
<td>20,514</td>
<td>12,484</td>
<td>3,953</td>
<td>4,073</td>
<td>20,510</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.134">v1.0.134</a></td>
<td>2019-02-27T10:21:44Z</td>
<td>1,464</td>
<td>564</td>
<td>1,463</td>
<td>563</td>
<td>217</td>
<td>2,245</td>
<td>2,243</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.132">v1.0.132</a></td>
<td>2019-02-26T23:02:05Z</td>
<td>1,081</td>
<td>448</td>
<td>94</td>
<td>1,623</td>
<td>447</td>
<td>93</td>
<td>1,621</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.127">v1.0.127</a></td>
<td>2019-02-14T23:12:48Z</td>
<td>9,741</td>
<td>3,165</td>
<td>9,734</td>
<td>3,164</td>
<td>2,928</td>
<td>15,834</td>
<td>15,826</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.125">v1.0.125</a></td>
<td>2019-01-26T18:14:33Z</td>
<td>10,246</td>
<td>3,554</td>
<td>10,245</td>
<td>3,552</td>
<td>1,701</td>
<td>15,501</td>
<td>15,498</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.120">v1.0.120</a></td>
<td>2019-01-10T21:42:53Z</td>
<td>15,599</td>
<td>5,197</td>
<td>6,514</td>
<td>27,310</td>
<td>15,598</td>
<td>5,196</td>
<td>6,512</td>
<td>27,306</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.119">v1.0.119</a></td>
<td>2018-12-18T12:40:22Z</td>
<td>8,902</td>
<td>3,259</td>
<td>3,257</td>
<td>2,013</td>
<td>14,174</td>
<td>14,172</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.118">v1.0.118</a></td>
<td>2019-01-11T08:34:13Z</td>
<td>713</td>
<td>246</td>
<td>88</td>
<td>1,047</td>
<td>244</td>
<td>87</td>
<td>1,044</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.117">v1.0.117</a></td>
<td>2018-11-24T12:05:24Z</td>
<td>16,252</td>
<td>4,892</td>
<td>4,889</td>
<td>6,379</td>
<td>27,523</td>
<td>27,520</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.116">v1.0.116</a></td>
<td>2018-11-20T19:09:24Z</td>
<td>3,469</td>
<td>1,119</td>
<td>3,468</td>
<td>1,117</td>
<td>712</td>
<td>5,300</td>
<td>5,297</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.115">v1.0.115</a></td>
<td>2018-11-16T16:52:02Z</td>
<td>3,653</td>
<td>1,300</td>
<td>3,652</td>
<td>1,299</td>
<td>797</td>
<td>5,750</td>
<td>5,748</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.114">v1.0.114</a></td>
<td>2018-10-24T20:14:10Z</td>
<td>11,393</td>
<td>3,494</td>
<td>3,492</td>
<td>3,828</td>
<td>18,715</td>
<td>18,713</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.111">v1.0.111</a></td>
<td>2018-09-30T20:15:09Z</td>
<td>12,008</td>
<td>3,290</td>
<td>3,667</td>
<td>18,965</td>
<td>12,007</td>
<td>3,286</td>
<td>3,663</td>
<td>18,956</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.110">v1.0.110</a></td>
<td>2018-09-29T12:29:21Z</td>
<td>956</td>
<td>407</td>
<td>117</td>
<td>1,480</td>
<td>405</td>
<td>116</td>
<td>1,477</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.109">v1.0.109</a></td>
<td>2018-09-27T18:01:41Z</td>
<td>2,098</td>
<td>703</td>
<td>2,096</td>
<td>700</td>
<td>326</td>
<td>3,127</td>
<td>3,122</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.107">v1.0.107</a></td>
<td>2018-09-16T19:51:07Z</td>
<td>7,146</td>
<td>2,134</td>
<td>7,145</td>
<td>2,132</td>
<td>1,705</td>
<td>10,985</td>
<td>10,982</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.106">v1.0.106</a></td>
<td>2018-09-08T15:23:40Z</td>
<td>4,554</td>
<td>1,455</td>
<td>4,553</td>
<td>1,453</td>
<td>316</td>
<td>6,325</td>
<td>6,322</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.105">v1.0.105</a></td>
<td>2018-09-05T11:29:36Z</td>
<td>4,652</td>
<td>1,587</td>
<td>1,585</td>
<td>1,453</td>
<td>7,692</td>
<td>7,690</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.104">v1.0.104</a></td>
<td>2018-06-28T20:25:36Z</td>
<td>15,043</td>
<td>4,698</td>
<td>7,328</td>
<td>27,069</td>
<td>15,038</td>
<td>4,696</td>
<td>7,327</td>
<td>27,061</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.103">v1.0.103</a></td>
<td>2018-06-21T19:38:13Z</td>
<td>2,050</td>
<td>883</td>
<td>2,049</td>
<td>882</td>
<td>679</td>
<td>3,612</td>
<td>3,610</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.101">v1.0.101</a></td>
<td>2018-06-17T18:35:11Z</td>
<td>1,306</td>
<td>606</td>
<td>408</td>
<td>2,320</td>
<td>1,304</td>
<td>604</td>
<td>407</td>
<td>2,315</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.100">v1.0.100</a></td>
<td>2018-06-14T17:41:43Z</td>
<td>877</td>
<td>431</td>
<td>240</td>
<td>1,548</td>
<td>875</td>
<td>429</td>
<td>239</td>
<td>1,543</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.99">v1.0.99</a></td>
<td>2018-06-10T13:18:23Z</td>
<td>1,251</td>
<td>594</td>
<td>1,250</td>
<td>593</td>
<td>379</td>
<td>2,224</td>
<td>2,222</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.97">v1.0.97</a></td>
<td>2018-06-09T19:23:34Z</td>
<td>309</td>
<td>156</td>
<td>60</td>
<td>525</td>
<td>154</td>
<td>59</td>
<td>522</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.96">v1.0.96</a></td>
<td>2018-05-26T16:36:39Z</td>
<td>2,715</td>
<td>1,222</td>
<td>1,617</td>
<td>5,554</td>
<td>1,221</td>
<td>1,606</td>
<td>5,542</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.95">v1.0.95</a></td>
<td>2018-05-25T13:04:30Z</td>
<td>415</td>
<td>217</td>
<td>118</td>
<td>750</td>
<td>215</td>
<td>116</td>
<td>746</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.94">v1.0.94</a></td>
<td>2018-05-21T20:52:59Z</td>
<td>1,128</td>
<td>582</td>
<td>580</td>
<td>395</td>
<td>2,105</td>
<td>2,103</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.93">v1.0.93</a></td>
<td>2018-05-14T11:36:01Z</td>
<td>1,787</td>
<td>1,090</td>
<td>756</td>
<td>3,633</td>
<td>1,786</td>
<td>1,081</td>
<td>755</td>
<td>3,622</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.91">v1.0.91</a></td>
<td>2018-05-10T14:48:04Z</td>
<td>825</td>
<td>548</td>
<td>304</td>
<td>1,677</td>
<td>824</td>
<td>547</td>
<td>303</td>
<td>1,674</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.89">v1.0.89</a></td>
<td>2018-05-09T13:05:05Z</td>
<td>489</td>
<td>228</td>
<td>488</td>
<td>227</td>
<td>107</td>
<td>824</td>
<td>822</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.85">v1.0.85</a></td>
<td>2018-05-01T21:08:24Z</td>
<td>1,648</td>
<td>948</td>
<td>628</td>
<td>3,224</td>
<td>1,647</td>
<td>946</td>
<td>627</td>
<td>3,220</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.83">v1.0.83</a></td>
<td>2018-04-04T19:43:58Z</td>
<td>4,814</td>
<td>4,809</td>
<td>2,529</td>
<td>2,656</td>
<td>9,999</td>
<td>9,994</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.82">v1.0.82</a></td>
<td>2018-03-31T19:16:31Z</td>
<td>692</td>
<td>401</td>
<td>400</td>
<td>119</td>
<td>1,212</td>
<td>1,211</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.81">v1.0.81</a></td>
@@ -1104,10 +1072,10 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.77">v1.0.77</a></td>
<td>2018-03-16T15:12:35Z</td>
<td>177</td>
<td>176</td>
<td>103</td>
<td>44</td>
<td>324</td>
<td>323</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.72">v1.0.72</a></td>
@@ -1122,8 +1090,8 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<td>2018-02-28T20:04:30Z</td>
<td>1,853</td>
<td>1,049</td>
<td>1,252</td>
<td>4,154</td>
<td>1,251</td>
<td>4,153</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.67">v1.0.67</a></td>
@@ -1145,9 +1113,9 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.65">v1.0.65</a></td>
<td>2018-02-17T20:02:25Z</td>
<td>193</td>
<td>126</td>
<td>124</td>
<td>133</td>
<td>452</td>
<td>450</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.64">v1.0.64</a></td>
@@ -1178,8 +1146,8 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<td>2018-02-08T18:27:39Z</td>
<td>971</td>
<td>630</td>
<td>960</td>
<td>2,561</td>
<td>958</td>
<td>2,559</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.60">v0.10.60</a></td>
@@ -1194,8 +1162,8 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<td>2018-01-31T20:21:30Z</td>
<td>1,819</td>
<td>1,458</td>
<td>322</td>
<td>3,599</td>
<td>321</td>
<td>3,598</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.52">v0.10.52</a></td>
@@ -1256,10 +1224,10 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.39">v0.10.39</a></td>
<td>2017-12-11T21:19:44Z</td>
<td>5,790</td>
<td>4,262</td>
<td>3,164</td>
<td>13,216</td>
<td>5,784</td>
<td>4,258</td>
<td>3,160</td>
<td>13,202</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.38">v0.10.38</a></td>
@@ -1346,8 +1314,8 @@ https://github.com/laurent22/joplin/blob/dev/readme/stats.md
<td>2017-11-24T14:27:49Z</td>
<td>148</td>
<td>694</td>
<td>6,389</td>
<td>7,231</td>
<td>6,378</td>
<td>7,220</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.23">v0.10.23</a></td>

View File

@@ -37,8 +37,7 @@
"tsc": "lerna run tsc --stream --parallel",
"updateIgnored": "gulp updateIgnoredTypeScriptBuild",
"updatePluginTypes": "./packages/generator-joplin/updateTypes.sh",
"watch": "lerna run watch --stream --parallel",
"i": "lerna add --no-bootstrap --scope"
"watch": "lerna run watch --stream --parallel"
},
"husky": {
"hooks": {

View File

@@ -5,7 +5,6 @@ import BasePluginRunner from '@joplin/lib/services/plugins/BasePluginRunner';
import executeSandboxCall from '@joplin/lib/services/plugins/utils/executeSandboxCall';
import Global from '@joplin/lib/services/plugins/api/Global';
import mapEventHandlersToIds, { EventHandlers } from '@joplin/lib/services/plugins/utils/mapEventHandlersToIds';
import uuid from '@joplin/lib/uuid';
function createConsoleWrapper(pluginId: string) {
const wrapper: any = {};
@@ -32,7 +31,6 @@ function createConsoleWrapper(pluginId: string) {
export default class PluginRunner extends BasePluginRunner {
private eventHandlers_: EventHandlers = {};
private activeSandboxCalls_: any = {};
constructor() {
super();
@@ -47,13 +45,7 @@ export default class PluginRunner extends BasePluginRunner {
private newSandboxProxy(pluginId: string, sandbox: Global) {
const target = async (path: string, args: any[]) => {
const callId = `${pluginId}::${path}::${uuid.createNano()}`;
this.activeSandboxCalls_[callId] = true;
const promise = executeSandboxCall(pluginId, sandbox, `joplin.${path}`, mapEventHandlersToIds(args, this.eventHandlers_), this.eventHandler);
promise.finally(() => {
delete this.activeSandboxCalls_[callId];
});
return promise;
return executeSandboxCall(pluginId, sandbox, `joplin.${path}`, mapEventHandlersToIds(args, this.eventHandlers_), this.eventHandler);
};
return {
@@ -77,25 +69,10 @@ export default class PluginRunner extends BasePluginRunner {
vm.runInContext(plugin.scriptText, vmSandbox);
} catch (error) {
reject(error);
// this.logger().error(`In plugin ${plugin.id}:`, error);
// return;
}
});
}
public async waitForSandboxCalls(): Promise<void> {
const startTime = Date.now();
return new Promise((resolve: Function, reject: Function) => {
const iid = setInterval(() => {
if (!Object.keys(this.activeSandboxCalls_).length) {
clearInterval(iid);
resolve();
}
if (Date.now() - startTime > 4000) {
clearInterval(iid);
reject(new Error(`Timeout while waiting for sandbox calls to complete: ${JSON.stringify(this.activeSandboxCalls_)}`));
}
}, 10);
});
}
}

View File

@@ -5,9 +5,9 @@
"author": "Laurent Cozic",
"private": true,
"scripts": {
"test": "jest --config=jest.config.js --bail --forceExit",
"test-one": "jest --verbose=false --config=jest.config.js --bail --forceExit",
"test-ci": "jest --config=jest.config.js --forceExit",
"test": "jest --config=jest.config.js --runInBand --bail --forceExit",
"test-one": "jest --verbose=false --config=jest.config.js --runInBand --bail --forceExit",
"test-ci": "jest --config=jest.config.js --runInBand --forceExit",
"build": "gulp build",
"start": "gulp build -L && node \"build/main.js\" --stack-trace-enabled --log-level debug --env dev",
"tsc": "node node_modules/typescript/bin/tsc --project tsconfig.json",
@@ -31,7 +31,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.5.0",
"version": "1.4.9",
"bin": {
"joplin": "./main.js"
},

View File

@@ -4,7 +4,7 @@ import shim from '@joplin/lib/shim';
const fs = require('fs-extra');
const os = require('os');
const { filename } = require('@joplin/lib/path-utils');
const { setupDatabaseAndSynchronizer, switchClient, expectNotThrow } = require('./test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
const { enexXmlToMd } = require('@joplin/lib/import-enex-md-gen.js');
const { importEnex } = require('@joplin/lib/import-enex');
const Note = require('@joplin/lib/models/Note');
@@ -96,21 +96,4 @@ describe('EnexToMd', function() {
expect(note.updated_time).toBe(1521822724000); // Because this date was invalid, it is set to the created time instead
});
it('should handle empty resources', async () => {
const filePath = `${enexSampleBaseDir}/empty_resource.enex`;
await expectNotThrow(() => importEnex('', filePath));
const all = await Resource.all();
expect(all.length).toBe(1);
expect(all[0].size).toBe(0);
});
it('should handle empty note content', async () => {
const filePath = `${enexSampleBaseDir}/empty_content.enex`;
await expectNotThrow(() => importEnex('', filePath));
const all = await Note.all();
expect(all.length).toBe(1);
expect(all[0].title).toBe('China and the case for stimulus.');
expect(all[0].body).toBe('');
});
});

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export2.dtd">
<en-export export-date="20201130T021533Z" application="Evernote/Windows" version="6.x">
<note>
<title>China and the case for stimulus.</title>
<content></content>
<created>20120904T185210Z</created>
<note-attributes>
<source>web.clip</source>
</note-attributes>
</note></en-export>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export2.dtd">
<en-export export-date="20201130T021533Z" application="Evernote/Windows" version="6.x">
<note><title>China and the case for stimulus.</title><content></content><created>20120904T185210Z</created><note-attributes><source>web.clip</source><source-url>http://www.slate.com/blogs/moneybox/2012/09/04/china_and_the_case_for_stimulus.html</source-url></note-attributes>
<resource>
<data/>
<mime>application/octet-stream</mime>
<resource-attributes>
<file-name>04\</file-name>
</resource-attributes>
</resource>
</note></en-export>

View File

@@ -1,52 +0,0 @@
import PluginService from '@joplin/lib/services/plugins/PluginService';
const { newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } = require('../../../test-utils');
const Note = require('@joplin/lib/models/Note');
const Folder = require('@joplin/lib/models/Folder');
const ItemChange = require('@joplin/lib/models/ItemChange');
describe('JoplinWorkspace', () => {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
afterEach(async () => {
await afterEachCleanUp();
});
test('should listen to noteChange events', async () => {
const service = new newPluginService() as PluginService;
const pluginScript = newPluginScript(`
joplin.plugins.register({
onStart: async function() {
await joplin.workspace.onNoteChange(async (event) => {
await joplin.data.post(['folders'], null, { title: JSON.stringify(event) });
});
},
});
`);
const note = await Note.save({});
await ItemChange.waitForAllSaved();
const plugin = await service.loadPluginFromJsBundle('', pluginScript);
await service.runPlugin(plugin);
await Note.save({ id: note.id, body: 'testing' });
await ItemChange.waitForAllSaved();
const folder = (await Folder.all())[0];
const result: any = JSON.parse(folder.title);
expect(result.id).toBe(note.id);
expect(result.event).toBe(ItemChange.TYPE_UPDATE);
await service.destroy();
});
});

View File

@@ -22,7 +22,9 @@ function newPluginService(appVersion: string = '1.4') {
service.initialize(
appVersion,
{
joplin: {},
joplin: {
workspace: {},
},
},
runner,
{

View File

@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -50,18 +50,9 @@ const KeychainServiceDriver = require('@joplin/lib/services/keychain/KeychainSer
const KeychainServiceDriverDummy = require('@joplin/lib/services/keychain/KeychainServiceDriver.dummy').default;
const md5 = require('md5');
const S3 = require('aws-sdk/clients/s3');
const PluginRunner = require('../app/services/plugins/PluginRunner').default;
const PluginService = require('@joplin/lib/services/plugins/PluginService').default;
const { Dirnames } = require('@joplin/lib/services/synchronizer/utils/types');
const sharp = require('sharp');
// Each suite has its own separate data and temp directory so that multiple
// suites can be run at the same time. suiteName is what is used to
// differentiate between suite and it is currently set to a random string
// (Ideally it would be something like the filename currently being executed by
// Jest, to make debugging easier, but it's not clear how to get this info).
const suiteName_ = uuid.createNano();
const databases_ = [];
let synchronizers_ = [];
const synchronizerContexts_ = {};
@@ -98,11 +89,10 @@ EncryptionService.fsDriver_ = fsDriver;
FileApiDriverLocal.fsDriver_ = fsDriver;
const logDir = `${__dirname}/../tests/logs`;
const baseTempDir = `${__dirname}/../tests/tmp/${suiteName_}`;
const dataDir = `${__dirname}/data/${suiteName_}`;
const baseTempDir = `${__dirname}/../tests/tmp`;
fs.mkdirpSync(logDir, 0o755);
fs.mkdirpSync(baseTempDir, 0o755);
fs.mkdirpSync(dataDir);
fs.mkdirpSync(`${__dirname}/data`);
SyncTargetRegistry.addClass(SyncTargetMemory);
SyncTargetRegistry.addClass(SyncTargetFilesystem);
@@ -149,12 +139,12 @@ const syncDir = `${__dirname}/../tests/sync`;
const dbLogger = new Logger();
dbLogger.addTarget('console');
// dbLogger.addTarget('file', { path: `${logDir}/log.txt` });
dbLogger.addTarget('file', { path: `${logDir}/log.txt` });
dbLogger.setLevel(Logger.LEVEL_WARN);
const logger = new Logger();
logger.addTarget('console');
// logger.addTarget('file', { path: `${logDir}/log.txt` });
logger.addTarget('file', { path: `${logDir}/log.txt` });
logger.setLevel(Logger.LEVEL_WARN); // Set to DEBUG to display sync process in console
Logger.initializeGlobalLogger(logger);
@@ -279,7 +269,7 @@ async function setupDatabase(id = null, options = null) {
return;
}
const filePath = `${dataDir}/test-${id}.sqlite`;
const filePath = `${__dirname}/data/test-${id}.sqlite`;
try {
await fs.unlink(filePath);
@@ -302,15 +292,15 @@ function resourceDirName(id = null) {
function resourceDir(id = null) {
if (id === null) id = currentClient_;
return `${dataDir}/${resourceDirName(id)}`;
return `${__dirname}/data/${resourceDirName(id)}`;
}
function pluginDir(id = null) {
if (id === null) id = currentClient_;
return `${dataDir}/plugins-${id}`;
return `${__dirname}/data/plugins-${id}`;
}
async function setupDatabaseAndSynchronizer(id, options = null) {
async function setupDatabaseAndSynchronizer(id = null, options = null) {
if (id === null) id = currentClient_;
BaseService.logger_ = logger;
@@ -679,39 +669,6 @@ async function createTempDir() {
return tempDirPath;
}
function newPluginService(appVersion = '1.4') {
const runner = new PluginRunner();
const service = new PluginService();
service.initialize(
appVersion,
{
joplin: {},
},
runner,
{
dispatch: () => {},
getState: () => {},
}
);
return service;
}
function newPluginScript(script) {
return `
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.PluginTest",
"manifest_version": 1,
"app_min_version": "1.4",
"name": "JS Bundle test",
"version": "1.0.0"
}
*/
${script}
`;
}
// TODO: Update for Jest
// function mockDate(year, month, day, tick) {
@@ -792,4 +749,4 @@ class TestApp extends BaseApplication {
}
}
module.exports = { newPluginService, newPluginScript, synchronizerStart, afterEachCleanUp, syncTargetName, setSyncTargetName, syncDir, createTempDir, isNetworkSyncTarget, kvStore, expectThrow, logger, expectNotThrow, resourceService, resourceFetcher, tempFilePath, allSyncTargetItemsEncrypted, msleep, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync, checkThrow, encryptionService, loadEncryptionMasterKey, fileContentEqual, decryptionWorker, asyncTest, currentClientId, id, ids, sortedIds, at, createNTestNotes, createNTestFolders, createNTestTags, TestApp };
module.exports = { synchronizerStart, afterEachCleanUp, syncTargetName, setSyncTargetName, syncDir, createTempDir, isNetworkSyncTarget, kvStore, expectThrow, logger, expectNotThrow, resourceService, resourceFetcher, tempFilePath, allSyncTargetItemsEncrypted, msleep, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync, checkThrow, encryptionService, loadEncryptionMasterKey, fileContentEqual, decryptionWorker, asyncTest, currentClientId, id, ids, sortedIds, at, createNTestNotes, createNTestFolders, createNTestTags, TestApp };

View File

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

View File

@@ -962,13 +962,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
const changeCommands = ['mceBlockQuote', 'ToggleJoplinChecklistItem'];
if (
changeCommands.includes(c) ||
c.indexOf('Insert') === 0 ||
c.indexOf('mceToggle') === 0 ||
c.indexOf('mceInsert') === 0 ||
c.indexOf('mceTable') === 0
) {
if (changeCommands.includes(c) || c.indexOf('Insert') === 0 || c.indexOf('mceToggle') === 0 || c.indexOf('mceInsert') === 0) {
onChangeHandler();
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "1.5.3",
"version": "1.4.18",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "1.5.3",
"version": "1.4.19",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,

View File

@@ -1,5 +1,11 @@
// import { EditorCommand } from '@joplin/lib/services/plugins/api/types';
import bridge from '../bridge';
// interface JoplinWorkspace {
// execEditorCommand(command:EditorCommand):Promise<string>
// }
interface JoplinViewsDialogs {
showMessageBox(message: string): Promise<number>;
}
@@ -9,6 +15,7 @@ interface JoplinViews {
}
interface Joplin {
// workspace: JoplinWorkspace;
views: JoplinViews;
}

View File

@@ -11,17 +11,6 @@ const ipcRenderer = require('electron').ipcRenderer;
const logger = Logger.create('PluginRunner');
// Electron error messages are useless so wrap the renderer call and print
// additional information when an error occurs.
function ipcRendererSend(message: string, args: any) {
try {
return ipcRenderer.send(message, args);
} catch (error) {
logger.error('Could not send IPC message:', message, ': ', args, error);
throw error;
}
}
enum PluginMessageTarget {
MainWindow = 'mainWindow',
Plugin = 'plugin',
@@ -57,7 +46,7 @@ function mapEventIdsToHandlers(pluginId: string, arg: any) {
callbackPromises[callbackId] = { resolve, reject };
});
ipcRendererSend('pluginMessage', {
ipcRenderer.send('pluginMessage', {
callbackId: callbackId,
target: PluginMessageTarget.Plugin,
pluginId: pluginId,
@@ -143,7 +132,7 @@ export default class PluginRunner extends BasePluginRunner {
// Don't log complete HTML code, which can be long, for setHtml calls
const debugMappedArgs = fullPath.includes('setHtml') ? '<hidden>' : mappedArgs;
logger.debug(`Got message (3): ${fullPath}`, debugMappedArgs);
logger.debug(`Got message (3): ${fullPath}: ${debugMappedArgs}`);
let result: any = null;
let error: any = null;
@@ -153,7 +142,7 @@ export default class PluginRunner extends BasePluginRunner {
error = e ? e : new Error('Unknown error');
}
ipcRendererSend('pluginMessage', {
ipcRenderer.send('pluginMessage', {
target: PluginMessageTarget.Plugin,
pluginId: plugin.id,
pluginCallbackId: message.callbackId,

View File

@@ -1,5 +1,13 @@
<html>
<head>
<script src="./plugin_index.js"></script>
</head>
<script>
// joplin.plugins.register({
// onStart: async function() {
// alert('PLUGIN STARTED');
// },
// });
</script>
</head>
</html>

View File

@@ -3,15 +3,6 @@
const sandboxProxy = require('../../node_modules/@joplin/lib/services/plugins/sandboxProxy.js').default;
const ipcRenderer = require('electron').ipcRenderer;
const ipcRendererSend = (message, args) => {
try {
return ipcRenderer.send(message, args);
} catch (error) {
console.error('Could not send IPC message:', message, ': ', args, error);
throw error;
}
};
const urlParams = new URLSearchParams(window.location.search);
const pluginId = urlParams.get('pluginId');
@@ -51,7 +42,7 @@
callbackPromises[callbackId] = { resolve, reject };
});
ipcRendererSend('pluginMessage', {
ipcRenderer.send('pluginMessage', {
target: 'mainWindow',
pluginId: pluginId,
callbackId: callbackId,
@@ -80,7 +71,7 @@
}
if (message.callbackId) {
ipcRendererSend('pluginMessage', {
ipcRenderer.send('pluginMessage', {
target: 'mainWindow',
pluginId: pluginId,
mainWindowCallbackId: message.callbackId,

View File

@@ -5,13 +5,6 @@ const electron_notarize = require('electron-notarize');
module.exports = async function(params) {
if (process.platform !== 'darwin') return;
console.info('Checking if notarization should be done...');
if (!process.env.TRAVIS || !process.env.TRAVIS_TAG) {
console.info(`Either not running in CI or not processing a tag - skipping notarization. process.env.TRAVIS = ${process.env.TRAVIS}; process.env.TRAVIS_TAG = ${process.env.TRAVIS}`);
return;
}
if (!process.env.APPLE_ID || !process.env.APPLE_ID_PASSWORD) {
console.warn('Environment variables APPLE_ID and APPLE_ID_PASSWORD not found - notarization will NOT be done.');
return;

View File

@@ -139,7 +139,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097613
versionName "1.5.0"
versionName "1.4.11"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

View File

@@ -18,11 +18,6 @@
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<!--
Android 10 introduced new "scoped storage" mechanism.
Apps targeting Android 10 (sdk 29) can no longer freely access arbitrary paths on the shared storage.
The attribute "requestLegacyExternalStorage" below allows to opt out of this restriction.
-->
<application
android:name=".MainApplication"
android:label="@string/app_name"
@@ -30,7 +25,6 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:theme="@style/AppTheme">
<!-- RN-NOTIFICATION -->

View File

@@ -344,7 +344,7 @@
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 10.5.0;
MARKETING_VERSION = 10.4.1;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -370,7 +370,7 @@
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 10.5.0;
MARKETING_VERSION = 10.4.1;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",

View File

@@ -0,0 +1,9 @@
{
"generator-node": {
"promptValues": {
"authorName": "Laurent Cozic",
"authorEmail": "laurent@cozic.net",
"authorUrl": ""
}
}
}

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2020 Laurent Cozic
Copyright (c) 2020 Laurent Cozic <laurent@cozic.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

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

View File

@@ -13,7 +13,7 @@ function readManifest(manifestPath) {
}
function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {

View File

@@ -1,6 +1,6 @@
{
"name": "generator-joplin",
"version": "1.5.0",
"version": "1.4.5",
"description": "Scaffolds out a new Joplin plugin",
"homepage": "https://joplinapp.org",
"author": {

View File

@@ -1,6 +1,6 @@
const events = require('events');
export class EventManager {
class EventManager {
private emitter_: any;
private appStatePrevious_: any;

View File

@@ -2,7 +2,6 @@ const { basicDelta } = require('./file-api');
const { basename } = require('./path-utils');
const shim = require('./shim').default;
const JoplinError = require('./JoplinError');
const { Buffer } = require('buffer');
const S3_MAX_DELETES = 1000;
@@ -84,14 +83,12 @@ class FileApiDriverAmazonS3 {
async s3UploadFileFrom(path, key) {
if (!shim.fsDriver().exists(path)) throw new Error('s3UploadFileFrom: file does not exist');
const body = await shim.fsDriver().readFile(path, 'base64');
const fileStat = await shim.fsDriver().stat(path);
const body = await shim.fsDriver().readFile(path, 'Buffer');
return new Promise((resolve, reject) => {
this.api().putObject({
this.api().upload({
Bucket: this.s3_bucket_,
Key: key,
Body: Buffer.from(body, 'base64'),
ContentLength: `${fileStat.size}`,
Body: body,
}, (err, response) => {
if (err) reject(err);
else resolve(response);

View File

@@ -138,36 +138,28 @@ async function fuzzyMatch(note) {
// At this point we have the resource has it's been parsed from the XML, but additional
// processing needs to be done to get the final resource file, its size, MD5, etc.
async function processNoteResource(resource) {
if (!resource.hasData) {
// Some resources have no data, go figure, so we need a special case for this.
resource.id = md5(Date.now() + Math.random());
resource.size = 0;
resource.dataFilePath = `${Setting.value('tempDir')}/${resource.id}.empty`;
await fs.writeFile(resource.dataFilePath, '');
} else {
if (resource.dataEncoding == 'base64') {
const decodedFilePath = `${resource.dataFilePath}.decoded`;
await decodeBase64File(resource.dataFilePath, decodedFilePath);
resource.dataFilePath = decodedFilePath;
} else if (resource.dataEncoding) {
throw new Error(`Cannot decode resource with encoding: ${resource.dataEncoding}`);
}
if (resource.dataEncoding == 'base64') {
const decodedFilePath = `${resource.dataFilePath}.decoded`;
await decodeBase64File(resource.dataFilePath, decodedFilePath);
resource.dataFilePath = decodedFilePath;
} else if (resource.dataEncoding) {
throw new Error(`Cannot decode resource with encoding: ${resource.dataEncoding}`);
}
const stats = fs.statSync(resource.dataFilePath);
resource.size = stats.size;
const stats = fs.statSync(resource.dataFilePath);
resource.size = stats.size;
if (!resource.id) {
// If no resource ID is present, the resource ID is actually the MD5 of the data.
// This ID will match the "hash" attribute of the corresponding <en-media> tag.
// resourceId = md5(decodedData);
resource.id = await md5FileAsync(resource.dataFilePath);
}
if (!resource.id) {
// If no resource ID is present, the resource ID is actually the MD5 of the data.
// This ID will match the "hash" attribute of the corresponding <en-media> tag.
// resourceId = md5(decodedData);
resource.id = await md5FileAsync(resource.dataFilePath);
}
if (!resource.id || !resource.size) {
const debugTemp = Object.assign({}, resource);
debugTemp.data = debugTemp.data ? `${debugTemp.data.substr(0, 32)}...` : debugTemp.data;
throw new Error(`This resource was not added because it has no ID or no content: ${JSON.stringify(debugTemp)}`);
}
if (!resource.id || !resource.size) {
const debugTemp = Object.assign({}, resource);
debugTemp.data = debugTemp.data ? `${debugTemp.data.substr(0, 32)}...` : debugTemp.data;
throw new Error(`This resource was not added because it has no ID or no content: ${JSON.stringify(debugTemp)}`);
}
return resource;
@@ -181,7 +173,6 @@ async function saveNoteResources(note) {
const toSave = Object.assign({}, resource);
delete toSave.dataFilePath;
delete toSave.dataEncoding;
delete toSave.hasData;
// The same resource sometimes appear twice in the same enex (exact same ID and file).
// In that case, just skip it - it means two different notes might be linked to the
@@ -415,8 +406,6 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
noteResource.dataFilePath = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}.base64`;
}
noteResource.hasData = true;
fs.appendFileSync(noteResource.dataFilePath, text);
} else {
if (!(n in noteResource)) noteResource[n] = '';
@@ -449,7 +438,6 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
note = {
resources: [],
tags: [],
bodyXml: '',
};
} else if (n == 'resource-attributes') {
noteResourceAttributes = {};
@@ -458,9 +446,7 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
} else if (n == 'note-attributes') {
noteAttributes = {};
} else if (n == 'resource') {
noteResource = {
hasData: false,
};
noteResource = {};
}
}));
@@ -471,7 +457,11 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
noteResourceRecognition.objID = extractRecognitionObjId(data);
} else if (note) {
if (n == 'content') {
note.bodyXml += data;
if ('bodyXml' in note) {
note.bodyXml += data;
} else {
note.bodyXml = data;
}
}
}
}));
@@ -521,7 +511,6 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
mime: noteResource.mime ? noteResource.mime.trim() : '',
title: noteResource.filename ? noteResource.filename.trim() : '',
filename: noteResource.filename ? noteResource.filename.trim() : '',
hasData: noteResource.hasData,
});
noteResource = null;

View File

@@ -1,13 +0,0 @@
module.exports = {
testMatch: [
'**/*.test.js',
],
testPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/rnInjectedJs/',
'<rootDir>/vendor/',
],
testEnvironment: 'node',
};

View File

@@ -1,7 +1,6 @@
const BaseModel = require('../BaseModel').default;
const Mutex = require('async-mutex').Mutex;
const shim = require('../shim').default;
const eventManager = require('../eventManager').default;
class ItemChange extends BaseModel {
static tableName() {
@@ -23,25 +22,10 @@ class ItemChange extends BaseModel {
const release = await ItemChange.addChangeMutex_.acquire();
try {
await this.db().transactionExecBatch([
{
sql: 'DELETE FROM item_changes WHERE item_id = ?',
params: [itemId],
},
{
sql: 'INSERT INTO item_changes (item_type, item_id, type, source, created_time, before_change_item) VALUES (?, ?, ?, ?, ?, ?)',
params: [itemType, itemId, type, changeSource, Date.now(), beforeChangeItemJson],
}
]);
await this.db().transactionExecBatch([{ sql: 'DELETE FROM item_changes WHERE item_id = ?', params: [itemId] }, { sql: 'INSERT INTO item_changes (item_type, item_id, type, source, created_time, before_change_item) VALUES (?, ?, ?, ?, ?, ?)', params: [itemType, itemId, type, changeSource, Date.now(), beforeChangeItemJson] }]);
} finally {
release();
ItemChange.saveCalls_.pop();
eventManager.emit('itemChange', {
itemType: itemType,
itemId: itemId,
eventType: type,
});
}
}
@@ -78,6 +62,6 @@ ItemChange.TYPE_DELETE = 3;
ItemChange.SOURCE_UNSPECIFIED = 1;
ItemChange.SOURCE_SYNC = 2;
ItemChange.SOURCE_DECRYPTION = 2; // CAREFUL - SAME ID AS SOURCE_SYNC!
ItemChange.SOURCE_DECRYPTION = 2;
module.exports = ItemChange;

View File

@@ -179,7 +179,7 @@ class Note extends BaseItem {
pathsToTry.push(Resource.baseRelativeDirectoryPath());
}
this.logger().debug('replaceResourceExternalToInternalLinks', 'options:', options, 'pathsToTry:', pathsToTry);
this.logger().debug('replaceResourceExternalToInternalLinks', 'options:', options, 'pathsToTry:', pathsToTry, 'body:', body);
for (const basePath of pathsToTry) {
const reStrings = [
@@ -200,7 +200,7 @@ class Note extends BaseItem {
body = body.replace(/\(joplin:\/\/([a-zA-Z0-9]{32})\)/g, '(:/$1)');
}
// this.logger().debug('replaceResourceExternalToInternalLinks result', body);
this.logger().debug('replaceResourceExternalToInternalLinks result', body);
return body;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
{
"name": "@joplin/lib",
"version": "1.0.9",
"description": "Joplin Core library",
"author": "Laurent Cozic",
"description": "> TODO: description",
"author": "Laurent Cozic <laurent@cozic.net>",
"homepage": "",
"license": "ISC",
"publishConfig": {
@@ -11,13 +11,9 @@
"scripts": {
"tsc": "node node_modules/typescript/bin/tsc --project tsconfig.json",
"watch": "node node_modules/typescript/bin/tsc --watch --project tsconfig.json",
"generatePluginTypes": "rm -rf ./plugin_types && node node_modules/typescript/bin/tsc --declaration --declarationDir ./plugin_types --project tsconfig.json",
"test": "jest",
"test-ci": "npm run test"
"generatePluginTypes": "rm -rf ./plugin_types && node node_modules/typescript/bin/tsc --declaration --declarationDir ./plugin_types --project tsconfig.json"
},
"devDependencies": {
"@types/jest": "^26.0.15",
"jest": "^26.6.3",
"@types/node": "^14.14.6",
"typescript": "^4.0.5"
},

View File

@@ -8,8 +8,4 @@ export default abstract class BasePluginRunner extends BaseService {
throw new Error(`Not implemented: ${plugin} / ${sandbox}`);
}
public async waitForSandboxCalls(): Promise<void> {
throw new Error('Not implemented: waitForSandboxCalls');
}
}

View File

@@ -385,8 +385,4 @@ export default class PluginService extends BaseService {
return newSettings;
}
public async destroy() {
await this.runner_.waitForSandboxCalls();
}
}

View File

@@ -37,7 +37,7 @@ export default class Joplin {
constructor(implementation: any, plugin: Plugin, store: any) {
this.data_ = new JoplinData();
this.plugins_ = new JoplinPlugins(plugin);
this.workspace_ = new JoplinWorkspace(store);
this.workspace_ = new JoplinWorkspace(implementation.workspace, store);
this.filters_ = new JoplinFilters();
this.commands_ = new JoplinCommands();
this.views_ = new JoplinViews(implementation.views, plugin, store);

View File

@@ -1,31 +1,13 @@
import { ModelType } from '../../../BaseModel';
import eventManager from '../../../eventManager';
import makeListener from '../utils/makeListener';
import { Disposable } from './types';
/**
* @ignore
*/
const Note = require('../../../models/Note');
enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3,
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
type ItemChangeHandler = (event: ItemChangeEvent)=> void;
/**
* The workspace service provides access to all the parts of Joplin that
* are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* The workspace service provides access to all the parts of Joplin that are being worked on - i.e. the currently selected notes or notebooks as well
* as various related events, such as when a new note is selected, or when the note content changes.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/
@@ -33,68 +15,45 @@ export default class JoplinWorkspace {
// TODO: unregister events when plugin is closed or disabled
private store: any;
// private implementation_:any;
constructor(store: any) {
constructor(_implementation: any, store: any) {
this.store = store;
// this.implementation_ = implementation;
}
/**
* Called when a new note or notes are selected.
*/
public async onNoteSelectionChange(callback: Function): Promise<Disposable> {
async onNoteSelectionChange(callback: Function) {
eventManager.appStateOn('selectedNoteIds', callback);
return {};
// return {
// dispose: () => {
// eventManager.appStateOff('selectedNoteIds', callback);
// }
// };
}
/**
* Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/
public async onNoteContentChange(callback: Function) {
async onNoteContentChange(callback: Function) {
eventManager.on('noteContentChange', callback);
}
/**
* Called when the content of a note changes.
*/
public async onNoteChange(handler: ItemChangeHandler): Promise<Disposable> {
const wrapperHandler = (event: any) => {
if (event.itemType !== ModelType.Note) return;
handler({
id: event.itemId,
event: event.eventType,
});
};
return makeListener(eventManager, 'itemChange', wrapperHandler);
}
/**
* Called when an alarm associated with a to-do is triggered.
*/
public async onNoteAlarmTrigger(callback: Function): Promise<Disposable> {
return makeListener(eventManager, 'noteAlarmTrigger', callback);
async onNoteAlarmTrigger(callback: Function) {
eventManager.on('noteAlarmTrigger', callback);
}
/**
* Called when the synchronisation process has finished.
*/
public async onSyncComplete(callback: Function): Promise<Disposable> {
return makeListener(eventManager, 'syncComplete', callback);
async onSyncComplete(callback: Function) {
eventManager.on('syncComplete', callback);
}
/**
* Gets the currently selected note
*/
public async selectedNote(): Promise<any> {
async selectedNote(): Promise<any> {
const noteIds = this.store.getState().selectedNoteIds;
if (noteIds.length !== 1) { return null; }
return Note.load(noteIds[0]);
@@ -103,7 +62,7 @@ export default class JoplinWorkspace {
/**
* Gets the IDs of the selected notes (can be zero, one, or many). Use the data API to retrieve information about these notes.
*/
public async selectedNoteIds(): Promise<string[]> {
async selectedNoteIds(): Promise<string[]> {
return this.store.getState().selectedNoteIds.slice();
}
}

View File

@@ -189,10 +189,6 @@ export interface Script {
onStart?(event: any): Promise<void>;
}
export interface Disposable {
// dispose():void;
}
// =================================================================
// Menu types
// =================================================================

View File

@@ -1,22 +0,0 @@
import { EventManager } from '../../../eventManager';
import { Disposable } from '../api/types';
export default function(eventManager: EventManager, eventName: string, callback: Function): Disposable {
eventManager.on(eventName, callback);
return {};
// Note: It is not currently possible to return an object with a dispose() function because function cannot be serialized when sent via IPC. So it would need send callback mechanism as for plugin functions.
//
// Or it could return a simple string ID, which can then be used to stop listening to the event. eg:
//
// const listenerId = await joplin.workspace.onNoteChange(() => {});
// // ... later:
// await joplin.workspace.removeListener(listenerId);
// return {
// dispose: () => {
// eventManager.off(eventName, callback);
// }
// };
}

View File

@@ -99,7 +99,7 @@ function filterLogs(logs, platform) {
if (platform === 'android' && prefix.indexOf('android') >= 0) addIt = true;
if (platform === 'ios' && prefix.indexOf('ios') >= 0) addIt = true;
if (platform === 'desktop' && prefix.indexOf('desktop') >= 0) addIt = true;
if (platform === 'desktop' && (prefix.indexOf('desktop') >= 0 || prefix.indexOf('api') >= 0 || prefix.indexOf('plugins') >= 0 || prefix.indexOf('macos') >= 0)) addIt = true;
if (platform === 'desktop' && (prefix.indexOf('desktop') >= 0 || prefix.indexOf('api') >= 0 || prefix.indexOf('plugins') >= 0)) addIt = true;
if (platform === 'cli' && prefix.indexOf('cli') >= 0) addIt = true;
if (platform === 'clipper' && prefix.indexOf('clipper') >= 0) addIt = true;

View File

@@ -1,99 +1,5 @@
# Joplin changelog
## [v1.4.18](https://github.com/laurent22/joplin/releases/tag/v1.4.18) - 2020-11-28T12:21:41Z
- Fixed: Fixed notifications on macOS
- Fixed: Re-enabled ASAR packing to improve startup time
## [v1.4.16](https://github.com/laurent22/joplin/releases/tag/v1.4.16) - 2020-11-27T19:40:16Z
- Fixed: Fix sorting by title in a case insensitive way
- Fixed: Fixed spell checker crash when no language is selected
## [v1.4.15](https://github.com/laurent22/joplin/releases/tag/v1.4.15) - 2020-11-27T13:25:43Z
- Fixed: Notifications on macOS
- Fixed: Fixed potential crash when watching note files or resources
- Fixed: Prevents crash when invalid spell checker language is selected, and provide fallback for invalid language codes ([#4146](https://github.com/laurent22/joplin/issues/4146))
- Plugins: Fixed webview postMessage call
## [v1.4.12](https://github.com/laurent22/joplin/releases/tag/v1.4.12) - 2020-11-23T18:58:07Z
**Breaking Changes:**
- If you use the Clipper API, please note that there are a few breaking changes in this version. See this link for more information: https://github.com/laurent22/joplin/pull/3983
- Plugins: `joplin.views.dialogs.open()` now returns an object instead of the button ID that was clicked. So for example instead of getting just `"ok"`, you will get `{ "id": "ok" }`. This is to allow adding form data to that object.
**Deprecated:**
The following features are deprecated. It will still work for now but please update your code:
- Plugins: All `create()` functions under `joplin.views` now take a `viewId` as a first parameter.
- Plugins: `MenuItemLocation.Context` is deprecated and is now an alias for `MenuItemLocation.NoteListContextMenu`
- Plugins: The `app_min_version` manifest property is now required. If not provided it will assume v14.
- Plugins: The `id` manifest property is now required. If not set, it will be the plugin filename or directory.
Plugin doc has been updated with some info about the [development process](https://joplinapp.org/api/references/plugin_api/classes/joplin.html).
- New: Add {{bowm}} and {{bows}} - Beginning Of Week (Monday/Sunday) ([#4023](https://github.com/laurent22/joplin/issues/4023) by Helmut K. C. Tessarek)
- New: Add config screen to add, remove or enable, disable plugins
- New: Add option to toggle spellchecking for the markdown editor ([#4109](https://github.com/laurent22/joplin/issues/4109) by [@CalebJohn](https://github.com/CalebJohn))
- New: Added toolbar button to switch spell checker language
- New: Adds spell checker support for Rich Text editor ([#3974](https://github.com/laurent22/joplin/issues/3974))
- New: Allow customising application layout
- New: Api: Added ability to watch resource file
- New: Api: Added way to get the notes associated with a resource
- New: API: Adds ability to paginate data ([#3983](https://github.com/laurent22/joplin/issues/3983))
- New: Plugins: Add command "editorSetText" for desktop app
- New: Plugins: Add support for editor context menu
- New: Plugins: Add support for external CodeMirror plugins ([#4015](https://github.com/laurent22/joplin/issues/4015) by [@CalebJohn](https://github.com/CalebJohn))
- New: Plugins: Add support for JPL archive format
- New: Plugins: Added command to export folders and notes
- New: Plugins: Added support app_min_version property and made it required
- Fixed: Api: Fix note and resource association end points
- Fixed: Display note count for conflict folder, and display notes even if they are completed to-dos ([#3997](https://github.com/laurent22/joplin/issues/3997))
- Fixed: Fix crash due to React when trying to upgrade sync target ([#4098](https://github.com/laurent22/joplin/issues/4098))
- Fixed: Fix drag and drop behaviour to "copy" instead of "move" ([#4031](https://github.com/laurent22/joplin/issues/4031) by [@CalebJohn](https://github.com/CalebJohn))
- Fixed: Fix handling of certain keys in shortcut editor ([#4022](https://github.com/laurent22/joplin/issues/4022) by Helmut K. C. Tessarek)
- Fixed: Fix handling of new line escaping when using external edit
- Fixed: Fix size of search bar area when notebook is empty
- Fixed: Fixed importing certain ENEX files that contain invalid dates
- Fixed: Fixed inconsistent note list state when using search ([#3904](https://github.com/laurent22/joplin/issues/3904))
- Fixed: Fixed issue when a newly created note would be automatically moved to the wrong folder on save ([#4038](https://github.com/laurent22/joplin/issues/4038))
- Fixed: Fixed issue with note being saved after word has been replaced by spell checker
- Fixed: Fixed links imported from ENEX as HTML ([#4119](https://github.com/laurent22/joplin/issues/4119))
- Fixed: Fixed Markdown rendering when code highlighting is disabled
- Fixed: Fixed note list overflow when resized very small
- Fixed: Fixed text editor button tooltips
- Fixed: Plugins: Fix crash when path includes trailing slash
- Fixed: Plugins: Fixed issue with dialog being empty in some cases
- Fixed: Plugins: Fixed issue with toolbar button key not being unique
- Fixed: Prevent log from filling up when certain external editors trigger many watch events ([#4011](https://github.com/laurent22/joplin/issues/4011))
- Fixed: Regression: Fix application name
- Fixed: Regression: Fix exporting to HTML and PDF
- Fixed: Regression: Fixed external edit file watching
- Fixed: Resource links could not be opened from Rich Text editor on Linux ([#4073](https://github.com/laurent22/joplin/issues/4073))
- Fixed: Tags could not be selected in some cases ([#3876](https://github.com/laurent22/joplin/issues/3876))
- Improved: Allow exporting conflict notes ([#4095](https://github.com/laurent22/joplin/issues/4095))
- Improved: Allow lowercase filters when doing search
- Improved: Api: Always include 'has_more' field for paginated data
- Improved: Api: Make sure pagination sort options are respected for search and other requests
- Improved: Attempt to fix Outlook drag and drop on Markdown editor ([#4093](https://github.com/laurent22/joplin/issues/4093) by [@CalebJohn](https://github.com/CalebJohn))
- Improved: Change Markdown rendering to align with CommonMark spec ([#3839](https://github.com/laurent22/joplin/issues/3839))
- Improved: Disable spell checker on config and search input fields
- Improved: Disabled the auto update option in linux ([#4102](https://github.com/laurent22/joplin/issues/4102)) ([#4096](https://github.com/laurent22/joplin/issues/4096) by Anshuman Pandey)
- Improved: Make Markdown editor selection more visible in Dark mode
- Improved: Optimized resizing window
- Improved: Plugins: Allow retrieving form values from dialogs
- Improved: Plugins: Force plugin devtool dialog to be detached
- Improved: Plugins: Make sure "replaceSelection" command can be undone in Rich Text editor
- Improved: Plugins: Provides selected notes when triggering a command from the note list context menu
- Improved: Plugins: Rename command "editorSetText" to "editor.setText"
- Improved: Prevent lines from shifting in Markdown Editor when Scrollbar appears ([#4110](https://github.com/laurent22/joplin/issues/4110) by [@CalebJohn](https://github.com/CalebJohn))
- Improved: Put title bar and toolbar button over two lines when window size is below 800px
- Improved: Refresh sidebar and notes when moving note outside of conflict folder
- Improved: Upgrade to Electron 10
## [v1.3.18](https://github.com/laurent22/joplin/releases/tag/v1.3.18) - 2020-11-06T12:07:02Z
- Regression: Random crash when syncing due to undefined tags ([#4051](https://github.com/laurent22/joplin/issues/4051))

View File

@@ -2,109 +2,105 @@
Name | Value
--- | ---
Total Windows downloads | 1,121,074
Total macOs downloads | 434,816
Total Linux downloads | 318,581
Total Windows downloads | 1,096,772
Total macOs downloads | 425,802
Total Linux downloads | 310,292
Windows % | 60%
macOS % | 23%
Linux % | 17%
Version | Date | Windows | macOS | Linux | Total
--- | --- | --- | --- | --- | ---
[v1.4.18](https://github.com/laurent22/joplin/releases/tag/v1.4.18) | 2020-11-28T12:21:41Z | 3,390 | 1,584 | 1,141 | 6,115
[v1.4.16](https://github.com/laurent22/joplin/releases/tag/v1.4.16) | 2020-11-27T19:40:16Z | 1,333 | 798 | 573 | 2,704
[v1.4.15](https://github.com/laurent22/joplin/releases/tag/v1.4.15) | 2020-11-27T13:25:43Z | 808 | 465 | 248 | 1,521
[v1.4.12](https://github.com/laurent22/joplin/releases/tag/v1.4.12) | 2020-11-23T18:58:07Z | 2,807 | 1,278 | 1,256 | 5,341
[v1.3.18](https://github.com/laurent22/joplin/releases/tag/v1.3.18) | 2020-11-06T12:07:02Z | 29,861 | 11,217 | 10,451 | 51,529
[v1.3.15](https://github.com/laurent22/joplin/releases/tag/v1.3.15) | 2020-11-04T12:22:50Z | 2,155 | 1,270 | 826 | 4,251
[v1.2.6](https://github.com/laurent22/joplin/releases/tag/v1.2.6) | 2020-10-09T13:56:59Z | 43,519 | 17,667 | 14,004 | 75,190
[v1.1.4](https://github.com/laurent22/joplin/releases/tag/v1.1.4) | 2020-09-21T11:20:09Z | 27,413 | 13,460 | 7,696 | 48,569
[v1.0.245](https://github.com/laurent22/joplin/releases/tag/v1.0.245) | 2020-09-09T12:56:10Z | 20,791 | 9,964 | 5,618 | 36,373
[v1.0.242](https://github.com/laurent22/joplin/releases/tag/v1.0.242) | 2020-09-04T22:00:34Z | 12,309 | 6,396 | 3,007 | 21,712
[v1.0.241](https://github.com/laurent22/joplin/releases/tag/v1.0.241) | 2020-09-04T18:06:00Z | 23,078 | 5,689 | 4,961 | 33,728
[v1.0.233](https://github.com/laurent22/joplin/releases/tag/v1.0.233) | 2020-08-01T14:51:15Z | 42,344 | 18,156 | 12,344 | 72,844
[v1.0.227](https://github.com/laurent22/joplin/releases/tag/v1.0.227) | 2020-07-07T20:44:54Z | 40,163 | 15,240 | 9,611 | 65,014
[v1.0.224](https://github.com/laurent22/joplin/releases/tag/v1.0.224) | 2020-06-20T22:26:08Z | 24,711 | 10,980 | 5,999 | 41,690
[v1.0.220](https://github.com/laurent22/joplin/releases/tag/v1.0.220) | 2020-06-13T18:26:22Z | 31,522 | 9,890 | 6,407 | 47,819
[v1.0.218](https://github.com/laurent22/joplin/releases/tag/v1.0.218) | 2020-06-07T10:43:34Z | 14,498 | 6,948 | 2,950 | 24,396
[v1.0.216](https://github.com/laurent22/joplin/releases/tag/v1.0.216) | 2020-05-24T14:21:01Z | 36,541 | 14,240 | 10,169 | 60,950
[v1.0.201](https://github.com/laurent22/joplin/releases/tag/v1.0.201) | 2020-04-15T22:55:13Z | 52,539 | 20,035 | 18,168 | 90,742
[v1.3.18](https://github.com/laurent22/joplin/releases/tag/v1.3.18) | 2020-11-06T12:07:02Z | 14,764 | 6,490 | 5,476 | 26,730
[v1.3.15](https://github.com/laurent22/joplin/releases/tag/v1.3.15) | 2020-11-04T12:22:50Z | 2,133 | 1,260 | 824 | 4,217
[v1.2.6](https://github.com/laurent22/joplin/releases/tag/v1.2.6) | 2020-10-09T13:56:59Z | 43,408 | 17,645 | 13,992 | 75,045
[v1.1.4](https://github.com/laurent22/joplin/releases/tag/v1.1.4) | 2020-09-21T11:20:09Z | 27,403 | 13,458 | 7,694 | 48,555
[v1.0.245](https://github.com/laurent22/joplin/releases/tag/v1.0.245) | 2020-09-09T12:56:10Z | 20,771 | 9,961 | 5,617 | 36,349
[v1.0.242](https://github.com/laurent22/joplin/releases/tag/v1.0.242) | 2020-09-04T22:00:34Z | 12,301 | 6,394 | 3,007 | 21,702
[v1.0.241](https://github.com/laurent22/joplin/releases/tag/v1.0.241) | 2020-09-04T18:06:00Z | 23,069 | 5,684 | 4,959 | 33,712
[v1.0.233](https://github.com/laurent22/joplin/releases/tag/v1.0.233) | 2020-08-01T14:51:15Z | 42,195 | 18,151 | 12,344 | 72,690
[v1.0.227](https://github.com/laurent22/joplin/releases/tag/v1.0.227) | 2020-07-07T20:44:54Z | 40,135 | 15,235 | 9,610 | 64,980
[v1.0.224](https://github.com/laurent22/joplin/releases/tag/v1.0.224) | 2020-06-20T22:26:08Z | 24,705 | 10,977 | 5,999 | 41,681
[v1.0.220](https://github.com/laurent22/joplin/releases/tag/v1.0.220) | 2020-06-13T18:26:22Z | 31,510 | 9,887 | 6,407 | 47,804
[v1.0.218](https://github.com/laurent22/joplin/releases/tag/v1.0.218) | 2020-06-07T10:43:34Z | 14,488 | 6,946 | 2,950 | 24,384
[v1.0.216](https://github.com/laurent22/joplin/releases/tag/v1.0.216) | 2020-05-24T14:21:01Z | 36,371 | 14,235 | 10,169 | 60,775
[v1.0.201](https://github.com/laurent22/joplin/releases/tag/v1.0.201) | 2020-04-15T22:55:13Z | 52,378 | 20,032 | 18,167 | 90,577
[v1.0.200](https://github.com/laurent22/joplin/releases/tag/v1.0.200) | 2020-04-12T12:17:46Z | 9,543 | 4,885 | 1,898 | 16,326
[v1.0.199](https://github.com/laurent22/joplin/releases/tag/v1.0.199) | 2020-04-10T18:41:58Z | 19,248 | 5,878 | 3,783 | 28,909
[v1.0.197](https://github.com/laurent22/joplin/releases/tag/v1.0.197) | 2020-03-30T17:21:22Z | 22,073 | 9,507 | 5,618 | 37,198
[v1.0.195](https://github.com/laurent22/joplin/releases/tag/v1.0.195) | 2020-03-22T19:56:12Z | 18,867 | 7,942 | 4,502 | 31,311
[v1.0.193](https://github.com/laurent22/joplin/releases/tag/v1.0.193) | 2020-03-08T08:58:53Z | 28,598 | 10,895 | 7,356 | 46,849
[v1.0.179](https://github.com/laurent22/joplin/releases/tag/v1.0.179) | 2020-01-24T22:42:41Z | 70,962 | 28,472 | 22,494 | 121,928
[v1.0.178](https://github.com/laurent22/joplin/releases/tag/v1.0.178) | 2020-01-20T19:06:45Z | 17,527 | 5,956 | 2,579 | 26,062
[v1.0.175](https://github.com/laurent22/joplin/releases/tag/v1.0.175) | 2019-12-08T11:48:47Z | 72,026 | 16,856 | 16,481 | 105,363
[v1.0.174](https://github.com/laurent22/joplin/releases/tag/v1.0.174) | 2019-11-12T18:20:58Z | 30,390 | 11,689 | 8,217 | 50,296
[v1.0.173](https://github.com/laurent22/joplin/releases/tag/v1.0.173) | 2019-11-11T08:33:35Z | 5,060 | 2,072 | 740 | 7,872
[v1.0.170](https://github.com/laurent22/joplin/releases/tag/v1.0.170) | 2019-10-13T22:13:04Z | 27,375 | 8,739 | 7,668 | 43,782
[v1.0.169](https://github.com/laurent22/joplin/releases/tag/v1.0.169) | 2019-09-27T18:35:13Z | 17,083 | 5,916 | 3,750 | 26,749
[v1.0.168](https://github.com/laurent22/joplin/releases/tag/v1.0.168) | 2019-09-25T21:21:38Z | 5,323 | 2,267 | 714 | 8,304
[v1.0.167](https://github.com/laurent22/joplin/releases/tag/v1.0.167) | 2019-09-10T08:48:37Z | 16,779 | 5,699 | 3,701 | 26,179
[v1.0.199](https://github.com/laurent22/joplin/releases/tag/v1.0.199) | 2020-04-10T18:41:58Z | 19,239 | 5,878 | 3,783 | 28,900
[v1.0.197](https://github.com/laurent22/joplin/releases/tag/v1.0.197) | 2020-03-30T17:21:22Z | 22,062 | 9,506 | 5,610 | 37,178
[v1.0.195](https://github.com/laurent22/joplin/releases/tag/v1.0.195) | 2020-03-22T19:56:12Z | 18,860 | 7,942 | 4,502 | 31,304
[v1.0.193](https://github.com/laurent22/joplin/releases/tag/v1.0.193) | 2020-03-08T08:58:53Z | 28,595 | 10,895 | 7,356 | 46,846
[v1.0.179](https://github.com/laurent22/joplin/releases/tag/v1.0.179) | 2020-01-24T22:42:41Z | 70,959 | 28,467 | 22,491 | 121,917
[v1.0.178](https://github.com/laurent22/joplin/releases/tag/v1.0.178) | 2020-01-20T19:06:45Z | 17,526 | 5,956 | 2,579 | 26,061
[v1.0.175](https://github.com/laurent22/joplin/releases/tag/v1.0.175) | 2019-12-08T11:48:47Z | 71,981 | 16,855 | 16,478 | 105,314
[v1.0.174](https://github.com/laurent22/joplin/releases/tag/v1.0.174) | 2019-11-12T18:20:58Z | 30,388 | 11,688 | 8,216 | 50,292
[v1.0.173](https://github.com/laurent22/joplin/releases/tag/v1.0.173) | 2019-11-11T08:33:35Z | 5,058 | 2,071 | 740 | 7,869
[v1.0.170](https://github.com/laurent22/joplin/releases/tag/v1.0.170) | 2019-10-13T22:13:04Z | 27,372 | 8,737 | 7,668 | 43,777
[v1.0.169](https://github.com/laurent22/joplin/releases/tag/v1.0.169) | 2019-09-27T18:35:13Z | 17,081 | 5,915 | 3,750 | 26,746
[v1.0.168](https://github.com/laurent22/joplin/releases/tag/v1.0.168) | 2019-09-25T21:21:38Z | 5,323 | 2,265 | 714 | 8,302
[v1.0.167](https://github.com/laurent22/joplin/releases/tag/v1.0.167) | 2019-09-10T08:48:37Z | 16,779 | 5,699 | 3,700 | 26,178
[v1.0.166](https://github.com/laurent22/joplin/releases/tag/v1.0.166) | 2019-09-09T17:35:54Z | 1,950 | 557 | 235 | 2,742
[v1.0.165](https://github.com/laurent22/joplin/releases/tag/v1.0.165) | 2019-08-14T21:46:29Z | 18,876 | 6,968 | 5,460 | 31,304
[v1.0.161](https://github.com/laurent22/joplin/releases/tag/v1.0.161) | 2019-07-13T18:30:00Z | 19,274 | 6,348 | 4,133 | 29,755
[v1.0.160](https://github.com/laurent22/joplin/releases/tag/v1.0.160) | 2019-06-15T00:21:40Z | 30,463 | 7,742 | 8,099 | 46,304
[v1.0.159](https://github.com/laurent22/joplin/releases/tag/v1.0.159) | 2019-06-08T00:00:19Z | 5,190 | 2,175 | 1,105 | 8,470
[v1.0.158](https://github.com/laurent22/joplin/releases/tag/v1.0.158) | 2019-05-27T19:01:18Z | 9,810 | 3,536 | 1,934 | 15,280
[v1.0.157](https://github.com/laurent22/joplin/releases/tag/v1.0.157) | 2019-05-26T17:55:53Z | 2,173 | 842 | 289 | 3,304
[v1.0.152](https://github.com/laurent22/joplin/releases/tag/v1.0.152) | 2019-05-13T09:08:07Z | 13,862 | 4,424 | 4,060 | 22,346
[v1.0.151](https://github.com/laurent22/joplin/releases/tag/v1.0.151) | 2019-05-12T15:14:32Z | 1,950 | 530 | 956 | 3,436
[v1.0.150](https://github.com/laurent22/joplin/releases/tag/v1.0.150) | 2019-05-12T11:27:48Z | 418 | 129 | 67 | 614
[v1.0.145](https://github.com/laurent22/joplin/releases/tag/v1.0.145) | 2019-05-03T09:16:53Z | 7,003 | 2,859 | 1,434 | 11,296
[v1.0.143](https://github.com/laurent22/joplin/releases/tag/v1.0.143) | 2019-04-22T10:51:38Z | 11,912 | 3,548 | 2,777 | 18,237
[v1.0.142](https://github.com/laurent22/joplin/releases/tag/v1.0.142) | 2019-04-02T16:44:51Z | 14,650 | 4,558 | 4,724 | 23,932
[v1.0.140](https://github.com/laurent22/joplin/releases/tag/v1.0.140) | 2019-03-10T20:59:58Z | 13,622 | 4,166 | 3,178 | 20,966
[v1.0.135](https://github.com/laurent22/joplin/releases/tag/v1.0.135) | 2019-02-27T23:36:57Z | 12,486 | 3,954 | 4,074 | 20,514
[v1.0.134](https://github.com/laurent22/joplin/releases/tag/v1.0.134) | 2019-02-27T10:21:44Z | 1,464 | 564 | 217 | 2,245
[v1.0.132](https://github.com/laurent22/joplin/releases/tag/v1.0.132) | 2019-02-26T23:02:05Z | 1,081 | 448 | 94 | 1,623
[v1.0.127](https://github.com/laurent22/joplin/releases/tag/v1.0.127) | 2019-02-14T23:12:48Z | 9,741 | 3,165 | 2,928 | 15,834
[v1.0.125](https://github.com/laurent22/joplin/releases/tag/v1.0.125) | 2019-01-26T18:14:33Z | 10,246 | 3,554 | 1,701 | 15,501
[v1.0.120](https://github.com/laurent22/joplin/releases/tag/v1.0.120) | 2019-01-10T21:42:53Z | 15,599 | 5,197 | 6,514 | 27,310
[v1.0.119](https://github.com/laurent22/joplin/releases/tag/v1.0.119) | 2018-12-18T12:40:22Z | 8,902 | 3,259 | 2,013 | 14,174
[v1.0.118](https://github.com/laurent22/joplin/releases/tag/v1.0.118) | 2019-01-11T08:34:13Z | 713 | 246 | 88 | 1,047
[v1.0.117](https://github.com/laurent22/joplin/releases/tag/v1.0.117) | 2018-11-24T12:05:24Z | 16,252 | 4,892 | 6,379 | 27,523
[v1.0.116](https://github.com/laurent22/joplin/releases/tag/v1.0.116) | 2018-11-20T19:09:24Z | 3,469 | 1,119 | 712 | 5,300
[v1.0.115](https://github.com/laurent22/joplin/releases/tag/v1.0.115) | 2018-11-16T16:52:02Z | 3,653 | 1,300 | 797 | 5,750
[v1.0.114](https://github.com/laurent22/joplin/releases/tag/v1.0.114) | 2018-10-24T20:14:10Z | 11,393 | 3,494 | 3,828 | 18,715
[v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 12,008 | 3,290 | 3,667 | 18,965
[v1.0.110](https://github.com/laurent22/joplin/releases/tag/v1.0.110) | 2018-09-29T12:29:21Z | 956 | 407 | 117 | 1,480
[v1.0.109](https://github.com/laurent22/joplin/releases/tag/v1.0.109) | 2018-09-27T18:01:41Z | 2,098 | 703 | 326 | 3,127
[v1.0.107](https://github.com/laurent22/joplin/releases/tag/v1.0.107) | 2018-09-16T19:51:07Z | 7,146 | 2,134 | 1,705 | 10,985
[v1.0.106](https://github.com/laurent22/joplin/releases/tag/v1.0.106) | 2018-09-08T15:23:40Z | 4,554 | 1,455 | 316 | 6,325
[v1.0.105](https://github.com/laurent22/joplin/releases/tag/v1.0.105) | 2018-09-05T11:29:36Z | 4,652 | 1,587 | 1,453 | 7,692
[v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 15,043 | 4,698 | 7,328 | 27,069
[v1.0.103](https://github.com/laurent22/joplin/releases/tag/v1.0.103) | 2018-06-21T19:38:13Z | 2,050 | 883 | 679 | 3,612
[v1.0.101](https://github.com/laurent22/joplin/releases/tag/v1.0.101) | 2018-06-17T18:35:11Z | 1,306 | 606 | 408 | 2,320
[v1.0.100](https://github.com/laurent22/joplin/releases/tag/v1.0.100) | 2018-06-14T17:41:43Z | 877 | 431 | 240 | 1,548
[v1.0.99](https://github.com/laurent22/joplin/releases/tag/v1.0.99) | 2018-06-10T13:18:23Z | 1,251 | 594 | 379 | 2,224
[v1.0.97](https://github.com/laurent22/joplin/releases/tag/v1.0.97) | 2018-06-09T19:23:34Z | 309 | 156 | 60 | 525
[v1.0.96](https://github.com/laurent22/joplin/releases/tag/v1.0.96) | 2018-05-26T16:36:39Z | 2,715 | 1,222 | 1,617 | 5,554
[v1.0.95](https://github.com/laurent22/joplin/releases/tag/v1.0.95) | 2018-05-25T13:04:30Z | 415 | 217 | 118 | 750
[v1.0.94](https://github.com/laurent22/joplin/releases/tag/v1.0.94) | 2018-05-21T20:52:59Z | 1,128 | 582 | 395 | 2,105
[v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1,787 | 1,090 | 756 | 3,633
[v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) | 2018-05-10T14:48:04Z | 825 | 548 | 304 | 1,677
[v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 489 | 228 | 107 | 824
[v1.0.85](https://github.com/laurent22/joplin/releases/tag/v1.0.85) | 2018-05-01T21:08:24Z | 1,648 | 948 | 628 | 3,224
[v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 4,814 | 2,529 | 2,656 | 9,999
[v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 692 | 401 | 119 | 1,212
[v1.0.165](https://github.com/laurent22/joplin/releases/tag/v1.0.165) | 2019-08-14T21:46:29Z | 18,875 | 6,968 | 5,460 | 31,303
[v1.0.161](https://github.com/laurent22/joplin/releases/tag/v1.0.161) | 2019-07-13T18:30:00Z | 19,272 | 6,348 | 4,133 | 29,753
[v1.0.160](https://github.com/laurent22/joplin/releases/tag/v1.0.160) | 2019-06-15T00:21:40Z | 30,459 | 7,742 | 8,098 | 46,299
[v1.0.159](https://github.com/laurent22/joplin/releases/tag/v1.0.159) | 2019-06-08T00:00:19Z | 5,189 | 2,174 | 1,105 | 8,468
[v1.0.158](https://github.com/laurent22/joplin/releases/tag/v1.0.158) | 2019-05-27T19:01:18Z | 9,809 | 3,534 | 1,934 | 15,277
[v1.0.157](https://github.com/laurent22/joplin/releases/tag/v1.0.157) | 2019-05-26T17:55:53Z | 2,173 | 841 | 289 | 3,303
[v1.0.152](https://github.com/laurent22/joplin/releases/tag/v1.0.152) | 2019-05-13T09:08:07Z | 13,861 | 4,423 | 4,060 | 22,344
[v1.0.151](https://github.com/laurent22/joplin/releases/tag/v1.0.151) | 2019-05-12T15:14:32Z | 1,948 | 530 | 955 | 3,433
[v1.0.150](https://github.com/laurent22/joplin/releases/tag/v1.0.150) | 2019-05-12T11:27:48Z | 418 | 129 | 66 | 613
[v1.0.145](https://github.com/laurent22/joplin/releases/tag/v1.0.145) | 2019-05-03T09:16:53Z | 7,000 | 2,858 | 1,434 | 11,292
[v1.0.143](https://github.com/laurent22/joplin/releases/tag/v1.0.143) | 2019-04-22T10:51:38Z | 11,911 | 3,546 | 2,776 | 18,233
[v1.0.142](https://github.com/laurent22/joplin/releases/tag/v1.0.142) | 2019-04-02T16:44:51Z | 14,649 | 4,557 | 4,724 | 23,930
[v1.0.140](https://github.com/laurent22/joplin/releases/tag/v1.0.140) | 2019-03-10T20:59:58Z | 13,622 | 4,166 | 3,172 | 20,960
[v1.0.135](https://github.com/laurent22/joplin/releases/tag/v1.0.135) | 2019-02-27T23:36:57Z | 12,484 | 3,953 | 4,073 | 20,510
[v1.0.134](https://github.com/laurent22/joplin/releases/tag/v1.0.134) | 2019-02-27T10:21:44Z | 1,463 | 563 | 217 | 2,243
[v1.0.132](https://github.com/laurent22/joplin/releases/tag/v1.0.132) | 2019-02-26T23:02:05Z | 1,081 | 447 | 93 | 1,621
[v1.0.127](https://github.com/laurent22/joplin/releases/tag/v1.0.127) | 2019-02-14T23:12:48Z | 9,734 | 3,164 | 2,928 | 15,826
[v1.0.125](https://github.com/laurent22/joplin/releases/tag/v1.0.125) | 2019-01-26T18:14:33Z | 10,245 | 3,552 | 1,701 | 15,498
[v1.0.120](https://github.com/laurent22/joplin/releases/tag/v1.0.120) | 2019-01-10T21:42:53Z | 15,598 | 5,196 | 6,512 | 27,306
[v1.0.119](https://github.com/laurent22/joplin/releases/tag/v1.0.119) | 2018-12-18T12:40:22Z | 8,902 | 3,257 | 2,013 | 14,172
[v1.0.118](https://github.com/laurent22/joplin/releases/tag/v1.0.118) | 2019-01-11T08:34:13Z | 713 | 244 | 87 | 1,044
[v1.0.117](https://github.com/laurent22/joplin/releases/tag/v1.0.117) | 2018-11-24T12:05:24Z | 16,252 | 4,889 | 6,379 | 27,520
[v1.0.116](https://github.com/laurent22/joplin/releases/tag/v1.0.116) | 2018-11-20T19:09:24Z | 3,468 | 1,117 | 712 | 5,297
[v1.0.115](https://github.com/laurent22/joplin/releases/tag/v1.0.115) | 2018-11-16T16:52:02Z | 3,652 | 1,299 | 797 | 5,748
[v1.0.114](https://github.com/laurent22/joplin/releases/tag/v1.0.114) | 2018-10-24T20:14:10Z | 11,393 | 3,492 | 3,828 | 18,713
[v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 12,007 | 3,286 | 3,663 | 18,956
[v1.0.110](https://github.com/laurent22/joplin/releases/tag/v1.0.110) | 2018-09-29T12:29:21Z | 956 | 405 | 116 | 1,477
[v1.0.109](https://github.com/laurent22/joplin/releases/tag/v1.0.109) | 2018-09-27T18:01:41Z | 2,096 | 700 | 326 | 3,122
[v1.0.107](https://github.com/laurent22/joplin/releases/tag/v1.0.107) | 2018-09-16T19:51:07Z | 7,145 | 2,132 | 1,705 | 10,982
[v1.0.106](https://github.com/laurent22/joplin/releases/tag/v1.0.106) | 2018-09-08T15:23:40Z | 4,553 | 1,453 | 316 | 6,322
[v1.0.105](https://github.com/laurent22/joplin/releases/tag/v1.0.105) | 2018-09-05T11:29:36Z | 4,652 | 1,585 | 1,453 | 7,690
[v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 15,038 | 4,696 | 7,327 | 27,061
[v1.0.103](https://github.com/laurent22/joplin/releases/tag/v1.0.103) | 2018-06-21T19:38:13Z | 2,049 | 882 | 679 | 3,610
[v1.0.101](https://github.com/laurent22/joplin/releases/tag/v1.0.101) | 2018-06-17T18:35:11Z | 1,304 | 604 | 407 | 2,315
[v1.0.100](https://github.com/laurent22/joplin/releases/tag/v1.0.100) | 2018-06-14T17:41:43Z | 875 | 429 | 239 | 1,543
[v1.0.99](https://github.com/laurent22/joplin/releases/tag/v1.0.99) | 2018-06-10T13:18:23Z | 1,250 | 593 | 379 | 2,222
[v1.0.97](https://github.com/laurent22/joplin/releases/tag/v1.0.97) | 2018-06-09T19:23:34Z | 309 | 154 | 59 | 522
[v1.0.96](https://github.com/laurent22/joplin/releases/tag/v1.0.96) | 2018-05-26T16:36:39Z | 2,715 | 1,221 | 1,606 | 5,542
[v1.0.95](https://github.com/laurent22/joplin/releases/tag/v1.0.95) | 2018-05-25T13:04:30Z | 415 | 215 | 116 | 746
[v1.0.94](https://github.com/laurent22/joplin/releases/tag/v1.0.94) | 2018-05-21T20:52:59Z | 1,128 | 580 | 395 | 2,103
[v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1,786 | 1,081 | 755 | 3,622
[v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) | 2018-05-10T14:48:04Z | 824 | 547 | 303 | 1,674
[v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 488 | 227 | 107 | 822
[v1.0.85](https://github.com/laurent22/joplin/releases/tag/v1.0.85) | 2018-05-01T21:08:24Z | 1,647 | 946 | 627 | 3,220
[v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 4,809 | 2,529 | 2,656 | 9,994
[v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 692 | 400 | 119 | 1,211
[v1.0.81](https://github.com/laurent22/joplin/releases/tag/v1.0.81) | 2018-03-28T08:13:58Z | 999 | 595 | 780 | 2,374
[v1.0.79](https://github.com/laurent22/joplin/releases/tag/v1.0.79) | 2018-03-23T18:00:11Z | 930 | 534 | 377 | 1,841
[v1.0.78](https://github.com/laurent22/joplin/releases/tag/v1.0.78) | 2018-03-17T15:27:18Z | 1,311 | 868 | 867 | 3,046
[v1.0.77](https://github.com/laurent22/joplin/releases/tag/v1.0.77) | 2018-03-16T15:12:35Z | 177 | 103 | 44 | 324
[v1.0.77](https://github.com/laurent22/joplin/releases/tag/v1.0.77) | 2018-03-16T15:12:35Z | 176 | 103 | 44 | 323
[v1.0.72](https://github.com/laurent22/joplin/releases/tag/v1.0.72) | 2018-03-14T09:44:35Z | 405 | 254 | 54 | 713
[v1.0.70](https://github.com/laurent22/joplin/releases/tag/v1.0.70) | 2018-02-28T20:04:30Z | 1,853 | 1,049 | 1,252 | 4,154
[v1.0.70](https://github.com/laurent22/joplin/releases/tag/v1.0.70) | 2018-02-28T20:04:30Z | 1,853 | 1,049 | 1,251 | 4,153
[v1.0.67](https://github.com/laurent22/joplin/releases/tag/v1.0.67) | 2018-02-19T22:51:08Z | 1,814 | 600 | 0 | 2,414
[v1.0.66](https://github.com/laurent22/joplin/releases/tag/v1.0.66) | 2018-02-18T23:09:09Z | 326 | 134 | 85 | 545
[v1.0.65](https://github.com/laurent22/joplin/releases/tag/v1.0.65) | 2018-02-17T20:02:25Z | 193 | 126 | 133 | 452
[v1.0.65](https://github.com/laurent22/joplin/releases/tag/v1.0.65) | 2018-02-17T20:02:25Z | 193 | 124 | 133 | 450
[v1.0.64](https://github.com/laurent22/joplin/releases/tag/v1.0.64) | 2018-02-16T00:58:20Z | 1,084 | 543 | 1,123 | 2,750
[v1.0.63](https://github.com/laurent22/joplin/releases/tag/v1.0.63) | 2018-02-14T19:40:36Z | 300 | 159 | 93 | 552
[v1.0.62](https://github.com/laurent22/joplin/releases/tag/v1.0.62) | 2018-02-12T20:19:58Z | 558 | 297 | 367 | 1,222
[v0.10.61](https://github.com/laurent22/joplin/releases/tag/v0.10.61) | 2018-02-08T18:27:39Z | 971 | 630 | 960 | 2,561
[v0.10.61](https://github.com/laurent22/joplin/releases/tag/v0.10.61) | 2018-02-08T18:27:39Z | 971 | 630 | 958 | 2,559
[v0.10.60](https://github.com/laurent22/joplin/releases/tag/v0.10.60) | 2018-02-06T13:09:56Z | 721 | 519 | 552 | 1,792
[v0.10.54](https://github.com/laurent22/joplin/releases/tag/v0.10.54) | 2018-01-31T20:21:30Z | 1,819 | 1,458 | 322 | 3,599
[v0.10.54](https://github.com/laurent22/joplin/releases/tag/v0.10.54) | 2018-01-31T20:21:30Z | 1,819 | 1,458 | 321 | 3,598
[v0.10.52](https://github.com/laurent22/joplin/releases/tag/v0.10.52) | 2018-01-31T19:25:18Z | 46 | 632 | 15 | 693
[v0.10.51](https://github.com/laurent22/joplin/releases/tag/v0.10.51) | 2018-01-28T18:47:02Z | 1,327 | 1,598 | 327 | 3,252
[v0.10.48](https://github.com/laurent22/joplin/releases/tag/v0.10.48) | 2018-01-23T11:19:51Z | 1,964 | 1,750 | 30 | 3,744
@@ -112,7 +108,7 @@ Version | Date | Windows | macOS | Linux | Total
[v0.10.43](https://github.com/laurent22/joplin/releases/tag/v0.10.43) | 2018-01-08T10:12:10Z | 3,437 | 2,354 | 1,205 | 6,996
[v0.10.41](https://github.com/laurent22/joplin/releases/tag/v0.10.41) | 2018-01-05T20:38:12Z | 1,036 | 1,547 | 238 | 2,821
[v0.10.40](https://github.com/laurent22/joplin/releases/tag/v0.10.40) | 2018-01-02T23:16:57Z | 1,594 | 1,786 | 338 | 3,718
[v0.10.39](https://github.com/laurent22/joplin/releases/tag/v0.10.39) | 2017-12-11T21:19:44Z | 5,790 | 4,262 | 3,164 | 13,216
[v0.10.39](https://github.com/laurent22/joplin/releases/tag/v0.10.39) | 2017-12-11T21:19:44Z | 5,784 | 4,258 | 3,160 | 13,202
[v0.10.38](https://github.com/laurent22/joplin/releases/tag/v0.10.38) | 2017-12-08T10:12:06Z | 1,048 | 1,229 | 306 | 2,583
[v0.10.37](https://github.com/laurent22/joplin/releases/tag/v0.10.37) | 2017-12-07T19:38:05Z | 264 | 843 | 81 | 1,188
[v0.10.36](https://github.com/laurent22/joplin/releases/tag/v0.10.36) | 2017-12-05T09:34:40Z | 1,014 | 1,354 | 437 | 2,805
@@ -123,7 +119,7 @@ Version | Date | Windows | macOS | Linux | Total
[v0.10.30](https://github.com/laurent22/joplin/releases/tag/v0.10.30) | 2017-11-30T20:28:16Z | 722 | 1,367 | 419 | 2,508
[v0.10.28](https://github.com/laurent22/joplin/releases/tag/v0.10.28) | 2017-11-30T01:07:46Z | 1,328 | 1,698 | 872 | 3,898
[v0.10.26](https://github.com/laurent22/joplin/releases/tag/v0.10.26) | 2017-11-29T16:02:17Z | 186 | 699 | 260 | 1,145
[v0.10.25](https://github.com/laurent22/joplin/releases/tag/v0.10.25) | 2017-11-24T14:27:49Z | 148 | 694 | 6,389 | 7,231
[v0.10.25](https://github.com/laurent22/joplin/releases/tag/v0.10.25) | 2017-11-24T14:27:49Z | 148 | 694 | 6,378 | 7,220
[v0.10.23](https://github.com/laurent22/joplin/releases/tag/v0.10.23) | 2017-11-21T19:38:41Z | 132 | 645 | 27 | 804
[v0.10.22](https://github.com/laurent22/joplin/releases/tag/v0.10.22) | 2017-11-20T21:45:57Z | 84 | 643 | 18 | 745
[v0.10.21](https://github.com/laurent22/joplin/releases/tag/v0.10.21) | 2017-11-18T00:53:15Z | 51 | 636 | 12 | 699