You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-09-02 20:46:21 +02:00
Compare commits
95 Commits
android-v1
...
android-v1
Author | SHA1 | Date | |
---|---|---|---|
|
a5f17fad58 | ||
|
22c3646fc6 | ||
|
a3e7f0b5ef | ||
|
9f5da92ab4 | ||
|
fdafe3b947 | ||
|
6dec711a0a | ||
|
ec67bc7f1a | ||
|
47aaf639b3 | ||
|
51233c2745 | ||
|
90bc84c010 | ||
|
7f1e684dab | ||
|
5f28d0ec24 | ||
|
348c4ad3a3 | ||
|
f90cc8d67d | ||
|
d3e9ffcaea | ||
|
b0a4a10dcc | ||
|
8ef5c96cb6 | ||
|
6be36ffe17 | ||
|
7d7975daf4 | ||
|
c98644b72f | ||
|
8a097fb79c | ||
|
f71e7f4fd3 | ||
|
9c8add97e7 | ||
|
b099c811cc | ||
|
a8ae0f8078 | ||
|
d355169b60 | ||
|
08295525de | ||
|
fdcf27fc65 | ||
|
f2c82b05d9 | ||
|
add9dda759 | ||
|
fbba4a1ec4 | ||
|
154d303463 | ||
|
fdef2db232 | ||
|
d49fa8e42b | ||
|
871d3cb87d | ||
|
f1d751b356 | ||
|
60c1939d26 | ||
|
d2aaac22e5 | ||
|
c6842a8591 | ||
|
60e9abdd61 | ||
|
9796630aa2 | ||
|
7230cdea33 | ||
|
6460907976 | ||
|
d7a50a1b48 | ||
|
4a88343372 | ||
|
74c2bbc2f0 | ||
|
5ed5d16716 | ||
|
43083b0b7a | ||
|
a4e5054008 | ||
|
02eb2f2e45 | ||
|
5d015bf746 | ||
|
ce5db5a5c1 | ||
|
cdcc3902c5 | ||
|
309835f2fe | ||
|
eca0ab0ef6 | ||
|
4ce35ee1ed | ||
|
8856456afd | ||
|
4259d900f4 | ||
|
438c448ef7 | ||
|
0fb5b35212 | ||
|
b69efb4970 | ||
|
44ea237538 | ||
|
a58316b24c | ||
|
df95d01f6e | ||
|
d6924893e5 | ||
|
0f04ea4f70 | ||
|
4b8026cf83 | ||
|
a98a586295 | ||
|
29ec7ba03a | ||
|
a35cc23d28 | ||
|
20a8ddd841 | ||
|
774fc9ce53 | ||
|
84ab395fae | ||
|
edc4dc5801 | ||
|
6e128a7285 | ||
|
ff977cebaf | ||
|
5bcd5f050a | ||
|
fe57f163f3 | ||
|
cb24db4e39 | ||
|
e93d96193c | ||
|
637a4dc1f9 | ||
|
2c522637ef | ||
|
8fbb1fd246 | ||
|
75b7e7d999 | ||
|
7e2e901035 | ||
|
a73a1f896c | ||
|
ae7f0e8ffb | ||
|
08343e6be9 | ||
|
9cb3496159 | ||
|
37b035d0d0 | ||
|
f37ac8b5de | ||
|
343d04b05d | ||
|
e92741edd6 | ||
|
8565cd7d40 | ||
|
58e299383d |
@@ -45,3 +45,4 @@ Server/docs/
|
||||
Server/dist/
|
||||
Server/bin/
|
||||
Server/node_modules/
|
||||
ElectronClient/app/packageInfo.js
|
39
.eslintrc.js
39
.eslintrc.js
@@ -33,14 +33,22 @@ module.exports = {
|
||||
"sourceType": "module",
|
||||
},
|
||||
'rules': {
|
||||
// -------------------------------
|
||||
// Code correctness
|
||||
// -------------------------------
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
// Ignore all unused function arguments, because in some
|
||||
// case they are kept to indicate the function signature.
|
||||
//"no-unused-vars": ["error", { "argsIgnorePattern": ".*" }],
|
||||
"@typescript-eslint/no-unused-vars": ["error"],
|
||||
"no-unused-vars": "error",
|
||||
"no-constant-condition": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
// This error is always a false positive so far since it detects
|
||||
// possible race conditions in contexts where we know it cannot happen.
|
||||
"require-atomic-updates": 0,
|
||||
// "no-lonely-if": "error",
|
||||
|
||||
// -------------------------------
|
||||
// Formatting
|
||||
// -------------------------------
|
||||
"space-in-parens": ["error", "never"],
|
||||
"semi": ["error", "always"],
|
||||
"eol-last": ["error", "always"],
|
||||
@@ -49,11 +57,26 @@ module.exports = {
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"no-trailing-spaces": "error",
|
||||
"linebreak-style": ["error", "unix"],
|
||||
// This error is always a false positive so far since it detects
|
||||
// possible race conditions in contexts where we know it cannot happen.
|
||||
"require-atomic-updates": 0,
|
||||
"prefer-template": ["error"],
|
||||
"template-curly-spacing": ["error", "never"]
|
||||
"template-curly-spacing": ["error", "never"],
|
||||
"key-spacing": ["error", {
|
||||
"beforeColon": false,
|
||||
"afterColon": true,
|
||||
"mode": "strict"
|
||||
}],
|
||||
"block-spacing": ["error"],
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||
"no-spaced-func": ["error"],
|
||||
"func-call-spacing": ["error"],
|
||||
"space-before-function-paren": ["error", {
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}],
|
||||
"multiline-comment-style": ["error", "separate-lines"],
|
||||
"space-before-blocks": "error",
|
||||
"spaced-comment": ["error", "always"],
|
||||
"keyword-spacing": ["error", { "before": true, "after": true }]
|
||||
},
|
||||
"plugins": [
|
||||
"react",
|
||||
|
5
.github/ISSUE_TEMPLATE.md
vendored
5
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,4 +1,9 @@
|
||||
👉 Please follow one of these issue templates:
|
||||
- https://github.com/laurent22/joplin/issues/new/choose
|
||||
|
||||
⚠️
|
||||
The GitHub issue tracker is for **bugs** and **security issues** ONLY. For feature requests and support, please use the forum:
|
||||
https://discourse.joplinapp.org/
|
||||
⚠️
|
||||
|
||||
Note: to keep the backlog clean and actionable, issues may be immediately closed if they do not follow one of the above issue templates.
|
||||
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Report an accepted feature request.
|
||||
title: ''
|
||||
labels: 'feature request'
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Please search open issues first - many features have already been requested!
|
||||
-->
|
||||
|
||||
🚨 A feature request that has not been accepted on the forum will be closed! 🚨
|
||||
|
||||
## Has it been discussed in the forum? Link to topic.
|
||||
<!--
|
||||
Feature requests must be discussed and accepted in the forum first. https://discourse.joplinapp.org
|
||||
Please provide a link to the topic.
|
||||
Feature requests without a link to the discussion/topic on the forum will be closed.
|
||||
-->
|
4
.github/ISSUE_TEMPLATE/question.md
vendored
4
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -2,11 +2,11 @@
|
||||
name: "🤔 Questions and Help"
|
||||
about: The issue tracker is not for questions. Please ask questions on https://discourse.joplinapp.org/.
|
||||
title: ''
|
||||
labels: 'question'
|
||||
labels: 'invalid'
|
||||
|
||||
---
|
||||
|
||||
🚨 The issue tracker is not for questions. 🚨
|
||||
⚠🚨⛔ The issue tracker is not for questions. ⛔🚨⚠
|
||||
|
||||
As it happens, support requests that are created as issues are likely to be closed. We want to make sure you are able to find the help you seek.
|
||||
|
||||
|
2
.github/PULL_REQUEST_TEMPLATE
vendored
2
.github/PULL_REQUEST_TEMPLATE
vendored
@@ -6,6 +6,8 @@ Please prefix the title with the platform you are targetting:
|
||||
- "Mobile" for the mobile app (or "Android" / "iOS" if the pull request only applies to one of the mobile platforms)
|
||||
- "CLI" for the CLI app
|
||||
|
||||
If it's not related to any platform (such as a translation, change to the documentation, etc.), simply don't add a platform.
|
||||
|
||||
For example: "Desktop: Added new setting to change font", or "Mobile: Fixed config screen error"
|
||||
|
||||
PLEASE READ THE GUIDE FIRST: https://github.com/laurent22/joplin/blob/master/CONTRIBUTING.md
|
||||
|
27
.travis.yml
27
.travis.yml
@@ -55,19 +55,42 @@ before_install:
|
||||
script:
|
||||
- |
|
||||
# Install tools
|
||||
npm install
|
||||
cd Tools
|
||||
npm install
|
||||
cd ..
|
||||
|
||||
# Run test units
|
||||
cd ../CliClient
|
||||
cd CliClient
|
||||
npm install
|
||||
./run_test.sh
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
fi
|
||||
cd ..
|
||||
|
||||
# Run linter for pull requests only - this is so that
|
||||
# bypassing eslint is allowed for urgent fixes.
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
npm run linter-ci ./
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
fi
|
||||
fi
|
||||
|
||||
# Find out if we should run the build or not. Electron-builder gets stuck when
|
||||
# builing PRs so we disable it in this case. The Linux build should provide
|
||||
# enough info if the app builds or not.
|
||||
# https://github.com/electron-userland/electron-builder/issues/4263
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prepare the Electron app and build it
|
||||
cd ../ElectronClient/app
|
||||
cd ElectronClient/app
|
||||
rsync -aP --delete ../../ReactNativeClient/lib/ lib/
|
||||
npm install && USE_HARD_LINKS=false yarn dist
|
||||
|
2
BUILD.md
2
BUILD.md
@@ -65,7 +65,7 @@ The [building\_win32\_tips on this page](./readme/building_win32_tips.md) might
|
||||
|
||||
# Building the Mobile application
|
||||
|
||||
First you need to setup React Native to build projects with native code. For this, follow the instructions on the [Get Started](https://facebook.github.io/react-native/docs/getting-started.html) tutorial, in the "Building Projects with Native Code" tab.
|
||||
First you need to setup React Native to build projects with native code. For this, follow the instructions on the [Get Started](https://facebook.github.io/react-native/docs/getting-started.html) tutorial, in the "React Native CLI Quickstart" tab.
|
||||
|
||||
Then, from `/ReactNativeClient`, run `npm install`, then `react-native run-ios` or `react-native run-android`.
|
||||
|
||||
|
@@ -10,8 +10,8 @@ async function handleAutocompletionPromise(line) {
|
||||
// Auto-complete the command name
|
||||
const names = await app().commandNames();
|
||||
let words = getArguments(line);
|
||||
//If there is only one word and it is not already a command name then you
|
||||
//should look for commmands it could be
|
||||
// If there is only one word and it is not already a command name then you
|
||||
// should look for commmands it could be
|
||||
if (words.length == 1) {
|
||||
if (names.indexOf(words[0]) === -1) {
|
||||
let x = names.filter(n => n.indexOf(words[0]) === 0);
|
||||
@@ -23,29 +23,29 @@ async function handleAutocompletionPromise(line) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
//There is more than one word and it is a command
|
||||
// There is more than one word and it is a command
|
||||
const metadata = (await app().commandMetadata())[words[0]];
|
||||
//If for some reason this command does not have any associated metadata
|
||||
//just don't autocomplete. However, this should not happen.
|
||||
// If for some reason this command does not have any associated metadata
|
||||
// just don't autocomplete. However, this should not happen.
|
||||
if (metadata === undefined) {
|
||||
return line;
|
||||
}
|
||||
//complete an option
|
||||
// complete an option
|
||||
let next = words.length > 1 ? words[words.length - 1] : '';
|
||||
let l = [];
|
||||
if (next[0] === '-') {
|
||||
for (let i = 0; i < metadata.options.length; i++) {
|
||||
const options = metadata.options[i][0].split(' ');
|
||||
//if there are multiple options then they will be separated by comma and
|
||||
//space. The comma should be removed
|
||||
// if there are multiple options then they will be separated by comma and
|
||||
// space. The comma should be removed
|
||||
if (options[0][options[0].length - 1] === ',') {
|
||||
options[0] = options[0].slice(0, -1);
|
||||
}
|
||||
if (words.includes(options[0]) || words.includes(options[1])) {
|
||||
continue;
|
||||
}
|
||||
//First two elements are the flag and the third is the description
|
||||
//Only autocomplete long
|
||||
// First two elements are the flag and the third is the description
|
||||
// Only autocomplete long
|
||||
if (options.length > 1 && options[1].indexOf(next) === 0) {
|
||||
l.push(options[1]);
|
||||
} else if (options[0].indexOf(next) === 0) {
|
||||
@@ -59,9 +59,9 @@ async function handleAutocompletionPromise(line) {
|
||||
ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
|
||||
return ret;
|
||||
}
|
||||
//Complete an argument
|
||||
//Determine the number of positional arguments by counting the number of
|
||||
//words that don't start with a - less one for the command name
|
||||
// Complete an argument
|
||||
// Determine the number of positional arguments by counting the number of
|
||||
// words that don't start with a - less one for the command name
|
||||
const positionalArgs = words.filter(a => a.indexOf('-') !== 0).length - 1;
|
||||
|
||||
let cmdUsage = yargParser(metadata.usage)['_'];
|
||||
@@ -155,20 +155,20 @@ function getArguments(line) {
|
||||
if (line[i] === '"') {
|
||||
if (inDoubleQuotes) {
|
||||
inDoubleQuotes = false;
|
||||
//maybe push word to parsed?
|
||||
//currentWord += '"';
|
||||
// maybe push word to parsed?
|
||||
// currentWord += '"';
|
||||
} else {
|
||||
inDoubleQuotes = true;
|
||||
//currentWord += '"';
|
||||
// currentWord += '"';
|
||||
}
|
||||
} else if (line[i] === '\'') {
|
||||
if (inSingleQuotes) {
|
||||
inSingleQuotes = false;
|
||||
//maybe push word to parsed?
|
||||
//currentWord += "'";
|
||||
// maybe push word to parsed?
|
||||
// currentWord += "'";
|
||||
} else {
|
||||
inSingleQuotes = true;
|
||||
//currentWord += "'";
|
||||
// currentWord += "'";
|
||||
}
|
||||
} else if (/\s/.test(line[i]) && !(inDoubleQuotes || inSingleQuotes)) {
|
||||
if (currentWord !== '') {
|
||||
|
@@ -50,7 +50,15 @@ class Command extends BaseCommand {
|
||||
this.stdout(_('Operation cancelled'));
|
||||
return;
|
||||
}
|
||||
|
||||
const password2 = await this.prompt(_('Confirm master password:'), { type: 'string', secure: true });
|
||||
if (!password2) {
|
||||
this.stdout(_('Operation cancelled'));
|
||||
return;
|
||||
}
|
||||
if (password !== password2) {
|
||||
this.stdout(_('Passwords do not match!'));
|
||||
return;
|
||||
}
|
||||
await EncryptionService.instance().generateMasterKeyAndEnableEncryption(password);
|
||||
return;
|
||||
}
|
||||
|
@@ -39,7 +39,14 @@ class Command extends BaseCommand {
|
||||
type_: notes[i].type_,
|
||||
};
|
||||
newNote[propName] = propValue;
|
||||
await Note.save(newNote);
|
||||
|
||||
const timestamp = Date.now();
|
||||
|
||||
await Note.save(newNote, {
|
||||
autoTimestamp: false, // No auto-timestamp because user may have provided them
|
||||
updated_time: timestamp,
|
||||
created_time: timestamp,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -84,8 +84,8 @@ class StatusBarWidget extends BaseWidget {
|
||||
// On Windows, bgBlueBright is fine and looks dark enough (Windows is probably in the wrong though)
|
||||
// For now, just don't use any colour at all.
|
||||
|
||||
//const textStyle = this.promptActive ? (s) => s : chalk.bgBlueBright.white;
|
||||
//const textStyle = (s) => s;
|
||||
// const textStyle = this.promptActive ? (s) => s : chalk.bgBlueBright.white;
|
||||
// const textStyle = (s) => s;
|
||||
const textStyle = this.promptActive ? s => s : chalk.gray;
|
||||
|
||||
this.term.drawHLine(this.absoluteInnerX, this.absoluteInnerY, this.innerWidth, textStyle(' '));
|
||||
|
@@ -13,7 +13,7 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.3\n"
|
||||
"X-Generator: Poedit 2.2.4\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
@@ -396,17 +396,20 @@ msgid ""
|
||||
"Start, stop or check the API server. To specify on which port it should run, "
|
||||
"set the api.port config variable. Commands are (%s)."
|
||||
msgstr ""
|
||||
"Starte, stoppe oder überprüfe den API Server. Um den Port zu spezifizieren "
|
||||
"auf dem er laufen soll, setze die api.port Konfigurationsvariable. Die "
|
||||
"Befehle lauten (%s)."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is already running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Der Server lauft schon auf Port %d"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Der Server lauft auf Port %d"
|
||||
|
||||
msgid "Server is not running."
|
||||
msgstr ""
|
||||
msgstr "Der Server ist nicht gestartet."
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
@@ -701,9 +704,8 @@ msgstr "&Hilfe"
|
||||
msgid "Website and documentation"
|
||||
msgstr "Webseite und Dokumentation"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Joplin Forum"
|
||||
msgstr "Joplin v%s"
|
||||
msgstr "Joplin Forum"
|
||||
|
||||
msgid "Make a donation"
|
||||
msgstr "Spenden"
|
||||
@@ -821,6 +823,7 @@ msgstr ""
|
||||
|
||||
msgid "This will open a new screen. Save your current changes?"
|
||||
msgstr ""
|
||||
"Diese Aktion wird ein neues Fenster öffnen. Aktuelle Änderungen speichern?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
@@ -850,7 +853,7 @@ msgid ""
|
||||
"continue?"
|
||||
msgstr ""
|
||||
"Durch die Deaktivierung der Verschlüsselung werden *alle* Notizen und "
|
||||
"Anhänge neu synchronisiert und unverschlüsselt an das Synchronisierungsziel "
|
||||
"Anhänge neu synchronisiert und unverschlüsselt an das Synchronisationsziel "
|
||||
"gesendet. Möchtest du fortfahren?"
|
||||
|
||||
msgid ""
|
||||
@@ -929,13 +932,13 @@ msgid "Encryption is:"
|
||||
msgstr "Die Verschlüsselung ist:"
|
||||
|
||||
msgid "Firefox Extension"
|
||||
msgstr ""
|
||||
msgstr "Firefox Erweiterung"
|
||||
|
||||
msgid "Chrome Web Store"
|
||||
msgstr ""
|
||||
msgstr "Chrome-Webstore"
|
||||
|
||||
msgid "Get it now:"
|
||||
msgstr ""
|
||||
msgstr "Hole es jetzt:"
|
||||
|
||||
# 'Nutzung', 'Gebrauch', or 'Verwendung' - depends on the context
|
||||
msgid "Usage"
|
||||
@@ -1551,9 +1554,8 @@ msgstr "Aktiviere ++insert++ Syntax"
|
||||
msgid "Enable multimarkdown table extension"
|
||||
msgstr "Aktiviere multimarkdown Tabellen Erweiterung"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable Fountain syntax support"
|
||||
msgstr "Aktiviere ~sub~ Syntax"
|
||||
msgstr "Aktiviere Fountain Unterstützung"
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr "Zeige Tray-Icon"
|
||||
@@ -1579,7 +1581,6 @@ msgstr "Zoomstufe der Benutzeroberfläche"
|
||||
msgid "Editor font size"
|
||||
msgstr "Schriftgröße im Editor"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Editor font"
|
||||
msgstr "Schriftgröße im Editor"
|
||||
|
||||
@@ -1651,11 +1652,16 @@ msgid ""
|
||||
"Fail-safe: Do not wipe out local data when sync target is empty (often the "
|
||||
"result of a misconfiguration or bug)"
|
||||
msgstr ""
|
||||
"Störungssicher: Lösche nicht die lokalen Daten, wenn das "
|
||||
"Synchronisationsziel leer ist (oft ein Resultat von Fehlkonfiguration oder "
|
||||
"einem Programmfehler)"
|
||||
|
||||
msgid ""
|
||||
"Specify the port that should be used by the API server. If not set, a "
|
||||
"default will be used."
|
||||
msgstr ""
|
||||
"Spezifiziere den Port, der vom API Server verwendet werden soll. Wenn er "
|
||||
"nicht gesetzt ist, wird ein Standardwert verwendet."
|
||||
|
||||
msgid "Enable note history"
|
||||
msgstr "Aktiviere Notizen-Verlauf"
|
||||
@@ -1693,13 +1699,11 @@ msgstr "Zusatzprogramme"
|
||||
msgid "Application"
|
||||
msgstr "Applikation"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encryption"
|
||||
msgstr "Die Verschlüsselung ist:"
|
||||
msgstr "Verschlüsselung"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Web Clipper"
|
||||
msgstr "Web-Clipper Optionen"
|
||||
msgstr "Web Clipper"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
@@ -1715,13 +1719,11 @@ msgstr "Markdown"
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr "Joplin Export Verzeichnis"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as Markdown)"
|
||||
msgstr "Evernote Export Datei"
|
||||
msgstr "Evernote Export Datei (als Markdown)"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as HTML)"
|
||||
msgstr "Evernote Export Datei"
|
||||
msgstr "Evernote Export Datei (als HTML)"
|
||||
|
||||
msgid "Json Export Directory"
|
||||
msgstr "Json Export Verzeichnis"
|
||||
@@ -1830,13 +1832,11 @@ msgstr "Berechtigung zur Verwendung der Kamera"
|
||||
msgid "Your permission to use your camera is required."
|
||||
msgstr "Deine Zustimmung zur Verwendung deiner Kamera ist erforderlich."
|
||||
|
||||
#, fuzzy
|
||||
msgid "You currently have no notebooks."
|
||||
msgstr "Die/das momentan ausgewählte Notiz(-buch) löschen."
|
||||
msgstr "Du hast momentan keine Notizbücher."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Create a notebook"
|
||||
msgstr "Erstellt ein neues Notizbuch."
|
||||
msgstr "Notizbuch erstellen"
|
||||
|
||||
msgid "There are currently no notes. Create one by clicking on the (+) button."
|
||||
msgstr ""
|
||||
@@ -1896,7 +1896,7 @@ msgid ""
|
||||
"the sync target is accessible. The reported error was:"
|
||||
msgstr ""
|
||||
"Fehler. Bitte überprüfe, ob die URL, der Benutzername, das Passwort. usw. "
|
||||
"korrekt sind und das das Synchronisierungsziel erreichbar ist. Fehlermeldung:"
|
||||
"korrekt sind und das das Synchronisationsziel erreichbar ist. Fehlermeldung:"
|
||||
|
||||
msgid "The application has been authorised!"
|
||||
msgstr "Das Programm wurde erfolgreich autorisiert!"
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -211,7 +211,6 @@ msgstr ""
|
||||
msgid "Shortcuts are not available in CLI mode."
|
||||
msgstr "Le scorciatoie non sono disponibili nella modalità CLI."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Type `help [command]` for more information about a command; or type `help "
|
||||
"all` for the complete usage information."
|
||||
@@ -459,7 +458,7 @@ msgid ""
|
||||
"operation."
|
||||
msgstr ""
|
||||
"Trovato un file di blocco. Se si è certi che non è in corso alcuna "
|
||||
"sincronizzazione, è possibile eliminare il file di blocco in \"% s\" e "
|
||||
"sincronizzazione, è possibile eliminare il file di blocco in \"%s\" e "
|
||||
"riprendere l'operazione."
|
||||
|
||||
#, javascript-format
|
||||
@@ -731,7 +730,7 @@ msgstr "È disponibile un aggiornamento, vuoi scaricarlo ora?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Your version: %s"
|
||||
msgstr "Tua versione: %s"
|
||||
msgstr "La tua versione: %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "New version: %s"
|
||||
@@ -812,7 +811,7 @@ msgstr ""
|
||||
"terze parti di accedere a Joplin."
|
||||
|
||||
msgid "This will open a new screen. Save your current changes?"
|
||||
msgstr ""
|
||||
msgstr "Questo aprirà una nuova schermata. Salvare le tue modifiche correnti?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
@@ -1524,22 +1523,22 @@ msgid "Enable deflist syntax"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable abbreviation syntax"
|
||||
msgstr ""
|
||||
msgstr "Abilita abbreviazioni"
|
||||
|
||||
msgid "Enable markdown emoji"
|
||||
msgstr ""
|
||||
msgstr "Abilita emoji markdown"
|
||||
|
||||
msgid "Enable ++insert++ syntax"
|
||||
msgstr "Attiva sintassi ++insert++"
|
||||
|
||||
msgid "Enable multimarkdown table extension"
|
||||
msgstr ""
|
||||
msgstr "Abilita estensione tavola dei contenuti"
|
||||
|
||||
msgid "Enable Fountain syntax support"
|
||||
msgstr "Attiva supporto sintassi Fountain"
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr "Visualizza tray icon"
|
||||
msgstr "Visualizza nella barra delle applicazioni"
|
||||
|
||||
msgid "Note: Does not work in all desktop environments."
|
||||
msgstr "Nota: non funziona in tutti gli ambienti desktop."
|
||||
@@ -1549,12 +1548,12 @@ msgid ""
|
||||
"this setting so that your notes are constantly being synchronised, thus "
|
||||
"reducing the number of conflicts."
|
||||
msgstr ""
|
||||
"Questo consentirà Joplin di essere in esecuzione in background. E’ "
|
||||
"Questo consentirà a Joplin di essere in esecuzione in background. E’ "
|
||||
"raccomandata l’attivazione di questa impostazione per sincronizzare "
|
||||
"costantemente le tue note e quindi ridurre il numero di conflitti."
|
||||
|
||||
msgid "Start application minimised in the tray icon"
|
||||
msgstr "Avvia applicazione minimizzata nell’icona del vassoio"
|
||||
msgstr "Avvia applicazione minimizzata nella barra delle applicazioni"
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr "Percentuale di zoom globale"
|
||||
@@ -1562,9 +1561,8 @@ msgstr "Percentuale di zoom globale"
|
||||
msgid "Editor font size"
|
||||
msgstr "Editor dimensione caratteri"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Editor font"
|
||||
msgstr "Editor dimensione caratteri"
|
||||
msgstr "Editor caratteri"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr "Editor famiglia caratteri"
|
||||
@@ -1654,7 +1652,7 @@ msgid "%d days"
|
||||
msgstr "%d giorni"
|
||||
|
||||
msgid "Keep note history for"
|
||||
msgstr "Mantieni cronologia nota per"
|
||||
msgstr "Mantieni la cronologia note per"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
@@ -1678,13 +1676,11 @@ msgstr "Plugins"
|
||||
msgid "Application"
|
||||
msgstr "Applicazione"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encryption"
|
||||
msgstr "La crittografia è:"
|
||||
msgstr "Crittografia"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Web Clipper"
|
||||
msgstr "Opzioni Web Clipper"
|
||||
msgstr "Web Clipper"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
@@ -1699,13 +1695,11 @@ msgstr "Markdown"
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr "Cartella di esportazione di Joplin"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as Markdown)"
|
||||
msgstr "Esporta files di Evernote"
|
||||
msgstr "Esporta files di Evernote (come Markdown)"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as HTML)"
|
||||
msgstr "Esporta files di Evernote"
|
||||
msgstr "Esporta files di Evernote (come HTML)"
|
||||
|
||||
msgid "Json Export Directory"
|
||||
msgstr "Cartella di esportazione JSON"
|
||||
@@ -1807,7 +1801,7 @@ msgid "On %s: %s"
|
||||
msgstr "Su %s: %s"
|
||||
|
||||
msgid "Permission to use camera"
|
||||
msgstr "Permesso di usare la fotocamera"
|
||||
msgstr "Permesso per usare la fotocamera"
|
||||
|
||||
msgid "Your permission to use your camera is required."
|
||||
msgstr "E’ richiesto il permesso di usare la fotocamera."
|
||||
@@ -1911,6 +1905,8 @@ msgid ""
|
||||
"In order to use file system synchronisation your permission to write to "
|
||||
"external storage is required."
|
||||
msgstr ""
|
||||
"Per usare la sincronizzazione del file system è necessario il tuo permesso "
|
||||
"di scrittura sulla memoria esterna."
|
||||
|
||||
msgid "Encryption Config"
|
||||
msgstr "Configurazione Crittografia"
|
||||
@@ -2054,7 +2050,7 @@ msgid "View on map"
|
||||
msgstr "Guarda sulla mappa"
|
||||
|
||||
msgid "Go to source URL"
|
||||
msgstr ""
|
||||
msgstr "Vai all'URL"
|
||||
|
||||
msgid "Attach..."
|
||||
msgstr "Allega..."
|
||||
|
@@ -7,14 +7,16 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Joplin-CLI 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: AWASHIRO Ikuya <ikunya@gmail.com>\n"
|
||||
"Last-Translator: genneko <genneko217@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: ja_JP\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.3\n"
|
||||
"X-Generator: Poedit 1.8.4\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr "タグを削除するには、関連するノートからタグを外してください。"
|
||||
@@ -789,7 +791,7 @@ msgstr ""
|
||||
"するときにだけ使用します。"
|
||||
|
||||
msgid "This will open a new screen. Save your current changes?"
|
||||
msgstr ""
|
||||
msgstr "新しい画面を開きます。変更を保存しますか?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
@@ -896,13 +898,13 @@ msgid "Encryption is:"
|
||||
msgstr "暗号化の状態:"
|
||||
|
||||
msgid "Firefox Extension"
|
||||
msgstr ""
|
||||
msgstr "Firefox 拡張機能"
|
||||
|
||||
msgid "Chrome Web Store"
|
||||
msgstr ""
|
||||
msgstr "Chrome ウェブストア"
|
||||
|
||||
msgid "Get it now:"
|
||||
msgstr ""
|
||||
msgstr "今すぐ取得:"
|
||||
|
||||
msgid "Usage"
|
||||
msgstr "使い方"
|
||||
@@ -1534,9 +1536,8 @@ msgstr "全体ズームの割合"
|
||||
msgid "Editor font size"
|
||||
msgstr "エディターのフォントサイズ"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Editor font"
|
||||
msgstr "エディターのフォントサイズ"
|
||||
msgstr "エディターのフォント"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr "エディターのフォントファミリー"
|
||||
@@ -1604,6 +1605,8 @@ msgid ""
|
||||
"Fail-safe: Do not wipe out local data when sync target is empty (often the "
|
||||
"result of a misconfiguration or bug)"
|
||||
msgstr ""
|
||||
"フェイルセーフ: 同期先が空の場合 (設定ミスやバグに起因することが多い) にロー"
|
||||
"カルデータを消去しないようにする"
|
||||
|
||||
msgid ""
|
||||
"Specify the port that should be used by the API server. If not set, a "
|
||||
@@ -1647,13 +1650,11 @@ msgstr "プラグイン"
|
||||
msgid "Application"
|
||||
msgstr "アプリケーション"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encryption"
|
||||
msgstr "暗号化の状態:"
|
||||
msgstr "暗号化"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Web Clipper"
|
||||
msgstr "Webクリッパーのオプション"
|
||||
msgstr "Webクリッパー"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
@@ -1668,13 +1669,11 @@ msgstr "Markdown"
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr "Joplin エクスポートディレクトリ"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as Markdown)"
|
||||
msgstr "Evernote エクスポートファイル"
|
||||
msgstr "Evernote エクスポートファイル (Markdownとしてインポート)"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as HTML)"
|
||||
msgstr "Evernote エクスポートファイル"
|
||||
msgstr "Evernote エクスポートファイル (HTMLとしてインポート)"
|
||||
|
||||
msgid "Json Export Directory"
|
||||
msgstr "Json エクスポートディレクトリ"
|
||||
|
@@ -380,18 +380,19 @@ msgstr "Søker etter angitt <pattern> i alle notatene."
|
||||
msgid ""
|
||||
"Start, stop or check the API server. To specify on which port it should run, "
|
||||
"set the api.port config variable. Commands are (%s)."
|
||||
msgstr ""
|
||||
msgstr "Start, stopp eller sjekk API-serveren. For å angi på hvilken port den skal kjøre,"
|
||||
"sett api.port konfigurasjonsvariablen. Kommandoer er (%s)."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is already running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Serveren kjører allerede på port %d"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Serveren kjører på port %d"
|
||||
|
||||
msgid "Server is not running."
|
||||
msgstr ""
|
||||
msgstr "Serveren kjører ikke"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
@@ -587,13 +588,13 @@ msgid "About Joplin"
|
||||
msgstr "Om Joplin"
|
||||
|
||||
msgid "Preferences..."
|
||||
msgstr ""
|
||||
msgstr "Innstillinger..."
|
||||
|
||||
msgid "Check for updates..."
|
||||
msgstr "Se etter oppdatering..."
|
||||
|
||||
msgid "Templates"
|
||||
msgstr ""
|
||||
msgstr "Maler"
|
||||
|
||||
msgid "Import"
|
||||
msgstr "Importer"
|
||||
@@ -612,7 +613,7 @@ msgid "Quit"
|
||||
msgstr "Avslutt"
|
||||
|
||||
msgid "Close Window"
|
||||
msgstr ""
|
||||
msgstr "Lukk vindu"
|
||||
|
||||
msgid "&Edit"
|
||||
msgstr "&Rediger"
|
||||
@@ -677,15 +678,14 @@ msgstr "&Hjelp"
|
||||
msgid "Website and documentation"
|
||||
msgstr "Nettsted og dokumentasjon"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Joplin Forum"
|
||||
msgstr "Joplin v%s"
|
||||
msgstr "Joplin Forum"
|
||||
|
||||
msgid "Make a donation"
|
||||
msgstr "Gi et bidrag"
|
||||
|
||||
msgid "Toggle development tools"
|
||||
msgstr ""
|
||||
msgstr "Skru på/av utviklingsverktøy"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Open %s"
|
||||
@@ -792,7 +792,7 @@ msgstr ""
|
||||
"tredjepartsapplikasjoner tilgang til Joplin."
|
||||
|
||||
msgid "This will open a new screen. Save your current changes?"
|
||||
msgstr ""
|
||||
msgstr "Dette vil åpne et nytt vindu. Vil du lagre nåværende endringer?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
@@ -902,13 +902,13 @@ msgid "Encryption is:"
|
||||
msgstr "Kryptering er:"
|
||||
|
||||
msgid "Firefox Extension"
|
||||
msgstr ""
|
||||
msgstr "Firefox-utvidelse"
|
||||
|
||||
msgid "Chrome Web Store"
|
||||
msgstr ""
|
||||
msgstr "Chrome Web Store"
|
||||
|
||||
msgid "Get it now:"
|
||||
msgstr ""
|
||||
msgstr "Få den nå:"
|
||||
|
||||
msgid "Usage"
|
||||
msgstr "Bruk"
|
||||
@@ -942,7 +942,7 @@ msgid "Set alarm:"
|
||||
msgstr "Angi alarm:"
|
||||
|
||||
msgid "Template file:"
|
||||
msgstr ""
|
||||
msgstr "Malfiler"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Nytt notat"
|
||||
@@ -965,9 +965,8 @@ msgstr "Noen elementer kan ikke synkroniseres."
|
||||
msgid "View them now"
|
||||
msgstr "Vis nå"
|
||||
|
||||
#, fuzzy
|
||||
msgid "One or more master keys need a password."
|
||||
msgstr "Skriv inn masterpassordet:"
|
||||
msgstr "En eller flere masternøkler trenger et passord."
|
||||
|
||||
msgid "Set the password"
|
||||
msgstr "Sett passord"
|
||||
@@ -986,35 +985,34 @@ msgstr "Lokasjon"
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note History"
|
||||
msgstr "Notatliste"
|
||||
msgstr "Notathistorikk"
|
||||
|
||||
msgid "Markup"
|
||||
msgstr ""
|
||||
msgstr "Markup"
|
||||
|
||||
msgid "Previous versions of this note"
|
||||
msgstr ""
|
||||
msgstr "Forrige versjon av dette notatet"
|
||||
|
||||
msgid "Note properties"
|
||||
msgstr "Notategenskaper"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The note \"%s\" has been successfully restored to the notebook \"%s\"."
|
||||
msgstr ""
|
||||
msgstr "Notatet \"%s\" has blitt vellykket gjenopprettet i notatboken \"%s\"."
|
||||
|
||||
#, fuzzy
|
||||
msgid "This note has no history"
|
||||
msgstr "Dette notatet har blitt endret:"
|
||||
msgstr "Dette notatet har ingen historikk"
|
||||
|
||||
msgid "Restore"
|
||||
msgstr ""
|
||||
msgstr "Gjenopprett"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Click \"%s\" to restore the note. It will be copied in the notebook named "
|
||||
"\"%s\". The current version of the note will not be replaced or modified."
|
||||
msgstr ""
|
||||
msgstr "Velg \"%s\" for å gjenopprette notatet. Det vil bli kopiert til notatboken"
|
||||
"\"%s\". Den nåværende versjonen av notatet vil ikke bli erstattet eller modifisert."
|
||||
|
||||
msgid "Open..."
|
||||
msgstr "Åpne..."
|
||||
@@ -1169,7 +1167,7 @@ msgid "Please select where the sync status should be exported to"
|
||||
msgstr "Velg hvor synkroniseringsstatusen skal eksporteres til"
|
||||
|
||||
msgid "Retry"
|
||||
msgstr ""
|
||||
msgstr "Prøv igjen"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Legg til eller fjern merkelapper"
|
||||
@@ -1204,10 +1202,11 @@ msgstr "Slett disse %d notatene?"
|
||||
msgid ""
|
||||
"Type a note title to jump to it. Or type # followed by a tag name, or @ "
|
||||
"followed by a notebook name."
|
||||
msgstr ""
|
||||
msgstr "Skriv inn tittelen på et notat for å hoppe til det. Eller skriv # etterfulgt av en merkelapp,"
|
||||
" eller @ etterfulgt av tittelen på en notatbok."
|
||||
|
||||
msgid "Goto Anything..."
|
||||
msgstr ""
|
||||
msgstr "Hopp til..."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Usage: %s"
|
||||
@@ -1399,25 +1398,28 @@ msgid "WebDAV password"
|
||||
msgstr "WebDAV-passord"
|
||||
|
||||
msgid "Attachment download behaviour"
|
||||
msgstr ""
|
||||
msgstr "Nedlastningsoppførsel for vedlegg"
|
||||
|
||||
msgid ""
|
||||
"In \"Manual\" mode, attachments are downloaded only when you click on them. "
|
||||
"In \"Auto\", they are downloaded when you open the note. In \"Always\", all "
|
||||
"the attachments are downloaded whether you open the note or not."
|
||||
msgstr ""
|
||||
"I \"Manuell\" modus blir vedlegg kun lastet ned når du klikker på de. "
|
||||
"I \"Auto\" blir de lastet ned når du åpner notatet. I \"Alltid\" blir "
|
||||
"vedleggene lastet ned uansett om du åpner notatet eller ikke."
|
||||
|
||||
msgid "Always"
|
||||
msgstr ""
|
||||
msgstr "Alltid"
|
||||
|
||||
msgid "Manual"
|
||||
msgstr ""
|
||||
msgstr "Manuell"
|
||||
|
||||
msgid "Auto"
|
||||
msgstr ""
|
||||
msgstr "Auto"
|
||||
|
||||
msgid "Max concurrent connections"
|
||||
msgstr ""
|
||||
msgstr "Maksimalt samtidige tilkoblinger"
|
||||
|
||||
msgid "Language"
|
||||
msgstr "Språk"
|
||||
@@ -1438,10 +1440,10 @@ msgid "Dark"
|
||||
msgstr "Mørk"
|
||||
|
||||
msgid "Solarised Light"
|
||||
msgstr ""
|
||||
msgstr "Solarisert lys"
|
||||
|
||||
msgid "Solarised Dark"
|
||||
msgstr ""
|
||||
msgstr "Solarisert mørk"
|
||||
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Uferdige gjøremål på topp"
|
||||
@@ -1471,50 +1473,46 @@ msgid "Focus body"
|
||||
msgstr "Fokuser på brødtekst"
|
||||
|
||||
msgid "When creating a new note:"
|
||||
msgstr "Når du lager et nytt notat:"
|
||||
msgstr "Når du oppretter et nytt notat:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable soft breaks"
|
||||
msgstr "Liste over innhold"
|
||||
msgstr "Aktiver myke linjeskift"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable math expressions"
|
||||
msgstr "Aktiver kryptering"
|
||||
msgstr "Aktiver matteuttrykk"
|
||||
|
||||
msgid "Enable ==mark== syntax"
|
||||
msgstr ""
|
||||
msgstr "Aktiver ==mark==-syntaks"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable footnotes"
|
||||
msgstr "Liste over innhold"
|
||||
msgstr "Aktiver fotnoter"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable table of contents extension"
|
||||
msgstr "Liste over innhold"
|
||||
msgstr "Aktiver liste over innhold-utvidelse"
|
||||
|
||||
msgid "Enable ~sub~ syntax"
|
||||
msgstr ""
|
||||
msgstr "Aktiver ~sub~-syntaks"
|
||||
|
||||
msgid "Enable ^sup^ syntax"
|
||||
msgstr ""
|
||||
msgstr "Aktiver ^sup^-syntaks"
|
||||
|
||||
msgid "Enable deflist syntax"
|
||||
msgstr ""
|
||||
msgstr "Aktiver deflist-syntaks"
|
||||
|
||||
msgid "Enable abbreviation syntax"
|
||||
msgstr ""
|
||||
msgstr "Aktiver forkortelsesyntaks"
|
||||
|
||||
msgid "Enable markdown emoji"
|
||||
msgstr ""
|
||||
msgstr "Aktiver markdown-emoji"
|
||||
|
||||
msgid "Enable ++insert++ syntax"
|
||||
msgstr ""
|
||||
msgstr "Aktiver ++insert++-syntaks"
|
||||
|
||||
msgid "Enable multimarkdown table extension"
|
||||
msgstr ""
|
||||
msgstr "Aktiver multimarkdown-tabellutvidelse"
|
||||
|
||||
msgid "Enable Fountain syntax support"
|
||||
msgstr ""
|
||||
msgstr "Aktiver Fountain syntaksstøtte"
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr "Vis systemmenyikon"
|
||||
@@ -1540,12 +1538,11 @@ msgstr "Global forstørrelse"
|
||||
msgid "Editor font size"
|
||||
msgstr "Editorskriftstørrelse"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Editor font"
|
||||
msgstr "Editorskriftstørrelse"
|
||||
msgstr "Editorskrift"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr "Editorskrifttype"
|
||||
msgstr "Editorskriftfamilie"
|
||||
|
||||
msgid ""
|
||||
"This must be *monospace* font or it will not work properly. If the font is "
|
||||
@@ -1611,25 +1608,27 @@ msgid ""
|
||||
"Fail-safe: Do not wipe out local data when sync target is empty (often the "
|
||||
"result of a misconfiguration or bug)"
|
||||
msgstr ""
|
||||
"Feilhåndtering: Ikke slett lokal data når synkroniseringsmålet er tomt (ofte "
|
||||
"resultatet av en miskonfigurering eller bug)"
|
||||
|
||||
msgid ""
|
||||
"Specify the port that should be used by the API server. If not set, a "
|
||||
"default will be used."
|
||||
msgstr ""
|
||||
"Spesifiser porten som skal brukes av API-serveren. Hvis ikke satt vil "
|
||||
"en standardport brukes."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable note history"
|
||||
msgstr "Liste over innhold"
|
||||
msgstr "Aktiver notathistorikk"
|
||||
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
msgstr "dager"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%d days"
|
||||
msgstr ""
|
||||
msgstr "%d dager"
|
||||
|
||||
msgid "Keep note history for"
|
||||
msgstr ""
|
||||
msgstr "Behold notathistorikk i"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
@@ -1648,18 +1647,16 @@ msgid "Note"
|
||||
msgstr "Notat"
|
||||
|
||||
msgid "Plugins"
|
||||
msgstr ""
|
||||
msgstr "Utvidelser"
|
||||
|
||||
msgid "Application"
|
||||
msgstr "Applikasjon"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encryption"
|
||||
msgstr "Kryptering er:"
|
||||
msgstr "Kryptering"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Web Clipper"
|
||||
msgstr "Web Clipper-innstillinger"
|
||||
msgstr "Web Clipper"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
@@ -1674,13 +1671,11 @@ msgstr "Markdown"
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr "Joplin-eksportert katalog"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as Markdown)"
|
||||
msgstr "Evernote-eksportert fil"
|
||||
msgstr "Evernote-eksportert fil (Markdown)"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as HTML)"
|
||||
msgstr "Evernote-eksportert fil"
|
||||
msgstr "Evernote-eksportert fil (HTML)"
|
||||
|
||||
msgid "Json Export Directory"
|
||||
msgstr "Json-eksportert katalog"
|
||||
@@ -1714,7 +1709,7 @@ msgid "Please specify the notebook where the notes should be imported to."
|
||||
msgstr "Velg notatbok som notatene skal importeres til."
|
||||
|
||||
msgid "Restored Notes"
|
||||
msgstr ""
|
||||
msgstr "Gjenopprettede notater"
|
||||
|
||||
msgid "Items that cannot be synchronised"
|
||||
msgstr "Elementer som ikke vil synkronisere"
|
||||
@@ -1728,23 +1723,25 @@ msgstr ""
|
||||
"synkroniseringsmålet. For å finne disse elementene, enten søk etter tittel "
|
||||
"eller ID (som vises i parentes over)."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "%s (%s) could not be uploaded: %s"
|
||||
msgstr "Filen kunne ikke åpnes: %s"
|
||||
msgstr "%s (%s) ble ikke opplasted: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Item \"%s\" could not be downloaded: %s"
|
||||
msgstr "Filen kunne ikke åpnes: %s"
|
||||
msgstr "Element \"%s\" ble ikke nedlastet: %s"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Items that cannot be decrypted"
|
||||
msgstr "Elementer som ikke vil synkronisere"
|
||||
msgstr "Elementer som ikke kan dekrypteres"
|
||||
|
||||
msgid ""
|
||||
"Joplin failed to decrypt these items multiple times, possibly because they "
|
||||
"are corrupted or too large. These items will remain on the device but Joplin "
|
||||
"will no longer attempt to decrypt them."
|
||||
msgstr ""
|
||||
"Joplin feilet i å dekryptere disse elementene flere ganger, muligens fordi "
|
||||
"de er korrupte eller for store. Disse elementene vil forbli på enheten men "
|
||||
"Joplin vil ikke lenger forsøke å dekryptere de."
|
||||
|
||||
msgid "Sync status (synced items / total items)"
|
||||
msgstr "Synkroniseringsstatus (synkroniserte elementer / totale elementer)"
|
||||
@@ -1785,13 +1782,11 @@ msgstr "Tillatelse til å bruke kamera"
|
||||
msgid "Your permission to use your camera is required."
|
||||
msgstr "Tillatelse til å bruke kamera er nødvendig."
|
||||
|
||||
#, fuzzy
|
||||
msgid "You currently have no notebooks."
|
||||
msgstr "Ingen aktiv notatbok."
|
||||
msgstr "Du har ingen notatbøker."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Create a notebook"
|
||||
msgstr "Oppretter en ny notatbok."
|
||||
msgstr "Opprett en notatbok"
|
||||
|
||||
msgid "There are currently no notes. Create one by clicking on the (+) button."
|
||||
msgstr "Det finnes enda ingen notater. Lag en ved å klikke på (+)-knappen."
|
||||
@@ -1821,24 +1816,21 @@ msgstr "Velg dato"
|
||||
msgid "Confirm"
|
||||
msgstr "Bekreft"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Notebook: %s"
|
||||
msgstr "Notatbøker"
|
||||
msgstr "Notatbok: %s"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encrypted notebooks cannot be renamed"
|
||||
msgstr "Krypterte elementer kan ikke modifiseres"
|
||||
msgstr "Krypterte elementer kan ikke få endret navn"
|
||||
|
||||
#, fuzzy
|
||||
msgid "New Notebook"
|
||||
msgstr "Ny notatbok"
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr "Konfigurasjon"
|
||||
|
||||
#, fuzzy
|
||||
msgid "All notes"
|
||||
msgstr "notat"
|
||||
msgstr "Alle notater"
|
||||
|
||||
msgid "Checking... Please wait."
|
||||
msgstr "Sjekker… Vennligst vent."
|
||||
@@ -1881,48 +1873,48 @@ msgid "Type new tags or select from list"
|
||||
msgstr "Skriv inn nye merkelapper eller velg fra listen"
|
||||
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
msgstr "Advarsel"
|
||||
|
||||
msgid ""
|
||||
"In order to use file system synchronisation your permission to write to "
|
||||
"external storage is required."
|
||||
msgstr ""
|
||||
"For å kunne bruke filsystemsynkronisering behøves din tillatelse til å "
|
||||
"kunne skrive til ekstern lagrging."
|
||||
|
||||
msgid "Encryption Config"
|
||||
msgstr "Krypteringsinnstillinger"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Tools"
|
||||
msgstr "&Verktøy"
|
||||
msgstr "Verktøy"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Sync Status"
|
||||
msgstr "Status"
|
||||
msgstr "Synkroniseringsstatus"
|
||||
|
||||
msgid "Log"
|
||||
msgstr "Logg"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Creating report..."
|
||||
msgstr "Oppretter nytt %s..."
|
||||
msgstr "Oppretter rapport..."
|
||||
|
||||
msgid "Export Debug Report"
|
||||
msgstr "Eksporter feilsøkingsrapport"
|
||||
|
||||
msgid "Fixing search index..."
|
||||
msgstr ""
|
||||
msgstr "Fikser søkeindeks..."
|
||||
|
||||
msgid "Fix search index"
|
||||
msgstr ""
|
||||
msgstr "Fiks søkeindeks"
|
||||
|
||||
msgid ""
|
||||
"Use this to rebuild the search index if there is a problem with search. It "
|
||||
"may take a long time depending on the number of notes."
|
||||
msgstr ""
|
||||
"Velg dette for å gjenoppbygge søkeindeksen dersom du har problemer med søk. "
|
||||
"Det kan ta lang tid avhengig av antall notater."
|
||||
|
||||
#, fuzzy
|
||||
msgid "More information"
|
||||
msgstr "Konfigurasjon"
|
||||
msgstr "Mer informasjon"
|
||||
|
||||
msgid ""
|
||||
"To work correctly, the app needs the following permissions. Please enable "
|
||||
@@ -1985,9 +1977,8 @@ msgstr "Denne notatboken kunne ikke lagres: %s"
|
||||
msgid "Edit notebook"
|
||||
msgstr "Rediger notatbok"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enter notebook title"
|
||||
msgstr "Tittel på notatbok:"
|
||||
msgstr "Angi tittel på notatbok"
|
||||
|
||||
msgid "Show all"
|
||||
msgstr "Vis alle"
|
||||
@@ -2014,15 +2005,15 @@ msgstr "Joplins mobilapp støtter for tiden ikke denne type linker: %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Links with protocol \"%s\" are not supported"
|
||||
msgstr ""
|
||||
msgstr "Linker med protokoll \"%s\" er ikke støttet"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported image type: %s"
|
||||
msgstr "Bildetypen er ikke støttet: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Updated: %s"
|
||||
msgstr "Oppdatert: %d."
|
||||
msgstr "Oppdatert: %s"
|
||||
|
||||
msgid "View on map"
|
||||
msgstr "Vis på kart"
|
||||
@@ -2030,13 +2021,11 @@ msgstr "Vis på kart"
|
||||
msgid "Go to source URL"
|
||||
msgstr "Gå til kilde-URL"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Attach..."
|
||||
msgstr "Søk..."
|
||||
msgstr "Legg ved..."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Choose an option"
|
||||
msgstr "Vis avanserte innstillinger"
|
||||
msgstr "Velg et alternativ"
|
||||
|
||||
msgid "Take photo"
|
||||
msgstr "Ta bilde"
|
||||
@@ -2056,19 +2045,17 @@ msgstr "Konverter til notat"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Konverter til gjøremål"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Properties"
|
||||
msgstr "Notategenskaper"
|
||||
msgstr "Egenskaper"
|
||||
|
||||
msgid "Add body"
|
||||
msgstr ""
|
||||
msgstr "Legg til brødtekst"
|
||||
|
||||
msgid "Edit"
|
||||
msgstr "Rediger"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Add title"
|
||||
msgstr "tittel"
|
||||
msgstr "Legg til tittel"
|
||||
|
||||
msgid "Login with OneDrive"
|
||||
msgstr "Innlogging med OneDrive"
|
||||
@@ -2111,17 +2098,14 @@ msgstr "Søk"
|
||||
#~ msgid "Encryption options"
|
||||
#~ msgstr "Krypteringsvalg"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Insert template"
|
||||
#~ msgstr "Sett inn dato/tid"
|
||||
#~ msgstr "Legg inn mal"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Open template directory"
|
||||
#~ msgstr "Joplin-eksportert katalog"
|
||||
#~ msgstr "Åpne malkatalog"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Revision: %s (%s)"
|
||||
#~ msgstr "%s %s (%s)"
|
||||
#~ msgstr "Revisjon: %s (%s)"
|
||||
|
||||
#~ msgid "%s %s (%s, %s)"
|
||||
#~ msgstr "%s %s (%s, %s)"
|
||||
@@ -2132,13 +2116,11 @@ msgstr "Søk"
|
||||
#~ msgid "Clipper Options"
|
||||
#~ msgstr "Clipper-innstillinger"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Information"
|
||||
#~ msgstr "Konfigurasjon"
|
||||
#~ msgstr "Informasjon"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Permission to write to external storage"
|
||||
#~ msgstr "Tillatelse til å bruke kamera"
|
||||
#~ msgstr "Tillatelse til å skrive til ekstern lagring"
|
||||
|
||||
#~ msgid "Cancel synchronisation"
|
||||
#~ msgstr "Avbryt synkronisering"
|
||||
|
@@ -7,14 +7,16 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Joplin-CLI 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: Heimen Stoffels <vistausss@outlook.com>\n"
|
||||
"Language-Team: Dutch <vistausss@outlook.com>\n"
|
||||
"Last-Translator: Robert <metbril@outlook.com>\n"
|
||||
"Language-Team: Dutch / Nederlands\n"
|
||||
"Language: nl_NL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.3\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr ""
|
||||
@@ -389,17 +391,20 @@ msgid ""
|
||||
"Start, stop or check the API server. To specify on which port it should run, "
|
||||
"set the api.port config variable. Commands are (%s)."
|
||||
msgstr ""
|
||||
"Start, stop of controleer de API-server. Stel de api.port "
|
||||
"configuratievariabele in om te specificeren op welke poort deze draait. "
|
||||
"Commando's zijn (%s)."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is already running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Server draait reeds op poort %d"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Server draait op poort %d"
|
||||
|
||||
msgid "Server is not running."
|
||||
msgstr ""
|
||||
msgstr "Server draait niet."
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
@@ -687,9 +692,8 @@ msgstr "&Help"
|
||||
msgid "Website and documentation"
|
||||
msgstr "Website en documentatie"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Joplin Forum"
|
||||
msgstr "Joplin-website"
|
||||
msgstr "Joplin-forum"
|
||||
|
||||
msgid "Make a donation"
|
||||
msgstr "Doneren"
|
||||
@@ -803,7 +807,7 @@ msgstr ""
|
||||
"geven tot Joplin."
|
||||
|
||||
msgid "This will open a new screen. Save your current changes?"
|
||||
msgstr ""
|
||||
msgstr "Dit opent een nieuw scherm. Wijzigingen opslaan?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
@@ -913,13 +917,13 @@ msgid "Encryption is:"
|
||||
msgstr "Gebruikte versleuteling:"
|
||||
|
||||
msgid "Firefox Extension"
|
||||
msgstr ""
|
||||
msgstr "Firefox-extensie"
|
||||
|
||||
msgid "Chrome Web Store"
|
||||
msgstr ""
|
||||
msgstr "Chrome Web Store"
|
||||
|
||||
msgid "Get it now:"
|
||||
msgstr ""
|
||||
msgstr "Haal nu op:"
|
||||
|
||||
msgid "Usage"
|
||||
msgstr "Gebruik"
|
||||
@@ -1533,9 +1537,8 @@ msgstr "Inschakelen ++insert++ syntaxis"
|
||||
msgid "Enable multimarkdown table extension"
|
||||
msgstr "Inschakelen multimarkdown tabel extensie"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable Fountain syntax support"
|
||||
msgstr "Inschakelen ~sub~ syntaxis"
|
||||
msgstr "Inschakelen ondersteuning voor Fountain syntaxis"
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr "Systeemvakpictogram tonen"
|
||||
@@ -1561,9 +1564,8 @@ msgstr "Globaal zoompercentage"
|
||||
msgid "Editor font size"
|
||||
msgstr "Lettergrootte van bewerker"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Editor font"
|
||||
msgstr "Lettergrootte van bewerker"
|
||||
msgstr "Lettertype van bewerker"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr "Lettertype van bewerker"
|
||||
@@ -1634,11 +1636,15 @@ msgid ""
|
||||
"Fail-safe: Do not wipe out local data when sync target is empty (often the "
|
||||
"result of a misconfiguration or bug)"
|
||||
msgstr ""
|
||||
"Veiligheidswaarschuwing: Wis lokale gegevens niet wanneer synchronisatiedoel "
|
||||
"leeg is (vaak het gevolg van een misconfiguratie of softwarefout)"
|
||||
|
||||
msgid ""
|
||||
"Specify the port that should be used by the API server. If not set, a "
|
||||
"default will be used."
|
||||
msgstr ""
|
||||
"Specificeer de door de API-server te gebruiken poort. Indien niet ingesteld, "
|
||||
"wordt een standaardwaarde gebruikt."
|
||||
|
||||
msgid "Enable note history"
|
||||
msgstr "Inschakelen geschiedenis van notities"
|
||||
@@ -1675,13 +1681,11 @@ msgstr "Plugins"
|
||||
msgid "Application"
|
||||
msgstr "Applicatie"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encryption"
|
||||
msgstr "Gebruikte versleuteling:"
|
||||
msgstr "Versleuteling"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Web Clipper"
|
||||
msgstr "Webclipper-opties"
|
||||
msgstr "Webclipper"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
@@ -1696,13 +1700,11 @@ msgstr "Markdown"
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr "Joplin-exportmap"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as Markdown)"
|
||||
msgstr "Evernote-exportbestand"
|
||||
msgstr "Evernote-exportbestand (als Markdown)"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as HTML)"
|
||||
msgstr "Evernote-exportbestand"
|
||||
msgstr "Evernote-exportbestand (als HTML)"
|
||||
|
||||
msgid "Json Export Directory"
|
||||
msgstr "JSON-exportmap"
|
||||
@@ -1811,13 +1813,11 @@ msgstr "Toestemming om de camera te gebruiken"
|
||||
msgid "Your permission to use your camera is required."
|
||||
msgstr "Je toestemming om de camera te gebruiken is vereist."
|
||||
|
||||
#, fuzzy
|
||||
msgid "You currently have no notebooks."
|
||||
msgstr "Geen actief notitieboek."
|
||||
msgstr "Je hebt nog geen notitieboeken."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Create a notebook"
|
||||
msgstr "Creëert een nieuw notitieboek."
|
||||
msgstr "Creëer een notitieboek"
|
||||
|
||||
msgid "There are currently no notes. Create one by clicking on the (+) button."
|
||||
msgstr ""
|
||||
@@ -1849,24 +1849,21 @@ msgstr "Datum kiezen"
|
||||
msgid "Confirm"
|
||||
msgstr "Bevestigen"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Notebook: %s"
|
||||
msgstr "Notitieboeken"
|
||||
msgstr "Notitieboek: %s"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encrypted notebooks cannot be renamed"
|
||||
msgstr "Versleutelde items kunnen niet worden bewerkt"
|
||||
msgstr "Versleutelde notitieboeken kunnen niet worden hernoemd"
|
||||
|
||||
#, fuzzy
|
||||
msgid "New Notebook"
|
||||
msgstr "Nieuw notitieboek"
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr "Configuratie"
|
||||
|
||||
#, fuzzy
|
||||
msgid "All notes"
|
||||
msgstr "notitie"
|
||||
msgstr "Alle notities"
|
||||
|
||||
msgid "Checking... Please wait."
|
||||
msgstr "Controleren… Even geduld."
|
||||
@@ -1921,20 +1918,17 @@ msgstr ""
|
||||
msgid "Encryption Config"
|
||||
msgstr "Versleutelconfiguratie"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Tools"
|
||||
msgstr "E&xtra"
|
||||
msgstr "Hulpmiddelen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Sync Status"
|
||||
msgstr "Status"
|
||||
msgstr "Synchronisatiestatus"
|
||||
|
||||
msgid "Log"
|
||||
msgstr "Log"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Creating report..."
|
||||
msgstr "Bezig met creëren van nieuw(e) %s..."
|
||||
msgstr "Creëren rapport..."
|
||||
|
||||
msgid "Export Debug Report"
|
||||
msgstr "Foutopsporingsrapportage exporteren"
|
||||
@@ -2017,9 +2011,8 @@ msgstr "Het notitieboek kan niet worden opgeslagen: %s"
|
||||
msgid "Edit notebook"
|
||||
msgstr "Notitieboek bewerken"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enter notebook title"
|
||||
msgstr "Titel van notitieboek:"
|
||||
msgstr "Invoeren titel notitieboek"
|
||||
|
||||
msgid "Show all"
|
||||
msgstr "Alles tonen"
|
||||
@@ -2052,9 +2045,9 @@ msgstr "Links met protocol “%s” worden niet ondersteund"
|
||||
msgid "Unsupported image type: %s"
|
||||
msgstr "Niet-ondersteunde afbeeldingssoort: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Updated: %s"
|
||||
msgstr "Bijgewerkt: %d."
|
||||
msgstr "Bijgewerkt: %s"
|
||||
|
||||
msgid "View on map"
|
||||
msgstr "Tonen op kaart"
|
||||
@@ -2062,13 +2055,11 @@ msgstr "Tonen op kaart"
|
||||
msgid "Go to source URL"
|
||||
msgstr "Ga naar bron-URL"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Attach..."
|
||||
msgstr "Zoeken..."
|
||||
msgstr "Bijvoegen..."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Choose an option"
|
||||
msgstr "Geavanceerde opties tonen"
|
||||
msgstr "Kies een optie"
|
||||
|
||||
msgid "Take photo"
|
||||
msgstr "Foto maken"
|
||||
@@ -2088,9 +2079,8 @@ msgstr "Omzetten naar notitie"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Omzetten naar taak"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Properties"
|
||||
msgstr "Eigenschappen van notitie"
|
||||
msgstr "Eigenschappen"
|
||||
|
||||
msgid "Add body"
|
||||
msgstr "Inhoud toevoegen"
|
||||
@@ -2098,9 +2088,8 @@ msgstr "Inhoud toevoegen"
|
||||
msgid "Edit"
|
||||
msgstr "Bewerken"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Add title"
|
||||
msgstr "titel"
|
||||
msgstr "Toevoegen titel"
|
||||
|
||||
msgid "Login with OneDrive"
|
||||
msgstr "Inloggen met OneDrive"
|
||||
|
@@ -13,17 +13,18 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.6\n"
|
||||
"X-Generator: Poedit 2.2.3\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr "Для удаления метки, открепите ее от связанных с ней заметок."
|
||||
|
||||
msgid "Please select the note or notebook to be deleted first."
|
||||
msgstr ""
|
||||
"Пожалуйста, выберите заметку или блокнот, которые будут удалены в первую "
|
||||
"очередь."
|
||||
"Пожалуйста, выберите заметку или блокнот, которые будут удалены первыми."
|
||||
|
||||
msgid "Press Ctrl+D or type \"exit\" to exit the application"
|
||||
msgstr "Для выхода из приложения нажмите Ctrl+D или введите \"exit\""
|
||||
@@ -103,7 +104,7 @@ msgstr ""
|
||||
"конфигурацию."
|
||||
|
||||
msgid "Also displays unset and hidden config variables."
|
||||
msgstr "Также выводит неустановленные или скрытые переменные конфигурации."
|
||||
msgstr "Также показывает неустановленные или скрытые переменные конфигурации."
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s = %s (%s)"
|
||||
@@ -127,7 +128,6 @@ msgstr "Отмечает задачу как выполненную."
|
||||
msgid "Note is not a to-do: \"%s\""
|
||||
msgstr "Заметка не является задачей: «%s»"
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, "
|
||||
"`status`, `decrypt-file` and `target-status`."
|
||||
@@ -177,6 +177,18 @@ msgstr "Нет активного блокнота."
|
||||
msgid "Note does not exist: \"%s\". Create it?"
|
||||
msgstr "Заметка не существует: \"%s\". Создать?"
|
||||
|
||||
msgid "Starting to edit note. Close the editor to get back to the prompt."
|
||||
msgstr ""
|
||||
"Запуск редактирования заметки. Закройте редактор, чтобы вернуться к "
|
||||
"приглашению."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Error opening note in editor: %s"
|
||||
msgstr "Ошибка при открытии заметки в редакторе: %s"
|
||||
|
||||
msgid "Note has been saved."
|
||||
msgstr "Заметка сохранена."
|
||||
|
||||
msgid "Exits the application."
|
||||
msgstr "Выйти из приложения."
|
||||
|
||||
@@ -387,17 +399,19 @@ msgid ""
|
||||
"Start, stop or check the API server. To specify on which port it should run, "
|
||||
"set the api.port config variable. Commands are (%s)."
|
||||
msgstr ""
|
||||
"Запустить, остановить или проверить сервер API. Порт сервера настраивается с "
|
||||
"помощью переменной api.port. Доступные команды: (%s)."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is already running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Сервер уже запущен на порту %d"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Server is running on port %d"
|
||||
msgstr ""
|
||||
msgstr "Сервер запущен на порту %d"
|
||||
|
||||
msgid "Server is not running."
|
||||
msgstr ""
|
||||
msgstr "Сервер не запущен."
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
@@ -539,6 +553,10 @@ msgstr "Введите `joplin help` для получения информац
|
||||
msgid "Fatal error:"
|
||||
msgstr "Фатальная ошибка:"
|
||||
|
||||
#, javascript-format
|
||||
msgid "All potential ports are in use - please report the issue at %s"
|
||||
msgstr "Все возможные порты заняты - пожалуйста, сообщите о проблеме в %s"
|
||||
|
||||
msgid ""
|
||||
"The application has been authorised - you may now close this browser tab."
|
||||
msgstr "Приложение авторизовано — можно закрыть вкладку браузера."
|
||||
@@ -593,6 +611,72 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Экспорт в \"%s\" в формате \"%s\". Пожалуйста, подождите..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr "Боковая панель"
|
||||
|
||||
msgid "Note list"
|
||||
msgstr "Список заметок"
|
||||
|
||||
msgid "Note title"
|
||||
msgstr "Название заметки"
|
||||
|
||||
msgid "Note body"
|
||||
msgstr "Тело заметки"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Импорт из \"%s\" в формате \"%s\". Пожалуйста, подождите..."
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr "Файл PDF"
|
||||
|
||||
msgid "Synchronisation status"
|
||||
msgstr "Статус синхронизации"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Новая заметка"
|
||||
|
||||
msgid "New to-do"
|
||||
msgstr "Новая задача"
|
||||
|
||||
msgid "New notebook"
|
||||
msgstr "Новый блокнот"
|
||||
|
||||
msgid "Print"
|
||||
msgstr "Печать"
|
||||
|
||||
msgid "General Options"
|
||||
msgstr "Основные настройки"
|
||||
|
||||
msgid "Encryption options"
|
||||
msgstr "Настройки шифрования"
|
||||
|
||||
msgid "Web clipper options"
|
||||
msgstr "Настройки веб-клиппера"
|
||||
|
||||
msgid "Create note from template"
|
||||
msgstr "Создать заметку из шаблона"
|
||||
|
||||
msgid "Create to-do from template"
|
||||
msgstr "Создать задачу из шаблона"
|
||||
|
||||
msgid "Insert template"
|
||||
msgstr "Вставить шаблон"
|
||||
|
||||
msgid "Open template directory"
|
||||
msgstr "Открыть папку с шаблонами"
|
||||
|
||||
msgid "Refresh templates"
|
||||
msgstr "Обновить шаблоны"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Revision: %s (%s)"
|
||||
msgstr "Изменения: %s (%s)"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s %s (%s, %s)"
|
||||
msgstr "%s %s (%s, %s)"
|
||||
|
||||
msgid "&File"
|
||||
msgstr "&Файл"
|
||||
|
||||
@@ -600,13 +684,13 @@ msgid "About Joplin"
|
||||
msgstr "О Joplin"
|
||||
|
||||
msgid "Preferences..."
|
||||
msgstr ""
|
||||
msgstr "Настройки…"
|
||||
|
||||
msgid "Check for updates..."
|
||||
msgstr "Проверить обновления..."
|
||||
|
||||
msgid "Templates"
|
||||
msgstr ""
|
||||
msgstr "Шаблоны"
|
||||
|
||||
msgid "Import"
|
||||
msgstr "Импорт"
|
||||
@@ -625,7 +709,7 @@ msgid "Quit"
|
||||
msgstr "Выход"
|
||||
|
||||
msgid "Close Window"
|
||||
msgstr ""
|
||||
msgstr "Закрыть окно"
|
||||
|
||||
msgid "&Edit"
|
||||
msgstr "&Правка"
|
||||
@@ -643,10 +727,10 @@ msgid "Select all"
|
||||
msgstr "Выбрать все"
|
||||
|
||||
msgid "Bold"
|
||||
msgstr "Жирный"
|
||||
msgstr "Полужирный"
|
||||
|
||||
msgid "Italic"
|
||||
msgstr "Наклонный"
|
||||
msgstr "Курсивный"
|
||||
|
||||
msgid "Link"
|
||||
msgstr "Ссылка"
|
||||
@@ -690,15 +774,14 @@ msgstr "&Помощь"
|
||||
msgid "Website and documentation"
|
||||
msgstr "Сайт и документация"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Joplin Forum"
|
||||
msgstr "Joplin v%s"
|
||||
msgstr "Форум Joplin"
|
||||
|
||||
msgid "Make a donation"
|
||||
msgstr "Сделать пожертвование"
|
||||
msgstr "Пожертвовать"
|
||||
|
||||
msgid "Toggle development tools"
|
||||
msgstr ""
|
||||
msgstr "Включить средства разработки"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Open %s"
|
||||
@@ -768,7 +851,7 @@ msgstr ""
|
||||
"браузера в Joplin."
|
||||
|
||||
msgid "In order to use the web clipper, you need to do the following:"
|
||||
msgstr "Для того, чтобы использовать веб-клиппер, вам нужно сделать следующее:"
|
||||
msgstr "Для использования веб-клиппера вам нужно сделать следующее:"
|
||||
|
||||
msgid "Step 1: Enable the clipper service"
|
||||
msgstr "Шаг 1: включите службу веб-клиппера"
|
||||
@@ -778,7 +861,7 @@ msgid ""
|
||||
"enabling it your firewall may ask you to give permission to Joplin to listen "
|
||||
"to a particular port."
|
||||
msgstr ""
|
||||
"Эта служба позволяет расширению браузера общаться с Joplin. После ее "
|
||||
"Эта служба позволяет расширению браузера взаимодействовать с Joplin. После ее "
|
||||
"включения брандмауэр ОС может запросить разрешение на использование Joplin "
|
||||
"определенного порта."
|
||||
|
||||
@@ -804,9 +887,6 @@ msgstr ""
|
||||
"Этот токен авторизации необходим только для разрешения сторонним приложениям "
|
||||
"получать доступ к Joplin."
|
||||
|
||||
msgid "This will open a new screen. Save your current changes?"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Заметки и настройки сохранены в: %s"
|
||||
@@ -817,9 +897,6 @@ msgstr "Проверить настройки синхронизации"
|
||||
msgid "Browse..."
|
||||
msgstr "Обзор..."
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Назад"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Применить"
|
||||
|
||||
@@ -915,18 +992,12 @@ msgstr "Статус"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Шифрование:"
|
||||
|
||||
msgid "Firefox Extension"
|
||||
msgstr ""
|
||||
|
||||
msgid "Chrome Web Store"
|
||||
msgstr ""
|
||||
|
||||
msgid "Get it now:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Usage"
|
||||
msgstr "Использование: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Назад"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"New notebook \"%s\" will be created and file \"%s\" will be imported into it"
|
||||
@@ -955,16 +1026,7 @@ msgid "Set alarm:"
|
||||
msgstr "Установить напоминание:"
|
||||
|
||||
msgid "Template file:"
|
||||
msgstr ""
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Новая заметка"
|
||||
|
||||
msgid "New to-do"
|
||||
msgstr "Новая задача"
|
||||
|
||||
msgid "New notebook"
|
||||
msgstr "Новый блокнот"
|
||||
msgstr "Файл шаблона:"
|
||||
|
||||
msgid "Layout"
|
||||
msgstr "Разметка"
|
||||
@@ -978,9 +1040,8 @@ msgstr "Некоторые элементы не могут быть синхр
|
||||
msgid "View them now"
|
||||
msgstr "Просмотреть их сейчас"
|
||||
|
||||
#, fuzzy
|
||||
msgid "One or more master keys need a password."
|
||||
msgstr "Введите мастер-пароль:"
|
||||
msgstr "Для одного или нескольких мастер-ключей требуется пароль."
|
||||
|
||||
msgid "Set the password"
|
||||
msgstr "Установить пароль"
|
||||
@@ -998,35 +1059,35 @@ msgstr "Местоположение"
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note History"
|
||||
msgstr "Список заметок"
|
||||
msgstr "История заметок"
|
||||
|
||||
msgid "Markup"
|
||||
msgstr ""
|
||||
msgstr "Разметка"
|
||||
|
||||
msgid "Previous versions of this note"
|
||||
msgstr ""
|
||||
msgstr "Предыдущая версия заметки"
|
||||
|
||||
msgid "Note properties"
|
||||
msgstr "Свойства заметки"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The note \"%s\" has been successfully restored to the notebook \"%s\"."
|
||||
msgstr ""
|
||||
msgstr "Заметка “%s” была успешно восстановлена в блокнот “%s”."
|
||||
|
||||
#, fuzzy
|
||||
msgid "This note has no history"
|
||||
msgstr "Эта заметка была изменена:"
|
||||
msgstr "Эта заметка не имеет предыдущей версии"
|
||||
|
||||
msgid "Restore"
|
||||
msgstr ""
|
||||
msgstr "Восстановить"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Click \"%s\" to restore the note. It will be copied in the notebook named "
|
||||
"\"%s\". The current version of the note will not be replaced or modified."
|
||||
msgstr ""
|
||||
"Нажмите “%s”, чтобы восстановить заметку. Она будет скопирована в блокнот "
|
||||
"“%s”. Текущая версия заметки не будет заменена или изменена."
|
||||
|
||||
msgid "Open..."
|
||||
msgstr "Открыть..."
|
||||
@@ -1063,13 +1124,6 @@ msgid "Only one note can be printed or exported to PDF at a time."
|
||||
msgstr ""
|
||||
"Только одна заметка может быть напечатана или экспортирована в PDF за раз."
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr "Файл PDF"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Error opening note in editor: %s"
|
||||
msgstr "Ошибка при открытии заметки в редакторе: %s"
|
||||
|
||||
msgid "strong text"
|
||||
msgstr "выделенный текст"
|
||||
|
||||
@@ -1144,18 +1198,25 @@ msgstr "Настройки"
|
||||
msgid "Synchronisation Status"
|
||||
msgstr "Статус синхронизации"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Encryption Options"
|
||||
msgstr "Настройки шифрования"
|
||||
|
||||
msgid "Clipper Options"
|
||||
msgstr "Настройки клиппера"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Delete notebook \"%s\"?\n"
|
||||
"\n"
|
||||
"All notes and sub-notebooks within this notebook will also be deleted."
|
||||
msgstr ""
|
||||
"Удалить блокнот? Все заметки и вложенные блокноты в этом блокноте также "
|
||||
"будут удалены."
|
||||
"Удалить блокнот “%s”?\n"
|
||||
"\n"
|
||||
"Все заметки и вложенные блокноты в этом блокноте также будут удалены."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Remove tag \"%s\" from all notes?"
|
||||
msgstr "Удалить эту метку из всех заметок?"
|
||||
msgstr "Удалить метку “%s” из всех заметок?"
|
||||
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Удалить этот поиск из боковой панели?"
|
||||
@@ -1166,23 +1227,12 @@ msgstr "Удалить"
|
||||
msgid "Rename"
|
||||
msgstr "Переименовать"
|
||||
|
||||
msgid "Notebooks"
|
||||
msgstr "Блокноты"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Decrypting items: %d/%d"
|
||||
msgstr "Расшифровано элементов: %d/%d"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Fetching resources: %d/%d"
|
||||
msgstr "Получение ресурсов: %d/%d"
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr ""
|
||||
"Пожалуйста, выберите, куда должен быть экспортирован статус синхронизации"
|
||||
|
||||
msgid "Retry"
|
||||
msgstr ""
|
||||
msgstr "Повторить попытку"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Добавить или удалить метки"
|
||||
@@ -1218,9 +1268,11 @@ msgid ""
|
||||
"Type a note title to jump to it. Or type # followed by a tag name, or @ "
|
||||
"followed by a notebook name."
|
||||
msgstr ""
|
||||
"Введите название заметки, чтобы перейти к ней, либо введите #имя_тега или "
|
||||
"@имя_блокнота."
|
||||
|
||||
msgid "Goto Anything..."
|
||||
msgstr ""
|
||||
msgstr "Перейти к чему угодно…"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Usage: %s"
|
||||
@@ -1334,6 +1386,12 @@ msgstr "Выполнение"
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "Синхронизация уже выполняется. Состояние: %s"
|
||||
|
||||
msgid ""
|
||||
"Unknown item type downloaded - please upgrade Joplin to the latest version"
|
||||
msgstr ""
|
||||
"Обнаружен неизвестный тип файла - пожалуйста, обновите Joplin до последней "
|
||||
"версии"
|
||||
|
||||
msgid "Encrypted"
|
||||
msgstr "Зашифровано"
|
||||
|
||||
@@ -1395,7 +1453,7 @@ msgid "Directory to synchronise with (absolute path)"
|
||||
msgstr "Каталог синхронизации (абсолютный путь)"
|
||||
|
||||
msgid "Nextcloud WebDAV URL"
|
||||
msgstr "Nextcloud WebDAV URL"
|
||||
msgstr "URL-адрес WebDAV-сервера Nextcloud"
|
||||
|
||||
msgid "Nextcloud username"
|
||||
msgstr "Имя пользователя Nextcloud"
|
||||
@@ -1404,7 +1462,7 @@ msgid "Nextcloud password"
|
||||
msgstr "Пароль Nextcloud"
|
||||
|
||||
msgid "WebDAV URL"
|
||||
msgstr "WebDAV URL"
|
||||
msgstr "URL-адрес WebDAV"
|
||||
|
||||
msgid "WebDAV username"
|
||||
msgstr "Имя пользователя WebDAV"
|
||||
@@ -1413,25 +1471,28 @@ msgid "WebDAV password"
|
||||
msgstr "Пароль WebDAV"
|
||||
|
||||
msgid "Attachment download behaviour"
|
||||
msgstr ""
|
||||
msgstr "Правило загрузок вложений"
|
||||
|
||||
msgid ""
|
||||
"In \"Manual\" mode, attachments are downloaded only when you click on them. "
|
||||
"In \"Auto\", they are downloaded when you open the note. In \"Always\", all "
|
||||
"the attachments are downloaded whether you open the note or not."
|
||||
msgstr ""
|
||||
"В режиме “Ручной” вложения скачиваются, если на них кликнуть. В режиме "
|
||||
"“Автоматически”, вложения скачиваются при открытии заметки. В режиме "
|
||||
"“Всегда” все заметки скачиваются всегда."
|
||||
|
||||
msgid "Always"
|
||||
msgstr ""
|
||||
msgstr "Всегда"
|
||||
|
||||
msgid "Manual"
|
||||
msgstr ""
|
||||
msgstr "Ручной"
|
||||
|
||||
msgid "Auto"
|
||||
msgstr ""
|
||||
msgstr "Автоматически"
|
||||
|
||||
msgid "Max concurrent connections"
|
||||
msgstr ""
|
||||
msgstr "Максимальное число одновременных соединений"
|
||||
|
||||
msgid "Language"
|
||||
msgstr "Язык"
|
||||
@@ -1449,13 +1510,13 @@ msgid "Light"
|
||||
msgstr "Светлая"
|
||||
|
||||
msgid "Dark"
|
||||
msgstr "Темная"
|
||||
msgstr "Тёмная"
|
||||
|
||||
msgid "Solarised Light"
|
||||
msgstr ""
|
||||
msgstr "Ярко-светлая"
|
||||
|
||||
msgid "Solarised Dark"
|
||||
msgstr ""
|
||||
msgstr "Ярко-тёмная"
|
||||
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Незавершенные задачи сверху"
|
||||
@@ -1488,44 +1549,43 @@ msgid "When creating a new note:"
|
||||
msgstr "При создании новой заметки:"
|
||||
|
||||
msgid "Enable soft breaks"
|
||||
msgstr ""
|
||||
msgstr "Включить мягкие отступы"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable math expressions"
|
||||
msgstr "Включить шифрование"
|
||||
msgstr "Включить математические выражения"
|
||||
|
||||
msgid "Enable ==mark== syntax"
|
||||
msgstr ""
|
||||
msgstr "Включить синтаксис ==mark=="
|
||||
|
||||
msgid "Enable footnotes"
|
||||
msgstr ""
|
||||
msgstr "Включить постраничные сноски"
|
||||
|
||||
msgid "Enable table of contents extension"
|
||||
msgstr ""
|
||||
msgstr "Включить расширение содержания"
|
||||
|
||||
msgid "Enable ~sub~ syntax"
|
||||
msgstr ""
|
||||
msgstr "Включить синтаксис ~sub~"
|
||||
|
||||
msgid "Enable ^sup^ syntax"
|
||||
msgstr ""
|
||||
msgstr "Включить синтаксис ^sup^"
|
||||
|
||||
msgid "Enable deflist syntax"
|
||||
msgstr ""
|
||||
msgstr "Включить синтаксис deflist"
|
||||
|
||||
msgid "Enable abbreviation syntax"
|
||||
msgstr ""
|
||||
msgstr "Включить синтаксис аббревиатур"
|
||||
|
||||
msgid "Enable markdown emoji"
|
||||
msgstr ""
|
||||
msgstr "Включить markdown emoji"
|
||||
|
||||
msgid "Enable ++insert++ syntax"
|
||||
msgstr ""
|
||||
msgstr "Включить синтаксис ++insert++"
|
||||
|
||||
msgid "Enable multimarkdown table extension"
|
||||
msgstr ""
|
||||
msgstr "Включить расширение таблиц multimarkdown"
|
||||
|
||||
msgid "Enable Fountain syntax support"
|
||||
msgstr ""
|
||||
msgstr "Включить поддержку Fountain"
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr "Показывать иконку в трее"
|
||||
@@ -1551,10 +1611,6 @@ msgstr "Глобальный масштаб в процентах"
|
||||
msgid "Editor font size"
|
||||
msgstr "Размер шрифта редактора"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Editor font"
|
||||
msgstr "Размер шрифта редактора"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr "Семейство шрифтов редактора"
|
||||
|
||||
@@ -1621,29 +1677,25 @@ msgstr ""
|
||||
msgid "Ignore TLS certificate errors"
|
||||
msgstr "Игнорировать ошибки сертификата TLS"
|
||||
|
||||
msgid ""
|
||||
"Fail-safe: Do not wipe out local data when sync target is empty (often the "
|
||||
"result of a misconfiguration or bug)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Specify the port that should be used by the API server. If not set, a "
|
||||
"default will be used."
|
||||
msgstr ""
|
||||
"Укажите порт для работы сервера API. Если не указано, будет использовано "
|
||||
"значение по умолчанию."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable note history"
|
||||
msgstr "Включить шифрование"
|
||||
msgstr "Включить историю заметок"
|
||||
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
msgstr "дни"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%d days"
|
||||
msgstr ""
|
||||
msgstr "%d дней"
|
||||
|
||||
msgid "Keep note history for"
|
||||
msgstr ""
|
||||
msgstr "Хранить историю заметки"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
@@ -1662,19 +1714,11 @@ msgid "Note"
|
||||
msgstr "Заметки"
|
||||
|
||||
msgid "Plugins"
|
||||
msgstr ""
|
||||
msgstr "Плагины"
|
||||
|
||||
msgid "Application"
|
||||
msgstr "Приложение"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encryption"
|
||||
msgstr "Шифрование:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Web Clipper"
|
||||
msgstr "Настройки веб-клиппера"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr "Метка \"%s\" уже существует. Пожалуйста, выберите другое имя."
|
||||
@@ -1688,12 +1732,7 @@ msgstr "Markdown"
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr "Каталог экспорта Joplin"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as Markdown)"
|
||||
msgstr "Файл экспорта Evernote"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File (as HTML)"
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Файл экспорта Evernote"
|
||||
|
||||
msgid "Json Export Directory"
|
||||
@@ -1729,7 +1768,7 @@ msgstr ""
|
||||
"Пожалуйста, укажите блокнот, в который должны быть импортированы заметки."
|
||||
|
||||
msgid "Restored Notes"
|
||||
msgstr ""
|
||||
msgstr "Восстановленные заметки"
|
||||
|
||||
msgid "Items that cannot be synchronised"
|
||||
msgstr "Элементы, которые не могут быть синхронизированы"
|
||||
@@ -1743,23 +1782,25 @@ msgstr ""
|
||||
"синхронизации. Чтобы найти эти элементы, воспользуйтесь поиском по названию "
|
||||
"или ID (который указывается в скобках выше)."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "%s (%s) could not be uploaded: %s"
|
||||
msgstr "Этот файл не может быть открыт: %s"
|
||||
msgstr "Не удается загрузить файл %s (%s): %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Item \"%s\" could not be downloaded: %s"
|
||||
msgstr "Этот файл не может быть открыт: %s"
|
||||
msgstr "Не удается скачать файл “%s”: %s"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Items that cannot be decrypted"
|
||||
msgstr "Элементы, которые не могут быть синхронизированы"
|
||||
msgstr "Элементы, которые не могут быть расшифрованы"
|
||||
|
||||
msgid ""
|
||||
"Joplin failed to decrypt these items multiple times, possibly because they "
|
||||
"are corrupted or too large. These items will remain on the device but Joplin "
|
||||
"will no longer attempt to decrypt them."
|
||||
msgstr ""
|
||||
"Joplin не удалось расшифровать эти файлы несколько раз. Возможно они "
|
||||
"повреждены или слишком большие. Файлы останутся на устройстве без дальнейших "
|
||||
"попыток расшифровать их."
|
||||
|
||||
msgid "Sync status (synced items / total items)"
|
||||
msgstr "Статус синхронизации (синхронизировано / всего)"
|
||||
@@ -1800,13 +1841,11 @@ msgstr "Разрешение на использование камеры"
|
||||
msgid "Your permission to use your camera is required."
|
||||
msgstr "Необходимо ваше разрешение на использование камеры."
|
||||
|
||||
#, fuzzy
|
||||
msgid "You currently have no notebooks."
|
||||
msgstr "Нет активного блокнота."
|
||||
msgstr "Сейчас у вас нет блокнотов."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Create a notebook"
|
||||
msgstr "Создает новый блокнот."
|
||||
msgstr "Создать новый блокнот"
|
||||
|
||||
msgid "There are currently no notes. Create one by clicking on the (+) button."
|
||||
msgstr "Сейчас здесь нет заметок. Создайте новую, нажав кнопку (+)."
|
||||
@@ -1836,24 +1875,32 @@ msgstr "Выбрать дату"
|
||||
msgid "Confirm"
|
||||
msgstr "Подтвердить"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Notebook: %s"
|
||||
msgstr "Блокноты"
|
||||
msgstr "Блокноты: %s"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encrypted notebooks cannot be renamed"
|
||||
msgstr "Зашифрованные элементы не могут быть изменены"
|
||||
msgstr "Невозможно переименовать зашифрованные блокноты"
|
||||
|
||||
#, fuzzy
|
||||
msgid "New Notebook"
|
||||
msgstr "Новый блокнот"
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr "Конфигурация"
|
||||
|
||||
#, fuzzy
|
||||
#, javascript-format
|
||||
msgid "Decrypting items: %d/%d"
|
||||
msgstr "Расшифровано элементов: %d/%d"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Fetching resources: %d/%d"
|
||||
msgstr "Получение ресурсов: %d/%d"
|
||||
|
||||
msgid "All notes"
|
||||
msgstr "заметка"
|
||||
msgstr "Все заметки"
|
||||
|
||||
msgid "Notebooks"
|
||||
msgstr "Блокноты"
|
||||
|
||||
msgid "Checking... Please wait."
|
||||
msgstr "Проверка... Пожалуйста, подождите."
|
||||
@@ -1896,48 +1943,51 @@ msgid "Type new tags or select from list"
|
||||
msgstr "Введите новые метки или выберите из списка"
|
||||
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
msgstr "Предупрежение"
|
||||
|
||||
msgid ""
|
||||
"In order to use file system synchronisation your permission to write to "
|
||||
"external storage is required."
|
||||
msgstr ""
|
||||
"Для использование синхронизации файловой системы, необходимо дать разрешение "
|
||||
"на запись."
|
||||
|
||||
msgid "Information"
|
||||
msgstr "Информация"
|
||||
|
||||
msgid "Encryption Config"
|
||||
msgstr "Конфигурация шифрования"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Tools"
|
||||
msgstr "&Сервис"
|
||||
msgstr "Инструменты"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Sync Status"
|
||||
msgstr "Статус"
|
||||
msgstr "Синхронизировать статус"
|
||||
|
||||
msgid "Log"
|
||||
msgstr "Журнал"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Creating report..."
|
||||
msgstr "Создание новой %s..."
|
||||
msgstr "Создание отчета…"
|
||||
|
||||
msgid "Export Debug Report"
|
||||
msgstr "Экспортировать отладочный отчет"
|
||||
|
||||
msgid "Fixing search index..."
|
||||
msgstr ""
|
||||
msgstr "Исправление индекса поиска…"
|
||||
|
||||
msgid "Fix search index"
|
||||
msgstr ""
|
||||
msgstr "Исправить индекс поиска"
|
||||
|
||||
msgid ""
|
||||
"Use this to rebuild the search index if there is a problem with search. It "
|
||||
"may take a long time depending on the number of notes."
|
||||
msgstr ""
|
||||
"Используйте это, чтобы перестроить индекс поиска, если возникли проблемы с "
|
||||
"поиском. Это может занять много времени в зависимости от количества заметок."
|
||||
|
||||
#, fuzzy
|
||||
msgid "More information"
|
||||
msgstr "Конфигурация"
|
||||
msgstr "Больше информации"
|
||||
|
||||
msgid ""
|
||||
"To work correctly, the app needs the following permissions. Please enable "
|
||||
@@ -2002,9 +2052,8 @@ msgstr "Блокнот не может быть сохранен: %s"
|
||||
msgid "Edit notebook"
|
||||
msgstr "Редактировать блокнот"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enter notebook title"
|
||||
msgstr "Название блокнота:"
|
||||
msgstr "Введите название блокнота"
|
||||
|
||||
msgid "Show all"
|
||||
msgstr "Показать все"
|
||||
@@ -2033,15 +2082,15 @@ msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Links with protocol \"%s\" are not supported"
|
||||
msgstr ""
|
||||
msgstr "Связь с протоколом “%s” не поддерживается"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported image type: %s"
|
||||
msgstr "Неподдерживаемый формат изображения: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Updated: %s"
|
||||
msgstr "Обновлено: %d."
|
||||
msgstr "Обновлено: %s"
|
||||
|
||||
msgid "View on map"
|
||||
msgstr "Посмотреть на карте"
|
||||
@@ -2049,13 +2098,11 @@ msgstr "Посмотреть на карте"
|
||||
msgid "Go to source URL"
|
||||
msgstr "Перейти к исходному URL"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Attach..."
|
||||
msgstr "Поиск..."
|
||||
msgstr "Прикрепить…"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Choose an option"
|
||||
msgstr "Показывать расширенные настройки"
|
||||
msgstr "Выберите"
|
||||
|
||||
msgid "Take photo"
|
||||
msgstr "Сделать фото"
|
||||
@@ -2075,19 +2122,17 @@ msgstr "Преобразовать в заметку"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Преобразовать в задачу"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Properties"
|
||||
msgstr "Свойства заметки"
|
||||
msgstr "Свойства"
|
||||
|
||||
msgid "Add body"
|
||||
msgstr ""
|
||||
msgstr "Добавить тело"
|
||||
|
||||
msgid "Edit"
|
||||
msgstr "Правка"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Add title"
|
||||
msgstr "заголовок"
|
||||
msgstr "Добавить заголовок"
|
||||
|
||||
msgid "Login with OneDrive"
|
||||
msgstr "Войти с OneDrive"
|
||||
@@ -2095,66 +2140,6 @@ msgstr "Войти с OneDrive"
|
||||
msgid "Search"
|
||||
msgstr "Поиск"
|
||||
|
||||
#~ msgid "Starting to edit note. Close the editor to get back to the prompt."
|
||||
#~ msgstr ""
|
||||
#~ "Запуск редактирования заметки. Закройте редактор, чтобы вернуться к "
|
||||
#~ "приглашению."
|
||||
|
||||
#~ msgid "Note has been saved."
|
||||
#~ msgstr "Заметка сохранена."
|
||||
|
||||
#~ msgid "Sidebar"
|
||||
#~ msgstr "Боковая панель"
|
||||
|
||||
#~ msgid "Note list"
|
||||
#~ msgstr "Список заметок"
|
||||
|
||||
#~ msgid "Note title"
|
||||
#~ msgstr "Название заметки"
|
||||
|
||||
#~ msgid "Note body"
|
||||
#~ msgstr "Тело заметки"
|
||||
|
||||
#~ msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
#~ msgstr "Импорт из \"%s\" в формате \"%s\". Пожалуйста, подождите..."
|
||||
|
||||
#~ msgid "Synchronisation status"
|
||||
#~ msgstr "Статус синхронизации"
|
||||
|
||||
#~ msgid "Print"
|
||||
#~ msgstr "Печать"
|
||||
|
||||
#~ msgid "General Options"
|
||||
#~ msgstr "Основные настройки"
|
||||
|
||||
#~ msgid "Encryption options"
|
||||
#~ msgstr "Настройки шифрования"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Insert template"
|
||||
#~ msgstr "Вставить дату и время"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Open template directory"
|
||||
#~ msgstr "Каталог экспорта Joplin"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Revision: %s (%s)"
|
||||
#~ msgstr "%s %s (%s)"
|
||||
|
||||
#~ msgid "%s %s (%s, %s)"
|
||||
#~ msgstr "%s %s (%s, %s)"
|
||||
|
||||
#~ msgid "Encryption Options"
|
||||
#~ msgstr "Настройки шифрования"
|
||||
|
||||
#~ msgid "Clipper Options"
|
||||
#~ msgstr "Настройки клиппера"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Information"
|
||||
#~ msgstr "Конфигурация"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Permission to write to external storage"
|
||||
#~ msgstr "Разрешение на использование камеры"
|
||||
|
366
CliClient/package-lock.json
generated
366
CliClient/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "joplin",
|
||||
"version": "1.0.147",
|
||||
"version": "1.0.149",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -18,9 +18,9 @@
|
||||
}
|
||||
},
|
||||
"abab": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
|
||||
"integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w=="
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.2.tgz",
|
||||
"integrity": "sha512-2scffjvioEmNz0OyDSLGWDfKCVwaKc6l9Pm9kOIREU13ClXZvHpg/nRL5xyjSSSLhOnXqft2HpsAzNEEA8cFFg=="
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
@@ -28,17 +28,24 @@
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"acorn": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz",
|
||||
"integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw=="
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
|
||||
},
|
||||
"acorn-globals": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz",
|
||||
"integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==",
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
|
||||
"integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
|
||||
"requires": {
|
||||
"acorn": "^6.0.1",
|
||||
"acorn-walk": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
|
||||
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"acorn-walk": {
|
||||
@@ -141,9 +148,9 @@
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
},
|
||||
"async-mutex": {
|
||||
"version": "0.1.3",
|
||||
@@ -467,11 +474,11 @@
|
||||
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
|
||||
},
|
||||
"cssstyle": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.3.0.tgz",
|
||||
"integrity": "sha512-wXsoRfsRfsLVNaVzoKdqvEmK/5PFaEXNspVT22Ots6K/cnJdpoDKuQFw+qlMiXnmaif1OgeC466X1zISgAOcGg==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz",
|
||||
"integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==",
|
||||
"requires": {
|
||||
"cssom": "~0.3.6"
|
||||
"cssom": "0.3.x"
|
||||
}
|
||||
},
|
||||
"cwise-compiler": {
|
||||
@@ -498,6 +505,18 @@
|
||||
"abab": "^2.0.0",
|
||||
"whatwg-mimetype": "^2.2.0",
|
||||
"whatwg-url": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"whatwg-url": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz",
|
||||
"integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==",
|
||||
"requires": {
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"tr46": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
@@ -705,9 +724,9 @@
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"escodegen": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz",
|
||||
"integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==",
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz",
|
||||
"integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==",
|
||||
"requires": {
|
||||
"esprima": "^3.1.3",
|
||||
"estraverse": "^4.2.0",
|
||||
@@ -730,14 +749,14 @@
|
||||
"integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
|
||||
},
|
||||
"estraverse": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
|
||||
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
|
||||
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
|
||||
},
|
||||
"exit": {
|
||||
"version": "0.1.2",
|
||||
@@ -1112,6 +1131,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
|
||||
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
@@ -1516,206 +1554,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"joplin-turndown": {
|
||||
"version": "4.0.17",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.17.tgz",
|
||||
"integrity": "sha512-57mw92ZOKoR77YBLUkauN1xNq1xlxOm2KaPty/jlYrkEyGotUBBvq46a6wXh6d3aM4CccGuwymSge18/9IoB3A==",
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.18.tgz",
|
||||
"integrity": "sha512-YD0pkj2a7+XjjNNI1X9ZIwYthFwNsswvO4gl5aAoWdwJj5m8tunnoSyVenvqleXzAcaURIi/q9EOAQ1jw7xDiQ==",
|
||||
"requires": {
|
||||
"css": "^2.2.4",
|
||||
"html-entities": "^1.2.1",
|
||||
"jsdom": "^11.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.10.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.1.tgz",
|
||||
"integrity": "sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||
"requires": {
|
||||
"ajv": "^6.5.5",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"jsdom": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
|
||||
"integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
|
||||
"requires": {
|
||||
"abab": "^2.0.0",
|
||||
"acorn": "^5.5.3",
|
||||
"acorn-globals": "^4.1.0",
|
||||
"array-equal": "^1.0.0",
|
||||
"cssom": ">= 0.3.2 < 0.4.0",
|
||||
"cssstyle": "^1.0.0",
|
||||
"data-urls": "^1.0.0",
|
||||
"domexception": "^1.0.1",
|
||||
"escodegen": "^1.9.1",
|
||||
"html-encoding-sniffer": "^1.0.2",
|
||||
"left-pad": "^1.3.0",
|
||||
"nwsapi": "^2.0.7",
|
||||
"parse5": "4.0.0",
|
||||
"pn": "^1.1.0",
|
||||
"request": "^2.87.0",
|
||||
"request-promise-native": "^1.0.5",
|
||||
"sax": "^1.2.4",
|
||||
"symbol-tree": "^3.2.2",
|
||||
"tough-cookie": "^2.3.4",
|
||||
"w3c-hr-time": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2",
|
||||
"whatwg-encoding": "^1.0.3",
|
||||
"whatwg-mimetype": "^2.1.0",
|
||||
"whatwg-url": "^6.4.1",
|
||||
"ws": "^5.2.0",
|
||||
"xml-name-validator": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.40.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
|
||||
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.24",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
|
||||
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.40.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"parse5": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
|
||||
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.0",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.4.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
|
||||
"integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
|
||||
"requires": {
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"tr46": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"joplin-turndown-plugin-gfm": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown-plugin-gfm/-/joplin-turndown-plugin-gfm-1.0.9.tgz",
|
||||
"integrity": "sha512-SOa/Uiy3nyoBGtHqFe+TBg10UTIOzzcUUzNhx2MyR4Z0vbKL3enGggGypig1t7G5uHwv5j+NhooRuM619Zk0bw=="
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown-plugin-gfm/-/joplin-turndown-plugin-gfm-1.0.11.tgz",
|
||||
"integrity": "sha512-S2I+VCTqIhpWKKkPHsyJ5rdll9H/JjMXoBVClRX1TnphcmrSxufevdoXWWVgLncdXpSSiuoifCXgFZy3ueVElg=="
|
||||
},
|
||||
"jpeg-js": {
|
||||
"version": "0.1.2",
|
||||
@@ -1733,6 +1584,39 @@
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
},
|
||||
"jsdom": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
|
||||
"integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
|
||||
"requires": {
|
||||
"abab": "^2.0.0",
|
||||
"acorn": "^5.5.3",
|
||||
"acorn-globals": "^4.1.0",
|
||||
"array-equal": "^1.0.0",
|
||||
"cssom": ">= 0.3.2 < 0.4.0",
|
||||
"cssstyle": "^1.0.0",
|
||||
"data-urls": "^1.0.0",
|
||||
"domexception": "^1.0.1",
|
||||
"escodegen": "^1.9.1",
|
||||
"html-encoding-sniffer": "^1.0.2",
|
||||
"left-pad": "^1.3.0",
|
||||
"nwsapi": "^2.0.7",
|
||||
"parse5": "4.0.0",
|
||||
"pn": "^1.1.0",
|
||||
"request": "^2.87.0",
|
||||
"request-promise-native": "^1.0.5",
|
||||
"sax": "^1.2.4",
|
||||
"symbol-tree": "^3.2.2",
|
||||
"tough-cookie": "^2.3.4",
|
||||
"w3c-hr-time": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2",
|
||||
"whatwg-encoding": "^1.0.3",
|
||||
"whatwg-mimetype": "^2.1.0",
|
||||
"whatwg-url": "^6.4.1",
|
||||
"ws": "^5.2.0",
|
||||
"xml-name-validator": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
@@ -2293,6 +2177,11 @@
|
||||
"no-case": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"parse5": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
|
||||
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
@@ -2595,13 +2484,6 @@
|
||||
"integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.14",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
|
||||
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"request-promise-native": {
|
||||
@@ -3208,7 +3090,7 @@
|
||||
"requires": {
|
||||
"chalk": "^2.1.0",
|
||||
"emphasize": "^1.5.0",
|
||||
"node-emoji": "git+https://github.com/laurent22/node-emoji.git#9fa01eac463e94dde1316ef8c53089eeef4973b5",
|
||||
"node-emoji": "git+https://github.com/laurent22/node-emoji.git",
|
||||
"slice-ansi": "^1.0.0",
|
||||
"string-width": "^2.1.1",
|
||||
"terminal-kit": "^1.13.11",
|
||||
@@ -3235,11 +3117,19 @@
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
|
||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"requires": {
|
||||
"punycode": "^1.4.1"
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
@@ -3434,9 +3324,9 @@
|
||||
"integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz",
|
||||
"integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
|
||||
"integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
|
||||
"requires": {
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"tr46": "^1.0.1",
|
||||
@@ -3489,6 +3379,14 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"ws": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"xml-name-validator": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
|
||||
|
@@ -20,7 +20,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "1.0.147",
|
||||
"version": "1.0.149",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
@@ -44,8 +44,8 @@
|
||||
"html-minifier": "^3.5.15",
|
||||
"image-data-uri": "^2.0.0",
|
||||
"image-type": "^3.0.0",
|
||||
"joplin-turndown": "^4.0.17",
|
||||
"joplin-turndown-plugin-gfm": "^1.0.9",
|
||||
"joplin-turndown": "^4.0.18",
|
||||
"joplin-turndown-plugin-gfm": "^1.0.11",
|
||||
"jssha": "^2.3.0",
|
||||
"levenshtein": "^1.0.5",
|
||||
"markdown-it": "^8.4.2",
|
||||
|
@@ -24,6 +24,7 @@ cd "$ROOT_DIR"
|
||||
NODE_ENV=testing npm test tests-build/ArrayUtils.js && \
|
||||
NODE_ENV=testing npm test tests-build/encryption.js && \
|
||||
NODE_ENV=testing npm test tests-build/EnexToMd.js && \
|
||||
NODE_ENV=testing npm test tests-build/EnexToHtml.js && \
|
||||
NODE_ENV=testing npm test tests-build/HtmlToMd.js && \
|
||||
NODE_ENV=testing npm test tests-build/markdownUtils.js && \
|
||||
NODE_ENV=testing npm test tests-build/models_BaseItem.js && \
|
||||
@@ -44,4 +45,4 @@ NODE_ENV=testing npm test tests-build/services_Revision.js && \
|
||||
NODE_ENV=testing npm test tests-build/StringUtils.js && \
|
||||
NODE_ENV=testing npm test tests-build/TaskQueue.js && \
|
||||
NODE_ENV=testing npm test tests-build/synchronizer.js && \
|
||||
NODE_ENV=testing npm test tests-build/urlUtils.js
|
||||
NODE_ENV=testing npm test tests-build/urlUtils.js
|
||||
|
@@ -39,7 +39,7 @@ describe('HtmlToMd', function() {
|
||||
const htmlPath = `${basePath}/${htmlFilename}`;
|
||||
const mdPath = `${basePath}/${filename(htmlFilename)}.md`;
|
||||
|
||||
// if (htmlFilename !== 'table_with_pipe.html') continue;
|
||||
// if (htmlFilename !== 'table_with_header.html') continue;
|
||||
|
||||
const htmlToMdOptions = {};
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('HtmlToMd', function() {
|
||||
// This is straightforward when the document is still in DOM format, as with the clipper,
|
||||
// but otherwise it would need to be somehow parsed out from the HTML. Here we just
|
||||
// hard code the anchors that we know are in the file.
|
||||
htmlToMdOptions.anchorNames = ['first', 'second'];
|
||||
htmlToMdOptions.anchorNames = ['first', 'second', 'fourth'];
|
||||
}
|
||||
|
||||
const html = await shim.fsDriver().readFile(htmlPath);
|
||||
|
@@ -0,0 +1,8 @@
|
||||
<div><span style="font-style: italic;">singleline italic text with span style font-style: italic;.</span></div><div><br/></div>
|
||||
<div><span style="font-style: italic;">multiline italic
|
||||
text with span style font-style: italic;.</span></div><div><br/></div>
|
||||
|
||||
<div><span style="font-style: italic;">singleline italic text with span style font-style: italic;</span> next to normal text with leading space.</div><div><br/></div>
|
||||
<div><span style="font-style: italic;">singleline italic text with span style font-style: italic; and with trailing space </span>next to normal text.</div><div><br/></div>
|
||||
<div><span style="font-style: italic;">singleline italic text with span style font-style: italic;</span><span style="font-style: italic;"> next to more italic text with span style font-style: italic; and with leading space.</span></div><div><br/></div>
|
||||
<div><span style="font-style: italic;">singleline italic text with span style font-style: italic; and with trailing space </span><span style="font-style: italic;">next to more italic text with span style font-style: italic;.</span></div>
|
11
CliClient/tests/enex_to_md/text_formatting_span_italic.md
Normal file
11
CliClient/tests/enex_to_md/text_formatting_span_italic.md
Normal file
@@ -0,0 +1,11 @@
|
||||
*singleline italic text with span style font-style: italic;.*
|
||||
|
||||
*multiline italic text with span style font-style: italic;.*
|
||||
|
||||
*singleline italic text with span style font-style: italic;* next to normal text with leading space.
|
||||
|
||||
*singleline italic text with span style font-style: italic; and with trailing space *next to normal text.
|
||||
|
||||
*singleline italic text with span style font-style: italic;** next to more italic text with span style font-style: italic; and with leading space.*
|
||||
|
||||
*singleline italic text with span style font-style: italic; and with trailing space **next to more italic text with span style font-style: italic;.*
|
@@ -1,6 +1,8 @@
|
||||
<p><a href="#first">First</a></p>
|
||||
<p><a href="#second">Second</a></p>
|
||||
<p>Third</p>
|
||||
<p><a href="#fourth">Fourth</a></p>
|
||||
<p><a name="first"></a>First</p>
|
||||
<p><a id="second"></a>Second</p>
|
||||
<p><a id="third"></a>Third</p>
|
||||
<p><a id="third"></a>Third</p>
|
||||
<p><span id="fourth">Fourth</span></p>
|
@@ -4,8 +4,12 @@
|
||||
|
||||
Third
|
||||
|
||||
[Fourth](#fourth)
|
||||
|
||||
<a id="first"></a>First
|
||||
|
||||
<a id="second"></a>Second
|
||||
|
||||
Third
|
||||
Third
|
||||
|
||||
<a id="fourth"></a>Fourth
|
14
CliClient/tests/html_to_md/table_with_header.html
Normal file
14
CliClient/tests/html_to_md/table_with_header.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>A</th>
|
||||
<th>B</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>c</td>
|
||||
<td>d</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
3
CliClient/tests/html_to_md/table_with_header.md
Normal file
3
CliClient/tests/html_to_md/table_with_header.md
Normal file
@@ -0,0 +1,3 @@
|
||||
| A | B |
|
||||
| --- | --- |
|
||||
| c | d |
|
@@ -92,11 +92,11 @@ describe('models_Note', function() {
|
||||
it('should serialize and unserialize without modifying data', asyncTest(async () => {
|
||||
let folder1 = await Folder.save({ title: 'folder1'});
|
||||
const testCases = [
|
||||
[ {title: '', body:'Body and no title\nSecond line\nThird Line', parent_id: folder1.id},
|
||||
[ {title: '', body: 'Body and no title\nSecond line\nThird Line', parent_id: folder1.id},
|
||||
'', 'Body and no title\nSecond line\nThird Line'],
|
||||
[ {title: 'Note title', body:'Body and title', parent_id: folder1.id},
|
||||
[ {title: 'Note title', body: 'Body and title', parent_id: folder1.id},
|
||||
'Note title', 'Body and title'],
|
||||
[ {title: 'Title and no body', body:'', parent_id: folder1.id},
|
||||
[ {title: 'Title and no body', body: '', parent_id: folder1.id},
|
||||
'Title and no body', ''],
|
||||
];
|
||||
|
||||
|
@@ -279,7 +279,7 @@ describe('services_rest_Api', function() {
|
||||
const response = await api.route('GET', 'notes', { token: 'mytoken' });
|
||||
expect(response.length).toBe(0);
|
||||
|
||||
hasThrown = await checkThrowAsync(async () => await api.route('POST', 'notes', null, JSON.stringify({title:'testing'})));
|
||||
hasThrown = await checkThrowAsync(async () => await api.route('POST', 'notes', null, JSON.stringify({title: 'testing'})));
|
||||
expect(hasThrown).toBe(true);
|
||||
}));
|
||||
|
||||
|
@@ -892,10 +892,12 @@ describe('Synchronizer', function() {
|
||||
|
||||
await synchronizer().start();
|
||||
|
||||
const fetcher = new ResourceFetcher(() => { return {
|
||||
const fetcher = new ResourceFetcher(() => {
|
||||
return {
|
||||
// Simulate a failed download
|
||||
get: () => { return new Promise((resolve, reject) => { reject(new Error('did not work')); }); },
|
||||
}; });
|
||||
get: () => { return new Promise((resolve, reject) => { reject(new Error('did not work')); }); },
|
||||
};
|
||||
});
|
||||
fetcher.queueDownload_(resource1.id);
|
||||
await fetcher.waitForAllFinished();
|
||||
|
||||
@@ -1025,8 +1027,8 @@ describe('Synchronizer', function() {
|
||||
// If we try to disable encryption now, it should throw an error because some items are
|
||||
// currently encrypted. They must be decrypted first so that they can be sent as
|
||||
// plain text to the sync target.
|
||||
//let hasThrown = await checkThrowAsync(async () => await encryptionService().disableEncryption());
|
||||
//expect(hasThrown).toBe(true);
|
||||
// let hasThrown = await checkThrowAsync(async () => await encryptionService().disableEncryption());
|
||||
// expect(hasThrown).toBe(true);
|
||||
|
||||
// Now supply the password, and decrypt the items
|
||||
Setting.setObjectKey('encryption.passwordCache', masterKey.id, '123456');
|
||||
@@ -1504,4 +1506,39 @@ describe('Synchronizer', function() {
|
||||
expect((await Note.all()).length).toBe(11);
|
||||
}));
|
||||
|
||||
it('should not sync if client sync version is lower than target', asyncTest(async () => {
|
||||
// This should work - syncing two clients with same supported sync target version
|
||||
await synchronizer().start();
|
||||
await switchClient(2);
|
||||
await synchronizer().start();
|
||||
|
||||
// This should not work - syncing two clients, but one of them has not been upgraded yet to the latest sync version
|
||||
await switchClient(1);
|
||||
Setting.setConstant('syncVersion', 2);
|
||||
await synchronizer().start();
|
||||
|
||||
await switchClient(2);
|
||||
Setting.setConstant('syncVersion', 1);
|
||||
const hasThrown = await checkThrowAsync(async () => synchronizer().start({ throwOnError: true }));
|
||||
expect(hasThrown).toBe(true);
|
||||
}));
|
||||
|
||||
it('should not sync when target is locked', asyncTest(async () => {
|
||||
await synchronizer().start();
|
||||
await synchronizer().acquireLock_();
|
||||
|
||||
await switchClient(2);
|
||||
const hasThrown = await checkThrowAsync(async () => synchronizer().start({ throwOnError: true }));
|
||||
expect(hasThrown).toBe(true);
|
||||
}));
|
||||
|
||||
it('should clear a lock if it was created by the same app as the current one', asyncTest(async () => {
|
||||
await synchronizer().start();
|
||||
await synchronizer().acquireLock_();
|
||||
expect((await synchronizer().lockFiles_()).length).toBe(1);
|
||||
await synchronizer().start({ throwOnError: true });
|
||||
expect((await synchronizer().lockFiles_()).length).toBe(0);
|
||||
}));
|
||||
|
||||
|
||||
});
|
||||
|
@@ -24,6 +24,7 @@ const BaseService = require('lib/services/BaseService.js');
|
||||
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { shimInit } = require('lib/shim-init-node.js');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry.js');
|
||||
const SyncTargetMemory = require('lib/SyncTargetMemory.js');
|
||||
const SyncTargetFilesystem = require('lib/SyncTargetFilesystem.js');
|
||||
@@ -69,11 +70,11 @@ SyncTargetRegistry.addClass(SyncTargetDropbox);
|
||||
|
||||
// const syncTargetId_ = SyncTargetRegistry.nameToId("nextcloud");
|
||||
const syncTargetId_ = SyncTargetRegistry.nameToId('memory');
|
||||
//const syncTargetId_ = SyncTargetRegistry.nameToId('filesystem');
|
||||
// const syncTargetId_ = SyncTargetRegistry.nameToId('filesystem');
|
||||
// const syncTargetId_ = SyncTargetRegistry.nameToId('dropbox');
|
||||
const syncDir = `${__dirname}/../tests/sync`;
|
||||
|
||||
const sleepTime = syncTargetId_ == SyncTargetRegistry.nameToId('filesystem') ? 1001 : 100;//400;
|
||||
const sleepTime = syncTargetId_ == SyncTargetRegistry.nameToId('filesystem') ? 1001 : 100;// 400;
|
||||
|
||||
console.info(`Testing with sync target: ${SyncTargetRegistry.idToName(syncTargetId_)}`);
|
||||
|
||||
@@ -137,6 +138,7 @@ async function switchClient(id) {
|
||||
|
||||
await Setting.load();
|
||||
|
||||
if (!Setting.value('clientId')) Setting.setValue('clientId', uuid.create());
|
||||
Setting.setValue('sync.wipeOutFailSafe', false); // To keep things simple, always disable fail-safe unless explicitely set in the test itself
|
||||
}
|
||||
|
||||
@@ -180,6 +182,7 @@ async function setupDatabase(id = null) {
|
||||
if (databases_[id]) {
|
||||
await clearDatabase(id);
|
||||
await Setting.load();
|
||||
if (!Setting.value('clientId')) Setting.setValue('clientId', uuid.create());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,6 +200,7 @@ async function setupDatabase(id = null) {
|
||||
|
||||
BaseModel.db_ = databases_[id];
|
||||
await Setting.load();
|
||||
if (!Setting.value('clientId')) Setting.setValue('clientId', uuid.create());
|
||||
}
|
||||
|
||||
function resourceDir(id = null) {
|
||||
|
@@ -83,14 +83,18 @@
|
||||
}
|
||||
|
||||
function getAnchorNames(element) {
|
||||
const anchors = element.getElementsByTagName('a');
|
||||
const output = [];
|
||||
for (let i = 0; i < anchors.length; i++) {
|
||||
const anchor = anchors[i];
|
||||
if (anchor.id) {
|
||||
output.push(anchor.id);
|
||||
} else if (anchor.name) {
|
||||
output.push(anchor.name);
|
||||
// Anchor names are normally in A tags but can be in SPAN too
|
||||
// https://github.com/laurent22/joplin-turndown/commit/45f4ee6bf15b8804bdc2aa1d7ecb2f8cb594b8e5#diff-172b8b2bc3ba160589d3a7eeb4913687R232
|
||||
for (const tagName of ['a', 'span']) {
|
||||
const anchors = element.getElementsByTagName(tagName);
|
||||
for (let i = 0; i < anchors.length; i++) {
|
||||
const anchor = anchors[i];
|
||||
if (anchor.id) {
|
||||
output.push(anchor.id);
|
||||
} else if (anchor.name) {
|
||||
output.push(anchor.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
@@ -134,11 +138,17 @@
|
||||
const src = absoluteUrl(imageSrc(node));
|
||||
node.setAttribute('src', src);
|
||||
if (!(src in imageIndexes)) imageIndexes[src] = 0;
|
||||
const imageSize = imageSizes[src][imageIndexes[src]];
|
||||
imageIndexes[src]++;
|
||||
if (imageSize && convertToMarkup === 'markdown') {
|
||||
node.width = imageSize.width;
|
||||
node.height = imageSize.height;
|
||||
|
||||
if (!imageSizes[src]) {
|
||||
// This seems to concern dynamic images that don't really such as Gravatar, etc.
|
||||
console.warn('Found an image for which the size had not been fetched:', src);
|
||||
} else {
|
||||
const imageSize = imageSizes[src][imageIndexes[src]];
|
||||
imageIndexes[src]++;
|
||||
if (imageSize && convertToMarkup === 'markdown') {
|
||||
node.width = imageSize.width;
|
||||
node.height = imageSize.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,20 +1,22 @@
|
||||
function randomClipperPort(state, env) {
|
||||
const startPorts = {
|
||||
prod: 41184,
|
||||
dev: 27583,
|
||||
};
|
||||
|
||||
const startPort = env === 'prod' ? startPorts.prod : startPorts.dev;
|
||||
|
||||
if (!state) {
|
||||
state = { offset: 0 };
|
||||
} else {
|
||||
state.offset++;
|
||||
}
|
||||
|
||||
state.port = startPort + state.offset;
|
||||
state.port = startPort(env) + state.offset;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
module.exports = { randomClipperPort };
|
||||
function startPort(env) {
|
||||
const startPorts = {
|
||||
prod: 41184,
|
||||
dev: 27583,
|
||||
};
|
||||
|
||||
return env === 'prod' ? startPorts.prod : startPorts.dev;
|
||||
}
|
||||
|
||||
module.exports = { randomClipperPort, startPort };
|
||||
|
@@ -36,9 +36,13 @@ class InteropServiceHelper {
|
||||
if (options.sourceNoteIds) exportOptions.sourceNoteIds = options.sourceNoteIds;
|
||||
|
||||
const service = new InteropService();
|
||||
const result = await service.export(exportOptions);
|
||||
|
||||
console.info('Export result: ', result);
|
||||
try {
|
||||
const result = await service.export(exportOptions);
|
||||
console.info('Export result: ', result);
|
||||
} catch (error) {
|
||||
bridge().showErrorMessageBox(_('Could not export notes: %s', error.message));
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
|
@@ -196,7 +196,6 @@ class Application extends BaseApplication {
|
||||
break;
|
||||
|
||||
case 'NOTE_DEVTOOLS_TOGGLE':
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
newState.noteDevToolsVisible = !newState.noteDevToolsVisible;
|
||||
break;
|
||||
@@ -250,6 +249,11 @@ class Application extends BaseApplication {
|
||||
this.updateMenuItemStates();
|
||||
}
|
||||
|
||||
if (action.type === 'NOTE_DEVTOOLS_TOGGLE') {
|
||||
const menuItem = Menu.getApplicationMenu().getMenuItemById('help:toggleDevTools');
|
||||
menuItem.checked = newState.noteDevToolsVisible;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -418,15 +422,15 @@ class Application extends BaseApplication {
|
||||
},
|
||||
});
|
||||
|
||||
/* We need a dummy entry, otherwise the ternary operator to show a
|
||||
* menu item only on a specific OS does not work. */
|
||||
// We need a dummy entry, otherwise the ternary operator to show a
|
||||
// menu item only on a specific OS does not work.
|
||||
const noItem = {
|
||||
type: 'separator',
|
||||
visible: false,
|
||||
};
|
||||
|
||||
const syncStatusItem = {
|
||||
label: _('Synchronisation status'),
|
||||
label: _('Synchronisation Status'),
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'NAV_GO',
|
||||
@@ -565,6 +569,9 @@ class Application extends BaseApplication {
|
||||
'',
|
||||
'Copyright © 2016-2019 Laurent Cozic',
|
||||
_('%s %s (%s, %s)', p.name, p.version, Setting.value('env'), process.platform),
|
||||
'',
|
||||
_('Client ID: %s', Setting.value('clientId')),
|
||||
_('Sync Version: %s', Setting.value('syncVersion')),
|
||||
];
|
||||
if (gitInfo) {
|
||||
message.push(`\n${gitInfo}`);
|
||||
@@ -576,13 +583,13 @@ class Application extends BaseApplication {
|
||||
}
|
||||
|
||||
const rootMenuFile = {
|
||||
/* Using a dummy entry for macOS here, because first menu
|
||||
* becomes 'Joplin' and we need a nenu called 'File' later. */
|
||||
// Using a dummy entry for macOS here, because first menu
|
||||
// becomes 'Joplin' and we need a nenu called 'File' later.
|
||||
label: shim.isMac() ? '&JoplinMainMenu' : _('&File'),
|
||||
/* `&` before one of the char in the label name mean, that
|
||||
* <Alt + F> will open this menu. It's needed becase electron
|
||||
* opens the first menu on Alt press if no hotkey assigned.
|
||||
* Issue: https://github.com/laurent22/joplin/issues/934 */
|
||||
// `&` before one of the char in the label name mean, that
|
||||
// <Alt + F> will open this menu. It's needed becase electron
|
||||
// opens the first menu on Alt press if no hotkey assigned.
|
||||
// Issue: https://github.com/laurent22/joplin/issues/934
|
||||
submenu: [{
|
||||
label: _('About Joplin'),
|
||||
visible: shim.isMac() ? true : false,
|
||||
@@ -898,13 +905,13 @@ class Application extends BaseApplication {
|
||||
submenu: [{
|
||||
label: _('Website and documentation'),
|
||||
accelerator: 'F1',
|
||||
click () { bridge().openExternal('https://joplinapp.org'); },
|
||||
click() { bridge().openExternal('https://joplinapp.org'); },
|
||||
}, {
|
||||
label: _('Joplin Forum'),
|
||||
click () { bridge().openExternal('https://discourse.joplinapp.org'); },
|
||||
click() { bridge().openExternal('https://discourse.joplinapp.org'); },
|
||||
}, {
|
||||
label: _('Make a donation'),
|
||||
click () { bridge().openExternal('https://joplinapp.org/donate/'); },
|
||||
click() { bridge().openExternal('https://joplinapp.org/donate/'); },
|
||||
}, {
|
||||
label: _('Check for updates...'),
|
||||
visible: shim.isMac() ? false : true,
|
||||
@@ -913,6 +920,8 @@ class Application extends BaseApplication {
|
||||
type: 'separator',
|
||||
screens: ['Main'],
|
||||
}, {
|
||||
id: 'help:toggleDevTools',
|
||||
type: 'checkbox',
|
||||
label: _('Toggle development tools'),
|
||||
visible: true,
|
||||
click: () => {
|
||||
|
@@ -93,6 +93,18 @@ async function fetchLatestRelease(options) {
|
||||
};
|
||||
}
|
||||
|
||||
function truncateText(text, length) {
|
||||
let truncated = text.substring(0, length);
|
||||
const lastNewLine = truncated.lastIndexOf('\n');
|
||||
// Cut off at a line break unless we'd be cutting off half the text
|
||||
if (lastNewLine > length / 2) {
|
||||
truncated = `${truncated.substring(0, lastNewLine)}\n...`;
|
||||
} else {
|
||||
truncated = `${truncated.trim()}...`;
|
||||
}
|
||||
return truncated;
|
||||
}
|
||||
|
||||
function checkForUpdates(inBackground, window, logFilePath, options) {
|
||||
if (isCheckingForUpdate_) {
|
||||
autoUpdateLogger_.info('checkForUpdates: Skipping check because it is already running');
|
||||
@@ -126,16 +138,21 @@ function checkForUpdates(inBackground, window, logFilePath, options) {
|
||||
buttons: [_('OK')],
|
||||
});
|
||||
} else {
|
||||
const releaseNotes = release.notes.trim() ? `\n\n${release.notes.trim()}` : '';
|
||||
const fullReleaseNotes = release.notes.trim() ? `\n\n${release.notes.trim()}` : '';
|
||||
const MAX_RELEASE_NOTES_LENGTH = 1000;
|
||||
const truncateReleaseNotes = fullReleaseNotes.length > MAX_RELEASE_NOTES_LENGTH;
|
||||
const releaseNotes = truncateReleaseNotes ? truncateText(fullReleaseNotes, MAX_RELEASE_NOTES_LENGTH) : fullReleaseNotes;
|
||||
|
||||
const newVersionString = release.prerelease ? _('%s (pre-release)', release.version) : release.version;
|
||||
|
||||
const buttonIndex = dialog.showMessageBox(parentWindow_, {
|
||||
type: 'info',
|
||||
message: `${_('An update is available, do you want to download it now?')}\n\n${_('Your version: %s', packageInfo.version)}\n${_('New version: %s', newVersionString)}${releaseNotes}`,
|
||||
buttons: [_('Yes'), _('No')],
|
||||
buttons: [_('Yes'), _('No')].concat(truncateReleaseNotes ? [_('Full Release Notes')] : []),
|
||||
});
|
||||
|
||||
if (buttonIndex === 0) require('electron').shell.openExternal(release.downloadUrl ? release.downloadUrl : release.pageUrl);
|
||||
if (buttonIndex === 2) require('electron').shell.openExternal(release.pageUrl);
|
||||
}
|
||||
}).catch(error => {
|
||||
autoUpdateLogger_.error(error);
|
||||
|
@@ -22,8 +22,7 @@ let hash;
|
||||
try {
|
||||
branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
|
||||
hash = execSync('git log --pretty="%h" -1').toString().trim();
|
||||
}
|
||||
catch(err) {
|
||||
} catch (err) {
|
||||
console.warn('Could not get git info', err);
|
||||
}
|
||||
if (typeof branch !== 'undefined' && typeof hash !== 'undefined') {
|
||||
|
@@ -28,7 +28,7 @@ function ConfigMenuBar(props) {
|
||||
key={section.name}
|
||||
iconName={Setting.sectionNameToIcon(section.name)}
|
||||
label={Setting.sectionNameToLabel(section.name)}
|
||||
onClick={() => { props.onSelectionChange({ section: section });}}
|
||||
onClick={() => { props.onSelectionChange({ section: section }); }}
|
||||
/>);
|
||||
}
|
||||
|
||||
|
@@ -478,7 +478,7 @@ class ConfigScreenComponent extends React.Component {
|
||||
borderTopColor: theme.dividerColor,
|
||||
};
|
||||
|
||||
const screenComp = this.state.screenName ? <div style={{overflow: 'scroll', flex:1}}>{this.screenFromName(this.state.screenName)}</div> : null;
|
||||
const screenComp = this.state.screenName ? <div style={{overflow: 'scroll', flex: 1}}>{this.screenFromName(this.state.screenName)}</div> : null;
|
||||
|
||||
if (screenComp) containerStyle.display = 'none';
|
||||
|
||||
|
@@ -161,11 +161,13 @@ class HeaderComponent extends React.Component {
|
||||
const inputStyle = {
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
marginLeft: 10,
|
||||
paddingLeft: 6,
|
||||
paddingRight: 6,
|
||||
paddingTop: 1, // vertical alignment with buttons
|
||||
paddingBottom: 0, // vertical alignment with buttons
|
||||
height: style.fontSize * 2,
|
||||
width: 300,
|
||||
color: style.color,
|
||||
fontSize: style.fontSize,
|
||||
fontFamily: style.fontFamily,
|
||||
|
@@ -245,7 +245,16 @@ class MainScreenComponent extends React.Component {
|
||||
} else if (command.name === 'toggleSidebar') {
|
||||
this.toggleSidebar();
|
||||
} else if (command.name === 'showModalMessage') {
|
||||
this.setState({ modalLayer: { visible: true, message: command.message } });
|
||||
this.setState({
|
||||
modalLayer: {
|
||||
visible: true,
|
||||
message:
|
||||
<div className="modal-message">
|
||||
<div id="loading-animation" />
|
||||
<div className="text">{command.message}</div>
|
||||
</div>,
|
||||
},
|
||||
});
|
||||
} else if (command.name === 'hideModalMessage') {
|
||||
this.setState({ modalLayer: { visible: false, message: '' } });
|
||||
} else if (command.name === 'editAlarm') {
|
||||
|
@@ -106,7 +106,7 @@ class NotePropertiesDialog extends React.Component {
|
||||
|
||||
this.styles_.controlBox = {
|
||||
marginBottom: '1em',
|
||||
color: 'black', //This will apply for the calendar
|
||||
color: 'black', // This will apply for the calendar
|
||||
};
|
||||
|
||||
this.styles_.button = {
|
||||
|
@@ -48,6 +48,7 @@ require('brace/theme/chrome');
|
||||
require('brace/theme/solarized_light');
|
||||
require('brace/theme/solarized_dark');
|
||||
require('brace/theme/twilight');
|
||||
require('brace/theme/dracula');
|
||||
|
||||
const NOTE_TAG_BAR_FEATURE_ENABLED = false;
|
||||
|
||||
@@ -690,10 +691,13 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
async noteRevisionViewer_onBack() {
|
||||
this.setState({ showRevisions: false });
|
||||
|
||||
this.lastSetHtml_ = '';
|
||||
this.scheduleReloadNote(this.props);
|
||||
// When coming back from the revision viewer, the webview has been
|
||||
// unmounted so will need to reload. We set webviewReady to false
|
||||
// to make sure everything is reloaded as expected.
|
||||
this.setState({ showRevisions: false, webviewReady: false }, () => {
|
||||
this.lastSetHtml_ = '';
|
||||
this.scheduleReloadNote(this.props);
|
||||
});
|
||||
}
|
||||
|
||||
title_changeText(event) {
|
||||
@@ -1209,7 +1213,7 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
setTimeout(() => {
|
||||
if (target === 'pdf') {
|
||||
this.webviewRef_.current.wrappedInstance.printToPDF({ printBackground: true }, (error, data) => {
|
||||
this.webviewRef_.current.wrappedInstance.printToPDF({ printBackground: true, pageSize: Setting.value('export.pdfPageSize'), landscape: Setting.value('export.pdfPageOrientation') === 'landscape' }, (error, data) => {
|
||||
restoreSettings();
|
||||
|
||||
if (error) {
|
||||
@@ -1369,9 +1373,16 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
const r = this.selectionRange_;
|
||||
|
||||
// Because some insertion strings will have newlines, we'll need to account for them
|
||||
const str1Split = string1.split(/\r?\n/);
|
||||
|
||||
// Add the number of newlines to the row
|
||||
// and add the length of the final line to the column (for strings with no newlines this is the string length)
|
||||
const newRange = {
|
||||
start: { row: r.start.row, column: r.start.column + string1.length },
|
||||
end: { row: r.end.row, column: r.end.column + string1.length },
|
||||
start: { row: r.start.row + str1Split.length - 1,
|
||||
column: r.start.column + str1Split[str1Split.length - 1].length },
|
||||
end: { row: r.end.row + str1Split.length - 1,
|
||||
column: r.end.column + str1Split[str1Split.length - 1].length },
|
||||
};
|
||||
|
||||
if (replacementText) {
|
||||
@@ -1444,7 +1455,18 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
commandTextCode() {
|
||||
this.wrapSelectionWithStrings('`', '`');
|
||||
const selection = this.textOffsetSelection();
|
||||
let string = this.state.note.body.substr(selection.start, selection.end - selection.start);
|
||||
|
||||
// Look for newlines
|
||||
let match = string.match(/\r?\n/);
|
||||
|
||||
if (match && match.length > 0) {
|
||||
// Follow the same newline style
|
||||
this.wrapSelectionWithStrings(`\`\`\`${match[0]}`, `${match[0]}\`\`\``);
|
||||
} else {
|
||||
this.wrapSelectionWithStrings('`', '`');
|
||||
}
|
||||
}
|
||||
|
||||
commandTemplate(value) {
|
||||
@@ -1524,7 +1546,7 @@ class NoteTextComponent extends React.Component {
|
||||
menu.popup(bridge().window());
|
||||
}
|
||||
|
||||
createToolbarItems(note) {
|
||||
createToolbarItems(note, editorIsVisible) {
|
||||
const toolbarItems = [];
|
||||
if (note && this.state.folder && ['Search', 'Tag'].includes(this.props.notesParentType)) {
|
||||
toolbarItems.push({
|
||||
@@ -1559,7 +1581,7 @@ class NoteTextComponent extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
if (note.markup_language === Note.MARKUP_LANGUAGE_MARKDOWN) {
|
||||
if (note.markup_language === Note.MARKUP_LANGUAGE_MARKDOWN && editorIsVisible) {
|
||||
toolbarItems.push({
|
||||
tooltip: _('Bold'),
|
||||
iconName: 'fa-bold',
|
||||
@@ -1821,7 +1843,7 @@ class NoteTextComponent extends React.Component {
|
||||
if (this.props.selectedNoteIds.length > 1) {
|
||||
return this.renderMultiNotes(rootStyle);
|
||||
} else if (!note || !!note.encryption_applied) {
|
||||
//|| (note && !this.props.newNote && this.props.noteId && note.id !== this.props.noteId)) { // note.id !== props.noteId is when the note has not been loaded yet, and the previous one is still in the state
|
||||
// || (note && !this.props.newNote && this.props.noteId && note.id !== this.props.noteId)) { // note.id !== props.noteId is when the note has not been loaded yet, and the previous one is still in the state
|
||||
return this.renderNoNotes(rootStyle);
|
||||
}
|
||||
|
||||
@@ -1961,7 +1983,8 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const toolbarItems = this.createToolbarItems(note);
|
||||
const editorIsVisible = visiblePanes.indexOf('editor') >= 0;
|
||||
const toolbarItems = this.createToolbarItems(note, editorIsVisible);
|
||||
|
||||
const toolbar = <Toolbar style={toolbarStyle} items={toolbarItems} />;
|
||||
|
||||
|
@@ -267,9 +267,11 @@ class SideBarComponent extends React.Component {
|
||||
if (!itemId || !itemType) throw new Error('No data on element');
|
||||
|
||||
let deleteMessage = '';
|
||||
let buttonLabel = _('Remove');
|
||||
if (itemType === BaseModel.TYPE_FOLDER) {
|
||||
const folder = await Folder.load(itemId);
|
||||
deleteMessage = _('Delete notebook "%s"?\n\nAll notes and sub-notebooks within this notebook will also be deleted.', substrWithEllipsis(folder.title, 0, 32));
|
||||
buttonLabel = _('Delete');
|
||||
} else if (itemType === BaseModel.TYPE_TAG) {
|
||||
const tag = await Tag.load(itemId);
|
||||
deleteMessage = _('Remove tag "%s" from all notes?', substrWithEllipsis(tag.title, 0, 32));
|
||||
@@ -286,9 +288,12 @@ class SideBarComponent extends React.Component {
|
||||
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: _('Delete'),
|
||||
label: buttonLabel,
|
||||
click: async () => {
|
||||
const ok = bridge().showConfirmMessageBox(deleteMessage);
|
||||
const ok = bridge().showConfirmMessageBox(deleteMessage, {
|
||||
buttons: [buttonLabel, _('Cancel')],
|
||||
defaultId: 1,
|
||||
});
|
||||
if (!ok) return;
|
||||
|
||||
if (itemType === BaseModel.TYPE_FOLDER) {
|
||||
|
338
ElectronClient/app/package-lock.json
generated
338
ElectronClient/app/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.0.169",
|
||||
"version": "1.0.170",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -144,9 +144,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"abab": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
|
||||
"integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w=="
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.2.tgz",
|
||||
"integrity": "sha512-2scffjvioEmNz0OyDSLGWDfKCVwaKc6l9Pm9kOIREU13ClXZvHpg/nRL5xyjSSSLhOnXqft2HpsAzNEEA8cFFg=="
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
@@ -154,17 +154,24 @@
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"acorn": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz",
|
||||
"integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw=="
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
|
||||
},
|
||||
"acorn-globals": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz",
|
||||
"integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==",
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
|
||||
"integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
|
||||
"requires": {
|
||||
"acorn": "^6.0.1",
|
||||
"acorn-walk": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
|
||||
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"acorn-walk": {
|
||||
@@ -399,6 +406,11 @@
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"astral-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
|
||||
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg=="
|
||||
},
|
||||
"async-each": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
|
||||
@@ -413,9 +425,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
},
|
||||
"async-mutex": {
|
||||
"version": "0.1.3",
|
||||
@@ -1955,6 +1967,50 @@
|
||||
"integrity": "sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"cli-truncate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.0.0.tgz",
|
||||
"integrity": "sha512-C4hp+8GCIFVsUUiXcw+ce+7wexVWImw8rQrgMBFsqerx9LvvcGlwm6sMjQYAEmV/Xb87xc1b5Ttx505MSpZVqg==",
|
||||
"requires": {
|
||||
"slice-ansi": "^2.1.0",
|
||||
"string-width": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz",
|
||||
"integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^5.2.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"requires": {
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
||||
@@ -2019,7 +2075,6 @@
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
@@ -2027,8 +2082,7 @@
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.3.3",
|
||||
@@ -2222,11 +2276,11 @@
|
||||
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
|
||||
},
|
||||
"cssstyle": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.3.0.tgz",
|
||||
"integrity": "sha512-wXsoRfsRfsLVNaVzoKdqvEmK/5PFaEXNspVT22Ots6K/cnJdpoDKuQFw+qlMiXnmaif1OgeC466X1zISgAOcGg==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz",
|
||||
"integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==",
|
||||
"requires": {
|
||||
"cssom": "~0.3.6"
|
||||
"cssom": "0.3.x"
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
@@ -2264,6 +2318,18 @@
|
||||
"abab": "^2.0.0",
|
||||
"whatwg-mimetype": "^2.2.0",
|
||||
"whatwg-url": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"whatwg-url": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz",
|
||||
"integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==",
|
||||
"requires": {
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"tr46": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
@@ -2540,25 +2606,26 @@
|
||||
}
|
||||
},
|
||||
"electron-context-menu": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-context-menu/-/electron-context-menu-0.9.1.tgz",
|
||||
"integrity": "sha1-7U3yDAgEkcPJlqv8s2MVmUajgFg=",
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-context-menu/-/electron-context-menu-0.15.0.tgz",
|
||||
"integrity": "sha512-XLdtbX90NPkWycG3IzwtCmfX4ggu+lofNOW1nVRStb+ScFs49WTourW1k77Z4DTyThR3gUHg3UPXVBMbW1gNsg==",
|
||||
"requires": {
|
||||
"cli-truncate": "^2.0.0",
|
||||
"electron-dl": "^1.2.0",
|
||||
"electron-is-dev": "^0.1.1"
|
||||
"electron-is-dev": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-is-dev": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.1.2.tgz",
|
||||
"integrity": "sha1-ihBD4ys6HaHD9VPc4oznZCRhZ+M="
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-1.1.0.tgz",
|
||||
"integrity": "sha512-Z1qA/1oHNowGtSBIcWk0pcLEqYT/j+13xUw/MYOrBUOL4X7VN0i0KCTf5SqyvMPmW5pSPKbo28wkxMxzZ20YnQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron-dl": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-dl/-/electron-dl-1.12.0.tgz",
|
||||
"integrity": "sha512-UMc2CL45Ybpvu66LDPYzwmDRmYK4Ivz+wdnTM0eXcNMztvQwhixAk2UPme1c7McqG8bAlKEkQpZn3epmQy4EWg==",
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-dl/-/electron-dl-1.14.0.tgz",
|
||||
"integrity": "sha512-4okyei42a1mLsvLK7hLrIfd20EQzB18nIlLTwBV992aMSmTGLUEFRTmO1MfSslGNrzD8nuPuy1l/VxO8so4lig==",
|
||||
"requires": {
|
||||
"ext-name": "^5.0.0",
|
||||
"pupa": "^1.0.0",
|
||||
@@ -2955,9 +3022,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"escodegen": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz",
|
||||
"integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==",
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz",
|
||||
"integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==",
|
||||
"requires": {
|
||||
"esprima": "^3.1.3",
|
||||
"estraverse": "^4.2.0",
|
||||
@@ -2985,9 +3052,9 @@
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"estraverse": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
|
||||
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.2",
|
||||
@@ -3312,9 +3379,9 @@
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz",
|
||||
"integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.0.tgz",
|
||||
"integrity": "sha512-+iXhW3LuDQsno8dOIrCIT/CBjeBWuP7PXe8w9shnj9Lebny/Gx1ZjVBYwexLz36Ri2jKuXMNpV6CYNh8lHHgrQ==",
|
||||
"optional": true
|
||||
},
|
||||
"fullstore": {
|
||||
@@ -3908,6 +3975,11 @@
|
||||
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
|
||||
"dev": true
|
||||
},
|
||||
"is-wsl": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz",
|
||||
"integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog=="
|
||||
},
|
||||
"is2": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/is2/-/is2-0.0.9.tgz",
|
||||
@@ -3947,82 +4019,19 @@
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"joplin-turndown": {
|
||||
"version": "4.0.17",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.17.tgz",
|
||||
"integrity": "sha512-57mw92ZOKoR77YBLUkauN1xNq1xlxOm2KaPty/jlYrkEyGotUBBvq46a6wXh6d3aM4CccGuwymSge18/9IoB3A==",
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.18.tgz",
|
||||
"integrity": "sha512-YD0pkj2a7+XjjNNI1X9ZIwYthFwNsswvO4gl5aAoWdwJj5m8tunnoSyVenvqleXzAcaURIi/q9EOAQ1jw7xDiQ==",
|
||||
"requires": {
|
||||
"css": "^2.2.4",
|
||||
"html-entities": "^1.2.1",
|
||||
"jsdom": "^11.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
|
||||
},
|
||||
"jsdom": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
|
||||
"integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
|
||||
"requires": {
|
||||
"abab": "^2.0.0",
|
||||
"acorn": "^5.5.3",
|
||||
"acorn-globals": "^4.1.0",
|
||||
"array-equal": "^1.0.0",
|
||||
"cssom": ">= 0.3.2 < 0.4.0",
|
||||
"cssstyle": "^1.0.0",
|
||||
"data-urls": "^1.0.0",
|
||||
"domexception": "^1.0.1",
|
||||
"escodegen": "^1.9.1",
|
||||
"html-encoding-sniffer": "^1.0.2",
|
||||
"left-pad": "^1.3.0",
|
||||
"nwsapi": "^2.0.7",
|
||||
"parse5": "4.0.0",
|
||||
"pn": "^1.1.0",
|
||||
"request": "^2.87.0",
|
||||
"request-promise-native": "^1.0.5",
|
||||
"sax": "^1.2.4",
|
||||
"symbol-tree": "^3.2.2",
|
||||
"tough-cookie": "^2.3.4",
|
||||
"w3c-hr-time": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2",
|
||||
"whatwg-encoding": "^1.0.3",
|
||||
"whatwg-mimetype": "^2.1.0",
|
||||
"whatwg-url": "^6.4.1",
|
||||
"ws": "^5.2.0",
|
||||
"xml-name-validator": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"parse5": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
|
||||
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
|
||||
"integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
|
||||
"requires": {
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"tr46": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"joplin-turndown-plugin-gfm": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown-plugin-gfm/-/joplin-turndown-plugin-gfm-1.0.9.tgz",
|
||||
"integrity": "sha512-SOa/Uiy3nyoBGtHqFe+TBg10UTIOzzcUUzNhx2MyR4Z0vbKL3enGggGypig1t7G5uHwv5j+NhooRuM619Zk0bw=="
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown-plugin-gfm/-/joplin-turndown-plugin-gfm-1.0.11.tgz",
|
||||
"integrity": "sha512-S2I+VCTqIhpWKKkPHsyJ5rdll9H/JjMXoBVClRX1TnphcmrSxufevdoXWWVgLncdXpSSiuoifCXgFZy3ueVElg=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "3.0.2",
|
||||
@@ -4045,6 +4054,39 @@
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
},
|
||||
"jsdom": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
|
||||
"integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
|
||||
"requires": {
|
||||
"abab": "^2.0.0",
|
||||
"acorn": "^5.5.3",
|
||||
"acorn-globals": "^4.1.0",
|
||||
"array-equal": "^1.0.0",
|
||||
"cssom": ">= 0.3.2 < 0.4.0",
|
||||
"cssstyle": "^1.0.0",
|
||||
"data-urls": "^1.0.0",
|
||||
"domexception": "^1.0.1",
|
||||
"escodegen": "^1.9.1",
|
||||
"html-encoding-sniffer": "^1.0.2",
|
||||
"left-pad": "^1.3.0",
|
||||
"nwsapi": "^2.0.7",
|
||||
"parse5": "4.0.0",
|
||||
"pn": "^1.1.0",
|
||||
"request": "^2.87.0",
|
||||
"request-promise-native": "^1.0.5",
|
||||
"sax": "^1.2.4",
|
||||
"symbol-tree": "^3.2.2",
|
||||
"tough-cookie": "^2.3.4",
|
||||
"w3c-hr-time": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2",
|
||||
"whatwg-encoding": "^1.0.3",
|
||||
"whatwg-mimetype": "^2.1.0",
|
||||
"whatwg-url": "^6.4.1",
|
||||
"ws": "^5.2.0",
|
||||
"xml-name-validator": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"jsesc": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
|
||||
@@ -4515,15 +4557,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
|
||||
"integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.34.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.34.0.tgz",
|
||||
"integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o="
|
||||
"version": "1.42.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
|
||||
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.18",
|
||||
@@ -4778,14 +4815,22 @@
|
||||
}
|
||||
},
|
||||
"node-notifier": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz",
|
||||
"integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz",
|
||||
"integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==",
|
||||
"requires": {
|
||||
"growly": "^1.3.0",
|
||||
"semver": "^5.4.1",
|
||||
"is-wsl": "^2.1.1",
|
||||
"semver": "^6.3.0",
|
||||
"shellwords": "^0.1.1",
|
||||
"which": "^1.3.0"
|
||||
"which": "^1.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-pre-gyp": {
|
||||
@@ -5225,6 +5270,11 @@
|
||||
"error-ex": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"parse5": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
|
||||
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
@@ -5899,13 +5949,6 @@
|
||||
"integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.14",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
|
||||
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"request-promise-native": {
|
||||
@@ -6114,6 +6157,31 @@
|
||||
"integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
|
||||
"dev": true
|
||||
},
|
||||
"slice-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
|
||||
"integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.0",
|
||||
"astral-regex": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"smalltalk": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/smalltalk/-/smalltalk-2.5.1.tgz",
|
||||
@@ -6901,9 +6969,9 @@
|
||||
"integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz",
|
||||
"integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
|
||||
"integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
|
||||
"requires": {
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"tr46": "^1.0.1",
|
||||
@@ -7005,6 +7073,14 @@
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"xdg-basedir": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.0.169",
|
||||
"version": "1.0.170",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@@ -91,7 +91,7 @@
|
||||
"compare-versions": "^3.2.1",
|
||||
"diacritics": "^1.3.0",
|
||||
"diff-match-patch": "^1.0.4",
|
||||
"electron-context-menu": "^0.9.1",
|
||||
"electron-context-menu": "^0.15.0",
|
||||
"electron-is-dev": "^0.3.0",
|
||||
"electron-window-state": "^4.1.1",
|
||||
"es6-promise-pool": "^2.5.0",
|
||||
@@ -104,8 +104,8 @@
|
||||
"html-entities": "^1.2.1",
|
||||
"html-minifier": "^4.0.0",
|
||||
"image-type": "^3.0.0",
|
||||
"joplin-turndown": "^4.0.17",
|
||||
"joplin-turndown-plugin-gfm": "^1.0.9",
|
||||
"joplin-turndown": "^4.0.18",
|
||||
"joplin-turndown-plugin-gfm": "^1.0.11",
|
||||
"jssha": "^2.3.1",
|
||||
"katex": "^0.10.0",
|
||||
"levenshtein": "^1.0.5",
|
||||
@@ -125,12 +125,11 @@
|
||||
"markdown-it-sup": "^1.0.0",
|
||||
"markdown-it-toc-done-right": "^4.0.2",
|
||||
"md5": "^2.2.1",
|
||||
"mime": "^2.3.1",
|
||||
"moment": "^2.22.2",
|
||||
"multiparty": "^4.2.1",
|
||||
"mustache": "^3.0.1",
|
||||
"node-fetch": "^1.7.3",
|
||||
"node-notifier": "^5.2.1",
|
||||
"node-notifier": "^6.0.0",
|
||||
"promise": "^8.0.1",
|
||||
"query-string": "^5.1.1",
|
||||
"react": "^16.4.0",
|
||||
|
@@ -60,7 +60,7 @@ class Dialog extends React.PureComponent {
|
||||
this.styles_[this.props.theme] = {
|
||||
dialogBox: Object.assign({}, theme.dialogBox, { minWidth: '50%', maxWidth: '50%' }),
|
||||
input: Object.assign({}, theme.inputStyle, { flex: 1 }),
|
||||
row: {overflow: 'hidden', height:itemHeight, display: 'flex', justifyContent: 'center', flexDirection: 'column', paddingLeft: 10, paddingRight: 10},
|
||||
row: {overflow: 'hidden', height: itemHeight, display: 'flex', justifyContent: 'center', flexDirection: 'column', paddingLeft: 10, paddingRight: 10},
|
||||
help: Object.assign({}, theme.textStyle, { marginBottom: 10 }),
|
||||
inputHelpWrapper: {display: 'flex', flexDirection: 'row', alignItems: 'center'},
|
||||
};
|
||||
|
@@ -149,3 +149,30 @@ a {
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
.modal-message {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: grey;
|
||||
font-size: 1.2em;
|
||||
margin: 40px 20px;
|
||||
}
|
||||
|
||||
.modal-message #loading-animation {
|
||||
margin-right: 20px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 5px solid lightgrey;
|
||||
border-top: 4px solid white;
|
||||
border-radius: 50%;
|
||||
transition-property: transform;
|
||||
animation-name: rotate;
|
||||
animation-duration: 1.2s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {transform: rotate(0deg);}
|
||||
to {transform: rotate(360deg);}
|
||||
}
|
||||
|
@@ -96,7 +96,7 @@ const lightStyle = {
|
||||
|
||||
warningBackgroundColor: '#FFD08D',
|
||||
|
||||
htmlColor:'#222222',
|
||||
htmlColor: '#222222',
|
||||
htmlBackgroundColor: 'white',
|
||||
htmlDividerColor: 'rgb(230,230,230)',
|
||||
htmlLinkColor: 'rgb(80,130,190)',
|
||||
@@ -223,6 +223,43 @@ const solarizedDarkStyle = {
|
||||
codeThemeCss: 'atom-one-dark-reasonable.css',
|
||||
};
|
||||
|
||||
const draculaStyle = {
|
||||
backgroundColor: '#282a36',
|
||||
backgroundColorTransparent: 'rgba(40, 42, 54, 0.9)',
|
||||
oddBackgroundColor: '#282a36',
|
||||
color: '#f8f8f2', // For regular text
|
||||
colorError: '#ff5555',
|
||||
colorWarn: '#ffb86c',
|
||||
colorFaded: '#6272a4', // For less important text;
|
||||
colorBright: '#50fa7b', // For important text;
|
||||
dividerColor: '#bd93f9',
|
||||
selectedColor: '#44475a',
|
||||
urlColor: '#8be9fd',
|
||||
|
||||
backgroundColor2: '#21222C',
|
||||
depthColor: 'rgb(200, 200, 200, OPACITY)',
|
||||
color2: '#bd93f9',
|
||||
selectedColor2: '#44475a',
|
||||
colorError2: '#ff5555',
|
||||
|
||||
raisedBackgroundColor: '#44475a',
|
||||
raisedColor: '#bd93f9',
|
||||
|
||||
warningBackgroundColor: '#ffb86c',
|
||||
|
||||
htmlColor: '#f8f8f2',
|
||||
htmlBackgroundColor: '#282a36',
|
||||
htmlDividerColor: '#f8f8f2',
|
||||
htmlLinkColor: '#8be9fd',
|
||||
htmlTableBackgroundColor: '#6272a4',
|
||||
htmlCodeBackgroundColor: '#44475a',
|
||||
htmlCodeBorderColor: '#f8f8f2',
|
||||
htmlCodeColor: '#50fa7b',
|
||||
|
||||
editorTheme: 'dracula',
|
||||
codeThemeCss: 'atom-one-dark-reasonable.css',
|
||||
};
|
||||
|
||||
function addExtraStyles(style) {
|
||||
style.tagStyle = {
|
||||
fontSize: style.fontSize,
|
||||
@@ -349,7 +386,7 @@ function themeStyle(theme) {
|
||||
|
||||
// For WebView - must correspond to the properties above
|
||||
htmlFontSize: `${Math.round(15 * zoomRatio)}px`,
|
||||
htmlLineHeight: '1.6em', //Math.round(20 * zoomRatio) + 'px'
|
||||
htmlLineHeight: '1.6em', // Math.round(20 * zoomRatio) + 'px'
|
||||
|
||||
htmlCodeFontSize: '.9em',
|
||||
};
|
||||
@@ -368,6 +405,8 @@ function themeStyle(theme) {
|
||||
output = Object.assign({}, output, solarizedLightStyle);
|
||||
} else if (theme == Setting.THEME_SOLARIZED_DARK) {
|
||||
output = Object.assign({}, output, solarizedDarkStyle);
|
||||
} else if (theme == Setting.THEME_DRACULA) {
|
||||
output = Object.assign({}, output, draculaStyle);
|
||||
}
|
||||
|
||||
// Note: All the theme specific things should go in addExtraStyles
|
||||
|
@@ -1,14 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
# Title
|
||||
echo " _ _ _ "
|
||||
echo " | | ___ _ __ | (_)_ __ "
|
||||
echo " _ | |/ _ \| '_ \| | | '_ \ "
|
||||
echo "| |_| | (_) | |_) | | | | | |"
|
||||
echo " \___/ \___/| .__/|_|_|_| |_|"
|
||||
echo " |_|"
|
||||
echo ""
|
||||
echo "Linux Installer and Updater"
|
||||
|
||||
#-----------------------------------------------------
|
||||
# Variables
|
||||
@@ -16,8 +7,20 @@ echo "Linux Installer and Updater"
|
||||
COLOR_RED=`tput setaf 1`
|
||||
COLOR_GREEN=`tput setaf 2`
|
||||
COLOR_RESET=`tput sgr0`
|
||||
SILENT=false
|
||||
|
||||
# Check and warn if running as root.
|
||||
print() {
|
||||
if [[ "$SILENT" == false ]] ; then
|
||||
echo $1
|
||||
fi
|
||||
}
|
||||
|
||||
#-----------------------------------------------------
|
||||
# ARGUMENTS
|
||||
#-----------------------------------------------------
|
||||
|
||||
# --allow-root
|
||||
## Check and warn if running as root.
|
||||
if [[ $EUID = 0 ]] ; then
|
||||
if [[ $* != *--allow-root* ]] ; then
|
||||
echo "${COLOR_RED}It is not recommended (nor necessary) to run this script as root. To do so anyway, please use '--allow-root'${COLOR_RESET}"
|
||||
@@ -25,53 +28,73 @@ if [[ $EUID = 0 ]] ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# --silent
|
||||
## Mutes messages by console
|
||||
if [[ $* == *--silent* ]] ; then
|
||||
SILENT=true
|
||||
fi
|
||||
|
||||
#-----------------------------------------------------
|
||||
# START
|
||||
#-----------------------------------------------------
|
||||
|
||||
# Title
|
||||
print " _ _ _ "
|
||||
print " | | ___ _ __ | (_)_ __ "
|
||||
print " _ | |/ _ \| '_ \| | | '_ \ "
|
||||
print "| |_| | (_) | |_) | | | | | |"
|
||||
print " \___/ \___/| .__/|_|_|_| |_|"
|
||||
print " |_|"
|
||||
print ""
|
||||
print "Linux Installer and Updater"
|
||||
|
||||
#-----------------------------------------------------
|
||||
# Download Joplin
|
||||
#-----------------------------------------------------
|
||||
|
||||
# Get the latest version to download
|
||||
version=$(wget -qO - "https://api.github.com/repos/laurent22/joplin/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")')
|
||||
RELEASE_VERSION=$(wget -qO - "https://api.github.com/repos/laurent22/joplin/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")')
|
||||
|
||||
# Check if it's in the latest version
|
||||
if [[ ! -e ~/.joplin/VERSION ]] || [[ $(< ~/.joplin/VERSION) != "$version" ]]; then
|
||||
if [[ ! -e ~/.joplin/VERSION ]] || [[ $(< ~/.joplin/VERSION) != "$RELEASE_VERSION" ]]; then
|
||||
|
||||
echo 'Downloading Joplin...'
|
||||
print 'Downloading Joplin...'
|
||||
# Delete previous version (in future versions joplin.desktop shouldn't exist)
|
||||
rm -f ~/.joplin/*.AppImage ~/.local/share/applications/joplin.desktop ~/.joplin/VERSION
|
||||
|
||||
|
||||
# Creates the folder where the binary will be stored
|
||||
mkdir -p ~/.joplin/
|
||||
|
||||
|
||||
# Download the latest version
|
||||
wget -nv --show-progress -O ~/.joplin/Joplin.AppImage https://github.com/laurent22/joplin/releases/download/v$version/Joplin-$version-x86_64.AppImage
|
||||
|
||||
wget -nv --show-progress -O ~/.joplin/Joplin.AppImage https://github.com/laurent22/joplin/releases/download/v$RELEASE_VERSION/Joplin-$RELEASE_VERSION-x86_64.AppImage
|
||||
|
||||
# Gives execution privileges
|
||||
chmod +x ~/.joplin/Joplin.AppImage
|
||||
|
||||
echo "${COLOR_GREEN}OK${COLOR_RESET}"
|
||||
|
||||
|
||||
print "${COLOR_GREEN}OK${COLOR_RESET}"
|
||||
|
||||
#-----------------------------------------------------
|
||||
# Icon
|
||||
#-----------------------------------------------------
|
||||
|
||||
|
||||
# Download icon
|
||||
echo 'Downloading icon...'
|
||||
print 'Downloading icon...'
|
||||
mkdir -p ~/.local/share/icons/hicolor/512x512/apps
|
||||
wget -nv -O ~/.local/share/icons/hicolor/512x512/apps/joplin.png https://joplinapp.org/images/Icon512.png
|
||||
echo "${COLOR_GREEN}OK${COLOR_RESET}"
|
||||
|
||||
# Detect desktop environment
|
||||
print "${COLOR_GREEN}OK${COLOR_RESET}"
|
||||
|
||||
# Detect desktop environment
|
||||
if [ "$XDG_CURRENT_DESKTOP" = "" ]
|
||||
then
|
||||
desktop=$(echo "$XDG_DATA_DIRS" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
|
||||
DESKTOP=$(echo "$XDG_DATA_DIRS" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
|
||||
else
|
||||
desktop=$XDG_CURRENT_DESKTOP
|
||||
DESKTOP=$XDG_CURRENT_DESKTOP
|
||||
fi
|
||||
desktop=${desktop,,} # convert to lower case
|
||||
DESKTOP=${DESKTOP,,} # convert to lower case
|
||||
|
||||
# Create icon for Gnome
|
||||
echo 'Create Desktop icon.'
|
||||
if [[ $desktop =~ .*gnome.*|.*kde.*|.*xfce.*|.*mate.*|.*lxqt.*|.*unity.*|.*x-cinnamon.*|.*deepin.* ]]
|
||||
if [[ $DESKTOP =~ .*gnome.*|.*kde.*|.*xfce.*|.*mate.*|.*lxqt.*|.*unity.*|.*x-cinnamon.*|.*deepin.* ]]
|
||||
then
|
||||
: "${TMPDIR:=/tmp}"
|
||||
# This command extracts to squashfs-root by default and can't be changed...
|
||||
@@ -84,22 +107,23 @@ if [[ ! -e ~/.joplin/VERSION ]] || [[ $(< ~/.joplin/VERSION) != "$version" ]]; t
|
||||
|
||||
# On some systems this directory doesn't exist by default
|
||||
mkdir -p ~/.local/share/applications
|
||||
echo -e "[Desktop Entry]\nEncoding=UTF-8\nName=Joplin\nComment=Joplin for Desktop\nExec=/home/$USER/.joplin/Joplin.AppImage\nIcon=joplin\nStartupWMClass=Joplin\nType=Application\nCategories=Application;\n$APPIMAGE_VERSION" >> ~/.local/share/applications/appimagekit-joplin.desktop
|
||||
echo "${COLOR_GREEN}OK${COLOR_RESET}"
|
||||
echo -e "[Desktop Entry]\nEncoding=UTF-8\nName=Joplin\nComment=Joplin for Desktop\nExec=/home/$USER/.joplin/Joplin.AppImage\nIcon=joplin\nStartupWMClass=Joplin\nType=Application\nCategories=Office;\n$APPIMAGE_VERSION" >> ~/.local/share/applications/appimagekit-joplin.desktop
|
||||
print "${COLOR_GREEN}OK${COLOR_RESET}"
|
||||
else
|
||||
echo "${COLOR_RED}NOT DONE${COLOR_RESET}"
|
||||
print "${COLOR_RED}NOT DONE${COLOR_RESET}"
|
||||
fi
|
||||
|
||||
|
||||
#-----------------------------------------------------
|
||||
# Finish
|
||||
#-----------------------------------------------------
|
||||
|
||||
# Informs the user that it has been installed and cleans variables
|
||||
echo "${COLOR_GREEN}Joplin version${COLOR_RESET}" $version "${COLOR_GREEN}installed.${COLOR_RESET}"
|
||||
print "${COLOR_GREEN}Joplin version${COLOR_RESET}" $RELEASE_VERSION "${COLOR_GREEN}installed.${COLOR_RESET}"
|
||||
|
||||
# Add version
|
||||
echo $version > ~/.joplin/VERSION
|
||||
echo $RELEASE_VERSION > ~/.joplin/VERSION
|
||||
else
|
||||
echo "${COLOR_GREEN}You already have the latest version${COLOR_RESET}" $version "${COLOR_GREEN}installed.${COLOR_RESET}"
|
||||
print "${COLOR_GREEN}You already have the latest version${COLOR_RESET}" $version "${COLOR_GREEN}installed.${COLOR_RESET}"
|
||||
fi
|
||||
echo 'Bye!'
|
||||
unset version
|
||||
|
||||
# Goodbye
|
||||
print 'Bye!'
|
||||
|
108
README.md
108
README.md
@@ -2,6 +2,18 @@
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=E8JMYD2LQ8MMA&lc=GB&item_name=Joplin+Development¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) [](https://www.patreon.com/joplin)
|
||||
|
||||
* * *
|
||||
[Hacktoberfest 🎃](https://hacktoberfest.digitalocean.com/) is back this year again for our great pleasure ^^
|
||||
|
||||
To participate go to [https://hacktoberfest.digitalocean.com/](https://hacktoberfest.digitalocean.com/), log in (with you GitHub account) and you are ready to get in. Next, go dive into the Joplin issues list labelled "[Hacktoberfest](https://github.com/laurent22/joplin/labels/hacktoberfest)"
|
||||
|
||||
Start hacking, submit the PR from the 1st of October, not before.
|
||||
|
||||
We hope you will enjoy that event this year again like the previous one 🎃🎉
|
||||
|
||||
*PS: the 4 Pull Request don’t have to be done **only** on Joplin project, those can be done on any FOSS projects. Even PR for issue not tagged as 'hacktoberfest'*
|
||||
* * *
|
||||
|
||||
Joplin is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified either from the applications directly or from your own text editor. The notes are in [Markdown format](#markdown).
|
||||
|
||||
Notes exported from Evernote via .enex files [can be imported](#importing) into Joplin, including the formatted content (which is converted to Markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.). Plain Markdown files can also be imported.
|
||||
@@ -20,15 +32,15 @@ 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.0.168/Joplin-Setup-1.0.168.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.0.168/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.0.168/Joplin-1.0.168.dmg'><img alt='Get it on macOS' width="134px" src='https://joplinapp.org/images/BadgeMacOS.png'/></a> | You can also use Homebrew: `brew cask install joplin`
|
||||
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.168/Joplin-1.0.168-x86_64.AppImage'><img alt='Get it on Linux' width="134px" src='https://joplinapp.org/images/BadgeLinux.png'/></a> | An Arch Linux package [is also available](#terminal-application).<br><br>If it works with your distribution (it has been tested on Ubuntu, Fedora, Gnome and Mint), 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/master/Joplin_install_and_update.sh \| bash`
|
||||
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.169/Joplin-Setup-1.0.169.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.0.169/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.0.169/Joplin-1.0.169.dmg'><img alt='Get it on macOS' width="134px" src='https://joplinapp.org/images/BadgeMacOS.png'/></a> | You can also use Homebrew: `brew cask install joplin`
|
||||
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.169/Joplin-1.0.169-x86_64.AppImage'><img alt='Get it on Linux' width="134px" src='https://joplinapp.org/images/BadgeLinux.png'/></a> | An Arch Linux package [is also available](#terminal-application).<br><br>If it works with your distribution (it has been tested on Ubuntu, Fedora, Gnome and Mint), 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/master/Joplin_install_and_update.sh \| bash`
|
||||
|
||||
## 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://joplinapp.org/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.307/joplin-v1.0.307.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.307/joplin-v1.0.307-32bit.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://joplinapp.org/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.308/joplin-v1.0.308.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.308/joplin-v1.0.308-32bit.apk)
|
||||
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://joplinapp.org/images/BadgeIOS.png'/></a> | -
|
||||
|
||||
## Terminal application
|
||||
@@ -37,7 +49,7 @@ Operating system | Method
|
||||
-----------------|----------------
|
||||
macOS | `brew install joplin`
|
||||
Linux or Windows (via [WSL](https://msdn.microsoft.com/en-us/commandline/wsl/faq?f=255&MSPPError=-2147217396)) | **Important:** First, [install Node 8+](https://nodejs.org/en/download/package-manager/).<br/><br/>`NPM_CONFIG_PREFIX=~/.joplin-bin npm install -g joplin`<br/>`sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin`<br><br>By default, the application binary will be installed under `~/.joplin-bin`. You may change this directory if needed. Alternatively, if your npm permissions are setup as described [here](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-2-change-npms-default-directory-to-another-directory) (Option 2) then simply running `npm -g install joplin` would work.
|
||||
Arch Linux | An Arch Linux package is available [here](https://aur.archlinux.org/packages/joplin/). To install it, use an AUR wrapper such as yay: `yay -S joplin`. Both the CLI tool (type `joplin`) and desktop app (type `joplin-desktop`) are packaged. For support, please go to the [GitHub repo](https://github.com/masterkorp/joplin-pkgbuild).
|
||||
Arch Linux | An Arch Linux package is available [here](https://aur.archlinux.org/packages/joplin/). To install it, use an AUR wrapper such as yay: `yay -S joplin`. Both the CLI tool (type `joplin`) and desktop app (type `joplin-desktop`) are packaged. You can also install a compiled version with the [chaotic-aur](https://wiki.archlinux.org/index.php/Unofficial_user_repositories#chaotic-aur) repository. For support, please go to the [GitHub repo](https://github.com/masterkorp/joplin-pkgbuild).
|
||||
|
||||
To start it, type `joplin`.
|
||||
|
||||
@@ -60,6 +72,7 @@ The Web Clipper is a browser extension that allows you to save web pages and scr
|
||||
- Support
|
||||
|
||||
- [Joplin Forum](https://discourse.joplinapp.org)
|
||||
- [Markdown Guide](https://github.com/laurent22/joplin/blob/master/readme/markdown.md)
|
||||
- [How to enable end-to-end encryption](https://github.com/laurent22/joplin/blob/master/readme/e2ee.md)
|
||||
- [End-to-end encryption spec](https://github.com/laurent22/joplin/blob/master/readme/spec.md)
|
||||
- [How to enable debug mode](https://github.com/laurent22/joplin/blob/master/readme/debugging.md)
|
||||
@@ -109,7 +122,7 @@ To import Evernote data, first export your Evernote notebooks to ENEX files as d
|
||||
|
||||
In the **desktop application**, open File > Import > ENEX and select your file. The notes will be imported into a new separate notebook. If needed they can then be moved to a different notebook, or the notebook can be renamed, etc.
|
||||
|
||||
In the **terminal application**, in [command-line mode](https://joplinapp.org/terminal/#command-line-mode), type `import /path/to/file.enex`. This will import the notes into a new notebook named after the filename.
|
||||
In the **terminal application**, in [command-line mode](https://github.com/laurent22/joplin/blob/master/readme/terminal.md#command-line-mode), type `import /path/to/file.enex`. This will import the notes into a new notebook named after the filename.
|
||||
|
||||
## Importing from Markdown files
|
||||
|
||||
@@ -117,7 +130,7 @@ Joplin can import notes from plain Markdown file. You can either import a comple
|
||||
|
||||
In the **desktop application**, open File > Import > MD and select your Markdown file or directory.
|
||||
|
||||
In the **terminal application**, in [command-line mode](https://joplinapp.org/terminal/#command-line-mode), type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`.
|
||||
In the **terminal application**, in [command-line mode](https://github.com/laurent22/joplin/blob/master/readme/terminal.md#command-line-mode), type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`.
|
||||
|
||||
## Importing from other applications
|
||||
|
||||
@@ -192,9 +205,9 @@ In the **terminal application**, to initiate the synchronisation process, type `
|
||||
|
||||
# Encryption
|
||||
|
||||
Joplin supports end-to-end encryption (E2EE) on all the applications. E2EE is a system where only the owner of the notes, notebooks, tags or resources can read them. It prevents potential eavesdroppers - including telecom providers, internet providers, and even the developers of Joplin from being able to access the data. Please see the [End-To-End Encryption Tutorial](https://joplinapp.org/e2ee/) for more information about this feature and how to enable it.
|
||||
Joplin supports end-to-end encryption (E2EE) on all the applications. E2EE is a system where only the owner of the notes, notebooks, tags or resources can read them. It prevents potential eavesdroppers - including telecom providers, internet providers, and even the developers of Joplin from being able to access the data. Please see the [End-To-End Encryption Tutorial](https://github.com/laurent22/joplin/blob/master/readme/e2ee.md) for more information about this feature and how to enable it.
|
||||
|
||||
For a more technical description, mostly relevant for development or to review the method being used, please see the [Encryption specification](https://joplinapp.org/spec/).
|
||||
For a more technical description, mostly relevant for development or to review the method being used, please see the [Encryption specification](https://github.com/laurent22/joplin/blob/master/readme/spec.md).
|
||||
|
||||
# Note history
|
||||
|
||||
@@ -249,76 +262,13 @@ Sub-notebooks allow organising multiple notebooks into a tree of notebooks. For
|
||||
|
||||
# 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:
|
||||
Joplin uses and renders a Github-flavoured Markdown with a few variations and additions. In particular it adds math formula support, interactive checkboxes and support for note links. Joplin also supports Markdown plugins which allow enabling and disabling various advanced Markdown features. Have a look at the [Markdown Guide](https://github.com/laurent22/joplin/blob/master/readme/markdown.md) for more information.
|
||||
|
||||
## Links to other notes
|
||||
|
||||
You can create a link to a note by specifying its ID in the URL. For example:
|
||||
|
||||
[Link to my note](:/0b0d62d15e60409dac34f354b6e9e839)
|
||||
|
||||
Since getting the ID of a note is not straightforward, each app provides a way to create such link. In the **desktop app**, right click on a note an select "Copy Markdown link". In the **mobile app**, open a note and, in the top right menu, select "Copy Markdown link". You can then paste this link anywhere in another note.
|
||||
|
||||
## Plugins
|
||||
|
||||
Joplin supports a number of plugins that can be toggled on top the standard markdown features you would expect. These toggle-able plugins are listed below. Note: not all of the plugins are enabled by default, if the enable field is 'no' below, then enter Tools->General Options to enable the plugin. Plugins can be disabled in the same manner.
|
||||
|
||||
| Plugin | Syntax | Description | Enabled |
|
||||
|--------|--------|-------------|---------|
|
||||
| [Katex](https://katex.org) | `$$math expr$$` or `$math$` | [See Below](https://github.com/laurent22/joplin#math-notation) | yes |
|
||||
| [Mark](https://github.com/markdown-it/markdown-it-mark) | `==marked==` | Transforms into `<mark>marked</mark>` (highlighted) | yes |
|
||||
| [Footnote](https://github.com/markdown-it/markdown-it-footnote) | `Simples inline footnote ^[I'm inline!]` | See [plugin page](https://github.com/markdown-it/markdown-it-footnote) for full description | yes |
|
||||
| [TOC](https://github.com/nagaozen/markdown-it-toc-done-right) | Any of `${toc}, [[toc]], [toc], [[_toc_]]` | Adds a table of contents to the location of the toc page. Based on headings and sub-headings | no |
|
||||
| [Sub](https://github.com/markdown-it/markdown-it-sub) | `X~1~` | Transforms into X<sub>1</sub> | no |
|
||||
| [Sup](https://github.com/markdown-it/markdown-it-sup) | `X^2^` | Transforms into X<sup>2</sup> | no |
|
||||
| [Deflist](https://github.com/markdown-it/markdown-it-deflist) | See [pandoc](http://johnmacfarlane.net/pandoc/README.html#definition-lists) page for syntax | Adds the html `<dl>` tag accessible through markdown | no |
|
||||
| [Abbr](https://github.com/markdown-it/markdown-it-abbr) | *[HTML]: Hyper Text Markup Language | Allows definition of abbreviations that can be hovered over later for a full expansion | no |
|
||||
| [Emoji](https://github.com/markdown-it/markdown-it-emoji) | `:smile:` :smile: | See [this list](https://gist.github.com/rxaviers/7360908) for more emoji | no |
|
||||
| [Insert](https://github.com/markdown-it/markdown-it-ins) | `++inserted++` | Transforms into `<ins>inserted</ins>` (<ins>inserted</ins>) | no |
|
||||
| [Multitable](https://github.com/RedBug312/markdown-it-multimd-table) | See [MultiMarkdown](https://fletcher.github.io/MultiMarkdown-6/syntax/tables.html) page | Adds more power and customization to markdown tables | no |
|
||||
| [Fountain](https://fountain.io) | <code>\`\`\`fountain</code><br/>Your screenplay...<br/><code>\`\`\`</code> | Adds support for the Fountain markup language, a plain text markup language for screenwriting | no |
|
||||
|
||||
## 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 `$EXPRESSION$`, eg. `$\sqrt{3x-1}+(1+x)^2$`. To create an expression block, wrap it as follow:
|
||||
|
||||
$$
|
||||
EXPRESSION
|
||||
$$
|
||||
|
||||
For example:
|
||||
|
||||
$$
|
||||
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://joplinapp.org/images/Katex.png" height="400px">
|
||||
|
||||
## Checkboxes
|
||||
|
||||
Checkboxes can be added like so:
|
||||
|
||||
- [ ] Milk
|
||||
- [ ] Rice
|
||||
- [ ] Eggs
|
||||
|
||||
The checkboxes can then be ticked in the mobile and desktop applications.
|
||||
|
||||
## HTML support
|
||||
|
||||
It is generally recommended to enter the notes as Markdown as it makes the notes easier to edit. However for cases where certain features aren't supported (such as strikethrough or to highlight text), you can also use HTML code directly. For example this would be a valid note:
|
||||
|
||||
This is <s>strikethrough text</s> mixed with regular **Markdown**.
|
||||
|
||||
## Custom CSS
|
||||
# Custom CSS
|
||||
|
||||
Rendered markdown can be customized by placing a userstyle file in the profile directory `~/.config/joplin-desktop/userstyle.css` (This path might be different on your device - check at the top of the Config screen for the exact path). This file supports standard CSS syntax. Joplin ***must*** be restarted for the new css to be applied, please ensure that Joplin is not closing to the tray, but is actually exiting. Note that this file is used only when display the notes, **not when printing or exporting to PDF**. This is because printing has a lot more restrictions (for example, printing white text over a black background is usually not wanted), so special rules are applied to make it look good when printing, and a userstyle.css would interfer with that.
|
||||
|
||||
## Note templates
|
||||
# Note templates
|
||||
|
||||
In the **desktop app**, templates can be used to create new notes or to insert into existing ones by creating a `templates` folder in Joplin's config folder and placing Markdown template files into it. For example creating the file `hours.md` in the `templates` directory with the contents:
|
||||
|
||||
@@ -361,7 +311,7 @@ In the desktop application, press Ctrl+G or Cmd+G and type the title of a note t
|
||||
|
||||
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.
|
||||
|
||||
Please see the [donation page](https://joplinapp.org/donate/) for information on how to support the development of Joplin.
|
||||
Please see the [donation page](https://github.com/laurent22/joplin/blob/master/readme/donate.md) for information on how to support the development of Joplin.
|
||||
|
||||
# Community
|
||||
|
||||
@@ -430,9 +380,9 @@ Current translations:
|
||||
|
||||
Thanks to our GitHub sponsors!
|
||||
|
||||
| | |
|
||||
| :---: | :---: |
|
||||
| <img width="50" src="https://avatars1.githubusercontent.com/u/6979755?v=4"/></br>[devonzuegel](https://github.com/devonzuegel) | <img width="50" src="https://avatars1.githubusercontent.com/u/794584?v=4"/></br>[corvus-ch](https://github.com/corvus-ch) |
|
||||
| | | |
|
||||
| :---: | :---: | :---: |
|
||||
| <img width="50" src="https://avatars1.githubusercontent.com/u/6979755?v=4"/></br>[devonzuegel](https://github.com/devonzuegel) | <img width="50" src="https://avatars1.githubusercontent.com/u/794584?v=4"/></br>[corvus-ch](https://github.com/corvus-ch) | <img width="50" src="https://avatars2.githubusercontent.com/u/5559891?v=4"/></br>[stellaktran](https://github.com/stellaktran)
|
||||
|
||||
# Contributors
|
||||
|
||||
|
@@ -94,8 +94,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097543
|
||||
versionName "1.0.307"
|
||||
versionCode 2097544
|
||||
versionName "1.0.308"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
}
|
||||
|
@@ -20,18 +20,18 @@ ArrayUtils.binarySearch = function(items, value) {
|
||||
middle = Math.floor((stopIndex + startIndex) / 2);
|
||||
|
||||
while (items[middle] != value && startIndex < stopIndex) {
|
||||
//adjust search area
|
||||
// adjust search area
|
||||
if (value < items[middle]) {
|
||||
stopIndex = middle - 1;
|
||||
} else if (value > items[middle]) {
|
||||
startIndex = middle + 1;
|
||||
}
|
||||
|
||||
//recalculate middle
|
||||
// recalculate middle
|
||||
middle = Math.floor((stopIndex + startIndex) / 2);
|
||||
}
|
||||
|
||||
//make sure it's the right value
|
||||
// make sure it's the right value
|
||||
return items[middle] != value ? -1 : middle;
|
||||
};
|
||||
|
||||
|
@@ -15,6 +15,7 @@ const { reg } = require('lib/registry.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const BaseSyncTarget = require('lib/BaseSyncTarget.js');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const { _, setLocale } = require('lib/locale.js');
|
||||
const reduxSharedMiddleware = require('lib/components/shared/reduxSharedMiddleware');
|
||||
const os = require('os');
|
||||
@@ -598,6 +599,8 @@ class BaseApplication {
|
||||
|
||||
await Setting.load();
|
||||
|
||||
if (!Setting.value('clientId')) Setting.setValue('clientId', uuid.create());
|
||||
|
||||
if (Setting.value('firstStart')) {
|
||||
const locale = shim.detectAndSetLocale(Setting);
|
||||
reg.logger().info(`First start: detected locale as ${locale}`);
|
||||
|
@@ -150,8 +150,8 @@ class BaseModel {
|
||||
});
|
||||
}
|
||||
|
||||
static load(id) {
|
||||
return this.loadByField('id', id);
|
||||
static load(id, options = null) {
|
||||
return this.loadByField('id', id, options);
|
||||
}
|
||||
|
||||
static shortId(id) {
|
||||
@@ -250,7 +250,8 @@ class BaseModel {
|
||||
static loadByField(fieldName, fieldValue, options = null) {
|
||||
if (!options) options = {};
|
||||
if (!('caseInsensitive' in options)) options.caseInsensitive = false;
|
||||
let sql = `SELECT * FROM \`${this.tableName()}\` WHERE \`${fieldName}\` = ?`;
|
||||
if (!options.fields) options.fields = '*';
|
||||
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\` WHERE \`${fieldName}\` = ?`;
|
||||
if (options.caseInsensitive) sql += ' COLLATE NOCASE';
|
||||
return this.modelSelectOne(sql, [fieldValue]);
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ class WebDavApi {
|
||||
try {
|
||||
// Note: Non-ASCII passwords will throw an error about Latin1 characters - https://github.com/laurent22/joplin/issues/246
|
||||
// Tried various things like the below, but it didn't work on React Native:
|
||||
//return base64.encode(utf8.encode(this.options_.username() + ':' + this.options_.password()));
|
||||
// return base64.encode(utf8.encode(this.options_.username() + ':' + this.options_.password()));
|
||||
return base64.encode(`${this.options_.username()}:${this.options_.password()}`);
|
||||
} catch (error) {
|
||||
error.message = `Cannot encode username/password: ${error.message}`;
|
||||
|
@@ -11,16 +11,30 @@ class CameraView extends Component {
|
||||
|
||||
this.state = {
|
||||
snapping: false,
|
||||
camera: RNCamera.Constants.Type.back,
|
||||
};
|
||||
|
||||
this.back_onPress = this.back_onPress.bind(this);
|
||||
this.photo_onPress = this.photo_onPress.bind(this);
|
||||
this.reverse_onPress = this.reverse_onPress.bind(this);
|
||||
}
|
||||
|
||||
back_onPress() {
|
||||
if (this.props.onCancel) this.props.onCancel();
|
||||
}
|
||||
|
||||
reverse_onPress() {
|
||||
if (this.state.camera == RNCamera.Constants.Type.back) {
|
||||
this.setState({
|
||||
camera: RNCamera.Constants.Type.front,
|
||||
});
|
||||
} else if (this.state.camera == RNCamera.Constants.Type.front) {
|
||||
this.setState({
|
||||
camera: RNCamera.Constants.Type.back,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async photo_onPress() {
|
||||
if (!this.camera || !this.props.onPhoto) return;
|
||||
|
||||
@@ -47,7 +61,7 @@ class CameraView extends Component {
|
||||
ref={ref => {
|
||||
this.camera = ref;
|
||||
}}
|
||||
type={RNCamera.Constants.Type.back}
|
||||
type={this.state.camera}
|
||||
captureAudio={false}
|
||||
androidCameraPermissionOptions={{
|
||||
title: _('Permission to use camera'),
|
||||
@@ -70,18 +84,31 @@ class CameraView extends Component {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-end', flexDirection: 'row' }}>
|
||||
<TouchableOpacity onPress={this.photo_onPress}>
|
||||
<View style={{ marginBottom: 20, borderRadius: 90, width: 90, height: 90, backgroundColor: '#ffffffaa', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<Icon
|
||||
name={photoIcon}
|
||||
style={{
|
||||
fontSize: 60,
|
||||
color: 'black',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<View style={{ flex: 1, alignItems: 'flex-end', flexDirection: 'row', width: '100%' }}>
|
||||
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<TouchableOpacity onPress={this.reverse_onPress} style={{width: '35%', marginLeft: 20}}>
|
||||
<View style={{borderRadius: 32, width: 60, height: 60, backgroundColor: '#ffffffaa', justifyContent: 'center', alignItems: 'center', alignSelf: 'baseline' }}>
|
||||
<Icon
|
||||
name="md-reverse-camera"
|
||||
style={{
|
||||
fontSize: 40,
|
||||
color: 'black',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={this.photo_onPress} style={{width: '65%'}}>
|
||||
<View style={{ marginBottom: 20, borderRadius: 90, width: 90, height: 90, backgroundColor: '#ffffffaa', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<Icon
|
||||
name={photoIcon}
|
||||
style={{
|
||||
fontSize: 60,
|
||||
color: 'black',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</RNCamera>
|
||||
|
@@ -67,7 +67,7 @@ class ItemList extends React.Component {
|
||||
render() {
|
||||
const style = this.props.style ? this.props.style : {};
|
||||
|
||||
//if (!this.props.itemHeight) throw new Error('itemHeight is required');
|
||||
// if (!this.props.itemHeight) throw new Error('itemHeight is required');
|
||||
|
||||
let itemComps = [];
|
||||
|
||||
|
@@ -7,7 +7,7 @@ const styles = {
|
||||
checkboxIcon: {
|
||||
fontSize: 20,
|
||||
height: 22,
|
||||
//marginRight: 10,
|
||||
// marginRight: 10,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ class Checkbox extends Component {
|
||||
|
||||
if (style && style.display === 'none') return <View />;
|
||||
|
||||
//if (style.display) thStyle.display = style.display;
|
||||
// if (style.display) thStyle.display = style.display;
|
||||
|
||||
return (
|
||||
<TouchableHighlight onPress={() => this.onPress()} style={thStyle}>
|
||||
|
@@ -96,7 +96,7 @@ class NoteBodyViewer extends Component {
|
||||
},
|
||||
paddingBottom: '3.8em', // Extra bottom padding to make it possible to scroll past the action button (so that it doesn't overlap the text)
|
||||
highlightedKeywords: this.props.highlightedKeywords,
|
||||
resources: this.props.noteResources, //await shared.attachedResources(bodyToRender),
|
||||
resources: this.props.noteResources, // await shared.attachedResources(bodyToRender),
|
||||
codeTheme: theme.codeThemeCss,
|
||||
postMessageSyntax: 'window.ReactNativeWebView.postMessage',
|
||||
};
|
||||
|
@@ -30,7 +30,7 @@ class NoteItemComponent extends Component {
|
||||
let styles = {
|
||||
listItem: {
|
||||
flexDirection: 'row',
|
||||
//height: 40,
|
||||
// height: 40,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.dividerColor,
|
||||
alignItems: 'flex-start',
|
||||
@@ -38,7 +38,7 @@ class NoteItemComponent extends Component {
|
||||
paddingRight: theme.marginRight,
|
||||
paddingTop: theme.itemMarginTop,
|
||||
paddingBottom: theme.itemMarginBottom,
|
||||
//backgroundColor: theme.backgroundColor,
|
||||
// backgroundColor: theme.backgroundColor,
|
||||
},
|
||||
listItemText: {
|
||||
flex: 1,
|
||||
|
@@ -61,7 +61,7 @@ class NoteListComponent extends Component {
|
||||
}
|
||||
|
||||
filterNotes(notes) {
|
||||
const todoFilter = 'all'; //Setting.value('todoFilter');
|
||||
const todoFilter = 'all'; // Setting.value('todoFilter');
|
||||
if (todoFilter == 'all') return notes;
|
||||
|
||||
const now = time.unixMs();
|
||||
|
@@ -163,6 +163,16 @@ class ScreenHeaderComponent extends React.PureComponent {
|
||||
NavService.go('Search');
|
||||
}
|
||||
|
||||
async duplicateButton_press() {
|
||||
const noteIds = this.props.selectedNoteIds;
|
||||
|
||||
//Duplicate all selected notes. ensureUniqueTitle is set to true to use the
|
||||
//original note's name as a root for the new unique identifier.
|
||||
await Note.duplicateMultipleNotes(noteIds, {ensureUniqueTitle: true});
|
||||
|
||||
this.props.dispatch({ type: 'NOTE_SELECTION_END' });
|
||||
}
|
||||
|
||||
async deleteButton_press() {
|
||||
// Dialog needs to be displayed as a child of the parent component, otherwise
|
||||
// it won't be visible within the header component.
|
||||
@@ -245,6 +255,16 @@ class ScreenHeaderComponent extends React.PureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
function duplicateButton(styles, onPress) {
|
||||
return (
|
||||
<TouchableOpacity onPress={onPress}>
|
||||
<View style={styles.iconButton}>
|
||||
<Icon name="md-copy" style={styles.topIcon} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
function sortButton(styles, onPress) {
|
||||
return (
|
||||
<TouchableOpacity onPress={onPress}>
|
||||
@@ -282,6 +302,12 @@ class ScreenHeaderComponent extends React.PureComponent {
|
||||
<Text style={this.styles().contextMenuItemText}>{_('Delete')}</Text>
|
||||
</MenuOption>
|
||||
);
|
||||
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={() => this.duplicateButton_press()} key={'menuOption_duplicate'} style={this.styles().contextMenuItem}>
|
||||
<Text style={this.styles().contextMenuItemText}>{_('Duplicate')}</Text>
|
||||
</MenuOption>
|
||||
);
|
||||
}
|
||||
|
||||
const createTitleComponent = () => {
|
||||
@@ -383,6 +409,7 @@ class ScreenHeaderComponent extends React.PureComponent {
|
||||
const backButtonComp = !showBackButton ? null : backButton(this.styles(), () => this.backButton_press(), backButtonDisabled);
|
||||
const searchButtonComp = !showSearchButton ? null : searchButton(this.styles(), () => this.searchButton_press());
|
||||
const deleteButtonComp = this.props.noteSelectionEnabled ? deleteButton(this.styles(), () => this.deleteButton_press()) : null;
|
||||
const duplicateButtonComp = this.props.noteSelectionEnabled ? duplicateButton(this.styles(), () => this.duplicateButton_press()) : null;
|
||||
const sortButtonComp = !this.props.noteSelectionEnabled && this.props.sortButton_press ? sortButton(this.styles(), () => this.props.sortButton_press()) : null;
|
||||
const windowHeight = Dimensions.get('window').height - 50;
|
||||
|
||||
@@ -419,6 +446,7 @@ class ScreenHeaderComponent extends React.PureComponent {
|
||||
{titleComp}
|
||||
{searchButtonComp}
|
||||
{deleteButtonComp}
|
||||
{duplicateButtonComp}
|
||||
{sortButtonComp}
|
||||
{menuComp}
|
||||
</View>
|
||||
|
@@ -194,7 +194,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||
|
||||
styles.switchSettingControl = Object.assign({}, styles.settingControl);
|
||||
delete styles.switchSettingControl.color;
|
||||
//styles.switchSettingControl.width = '20%';
|
||||
// styles.switchSettingControl.width = '20%';
|
||||
styles.switchSettingControl.flex = 0;
|
||||
|
||||
this.styles_[themeId] = StyleSheet.create(styles);
|
||||
@@ -366,7 +366,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
//throw new Error('Unsupported setting type: ' + md.type);
|
||||
// throw new Error('Unsupported setting type: ' + md.type);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
@@ -23,6 +23,7 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
|
||||
this.state = {
|
||||
passwordPromptShow: false,
|
||||
passwordPromptAnswer: '',
|
||||
passwordPromptConfirmAnswer: '',
|
||||
};
|
||||
|
||||
shared.constructor(this);
|
||||
@@ -82,6 +83,12 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
|
||||
fontSize: theme.fontSize,
|
||||
color: theme.color,
|
||||
},
|
||||
normalTextInput: {
|
||||
margin: 10,
|
||||
color: theme.color,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.dividerColor,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: theme.margin,
|
||||
@@ -131,6 +138,9 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
|
||||
try {
|
||||
const password = this.state.passwordPromptAnswer;
|
||||
if (!password) throw new Error(_('Password cannot be empty'));
|
||||
const password2 = this.state.passwordPromptConfirmAnswer;
|
||||
if (!password2) throw new Error(_('Confirm password cannot be empty'));
|
||||
if (password !== password2) throw new Error(_('Passwords do not match!'));
|
||||
await EncryptionService.instance().generateMasterKeyAndEnableEncryption(password);
|
||||
this.setState({ passwordPromptShow: false });
|
||||
} catch (error) {
|
||||
@@ -140,16 +150,30 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, borderColor: theme.dividerColor, borderWidth: 1, padding: 10, marginTop: 10, marginBottom: 10 }}>
|
||||
<Text style={{ fontSize: theme.fontSize, color: theme.color }}>{_('Enabling encryption means *all* your notes and attachments are going to be re-synchronised and sent encrypted to the sync target. Do not lose the password as, for security purposes, this will be the *only* way to decrypt the data! To enable encryption, please enter your password below.')}</Text>
|
||||
<Text style={{ fontSize: theme.fontSize, color: theme.color, marginBottom: 10 }}>{_('Enabling encryption means *all* your notes and attachments are going to be re-synchronised and sent encrypted to the sync target. Do not lose the password as, for security purposes, this will be the *only* way to decrypt the data! To enable encryption, please enter your password below.')}</Text>
|
||||
<Text style={this.styles().normalText}>{_('Password:')}</Text>
|
||||
<TextInput
|
||||
placeholder={_('Password')}
|
||||
selectionColor={theme.textSelectionColor}
|
||||
style={{ margin: 10, color: theme.color, borderWidth: 1, borderColor: theme.dividerColor }}
|
||||
style={this.styles().normalTextInput}
|
||||
secureTextEntry={true}
|
||||
value={this.state.passwordPromptAnswer}
|
||||
onChangeText={text => {
|
||||
this.setState({ passwordPromptAnswer: text });
|
||||
}}
|
||||
></TextInput>
|
||||
|
||||
<Text style={this.styles().normalText}>{_('Confirm password:')}</Text>
|
||||
<TextInput
|
||||
placeholder={_('Confirm password')}
|
||||
selectionColor={theme.textSelectionColor}
|
||||
style={this.styles().normalTextInput}
|
||||
secureTextEntry={true}
|
||||
value={this.state.passwordPromptConfirmAnswer}
|
||||
onChangeText={text => {
|
||||
this.setState({ passwordPromptConfirmAnswer: text });
|
||||
}}
|
||||
></TextInput>
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<View style={{ flex: 1, marginRight: 10 }}>
|
||||
<Button
|
||||
@@ -203,6 +227,7 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
|
||||
this.setState({
|
||||
passwordPromptShow: true,
|
||||
passwordPromptAnswer: '',
|
||||
passwordPromptConfirmAnswer: '',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@@ -164,14 +164,16 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
}
|
||||
};
|
||||
|
||||
this.refreshResource = async resource => {
|
||||
if (!this.state.note || !this.state.note.body) return;
|
||||
const resourceIds = await Note.linkedResourceIds(this.state.note.body);
|
||||
if (resourceIds.indexOf(resource.id) >= 0 && this.refs.noteBodyViewer) {
|
||||
this.refreshResource = async (resource, noteBody = null) => {
|
||||
if (noteBody === null && this.state.note && this.state.note.body) noteBody = this.state.note.body;
|
||||
if (noteBody === null) return;
|
||||
|
||||
const resourceIds = await Note.linkedResourceIds(noteBody);
|
||||
if (resourceIds.indexOf(resource.id) >= 0) {
|
||||
shared.clearResourceCache();
|
||||
const attachedResources = await shared.attachedResources(this.state.note.body);
|
||||
const attachedResources = await shared.attachedResources(noteBody);
|
||||
this.setState({ noteResources: attachedResources }, () => {
|
||||
this.refs.noteBodyViewer.rebuildMd();
|
||||
if (this.refs.noteBodyViewer) this.refs.noteBodyViewer.rebuildMd();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -410,7 +412,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
|
||||
const format = mimeType == 'image/png' ? 'PNG' : 'JPEG';
|
||||
reg.logger().info(`Resizing image ${localFilePath}`);
|
||||
const resizedImage = await ImageResizer.createResizedImage(localFilePath, dimensions.width, dimensions.height, format, 85); //, 0, targetPath);
|
||||
const resizedImage = await ImageResizer.createResizedImage(localFilePath, dimensions.width, dimensions.height, format, 85); // , 0, targetPath);
|
||||
|
||||
const resizedImagePath = resizedImage.uri;
|
||||
reg.logger().info('Resized image ', resizedImagePath);
|
||||
@@ -512,7 +514,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
newNote.body += `\n${resourceTag}`;
|
||||
this.setState({ note: newNote });
|
||||
|
||||
this.refreshResource(resource);
|
||||
this.refreshResource(resource, newNote.body);
|
||||
|
||||
this.scheduleSave();
|
||||
}
|
||||
|
@@ -78,7 +78,7 @@ class SelectDateTimeDialog extends React.PureComponent {
|
||||
width={0.9}
|
||||
height={350}
|
||||
>
|
||||
<View style={{flex:1, margin: 20, alignItems:'center'}}>
|
||||
<View style={{flex: 1, margin: 20, alignItems: 'center'}}>
|
||||
<DatePicker
|
||||
date={this.state.date}
|
||||
mode="datetime"
|
||||
@@ -87,7 +87,7 @@ class SelectDateTimeDialog extends React.PureComponent {
|
||||
confirmBtnText={_('Confirm')}
|
||||
cancelBtnText={_('Cancel')}
|
||||
onDateChange={(date) => { this.setState({ date: this.stringToDate(date) }); }}
|
||||
style={{width:300}}
|
||||
style={{width: 300}}
|
||||
customStyles={{
|
||||
btnConfirm: {
|
||||
paddingVertical: 0,
|
||||
|
@@ -35,11 +35,13 @@ class SideMenuContentNoteComponent extends Component {
|
||||
fontSize: 22,
|
||||
color: theme.color,
|
||||
},
|
||||
sideButtonText: {
|
||||
color: theme.color,
|
||||
},
|
||||
};
|
||||
|
||||
styles.sideButton = Object.assign({}, styles.button, { flex: 0 });
|
||||
styles.sideButtonDisabled = Object.assign({}, styles.sideButton, { opacity: 0.6 });
|
||||
styles.sideButtonText = Object.assign({}, styles.buttonText);
|
||||
|
||||
this.styles_[this.props.theme] = StyleSheet.create(styles);
|
||||
return this.styles_[this.props.theme];
|
||||
|
@@ -76,7 +76,7 @@ class SideMenuContentComponent extends Component {
|
||||
styles.folderButtonSelected = Object.assign({}, styles.folderButton);
|
||||
styles.folderButtonSelected.backgroundColor = theme.selectedColor;
|
||||
styles.folderIcon = Object.assign({}, theme.icon);
|
||||
styles.folderIcon.color = theme.colorFaded; //'#0072d5';
|
||||
styles.folderIcon.color = theme.colorFaded; // '#0072d5';
|
||||
styles.folderIcon.paddingTop = 3;
|
||||
|
||||
styles.sideButton = Object.assign({}, styles.button, { flex: 0 });
|
||||
|
@@ -6,7 +6,7 @@ class DatabaseDriverReactNative {
|
||||
}
|
||||
|
||||
open(options) {
|
||||
//SQLite.DEBUG(true);
|
||||
// SQLite.DEBUG(true);
|
||||
return new Promise((resolve, reject) => {
|
||||
SQLite.openDatabase(
|
||||
{ name: options.name },
|
||||
|
@@ -97,10 +97,10 @@ class FileApiDriverLocal {
|
||||
|
||||
try {
|
||||
if (options.target === 'file') {
|
||||
//output = await fs.copy(path, options.path, { overwrite: true });
|
||||
// output = await fs.copy(path, options.path, { overwrite: true });
|
||||
output = await this.fsDriver().copy(path, options.path);
|
||||
} else {
|
||||
//output = await fs.readFile(path, options.encoding);
|
||||
// output = await fs.readFile(path, options.encoding);
|
||||
output = await this.fsDriver().readFile(path, options.encoding);
|
||||
}
|
||||
} catch (error) {
|
||||
|
@@ -131,7 +131,7 @@ class FileApi {
|
||||
|
||||
this.logger().debug(`list ${this.baseDir()}`);
|
||||
|
||||
const result = await tryAndRepeat(() => this.driver_.list(this.baseDir(), options), this.requestRepeatCount());
|
||||
const result = await tryAndRepeat(() => this.driver_.list(this.fullPath_(path), options), this.requestRepeatCount());
|
||||
|
||||
if (!options.includeHidden) {
|
||||
let temp = [];
|
||||
@@ -148,7 +148,7 @@ class FileApi {
|
||||
setTimestamp(path, timestampMs) {
|
||||
this.logger().debug(`setTimestamp ${this.fullPath_(path)}`);
|
||||
return tryAndRepeat(() => this.driver_.setTimestamp(this.fullPath_(path), timestampMs), this.requestRepeatCount());
|
||||
//return this.driver_.setTimestamp(this.fullPath_(path), timestampMs);
|
||||
// return this.driver_.setTimestamp(this.fullPath_(path), timestampMs);
|
||||
}
|
||||
|
||||
mkdir(path) {
|
||||
|
@@ -173,7 +173,7 @@ class FsDriverNode extends FsDriverBase {
|
||||
}
|
||||
|
||||
async readFileChunk(handle, length, encoding = 'base64') {
|
||||
//let buffer = new Buffer(length);
|
||||
// let buffer = new Buffer(length);
|
||||
let buffer = Buffer.alloc(length);
|
||||
const result = await fs.read(handle, buffer, 0, length, null);
|
||||
if (!result.bytesRead) return null;
|
||||
|
@@ -392,14 +392,20 @@ function isSpanStyleBold(attributes) {
|
||||
if (style.includes('font-weight: bold;')) {
|
||||
return true;
|
||||
} else if (style.search(/font-family:.*,Bold.*;/) != -1) {
|
||||
//console.debug('font-family regex matched');
|
||||
// console.debug('font-family regex matched');
|
||||
return true;
|
||||
} else {
|
||||
//console.debug('Found unsupported style(s) in span tag: %s', style);
|
||||
// console.debug('Found unsupported style(s) in span tag: %s', style);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isSpanStyleItalic(attributes) {
|
||||
let style = attributes.style;
|
||||
style = style.replace(/\s+/g, '');
|
||||
return (style.toLowerCase().includes('font-style:italic;'));
|
||||
}
|
||||
|
||||
function enexXmlToMdArray(stream, resources) {
|
||||
let remainingResources = resources.slice();
|
||||
|
||||
@@ -694,11 +700,16 @@ function enexXmlToMdArray(stream, resources) {
|
||||
}
|
||||
} else if (n == 'span') {
|
||||
if (isSpanWithStyle(nodeAttributes)) {
|
||||
// console.debug('Found style(s) in span tag: %s', nodeAttributes.style);
|
||||
state.spanAttributes.push(nodeAttributes);
|
||||
if (isSpanStyleBold(nodeAttributes)) {
|
||||
//console.debug('Applying style found in span tag: bold')
|
||||
// console.debug('Applying style found in span tag: bold')
|
||||
section.lines.push('**');
|
||||
}
|
||||
if (isSpanStyleItalic(nodeAttributes)) {
|
||||
// console.debug('Applying style found in span tag: italic')
|
||||
section.lines.push('*');
|
||||
}
|
||||
}
|
||||
} else if (['font', 'sup', 'cite', 'abbr', 'small', 'tt', 'sub', 'colgroup', 'col', 'ins', 'caption', 'var', 'map', 'area'].indexOf(n) >= 0) {
|
||||
// Inline tags that can be ignored in Markdown
|
||||
@@ -884,9 +895,13 @@ function enexXmlToMdArray(stream, resources) {
|
||||
let attributes = state.spanAttributes.pop();
|
||||
if (isSpanWithStyle(attributes)) {
|
||||
if (isSpanStyleBold(attributes)) {
|
||||
//console.debug('Applying style found in span tag (closing): bold')
|
||||
// console.debug('Applying style found in span tag (closing): bold')
|
||||
section.lines.push('**');
|
||||
}
|
||||
if (isSpanStyleItalic(attributes)) {
|
||||
// console.debug('Applying style found in span tag (closing): italic')
|
||||
section.lines.push('*');
|
||||
}
|
||||
}
|
||||
} else if (isIgnoredEndTag(n)) {
|
||||
// Skip
|
||||
|
@@ -10,7 +10,7 @@ const { time } = require('lib/time-utils.js');
|
||||
const Levenshtein = require('levenshtein');
|
||||
const md5 = require('md5');
|
||||
|
||||
//const Promise = require('promise');
|
||||
// const Promise = require('promise');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
function dateToTimestamp(s, zeroIfInvalid = false) {
|
||||
|
@@ -768,6 +768,9 @@ const mimeTypes = [
|
||||
{ t: 'x-conference/x-cooltalk', e: ['ice'] },
|
||||
];
|
||||
|
||||
// Note: if the list above is ever updated, make sure Markdown doesn't appear twice
|
||||
mimeTypes.push({ t: 'text/markdown', e: ['md', 'markdown'] });
|
||||
|
||||
const mime = {
|
||||
fromFileExtension(ext) {
|
||||
ext = ext.toLowerCase();
|
||||
@@ -780,6 +783,13 @@ const mime = {
|
||||
return null;
|
||||
},
|
||||
|
||||
fromFilename(name) {
|
||||
if (!name) return null;
|
||||
const splitted = name.trim().split('.');
|
||||
if (splitted.length <= 1) return null;
|
||||
return mime.fromFileExtension(splitted[splitted.length - 1]);
|
||||
},
|
||||
|
||||
toFileExtension(mimeType) {
|
||||
mimeType = mimeType.toLowerCase();
|
||||
for (let i = 0; i < mimeTypes.length; i++) {
|
||||
|
@@ -238,11 +238,7 @@ class BaseItem extends BaseModel {
|
||||
static serialize_format(propName, propValue) {
|
||||
if (['created_time', 'updated_time', 'sync_time', 'user_updated_time', 'user_created_time'].indexOf(propName) >= 0) {
|
||||
if (!propValue) return '';
|
||||
propValue =
|
||||
`${moment
|
||||
.unix(propValue / 1000)
|
||||
.utc()
|
||||
.format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`;
|
||||
propValue = `${moment.unix(propValue / 1000).utc().format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`;
|
||||
} else if (['title_diff', 'body_diff'].indexOf(propName) >= 0) {
|
||||
if (!propValue) return '';
|
||||
propValue = JSON.stringify(propValue);
|
||||
|
@@ -481,6 +481,25 @@ class Note extends BaseItem {
|
||||
return note;
|
||||
}
|
||||
|
||||
static async duplicateMultipleNotes(noteIds, options = null){
|
||||
/*
|
||||
if options.uniqueTitle is true, a unique title for the duplicated file will be assigned.
|
||||
*/
|
||||
const ensureUniqueTitle = options && options.ensureUniqueTitle;
|
||||
|
||||
for(const noteId of noteIds){
|
||||
const noteOptions = {};
|
||||
|
||||
//If ensureUniqueTitle is truthy, set the original note's name as root for the unique title.
|
||||
if(ensureUniqueTitle){
|
||||
const originalNote = await Note.load(noteId);
|
||||
noteOptions.uniqueTitle = originalNote.title;
|
||||
}
|
||||
|
||||
await Note.duplicate(noteId, noteOptions);
|
||||
}
|
||||
}
|
||||
|
||||
static async duplicate(noteId, options = null) {
|
||||
const changes = options && options.changes;
|
||||
const uniqueTitle = options && options.uniqueTitle;
|
||||
|
@@ -31,6 +31,12 @@ class Setting extends BaseModel {
|
||||
// public for the mobile and desktop apps because they are handled separately in menus.
|
||||
|
||||
this.metadata_ = {
|
||||
'clientId': {
|
||||
value: '',
|
||||
type: Setting.TYPE_STRING,
|
||||
public: false,
|
||||
},
|
||||
|
||||
'sync.target': {
|
||||
value: SyncTargetRegistry.nameToId('dropbox'),
|
||||
type: Setting.TYPE_INT,
|
||||
@@ -219,6 +225,7 @@ class Setting extends BaseModel {
|
||||
output[Setting.THEME_LIGHT] = _('Light');
|
||||
output[Setting.THEME_DARK] = _('Dark');
|
||||
if (platform !== 'mobile') {
|
||||
output[Setting.THEME_DRACULA] = _('Dracula');
|
||||
output[Setting.THEME_SOLARIZED_LIGHT] = _('Solarised Light');
|
||||
output[Setting.THEME_SOLARIZED_DARK] = _('Solarised Dark');
|
||||
}
|
||||
@@ -400,6 +407,23 @@ class Setting extends BaseModel {
|
||||
tagHeaderIsExpanded: { value: true, type: Setting.TYPE_BOOL, public: false, appTypes: ['desktop'] },
|
||||
folderHeaderIsExpanded: { value: true, type: Setting.TYPE_BOOL, public: false, appTypes: ['desktop'] },
|
||||
editor: { value: '', type: Setting.TYPE_STRING, subType: 'file_path_and_args', public: true, appTypes: ['cli', 'desktop'], label: () => _('Text editor command'), description: () => _('The editor command (may include arguments) that will be used to open a note. If none is provided it will try to auto-detect the default editor.') },
|
||||
'export.pdfPageSize': { value: 'A4', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['desktop'], label: () => _('Page size for PDF export'), options: () => {
|
||||
return {
|
||||
'A4': _('A4'),
|
||||
'Letter': _('Letter'),
|
||||
'A3': _('A3'),
|
||||
'A5': _('A5'),
|
||||
'Tabloid': _('Tabloid'),
|
||||
'Legal': _('Legal'),
|
||||
};
|
||||
}},
|
||||
'export.pdfPageOrientation': { value: 'portrait', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['desktop'], label: () => _('Page orientation for PDF export'), options: () => {
|
||||
return {
|
||||
'portrait': _('Portrait'),
|
||||
'landscape': _('Landscape'),
|
||||
};
|
||||
}},
|
||||
|
||||
|
||||
'net.customCertificates': {
|
||||
value: '',
|
||||
@@ -884,6 +908,7 @@ Setting.THEME_LIGHT = 1;
|
||||
Setting.THEME_DARK = 2;
|
||||
Setting.THEME_SOLARIZED_LIGHT = 3;
|
||||
Setting.THEME_SOLARIZED_DARK = 4;
|
||||
Setting.THEME_DRACULA = 5;
|
||||
|
||||
Setting.FONT_DEFAULT = 0;
|
||||
Setting.FONT_MENLO = 1;
|
||||
@@ -915,6 +940,7 @@ Setting.constants_ = {
|
||||
templateDir: '',
|
||||
tempDir: '',
|
||||
openDevTools: false,
|
||||
syncVersion: 1,
|
||||
};
|
||||
|
||||
Setting.autoSaveEnabled = true;
|
||||
|
@@ -186,7 +186,7 @@ class OneDriveApi {
|
||||
let errorResponseText = await response.text();
|
||||
let errorResponse = null;
|
||||
try {
|
||||
errorResponse = JSON.parse(errorResponseText); //await response.json();
|
||||
errorResponse = JSON.parse(errorResponseText); // await response.json();
|
||||
} catch (error) {
|
||||
error.message = `OneDriveApi::exec: Cannot parse JSON error: ${errorResponseText} ${error.message}`;
|
||||
throw error;
|
||||
@@ -249,12 +249,12 @@ class OneDriveApi {
|
||||
let response = await this.exec(method, path, query, data);
|
||||
let errorResponseText = await response.text();
|
||||
try {
|
||||
let output = JSON.parse(errorResponseText); //await response.json();
|
||||
let output = JSON.parse(errorResponseText); // await response.json();
|
||||
return output;
|
||||
} catch (error) {
|
||||
error.message = `OneDriveApi::execJson: Cannot parse JSON: ${errorResponseText} ${error.message}`;
|
||||
throw error;
|
||||
//throw new Error('Cannot parse JSON: ' + text);
|
||||
// throw new Error('Cannot parse JSON: ' + text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*eslint no-useless-escape: 0*/
|
||||
/* eslint no-useless-escape: 0*/
|
||||
|
||||
// parseUri 1.2.2
|
||||
// (c) Steven Levithan <stevenlevithan.com>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*eslint no-useless-escape: 0*/
|
||||
/* eslint no-useless-escape: 0*/
|
||||
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
|
@@ -459,7 +459,7 @@ const reducer = (state = defaultState, action) => {
|
||||
}
|
||||
}
|
||||
|
||||
//newNotes = Note.sortNotes(newNotes, state.notesOrder, newState.settings.uncompletedTodosOnTop);
|
||||
// newNotes = Note.sortNotes(newNotes, state.notesOrder, newState.settings.uncompletedTodosOnTop);
|
||||
newNotes = Note.sortNotes(newNotes, stateUtils.notesOrder(state.settings), newState.settings.uncompletedTodosOnTop);
|
||||
newState = Object.assign({}, state);
|
||||
newState.notes = newNotes;
|
||||
|
@@ -10,7 +10,7 @@ reg.syncTargets_ = {};
|
||||
|
||||
reg.logger = () => {
|
||||
if (!reg.logger_) {
|
||||
//console.warn('Calling logger before it is initialized');
|
||||
// console.warn('Calling logger before it is initialized');
|
||||
return new Logger();
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
const htmlUtils = require('lib/htmlUtils');
|
||||
const utils = require('./utils');
|
||||
const noteStyle = require('./noteStyle');
|
||||
|
||||
class HtmlToHtml {
|
||||
constructor(options) {
|
||||
@@ -26,8 +27,11 @@ class HtmlToHtml {
|
||||
}
|
||||
});
|
||||
|
||||
const cssStrings = noteStyle(theme, options);
|
||||
const styleHtml = `<style>${cssStrings.join('\n')}</style>`;
|
||||
|
||||
return {
|
||||
html: html,
|
||||
html: styleHtml + html,
|
||||
cssFiles: [],
|
||||
};
|
||||
}
|
||||
|
@@ -119,7 +119,7 @@ function installRule(markdownIt, mdOptions, ruleOptions, context) {
|
||||
return self.renderToken(tokens, idx, options);
|
||||
};
|
||||
|
||||
markdownIt.renderer.rules.fence = function (tokens, idx, options, env, self) {
|
||||
markdownIt.renderer.rules.fence = function(tokens, idx, options, env, self) {
|
||||
const token = tokens[idx];
|
||||
if (token.info !== 'fountain') return defaultRender(tokens, idx, options, env, self);
|
||||
addContextAssets(context);
|
||||
|
@@ -7,6 +7,9 @@ const Setting = require('lib/models/Setting');
|
||||
var katex = require('katex');
|
||||
const katexCss = require('lib/csstojs/katex.css.js');
|
||||
const md5 = require('md5');
|
||||
const mhchemModule = require('./katex_mhchem.js');
|
||||
|
||||
katex = mhchemModule(katex);
|
||||
|
||||
// const style = `
|
||||
// /*
|
||||
|
1732
ReactNativeClient/lib/renderers/MdToHtml/rules/katex_mhchem.js
Normal file
1732
ReactNativeClient/lib/renderers/MdToHtml/rules/katex_mhchem.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9,17 +9,23 @@ function installRule(markdownIt, mdOptions, ruleOptions) {
|
||||
let href = utils.getAttr(token.attrs, 'href');
|
||||
const resourceHrefInfo = urlUtils.parseResourceUrl(href);
|
||||
const isResourceUrl = !!resourceHrefInfo;
|
||||
const title = isResourceUrl ? utils.getAttr(token.attrs, 'title') : href;
|
||||
let title = utils.getAttr(token.attrs, 'title', isResourceUrl ? '' : href);
|
||||
|
||||
let resourceIdAttr = '';
|
||||
let icon = '';
|
||||
let hrefAttr = '#';
|
||||
let mime = '';
|
||||
if (isResourceUrl) {
|
||||
const resourceId = resourceHrefInfo.itemId;
|
||||
|
||||
const result = ruleOptions.resources[resourceId];
|
||||
const resourceStatus = utils.resourceStatus(result);
|
||||
|
||||
if (result && result.item) {
|
||||
title = utils.getAttr(token.attrs, 'title', result.item.title);
|
||||
mime = result.item.mime;
|
||||
}
|
||||
|
||||
if (result && resourceStatus !== 'ready') {
|
||||
const icon = utils.resourceStatusFile(resourceStatus);
|
||||
return `<a class="not-loaded-resource resource-status-${resourceStatus}" data-resource-id="${resourceId}">` + `<img src="data:image/svg+xml;utf8,${htmlentities(icon)}"/>`;
|
||||
@@ -37,7 +43,7 @@ function installRule(markdownIt, mdOptions, ruleOptions) {
|
||||
|
||||
let js = `${ruleOptions.postMessageSyntax}(${JSON.stringify(href)}); return false;`;
|
||||
if (hrefAttr.indexOf('#') === 0 && href.indexOf('#') === 0) js = ''; // If it's an internal anchor, don't add any JS since the webview is going to handle navigating to the right place
|
||||
return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${hrefAttr}' onclick='${js}'>${icon}`;
|
||||
return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${hrefAttr}' onclick='${js}' type='${htmlentities(mime)}'>${icon}`;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,8 @@ const Alarm = require('lib/models/Alarm.js');
|
||||
class AlarmService {
|
||||
static setDriver(v) {
|
||||
this.driver_ = v;
|
||||
|
||||
if (this.driver_.setService) this.driver_.setService(this);
|
||||
}
|
||||
|
||||
static driver() {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
const notifier = require('node-notifier');
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
|
||||
class AlarmServiceDriverNode {
|
||||
constructor(options) {
|
||||
@@ -6,6 +7,15 @@ class AlarmServiceDriverNode {
|
||||
// https://github.com/mikaelbr/node-notifier/issues/144#issuecomment-319324058
|
||||
this.appName_ = options.appName;
|
||||
this.notifications_ = {};
|
||||
this.service_ = null;
|
||||
}
|
||||
|
||||
setService(s) {
|
||||
this.service_ = s;
|
||||
}
|
||||
|
||||
logger() {
|
||||
return this.service_.logger();
|
||||
}
|
||||
|
||||
hasPersistentNotifications() {
|
||||
@@ -31,15 +41,46 @@ class AlarmServiceDriverNode {
|
||||
throw new Error(`Trying to create a notification from an invalid object: ${JSON.stringify(notification)}`);
|
||||
}
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
const o = {
|
||||
appName: this.appName_,
|
||||
title: notification.title,
|
||||
};
|
||||
if ('body' in notification) o.message = notification.body;
|
||||
notifier.notify(o);
|
||||
this.clearNotification(notification.id);
|
||||
}, interval);
|
||||
this.logger().info(`AlarmServiceDriverNode::scheduleNotification: Notification ${notification.id} with interval: ${interval}ms`);
|
||||
|
||||
if (this.notifications_[notification.id]) clearTimeout(this.notifications_[notification.id].timeoutId);
|
||||
|
||||
let timeoutId = null;
|
||||
|
||||
// Note: setTimeout will break for values larger than Number.MAX_VALUE - in which case the timer
|
||||
// will fire immediately. So instead, if the interval is greater than a set max, reschedule after
|
||||
// that max interval.
|
||||
// https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values/3468699
|
||||
|
||||
const maxInterval = 60 * 60 * 1000;
|
||||
if (interval >= maxInterval) {
|
||||
this.logger().info(`AlarmServiceDriverNode::scheduleNotification: Notification interval is greater than ${maxInterval}ms - will reschedule in ${maxInterval}ms`);
|
||||
|
||||
timeoutId = setTimeout(() => {
|
||||
if (!this.notifications_[notification.id]) {
|
||||
this.logger().info(`AlarmServiceDriverNode::scheduleNotification: Notification ${notification.id} has been deleted - not rescheduling it`);
|
||||
return;
|
||||
}
|
||||
this.scheduleNotification(this.notifications_[notification.id]);
|
||||
}, maxInterval);
|
||||
} else {
|
||||
timeoutId = setTimeout(() => {
|
||||
const o = {
|
||||
appID: this.appName_,
|
||||
title: notification.title,
|
||||
icon: `${bridge().electronApp().buildDir()}/icons/512x512.png`,
|
||||
};
|
||||
if ('body' in notification) o.message = notification.body;
|
||||
|
||||
this.logger().info('AlarmServiceDriverNode::scheduleNotification: Triggering notification:', o);
|
||||
|
||||
notifier.notify(o, (error, response) => {
|
||||
this.logger().info('AlarmServiceDriverNode::scheduleNotification: node-notifier response:', error, response);
|
||||
});
|
||||
|
||||
this.clearNotification(notification.id);
|
||||
}, interval);
|
||||
}
|
||||
|
||||
this.notifications_[notification.id] = Object.assign({}, notification);
|
||||
this.notifications_[notification.id].timeoutId = timeoutId;
|
||||
|
@@ -273,7 +273,7 @@ class EncryptionService {
|
||||
ks: 128, // Key size - "128 bits should be secure enough"
|
||||
ts: 64, // ???
|
||||
mode: 'ocb2', // The cipher mode is a standard for how to use AES and other algorithms to encrypt and authenticate your message. OCB2 mode is slightly faster and has more features, but CCM mode has wider support because it is not patented.
|
||||
//"adata":"", // Associated Data - not needed?
|
||||
// "adata":"", // Associated Data - not needed?
|
||||
cipher: 'aes',
|
||||
});
|
||||
} catch (error) {
|
||||
|
@@ -8,6 +8,7 @@ const { fileExtension, basename } = require('lib/path-utils');
|
||||
const spawn = require('child_process').spawn;
|
||||
const chokidar = require('chokidar');
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
|
||||
class ExternalEditWatcher {
|
||||
constructor() {
|
||||
@@ -51,7 +52,11 @@ class ExternalEditWatcher {
|
||||
if (!this.watcher_) {
|
||||
this.watcher_ = this.chokidar_.watch(fileToWatch);
|
||||
this.watcher_.on('all', async (event, path) => {
|
||||
this.logger().debug(`ExternalEditWatcher: Event: ${event}: ${path}`);
|
||||
// For now, to investigate the lost content issue when using an external editor,
|
||||
// make all the debug statement to info() so that it goes to the log file.
|
||||
// Those that were previous debug() statements are marked as "was_debug"
|
||||
|
||||
/* was_debug */ this.logger().info(`ExternalEditWatcher: Event: ${event}: ${path}`);
|
||||
|
||||
if (event === 'unlink') {
|
||||
// File are unwatched in the stopWatching functions below. When we receive an unlink event
|
||||
@@ -67,12 +72,37 @@ class ExternalEditWatcher {
|
||||
const note = await Note.load(id);
|
||||
|
||||
if (!note) {
|
||||
this.logger().warn(`Watched note has been deleted: ${id}`);
|
||||
this.logger().warn(`ExternalEditWatcher: Watched note has been deleted: ${id}`);
|
||||
this.stopWatching(id);
|
||||
return;
|
||||
}
|
||||
|
||||
const noteContent = await shim.fsDriver().readFile(path, 'utf-8');
|
||||
let noteContent = await shim.fsDriver().readFile(path, 'utf-8');
|
||||
|
||||
// In some very rare cases, the "change" event is going to be emitted but the file will be empty.
|
||||
// This is likely to be the editor that first clears the file, then writes the content to it, so if
|
||||
// the file content is read very quickly after the change event, we'll get empty content.
|
||||
// Usually, re-reading the content again will fix the issue and give back the file content.
|
||||
// To replicate on Windows: associate Typora as external editor, and leave Ctrl+S pressed -
|
||||
// it will keep on saving very fast and the bug should happen at some point.
|
||||
// Below we re-read the file multiple times until we get the content, but in my tests it always
|
||||
// work in the first try anyway. The loop is just for extra safety.
|
||||
// https://github.com/laurent22/joplin/issues/1854
|
||||
if (!noteContent) {
|
||||
this.logger().warn(`ExternalEditWatcher: Watched note is empty - this is likely to be a bug and re-reading the note should fix it. Trying again... ${id}`);
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
noteContent = await shim.fsDriver().readFile(path, 'utf-8');
|
||||
if (noteContent) {
|
||||
this.logger().info(`ExternalEditWatcher: Note is now readable: ${id}`);
|
||||
break;
|
||||
}
|
||||
await time.msleep(100);
|
||||
}
|
||||
|
||||
if (!noteContent) this.logger().warn(`ExternalEditWatcher: Could not re-read note - user might have purposely deleted note content: ${id}`);
|
||||
}
|
||||
|
||||
const updatedNote = await Note.unserializeForEdit(noteContent);
|
||||
updatedNote.id = id;
|
||||
updatedNote.parent_id = note.parent_id;
|
||||
@@ -197,7 +227,7 @@ class ExternalEditWatcher {
|
||||
|
||||
const iid = setInterval(() => {
|
||||
if (subProcess && subProcess.pid) {
|
||||
this.logger().debug(`Started editor with PID ${subProcess.pid}`);
|
||||
/* was_debug */ this.logger().info(`Started editor with PID ${subProcess.pid}`);
|
||||
clearInterval(iid);
|
||||
resolve();
|
||||
}
|
||||
@@ -273,7 +303,7 @@ class ExternalEditWatcher {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger().debug(`ExternalEditWatcher: Update note file: ${note.id}`);
|
||||
/* was_debug */ this.logger().info(`ExternalEditWatcher: Update note file: ${note.id}`);
|
||||
|
||||
// When the note file is updated programmatically, we skip the next change event to
|
||||
// avoid update loops. We only want to listen to file changes made by the user.
|
||||
|
@@ -13,7 +13,8 @@ const { toTitleCase } = require('lib/string-utils');
|
||||
|
||||
class InteropService {
|
||||
constructor() {
|
||||
this.modules_ = null; }
|
||||
this.modules_ = null;
|
||||
}
|
||||
|
||||
modules() {
|
||||
if (this.modules_) return this.modules_;
|
||||
|
@@ -1,5 +1,7 @@
|
||||
/* eslint @typescript-eslint/no-unused-vars: 0, no-unused-vars: ["error", { "argsIgnorePattern": ".*" }], */
|
||||
|
||||
const Setting = require('lib/models/Setting');
|
||||
|
||||
class InteropService_Exporter_Base {
|
||||
async init(destDir) {}
|
||||
async processItem(ItemClass, item) {}
|
||||
@@ -24,7 +26,7 @@ class InteropService_Exporter_Base {
|
||||
|
||||
async temporaryDirectory_(createIt) {
|
||||
const md5 = require('md5');
|
||||
const tempDir = `${require('os').tmpdir()}/${md5(Math.random() + Date.now())}`;
|
||||
const tempDir = `${Setting.value('tempDir')}/${md5(Math.random() + Date.now())}`;
|
||||
if (createIt) await require('fs-extra').mkdirp(tempDir);
|
||||
return tempDir;
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
const Setting = require('lib/models/Setting');
|
||||
|
||||
class InteropService_Importer_Base {
|
||||
setMetadata(md) {
|
||||
this.metadata_ = md;
|
||||
@@ -16,7 +18,7 @@ class InteropService_Importer_Base {
|
||||
|
||||
async temporaryDirectory_(createIt) {
|
||||
const md5 = require('md5');
|
||||
const tempDir = `${require('os').tmpdir()}/${md5(Math.random() + Date.now())}`;
|
||||
const tempDir = `${Setting.value('tempDir')}/${md5(Math.random() + Date.now())}`;
|
||||
if (createIt) await require('fs-extra').mkdirp(tempDir);
|
||||
return tempDir;
|
||||
}
|
||||
|
@@ -19,8 +19,7 @@ class ResourceService extends BaseService {
|
||||
let foundNoteWithEncryption = false;
|
||||
|
||||
while (true) {
|
||||
const changes = await ItemChange.modelSelectAll(
|
||||
`
|
||||
const changes = await ItemChange.modelSelectAll(`
|
||||
SELECT id, item_id, type
|
||||
FROM item_changes
|
||||
WHERE item_type = ?
|
||||
@@ -28,7 +27,7 @@ class ResourceService extends BaseService {
|
||||
ORDER BY id ASC
|
||||
LIMIT 10
|
||||
`,
|
||||
[BaseModel.TYPE_NOTE, Setting.value('resourceService.lastProcessedChangeId')]
|
||||
[BaseModel.TYPE_NOTE, Setting.value('resourceService.lastProcessedChangeId')]
|
||||
);
|
||||
|
||||
if (!changes.length) break;
|
||||
@@ -54,16 +53,16 @@ class ResourceService extends BaseService {
|
||||
if (change.type === ItemChange.TYPE_CREATE || change.type === ItemChange.TYPE_UPDATE) {
|
||||
const note = noteById(change.item_id);
|
||||
|
||||
if (note.encryption_applied) {
|
||||
// If we hit an encrypted note, abort processing for now.
|
||||
// Note will eventually get decrypted and processing can resume then.
|
||||
// This is a limitation of the change tracking system - we cannot skip a change
|
||||
// and keep processing the rest since we only keep track of "lastProcessedChangeId".
|
||||
foundNoteWithEncryption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (note) {
|
||||
if (note.encryption_applied) {
|
||||
// If we hit an encrypted note, abort processing for now.
|
||||
// Note will eventually get decrypted and processing can resume then.
|
||||
// This is a limitation of the change tracking system - we cannot skip a change
|
||||
// and keep processing the rest since we only keep track of "lastProcessedChangeId".
|
||||
foundNoteWithEncryption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
await this.setAssociatedResources_(note);
|
||||
} else {
|
||||
this.logger().warn(`ResourceService::indexNoteResources: A change was recorded for a note that has been deleted: ${change.item_id}`);
|
||||
|
@@ -354,12 +354,28 @@ class Api {
|
||||
return options;
|
||||
}
|
||||
|
||||
defaultLoadOptions_(request) {
|
||||
const options = {};
|
||||
const fields = this.fields_(request, []);
|
||||
if (fields.length) options.fields = fields;
|
||||
return options;
|
||||
}
|
||||
|
||||
async action_notes(request, id = null, link = null) {
|
||||
this.checkToken_(request);
|
||||
|
||||
if (request.method === 'GET') {
|
||||
if (link && link === 'tags') {
|
||||
return Tag.tagsByNoteId(id);
|
||||
} else if (link && link === 'resources') {
|
||||
const note = await Note.load(id);
|
||||
const resourceIds = await Note.linkedResourceIds(note.body);
|
||||
const output = [];
|
||||
const loadOptions = this.defaultLoadOptions_(request);
|
||||
for (let resourceId of resourceIds) {
|
||||
output.push(await Resource.load(resourceId, loadOptions));
|
||||
}
|
||||
return output;
|
||||
} else if (link) {
|
||||
throw new ErrorNotFound();
|
||||
}
|
||||
@@ -552,7 +568,7 @@ class Api {
|
||||
return output;
|
||||
}
|
||||
|
||||
async downloadImage_(url /*, allowFileProtocolImages */) {
|
||||
async downloadImage_(url /* , allowFileProtocolImages */) {
|
||||
const tempDir = Setting.value('tempDir');
|
||||
|
||||
const isDataUrl = url && url.toLowerCase().indexOf('data:') === 0;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user