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

Compare commits

...

19 Commits

Author SHA1 Message Date
Laurent Cozic
9d762a4319 Android release v0.10.86 2018-02-06 13:01:20 +00:00
Laurent Cozic
18d94c7585 Electron release v0.10.60 2018-02-06 12:57:40 +00:00
Laurent Cozic
af82345eb8 Fixed tray icon and update issue 2018-02-06 13:11:59 +00:00
Laurent Cozic
1e94a22986 Merge branch 'master' of github.com:laurent22/joplin 2018-02-06 13:06:59 +00:00
Laurent Cozic
e19a8a99ff macOS: Fixed startup crash 2018-02-06 13:05:36 +00:00
Laurent Cozic
f975009e24 Update readme 2018-02-05 19:02:11 +00:00
Laurent Cozic
90640fafc7 Merge branch 'master' of github.com:laurent22/joplin 2018-02-05 18:49:58 +00:00
Laurent Cozic
42e0e1e5a5 Updated build instructions 2018-02-06 09:42:20 +00:00
Laurent Cozic
61f64fa933 Added Markdown doc 2018-02-05 22:53:10 +00:00
Laurent Cozic
0d0ffd6d27 Added Markdown doc 2018-02-05 22:50:17 +00:00
Laurent Cozic
023ccffd2e Electron release v0.10.59 2018-02-05 22:20:31 +00:00
Laurent Cozic
bc26098c7d Android release v0.10.85 2018-02-05 22:19:21 +00:00
Laurent Cozic
7257a71a18 Mobile: Fixes #159: Make sure text fields aren't hidden by keyboard on iOS 2018-02-05 18:32:59 +00:00
Laurent Cozic
8ad8b73585 Better error handling for Katex and handling of code blocks and inline 2018-02-05 17:55:35 +00:00
Laurent Cozic
9a06815db9 Electron release v0.10.58 2018-02-05 17:34:39 +00:00
Laurent Cozic
66947d4954 Fixing appveyor script 2018-02-05 17:34:31 +00:00
Laurent Cozic
3ec22185d5 Electron release v0.10.57 2018-02-05 17:32:54 +00:00
Laurent Cozic
0f05c23e26 Fixing deployment script 2018-02-05 17:32:48 +00:00
Laurent Cozic
74493fece0 Android release v0.10.83 2018-02-05 17:32:00 +00:00
17 changed files with 212 additions and 85 deletions

View File

@@ -46,6 +46,8 @@ before_install:
script:
- |
cd ElectronClient/app
cd Tools
npm install
cd ../ElectronClient/app
rsync -aP --delete ../../ReactNativeClient/lib/ lib/
npm install && yarn dist

View File

@@ -17,6 +17,15 @@ If you get a node-gyp related error you might need to manually install it: `npm
- Install node v8.x (check with `node --version`) - https://nodejs.org/en/
- If you get a node-gyp related error you might need to manually install it: `npm install -g node-gyp`
# Building the tools
Before building any of the applications, you need to build the tools:
```
cd Tools
npm install
```
# Building the Electron application
```

View File

@@ -4,6 +4,8 @@ const { shim } = require('lib/shim');
const url = require('url')
const path = require('path')
const urlUtils = require('lib/urlUtils.js');
const { dirname, basename } = require('lib/path-utils');
const fs = require('fs-extra');
class ElectronAppWrapper {
@@ -13,6 +15,7 @@ class ElectronAppWrapper {
this.win_ = null;
this.willQuitApp_ = false;
this.tray_ = null;
this.buildDir_ = null;
}
electronApp() {
@@ -114,15 +117,31 @@ class ElectronAppWrapper {
return !!this.tray_;
}
buildDir() {
if (this.buildDir_) return this.buildDir_;
let dir = __dirname + '/build';
if (!fs.pathExistsSync(dir)) {
dir = dirname(__dirname) + '/build';
if (!fs.pathExistsSync(dir)) throw new Error('Cannot find build dir');
}
this.buildDir_ = dir;
return dir;
}
// Note: this must be called only after the "ready" event of the app has been dispatched
createTray(contextMenu) {
this.tray_ = new Tray(__dirname + '/build/icons/16x16.png')
this.tray_.setToolTip(this.electronApp_.getName())
this.tray_.setContextMenu(contextMenu)
try {
this.tray_ = new Tray(this.buildDir() + '/icons/16x16.png')
this.tray_.setToolTip(this.electronApp_.getName())
this.tray_.setContextMenu(contextMenu)
this.tray_.on('click', () => {
this.window().show();
});
this.tray_.on('click', () => {
this.window().show();
});
} catch (error) {
console.error("Cannot create tray", error);
}
}
destroyTray() {

View File

@@ -6,6 +6,9 @@ const { _ } = require('lib/locale.js');
let autoUpdateLogger_ = new Logger();
let checkInBackground_ = false;
// Note: Electron Builder's autoUpdater is incredibly buggy so currently it's only used
// to detect if a new version is present. If it is, the download link is simply opened
// in a new browser window.
autoUpdater.autoDownload = false;
autoUpdater.on('error', (error) => {
@@ -14,19 +17,36 @@ autoUpdater.on('error', (error) => {
dialog.showErrorBox(_('Error'), error == null ? "unknown" : (error.stack || error).toString())
})
autoUpdater.on('update-available', () => {
function htmlToText_(html) {
let output = html.replace(/\n/g, '');
output = output.replace(/<li>/g, '- ');
output = output.replace(/<\/li>/g, '\n');
output = output.replace(/<ul>/g, '');
output = output.replace(/<\/ul>/g, '');
output = output.replace(/<.*?>/g, '');
output = output.replace(/<\/.*?>/g, '');
return output;
}
autoUpdater.on('update-available', (info) => {
if (!info.version || !info.path) {
if (checkInBackground_) return;
dialog.showErrorBox(_('Error'), ('Could not get version info: ' + JSON.stringify(info)));
return;
}
const downloadUrl = 'https://github.com/laurent22/joplin/releases/download/v' + info.version + '/' + info.path;
let releaseNotes = info.releaseNotes + '';
if (releaseNotes) releaseNotes = '\n\n' + _('Release notes:\n\n%s', htmlToText_(releaseNotes));
dialog.showMessageBox({
type: 'info',
message: _('An update is available, do you want to update now?'),
message: _('An update is available, do you want to download it now?' + releaseNotes),
buttons: [_('Yes'), _('No')]
}, (buttonIndex) => {
if (buttonIndex === 0) {
try {
autoUpdater.downloadUpdate()
} catch (error) {
autoUpdateLogger_.error(error);
dialog.showErrorBox(_('Error'), _('Could not download the update: %s', error.message));
}
require('electron').shell.openExternal(downloadUrl);
}
})
})
@@ -37,18 +57,18 @@ autoUpdater.on('update-not-available', () => {
dialog.showMessageBox({ message: _('Current version is up-to-date.') })
})
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox({ message: _('New version downloaded - application will quit now and update...') }, () => {
setTimeout(() => {
try {
autoUpdater.quitAndInstall();
} catch (error) {
autoUpdateLogger_.error(error);
dialog.showErrorBox(_('Error'), _('Could not install the update: %s', error.message));
}
}, 100);
})
})
// autoUpdater.on('update-downloaded', () => {
// dialog.showMessageBox({ message: _('New version downloaded - application will quit now and update...') }, () => {
// setTimeout(() => {
// try {
// autoUpdater.quitAndInstall();
// } catch (error) {
// autoUpdateLogger_.error(error);
// dialog.showErrorBox(_('Error'), _('Could not install the update: %s', error.message));
// }
// }, 100);
// })
// })
function checkForUpdates(inBackground, logFilePath) {
if (logFilePath && !autoUpdateLogger_.targets().length) {

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "0.10.56",
"version": "0.10.60",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "0.10.56",
"version": "0.10.60",
"description": "Joplin for Desktop",
"main": "main.js",
"scripts": {
@@ -22,6 +22,9 @@
},
"build": {
"appId": "net.cozic.joplin-desktop",
"extraResources": [
"build/icons/*"
],
"win": {
"icon": "../../Assets/Joplin.ico"
},

View File

@@ -18,15 +18,15 @@ Three types of applications are available: for the **desktop** (Windows, macOS a
Operating System | Download
-----------------|--------
Windows | <a href='https://github.com/laurent22/joplin/releases/download/v0.10.54/Joplin-Setup-0.10.54.exe'><img alt='Get it on Windows' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeWindows.png'/></a>
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v0.10.54/Joplin-0.10.54.dmg'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeMacOS.png'/></a>
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v0.10.54/Joplin-0.10.54-x86_64.AppImage'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeLinux.png'/></a>
Windows | <a href='https://github.com/laurent22/joplin/releases/download/v0.10.59/Joplin-Setup-0.10.59.exe'><img alt='Get it on Windows' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeWindows.png'/></a>
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v0.10.59/Joplin-0.10.59.dmg'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeMacOS.png'/></a>
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v0.10.59/Joplin-0.10.59-x86_64.AppImage'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeLinux.png'/></a>
## Mobile applications
Operating System | Download | Alt. Download
-----------------|----------|----------------
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin/releases/download/android-v0.10.81/joplin-v0.10.81.apk)
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin/releases/download/android-v0.10.86/joplin-v0.10.86.apk)
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeIOS.png'/></a> | -
## Terminal application
@@ -144,6 +144,44 @@ On mobile, the alarms will be displayed using the built-in notification system.
If for any reason the notifications do not work, please [open an issue](https://github.com/laurent22/joplin/issues).
# Markdown
Joplin uses and renders [Github-flavoured Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) with a few variations and additions. In particular:
## Math notation
Math expressions can be added using the [Katex notation](https://khan.github.io/KaTeX/). To add an inline equation, wrap the expression in `` `{.katex}EXPRESSION` ``, eg. `` `{.katex}\sqrt{3x-1}+(1+x)^2` ``. To create an expression block, wrap it as follow:
```katex
EXPRESSION
```
For example:
```katex
f(x) = \int_{-\infty}^\infty
\hat f(\xi)\,e^{2 \pi i \xi x}
\,d\xi
```
Here is an example with the Markdown and rendered result side by side:
<img src="https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/Katex.png" style="max-width: 100%; max-height: 35em;">
## Checkboxes
Checkboxes can be added like so:
-[ ] Milk
-[ ] Rice
-[ ] Eggs
The checkboxes can then be ticked in the mobile and desktop applications.
# Contributing
Please see the guide for information on how to contribute to the development of Joplin: https://github.com/laurent22/joplin/blob/master/CONTRIBUTING.md
# Localisation
Joplin is currently available in the languages below. If you would like to contribute a **new translation**, it is quite straightforward, please follow these steps:
@@ -176,10 +214,6 @@ Current translations:
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/jp.png) | 日本語 | ja_JP | | 74%
<!-- LOCALE-TABLE-AUTO-GENERATED -->
# Contributing
Please see the guide for information on how to contribute to the development of Joplin: https://github.com/laurent22/joplin/blob/master/CONTRIBUTING.md
# Coming features
- Mobile: manage tags

View File

@@ -90,8 +90,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion 16
targetSdkVersion 22
versionCode 2097259
versionName "0.10.81"
versionCode 2097264
versionName "0.10.86"
ndk {
abiFilters "armeabi-v7a", "x86"
}

View File

@@ -251,7 +251,11 @@ class MdToHtml {
}
}
if (codeBlockHandler) codeBlockHandler.loadAssets();
if (codeBlockHandler) {
codeBlockHandler.loadAssets().catch((error) => {
console.warn('MdToHtml: Error loading assets for ' + codeBlockHandler.name() + ': ', error.message);
});
}
if (t.type === 'image') {
if (tokenContent) attrs.push(['title', tokenContent]);
@@ -267,7 +271,7 @@ class MdToHtml {
} else {
if (tokenContent) {
if ((isCodeBlock || isInlineCode) && codeBlockHandler) {
output = codeBlockHandler.processContent(output, tokenContent);
output = codeBlockHandler.processContent(output, tokenContent, isCodeBlock ? 'block' : 'inline');
} else {
output.push(htmlentities(tokenContent));
}

View File

@@ -9,9 +9,12 @@ class MdToHtml_Katex {
return 'katex';
}
processContent(renderedTokens, content) {
processContent(renderedTokens, content, tagType) {
try {
const renderered = katex.renderToString(content);
let renderered = katex.renderToString(content);
if (tagType === 'block') renderered = '<p>' + renderered + '</p>';
renderedTokens.push(renderered);
} catch (error) {
renderedTokens.push('Cannot render Katex content: ' + error.message);
@@ -33,6 +36,7 @@ class MdToHtml_Katex {
// Fonts must go under the resourceDir directory because this is the baseUrl of NoteBodyViewer
const baseDir = Setting.value('resourceDir');
await shim.fsDriver().mkdir(baseDir + '/fonts');
await shim.fetchBlob('https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0-beta1/fonts/KaTeX_Main-Regular.woff2', { overwrite: false, path: baseDir + '/fonts/KaTeX_Main-Regular.woff2' });
await shim.fetchBlob('https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0-beta1/fonts/KaTeX_Math-Italic.woff2', { overwrite: false, path: baseDir + '/fonts/KaTeX_Math-Italic.woff2' });
await shim.fetchBlob('https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0-beta1/fonts/KaTeX_Size1-Regular.woff2', { overwrite: false, path: baseDir + '/fonts/KaTeX_Size1-Regular.woff2' });

View File

@@ -2,7 +2,7 @@ const React = require('react'); const Component = React.Component;
const { connect } = require('react-redux');
const { NotesScreen } = require('lib/components/screens/notes.js');
const { SearchScreen } = require('lib/components/screens/search.js');
const { View } = require('react-native');
const { KeyboardAvoidingView, Keyboard, Platform, View } = require('react-native');
const { _ } = require('lib/locale.js');
const { themeStyle } = require('lib/components/global-style.js');
@@ -11,6 +11,31 @@ class AppNavComponent extends Component {
constructor() {
super();
this.previousRouteName_ = null;
this.state = {
autoCompletionBarExtraHeight: 0, // Extra padding for the auto completion bar at the top of the keyboard
}
}
componentWillMount() {
if (Platform.OS === 'ios') {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow.bind(this));
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide.bind(this));
}
}
componentWillUnmount() {
if (this.keyboardDidShowListener) this.keyboardDidShowListener.remove();
if (this.keyboardDidHideListener) this.keyboardDidHideListener.remove();
this.keyboardDidShowListener = null;
this.keyboardDidHideListener = null;
}
keyboardDidShow () {
this.setState({ autoCompletionBarExtraHeight: 30 })
}
keyboardDidHide () {
this.setState({ autoCompletionBarExtraHeight:0 })
}
render() {
@@ -44,11 +69,12 @@ class AppNavComponent extends Component {
const style = { flex: 1, backgroundColor: theme.backgroundColor }
return (
<View style={style}>
<KeyboardAvoidingView behavior={ Platform.OS === 'ios' ? "padding" : null } style={style}>
<NotesScreen visible={notesScreenVisible} navigation={{ state: route }} />
{ searchScreenLoaded && <SearchScreen visible={searchScreenVisible} navigation={{ state: route }} /> }
{ (!notesScreenVisible && !searchScreenVisible) && <Screen navigation={{ state: route }} /> }
</View>
<View style={{ height: this.state.autoCompletionBarExtraHeight }} />
</KeyboardAvoidingView>
);
}

View File

@@ -1,5 +1,5 @@
const React = require('react'); const Component = React.Component;
const { TouchableOpacity, Linking, View, Switch, Slider, StyleSheet, Text, Button, ScrollView, TextInput } = require('react-native');
const { Platform, TouchableOpacity, Linking, View, Switch, Slider, StyleSheet, Text, Button, ScrollView, TextInput } = require('react-native');
const { connect } = require('react-redux');
const { ScreenHeader } = require('lib/components/screen-header.js');
const { _, setLocale } = require('lib/locale.js');
@@ -72,6 +72,11 @@ class ConfigScreenComponent extends BaseScreenComponent {
},
}
if (Platform.OS === 'ios') {
styles.settingControl.borderBottomWidth = 1;
styles.settingControl.borderBottomColor = theme.dividerColor;
}
styles.switchSettingText = Object.assign({}, styles.settingText);
styles.switchSettingText.width = '80%';
@@ -106,8 +111,6 @@ class ConfigScreenComponent extends BaseScreenComponent {
settings: settings,
settingsChanged: true,
});
console.info(settings['sync.5.path']);
}
const md = Setting.settingMetadata(key);
@@ -163,7 +166,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
return (
<View key={key} style={this.styles().settingContainer}>
<Text key="label" style={this.styles().settingText}>{md.label()}</Text>
<TextInput key="control" style={this.styles().settingControl} value={value} onChangeText={(value) => updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
<TextInput autoCapitalize="none" key="control" style={this.styles().settingControl} value={value} onChangeText={(value) => updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
</View>
);
} else {

View File

@@ -1,5 +1,5 @@
const React = require('react'); const Component = React.Component;
const { Platform, Keyboard, BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking, Image, KeyboardAvoidingView } = require('react-native');
const { Platform, Keyboard, BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking, Image } = require('react-native');
const { connect } = require('react-redux');
const { uuid } = require('lib/uuid.js');
const { Log } = require('lib/log.js');
@@ -149,12 +149,6 @@ class NoteScreenComponent extends BaseScreenComponent {
await shared.initState(this);
this.refreshNoteMetadata();
if (Platform.OS === 'ios') {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow.bind(this));
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide.bind(this));
}
}
refreshNoteMetadata(force = null) {
@@ -163,19 +157,6 @@ class NoteScreenComponent extends BaseScreenComponent {
componentWillUnmount() {
BackButtonService.removeHandler(this.backHandler);
if (Platform.OS === 'ios'){
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
}
_keyboardDidShow () {
this.setState({ heightBumpView:30 })
}
_keyboardDidHide () {
this.setState({ heightBumpView:0 })
}
title_changeText(text) {
@@ -542,7 +523,7 @@ class NoteScreenComponent extends BaseScreenComponent {
);
return (
<KeyboardAvoidingView behavior= {(Platform.OS === 'ios')? "padding" : null} style={this.rootStyle(this.props.theme).root}>
<View style={this.rootStyle(this.props.theme).root}>
<ScreenHeader
folderPickerOptions={{
enabled: true,
@@ -578,8 +559,7 @@ class NoteScreenComponent extends BaseScreenComponent {
/>
<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
<View style={{ height: this.state.heightBumpView }} />
</KeyboardAvoidingView>
</View>
);
}

View File

@@ -22,7 +22,7 @@ async function main() {
const release = await githubRelease(tagName, true);
console.info('Created GitHub release: ' + release.url);
console.info('Created GitHub release: ' + release.html_url);
}
main().catch((error) => {

View File

@@ -13,7 +13,9 @@ install:
- yarn
build_script:
- ps: cd ElectronClient\app
- ps: cd Tools
- npm install
- ps: cd ..\ElectronClient\app
- ps: xcopy /C /I /H /R /Y /S ..\..\ReactNativeClient\lib lib
- npm install
- yarn dist

BIN
docs/images/Katex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -218,15 +218,15 @@
<tbody>
<tr>
<td>Windows</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v0.10.54/Joplin-Setup-0.10.54.exe'><img alt='Get it on Windows' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeWindows.png'/></a></td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v0.10.59/Joplin-Setup-0.10.59.exe'><img alt='Get it on Windows' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeWindows.png'/></a></td>
</tr>
<tr>
<td>macOS</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v0.10.54/Joplin-0.10.54.dmg'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeMacOS.png'/></a></td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v0.10.59/Joplin-0.10.59.dmg'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeMacOS.png'/></a></td>
</tr>
<tr>
<td>Linux</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v0.10.54/Joplin-0.10.54-x86_64.AppImage'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeLinux.png'/></a></td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v0.10.59/Joplin-0.10.59-x86_64.AppImage'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeLinux.png'/></a></td>
</tr>
</tbody>
</table>
@@ -243,7 +243,7 @@
<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://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeAndroid.png'/></a></td>
<td>or <a href="https://github.com/laurent22/joplin/releases/download/android-v0.10.81/joplin-v0.10.81.apk">Download APK File</a></td>
<td>or <a href="https://github.com/laurent22/joplin/releases/download/android-v0.10.86/joplin-v0.10.86.apk">Download APK File</a></td>
</tr>
<tr>
<td>iOS</td>
@@ -328,6 +328,29 @@ sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin
<p>See <a href="https://github.com/mikaelbr/node-notifier/blob/master/DECISION_FLOW.md">documentation and flow chart for reporter choice</a></p>
<p>On mobile, the alarms will be displayed using the built-in notification system.</p>
<p>If for any reason the notifications do not work, please <a href="https://github.com/laurent22/joplin/issues">open an issue</a>.</p>
<h1 id="markdown">Markdown</h1>
<p>Joplin uses and renders <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet">Github-flavoured Markdown</a> with a few variations and additions. In particular:</p>
<h2 id="math-notation">Math notation</h2>
<p>Math expressions can be added using the <a href="https://khan.github.io/KaTeX/">Katex notation</a>. To add an inline equation, wrap the expression in <code>`{.katex}EXPRESSION` </code>, eg. <code>`{.katex}\sqrt{3x-1}+(1+x)^2` </code>. To create an expression block, wrap it as follow:</p>
<pre><code>```katex
EXPRESSION
```
</code></pre><p>For example:</p>
<pre><code>```katex
f(x) = \int_{-\infty}^\infty
\hat f(\xi)\,e^{2 \pi i \xi x}
\,d\xi
```
</code></pre><p>Here is an example with the Markdown and rendered result side by side:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/Katex.png" style="max-width: 100%; max-height: 35em;"></p>
<h2 id="checkboxes">Checkboxes</h2>
<p>Checkboxes can be added like so:</p>
<pre><code>-[ ] Milk
-[ ] Rice
-[ ] Eggs
</code></pre><p>The checkboxes can then be ticked in the mobile and desktop applications.</p>
<h1 id="contributing">Contributing</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/master/CONTRIBUTING.md">https://github.com/laurent22/joplin/blob/master/CONTRIBUTING.md</a></p>
<h1 id="localisation">Localisation</h1>
<p>Joplin is currently available in the languages below. If you would like to contribute a <strong>new translation</strong>, it is quite straightforward, please follow these steps:</p>
<ul>
@@ -355,14 +378,14 @@ sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/hr.png" alt=""></td>
<td>Croatian</td>
<td>hr_HR</td>
<td>Hrvoje Mandić <a href="&#x6d;&#x61;&#x69;&#108;&#116;&#111;&#x3a;&#x74;&#114;&#98;&#x75;&#x68;&#111;&#109;&#64;&#110;&#x65;&#116;&#x2e;&#104;&#x72;">&#x74;&#114;&#98;&#x75;&#x68;&#111;&#109;&#64;&#110;&#x65;&#116;&#x2e;&#104;&#x72;</a></td>
<td>Hrvoje Mandić <a href="&#109;&#97;&#x69;&#x6c;&#116;&#111;&#x3a;&#x74;&#114;&#98;&#117;&#104;&#x6f;&#x6d;&#x40;&#110;&#101;&#x74;&#46;&#104;&#114;">&#x74;&#114;&#98;&#117;&#104;&#x6f;&#x6d;&#x40;&#110;&#101;&#x74;&#46;&#104;&#114;</a></td>
<td>72%</td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/de.png" alt=""></td>
<td>Deutsch</td>
<td>de_DE</td>
<td>Tobias Strobel <a href="&#109;&#x61;&#105;&#108;&#x74;&#111;&#x3a;&#x67;&#x69;&#116;&#64;&#115;&#x74;&#x72;&#111;&#98;&#101;&#108;&#x74;&#x6f;&#98;&#105;&#97;&#115;&#46;&#x64;&#101;">&#x67;&#x69;&#116;&#64;&#115;&#x74;&#x72;&#111;&#98;&#101;&#108;&#x74;&#x6f;&#98;&#105;&#97;&#115;&#46;&#x64;&#101;</a></td>
<td>Tobias Strobel <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#58;&#x67;&#x69;&#x74;&#64;&#x73;&#x74;&#x72;&#x6f;&#x62;&#x65;&#108;&#x74;&#111;&#98;&#x69;&#97;&#x73;&#x2e;&#x64;&#x65;">&#x67;&#x69;&#x74;&#64;&#x73;&#x74;&#x72;&#x6f;&#x62;&#x65;&#108;&#x74;&#111;&#98;&#x69;&#97;&#x73;&#x2e;&#x64;&#x65;</a></td>
<td>92%</td>
</tr>
<tr>
@@ -418,14 +441,14 @@ sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/ru.png" alt=""></td>
<td>Русский</td>
<td>ru_RU</td>
<td>Artyom Karlov <a href="&#x6d;&#x61;&#x69;&#108;&#x74;&#x6f;&#x3a;&#97;&#x72;&#116;&#121;&#111;&#109;&#x2e;&#107;&#97;&#114;&#x6c;&#111;&#118;&#x40;&#x67;&#109;&#x61;&#x69;&#x6c;&#x2e;&#x63;&#x6f;&#109;">&#97;&#x72;&#116;&#121;&#111;&#109;&#x2e;&#107;&#97;&#114;&#x6c;&#111;&#118;&#x40;&#x67;&#109;&#x61;&#x69;&#x6c;&#x2e;&#x63;&#x6f;&#109;</a></td>
<td>Artyom Karlov <a href="&#x6d;&#97;&#105;&#x6c;&#116;&#x6f;&#58;&#x61;&#114;&#116;&#x79;&#111;&#109;&#46;&#107;&#x61;&#114;&#x6c;&#x6f;&#118;&#64;&#x67;&#109;&#x61;&#105;&#x6c;&#x2e;&#x63;&#x6f;&#x6d;">&#x61;&#114;&#116;&#x79;&#111;&#109;&#46;&#107;&#x61;&#114;&#x6c;&#x6f;&#118;&#64;&#x67;&#109;&#x61;&#105;&#x6c;&#x2e;&#x63;&#x6f;&#x6d;</a></td>
<td>96%</td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/cn.png" alt=""></td>
<td>中文 (简体)</td>
<td>zh_CN</td>
<td>RCJacH <a href="&#x6d;&#x61;&#x69;&#x6c;&#x74;&#111;&#x3a;&#x52;&#x43;&#74;&#97;&#99;&#72;&#x40;&#111;&#117;&#x74;&#x6c;&#111;&#111;&#x6b;&#x2e;&#99;&#x6f;&#x6d;">&#x52;&#x43;&#74;&#97;&#99;&#72;&#x40;&#111;&#117;&#x74;&#x6c;&#111;&#111;&#x6b;&#x2e;&#99;&#x6f;&#x6d;</a></td>
<td>RCJacH <a href="&#x6d;&#97;&#x69;&#108;&#116;&#111;&#58;&#x52;&#67;&#x4a;&#97;&#x63;&#72;&#x40;&#x6f;&#x75;&#116;&#108;&#111;&#x6f;&#107;&#x2e;&#x63;&#111;&#109;">&#x52;&#67;&#x4a;&#97;&#x63;&#72;&#x40;&#x6f;&#x75;&#116;&#108;&#111;&#x6f;&#107;&#x2e;&#x63;&#111;&#109;</a></td>
<td>76%</td>
</tr>
<tr>
@@ -438,8 +461,6 @@ sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin
</tbody>
</table>
<!-- LOCALE-TABLE-AUTO-GENERATED -->
<h1 id="contributing">Contributing</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/master/CONTRIBUTING.md">https://github.com/laurent22/joplin/blob/master/CONTRIBUTING.md</a></p>
<h1 id="coming-features">Coming features</h1>
<ul>
<li>Mobile: manage tags</li>