You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-30 20:39:46 +02:00
Compare commits
95 Commits
android-v1
...
cli-v1.0.1
Author | SHA1 | Date | |
---|---|---|---|
|
5710e3fad0 | ||
|
a03aa62d58 | ||
|
2203a39917 | ||
|
bc58668483 | ||
|
0b4650f355 | ||
|
aecdec48ad | ||
|
e49198a0d4 | ||
|
6aa4553dd3 | ||
|
860e8a8f5a | ||
|
434037d793 | ||
|
214eae27da | ||
|
0567188fa8 | ||
|
4326902683 | ||
|
da3589149d | ||
|
69b4b4d1f4 | ||
|
dd4b46a88b | ||
|
6f2253b2f4 | ||
|
4c00d9512e | ||
|
6f511cb1e6 | ||
|
029e84f538 | ||
|
42b1db1d08 | ||
|
9d4b34cad7 | ||
|
cd9aff0f59 | ||
|
032816fffc | ||
|
1408f06c8d | ||
|
49f8d0c6d8 | ||
|
0d6443c30a | ||
|
e62d91dda8 | ||
|
0e122c9dc5 | ||
|
c2bd453e8c | ||
|
949ea7afb7 | ||
|
9f575101d2 | ||
|
2b4470054e | ||
|
b220613e54 | ||
|
11328babe8 | ||
|
735bc92bc4 | ||
|
6894b9b1b7 | ||
|
4de7815f31 | ||
|
4ce7b48468 | ||
|
77e4cb87ad | ||
|
dd6b43035e | ||
|
e76094c546 | ||
|
9c00dc4cab | ||
|
fc416de348 | ||
|
a2156be4ec | ||
|
cf427eba0f | ||
|
0050c90678 | ||
|
5eeff02dbe | ||
|
eb283efc20 | ||
|
87121c9c21 | ||
|
a2dbbbf832 | ||
|
fd251cd9a9 | ||
|
8ced2d288e | ||
|
242926d381 | ||
|
8c9a148e71 | ||
|
9e165fc7dc | ||
|
f46e4e0cec | ||
|
efcf5ecef4 | ||
|
b6ba843d09 | ||
|
915112e274 | ||
|
cc8f8fcd2c | ||
|
bda3ea9a35 | ||
|
a7aed1f93a | ||
|
a33f602f3b | ||
|
4d08b49578 | ||
|
21e049ab45 | ||
|
1d4234caea | ||
|
d1269de3a7 | ||
|
8c19fcf8fc | ||
|
beaba2be55 | ||
|
32c9ad1d59 | ||
|
a194513252 | ||
|
cd93a1d1e1 | ||
|
2867728996 | ||
|
394cc78851 | ||
|
76f0a26322 | ||
|
92d7a577a0 | ||
|
9c1219b188 | ||
|
f62bbfe286 | ||
|
fef176eb96 | ||
|
ed541dac3b | ||
|
4a175b2158 | ||
|
4076899e11 | ||
|
998bdf3b56 | ||
|
76b211eb6d | ||
|
f781cb3922 | ||
|
ced3e5d623 | ||
|
2a4812cb87 | ||
|
1f384c7ae4 | ||
|
01a3285636 | ||
|
53166cb3f5 | ||
|
893462ae87 | ||
|
949dbf45f1 | ||
|
d7dc625042 | ||
|
cc91c77f9e |
@@ -16,14 +16,16 @@ If possible, **please provide a screenshot**. A screenshot showing the problem i
|
||||
|
||||
Again, please check that it has not already been requested. If it has, simply **up-vote the issue** - the ones with the most up-votes are likely to be implemented. "+1" comments are not tracked.
|
||||
|
||||
# Adding new features
|
||||
# Creating a pull request
|
||||
|
||||
If you want to add a new feature, consider asking about it before implementing it or checking existing discussions to make sure it is within the scope of the project. Of course you are free to create the pull request directly but it is not guaranteed it is going to be accepted.
|
||||
- If you want to add a new feature, consider asking about it before implementing it or checking existing discussions to make sure it is within the scope of the project. That scope, due to limited resources, might be narrower than you think. As a rule of thumb **if your change is likely to involve more than 50 lines of code, you should discuss it in the forum**, just so that you don't waste your time implementing something that might not be accepted.
|
||||
|
||||
- Bug fixes have a very high change of being accepted.
|
||||
|
||||
- A pull request that is relevant to the current roadmap has a very high change of being accepted.
|
||||
|
||||
Building the apps is relatively easy - please [see the build instructions](https://github.com/laurent22/joplin/blob/master/BUILD.md) for more details.
|
||||
|
||||
Pull requests that automatically change many files tend to be rejected (for example changes that automatically update the code styling, or to add new lines to many files, or to automatically convert images to a different format) so if you have such a pull request in mind, please discuss it first in the forum.
|
||||
|
||||
# Coding style
|
||||
|
||||
There are only two rules, but not following them means the pull request will not be accepted (it can be accepted once the issues are fixed):
|
||||
|
@@ -22,6 +22,7 @@ const os = require('os');
|
||||
const fs = require('fs-extra');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const Cache = require('lib/Cache');
|
||||
const WelcomeUtils = require('lib/WelcomeUtils');
|
||||
|
||||
class Application extends BaseApplication {
|
||||
|
||||
@@ -376,6 +377,8 @@ class Application extends BaseApplication {
|
||||
return this.stdout(object);
|
||||
});
|
||||
|
||||
await WelcomeUtils.install(this.dispatch.bind(this));
|
||||
|
||||
// If we have some arguments left at this point, it's a command
|
||||
// so execute it.
|
||||
if (argv.length) {
|
||||
@@ -393,6 +396,12 @@ class Application extends BaseApplication {
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await Setting.saveAll();
|
||||
|
||||
// Need to call exit() explicitely, otherwise Node wait for any timeout to complete
|
||||
// https://stackoverflow.com/questions/18050095
|
||||
process.exit(0);
|
||||
} else { // Otherwise open the GUI
|
||||
this.initRedux();
|
||||
|
||||
|
@@ -154,11 +154,11 @@ class Command extends BaseCommand {
|
||||
type: Database.enumId('fieldType', 'text'),
|
||||
description: 'If an image is provided, you can also specify an optional rectangle that will be used to crop the image. In format `{ x: x, y: y, width: width, height: height }`',
|
||||
});
|
||||
tableFields.push({
|
||||
name: 'tags',
|
||||
type: Database.enumId('fieldType', 'text'),
|
||||
description: 'Comma-separated list of tags. eg. `tag1,tag2`.',
|
||||
});
|
||||
// tableFields.push({
|
||||
// name: 'tags',
|
||||
// type: Database.enumId('fieldType', 'text'),
|
||||
// description: 'Comma-separated list of tags. eg. `tag1,tag2`.',
|
||||
// });
|
||||
}
|
||||
|
||||
lines.push('# ' + toTitleCase(tableName));
|
||||
|
@@ -1,5 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Use njstrace to find out what Node.js might be spending time on
|
||||
// var njstrace = require('njstrace').inject();
|
||||
|
||||
// Make it possible to require("/lib/...") without specifying full path
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
|
@@ -589,6 +589,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "S'està exportant a «%s» com a format «%s». Espereu..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Títol del bloc de notes:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Blocs de notes"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "S'està important des de «%s» com a format «%s». Espereu..."
|
||||
@@ -646,6 +660,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -668,6 +685,10 @@ msgstr "Mostra o amaga la barra lateral"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Canvia el disseny de l'editor"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Vés al cos"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Eines"
|
||||
|
||||
@@ -807,13 +828,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Comprova la configuració de la sincronització"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Les notes i la configuració es desen a: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Comprova la configuració de la sincronització"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -908,6 +932,10 @@ msgstr "Estat"
|
||||
msgid "Encryption is:"
|
||||
msgstr "El xifratge és:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Ús: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Enrere"
|
||||
|
||||
@@ -958,36 +986,6 @@ msgstr "Alguns elements no s'han pogut desxifrar."
|
||||
msgid "Set the password"
|
||||
msgstr "Establiu la contrasenya"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Afegeix o suprimeix etiquetes"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Copia"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Alterna entre el tipus nota i tasques pendents"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Alterna entre el tipus nota i tasques pendents"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Alterna entre el tipus nota i tasques pendents"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copia l'enllaç Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Suprimeix"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Voleu suprimir les notes?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "No hi ha cap nota aquí. Creeu-ne una fent clic a «Nota nova»."
|
||||
|
||||
@@ -1133,6 +1131,9 @@ msgstr "Voleu suprimir aquesta etiqueta de totes les notes?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Voleu suprimir aquesta cerca de la barra laterla?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Suprimeix"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Canvia el nom"
|
||||
|
||||
@@ -1481,6 +1482,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "El valor de l'opció no és vàlid: «%s». Els valors possibles són: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Opcions generals"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Estat de la sincronització"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Blocs de notes"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Surt de l'aplicació"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1776,6 +1796,9 @@ msgstr "Converteix a nota"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Converteix a llistat de tasques pendents"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copia l'enllaç Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Amaga les metadades"
|
||||
|
||||
@@ -1811,6 +1834,27 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Benvingut"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Afegeix o suprimeix etiquetes"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Copia"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Alterna entre el tipus nota i tasques pendents"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Alterna entre el tipus nota i tasques pendents"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Alterna entre el tipus nota i tasques pendents"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Voleu suprimir les notes?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Estat: %s"
|
||||
|
||||
|
@@ -571,6 +571,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exportuji do \"%s\" jako formát \"%s\". Chvíli strpení..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Název zápisníku:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Zápisníky"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importuji z \"%s\" jako formát \"%s\". Chvíli strpení..."
|
||||
@@ -628,6 +642,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -650,6 +667,10 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Změňit layout editoru"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Vybrat text poznámky"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Nástroje"
|
||||
|
||||
@@ -782,13 +803,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Zkontrolujte nastavení synchronizace"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Poznámky a nastavení uloženo v: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Zkontrolujte nastavení synchronizace"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -878,6 +902,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Šifrování je:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Použití: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Zpět"
|
||||
|
||||
@@ -930,37 +958,6 @@ msgstr "Některé položky nelze rozšifrovat."
|
||||
msgid "Set the password"
|
||||
msgstr "Nastavit heslo"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Přidat či odebrat tagy"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Kopírovat"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Přepnout mezi poznámkou a to-do"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Přepnout mezi poznámkou a to-do"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Přepnout mezi poznámkou a to-do"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Smazat"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Smazat poznámky?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Žádné poznámky. Vytvořte jednu kliknutím na \"Nová poznámka\"."
|
||||
|
||||
@@ -1103,6 +1100,9 @@ msgstr "Odebrat tento tag ze všech poznámek?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Smazat tento hledaný výraz z panelu?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Smazat"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Přejmenovat"
|
||||
|
||||
@@ -1456,6 +1456,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Neplatná hodnota: \"%s\". Přípustné hodnoty jsou: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Obecná nastavení"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Stav synchronizace"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Zápisníky"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Ukončí aplikaci."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1745,6 +1764,10 @@ msgstr "Konvertovat na poznámku"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Konvertovat na todo"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Schovat metadata"
|
||||
|
||||
@@ -1779,6 +1802,27 @@ msgstr "Nemáte žádný zápisník. Vytvořte jeden kliknutím na tlačítko (+
|
||||
msgid "Welcome"
|
||||
msgstr "Vítejte"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Přidat či odebrat tagy"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Kopírovat"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Přepnout mezi poznámkou a to-do"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Přepnout mezi poznámkou a to-do"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Přepnout mezi poznámkou a to-do"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Smazat poznámky?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Stav: %s."
|
||||
|
||||
|
@@ -576,6 +576,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Eksporterer til \"%s\" som \"%s\"-format. Vent venligst..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Notesbogs titel:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Notesbøger"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importerer fra \"%s\" som \"%s\"-format. Vent venligst..."
|
||||
@@ -633,6 +647,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -655,6 +672,10 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Skift editor layout"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Fokuser på brødtekst"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Værktøjer"
|
||||
|
||||
@@ -787,13 +808,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Check synkroniserings Indstillinger"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Noter og indstillinger er gemt i: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Check synkroniserings Indstillinger"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -887,6 +911,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Kryptering er:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Forbrug: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Tilbage"
|
||||
|
||||
@@ -939,37 +967,6 @@ msgstr "Nogle emner kan ikke krypteres."
|
||||
msgid "Set the password"
|
||||
msgstr "Indstil kodeord"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Tilføj eller slet mærker"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Kopier"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Skift mellem note- og opgave type"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Skift mellem note- og opgave type"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Skift mellem note- og opgave type"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Slet"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Slet noter?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Der er ingen noter her. Opret en ved at klikke på \"Ny note\"."
|
||||
|
||||
@@ -1112,6 +1109,9 @@ msgstr "Slet denne markering fra alle noter?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Slet denne søgning fra sidebjælke?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Slet"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Omdøb"
|
||||
|
||||
@@ -1465,6 +1465,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Ulovlig værdi: \"%s\". Mulige valg er: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Generelle indstillinger"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Synkroniserings status"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Notesbøger"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Forlad/luk program."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1754,6 +1773,10 @@ msgstr "Konverter til note"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Konverter til opgave"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Skjul metadata"
|
||||
|
||||
@@ -1788,6 +1811,27 @@ msgstr "Du har ingen notesbøger. Opret en ved at klikke på (+) knappen."
|
||||
msgid "Welcome"
|
||||
msgstr "Velkommen"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Tilføj eller slet mærker"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Kopier"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Skift mellem note- og opgave type"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Skift mellem note- og opgave type"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Skift mellem note- og opgave type"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Slet noter?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Tilstand: %s."
|
||||
|
||||
|
@@ -598,6 +598,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exportiere „%s“ ins „%s“ Format. Bitte warten..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Notizbuch-Titel:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Notizbücher"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importiere „%s“ ins „%s“ Format. Bitte warten..."
|
||||
@@ -654,6 +668,9 @@ msgstr "Fett"
|
||||
msgid "Italic"
|
||||
msgstr "Kursiv"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Datum / Uhrzeit einfügen"
|
||||
|
||||
@@ -675,6 +692,10 @@ msgstr "Seitenleiste umschalten"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Editor-Layout umschalten"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Fokussiere Inhalt"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Werkzeuge"
|
||||
|
||||
@@ -817,13 +838,16 @@ msgstr ""
|
||||
"Dieses Autorisierung-Token wird nur benötigt, um Drittanbieter-Anwendungen "
|
||||
"Zugriff auf Joplin zu gewähren."
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Überprüfen der Synchronisationseinstellungen"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Notizen und Einstellungen werden gespeichert in: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Überprüfen der Synchronisationseinstellungen"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Anwenden"
|
||||
|
||||
@@ -917,6 +941,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Die Verschlüsselung ist:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Nutzung: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Zurück"
|
||||
|
||||
@@ -969,34 +997,6 @@ msgstr "Einige Objekte können nicht entschlüsselt werden."
|
||||
msgid "Set the password"
|
||||
msgstr "Setze ein Passwort"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Schlagwörter hinzufügen oder entfernen"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Duplizieren"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Kopieren"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Zwischen Notiz und To-Do Typ wechseln"
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr "Zu Notiz-Typ wechseln"
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Zu To-Do-Typ wechseln"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown-Link kopieren"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Notizen löschen?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr ""
|
||||
"Keine Notizen vorhanden. Erstelle eine, indem du auf \"Neue Notiz\" drückst."
|
||||
@@ -1144,6 +1144,9 @@ msgstr "Dieses Schlagwort von allen Notizen entfernen?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Diese Suche von der Seitenleiste entfernen?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Umbenennen"
|
||||
|
||||
@@ -1503,6 +1506,26 @@ msgstr "Ignoriere TLS-Zertifikatfehler"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Ungültiger Optionswert: \"%s\". Mögliche Werte sind: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Allgemeine Einstellungen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Status der Synchronisation"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Notizbücher"
|
||||
|
||||
# Please note: The term 'Location' is assumed to be the geographical location where the note has been created. For this the german word 'Standort' fits better than the previously used 'Ablageort'. The latter one is used for the folder where files are stored.
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Standort"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1730,7 +1753,6 @@ msgstr "FTS aktiviert: %d"
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Mit Dropbox anmelden"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enter code here"
|
||||
msgstr "Hier Code eingeben"
|
||||
|
||||
@@ -1804,6 +1826,9 @@ msgstr "In eine Notiz umwandeln"
|
||||
msgid "Convert to todo"
|
||||
msgstr "In ein To-Do umwandeln"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown-Link kopieren"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Metadaten verstecken"
|
||||
|
||||
@@ -1841,6 +1866,27 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Willkommen"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Schlagwörter hinzufügen oder entfernen"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Duplizieren"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Kopieren"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Zwischen Notiz und To-Do Typ wechseln"
|
||||
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Zu Notiz-Typ wechseln"
|
||||
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Zu To-Do-Typ wechseln"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Notizen löschen?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Status: %s."
|
||||
|
||||
@@ -1902,7 +1948,6 @@ msgstr "Willkommen"
|
||||
#~ msgid "Set a to-do as completed / not completed"
|
||||
#~ msgstr "Ein To-Do als abgeschlossen / nicht abgeschlossen markieren"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "[t]oggle [c]onsole between maximized/minimized/hidden/visible."
|
||||
#~ msgstr ""
|
||||
#~ "Schal[t]e das Terminal zwischen maximiert/minimiert/versteckt/sichtbar um."
|
||||
|
@@ -508,6 +508,18 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
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 ""
|
||||
@@ -564,6 +576,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -585,6 +600,9 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tools"
|
||||
msgstr ""
|
||||
|
||||
@@ -716,13 +734,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -801,6 +822,9 @@ msgstr ""
|
||||
msgid "Encryption is:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Usage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
@@ -851,34 +875,6 @@ msgstr ""
|
||||
msgid "Set the password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr ""
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr ""
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr ""
|
||||
|
||||
@@ -1019,6 +1015,9 @@ msgstr ""
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rename"
|
||||
msgstr ""
|
||||
|
||||
@@ -1347,6 +1346,21 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
||||
msgid "Application"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1623,6 +1637,9 @@ msgstr ""
|
||||
msgid "Convert to todo"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -585,6 +585,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exportando el formato de \"%s\" a \"%s\". Por favor espere..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Título de libreta:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Libretas"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importando el formato de \"%s\" a \"%s\". Por favor espere..."
|
||||
@@ -642,6 +656,9 @@ msgstr "Negrita"
|
||||
msgid "Italic"
|
||||
msgstr "Cursiva"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Introduce fecha"
|
||||
|
||||
@@ -664,6 +681,10 @@ msgstr "Cambia la barra lateral"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Cambia el diseño del editor"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Foco en el cuerpo"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Herramientas"
|
||||
|
||||
@@ -803,13 +824,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Comprobar sincronización"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Las notas y los ajustes se guardan en: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Comprobar sincronización"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Aplicar"
|
||||
|
||||
@@ -903,6 +927,10 @@ msgstr "Estado"
|
||||
msgid "Encryption is:"
|
||||
msgstr "El cifrado está:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Uso: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Atrás"
|
||||
|
||||
@@ -953,36 +981,6 @@ msgstr "No se han podido descifrar algunos elementos."
|
||||
msgid "Set the password"
|
||||
msgstr "Establecer la contraseña"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Añadir o borrar etiquetas"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Duplicado"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Copiar"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Cambiar entre nota y lista de tareas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Cambiar entre nota y lista de tareas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Cambiar entre nota y lista de tareas"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copiar el enlace de Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "¿Desea eliminar notas?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "No hay ninguna nota. Cree una pulsando «Nota nueva»."
|
||||
|
||||
@@ -1125,6 +1123,9 @@ msgstr "¿Desea eliminar esta etiqueta de todas las notas?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "¿Desea eliminar esta búsqueda de la barra lateral?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Renombrar"
|
||||
|
||||
@@ -1479,6 +1480,25 @@ msgstr "Ignorar errores en certificados TLS"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Opción inválida: «%s». Los valores posibles son: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Opciones generales"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Estado de la sincronización"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Libretas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Salir de la aplicación."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1775,6 +1795,9 @@ msgstr "Convertir a nota"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Convertir a lista de tareas"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copiar el enlace de Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Ocultar metadatos"
|
||||
|
||||
@@ -1810,6 +1833,29 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Bienvenido"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Añadir o borrar etiquetas"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Duplicado"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Copiar"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Cambiar entre nota y lista de tareas"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Cambiar entre nota y lista de tareas"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Cambiar entre nota y lista de tareas"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "¿Desea eliminar notas?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Estado: «%s»."
|
||||
|
||||
@@ -1869,9 +1915,6 @@ msgstr "Bienvenido"
|
||||
#~ msgid "Cancel the current command."
|
||||
#~ msgstr "Cancelar el comando actual."
|
||||
|
||||
#~ msgid "Exit the application."
|
||||
#~ msgstr "Salir de la aplicación."
|
||||
|
||||
#~ msgid "Delete the currently selected note or notebook."
|
||||
#~ msgstr "Eliminar la nota o libreta seleccionada."
|
||||
|
||||
|
@@ -582,6 +582,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Koadernoaren izenburua: "
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Koadernoak"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
@@ -641,6 +655,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -663,6 +680,9 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Tresnak"
|
||||
|
||||
@@ -797,14 +817,17 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Sinkronizazioa utzi"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Oharrak eta ezarpenak hemen daude gordeta: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Sinkronizazioa utzi"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -895,6 +918,10 @@ msgstr "Egoera"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Zifratua da:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Erabili: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Atzera"
|
||||
|
||||
@@ -949,36 +976,6 @@ msgstr "Zenbait item ezin dira deszifratu."
|
||||
msgid "Set the password"
|
||||
msgstr "Ezarri pasahitza"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Gehitu edo ezabatu etiketak"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Kopiatu"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Aldatu oharra eta zeregin eren artean."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Aldatu oharra eta zeregin eren artean."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Aldatu oharra eta zeregin eren artean."
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Ezabatu"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Oharrak ezabatu?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Hemen ez dago oharrik. Sortu bat \"Ohar berria\" sakatuta."
|
||||
|
||||
@@ -1125,6 +1122,9 @@ msgstr "Kendu etiketa hori ohar guztietatik?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Kendu bilaketa hori ohar guztietatik?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Ezabatu"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Berrizendatu"
|
||||
|
||||
@@ -1486,6 +1486,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Balio aukera baliogabea: \"%s\". Litezkeen balioak: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Ezarpenak"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Sinkronizazioaren egoera"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Koadernoak"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Irten aplikaziotik"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1776,6 +1795,9 @@ msgstr "Oharra bihurtu"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Zeregina bihurtu"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Ezkutatu metadatuak"
|
||||
|
||||
@@ -1810,6 +1832,27 @@ msgstr "Oraindik ez duzu koadernorik. Sortu bat (+) botoian sakatuta."
|
||||
msgid "Welcome"
|
||||
msgstr "Ongi etorri!"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Gehitu edo ezabatu etiketak"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Kopiatu"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Aldatu oharra eta zeregin eren artean."
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Aldatu oharra eta zeregin eren artean."
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Aldatu oharra eta zeregin eren artean."
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Oharrak ezabatu?"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Egoera: \"%s\"."
|
||||
@@ -1861,9 +1904,6 @@ msgstr "Ongi etorri!"
|
||||
#~ msgid "Cancel the current command."
|
||||
#~ msgstr "Utzi uneko komandoa"
|
||||
|
||||
#~ msgid "Exit the application."
|
||||
#~ msgstr "Irten aplikaziotik"
|
||||
|
||||
#~ msgid "Delete the currently selected note or notebook."
|
||||
#~ msgstr "Ezabatu aukeratutako oharra edo koadernoa"
|
||||
|
||||
|
@@ -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.0.3\n"
|
||||
"X-Generator: Poedit 2.2.1\n"
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr "Pour supprimer une vignette, enlever là des notes associées."
|
||||
@@ -583,6 +583,18 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exporter vers \"%s\" au format \"%s\". Veuillez patienter..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr "Barre latérale"
|
||||
|
||||
msgid "Note list"
|
||||
msgstr "Liste de notes"
|
||||
|
||||
msgid "Note title"
|
||||
msgstr "Titre de la note"
|
||||
|
||||
msgid "Note body"
|
||||
msgstr "Corps de la note"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importer depuis \"%s\" au format \"%s\". Veuillez patienter..."
|
||||
@@ -639,6 +651,9 @@ msgstr "Gras"
|
||||
msgid "Italic"
|
||||
msgstr "Italique"
|
||||
|
||||
msgid "Link"
|
||||
msgstr "Lien"
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Insérer la date et l'heure"
|
||||
|
||||
@@ -660,6 +675,9 @@ msgstr "Basculer barre latérale"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Basculer l'agencement de l'éditeur"
|
||||
|
||||
msgid "Focus"
|
||||
msgstr "Naviguer"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Outils"
|
||||
|
||||
@@ -801,13 +819,16 @@ msgstr ""
|
||||
"Ce code d'authentification est nécessaire uniquement pour permettre aux "
|
||||
"logiciels tiers d'accéder aux données de Joplin."
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Vérifier config synchronisation"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Les notes et paramètres se trouve dans : %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr "Parcourir…"
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Vérifier config synchronisation"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Appliquer"
|
||||
|
||||
@@ -903,6 +924,9 @@ msgstr "État"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Le chiffrement est :"
|
||||
|
||||
msgid "Usage"
|
||||
msgstr "Utilisation"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Retour"
|
||||
|
||||
@@ -955,34 +979,6 @@ msgstr "Certains objets ne peuvent être déchiffrés."
|
||||
msgid "Set the password"
|
||||
msgstr "Définir le mot de passe"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Gérer les étiquettes"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Dupliquer"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Copie"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Alterner entre note et tâche"
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr "Convertir en note"
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Convertir en tâche"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copier lien Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Supprimer les notes ?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr ""
|
||||
"Pas de notes ici. Créez-en une en pressant le bouton \"Nouvelle note\"."
|
||||
@@ -1130,6 +1126,9 @@ msgstr "Enlever cette étiquette de toutes les notes ?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Enlever cette recherche de la barre latérale ?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Renommer"
|
||||
|
||||
@@ -1488,6 +1487,21 @@ msgstr "Ignorer les erreurs de certificats TLS"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Option invalide: \"%s\". Les valeurs possibles sont : %s."
|
||||
|
||||
msgid "General"
|
||||
msgstr "Général"
|
||||
|
||||
msgid "Synchronisation"
|
||||
msgstr "Synchronisation"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr "Apparence"
|
||||
|
||||
msgid "Note"
|
||||
msgstr "Note"
|
||||
|
||||
msgid "Application"
|
||||
msgstr "Application"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr "L'étiquette \"%s\" existe déjà. Veuillez choisir un autre nom."
|
||||
@@ -1785,6 +1799,9 @@ msgstr "Convertir en note"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Convertir en tâche"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copier lien Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Cacher les métadonnées"
|
||||
|
||||
@@ -1821,6 +1838,27 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Bienvenue"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Gérer les étiquettes"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Dupliquer"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Copie"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Alterner entre note et tâche"
|
||||
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Convertir en note"
|
||||
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Convertir en tâche"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Supprimer les notes ?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "État : %s."
|
||||
|
||||
|
@@ -576,6 +576,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exportando a «%s» como formato «%s». Agarde..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Título do caderno:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Cadernos"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importando de «%s» como formato «%s». Agarde..."
|
||||
@@ -633,6 +647,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -655,6 +672,10 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Cambiar a disposición do editor"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Focar no corpo"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Ferramentas"
|
||||
|
||||
@@ -787,13 +808,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Comprobar a configuración da sincronización"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "As notas e axustes gardáronse en: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Comprobar a configuración da sincronización"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -885,6 +909,10 @@ msgstr "Estado"
|
||||
msgid "Encryption is:"
|
||||
msgstr "O cifrado é:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Uso: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Anterior"
|
||||
|
||||
@@ -936,37 +964,6 @@ msgstr "Non é posíbel descifrar algúns elementos."
|
||||
msgid "Set the password"
|
||||
msgstr "Estabelecer un contrasinal"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Engadir ou eliminar etiquetas"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Copiar"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Cambiar entre notas e tarefas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Cambiar entre notas e tarefas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Cambiar entre notas e tarefas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Desexa eliminar as notas?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Aquí non hai notas. Cree unha premendo en «Nova nota»."
|
||||
|
||||
@@ -1111,6 +1108,9 @@ msgstr "Desexa eliminar esta etiqueta de todas as notas?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Desexa eliminar esta busca da barra lateral?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Renomear"
|
||||
|
||||
@@ -1464,6 +1464,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Valor incorrecto de opción: «%s». Os valores posíbeis son: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Opcións xerais"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Estado da sincronización"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Cadernos"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Sae do aplicativo."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1753,6 +1772,10 @@ msgstr "Converter para nota"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Converter para tarefa"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Ocultar metadados"
|
||||
|
||||
@@ -1787,6 +1810,27 @@ msgstr "Non ten cadernos actualmente. Cree un premendo no botón (+)."
|
||||
msgid "Welcome"
|
||||
msgstr "Benvido/a"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Engadir ou eliminar etiquetas"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Copiar"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Cambiar entre notas e tarefas"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Cambiar entre notas e tarefas"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Cambiar entre notas e tarefas"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Desexa eliminar as notas?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Estado: %s."
|
||||
|
||||
|
@@ -579,6 +579,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Naslov bilježnice:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Bilježnice"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
@@ -638,6 +652,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -660,6 +677,10 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Naslov bilješke:"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Alati"
|
||||
|
||||
@@ -795,14 +816,17 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Prekini sinkronizaciju"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Bilješke i postavke su pohranjene u: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Prekini sinkronizaciju"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -881,6 +905,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Korištenje: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Natrag"
|
||||
|
||||
@@ -936,36 +964,6 @@ msgstr "Neke stavke se ne mogu sinkronizirati."
|
||||
msgid "Set the password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Dodaj ili makni oznake"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Kopiraj"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Zamijeni bilješku i zadatak"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Zamijeni bilješku i zadatak"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Zamijeni bilješku i zadatak"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Obriši"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Obriši bilješke?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Ovdje nema bilješki. Stvori novu pritiskom na \"Nova bilješka\"."
|
||||
|
||||
@@ -1111,6 +1109,9 @@ msgstr "Makni ovu oznaku iz svih bilješki?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Makni ovu pretragu iz izbornika?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Obriši"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Preimenuj"
|
||||
|
||||
@@ -1463,6 +1464,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Nevažeća vrijednost: \"%s\". Moguće vrijednosti su: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Opcije"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Status sinkronizacije"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Bilježnice"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Izađi iz aplikacije."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1752,6 +1772,9 @@ msgstr "Pretvori u bilješku"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Pretvori u zadatak"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Sakrij metapodatke"
|
||||
|
||||
@@ -1786,6 +1809,27 @@ msgstr "Trenutno nemaš nijednu bilježnicu. Stvori novu klikom na (+) gumb."
|
||||
msgid "Welcome"
|
||||
msgstr "Dobro došli"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Dodaj ili makni oznake"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Kopiraj"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Zamijeni bilješku i zadatak"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Zamijeni bilješku i zadatak"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Zamijeni bilješku i zadatak"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Obriši bilješke?"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Stanje: \"%s\"."
|
||||
@@ -1836,9 +1880,6 @@ msgstr "Dobro došli"
|
||||
#~ msgid "Cancel the current command."
|
||||
#~ msgstr "Prekini trenutnu naredbu."
|
||||
|
||||
#~ msgid "Exit the application."
|
||||
#~ msgstr "Izađi iz aplikacije."
|
||||
|
||||
#~ msgid "Delete the currently selected note or notebook."
|
||||
#~ msgstr "Obriši odabranu bilješku ili bilježnicu."
|
||||
|
||||
|
@@ -589,6 +589,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Esportazione da \"%s\" come formato \"%s\". Si prega di attendere..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Titolo del Taccuino:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Taccuini"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importazione da \"%s\" come formato \"%s\". Si prega di attendere..."
|
||||
@@ -645,6 +659,9 @@ msgstr "Grasseto"
|
||||
msgid "Italic"
|
||||
msgstr "Corsivo"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Inserisci data e ora"
|
||||
|
||||
@@ -666,6 +683,10 @@ msgstr "Attiva / disattiva barra laterale"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Attiva / disattiva il layout dell'editor"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Focus sul testo"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Strumenti"
|
||||
|
||||
@@ -804,13 +825,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Controlla la configurazione della sincronizzazione"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Le note e le impostazioni sono memorizzate in: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Controlla la configurazione della sincronizzazione"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Applica"
|
||||
|
||||
@@ -906,6 +930,10 @@ msgstr "Stato"
|
||||
msgid "Encryption is:"
|
||||
msgstr "La crittografia è:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Uso: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Indietro"
|
||||
|
||||
@@ -956,34 +984,6 @@ msgstr "Alcuni elementi non possono essere decodificati."
|
||||
msgid "Set the password"
|
||||
msgstr "Imposta la password"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Aggiungi o rimuovi etichetta"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Duplicare"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Copia"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Converti nota in \"Cose-da-fare\" e viceversa"
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr "Converti in nota"
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Converti in \"Cose-da-fare\""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copia il link Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Elimina"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Eliminare le note?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Non è presente nessuna nota. Creane una cliccando \"Nuova nota\"."
|
||||
|
||||
@@ -1129,6 +1129,9 @@ msgstr "Rimuovere questa etichetta da tutte le note?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Rimuovere questa ricerca dalla barra laterale?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Elimina"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Rinomina"
|
||||
|
||||
@@ -1483,6 +1486,25 @@ msgstr "Ignora gli errori del certificato TLS"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Opzione non valida: \"%s\". I valori possibili sono: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Opzioni Generali"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Stato di sincronizzazione"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Taccuini"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Esci dall'applicazione."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr "Il tag \"%s\" esiste già. Scegliere un nome differente."
|
||||
@@ -1777,6 +1799,9 @@ msgstr "Converti in nota"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Converti in Todo"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copia il link Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Nascondi i Metadati"
|
||||
|
||||
@@ -1812,6 +1837,27 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Benvenuto"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Aggiungi o rimuovi etichetta"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Duplicare"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Copia"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Converti nota in \"Cose-da-fare\" e viceversa"
|
||||
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Converti in nota"
|
||||
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Converti in \"Cose-da-fare\""
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Eliminare le note?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Stato: %s."
|
||||
|
||||
@@ -1878,9 +1924,6 @@ msgstr "Benvenuto"
|
||||
#~ msgid "Cancel the current command."
|
||||
#~ msgstr "Cancella il comando corrente."
|
||||
|
||||
#~ msgid "Exit the application."
|
||||
#~ msgstr "Esci dall'applicazione."
|
||||
|
||||
#~ msgid "Delete the currently selected note or notebook."
|
||||
#~ msgstr "Elimina la nota o il taccuino selezionato."
|
||||
|
||||
|
@@ -570,6 +570,20 @@ msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
"\"%s\" を \"%s\" フォーマットにエクスポート中。しばらくお待ちください..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "ノートブックの題名:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "ノートブック"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
@@ -627,6 +641,9 @@ msgstr "太字"
|
||||
msgid "Italic"
|
||||
msgstr "斜体"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "日付の入力"
|
||||
|
||||
@@ -648,6 +665,10 @@ msgstr "サイドバーの表示切り替え"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "エディターレイアウトの表示切り替え"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "本文にフォーカス"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "ツール"
|
||||
|
||||
@@ -786,13 +807,16 @@ msgstr ""
|
||||
"この認証トークンはサードパーティアプリケーションがJoplinにアクセスするためだ"
|
||||
"けに必要です。"
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "同期の設定を確認する"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "ノートと設定は次の場所に保存されます: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "同期の設定を確認する"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "適用"
|
||||
|
||||
@@ -884,6 +908,10 @@ msgstr "状態"
|
||||
msgid "Encryption is:"
|
||||
msgstr "暗号化の状態:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "使用方法: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "戻る"
|
||||
|
||||
@@ -936,34 +964,6 @@ msgstr "いくつかの項目は復号されませんでした。"
|
||||
msgid "Set the password"
|
||||
msgstr "パスワードの設定"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "タグの追加と削除"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "複製"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - コピー"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "ノートとToDoを切り替え"
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr "ノートに切り替え"
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "ToDoに切り替え"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdownのリンクをコピー"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "ノートを削除しますか?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "ノートがありません。新しいノートを作成して下さい。"
|
||||
|
||||
@@ -1106,6 +1106,9 @@ msgstr "すべてのノートからこのタグを削除しますか?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "サイドバーからこの検索を削除しますか?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "名前の変更"
|
||||
|
||||
@@ -1461,6 +1464,25 @@ msgstr "TLS証明書のエラーを無視"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "無効な設定値: \"%s\"。有効な値は: %sです。"
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "全般のオプション"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "同期状況"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "ノートブック"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "場所"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr "タグ \"%s\" はすでにあります。ほかの名前を選択してください。"
|
||||
@@ -1754,6 +1776,9 @@ msgstr "ノートに変換"
|
||||
msgid "Convert to todo"
|
||||
msgstr "ToDoに変換"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdownのリンクをコピー"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "メタデータを隠す"
|
||||
|
||||
@@ -1790,6 +1815,27 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "ようこそ"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "タグの追加と削除"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "複製"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - コピー"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "ノートとToDoを切り替え"
|
||||
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "ノートに切り替え"
|
||||
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "ToDoに切り替え"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "ノートを削除しますか?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "状態: \"%s\"."
|
||||
|
||||
|
@@ -508,6 +508,18 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
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 ""
|
||||
@@ -564,6 +576,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -585,6 +600,9 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tools"
|
||||
msgstr ""
|
||||
|
||||
@@ -716,13 +734,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -801,6 +822,9 @@ msgstr ""
|
||||
msgid "Encryption is:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Usage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
@@ -851,34 +875,6 @@ msgstr ""
|
||||
msgid "Set the password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr ""
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr ""
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr ""
|
||||
|
||||
@@ -1019,6 +1015,9 @@ msgstr ""
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rename"
|
||||
msgstr ""
|
||||
|
||||
@@ -1347,6 +1346,21 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
||||
msgid "Application"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1623,6 +1637,9 @@ msgstr ""
|
||||
msgid "Convert to todo"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -447,12 +447,11 @@ msgid "Starting synchronisation..."
|
||||
msgstr "동기화를 시작합니다..."
|
||||
|
||||
msgid "Downloading resources..."
|
||||
msgstr ""
|
||||
msgstr "리소스 다운로드 중..."
|
||||
|
||||
msgid "Cancelling... Please wait."
|
||||
msgstr "취소하는 중입니다... 잠시만 기다리세요."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"<tag-command> can be \"add\", \"remove\" or \"list\" to assign or remove "
|
||||
"[tag] from [note], or to list the notes associated with [tag]. The command "
|
||||
@@ -460,7 +459,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"[note]로부터 [tag]를 지우거나 지정할 때, 아니면 [tag]와 관련된 노트의 목록을 "
|
||||
"확인할 때 <tag-command>로 \"add\", \"remove\" 또는 \"list\" 를 사용할 수 있습"
|
||||
"니다. `tag list` 명령어로 모든 태그의 목록을 확인할 수 있습니다."
|
||||
"니다. `tag list` 명령어로 모든 태그의 목록을 확인할 수 있습니다 (옵션 -l 사"
|
||||
"용 가능)."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid command: \"%s\""
|
||||
@@ -568,6 +568,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "\"%s\"에 \"%s\" 포맷으로 내보내는 중입니다. 잠시만 기다리세요..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "노트북 제목:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "노트북"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "\"%s\"에서 \"%s\" 포맷으로 가져오는 중입니다. 잠시만 기다리세요..."
|
||||
@@ -615,9 +629,8 @@ msgstr "잘라내기"
|
||||
msgid "Paste"
|
||||
msgstr "붙여넣기"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Select all"
|
||||
msgstr "날짜 선택"
|
||||
msgstr "모두 선택"
|
||||
|
||||
msgid "Bold"
|
||||
msgstr "굵게"
|
||||
@@ -625,6 +638,9 @@ msgstr "굵게"
|
||||
msgid "Italic"
|
||||
msgstr "기울임"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "날짜와 시간 입력"
|
||||
|
||||
@@ -634,9 +650,8 @@ msgstr "외부 편집기에서 편집하기"
|
||||
msgid "Search in all the notes"
|
||||
msgstr "모든 노트에서 검색"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Search in current note"
|
||||
msgstr "모든 노트에서 검색"
|
||||
msgstr "현재 노트에서 검색"
|
||||
|
||||
msgid "View"
|
||||
msgstr "보기"
|
||||
@@ -647,6 +662,10 @@ msgstr "사이드바 표시 전환"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "편집기 배치 형태 전환"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "내용에 포커스"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "도구"
|
||||
|
||||
@@ -699,18 +718,18 @@ msgstr "현재 버전은 최신입니다."
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s (pre-release)"
|
||||
msgstr ""
|
||||
msgstr "%s (프리-릴리즈)"
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr "업데이트가 있습니다. 지금 다운로드할까요?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Your version: v%s"
|
||||
msgstr ""
|
||||
msgstr "현재 버전: v%s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "New version: v%s"
|
||||
msgstr ""
|
||||
msgstr "새 버전: v%s"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr "예"
|
||||
@@ -719,7 +738,7 @@ msgid "No"
|
||||
msgstr "아니오"
|
||||
|
||||
msgid "Token has been copied to the clipboard!"
|
||||
msgstr ""
|
||||
msgstr "토큰이 클립보드로 복사되었습니다!"
|
||||
|
||||
msgid "The web clipper service is enabled and set to auto-start."
|
||||
msgstr "웹 수집기 서비스가 활성화되었고 자동으로 시작하도록 설정되었습니다."
|
||||
@@ -768,28 +787,32 @@ msgstr "2단계: 확장 기능 설치"
|
||||
msgid "Download and install the relevant extension for your browser:"
|
||||
msgstr "브라우저에 적절한 확장 기능을 다운로드 및 설치하세요:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Advanced options"
|
||||
msgstr "고급 옵션"
|
||||
|
||||
msgid "Authorisation token:"
|
||||
msgstr ""
|
||||
msgstr "인증 토큰:"
|
||||
|
||||
msgid "Copy token"
|
||||
msgstr ""
|
||||
msgstr "토큰 복사"
|
||||
|
||||
msgid ""
|
||||
"This authorisation token is only needed to allow third-party applications to "
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "동기화 설정 확인"
|
||||
"이 인증 토큰은 오직 서드파티 애플리케이션에서 조플린을 접근할 때만 필요합니"
|
||||
"다."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "노트와 설정값이 다음에 저장되었습니다: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "동기화 설정 확인"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "적용"
|
||||
|
||||
@@ -881,6 +904,10 @@ msgstr "상태"
|
||||
msgid "Encryption is:"
|
||||
msgstr "암호화는 다음과 같습니다:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "사용량: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "뒤로 가기"
|
||||
|
||||
@@ -931,36 +958,6 @@ msgstr "일부 항목들은 암호화할 수 없습니다."
|
||||
msgid "Set the password"
|
||||
msgstr "암호 설정"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "태그 추가 및 제거"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "복제"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - 복사"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "'노트' 또는'할 일' 형식으로 전환합니다."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "'노트' 또는'할 일' 형식으로 전환합니다."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "'노트' 또는'할 일' 형식으로 전환합니다."
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "마크다운 링크 복사"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "삭제"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "노트를 삭제할까요?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "노트가 없습니다. '새 노트'를 선택해서 노트를 새로 만드세요."
|
||||
|
||||
@@ -969,13 +966,13 @@ msgid ""
|
||||
msgstr "노트북이 없습니다. '새 노트북'을 선택해서 노트북을 새로 만드세요."
|
||||
|
||||
msgid "Location"
|
||||
msgstr ""
|
||||
msgstr "위치"
|
||||
|
||||
msgid "URL"
|
||||
msgstr ""
|
||||
msgstr "URL"
|
||||
|
||||
msgid "Note properties"
|
||||
msgstr ""
|
||||
msgstr "노트 속성"
|
||||
|
||||
msgid "Open..."
|
||||
msgstr "열기..."
|
||||
@@ -994,7 +991,7 @@ msgid "Copy Link Address"
|
||||
msgstr "링크 주소 복사"
|
||||
|
||||
msgid "This attachment is not downloaded or not decrypted yet."
|
||||
msgstr ""
|
||||
msgstr "이 첨부는 아직 다운로드 또는 복호화 되지 않았습니다."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported link or message: %s"
|
||||
@@ -1009,7 +1006,7 @@ msgstr ""
|
||||
"요."
|
||||
|
||||
msgid "Only one note can be printed or exported to PDF at a time."
|
||||
msgstr ""
|
||||
msgstr "한 번에 오직 하나의 노트만 출력하거나 내보내기 할 수 있습니다."
|
||||
|
||||
msgid "strong text"
|
||||
msgstr "중요 텍스트"
|
||||
@@ -1103,6 +1100,9 @@ msgstr "모든 노트에서 이 태그를 제거할까요?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "사이드바에서 이 검색 항목을 제거할까요?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "삭제"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "이름 바꾸기"
|
||||
|
||||
@@ -1116,9 +1116,9 @@ msgstr "노트북"
|
||||
msgid "Decrypting items: %d/%d"
|
||||
msgstr "복호화 항목: %d/%d"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Fetching resources: %d"
|
||||
msgstr "리소스: %d."
|
||||
msgstr "리소스 가져오는 중: %d."
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr "동기화 상태를 내보낼 대상을 선택하세요"
|
||||
@@ -1327,16 +1327,17 @@ msgid ""
|
||||
"this setting so that your notes are constantly being synchronised, thus "
|
||||
"reducing the number of conflicts."
|
||||
msgstr ""
|
||||
"조플린을 백그라운드에서 구동합니다. 노트가 정기적으로 동기화 되어 충돌 횟수"
|
||||
"를 줄이기 위해 이 옵션을 활성화 하는 것을 추천합니다."
|
||||
|
||||
msgid "Start application minimised in the tray icon"
|
||||
msgstr ""
|
||||
msgstr "트레이 아이콘에 최소화 된 상태로 애플리케이션 시작"
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr "전체적 확대 비율"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Editor font size"
|
||||
msgstr "편집기 글꼴 집합"
|
||||
msgstr "편집기 글꼴 크기"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr "편집기 글꼴 집합"
|
||||
@@ -1353,11 +1354,11 @@ msgid "Automatically update the application"
|
||||
msgstr "애플리케이션을 자동으로 업데이트"
|
||||
|
||||
msgid "Get pre-releases when checking for updates"
|
||||
msgstr ""
|
||||
msgstr "업데이트 확인 시 프리-릴리즈 받기"
|
||||
|
||||
#, javascript-format
|
||||
msgid "See the pre-release page for more details: %s"
|
||||
msgstr ""
|
||||
msgstr "자세한 내용은 프리-릴리즈 페이지를 참조하세요: %s"
|
||||
|
||||
msgid "Synchronisation interval"
|
||||
msgstr "동기화 간격"
|
||||
@@ -1416,6 +1417,8 @@ msgid ""
|
||||
"to it before syncing, otherwise all files will be removed! See the FAQ for "
|
||||
"more details: %s"
|
||||
msgstr ""
|
||||
"주의: 이 위치를 변경하시려면, 동기화 전에 모든 컨텐트를 복사했는지 확인하세"
|
||||
"요, 그렇지 않으면 모든 파일이 삭제됩니다! 자세한 정보는 FAQ를 참조하세요: %s"
|
||||
|
||||
msgid "Nextcloud username"
|
||||
msgstr "Nextcloud 사용자 이름"
|
||||
@@ -1453,9 +1456,28 @@ msgstr "TLS 인증서 오류 무시"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "올바르지 않은 옵션 값: \"%s\". 가능한 값은 다음과 같습니다: \"%s\"."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "일반 옵션"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "동기화 상태"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "노트북"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "위치"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
msgstr "태그 \"%s\"(이)가 이미 존재합니다. 다른 이름을 선택해 주세요."
|
||||
|
||||
msgid "Joplin Export File"
|
||||
msgstr "조플린 내보내기 파일"
|
||||
@@ -1469,9 +1491,8 @@ msgstr "조플린 내보내기 폴더"
|
||||
msgid "Evernote Export File"
|
||||
msgstr "에버노트 내보내기 파일"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Json Export Directory"
|
||||
msgstr "조플린 내보내기 폴더"
|
||||
msgstr "Json 내보내기 폴더"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "폴더"
|
||||
@@ -1548,10 +1569,10 @@ msgid "On %s: %s"
|
||||
msgstr "%s: %s"
|
||||
|
||||
msgid "Permission to use camera"
|
||||
msgstr ""
|
||||
msgstr "카메라 사용 허가"
|
||||
|
||||
msgid "Your permission to use your camera is required."
|
||||
msgstr ""
|
||||
msgstr "카메라 사용을 허가가 요구됩니다."
|
||||
|
||||
msgid "There are currently no notes. Create one by clicking on the (+) button."
|
||||
msgstr "노트가 없습니다. (+) 버튼을 선택해 새로 만드세요."
|
||||
@@ -1581,9 +1602,8 @@ msgstr "%d 노트를 \"%s\" 노트북으로 옮길까요?"
|
||||
msgid "Press to set the decryption password."
|
||||
msgstr "복호화 암호를 설정하려면 누르세요."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Clear alarm"
|
||||
msgstr "알람 설정"
|
||||
msgstr "알람 취소"
|
||||
|
||||
msgid "Save alarm"
|
||||
msgstr "알람 저장"
|
||||
@@ -1597,20 +1617,19 @@ msgstr "확인"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "동기화 취소"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Checking... Please wait."
|
||||
msgstr "취소하는 중입니다... 잠시만 기다리세요."
|
||||
msgstr "확인 중입니다... 잠시만 기다리세요."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Success! Synchronisation configuration appears to be correct."
|
||||
msgstr "동기화 설정 확인"
|
||||
msgstr "성공! 동기화 설정이 올바릅니다."
|
||||
|
||||
msgid ""
|
||||
"Error. Please check that URL, username, password, etc. are correct and that "
|
||||
"the sync target is accessible. The reported error was:"
|
||||
msgstr ""
|
||||
"Error. Please check that URL, username, password, etc. are correct and that "
|
||||
"the sync target is accessible. The reported error was:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "The application has been authorised!"
|
||||
msgstr "애플리케이션이 성공적으로 허가되었습니다."
|
||||
|
||||
@@ -1622,10 +1641,15 @@ msgid ""
|
||||
"\n"
|
||||
"Please try again."
|
||||
msgstr ""
|
||||
"애플리케이션을 허가할 수 없습니다:\n"
|
||||
"\n"
|
||||
"%s\n"
|
||||
"\n"
|
||||
"다시 시도해 주세요."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Decrypted items: %s / %s"
|
||||
msgstr "복호화 항목: %d/%d"
|
||||
msgstr "복호화된 항목: %s / %s"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr "새 태그:"
|
||||
@@ -1656,23 +1680,23 @@ msgstr "- 위치: 지리적 위치 정보를 노트에 첨부하기 위해서
|
||||
msgid "Joplin website"
|
||||
msgstr "조플린 웹사이트"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Joplin v%s"
|
||||
msgstr "조플린 웹사이트"
|
||||
msgstr "조플린 v%s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Database v%s"
|
||||
msgstr ""
|
||||
msgstr "데이터베이스 v%s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "FTS enabled: %d"
|
||||
msgstr "삭제: %d"
|
||||
msgstr "FTS 활성됨: %d"
|
||||
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Dropbox로 로그인"
|
||||
|
||||
msgid "Enter code here"
|
||||
msgstr ""
|
||||
msgstr "여기에 코드를 입력하세요"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
@@ -1725,9 +1749,8 @@ msgstr "조플린 모바일 앱은 현재 해당 형식의 링크를 지원하
|
||||
msgid "Unsupported image type: %s"
|
||||
msgstr "지원하지 않는 이미지 형식: %s"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Take photo"
|
||||
msgstr "사진 첨부"
|
||||
msgstr "사진 찍기"
|
||||
|
||||
msgid "Attach photo"
|
||||
msgstr "사진 첨부"
|
||||
@@ -1744,6 +1767,9 @@ msgstr "노트로 변환"
|
||||
msgid "Convert to todo"
|
||||
msgstr "'할 일'로 변환"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "마크다운 링크 복사"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "메타데이터 숨김"
|
||||
|
||||
@@ -1754,7 +1780,7 @@ msgid "View on map"
|
||||
msgstr "지도에 표시"
|
||||
|
||||
msgid "Go to source URL"
|
||||
msgstr ""
|
||||
msgstr "소스 URL로 이동"
|
||||
|
||||
msgid "Delete notebook"
|
||||
msgstr "노트북 삭제"
|
||||
@@ -1778,6 +1804,27 @@ msgstr "노트북이 없습니다. (+) 버튼을 눌러 새로 만드세요."
|
||||
msgid "Welcome"
|
||||
msgstr "환영합니다"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "태그 추가 및 제거"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "복제"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - 복사"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "'노트' 또는'할 일' 형식으로 전환합니다."
|
||||
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "'노트' 형식으로 전환합니다."
|
||||
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "'할 일' 형식으로 전환합니다."
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "노트를 삭제할까요?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "상태: %s."
|
||||
|
||||
|
@@ -164,7 +164,7 @@ msgstr "Rediger notat."
|
||||
msgid ""
|
||||
"No text editor is defined. Please set it using `config editor <editor-path>`"
|
||||
msgstr ""
|
||||
"Inger teksteditor er valgt. Velg en ved å bruke `config editor <editor-path>`"
|
||||
"Ingen teksteditor er valgt. Velg en ved å bruke `config editor <editor-path>`"
|
||||
|
||||
msgid "No active notebook."
|
||||
msgstr "Ingen aktiv notatbok."
|
||||
@@ -576,6 +576,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Eksporterer til \"%s\" i \"%s\" format. Vennligst vent..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Tittel på notatbok:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Notatbøker"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importerer fra \"%s\" i \"%s\"-format. Vennligst vent..."
|
||||
@@ -632,6 +646,9 @@ msgstr "Fet"
|
||||
msgid "Italic"
|
||||
msgstr "Kursiv"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Sett inn dato/tid"
|
||||
|
||||
@@ -646,7 +663,7 @@ msgid "Search in current note"
|
||||
msgstr "Søk i nåværende notat"
|
||||
|
||||
msgid "View"
|
||||
msgstr "Utseende"
|
||||
msgstr "Vis"
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr "Vis/skjul sidepanel"
|
||||
@@ -654,6 +671,10 @@ msgstr "Vis/skjul sidepanel"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Bytt editorutseende"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Fokuser på brødtekst"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Verktøy"
|
||||
|
||||
@@ -706,18 +727,18 @@ msgstr "Nåværende versjon er den siste tilgjengelige."
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s (pre-release)"
|
||||
msgstr ""
|
||||
msgstr "%s (førutgivelse)"
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr "En oppdatering er tilgjengelig, vil du laste den ned nå?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Your version: v%s"
|
||||
msgstr ""
|
||||
msgstr "Din versjon: v%s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "New version: v%s"
|
||||
msgstr ""
|
||||
msgstr "Ny versjon: v%s"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
@@ -789,16 +810,19 @@ msgid ""
|
||||
"This authorisation token is only needed to allow third-party applications to "
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
"Denne autentiseringsbeviset er det eneste nødvendig for å gi "
|
||||
"Denne autoriseringsbeviset er det eneste nødvendig for å gi "
|
||||
"tredjepartsapplikasjoner tilgang til Joplin."
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Sjekk synkroniseringskonfigurasjon"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Notater og innstillinger er lagret i: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Sjekk synkroniseringskonfigurasjon"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Bruk"
|
||||
|
||||
@@ -893,6 +917,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Kryptering er:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Bruk: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Tilbake"
|
||||
|
||||
@@ -945,34 +973,6 @@ msgstr "Noen elementer kan ikke dekrypteres."
|
||||
msgid "Set the password"
|
||||
msgstr "Sett passord"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Legg til eller fjern merkelapper"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Dupliser"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Kopier"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Bytt mellom notat og gjøremål"
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr "Bytt til notatmodus"
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Bytt til gjøremålmodus"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Kopier Markdown-link"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Slett"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Slette notater?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Ingen notater her enda. Opprett et ved å klikke på \"Nytt notat\"."
|
||||
|
||||
@@ -1115,6 +1115,9 @@ msgstr "Fjern denne merkelappen fra alle notater?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Fjerne dette søket fra sidepanelet?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Slett"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Gi nytt navn"
|
||||
|
||||
@@ -1368,11 +1371,11 @@ msgid "Automatically update the application"
|
||||
msgstr "Oppdater applikasjonen automatisk"
|
||||
|
||||
msgid "Get pre-releases when checking for updates"
|
||||
msgstr ""
|
||||
msgstr "Få førutgivelse når du sjekker etter oppdateringer"
|
||||
|
||||
#, javascript-format
|
||||
msgid "See the pre-release page for more details: %s"
|
||||
msgstr ""
|
||||
msgstr "Se førutgivelsessiden for flere detaljer: %s"
|
||||
|
||||
msgid "Synchronisation interval"
|
||||
msgstr "Synkroniserinsintervall"
|
||||
@@ -1471,6 +1474,25 @@ msgstr "Ignorer TLS-sertifikatfeil"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Ugyldig verdi: \"%s\". Mulige verdier er: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Generelle innstillinger"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Synkroniseringsstatus"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Notatbøker"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Lokasjon"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr "Merkelappen \"%s\" eksiterer allerede. Vennligst velg et annet navn."
|
||||
@@ -1764,6 +1786,9 @@ msgstr "Konverter til notat"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Konverter til gjøremål"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Kopier Markdown-link"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Skjul metadata"
|
||||
|
||||
@@ -1797,3 +1822,24 @@ msgstr "Du har enda ingen notatbok. Lag en ved å klikke på (+)-knappen."
|
||||
|
||||
msgid "Welcome"
|
||||
msgstr "Velkommen"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Legg til eller fjern merkelapper"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Dupliser"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Kopier"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Bytt mellom notat og gjøremål"
|
||||
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Bytt til notatmodus"
|
||||
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Bytt til gjøremålmodus"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Slette notater?"
|
||||
|
@@ -584,6 +584,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Notitieboek titel:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Notitieboeken"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
@@ -643,6 +657,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -665,6 +682,9 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Tools"
|
||||
|
||||
@@ -799,14 +819,17 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Annuleer synchronisatie"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Notities en instellingen zijn opgeslaan in %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Annuleer synchronisatie"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -897,6 +920,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Versleuteling is:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Gebruik: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Terug"
|
||||
|
||||
@@ -951,36 +978,6 @@ msgstr "Sommige items kunnen niet gedecodeerd worden."
|
||||
msgid "Set the password"
|
||||
msgstr "Stel wachtwoord in"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Voeg tag toe of verwijder tag"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Kopieer"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Wissel tussen notitie en to-do type"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Wissel tussen notitie en to-do type"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Wissel tussen notitie en to-do type"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Verwijderen"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Notities verwijderen?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Geen notities. Maak een notitie door op \"Nieuwe notitie\" te klikken."
|
||||
|
||||
@@ -1128,6 +1125,9 @@ msgstr "Deze tag verwijderen van alle notities?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Dit item verwijderen van de zijbalk?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Verwijderen"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Hernoem"
|
||||
|
||||
@@ -1486,6 +1486,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Ongeldige optie: \"%s\". Geldige waarden zijn: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Algemene opties"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Synchronisatie status"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Notitieboeken"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Sluit de applicatie."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1778,6 +1797,9 @@ msgstr "Converteer naar notitie"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Converteer naar to-do"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Verberg metadata"
|
||||
|
||||
@@ -1814,6 +1836,27 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Welkom"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Voeg tag toe of verwijder tag"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Kopieer"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Wissel tussen notitie en to-do type"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Wissel tussen notitie en to-do type"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Wissel tussen notitie en to-do type"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Notities verwijderen?"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Status: \"%s\""
|
||||
@@ -1865,9 +1908,6 @@ msgstr "Welkom"
|
||||
#~ msgid "Cancel the current command."
|
||||
#~ msgstr "Annuleer het huidige commando."
|
||||
|
||||
#~ msgid "Exit the application."
|
||||
#~ msgstr "Sluit de applicatie."
|
||||
|
||||
#~ msgid "Delete the currently selected note or notebook."
|
||||
#~ msgstr ""
|
||||
#~ "Verwijder de geselecteerde notitie of het geselecteerde notitieboek."
|
||||
|
@@ -585,6 +585,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Bezig met exporteren van \"%s\" in het formaat \"%s\". Even geduld..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Titel van notitieboek:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Notitieboeken"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Bezig met importeren van \"%s\" in het formaat \"%s\". Even geduld..."
|
||||
@@ -642,6 +656,9 @@ msgstr "Vetgedrukt"
|
||||
msgid "Italic"
|
||||
msgstr "Cursief"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Datum en tijd invoegen"
|
||||
|
||||
@@ -664,6 +681,10 @@ msgstr "Zijbalk tonen/verbergen"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Bewerkindeling tonen/verbergen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Inhoud focussen"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Hulpmiddelen"
|
||||
|
||||
@@ -802,13 +823,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Synchronisatieconfiguratie controleren"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Notities en instellingen worden opgeslagen in: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Synchronisatieconfiguratie controleren"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Toepassen"
|
||||
|
||||
@@ -903,6 +927,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Gebruikte versleuteling:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Gebruik: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Terug"
|
||||
|
||||
@@ -955,36 +983,6 @@ msgstr "Sommige items kunnen niet worden ontsleuteled."
|
||||
msgid "Set the password"
|
||||
msgstr "Wachtwoord instellen"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Labels toevoegen of verwijderen"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Dupliceren"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - kopiëren"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Schakelen tussen notitie en taak"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Schakelen tussen notitie en taak"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Schakelen tussen notitie en taak"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdownlink kopiëren"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Verwijderen"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Notities verwijderen?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr ""
|
||||
"Er zijn hier geen notities. Creëer een notitie door de klikken op \"Nieuwe "
|
||||
@@ -1131,6 +1129,9 @@ msgstr "Wil je dit label verwijderen van alle notities?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Wil je deze zoekopdracht verwijderen uit de zijbalk?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Verwijderen"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Naam wijzigen"
|
||||
|
||||
@@ -1484,6 +1485,25 @@ msgstr "TLS-certificaatfouten negeren"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Ongeldige optie: \"%s\". Geldige waarden zijn: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Algemene opties"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Synchronisatiestatus"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Notitieboeken"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Sluit de applicatie af."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1780,6 +1800,9 @@ msgstr "Omzetten naar notitie"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Omzetten naar taak"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdownlink kopiëren"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Metagegevens verbergen"
|
||||
|
||||
@@ -1816,6 +1839,29 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Welkom"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Labels toevoegen of verwijderen"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Dupliceren"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - kopiëren"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Schakelen tussen notitie en taak"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Schakelen tussen notitie en taak"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Schakelen tussen notitie en taak"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Notities verwijderen?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Status: %s."
|
||||
|
||||
|
@@ -582,6 +582,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exportando para \"%s\" com o formato \"%s\". Por favor, aguarde..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Título do caderno:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Cadernos"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importando de \"%s\" com o formato \"%s\". Por favor, aguarde..."
|
||||
@@ -638,6 +652,9 @@ msgstr "Negrito"
|
||||
msgid "Italic"
|
||||
msgstr "Itálico"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Inserir Data e Hora"
|
||||
|
||||
@@ -659,6 +676,10 @@ msgstr "Alternar barra lateral"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Alternar layout do editor"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Focar no corpo"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Ferramentas"
|
||||
|
||||
@@ -798,13 +819,16 @@ msgstr ""
|
||||
"Esse token de autoriza\\u00e7\\u00e3o só é necess\\u00e1rio para permitir "
|
||||
"que aplicativos de terceiros acessem o Joplin."
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Verificar a configuração da sincronização"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Notas e configurações estão armazenadas em: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Verificar a configuração da sincronização"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Aplicar"
|
||||
|
||||
@@ -898,6 +922,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Encriptação está:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Uso: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Voltar"
|
||||
|
||||
@@ -949,34 +977,6 @@ msgstr "Alguns itens não podem ser decriptados."
|
||||
msgid "Set the password"
|
||||
msgstr "Configurar a senha"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Adicionar ou remover tags"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Duplicar"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Copiar"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Alternar entre os tipos Nota e Tarefa"
|
||||
|
||||
msgid "Switch to note type"
|
||||
msgstr "Alternar para o tipo Nota"
|
||||
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Alternar para o tipo Tarefa"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copiar link de Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Excluir"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Excluir notas?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Não há notas aqui. Crie uma, clicando em \"Nova nota\"."
|
||||
|
||||
@@ -1119,6 +1119,9 @@ msgstr "Remover esta tag de todas as notas?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Remover essa pesquisa da barra lateral?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Excluir"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Renomear"
|
||||
|
||||
@@ -1478,6 +1481,25 @@ msgstr "Ignorar erros de certificados TLS"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Valor da opção inválida: \"%s\". Os valores possíveis são: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Opções Gerais"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Status de sincronização"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Cadernos"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Localização"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr "A tag \"%s\" já existe. Escolha um nome diferente."
|
||||
@@ -1776,6 +1798,9 @@ msgstr "Converter para nota"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Converter para tarefa"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copiar link de Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Ocultar metadados"
|
||||
|
||||
@@ -1810,6 +1835,27 @@ msgstr "Você não possui cadernos. Crie um clicando no botão (+)."
|
||||
msgid "Welcome"
|
||||
msgstr "Bem-vindo"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Adicionar ou remover tags"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Duplicar"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Copiar"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Alternar entre os tipos Nota e Tarefa"
|
||||
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Alternar para o tipo Nota"
|
||||
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Alternar para o tipo Tarefa"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Excluir notas?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Estado: \"%s\"."
|
||||
|
||||
|
@@ -521,6 +521,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Se exportă către \"%s\" în format \"%s\". Vă rugăm să așteotați..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Titlul caietului de notițe:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Caiete de notițe"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
@@ -578,6 +592,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -600,6 +617,9 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Unelte"
|
||||
|
||||
@@ -732,13 +752,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Aplicați"
|
||||
|
||||
@@ -817,6 +840,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Criptarea este:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Utilizare: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Înapoi"
|
||||
|
||||
@@ -867,36 +894,6 @@ msgstr "Câțiva itemi nu pot fi descriptați."
|
||||
msgid "Set the password"
|
||||
msgstr "Setați parola"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Adăugați ori eliminați etichete"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Duplicați"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Copiați"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Schimbați între notiță și sarcină"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Schimbați între notiță și sarcină"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Schimbați între notiță și sarcină"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copiați link-ul Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Ștergeți"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Ștergeți notițele?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr ""
|
||||
|
||||
@@ -1037,6 +1034,9 @@ msgstr ""
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Ștergeți"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Redenumiți"
|
||||
|
||||
@@ -1366,6 +1366,25 @@ msgstr "Ignoră erorile de certificat TLS"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Opțiuni Generale"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Statusul sincronizării"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Caiete de notițe"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Duplicați"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1645,6 +1664,9 @@ msgstr ""
|
||||
msgid "Convert to todo"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Copiați link-ul Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Ascundeți metadatele"
|
||||
|
||||
@@ -1680,6 +1702,26 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Bine ați venit"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Adăugați ori eliminați etichete"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Copiați"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Schimbați între notiță și sarcină"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Schimbați între notiță și sarcină"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Schimbați între notiță și sarcină"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Ștergeți notițele?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Statut: %s."
|
||||
|
||||
|
@@ -583,6 +583,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Экспорт в «%s» в формате «%s». Пожалуйста, ожидайте..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Название блокнота:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Блокноты"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Импорт из «%s» в формате «%s». Пожалуйста, ожидайте..."
|
||||
@@ -640,6 +654,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -662,6 +679,10 @@ msgstr "Переключить панель"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Переключить вид редактора"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Фокус на содержимом"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Инструменты"
|
||||
|
||||
@@ -794,13 +815,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Проверить настройки синхронизации"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Заметки и настройки сохранены в: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Проверить настройки синхронизации"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Применить"
|
||||
|
||||
@@ -894,6 +918,10 @@ msgstr "Статус"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Шифрование:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Использование: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Назад"
|
||||
|
||||
@@ -946,37 +974,6 @@ msgstr "Некоторые элементы не могут быть расши
|
||||
msgid "Set the password"
|
||||
msgstr "Установить пароль"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Добавить или удалить теги"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Копировать"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Переключить тип между заметкой и задачей"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Переключить тип между заметкой и задачей"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Переключить тип между заметкой и задачей"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Удалить"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Удалить заметки?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Здесь нет заметок. Создайте новую нажатием на «Новая заметка»."
|
||||
|
||||
@@ -1121,6 +1118,9 @@ msgstr "Убрать этот тег со всех заметок?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Убрать этот запрос с боковой панели?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Удалить"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Переименовать"
|
||||
|
||||
@@ -1474,6 +1474,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Неверное значение параметра: «%s». Доступные значения: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Основные настройки"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Статус синхронизации"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Блокноты"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Выйти из приложения."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1765,6 +1784,10 @@ msgstr "Преобразовать в заметку"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Преобразовать в задачу"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Скрыть метаданные"
|
||||
|
||||
@@ -1799,6 +1822,27 @@ msgstr "У вас сейчас нет блокнота. Создайте его
|
||||
msgid "Welcome"
|
||||
msgstr "Добро пожаловать"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Добавить или удалить теги"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Копировать"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Переключить тип между заметкой и задачей"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Переключить тип между заметкой и задачей"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Переключить тип между заметкой и задачей"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Удалить заметки?"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Статус: «%s»."
|
||||
@@ -1849,9 +1893,6 @@ msgstr "Добро пожаловать"
|
||||
#~ msgid "Cancel the current command."
|
||||
#~ msgstr "Отменить текущую команду."
|
||||
|
||||
#~ msgid "Exit the application."
|
||||
#~ msgstr "Выйти из приложения."
|
||||
|
||||
#~ msgid "Delete the currently selected note or notebook."
|
||||
#~ msgstr "Удалить текущую выбранную заметку или блокнот."
|
||||
|
||||
|
@@ -582,6 +582,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Izvažam v \"%s\" kot \"%s\" format. Prosim počakajte..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Naslov beležnice:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Beležnice"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Uvažam v \"%s\" kot \"%s\" format. Prosim počakajte..."
|
||||
@@ -639,6 +653,9 @@ msgstr ""
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -661,6 +678,10 @@ msgstr ""
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Spremeni izgled urejevalnika"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Fokusiraj vsebino"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Orodja"
|
||||
|
||||
@@ -793,13 +814,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Preveri nastavitve sinhronizacije"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Zabeležke in nastavitve so shranjene v: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Preveri nastavitve sinhronizacije"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
@@ -893,6 +917,10 @@ msgstr "Status"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Enkripcija je:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Uporaba: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Nazaj"
|
||||
|
||||
@@ -946,37 +974,6 @@ msgstr "Nekateri predmeti ne morejo biti dekriptirani."
|
||||
msgid "Set the password"
|
||||
msgstr "Nastavi geslo"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Dodaj ali odstrani oznake"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "Kopiraj"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Menjaj med zabeležko in seznamom opravil"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Menjaj med zabeležko in seznamom opravil"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Menjaj med zabeležko in seznamom opravil"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Sistem označevanja"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Izbriši"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Izbriši zabeležke?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr ""
|
||||
"Trenutno ni tukaj nobene zabeležke. Ustvarite jo z klikom na \"Nova zabeležka"
|
||||
@@ -1125,6 +1122,9 @@ msgstr "Odstranite to oznako iz vseh zabeležk?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Odstranite ta iskalni niz iz stranske vrstice?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Izbriši"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Preimenuj"
|
||||
|
||||
@@ -1478,6 +1478,25 @@ msgstr ""
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Neveljavna vrednost: \"%s\". Možne vrednosti so : %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Splošne možnosti"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Status sinhronizacije"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Beležnice"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Izhod iz aplikacije."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1767,6 +1786,10 @@ msgstr "Pretvori v zabeležko"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Pretvori v za narediti"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Sistem označevanja"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Skrij meta podatke"
|
||||
|
||||
@@ -1801,6 +1824,27 @@ msgstr "Trenutno nimate nobene beležnice. Ustvarite jo s klikom na (+) gumb."
|
||||
msgid "Welcome"
|
||||
msgstr "Dobrodošli"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Dodaj ali odstrani oznake"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "Kopiraj"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Menjaj med zabeležko in seznamom opravil"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Menjaj med zabeležko in seznamom opravil"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Menjaj med zabeležko in seznamom opravil"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Izbriši zabeležke?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Stanje: %s."
|
||||
|
||||
|
@@ -589,6 +589,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exportera till \"%s\" som \"%s\" format. Vänta..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "Titel på anteckningsbok:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "Anteckningsböcker"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importerar från \"%s\" som \"%s\" format. Vänta..."
|
||||
@@ -646,6 +660,9 @@ msgstr "Fet"
|
||||
msgid "Italic"
|
||||
msgstr "Kursiv"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "Infoga datumtid"
|
||||
|
||||
@@ -668,6 +685,10 @@ msgstr "Växla sidofältet"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Växla redigeringslayout"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "Fokus på huvuddel"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Verktyg"
|
||||
|
||||
@@ -805,13 +826,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Kontrollera synkroniseringskonfigurationen"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Anteckningar och inställningar lagras i: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Kontrollera synkroniseringskonfigurationen"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "Tillämpa"
|
||||
|
||||
@@ -906,6 +930,10 @@ msgstr "Tillstånd"
|
||||
msgid "Encryption is:"
|
||||
msgstr "Kryptering är:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "Användning: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Tillbaka"
|
||||
|
||||
@@ -958,36 +986,6 @@ msgstr "Några objekt kan inte dekrypteras."
|
||||
msgid "Set the password"
|
||||
msgstr "Ställ in lösenord"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Lägg till eller ta bort taggar"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "Duplikat"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - Kopiera"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "Växla mellan antecknings- och att-göra-typ"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "Växla mellan antecknings- och att-göra-typ"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "Växla mellan antecknings- och att-göra-typ"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Kopiera Markdown-länk"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Ta bort"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "Ta bort anteckningar?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Inga anteckningar här. Skapa en genom att klicka på \"Ny anteckning\"."
|
||||
|
||||
@@ -1132,6 +1130,9 @@ msgstr "Ta bort den här taggen från alla anteckningar?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "Ta bort den här sökningen från sidofältet?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Ta bort"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "Byt namn"
|
||||
|
||||
@@ -1485,6 +1486,25 @@ msgstr "Ignorera TLS-certifikatfel"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Ogiltigt inställningsvärde: \"%s\". Möjliga värden är: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "Allmänna inställningar"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "Synkroniseringstillstånd"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "Anteckningsböcker"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "Avslutar programmet."
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1783,6 +1803,9 @@ msgstr "Konvertera till anteckning"
|
||||
msgid "Convert to todo"
|
||||
msgstr "Konvertera till att-göra"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "Kopiera Markdown-länk"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "Dölj metadata"
|
||||
|
||||
@@ -1820,6 +1843,29 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Välkommen"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "Lägg till eller ta bort taggar"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "Duplikat"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - Kopiera"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "Växla mellan antecknings- och att-göra-typ"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "Växla mellan antecknings- och att-göra-typ"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "Växla mellan antecknings- och att-göra-typ"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "Ta bort anteckningar?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "Tillstånd: %s."
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -548,6 +548,20 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "匯出到 \"%s\" 為 \"%s\" 格式。請稍候..."
|
||||
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note list"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note title"
|
||||
msgstr "記事本標題:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note body"
|
||||
msgstr "記事本"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "從 \"%s\" 匯入為 \"%s\" 格式。請稍候..."
|
||||
@@ -605,6 +619,9 @@ msgstr "粗體"
|
||||
msgid "Italic"
|
||||
msgstr "斜體"
|
||||
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Date Time"
|
||||
msgstr "插入日期時間"
|
||||
|
||||
@@ -627,6 +644,10 @@ msgstr "顯示 / 隱藏側邊欄"
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "切換編輯器佈局"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus"
|
||||
msgstr "游標置於內文"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "工具"
|
||||
|
||||
@@ -761,13 +782,16 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "檢測同步設置"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "所有記事和設置均儲存於: %s"
|
||||
|
||||
msgid "Browse..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "檢測同步設置"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "套用"
|
||||
|
||||
@@ -855,6 +879,10 @@ msgstr "狀態"
|
||||
msgid "Encryption is:"
|
||||
msgstr "加密:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Usage"
|
||||
msgstr "使用資訊: %s"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "返回"
|
||||
|
||||
@@ -905,36 +933,6 @@ msgstr "有些項目不能解密。"
|
||||
msgid "Set the password"
|
||||
msgstr "設置密碼"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "新增或移除標籤"
|
||||
|
||||
msgid "Duplicate"
|
||||
msgstr "新增複本"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s - Copy"
|
||||
msgstr "%s - 複本"
|
||||
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr "切換到記事 / 待辦事項"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to note type"
|
||||
msgstr "切換到記事 / 待辦事項"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Switch to to-do type"
|
||||
msgstr "切換到記事 / 待辦事項"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "複製 Markdown 連結"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "刪除"
|
||||
|
||||
msgid "Delete notes?"
|
||||
msgstr "刪除此記事?"
|
||||
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "當前沒有任何筆記。通過按一下 \"新增筆記\" 去建立。"
|
||||
|
||||
@@ -1075,6 +1073,9 @@ msgstr "是否從所有記事中刪除此標籤?"
|
||||
msgid "Remove this search from the sidebar?"
|
||||
msgstr "是否從側邊欄中刪除此搜索?"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "刪除"
|
||||
|
||||
msgid "Rename"
|
||||
msgstr "重新命名"
|
||||
|
||||
@@ -1418,6 +1419,25 @@ msgstr "忽略 TLS 證書錯誤"
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "不正確選項值: \"%s\"。可能的值為: %s。"
|
||||
|
||||
#, fuzzy
|
||||
msgid "General"
|
||||
msgstr "一般選項"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation"
|
||||
msgstr "顯示同步狀態"
|
||||
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Note"
|
||||
msgstr "記事本"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Application"
|
||||
msgstr "離開本程式。"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The tag \"%s\" already exists. Please choose a different name."
|
||||
msgstr ""
|
||||
@@ -1704,6 +1724,9 @@ msgstr "轉換為記事"
|
||||
msgid "Convert to todo"
|
||||
msgstr "轉換為待辦事項"
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr "複製 Markdown 連結"
|
||||
|
||||
msgid "Hide metadata"
|
||||
msgstr "隱藏後設資料 (metadata)"
|
||||
|
||||
@@ -1736,6 +1759,29 @@ msgstr "您當前沒有任何筆記本。通過按一下 (+) 鍵去建立一本
|
||||
msgid "Welcome"
|
||||
msgstr "歡迎"
|
||||
|
||||
#~ msgid "Add or remove tags"
|
||||
#~ msgstr "新增或移除標籤"
|
||||
|
||||
#~ msgid "Duplicate"
|
||||
#~ msgstr "新增複本"
|
||||
|
||||
#~ msgid "%s - Copy"
|
||||
#~ msgstr "%s - 複本"
|
||||
|
||||
#~ msgid "Switch between note and to-do type"
|
||||
#~ msgstr "切換到記事 / 待辦事項"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to note type"
|
||||
#~ msgstr "切換到記事 / 待辦事項"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Switch to to-do type"
|
||||
#~ msgstr "切換到記事 / 待辦事項"
|
||||
|
||||
#~ msgid "Delete notes?"
|
||||
#~ msgstr "刪除此記事?"
|
||||
|
||||
#~ msgid "State: %s."
|
||||
#~ msgstr "狀態: %s。"
|
||||
|
||||
|
126
CliClient/package-lock.json
generated
126
CliClient/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "joplin",
|
||||
"version": "1.0.120",
|
||||
"version": "1.0.122",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -29,16 +29,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz",
|
||||
"integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg=="
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.6.tgz",
|
||||
"integrity": "sha512-5M3G/A4uBSMIlfJ+h9W125vJvPFH/zirISsW5qfxF5YzEvXJCtolLoQvM5yZft0DvMcUrPGKPOlgEu55I6iUtA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.0.1.tgz",
|
||||
"integrity": "sha512-PqVQ8c6a3kyqdsUZlC7nljp3FFuxipBRHKu+7C1h8QygBFlzTaDX5HD383jej3Peed+1aDG8HwkfB1Z1HMNPkw=="
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz",
|
||||
"integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
@@ -488,12 +488,12 @@
|
||||
"integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo="
|
||||
},
|
||||
"data-urls": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz",
|
||||
"integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
|
||||
"integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
|
||||
"requires": {
|
||||
"abab": "^2.0.0",
|
||||
"whatwg-mimetype": "^2.1.0",
|
||||
"whatwg-mimetype": "^2.2.0",
|
||||
"whatwg-url": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -1427,9 +1427,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"joplin-turndown": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.9.tgz",
|
||||
"integrity": "sha512-8MOxX4t5Ai22muHhXPMGNoKc/AB7gSo0eUvNh6dyd6b3vcSiMIRZE8UHpMjS9ruJQ+8e+8TtJXc0nfbexeHwrA==",
|
||||
"version": "4.0.11",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.11.tgz",
|
||||
"integrity": "sha512-2oiwWX0nKYi1NVcaprSsrXQkYdGoRtPWFmnXdWQnQW44jlgjFV38B4VrgliwX5ZMq7cbx6A9IBwfXcBL2YV2NA==",
|
||||
"requires": {
|
||||
"jsdom": "^11.9.0"
|
||||
}
|
||||
@@ -1488,6 +1488,17 @@
|
||||
"xml-name-validator": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz",
|
||||
"integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==",
|
||||
"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",
|
||||
@@ -1506,46 +1517,46 @@
|
||||
"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.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"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",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
|
||||
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
|
||||
"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": "^5.3.0",
|
||||
"ajv": "^6.5.5",
|
||||
"har-schema": "^2.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.36.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
|
||||
"integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw=="
|
||||
"version": "1.37.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
|
||||
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.20",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
|
||||
"integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
|
||||
"version": "2.1.21",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
|
||||
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
|
||||
"requires": {
|
||||
"mime-db": "~1.36.0"
|
||||
"mime-db": "~1.37.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
@@ -2793,7 +2804,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",
|
||||
@@ -2915,6 +2926,21 @@
|
||||
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
||||
"integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
},
|
||||
"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=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz",
|
||||
@@ -2963,17 +2989,17 @@
|
||||
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
|
||||
},
|
||||
"whatwg-encoding": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz",
|
||||
"integrity": "sha512-vM9KWN6MP2mIHZ86ytcyIv7e8Cj3KTfO2nd2c8PFDqcI4bxFmQp83ibq4wadq7rL9l9sZV6o9B0LTt8ygGAAXg==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
|
||||
"integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
|
||||
"requires": {
|
||||
"iconv-lite": "0.4.23"
|
||||
"iconv-lite": "0.4.24"
|
||||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
|
||||
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
@@ -2981,9 +3007,9 @@
|
||||
}
|
||||
},
|
||||
"whatwg-mimetype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz",
|
||||
"integrity": "sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw=="
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
|
||||
"integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "6.5.0",
|
||||
|
@@ -20,7 +20,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "1.0.120",
|
||||
"version": "1.0.122",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
@@ -41,7 +41,7 @@
|
||||
"html-minifier": "^3.5.15",
|
||||
"image-data-uri": "^2.0.0",
|
||||
"image-type": "^3.0.0",
|
||||
"joplin-turndown": "^4.0.9",
|
||||
"joplin-turndown": "^4.0.11",
|
||||
"joplin-turndown-plugin-gfm": "^1.0.7",
|
||||
"jssha": "^2.3.0",
|
||||
"levenshtein": "^1.0.5",
|
||||
|
@@ -22,20 +22,22 @@ trap finish EXIT
|
||||
|
||||
cd "$ROOT_DIR"
|
||||
npm test tests-build/ArrayUtils.js
|
||||
npm test tests-build/encryption.js
|
||||
npm test tests-build/EnexToMd.js
|
||||
npm test tests-build/HtmlToMd.js
|
||||
npm test tests-build/markdownUtils.js
|
||||
npm test tests-build/models_BaseItem.js
|
||||
npm test tests-build/models_Folder.js
|
||||
npm test tests-build/models_Note.js
|
||||
npm test tests-build/models_Tag.js
|
||||
npm test tests-build/models_ItemChange.js
|
||||
npm test tests-build/models_Note.js
|
||||
npm test tests-build/models_Resource.js
|
||||
npm test tests-build/models_Setting.js
|
||||
npm test tests-build/models_Tag.js
|
||||
npm test tests-build/pathUtils.js
|
||||
npm test tests-build/StringUtils.js
|
||||
npm test tests-build/services_InteropService.js
|
||||
npm test tests-build/services_ResourceService.js
|
||||
npm test tests-build/urlUtils.js
|
||||
npm test tests-build/encryption.js
|
||||
npm test tests-build/services_rest_Api.js
|
||||
npm test tests-build/synchronizer.js
|
||||
npm test tests-build/services_SearchEngine.js
|
||||
npm test tests-build/StringUtils.js
|
||||
npm test tests-build/synchronizer.js
|
||||
npm test tests-build/urlUtils.js
|
@@ -37,7 +37,7 @@ describe('HtmlToMd', function() {
|
||||
const htmlPath = basePath + '/' + htmlFilename;
|
||||
const mdPath = basePath + '/' + filename(htmlFilename) + '.md';
|
||||
|
||||
// if (htmlFilename !== 'anchor_with_url_with_spaces.html') continue;
|
||||
// if (htmlFilename !== 'picture.html') continue;
|
||||
|
||||
const html = await shim.fsDriver().readFile(htmlPath);
|
||||
let expectedMd = await shim.fsDriver().readFile(mdPath);
|
||||
|
@@ -20,9 +20,9 @@ describe('StringUtils', function() {
|
||||
[['test'], 'test', 'a', 'b', 'atestb'],
|
||||
[['test'], 'Test', 'a', 'b', 'aTestb'],
|
||||
[['te[]st'], 'Te[]st', 'a', 'b', 'aTe[]stb'],
|
||||
[['test1', 'test2'], 'bla test1 blabla test1 bla test2 not this one - test22', 'a', 'b', 'bla atest1b blabla atest1b bla atest2b not this one - test22'],
|
||||
// [['test1', 'test2'], 'bla test1 blabla test1 bla test2 not this one - test22', 'a', 'b', 'bla atest1b blabla atest1b bla atest2b not this one - test22'],
|
||||
[['test1', 'test2'], 'bla test1 test1 bla test2', '<span class="highlighted-keyword">', '</span>', 'bla <span class="highlighted-keyword">test1</span> <span class="highlighted-keyword">test1</span> bla <span class="highlighted-keyword">test2</span>'],
|
||||
[[{ type:'regex', value:'test.*?'}], 'bla test1 test1 bla test2 test tttest', 'a', 'b', 'bla atest1b atest1b bla atest2b atestb tttest'],
|
||||
// [[{ type:'regex', value:'test.*?'}], 'bla test1 test1 bla test2 test tttest', 'a', 'b', 'bla atest1b atest1b bla atest2b atestb tttest'],
|
||||
];
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
@@ -36,7 +36,7 @@ describe('StringUtils', function() {
|
||||
|
||||
const actual = StringUtils.surroundKeywords(keywords, input, prefix, suffix);
|
||||
|
||||
expect(actual).toBe(expected);
|
||||
expect(actual).toBe(expected, 'Test case ' + i);
|
||||
}
|
||||
|
||||
done();
|
||||
|
47
CliClient/tests/html_to_md/picture.html
Normal file
47
CliClient/tests/html_to_md/picture.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<figure itemprop="associatedMedia image" itemscope="" itemtype="http://schema.org/ImageObject" data-component="image" data-media-id="75583fcfe2eb74f1e89ea320355ff4156f4ade7b" id="img-1">
|
||||
<meta itemprop="representativeOfPage" content="true">
|
||||
<meta itemprop="url" content="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=700&quality=85&auto=format&fit=max&s=2a6a7ba9738c6a6a79eab39ba46c34cd">
|
||||
<meta itemprop="width" content="3904">
|
||||
<meta itemprop="height" content="2342">
|
||||
<a href="#img-1" data-link-name="Launch Article Lightbox" data-is-ajax="">
|
||||
<div>
|
||||
<picture>
|
||||
<!--[if IE 9]><video style="display: none;"><![endif]-->
|
||||
<source media="(min-width: 980px) and (-webkit-min-device-pixel-ratio: 1.25), (min-width: 980px) and (min-resolution: 120dpi)" sizes="620px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=620&quality=45&auto=format&fit=max&dpr=2&s=bacff59339e5ba117f957c24218ef76b 1240w">
|
||||
<source media="(min-width: 980px)" sizes="620px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=620&quality=85&auto=format&fit=max&s=f1427ce6689688d3d6e0087fe9cb5c18 620w">
|
||||
<source media="(min-width: 740px) and (-webkit-min-device-pixel-ratio: 1.25), (min-width: 740px) and (min-resolution: 120dpi)" sizes="700px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=700&quality=45&auto=format&fit=max&dpr=2&s=70accd3c6e7d2c36f5ccc7321eab097e 1400w">
|
||||
<source media="(min-width: 740px)" sizes="700px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=700&quality=85&auto=format&fit=max&s=2a6a7ba9738c6a6a79eab39ba46c34cd 700w">
|
||||
<source media="(min-width: 660px) and (-webkit-min-device-pixel-ratio: 1.25), (min-width: 660px) and (min-resolution: 120dpi)" sizes="620px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=620&quality=45&auto=format&fit=max&dpr=2&s=bacff59339e5ba117f957c24218ef76b 1240w">
|
||||
<source media="(min-width: 660px)" sizes="620px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=620&quality=85&auto=format&fit=max&s=f1427ce6689688d3d6e0087fe9cb5c18 620w">
|
||||
<source media="(min-width: 480px) and (-webkit-min-device-pixel-ratio: 1.25), (min-width: 480px) and (min-resolution: 120dpi)" sizes="645px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=645&quality=45&auto=format&fit=max&dpr=2&s=6751fcff1b880acc45ed5aab6511a2ca 1290w">
|
||||
<source media="(min-width: 480px)" sizes="645px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=645&quality=85&auto=format&fit=max&s=d18702564383ce5d613d22b96ec6d726 645w">
|
||||
<source media="(min-width: 0px) and (-webkit-min-device-pixel-ratio: 1.25), (min-width: 0px) and (min-resolution: 120dpi)" sizes="465px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=465&quality=45&auto=format&fit=max&dpr=2&s=a7b87fb26b9813d197f3c236a5282ca4 930w">
|
||||
<source media="(min-width: 0px)" sizes="465px" srcset="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=465&quality=85&auto=format&fit=max&s=821ae9e950ae92371b40a35e98a31116 465w">
|
||||
<!--[if IE 9]></video><![endif]-->
|
||||
<img itemprop="contentUrl" alt="A blood moon" src="https://i.guim.co.uk/img/media/75583fcfe2eb74f1e89ea320355ff4156f4ade7b/0_49_3904_2342/master/3904.jpg?width=300&quality=85&auto=format&fit=max&s=1e9b643d2c109a1e271f50046eac1324">
|
||||
</picture>
|
||||
</div>
|
||||
<span>
|
||||
<svg width="22" height="22" viewBox="0 0 22 22">
|
||||
<path d="M3.4 20.2L9 14.5 7.5 13l-5.7 5.6L1 14H0v7.5l.5.5H8v-1l-4.6-.8M18.7 1.9L13 7.6 14.4 9l5.7-5.7.5 4.7h1.2V.6l-.5-.5H14v1.2l4.7.6"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<label for="show-caption">
|
||||
<span>
|
||||
<svg width="6" height="14" viewBox="0 0 6 14">
|
||||
<path d="M4.6 12l-.4 1.4c-.7.2-1.9.6-3 .6-.7 0-1.2-.2-1.2-.9 0-.2 0-.3.1-.5l2-6.7H.7l.4-1.5 4.2-.6h.2L3 12h1.6zm-.3-9.2c-.9 0-1.4-.5-1.4-1.3C2.9.5 3.7 0 4.6 0 5.4 0 6 .5 6 1.3c0 1-.8 1.5-1.7 1.5z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</label>
|
||||
<figcaption itemprop="description">
|
||||
<span>
|
||||
<svg width="11" height="10" viewBox="0 0 11 10">
|
||||
<path fill-rule="evenodd" d="M5.5 0L11 10H0z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
A blood moon last occurred in July 2018, though clouds largely obscured the celestial phenomenon in the UK.
|
||||
Photograph: JM F Almeida/Getty Images
|
||||
</figcaption>
|
||||
</figure>
|
3
CliClient/tests/html_to_md/picture.md
Normal file
3
CliClient/tests/html_to_md/picture.md
Normal file
@@ -0,0 +1,3 @@
|
||||
[](#img-1)
|
||||
|
||||
A blood moon last occurred in July 2018, though clouds largely obscured the celestial phenomenon in the UK. Photograph: JM F Almeida/Getty Images
|
@@ -1,6 +1,6 @@
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { friendlySafeFilename } = require('lib/path-utils.js');
|
||||
const { extractExecutablePath, quotePath, unquotePath, friendlySafeFilename } = require('lib/path-utils.js');
|
||||
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
@@ -36,4 +36,41 @@ describe('pathUtils', function() {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should quote and unquote paths', async (done) => {
|
||||
const testCases = [
|
||||
['', ''],
|
||||
['/my/path', '/my/path'],
|
||||
['/my/path with spaces', '"/my/path with spaces"'],
|
||||
['/my/weird"path', '"/my/weird\\"path"'],
|
||||
['c:\\Windows\\test.dll', 'c:\\Windows\\test.dll'],
|
||||
['c:\\Windows\\test test.dll', '"c:\\Windows\\test test.dll"'],
|
||||
];
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
const t = testCases[i];
|
||||
expect(quotePath(t[0])).toBe(t[1]);
|
||||
expect(unquotePath(quotePath(t[0]))).toBe(t[0]);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should extract executable path from command', async (done) => {
|
||||
const testCases = [
|
||||
['', ''],
|
||||
['/my/cmd -some -args', '/my/cmd'],
|
||||
['"/my/cmd" -some -args', '"/my/cmd"'],
|
||||
['"/my/cmd"', '"/my/cmd"'],
|
||||
['"/my/cmd and space" -some -flags', '"/my/cmd and space"'],
|
||||
['"" -some -flags', '""'],
|
||||
];
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
const t = testCases[i];
|
||||
expect(extractExecutablePath(t[0])).toBe(t[1]);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
@@ -221,37 +221,63 @@ describe('services_SearchEngine', function() {
|
||||
const expected = t[1];
|
||||
const actual = engine.parseQuery(input);
|
||||
|
||||
expect(JSON.stringify(actual.terms._)).toBe(JSON.stringify(expected._));
|
||||
expect(JSON.stringify(actual.terms.title)).toBe(JSON.stringify(expected.title));
|
||||
expect(JSON.stringify(actual.terms.body)).toBe(JSON.stringify(expected.body));
|
||||
const _Values = actual.terms._ ? actual.terms._.map(v => v.value) : undefined;
|
||||
const titleValues = actual.terms.title ? actual.terms.title.map(v => v.value) : undefined;
|
||||
const bodyValues = actual.terms.body ? actual.terms.body.map(v => v.value) : undefined;
|
||||
|
||||
expect(JSON.stringify(_Values)).toBe(JSON.stringify(expected._), 'Test case (_) ' + i);
|
||||
expect(JSON.stringify(titleValues)).toBe(JSON.stringify(expected.title), 'Test case (title) ' + i);
|
||||
expect(JSON.stringify(bodyValues)).toBe(JSON.stringify(expected.body), 'Test case (body) ' + i);
|
||||
}
|
||||
}));
|
||||
|
||||
it('should parse query strings with wildcards', asyncTest(async () => {
|
||||
// it('should parse query strings with wildcards', asyncTest(async () => {
|
||||
// let rows;
|
||||
|
||||
// const testCases = [
|
||||
// ['do*', ['do', 'dog', 'domino'], [] ],
|
||||
// // "*" is a wildcard only when used at the end (to search for documents with the specified prefix)
|
||||
// // If it's at the beginning, it's ignored, if it's in the middle, it's treated as a litteral "*".
|
||||
// ['*an*', ['an', 'anneau'], ['piano', 'plan'] ],
|
||||
// ['no*no', ['no*no'], ['nonono'] ],
|
||||
// ];
|
||||
|
||||
// for (let i = 0; i < testCases.length; i++) {
|
||||
// const t = testCases[i];
|
||||
// const input = t[0];
|
||||
// const shouldMatch = t[1];
|
||||
// const shouldNotMatch = t[2];
|
||||
// const regex = new RegExp(engine.parseQuery(input).terms._[0].value, 'gmi');
|
||||
|
||||
// for (let j = 0; j < shouldMatch.length; j++) {
|
||||
// const r = shouldMatch[j].match(regex);
|
||||
// expect(!!r).toBe(true, '"' + input + '" should match "' + shouldMatch[j] + '"');
|
||||
// }
|
||||
// }
|
||||
|
||||
// expect(engine.parseQuery('*').termCount).toBe(0);
|
||||
// }));
|
||||
|
||||
it('should handle queries with special characters', asyncTest(async () => {
|
||||
let rows;
|
||||
|
||||
const testCases = [
|
||||
['do*', ['do', 'dog', 'domino'], [] ],
|
||||
// "*" is a wildcard only when used at the end (to searhc for documents with the specified prefix)
|
||||
// If it's at the beginning, it's ignored, if it's in the middle, it's treated as a litteral "*".
|
||||
['*an*', ['an', 'anneau'], ['piano', 'plan'] ],
|
||||
['no*no', ['no*no'], ['nonono'] ],
|
||||
['did-not-match', 'did-not-match'],
|
||||
['does match', 'does match'],
|
||||
];
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
const t = testCases[i];
|
||||
const input = t[0];
|
||||
const shouldMatch = t[1];
|
||||
const shouldNotMatch = t[2];
|
||||
const regex = new RegExp(engine.parseQuery(input).terms._[0].value, 'gmi');
|
||||
const content = t[0];
|
||||
const query = t[1];
|
||||
|
||||
for (let j = 0; j < shouldMatch.length; j++) {
|
||||
const r = shouldMatch[j].match(regex);
|
||||
expect(!!r).toBe(true, '"' + input + '" should match "' + shouldMatch[j] + '"');
|
||||
}
|
||||
const n = await Note.save({ title: content });
|
||||
await engine.syncTables();
|
||||
rows = await engine.search(query);
|
||||
expect(rows.length).toBe(1);
|
||||
|
||||
await Note.delete(n.id);
|
||||
}
|
||||
|
||||
expect(engine.parseQuery('*').termCount).toBe(0);
|
||||
}));
|
||||
|
||||
});
|
@@ -170,6 +170,17 @@ describe('services_rest_Api', function() {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should create folders with supplied ID', async (done) => {
|
||||
const response = await api.route('POST', 'folders', null, JSON.stringify({
|
||||
id: '12345678123456781234567812345678',
|
||||
title: 'from api',
|
||||
}));
|
||||
|
||||
expect(response.id).toBe('12345678123456781234567812345678');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should create notes with images', async (done) => {
|
||||
let response = null;
|
||||
const f = await Folder.save({ title: "mon carnet" });
|
||||
|
@@ -15,6 +15,7 @@ const MasterKey = require('lib/models/MasterKey');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry.js');
|
||||
const WelcomeUtils = require('lib/WelcomeUtils');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
@@ -1099,4 +1100,44 @@ describe('Synchronizer', function() {
|
||||
expect(note2.title).toBe("un UPDATE");
|
||||
}));
|
||||
|
||||
it("should sync Welcome notebook and not duplicate it", asyncTest(async () => {
|
||||
// Create the Welcome items on two separate clients and verify
|
||||
// that they appear only once (due to having hard-coded IDs), that they are not duplicated.
|
||||
|
||||
Setting.setConstant('env', 'prod');
|
||||
|
||||
await WelcomeUtils.createWelcomeItems();
|
||||
await synchronizer().start();
|
||||
|
||||
await switchClient(2);
|
||||
|
||||
await WelcomeUtils.createWelcomeItems();
|
||||
const beforeFolderCount = (await Folder.all()).length;
|
||||
const beforeNoteCount = (await Note.all()).length;
|
||||
expect(beforeFolderCount >= 1).toBe(true);
|
||||
expect(beforeNoteCount > 1).toBe(true);
|
||||
|
||||
await synchronizer().start();
|
||||
|
||||
const afterFolderCount = (await Folder.all()).length;
|
||||
const afterNoteCount = (await Note.all()).length;
|
||||
|
||||
expect(afterFolderCount).toBe(beforeFolderCount);
|
||||
expect(afterNoteCount).toBe(beforeNoteCount);
|
||||
|
||||
// Changes to the Welcome items should be synced to all clients
|
||||
|
||||
const f1 = (await Folder.all())[0];
|
||||
await Folder.save({ id: f1.id, title: 'Welcome MOD' });
|
||||
|
||||
await synchronizer().start();
|
||||
|
||||
await switchClient(1);
|
||||
|
||||
await synchronizer().start();
|
||||
|
||||
const f1_1 = (await Folder.all())[0];
|
||||
expect(f1_1.title).toBe('Welcome MOD');
|
||||
}));
|
||||
|
||||
});
|
||||
|
@@ -30,6 +30,21 @@
|
||||
return output;
|
||||
}
|
||||
|
||||
function getImageSizes(element) {
|
||||
const images = element.getElementsByTagName('img');
|
||||
const output = {};
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
const img = images[i];
|
||||
output[img.src] = {
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
naturalWidth: img.naturalWidth,
|
||||
naturalHeight: img.naturalHeight,
|
||||
};
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Cleans up element by removing all its invisible children (which we don't want to render as Markdown)
|
||||
function cleanUpElement(element) {
|
||||
const childNodes = element.childNodes;
|
||||
@@ -74,7 +89,7 @@
|
||||
async function prepareCommandResponse(command) {
|
||||
console.info('Got command: ' + command.name);
|
||||
|
||||
const clippedContentResponse = (title, html) => {
|
||||
const clippedContentResponse = (title, html, imageSizes) => {
|
||||
return {
|
||||
name: 'clippedContent',
|
||||
title: title,
|
||||
@@ -83,6 +98,7 @@
|
||||
url: location.origin + location.pathname + location.search,
|
||||
parent_id: command.parent_id,
|
||||
tags: command.tags || '',
|
||||
image_sizes: imageSizes,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -99,20 +115,20 @@
|
||||
response.warning = 'Could not retrieve simplified version of page - full page has been saved instead.';
|
||||
return response;
|
||||
}
|
||||
return clippedContentResponse(article.title, article.body);
|
||||
return clippedContentResponse(article.title, article.body, getImageSizes(document));
|
||||
|
||||
} else if (command.name === "completePageHtml") {
|
||||
|
||||
const cleanDocument = document.body.cloneNode(true);
|
||||
cleanUpElement(cleanDocument);
|
||||
return clippedContentResponse(pageTitle(), cleanDocument.innerHTML);
|
||||
return clippedContentResponse(pageTitle(), cleanDocument.innerHTML, getImageSizes(document));
|
||||
|
||||
} else if (command.name === "selectedHtml") {
|
||||
|
||||
const range = window.getSelection().getRangeAt(0);
|
||||
const container = document.createElement('div');
|
||||
container.appendChild(range.cloneContents());
|
||||
return clippedContentResponse(pageTitle(), container.innerHTML);
|
||||
return clippedContentResponse(pageTitle(), container.innerHTML, getImageSizes(document));
|
||||
|
||||
} else if (command.name === 'screenshot') {
|
||||
|
||||
|
@@ -29,6 +29,7 @@ class Bridge {
|
||||
source_url: command.url,
|
||||
parent_id: command.parent_id,
|
||||
tags: command.tags || '',
|
||||
image_sizes: command.image_sizes || {},
|
||||
};
|
||||
|
||||
this.dispatch({ type: 'CLIPPED_CONTENT_SET', content: content });
|
||||
|
@@ -42,6 +42,7 @@ const appDefaultState = Object.assign({}, defaultState, {
|
||||
sidebarVisibility: true,
|
||||
windowContentSize: bridge().windowContentSize(),
|
||||
watchedNoteFiles: [],
|
||||
lastEditorScrollPercents: {},
|
||||
});
|
||||
|
||||
class Application extends BaseApplication {
|
||||
@@ -171,6 +172,14 @@ class Application extends BaseApplication {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'EDITOR_SCROLL_PERCENT_SET':
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
const newPercents = Object.assign({}, newState.lastEditorScrollPercents);
|
||||
newPercents[action.noteId] = action.percent;
|
||||
newState.lastEditorScrollPercents = newPercents;
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
error.message = 'In reducer: ' + error.message + ' Action: ' + JSON.stringify(action);
|
||||
@@ -225,6 +234,14 @@ class Application extends BaseApplication {
|
||||
this.updateMenu(screen);
|
||||
}
|
||||
|
||||
focusElement_(target) {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'focusElement',
|
||||
target: target,
|
||||
});
|
||||
}
|
||||
|
||||
updateMenu(screen) {
|
||||
if (this.lastMenuScreen_ === screen) return;
|
||||
|
||||
@@ -244,6 +261,32 @@ class Application extends BaseApplication {
|
||||
});
|
||||
}
|
||||
|
||||
const focusItems = [];
|
||||
|
||||
focusItems.push({
|
||||
label: _('Sidebar'),
|
||||
click: () => { this.focusElement_('sideBar') },
|
||||
accelerator: 'CommandOrControl+Shift+S',
|
||||
});
|
||||
|
||||
focusItems.push({
|
||||
label: _('Note list'),
|
||||
click: () => { this.focusElement_('noteList') },
|
||||
accelerator: 'CommandOrControl+Shift+L',
|
||||
});
|
||||
|
||||
focusItems.push({
|
||||
label: _('Note title'),
|
||||
click: () => { this.focusElement_('noteTitle') },
|
||||
accelerator: 'CommandOrControl+Shift+N',
|
||||
});
|
||||
|
||||
focusItems.push({
|
||||
label: _('Note body'),
|
||||
click: () => { this.focusElement_('noteBody') },
|
||||
accelerator: 'CommandOrControl+Shift+B',
|
||||
});
|
||||
|
||||
const importItems = [];
|
||||
const exportItems = [];
|
||||
const ioService = new InteropService();
|
||||
@@ -431,10 +474,22 @@ class Application extends BaseApplication {
|
||||
name: 'textItalic',
|
||||
});
|
||||
},
|
||||
}, {
|
||||
label: _('Link'),
|
||||
screens: ['Main'],
|
||||
accelerator: 'CommandOrControl+K',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'textLink',
|
||||
});
|
||||
},
|
||||
}, {
|
||||
type: 'separator',
|
||||
screens: ['Main'],
|
||||
}, {
|
||||
label: _('Insert Date Time'),
|
||||
screens: ['Main'],
|
||||
visible: false,
|
||||
accelerator: 'CommandOrControl+Shift+T',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
@@ -461,7 +516,7 @@ class Application extends BaseApplication {
|
||||
}, {
|
||||
label: _('Search in all the notes'),
|
||||
screens: ['Main'],
|
||||
accelerator: 'F6',
|
||||
accelerator: shim.isMac() ? 'Shift+Command+F' : 'F6',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
@@ -484,7 +539,7 @@ class Application extends BaseApplication {
|
||||
submenu: [{
|
||||
label: _('Toggle sidebar'),
|
||||
screens: ['Main'],
|
||||
accelerator: 'F10',
|
||||
accelerator: shim.isMac() ? 'Option+Command+S' : 'F10',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
@@ -532,6 +587,13 @@ class Application extends BaseApplication {
|
||||
click: () => {
|
||||
Setting.setValue('showCompletedTodos', !Setting.value('showCompletedTodos'));
|
||||
},
|
||||
}, {
|
||||
type: 'separator',
|
||||
screens: ['Main'],
|
||||
}, {
|
||||
label: _('Focus'),
|
||||
screens: ['Main'],
|
||||
submenu: focusItems,
|
||||
}],
|
||||
}, {
|
||||
label: _('Tools'),
|
||||
|
@@ -7,6 +7,7 @@ const { Header } = require('./Header.min.js');
|
||||
const { themeStyle } = require('../theme.js');
|
||||
const pathUtils = require('lib/path-utils.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { commandArgumentsToString } = require('lib/string-utils');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
|
||||
const shared = require('lib/components/shared/config-shared.js');
|
||||
|
||||
@@ -43,6 +44,49 @@ class ConfigScreenComponent extends React.Component {
|
||||
return output;
|
||||
}
|
||||
|
||||
sectionToComponent(key, section, settings) {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const settingComps = [];
|
||||
|
||||
for (let i = 0; i < section.metadatas.length; i++) {
|
||||
const md = section.metadatas[i];
|
||||
|
||||
const settingComp = this.settingToComponent(md.key, settings[md.key]);
|
||||
settingComps.push(settingComp);
|
||||
}
|
||||
|
||||
const sectionStyle = {
|
||||
marginBottom: 20,
|
||||
};
|
||||
|
||||
const headerStyle = Object.assign({}, theme.headerStyle, {
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.dividerColor,
|
||||
borderBottomStyle: 'solid',
|
||||
paddingBottom: '.4em',
|
||||
});
|
||||
|
||||
if (section.name === 'general') {
|
||||
sectionStyle.borderTopWidth = 0;
|
||||
}
|
||||
|
||||
const noteComp = section.name !== 'general' ? null : (
|
||||
<div style={Object.assign({}, theme.textStyle, {marginBottom: 10})}>
|
||||
{_('Notes and settings are stored in: %s', pathUtils.toSystemSlashes(Setting.value('profileDir'), process.platform))}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div key={key} style={sectionStyle}>
|
||||
<h2 style={headerStyle}>{Setting.sectionNameToLabel(section.name)}</h2>
|
||||
{noteComp}
|
||||
<div>
|
||||
{settingComps}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
settingToComponent(key, value) {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
@@ -56,6 +100,15 @@ class ConfigScreenComponent extends React.Component {
|
||||
color: theme.color,
|
||||
});
|
||||
|
||||
const subLabel = Object.assign({}, labelStyle, {
|
||||
opacity: 0.7,
|
||||
marginBottom: Math.round(rowStyle.marginBottom * 0.7),
|
||||
});
|
||||
|
||||
const invisibleLabel = Object.assign({}, labelStyle, {
|
||||
opacity: 0,
|
||||
});
|
||||
|
||||
const controlStyle = {
|
||||
display: 'inline-block',
|
||||
color: theme.color,
|
||||
@@ -70,6 +123,7 @@ class ConfigScreenComponent extends React.Component {
|
||||
});
|
||||
|
||||
const updateSettingValue = (key, value) => {
|
||||
// console.info(key + ' = ' + value);
|
||||
return shared.updateSettingValue(this, key, value);
|
||||
}
|
||||
|
||||
@@ -119,23 +173,93 @@ class ConfigScreenComponent extends React.Component {
|
||||
</div>
|
||||
);
|
||||
} else if (md.type === Setting.TYPE_STRING) {
|
||||
const onTextChange = (event) => {
|
||||
updateSettingValue(key, event.target.value);
|
||||
}
|
||||
|
||||
const inputStyle = Object.assign({}, controlStyle, {
|
||||
width: '50%',
|
||||
minWidth: '20em',
|
||||
border: '1px solid' });
|
||||
const inputType = md.secure === true ? 'password' : 'text';
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
<div style={labelStyle}><label>{md.label()}</label></div>
|
||||
<input type={inputType} style={inputStyle} value={this.state.settings[key]} onChange={(event) => {onTextChange(event)}} />
|
||||
{ descriptionComp }
|
||||
</div>
|
||||
);
|
||||
if (md.subType === 'file_path_and_args') {
|
||||
inputStyle.marginBottom = subLabel.marginBottom;
|
||||
|
||||
const splitCmd = cmdString => {
|
||||
const path = pathUtils.extractExecutablePath(cmdString);
|
||||
const args = cmdString.substr(path.length + 1);
|
||||
return [pathUtils.unquotePath(path), args];
|
||||
}
|
||||
|
||||
const joinCmd = cmdArray => {
|
||||
if (!cmdArray[0] && !cmdArray[1]) return '';
|
||||
let cmdString = pathUtils.quotePath(cmdArray[0]);
|
||||
if (!cmdString) cmdString = '""';
|
||||
if (cmdArray[1]) cmdString += ' ' + cmdArray[1];
|
||||
return cmdString;
|
||||
}
|
||||
|
||||
const onPathChange = event => {
|
||||
const cmd = splitCmd(this.state.settings[key]);
|
||||
cmd[0] = event.target.value;
|
||||
updateSettingValue(key, joinCmd(cmd));
|
||||
}
|
||||
|
||||
const onArgsChange = event => {
|
||||
const cmd = splitCmd(this.state.settings[key]);
|
||||
cmd[1] = event.target.value;
|
||||
updateSettingValue(key, joinCmd(cmd));
|
||||
}
|
||||
|
||||
const browseButtonClick = () => {
|
||||
const paths = bridge().showOpenDialog();
|
||||
if (!paths || !paths.length) return;
|
||||
const cmd = splitCmd(this.state.settings[key]);
|
||||
cmd[0] = paths[0]
|
||||
updateSettingValue(key, joinCmd(cmd));
|
||||
}
|
||||
|
||||
const cmd = splitCmd(this.state.settings[key]);
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
<div style={{display:'flex'}}>
|
||||
<div style={{flex:0, whiteSpace: 'nowrap'}}>
|
||||
<div style={labelStyle}><label>{md.label()}</label></div>
|
||||
</div>
|
||||
<div style={{flex:0}}>
|
||||
<div style={subLabel}>Path:</div>
|
||||
<div style={subLabel}>Arguments:</div>
|
||||
</div>
|
||||
<div style={{flex:1}}>
|
||||
<div style={{display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: inputStyle.marginBottom}}>
|
||||
<input type={inputType} style={Object.assign({}, inputStyle, {marginBottom:0})} onChange={(event) => {onPathChange(event)}} value={cmd[0]} />
|
||||
<button onClick={browseButtonClick} style={Object.assign({}, theme.buttonStyle, { marginLeft: 5, minHeight: 20, height: 20 })}>{_('Browse...')}</button>
|
||||
</div>
|
||||
<input type={inputType} style={inputStyle} onChange={(event) => {onArgsChange(event)}} value={cmd[1]}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{display:'flex'}}>
|
||||
<div style={{flex:0, whiteSpace: 'nowrap'}}>
|
||||
<div style={invisibleLabel}><label>{md.label()}</label></div>
|
||||
</div>
|
||||
<div style={{flex:1}}>
|
||||
{ descriptionComp }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
const onTextChange = (event) => {
|
||||
updateSettingValue(key, event.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
<div style={labelStyle}><label>{md.label()}</label></div>
|
||||
<input type={inputType} style={inputStyle} value={this.state.settings[key]} onChange={(event) => {onTextChange(event)}} />
|
||||
{ descriptionComp }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
} else if (md.type === Setting.TYPE_INT) {
|
||||
const onNumChange = (event) => {
|
||||
updateSettingValue(key, event.target.value);
|
||||
@@ -170,21 +294,31 @@ class ConfigScreenComponent extends React.Component {
|
||||
|
||||
render() {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
const style = Object.assign({
|
||||
backgroundColor: theme.backgroundColor
|
||||
}, this.props.style, { overflow: 'auto' });
|
||||
const settings = this.state.settings;
|
||||
}, this.props.style, {
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
});
|
||||
|
||||
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
|
||||
let settings = this.state.settings;
|
||||
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10 });
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0 });
|
||||
|
||||
const hasChanges = !!this.state.changedSettingKeys.length;
|
||||
|
||||
const buttonStyle = Object.assign({}, theme.buttonStyle, {
|
||||
display: this.state.changedSettingKeys.length ? 'inline-block' : 'none',
|
||||
display: 'inline-block',
|
||||
marginRight: 10,
|
||||
});
|
||||
|
||||
const settingComps = shared.settingsToComponents(this, 'desktop', settings);
|
||||
const buttonStyleApprove = Object.assign({}, buttonStyle, {
|
||||
opacity: hasChanges ? 1 : theme.disabledOpacity,
|
||||
});
|
||||
|
||||
const settingComps = shared.settingsToComponents2(this, 'desktop', settings);
|
||||
|
||||
const syncTargetMd = SyncTargetRegistry.idToMetadata(settings['sync.target']);
|
||||
|
||||
@@ -199,22 +333,29 @@ class ConfigScreenComponent extends React.Component {
|
||||
|
||||
settingComps.push(
|
||||
<div key="check_sync_config_button" style={this.rowStyle_}>
|
||||
<button style={buttonStyle} disabled={this.state.checkSyncConfigResult === 'checking'} onClick={this.checkSyncConfig_}>{_('Check synchronisation configuration')}</button>
|
||||
<button disabled={this.state.checkSyncConfigResult === 'checking'} style={buttonStyle} onClick={this.checkSyncConfig_}>{_('Check synchronisation configuration')}</button>
|
||||
{ statusComp }
|
||||
</div>);
|
||||
}
|
||||
|
||||
const buttonBarStyle = {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: 15,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomStyle: 'solid',
|
||||
borderBottomColor: theme.dividerColor,
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={style}>
|
||||
<Header style={headerStyle} />
|
||||
<div style={buttonBarStyle}>
|
||||
<button onClick={() => {this.onCancelClick()}} style={buttonStyle}>{'⬅ ' + _('Cancel')}</button>
|
||||
<button disabled={!hasChanges} onClick={() => {this.onSaveClick()}} style={buttonStyleApprove}>{_('OK')}</button>
|
||||
<button disabled={!hasChanges} onClick={() => {this.onApplyClick()}} style={buttonStyleApprove}>{_('Apply')}</button>
|
||||
</div>
|
||||
<div style={containerStyle}>
|
||||
<div style={Object.assign({}, theme.textStyle, {marginBottom: 20})}>
|
||||
{_('Notes and settings are stored in: %s', pathUtils.toSystemSlashes(Setting.value('profileDir'), process.platform))}
|
||||
</div>
|
||||
{ settingComps }
|
||||
<button onClick={() => {this.onSaveClick()}} style={buttonStyle}>{_('OK')}</button>
|
||||
<button onClick={() => {this.onCancelClick()}} style={buttonStyle}>{_('Cancel')}</button>
|
||||
<button onClick={() => {this.onApplyClick()}} style={buttonStyle}>{_('Apply')}</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@@ -3,6 +3,7 @@ const { connect } = require('react-redux');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { themeStyle } = require('../theme.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
|
||||
class HeaderComponent extends React.Component {
|
||||
|
||||
@@ -10,6 +11,7 @@ class HeaderComponent extends React.Component {
|
||||
super();
|
||||
this.state = {
|
||||
searchQuery: '',
|
||||
showSearchUsageLink: false,
|
||||
};
|
||||
|
||||
this.scheduleSearchChangeEventIid_ = null;
|
||||
@@ -37,6 +39,27 @@ class HeaderComponent extends React.Component {
|
||||
triggerOnQuery('');
|
||||
if (this.searchElement_) this.searchElement_.focus();
|
||||
}
|
||||
|
||||
this.search_onFocus = event => {
|
||||
if (this.hideSearchUsageLinkIID_) {
|
||||
clearTimeout(this.hideSearchUsageLinkIID_);
|
||||
this.hideSearchUsageLinkIID_ = null;
|
||||
}
|
||||
|
||||
this.setState({ showSearchUsageLink: true });
|
||||
}
|
||||
|
||||
this.search_onBlur = event => {
|
||||
if (this.hideSearchUsageLinkIID_) return;
|
||||
|
||||
this.hideSearchUsageLinkIID_ = setTimeout(() => {
|
||||
this.setState({ showSearchUsageLink: false });
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
this.searchUsageLink_click = event => {
|
||||
bridge().openExternal('https://joplin.cozic.net/#searching');
|
||||
}
|
||||
}
|
||||
|
||||
async componentWillReceiveProps(nextProps) {
|
||||
@@ -45,6 +68,13 @@ class HeaderComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.hideSearchUsageLinkIID_) {
|
||||
clearTimeout(this.hideSearchUsageLinkIID_);
|
||||
this.hideSearchUsageLinkIID_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
async doCommand(command) {
|
||||
if (!command) return;
|
||||
|
||||
@@ -100,6 +130,8 @@ class HeaderComponent extends React.Component {
|
||||
}
|
||||
|
||||
makeSearch(key, style, options, state) {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
const inputStyle = {
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
@@ -137,6 +169,10 @@ class HeaderComponent extends React.Component {
|
||||
const icon = <i style={iconStyle} className={"fa " + iconName}></i>
|
||||
if (options.onQuery) this.searchOnQuery_ = options.onQuery;
|
||||
|
||||
const usageLink = !this.state.showSearchUsageLink ? null : (
|
||||
<a onClick={this.searchUsageLink_click} style={theme.urlStyle} href="#">{_('Usage')}</a>
|
||||
);
|
||||
|
||||
return (
|
||||
<div key={key} style={containerStyle}>
|
||||
<input
|
||||
@@ -146,12 +182,15 @@ class HeaderComponent extends React.Component {
|
||||
value={state.searchQuery}
|
||||
onChange={this.search_onChange}
|
||||
ref={elem => this.searchElement_ = elem}
|
||||
onFocus={this.search_onFocus}
|
||||
onBlur={this.search_onBlur}
|
||||
/>
|
||||
<a
|
||||
href="#"
|
||||
style={searchButton}
|
||||
onClick={this.search_onClear}
|
||||
>{icon}</a>
|
||||
{usageLink}
|
||||
</div>);
|
||||
}
|
||||
|
||||
|
@@ -6,13 +6,23 @@ class ItemList extends React.Component {
|
||||
super();
|
||||
|
||||
this.scrollTop_ = 0;
|
||||
|
||||
this.listRef = React.createRef();
|
||||
|
||||
this.onScroll = this.onScroll.bind(this);
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
}
|
||||
|
||||
visibleItemCount(props) {
|
||||
if (typeof props === 'undefined') props = this.props;
|
||||
return Math.ceil(props.style.height / props.itemHeight);
|
||||
}
|
||||
|
||||
updateStateItemIndexes(props) {
|
||||
if (typeof props === 'undefined') props = this.props;
|
||||
|
||||
const topItemIndex = Math.floor(this.scrollTop_ / props.itemHeight);
|
||||
const visibleItemCount = Math.ceil(props.style.height / props.itemHeight);
|
||||
const visibleItemCount = this.visibleItemCount(props);
|
||||
|
||||
let bottomItemIndex = topItemIndex + visibleItemCount;
|
||||
if (bottomItemIndex >= props.items.length) bottomItemIndex = props.items.length - 1;
|
||||
@@ -31,8 +41,33 @@ class ItemList extends React.Component {
|
||||
this.updateStateItemIndexes(newProps);
|
||||
}
|
||||
|
||||
onScroll(scrollTop) {
|
||||
onScroll(event) {
|
||||
this.scrollTop_ = event.target.scrollTop;
|
||||
this.updateStateItemIndexes();
|
||||
}
|
||||
|
||||
onKeyDown(event) {
|
||||
if (this.props.onKeyDown) this.props.onKeyDown(event);
|
||||
}
|
||||
|
||||
makeItemIndexVisible(itemIndex) {
|
||||
const top = Math.min(this.props.items.length - 1, this.state.topItemIndex + 1);
|
||||
const bottom = Math.max(0, this.state.bottomItemIndex - 1)
|
||||
|
||||
if (itemIndex >= top && itemIndex <= bottom) return;
|
||||
|
||||
let scrollTop = 0;
|
||||
if (itemIndex < top) {
|
||||
scrollTop = this.props.itemHeight * itemIndex;
|
||||
} else {
|
||||
scrollTop = this.props.itemHeight * itemIndex - (this.visibleItemCount() - 1) * this.props.itemHeight;
|
||||
}
|
||||
|
||||
if (scrollTop < 0) scrollTop = 0;
|
||||
|
||||
this.scrollTop_ = scrollTop;
|
||||
this.listRef.current.scrollTop = scrollTop;
|
||||
|
||||
this.updateStateItemIndexes();
|
||||
}
|
||||
|
||||
@@ -61,10 +96,8 @@ class ItemList extends React.Component {
|
||||
let classes = ['item-list'];
|
||||
if (this.props.className) classes.push(this.props.className);
|
||||
|
||||
const that = this;
|
||||
|
||||
return (
|
||||
<div className={classes.join(' ')} style={style} onScroll={ (event) => { this.onScroll(event.target.scrollTop) }}>
|
||||
<div ref={this.listRef} className={classes.join(' ')} style={style} onScroll={this.onScroll} onKeyDown={this.onKeyDown}>
|
||||
{ itemComps }
|
||||
</div>
|
||||
);
|
||||
|
@@ -295,7 +295,7 @@ class MainScreenComponent extends React.Component {
|
||||
height: rowHeight,
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
};
|
||||
};
|
||||
|
||||
if (isSidebarVisible === false) {
|
||||
this.styles_.sideBar.width = 0;
|
||||
@@ -338,9 +338,9 @@ class MainScreenComponent extends React.Component {
|
||||
render() {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const style = Object.assign({
|
||||
color: theme.color,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
}, this.props.style);
|
||||
color: theme.color,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
}, this.props.style);
|
||||
const promptOptions = this.state.promptOptions;
|
||||
const folders = this.props.folders;
|
||||
const notes = this.props.notes;
|
||||
|
@@ -13,8 +13,10 @@ const eventManager = require('../eventManager');
|
||||
const InteropService = require('lib/services/InteropService');
|
||||
const InteropServiceHelper = require('../InteropServiceHelper.js');
|
||||
const Search = require('lib/models/Search');
|
||||
const { stateUtils } = require('lib/reducer');
|
||||
const Mark = require('mark.js/dist/mark.min.js');
|
||||
const SearchEngine = require('lib/services/SearchEngine');
|
||||
const NoteListUtils = require('./utils/NoteListUtils');
|
||||
const { replaceRegexDiacritics, pregQuote } = require('lib/string-utils');
|
||||
|
||||
class NoteListComponent extends React.Component {
|
||||
@@ -22,7 +24,11 @@ class NoteListComponent extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.itemListRef = React.createRef();
|
||||
this.itemAnchorRefs_ = {};
|
||||
|
||||
this.itemRenderer = this.itemRenderer.bind(this);
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
}
|
||||
|
||||
style() {
|
||||
@@ -79,103 +85,10 @@ class NoteListComponent extends React.Component {
|
||||
|
||||
if (!noteIds.length) return;
|
||||
|
||||
const notes = noteIds.map((id) => BaseModel.byId(this.props.notes, id));
|
||||
|
||||
let hasEncrypted = false;
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
if (!!notes[i].encryption_applied) hasEncrypted = true;
|
||||
}
|
||||
|
||||
const menu = new Menu()
|
||||
|
||||
if (!hasEncrypted) {
|
||||
menu.append(new MenuItem({label: _('Add or remove tags'), enabled: noteIds.length === 1, click: async () => {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'setTags',
|
||||
noteId: noteIds[0],
|
||||
});
|
||||
}}));
|
||||
|
||||
menu.append(new MenuItem({label: _('Duplicate'), click: async () => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
await Note.duplicate(noteIds[i], {
|
||||
uniqueTitle: _('%s - Copy', note.title),
|
||||
});
|
||||
}
|
||||
}}));
|
||||
|
||||
if (noteIds.length <= 1) {
|
||||
menu.append(new MenuItem({label: _('Switch between note and to-do type'), click: async () => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
await Note.save(Note.toggleIsTodo(note), { userSideValidation: true });
|
||||
eventManager.emit('noteTypeToggle', { noteId: note.id });
|
||||
}
|
||||
}}));
|
||||
} else {
|
||||
const switchNoteType = async (noteIds, type) => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
const newNote = Note.changeNoteType(note, type);
|
||||
if (newNote === note) continue;
|
||||
await Note.save(newNote, { userSideValidation: true });
|
||||
eventManager.emit('noteTypeToggle', { noteId: note.id });
|
||||
}
|
||||
}
|
||||
|
||||
menu.append(new MenuItem({label: _('Switch to note type'), click: async () => {
|
||||
await switchNoteType(noteIds, 'note');
|
||||
}}));
|
||||
|
||||
menu.append(new MenuItem({label: _('Switch to to-do type'), click: async () => {
|
||||
await switchNoteType(noteIds, 'todo');
|
||||
}}));
|
||||
}
|
||||
|
||||
menu.append(new MenuItem({label: _('Copy Markdown link'), click: async () => {
|
||||
const { clipboard } = require('electron');
|
||||
const links = [];
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
links.push(Note.markdownTag(note));
|
||||
}
|
||||
clipboard.writeText(links.join(' '));
|
||||
}}));
|
||||
|
||||
const exportMenu = new Menu();
|
||||
|
||||
const ioService = new InteropService();
|
||||
const ioModules = ioService.modules();
|
||||
for (let i = 0; i < ioModules.length; i++) {
|
||||
const module = ioModules[i];
|
||||
if (module.type !== 'exporter') continue;
|
||||
|
||||
exportMenu.append(new MenuItem({ label: module.fullLabel() , click: async () => {
|
||||
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceNoteIds: noteIds });
|
||||
}}));
|
||||
}
|
||||
|
||||
if (noteIds.length === 1) {
|
||||
exportMenu.append(new MenuItem({ label: 'PDF - ' + _('PDF File') , click: () => {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'exportPdf',
|
||||
});
|
||||
}}));
|
||||
}
|
||||
|
||||
const exportMenuItem = new MenuItem({label: _('Export'), submenu: exportMenu});
|
||||
|
||||
menu.append(exportMenuItem);
|
||||
}
|
||||
|
||||
menu.append(new MenuItem({label: _('Delete'), click: async () => {
|
||||
const ok = bridge().showConfirmMessageBox(noteIds.length > 1 ? _('Delete notes?') : _('Delete note?'));
|
||||
if (!ok) return;
|
||||
await Note.batchDelete(noteIds);
|
||||
}}));
|
||||
const menu = NoteListUtils.makeContextMenu(noteIds, {
|
||||
notes: this.props.notes,
|
||||
dispatch: this.props.dispatch,
|
||||
});
|
||||
|
||||
menu.popup(bridge().window());
|
||||
}
|
||||
@@ -185,7 +98,7 @@ class NoteListComponent extends React.Component {
|
||||
const width = this.props.style.width;
|
||||
|
||||
const onTitleClick = async (event, item) => {
|
||||
if (event.ctrlKey) {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
event.preventDefault();
|
||||
this.props.dispatch({
|
||||
type: 'NOTE_SELECT_TOGGLE',
|
||||
@@ -304,11 +217,15 @@ class NoteListComponent extends React.Component {
|
||||
<i style={watchedIconStyle} className={"fa fa-external-link"}></i>
|
||||
);
|
||||
|
||||
if (!this.itemAnchorRefs_[item.id]) this.itemAnchorRefs_[item.id] = React.createRef();
|
||||
const ref = this.itemAnchorRefs_[item.id];
|
||||
|
||||
// Need to include "todo_completed" in key so that checkbox is updated when
|
||||
// item is changed via sync.
|
||||
return <div key={item.id + '_' + item.todo_completed} style={style}>
|
||||
{checkbox}
|
||||
<a
|
||||
ref={ref}
|
||||
className="list-item"
|
||||
onContextMenu={(event) => this.itemContextMenu(event)}
|
||||
href="#"
|
||||
@@ -324,6 +241,142 @@ class NoteListComponent extends React.Component {
|
||||
</div>
|
||||
}
|
||||
|
||||
itemAnchorRef(itemId) {
|
||||
if (this.itemAnchorRefs_[itemId] && this.itemAnchorRefs_[itemId].current) return this.itemAnchorRefs_[itemId].current;
|
||||
return null;
|
||||
}
|
||||
|
||||
doCommand(command) {
|
||||
if (!command) return;
|
||||
|
||||
let commandProcessed = true;
|
||||
|
||||
if (command.name === 'focusElement' && command.target === 'noteList') {
|
||||
if (this.props.selectedNoteIds.length) {
|
||||
const ref = this.itemAnchorRef(this.props.selectedNoteIds[0]);
|
||||
if (ref) ref.focus();
|
||||
}
|
||||
} else {
|
||||
commandProcessed = false;
|
||||
}
|
||||
|
||||
if (commandProcessed) {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (prevProps.windowCommand !== this.props.windowCommand) {
|
||||
this.doCommand(this.props.windowCommand);
|
||||
}
|
||||
|
||||
if (prevProps.selectedNoteIds !== this.props.selectedNoteIds && this.props.selectedNoteIds.length === 1) {
|
||||
const id = this.props.selectedNoteIds[0];
|
||||
for (let i = 0; i < this.props.notes.length; i++) {
|
||||
if (this.props.notes[i].id === id) {
|
||||
this.itemListRef.current.makeItemIndexVisible(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async onKeyDown(event) {
|
||||
const keyCode = event.keyCode;
|
||||
const noteIds = this.props.selectedNoteIds;
|
||||
|
||||
if (noteIds.length === 1 && (keyCode === 40 || keyCode === 38)) { // DOWN / UP
|
||||
const noteId = noteIds[0];
|
||||
let noteIndex = BaseModel.modelIndexById(this.props.notes, noteId);
|
||||
const inc = keyCode === 38 ? -1 : +1;
|
||||
|
||||
noteIndex += inc;
|
||||
|
||||
if (noteIndex < 0) noteIndex = 0;
|
||||
if (noteIndex > this.props.notes.length - 1) noteIndex = this.props.notes.length - 1;
|
||||
|
||||
const newSelectedNote = this.props.notes[noteIndex];
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'NOTE_SELECT',
|
||||
id: newSelectedNote.id,
|
||||
});
|
||||
|
||||
this.itemListRef.current.makeItemIndexVisible(noteIndex);
|
||||
|
||||
this.focusNoteId_(newSelectedNote.id);
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (noteIds.length && keyCode === 46) { // DELETE
|
||||
event.preventDefault();
|
||||
await NoteListUtils.confirmDeleteNotes(noteIds);
|
||||
}
|
||||
|
||||
if (noteIds.length && keyCode === 32) { // SPACE
|
||||
event.preventDefault();
|
||||
|
||||
const notes = BaseModel.modelsByIds(this.props.notes, noteIds);
|
||||
const todos = notes.filter(n => !!n.is_todo);
|
||||
if (!todos.length) return;
|
||||
|
||||
for (let i = 0; i < todos.length; i++) {
|
||||
const toggledTodo = Note.toggleTodoCompleted(todos[i]);
|
||||
await Note.save(toggledTodo);
|
||||
}
|
||||
|
||||
this.focusNoteId_(todos[0].id);
|
||||
}
|
||||
|
||||
if (keyCode === 9) { // TAB
|
||||
event.preventDefault();
|
||||
|
||||
if (event.shiftKey) {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'focusElement',
|
||||
target: 'sideBar',
|
||||
});
|
||||
} else {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'focusElement',
|
||||
target: 'noteTitle',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
focusNoteId_(noteId) {
|
||||
// - We need to focus the item manually otherwise focus might be lost when the
|
||||
// list is scrolled and items within it are being rebuilt.
|
||||
// - We need to use an interval because when leaving the arrow pressed, the rendering
|
||||
// of items might lag behind and so the ref is not yet available at this point.
|
||||
if (!this.itemAnchorRef(noteId)) {
|
||||
if (this.focusItemIID_) clearInterval(this.focusItemIID_);
|
||||
this.focusItemIID_ = setInterval(() => {
|
||||
if (this.itemAnchorRef(noteId)) {
|
||||
this.itemAnchorRef(noteId).focus();
|
||||
clearInterval(this.focusItemIID_)
|
||||
this.focusItemIID_ = null;
|
||||
}
|
||||
}, 10);
|
||||
} else {
|
||||
this.itemAnchorRef(noteId).focus();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.focusItemIID_) {
|
||||
clearInterval(this.focusItemIID_);
|
||||
this.focusItemIID_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const style = this.props.style;
|
||||
@@ -345,11 +398,13 @@ class NoteListComponent extends React.Component {
|
||||
|
||||
return (
|
||||
<ItemList
|
||||
ref={this.itemListRef}
|
||||
itemHeight={this.style().listItem.height}
|
||||
style={style}
|
||||
className={"note-list"}
|
||||
items={notes}
|
||||
itemRenderer={this.itemRenderer}
|
||||
onKeyDown={this.onKeyDown}
|
||||
></ItemList>
|
||||
);
|
||||
}
|
||||
@@ -366,6 +421,7 @@ const mapStateToProps = (state) => {
|
||||
searches: state.searches,
|
||||
selectedSearchId: state.selectedSearchId,
|
||||
watchedNoteFiles: state.watchedNoteFiles,
|
||||
windowCommand: state.windowCommand,
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -13,6 +13,7 @@ class NoteSearchBarComponent extends React.Component {
|
||||
};
|
||||
|
||||
this.searchInput_change = this.searchInput_change.bind(this);
|
||||
this.searchInput_keyDown = this.searchInput_keyDown.bind(this);
|
||||
this.previousButton_click = this.previousButton_click.bind(this);
|
||||
this.nextButton_click = this.nextButton_click.bind(this);
|
||||
this.closeButton_click = this.closeButton_click.bind(this);
|
||||
@@ -70,6 +71,24 @@ class NoteSearchBarComponent extends React.Component {
|
||||
this.triggerOnChange(query);
|
||||
}
|
||||
|
||||
searchInput_keyDown(event) {
|
||||
if (event.keyCode === 13) { // ENTER
|
||||
event.preventDefault();
|
||||
|
||||
if (!event.shiftKey) {
|
||||
if (this.props.onNext) this.props.onNext();
|
||||
} else {
|
||||
if (this.props.onPrevious) this.props.onPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.keyCode === 27) { // ESCAPE
|
||||
event.preventDefault();
|
||||
|
||||
if (this.props.onClose) this.props.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
previousButton_click(event) {
|
||||
if (this.props.onPrevious) this.props.onPrevious();
|
||||
}
|
||||
@@ -101,7 +120,7 @@ class NoteSearchBarComponent extends React.Component {
|
||||
<div style={this.props.style}>
|
||||
<div style={{display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
||||
{ closeButton }
|
||||
<input placeholder={_('Search...')} value={this.state.query} onChange={this.searchInput_change} ref="searchInput" type="text" style={{width: 200, marginRight: 5}}></input>
|
||||
<input placeholder={_('Search...')} value={this.state.query} onChange={this.searchInput_change} onKeyDown={this.searchInput_keyDown} ref="searchInput" type="text" style={{width: 200, marginRight: 5}}></input>
|
||||
{ nextButton }
|
||||
{ previousButton }
|
||||
</div>
|
||||
|
@@ -28,6 +28,7 @@ const ArrayUtils = require('lib/ArrayUtils');
|
||||
const ObjectUtils = require('lib/ObjectUtils');
|
||||
const urlUtils = require('lib/urlUtils');
|
||||
const dialogs = require('./dialogs');
|
||||
const NoteListUtils = require('./utils/NoteListUtils');
|
||||
const NoteSearchBar = require('./NoteSearchBar.min.js');
|
||||
const markdownUtils = require('lib/markdownUtils');
|
||||
const ExternalEditWatcher = require('lib/services/ExternalEditWatcher');
|
||||
@@ -35,6 +36,7 @@ const ResourceFetcher = require('lib/services/ResourceFetcher');
|
||||
const { toSystemSlashes, safeFilename } = require('lib/path-utils');
|
||||
const { clipboard } = require('electron');
|
||||
const SearchEngine = require('lib/services/SearchEngine');
|
||||
const NoteTextViewer = require('./NoteTextViewer.min');
|
||||
|
||||
require('brace/mode/markdown');
|
||||
// https://ace.c9.io/build/kitchen-sink.html
|
||||
@@ -78,6 +80,8 @@ class NoteTextComponent extends React.Component {
|
||||
localSearch: Object.assign({}, this.localSearchDefaultState),
|
||||
};
|
||||
|
||||
this.webviewRef_ = React.createRef();
|
||||
|
||||
this.lastLoadedNoteId_ = null;
|
||||
|
||||
this.webviewListeners_ = null;
|
||||
@@ -103,9 +107,9 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
this.onAlarmChange_ = (event) => { if (event.noteId === this.props.noteId) this.reloadNote(this.props); }
|
||||
this.onNoteTypeToggle_ = (event) => { if (event.noteId === this.props.noteId) this.reloadNote(this.props); }
|
||||
this.onTodoToggle_ = (event) => { if (event.noteId === this.props.noteId) this.reloadNote(this.props); }
|
||||
this.onAlarmChange_ = (event) => { if (event.noteId === this.props.noteId) this.scheduleReloadNote(this.props); }
|
||||
this.onNoteTypeToggle_ = (event) => { if (event.noteId === this.props.noteId) this.scheduleReloadNote(this.props); }
|
||||
this.onTodoToggle_ = (event) => { if (event.noteId === this.props.noteId) this.scheduleReloadNote(this.props); }
|
||||
|
||||
this.onEditorPaste_ = async (event = null) => {
|
||||
const formats = clipboard.availableFormats();
|
||||
@@ -214,7 +218,7 @@ class NoteTextComponent extends React.Component {
|
||||
this.externalEditWatcher_noteChange = (event) => {
|
||||
if (!this.state.note || !this.state.note.id) return;
|
||||
if (event.id === this.state.note.id) {
|
||||
this.reloadNote(this.props);
|
||||
this.scheduleReloadNote(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +261,10 @@ class NoteTextComponent extends React.Component {
|
||||
showLocalSearch: false,
|
||||
});
|
||||
}
|
||||
|
||||
this.titleField_keyDown = this.titleField_keyDown.bind(this);
|
||||
this.webview_ipcMessage = this.webview_ipcMessage.bind(this);
|
||||
this.webview_domReady = this.webview_domReady.bind(this);
|
||||
}
|
||||
|
||||
// Note:
|
||||
@@ -357,7 +365,6 @@ class NoteTextComponent extends React.Component {
|
||||
this.saveIfNeeded();
|
||||
|
||||
this.mdToHtml_ = null;
|
||||
this.destroyWebview();
|
||||
|
||||
eventManager.removeListener('alarmChange', this.onAlarmChange_);
|
||||
eventManager.removeListener('noteTypeToggle', this.onNoteTypeToggle_);
|
||||
@@ -398,6 +405,20 @@ class NoteTextComponent extends React.Component {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
scheduleReloadNote(props, options = null) {
|
||||
if (this.scheduleReloadNoteIID_) {
|
||||
clearTimeout(this.scheduleReloadNoteIID_);
|
||||
this.scheduleReloadNoteIID_ = null;
|
||||
}
|
||||
|
||||
this.scheduleReloadNoteIID_ = setTimeout(() => {
|
||||
this.reloadNote(props, options);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// Generally, reloadNote() should not be called directly so that it's not called multiple times
|
||||
// from multiple places within a short interval of time. Instead use scheduleReloadNote() to
|
||||
// delay reloading a bit and make sure that only one reload operation is performed.
|
||||
async reloadNote(props, options = null) {
|
||||
if (!options) options = {};
|
||||
if (!('noReloadIfLocalChanges' in options)) options.noReloadIfLocalChanges = false;
|
||||
@@ -412,12 +433,17 @@ class NoteTextComponent extends React.Component {
|
||||
let loadingNewNote = true;
|
||||
let parentFolder = null;
|
||||
let noteTags = [];
|
||||
let scrollPercent = 0;
|
||||
|
||||
if (props.newNote) {
|
||||
note = Object.assign({}, props.newNote);
|
||||
this.lastLoadedNoteId_ = null;
|
||||
} else {
|
||||
noteId = props.noteId;
|
||||
|
||||
scrollPercent = this.props.lastEditorScrollPercents[noteId];
|
||||
if (!scrollPercent) scrollPercent = 0;
|
||||
|
||||
loadingNewNote = stateNoteId !== noteId;
|
||||
noteTags = await Tag.tagsByNoteId(noteId);
|
||||
this.lastLoadedNoteId_ = noteId;
|
||||
@@ -438,7 +464,7 @@ class NoteTextComponent extends React.Component {
|
||||
// If we are loading nothing (noteId == null), make sure to
|
||||
// set webviewReady to false too because the webview component
|
||||
// is going to be removed in render().
|
||||
const webviewReady = this.webview_ && this.state.webviewReady && (noteId || props.newNote);
|
||||
const webviewReady = !!this.webviewRef_.current && this.state.webviewReady && (!!noteId || !!props.newNote);
|
||||
|
||||
// Scroll back to top when loading new note
|
||||
if (loadingNewNote) {
|
||||
@@ -481,6 +507,11 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
this.editor_.editor.clearSelection();
|
||||
this.editor_.editor.moveCursorTo(0,0);
|
||||
|
||||
setTimeout(() => {
|
||||
this.setEditorPercentScroll(scrollPercent ? scrollPercent : 0);
|
||||
this.setViewerPercentScroll(scrollPercent ? scrollPercent : 0);
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,18 +565,18 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
async componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.newNote) {
|
||||
await this.reloadNote(nextProps);
|
||||
} else if ('noteId' in nextProps && nextProps.noteId !== this.props.noteId) {
|
||||
await this.reloadNote(nextProps);
|
||||
if (this.props.newNote !== nextProps.newNote && nextProps.newNote) {
|
||||
await this.scheduleReloadNote(nextProps);
|
||||
} else if (('noteId' in nextProps) && nextProps.noteId !== this.props.noteId) {
|
||||
await this.scheduleReloadNote(nextProps);
|
||||
} else if ('noteTags' in nextProps && this.areNoteTagsModified(nextProps.noteTags, this.state.noteTags)) {
|
||||
this.setState({
|
||||
noteTags: nextProps.noteTags
|
||||
});
|
||||
}
|
||||
|
||||
if ('syncStarted' in nextProps && !nextProps.syncStarted && !this.isModified()) {
|
||||
await this.reloadNote(nextProps, { noReloadIfLocalChanges: true });
|
||||
if ((nextProps.syncStarted !== this.props.syncStarted) && ('syncStarted' in nextProps) && !nextProps.syncStarted && !this.isModified()) {
|
||||
await this.scheduleReloadNote(nextProps, { noReloadIfLocalChanges: true });
|
||||
}
|
||||
|
||||
if (nextProps.windowCommand) {
|
||||
@@ -678,6 +709,10 @@ class NoteTextComponent extends React.Component {
|
||||
type: "FOLDER_AND_NOTE_SELECT",
|
||||
folderId: item.parent_id,
|
||||
noteId: item.id,
|
||||
historyNoteAction: {
|
||||
id: this.state.note.id,
|
||||
parent_id: this.state.note.parent_id,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
throw new Error('Unsupported item type: ' + item.type_);
|
||||
@@ -710,11 +745,31 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
setEditorPercentScroll(p) {
|
||||
const noteId = this.props.noteId;
|
||||
|
||||
if (noteId) {
|
||||
this.props.dispatch({
|
||||
type: 'EDITOR_SCROLL_PERCENT_SET',
|
||||
noteId: noteId,
|
||||
percent: p,
|
||||
});
|
||||
}
|
||||
|
||||
this.editorSetScrollTop(p * this.editorMaxScroll());
|
||||
}
|
||||
|
||||
setViewerPercentScroll(p) {
|
||||
this.webview_.send('setPercentScroll', p);
|
||||
const noteId = this.props.noteId;
|
||||
|
||||
if (noteId) {
|
||||
this.props.dispatch({
|
||||
type: 'EDITOR_SCROLL_PERCENT_SET',
|
||||
noteId: noteId,
|
||||
percent: p,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.webviewRef_.current) this.webviewRef_.current.wrappedInstance.send('setPercentScroll', p);
|
||||
}
|
||||
|
||||
editor_scroll() {
|
||||
@@ -724,30 +779,19 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
const m = this.editorMaxScroll();
|
||||
this.setViewerPercentScroll(m ? this.editorScrollTop() / m : 0);
|
||||
const percent = m ? this.editorScrollTop() / m : 0;
|
||||
|
||||
this.setViewerPercentScroll(percent);
|
||||
}
|
||||
|
||||
webview_domReady() {
|
||||
if (!this.webview_) return;
|
||||
if (!this.webviewRef_.current) return;
|
||||
|
||||
this.setState({
|
||||
webviewReady: true,
|
||||
});
|
||||
|
||||
if (Setting.value('env') === 'dev') this.webview_.openDevTools();
|
||||
}
|
||||
|
||||
webview_ref(element) {
|
||||
if (this.webview_) {
|
||||
if (this.webview_ === element) return;
|
||||
this.destroyWebview();
|
||||
}
|
||||
|
||||
if (!element) {
|
||||
this.destroyWebview();
|
||||
} else {
|
||||
this.initWebview(element);
|
||||
}
|
||||
// if (Setting.value('env') === 'dev') this.webview_.openDevTools();
|
||||
}
|
||||
|
||||
editor_ref(element) {
|
||||
@@ -822,35 +866,6 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
initWebview(wv) {
|
||||
if (!this.webviewListeners_) {
|
||||
this.webviewListeners_ = {
|
||||
'dom-ready': this.webview_domReady.bind(this),
|
||||
'ipc-message': this.webview_ipcMessage.bind(this),
|
||||
};
|
||||
}
|
||||
|
||||
for (let n in this.webviewListeners_) {
|
||||
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
||||
const fn = this.webviewListeners_[n];
|
||||
wv.addEventListener(n, fn);
|
||||
}
|
||||
|
||||
this.webview_ = wv;
|
||||
}
|
||||
|
||||
destroyWebview() {
|
||||
if (!this.webview_) return;
|
||||
|
||||
for (let n in this.webviewListeners_) {
|
||||
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
||||
const fn = this.webviewListeners_[n];
|
||||
this.webview_.removeEventListener(n, fn);
|
||||
}
|
||||
|
||||
this.webview_ = null;
|
||||
}
|
||||
|
||||
aceEditor_change(body) {
|
||||
shared.noteComponent_change(this, 'body', body);
|
||||
this.scheduleHtmlUpdate();
|
||||
@@ -872,7 +887,10 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
updateHtml(body = null) {
|
||||
updateHtml(body = null, options = null) {
|
||||
if (!options) options = {};
|
||||
if (!('useCustomCss' in options)) options.useCustomCss = true;
|
||||
|
||||
const mdOptions = {
|
||||
onResourceLoaded: () => {
|
||||
if (this.resourceLoadedTimeoutId_) {
|
||||
@@ -893,7 +911,6 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
let bodyToRender = body;
|
||||
if (bodyToRender === null) bodyToRender = this.state.note && this.state.note.body ? this.state.note.body : '';
|
||||
bodyToRender = '<style>' + this.props.customCss + '</style>\n' + bodyToRender;
|
||||
let bodyHtml = '';
|
||||
|
||||
const visiblePanes = this.props.visiblePanes || ['editor', 'viewer'];
|
||||
@@ -903,11 +920,35 @@ class NoteTextComponent extends React.Component {
|
||||
bodyToRender = '*' + _('This note has no content. Click on "%s" to toggle the editor and edit the note.', _('Layout')) + '*';
|
||||
}
|
||||
|
||||
if (options.useCustomCss) bodyToRender = '<style>' + this.props.customCss + '</style>\n' + bodyToRender;
|
||||
|
||||
bodyHtml = this.mdToHtml().render(bodyToRender, theme, mdOptions);
|
||||
|
||||
this.setState({ bodyHtml: bodyHtml });
|
||||
}
|
||||
|
||||
titleField_keyDown(event) {
|
||||
const keyCode = event.keyCode;
|
||||
|
||||
if (keyCode === 9) { // TAB
|
||||
event.preventDefault();
|
||||
|
||||
if (event.shiftKey) {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'focusElement',
|
||||
target: 'noteList',
|
||||
});
|
||||
} else {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'focusElement',
|
||||
target: 'noteBody',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async doCommand(command) {
|
||||
if (!command) return;
|
||||
|
||||
@@ -924,7 +965,9 @@ class NoteTextComponent extends React.Component {
|
||||
fn = this.commandTextBold;
|
||||
} else if (command.name === 'textItalic') {
|
||||
fn = this.commandTextItalic;
|
||||
} else if (command.name === 'insertDateTime' ) {
|
||||
} else if (command.name === 'textLink') {
|
||||
fn = this.commandTextLink;
|
||||
} else if (command.name === 'insertDateTime') {
|
||||
fn = this.commandDateTime;
|
||||
} else if (command.name === 'commandStartExternalEditing') {
|
||||
fn = this.commandStartExternalEditing;
|
||||
@@ -933,6 +976,20 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (command.name === 'focusElement' && command.target === 'noteTitle') {
|
||||
fn = () => {
|
||||
if (!this.titleField_) return;
|
||||
this.titleField_.focus();
|
||||
}
|
||||
}
|
||||
|
||||
if (command.name === 'focusElement' && command.target === 'noteBody') {
|
||||
fn = () => {
|
||||
if (!this.editor_) return;
|
||||
this.editor_.editor.focus();
|
||||
}
|
||||
}
|
||||
|
||||
if (!fn) return;
|
||||
|
||||
this.props.dispatch({
|
||||
@@ -1002,7 +1059,7 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
printTo_(target, options) {
|
||||
if (this.props.selectedNoteIds.length !== 1 || !this.webview_) {
|
||||
if (this.props.selectedNoteIds.length !== 1 || !this.webviewRef_.current) {
|
||||
throw new Error(_('Only one note can be printed or exported to PDF at a time.'));
|
||||
}
|
||||
|
||||
@@ -1012,7 +1069,7 @@ class NoteTextComponent extends React.Component {
|
||||
const previousTheme = Setting.value('theme');
|
||||
Setting.setValue('theme', Setting.THEME_LIGHT);
|
||||
this.lastSetHtml_ = '';
|
||||
this.updateHtml(tempBody);
|
||||
this.updateHtml(tempBody, { useCustomCss: false });
|
||||
this.forceUpdate();
|
||||
|
||||
const restoreSettings = () => {
|
||||
@@ -1024,7 +1081,7 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
setTimeout(() => {
|
||||
if (target === 'pdf') {
|
||||
this.webview_.printToPDF({}, (error, data) => {
|
||||
this.webviewRef_.current.wrappedInstance.printToPDF({}, (error, data) => {
|
||||
restoreSettings();
|
||||
|
||||
if (error) {
|
||||
@@ -1034,7 +1091,7 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
});
|
||||
} else if (target === 'printer') {
|
||||
this.webview_.print();
|
||||
this.webviewRef_.current.wrappedInstance.print();
|
||||
restoreSettings();
|
||||
}
|
||||
}, 100);
|
||||
@@ -1318,6 +1375,25 @@ class NoteTextComponent extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.props.historyNotes.length) {
|
||||
toolbarItems.push({
|
||||
tooltip: _('Back'),
|
||||
iconName: 'fa-arrow-left',
|
||||
onClick: () => {
|
||||
if (!this.props.historyNotes.length) return;
|
||||
|
||||
const lastItem = this.props.historyNotes[this.props.historyNotes.length - 1];
|
||||
|
||||
this.props.dispatch({
|
||||
type: "FOLDER_AND_NOTE_SELECT",
|
||||
folderId: lastItem.parent_id,
|
||||
noteId: lastItem.id,
|
||||
historyNoteAction: 'pop',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
toolbarItems.push({
|
||||
tooltip: _('Bold'),
|
||||
iconName: 'fa-bold',
|
||||
@@ -1453,6 +1529,61 @@ class NoteTextComponent extends React.Component {
|
||||
return toolbarItems;
|
||||
}
|
||||
|
||||
renderNoNotes(rootStyle) {
|
||||
const emptyDivStyle = Object.assign({
|
||||
backgroundColor: 'black',
|
||||
opacity: 0.1,
|
||||
}, rootStyle);
|
||||
return <div style={emptyDivStyle}></div>
|
||||
}
|
||||
|
||||
renderMultiNotes(rootStyle) {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
const multiNotesButton_click = item => {
|
||||
if (item.submenu) {
|
||||
item.submenu.popup(bridge().window());
|
||||
} else {
|
||||
item.click();
|
||||
}
|
||||
}
|
||||
|
||||
const menu = NoteListUtils.makeContextMenu(this.props.selectedNoteIds, {
|
||||
notes: this.props.notes,
|
||||
dispatch: this.props.dispatch,
|
||||
});
|
||||
|
||||
const buttonStyle = Object.assign({}, theme.buttonStyle, {
|
||||
marginBottom: 10,
|
||||
});
|
||||
|
||||
const itemComps = [];
|
||||
const menuItems = menu.items;
|
||||
|
||||
for (let i = 0; i < menuItems.length; i++) {
|
||||
const item = menuItems[i];
|
||||
if (!item.enabled) continue;
|
||||
|
||||
itemComps.push(<button
|
||||
key={item.label}
|
||||
style={buttonStyle}
|
||||
onClick={() => multiNotesButton_click(item)}
|
||||
>{item.label}</button>);
|
||||
}
|
||||
|
||||
rootStyle = Object.assign({}, rootStyle, {
|
||||
paddingTop: rootStyle.paddingLeft,
|
||||
display: 'inline-flex',
|
||||
justifyContent: 'center',
|
||||
});
|
||||
|
||||
return (<div style={rootStyle}>
|
||||
<div style={{display: 'flex', flexDirection: 'column'}}>
|
||||
{itemComps}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
render() {
|
||||
const style = this.props.style;
|
||||
const note = this.state.note;
|
||||
@@ -1472,12 +1603,10 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
const innerWidth = rootStyle.width - rootStyle.paddingLeft - rootStyle.paddingRight - borderWidth;
|
||||
|
||||
if (!note || !!note.encryption_applied) {
|
||||
const emptyDivStyle = Object.assign({
|
||||
backgroundColor: 'black',
|
||||
opacity: 0.1,
|
||||
}, rootStyle);
|
||||
return <div style={emptyDivStyle}></div>
|
||||
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
|
||||
return this.renderNoNotes(rootStyle);
|
||||
}
|
||||
|
||||
const titleBarStyle = {
|
||||
@@ -1580,7 +1709,7 @@ class NoteTextComponent extends React.Component {
|
||||
const htmlHasChanged = this.lastSetHtml_ !== html;
|
||||
if (htmlHasChanged) {
|
||||
let options = {codeTheme: theme.codeThemeCss};
|
||||
this.webview_.send('setHtml', html, options);
|
||||
this.webviewRef_.current.wrappedInstance.send('setHtml', html, options);
|
||||
this.lastSetHtml_ = html;
|
||||
}
|
||||
|
||||
@@ -1606,7 +1735,7 @@ class NoteTextComponent extends React.Component {
|
||||
if (htmlHasChanged || keywordHash !== this.lastSetMarkers_ || !ObjectUtils.fieldsEqual(this.lastSetMarkersOptions_, markerOptions)) {
|
||||
this.lastSetMarkers_ = keywordHash;
|
||||
this.lastSetMarkersOptions_ = Object.assign({}, markerOptions);
|
||||
this.webview_.send('setMarkers', keywords, markerOptions);
|
||||
this.webviewRef_.current.wrappedInstance.send('setMarkers', keywords, markerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1623,6 +1752,7 @@ class NoteTextComponent extends React.Component {
|
||||
style={titleEditorStyle}
|
||||
value={note && note.title ? note.title : ''}
|
||||
onChange={(event) => { this.title_changeText(event); }}
|
||||
onKeyDown={this.titleField_keyDown}
|
||||
placeholder={ this.props.newNote ? _('Creating new %s...', isTodo ? _('to-do') : _('note')) : '' }
|
||||
/>
|
||||
|
||||
@@ -1637,32 +1767,13 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
const titleBarDate = <span style={Object.assign({}, theme.textStyle, {color: theme.colorFaded})}>{time.formatMsToLocal(note.user_updated_time)}</span>
|
||||
|
||||
const viewer = <webview
|
||||
style={viewerStyle}
|
||||
preload="gui/note-viewer/preload.js"
|
||||
src="gui/note-viewer/index.html"
|
||||
webpreferences="contextIsolation"
|
||||
ref={(elem) => { this.webview_ref(elem); } }
|
||||
const viewer = <NoteTextViewer
|
||||
ref={this.webviewRef_}
|
||||
viewerStyle={viewerStyle}
|
||||
onDomReady={this.webview_domReady}
|
||||
onIpcMessage={this.webview_ipcMessage}
|
||||
/>
|
||||
|
||||
// const markers = [{
|
||||
// startRow: 2,
|
||||
// startCol: 3,
|
||||
// endRow: 2,
|
||||
// endCol: 6,
|
||||
// type: 'text',
|
||||
// className: 'test-marker'
|
||||
// }];
|
||||
|
||||
// markers={markers}
|
||||
// editorProps={{$useWorker: false}}
|
||||
|
||||
// #note-editor .test-marker {
|
||||
// background-color: red;
|
||||
// color: yellow;
|
||||
// position: absolute;
|
||||
// }
|
||||
|
||||
const editorRootStyle = Object.assign({}, editorStyle);
|
||||
delete editorRootStyle.width;
|
||||
delete editorRootStyle.height;
|
||||
@@ -1684,6 +1795,7 @@ class NoteTextComponent extends React.Component {
|
||||
showPrintMargin={false}
|
||||
onSelectionChange={this.aceEditor_selectionChange}
|
||||
onFocus={this.aceEditor_focus}
|
||||
readOnly={visiblePanes.indexOf('editor') < 0}
|
||||
|
||||
// Disable warning: "Automatically scrolling cursor into view after
|
||||
// selection change this will be disabled in the next version set
|
||||
@@ -1727,6 +1839,7 @@ class NoteTextComponent extends React.Component {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
noteId: state.selectedNoteIds.length === 1 ? state.selectedNoteIds[0] : null,
|
||||
notes: state.notes,
|
||||
selectedNoteIds: state.selectedNoteIds,
|
||||
noteTags: state.selectedNoteTags,
|
||||
folderId: state.selectedFolderId,
|
||||
@@ -1742,6 +1855,8 @@ const mapStateToProps = (state) => {
|
||||
selectedSearchId: state.selectedSearchId,
|
||||
watchedNoteFiles: state.watchedNoteFiles,
|
||||
customCss: state.customCss,
|
||||
lastEditorScrollPercents: state.lastEditorScrollPercents,
|
||||
historyNotes: state.historyNotes,
|
||||
};
|
||||
};
|
||||
|
||||
|
99
ElectronClient/app/gui/NoteTextViewer.jsx
Normal file
99
ElectronClient/app/gui/NoteTextViewer.jsx
Normal file
@@ -0,0 +1,99 @@
|
||||
const React = require('react');
|
||||
const { connect } = require('react-redux');
|
||||
const { themeStyle } = require('../theme.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
class NoteTextViewerComponent extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.initialized_ = false;
|
||||
|
||||
this.webviewRef_ = React.createRef();
|
||||
this.webviewListeners_ = null;
|
||||
|
||||
this.webview_domReady = this.webview_domReady.bind(this);
|
||||
this.webview_ipcMessage = this.webview_ipcMessage.bind(this);
|
||||
}
|
||||
|
||||
webview_domReady(event) {
|
||||
this.props.onDomReady(event);
|
||||
}
|
||||
|
||||
webview_ipcMessage(event) {
|
||||
this.props.onIpcMessage(event);
|
||||
}
|
||||
|
||||
initWebview() {
|
||||
const wv = this.webviewRef_.current;
|
||||
|
||||
if (!this.webviewListeners_) {
|
||||
this.webviewListeners_ = {
|
||||
'dom-ready': this.webview_domReady.bind(this),
|
||||
'ipc-message': this.webview_ipcMessage.bind(this),
|
||||
};
|
||||
}
|
||||
|
||||
for (let n in this.webviewListeners_) {
|
||||
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
||||
const fn = this.webviewListeners_[n];
|
||||
wv.addEventListener(n, fn);
|
||||
}
|
||||
}
|
||||
|
||||
destroyWebview() {
|
||||
const wv = this.webviewRef_.current;
|
||||
if (!wv || !this.initialized_) return;
|
||||
|
||||
for (let n in this.webviewListeners_) {
|
||||
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
||||
const fn = this.webviewListeners_[n];
|
||||
wv.removeEventListener(n, fn);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (!this.initialized_ && this.webviewRef_.current) {
|
||||
this.initWebview();
|
||||
this.initialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.destroyWebview();
|
||||
}
|
||||
|
||||
send(channel, arg0 = null, arg1 = null, arg2 = null, arg3 = null) {
|
||||
return this.webviewRef_.current.send(channel, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
printToPDF(options, callback) {
|
||||
return this.webviewRef_.current.printToPDF(options, callback);
|
||||
}
|
||||
|
||||
print(options = {}) {
|
||||
return this.webviewRef_.current.print(options);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <webview
|
||||
ref={this.webviewRef_}
|
||||
style={this.props.viewerStyle}
|
||||
preload="gui/note-viewer/preload.js"
|
||||
src="gui/note-viewer/index.html"
|
||||
webpreferences="contextIsolation"
|
||||
/>
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
theme: state.settings.theme,
|
||||
};
|
||||
};
|
||||
|
||||
const NoteTextViewer = connect(mapStateToProps, null, null, { withRef: true })(NoteTextViewerComponent);
|
||||
|
||||
module.exports = NoteTextViewer;
|
@@ -15,6 +15,7 @@ const { ConfigScreen } = require('./ConfigScreen.min.js');
|
||||
const { EncryptionConfigScreen } = require('./EncryptionConfigScreen.min.js');
|
||||
const { ClipperConfigScreen } = require('./ClipperConfigScreen.min.js');
|
||||
const { Navigator } = require('./Navigator.min.js');
|
||||
const WelcomeUtils = require('lib/WelcomeUtils');
|
||||
|
||||
const { app } = require('../app');
|
||||
|
||||
@@ -71,6 +72,8 @@ class RootComponent extends React.Component {
|
||||
state: 'ready',
|
||||
});
|
||||
}
|
||||
|
||||
await WelcomeUtils.install(this.props.dispatch);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@@ -40,9 +40,15 @@ class SideBarComponent extends React.Component {
|
||||
const dt = event.dataTransfer;
|
||||
if (!dt) return;
|
||||
|
||||
// folderId can be NULL when dropping on the sidebar Notebook header. In that case, it's used
|
||||
// to put the dropped folder at the root. But for notes, folderId needs to always be defined
|
||||
// since there's no such thing as a root note.
|
||||
|
||||
if (dt.types.indexOf("text/x-jop-note-ids") >= 0) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!folderId) return;
|
||||
|
||||
const noteIds = JSON.parse(dt.getData("text/x-jop-note-ids"));
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
await Note.moveToFolder(noteIds[i], folderId);
|
||||
@@ -81,6 +87,15 @@ class SideBarComponent extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
this.folderItemsOrder_ = [];
|
||||
this.tagItemsOrder_ = [];
|
||||
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
|
||||
this.rootRef = React.createRef();
|
||||
|
||||
this.anchorItemRefs = {};
|
||||
|
||||
this.state = {
|
||||
tagHeaderIsExpanded: Setting.value('tagHeaderIsExpanded'),
|
||||
folderHeaderIsExpanded: Setting.value('folderHeaderIsExpanded')
|
||||
@@ -172,9 +187,8 @@ class SideBarComponent extends React.Component {
|
||||
marginTop: 10,
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
minHeight: 70,
|
||||
marginBottom: 10,
|
||||
wordWrap: "break-word",
|
||||
//width: "100%",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -192,6 +206,31 @@ class SideBarComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
doCommand(command) {
|
||||
if (!command) return;
|
||||
|
||||
let commandProcessed = true;
|
||||
|
||||
if (command.name === 'focusElement' && command.target === 'sideBar') {
|
||||
if (this.props.sidebarVisibility) {
|
||||
const item = this.selectedItem();
|
||||
if (item) {
|
||||
const anchorRef = this.anchorItemRefs[item.type][item.id];
|
||||
if (anchorRef) anchorRef.current.focus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
commandProcessed = false;
|
||||
}
|
||||
|
||||
if (commandProcessed) {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (shim.isLinux()) {
|
||||
// For some reason, the UI seems to sleep in some Linux distro during
|
||||
@@ -214,6 +253,12 @@ class SideBarComponent extends React.Component {
|
||||
this.clearForceUpdateDuringSync();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (prevProps.windowCommand !== this.props.windowCommand) {
|
||||
this.doCommand(this.props.windowCommand);
|
||||
}
|
||||
}
|
||||
|
||||
itemContextMenu(event) {
|
||||
const itemId = event.target.getAttribute("data-id");
|
||||
if (itemId === Folder.conflictFolderId()) return;
|
||||
@@ -341,17 +386,26 @@ class SideBarComponent extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
searchItem_click(search) {
|
||||
this.props.dispatch({
|
||||
type: "SEARCH_SELECT",
|
||||
id: search ? search.id : null,
|
||||
});
|
||||
}
|
||||
// searchItem_click(search) {
|
||||
// this.props.dispatch({
|
||||
// type: "SEARCH_SELECT",
|
||||
// id: search ? search.id : null,
|
||||
// });
|
||||
// }
|
||||
|
||||
async sync_click() {
|
||||
await shared.synchronize_press(this);
|
||||
}
|
||||
|
||||
anchorItemRef(type, id) {
|
||||
let refs = null;
|
||||
|
||||
if (!this.anchorItemRefs[type]) this.anchorItemRefs[type] = {};
|
||||
if (this.anchorItemRefs[type][id]) return this.anchorItemRefs[type][id];
|
||||
this.anchorItemRefs[type][id] = React.createRef();
|
||||
return this.anchorItemRefs[type][id];
|
||||
}
|
||||
|
||||
folderItem(folder, selected, hasChildren, depth) {
|
||||
let style = Object.assign({}, this.style().listItem);
|
||||
if (folder.id === Folder.conflictFolderId()) style = Object.assign(style, this.style().conflictFolder);
|
||||
@@ -359,8 +413,6 @@ class SideBarComponent extends React.Component {
|
||||
const itemTitle = Folder.displayTitle(folder);
|
||||
|
||||
let containerStyle = Object.assign({}, this.style().listItemContainer);
|
||||
// containerStyle.paddingLeft = containerStyle.paddingLeft + depth * 10;
|
||||
|
||||
if (selected) containerStyle = Object.assign(containerStyle, this.style().listItemSelected);
|
||||
|
||||
let expandLinkStyle = Object.assign({}, this.style().listItemExpandIcon);
|
||||
@@ -373,10 +425,13 @@ class SideBarComponent extends React.Component {
|
||||
const expandIcon = <i style={expandIconStyle} className={"fa " + iconName}></i>
|
||||
const expandLink = hasChildren ? <a style={expandLinkStyle} href="#" folderid={folder.id} onClick={this.onFolderToggleClick_}>{expandIcon}</a> : <span style={expandLinkStyle}>{expandIcon}</span>
|
||||
|
||||
const anchorRef = this.anchorItemRef('folder', folder.id);
|
||||
|
||||
return (
|
||||
<div className="list-item-container" style={containerStyle} key={folder.id} onDragStart={this.onFolderDragStart_} onDragOver={this.onFolderDragOver_} onDrop={this.onFolderDrop_} draggable={true} folderid={folder.id}>
|
||||
{ expandLink }
|
||||
<a
|
||||
ref={anchorRef}
|
||||
className="list-item"
|
||||
href="#"
|
||||
data-id={folder.id}
|
||||
@@ -398,10 +453,14 @@ class SideBarComponent extends React.Component {
|
||||
tagItem(tag, selected) {
|
||||
let style = Object.assign({}, this.style().tagItem);
|
||||
if (selected) style = Object.assign(style, this.style().listItemSelected);
|
||||
|
||||
const anchorRef = this.anchorItemRef('tag', tag.id);
|
||||
|
||||
return (
|
||||
<a
|
||||
className="list-item"
|
||||
href="#"
|
||||
ref={anchorRef}
|
||||
data-id={tag.id}
|
||||
data-type={BaseModel.TYPE_TAG}
|
||||
onContextMenu={event => this.itemContextMenu(event)}
|
||||
@@ -418,26 +477,26 @@ class SideBarComponent extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
searchItem(search, selected) {
|
||||
let style = Object.assign({}, this.style().listItem);
|
||||
if (selected) style = Object.assign(style, this.style().listItemSelected);
|
||||
return (
|
||||
<a
|
||||
className="list-item"
|
||||
href="#"
|
||||
data-id={search.id}
|
||||
data-type={BaseModel.TYPE_SEARCH}
|
||||
onContextMenu={event => this.itemContextMenu(event)}
|
||||
key={search.id}
|
||||
style={style}
|
||||
onClick={() => {
|
||||
this.searchItem_click(search);
|
||||
}}
|
||||
>
|
||||
{search.title}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
// searchItem(search, selected) {
|
||||
// let style = Object.assign({}, this.style().listItem);
|
||||
// if (selected) style = Object.assign(style, this.style().listItemSelected);
|
||||
// return (
|
||||
// <a
|
||||
// className="list-item"
|
||||
// href="#"
|
||||
// data-id={search.id}
|
||||
// data-type={BaseModel.TYPE_SEARCH}
|
||||
// onContextMenu={event => this.itemContextMenu(event)}
|
||||
// key={search.id}
|
||||
// style={style}
|
||||
// onClick={() => {
|
||||
// this.searchItem_click(search);
|
||||
// }}
|
||||
// >
|
||||
// {search.title}
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
|
||||
makeDivider(key) {
|
||||
return <div style={{ height: 2, backgroundColor: "blue" }} key={key} />;
|
||||
@@ -462,8 +521,11 @@ class SideBarComponent extends React.Component {
|
||||
toggleIcon = <i className={`fa ${isExpanded ? 'fa-chevron-down' : 'fa-chevron-left'}`} style={{ fontSize: style.fontSize * 0.75,
|
||||
marginRight: 12, marginLeft: 5, marginTop: style.fontSize * 0.125}}></i>;
|
||||
}
|
||||
|
||||
const ref = this.anchorItemRef('headers', key);
|
||||
|
||||
return (
|
||||
<div style={style} key={key} {...extraProps} onClick={(event) => {
|
||||
<div ref={ref} style={style} key={key} {...extraProps} onClick={(event) => {
|
||||
// if a custom click event is attached, trigger that.
|
||||
if (headerClick) {
|
||||
headerClick(key, event);
|
||||
@@ -477,6 +539,91 @@ class SideBarComponent extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
selectedItem() {
|
||||
if (this.props.notesParentType === 'Folder' && this.props.selectedFolderId) {
|
||||
return { type: 'folder', id: this.props.selectedFolderId };
|
||||
} else if (this.props.notesParentType === 'Tag' && this.props.selectedTagId) {
|
||||
return { type: 'tag', id: this.props.selectedTagId };
|
||||
} else if (this.props.notesParentType === 'Search' && this.props.selectedSearchId) {
|
||||
return { type: 'search', id: this.props.selectedSearchId };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
onKeyDown(event) {
|
||||
const keyCode = event.keyCode;
|
||||
const selectedItem = this.selectedItem();
|
||||
|
||||
if (keyCode === 40 || keyCode === 38) { // DOWN / UP
|
||||
event.preventDefault();
|
||||
|
||||
const focusItems = [];
|
||||
|
||||
for (let i = 0; i < this.folderItemsOrder_.length; i++) {
|
||||
const id = this.folderItemsOrder_[i];
|
||||
focusItems.push({ id: id, ref: this.anchorItemRefs['folder'][id], type: 'folder' });
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.tagItemsOrder_.length; i++) {
|
||||
const id = this.tagItemsOrder_[i];
|
||||
focusItems.push({ id: id, ref: this.anchorItemRefs['tag'][id], type: 'tag' });
|
||||
}
|
||||
|
||||
let currentIndex = 0;
|
||||
for (let i = 0; i < focusItems.length; i++) {
|
||||
if (!selectedItem || focusItems[i].id === selectedItem.id) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const inc = keyCode === 38 ? -1 : +1;
|
||||
let newIndex = currentIndex + inc;
|
||||
|
||||
if (newIndex < 0) newIndex = 0;
|
||||
if (newIndex > focusItems.length - 1) newIndex = focusItems.length - 1;
|
||||
|
||||
const focusItem = focusItems[newIndex];
|
||||
|
||||
let actionName = focusItem.type.toUpperCase() + '_SELECT';
|
||||
|
||||
this.props.dispatch({
|
||||
type: actionName,
|
||||
id: focusItem.id,
|
||||
});
|
||||
|
||||
focusItem.ref.current.focus();
|
||||
}
|
||||
|
||||
if (keyCode === 9) { // TAB
|
||||
event.preventDefault();
|
||||
|
||||
if (event.shiftKey) {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'focusElement',
|
||||
target: 'noteBody',
|
||||
});
|
||||
} else {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'focusElement',
|
||||
target: 'noteList',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedItem && selectedItem.type === 'folder' && keyCode === 32) { // SPACE
|
||||
event.preventDefault();
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'FOLDER_TOGGLE',
|
||||
id: selectedItem.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onHeaderClick_(key, event) {
|
||||
const currentHeader = event.currentTarget;
|
||||
const toggleBlock = +currentHeader.getAttribute('toggleblock');
|
||||
@@ -489,7 +636,7 @@ class SideBarComponent extends React.Component {
|
||||
}
|
||||
|
||||
synchronizeButton(type) {
|
||||
const style = this.style().button;
|
||||
const style = Object.assign({}, this.style().button, { marginBottom: 5 });
|
||||
const iconName = type === "sync" ? "fa-refresh" : "fa-times";
|
||||
const label = type === "sync" ? _("Synchronise") : _("Cancel");
|
||||
const icon = <i style={{ fontSize: style.fontSize, marginRight: 5 }} className={"fa " + iconName} />;
|
||||
@@ -513,7 +660,9 @@ class SideBarComponent extends React.Component {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const style = Object.assign({}, this.style().root, this.props.style, {
|
||||
overflowX: "hidden",
|
||||
overflowY: "auto",
|
||||
overflowY: "hidden",
|
||||
display: 'inline-flex',
|
||||
flexDirection: 'column',
|
||||
});
|
||||
|
||||
let items = [];
|
||||
@@ -524,7 +673,9 @@ class SideBarComponent extends React.Component {
|
||||
}));
|
||||
|
||||
if (this.props.folders.length) {
|
||||
const folderItems = shared.renderFolders(this.props, this.folderItem.bind(this));
|
||||
const result = shared.renderFolders(this.props, this.folderItem.bind(this));
|
||||
const folderItems = result.items;
|
||||
this.folderItemsOrder_ = result.order;
|
||||
items.push(<div className="folders" key="folder_items" style={{display: this.state.folderHeaderIsExpanded ? 'block': 'none'}}>
|
||||
{folderItems}</div>);
|
||||
}
|
||||
@@ -534,7 +685,9 @@ class SideBarComponent extends React.Component {
|
||||
}));
|
||||
|
||||
if (this.props.tags.length) {
|
||||
const tagItems = shared.renderTags(this.props, this.tagItem.bind(this));
|
||||
const result = shared.renderTags(this.props, this.tagItem.bind(this));
|
||||
const tagItems = result.items;
|
||||
this.tagItemsOrder_ = result.order;
|
||||
|
||||
items.push(
|
||||
<div className="tags" key="tag_items" style={{display: this.state.tagHeaderIsExpanded ? 'block': 'none'}}>
|
||||
@@ -565,17 +718,23 @@ class SideBarComponent extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
items.push(this.synchronizeButton(this.props.syncStarted ? "cancel" : "sync"));
|
||||
const syncButton = this.synchronizeButton(this.props.syncStarted ? "cancel" : "sync");
|
||||
|
||||
items.push(
|
||||
const syncReportComp = !syncReportText.length ? null : (
|
||||
<div style={this.style().syncReport} key="sync_report">
|
||||
{syncReportText}
|
||||
</div>
|
||||
);
|
||||
{syncReportText}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="side-bar" style={style}>
|
||||
{items}
|
||||
<div ref={this.rootRef} onKeyDown={this.onKeyDown} className="side-bar" style={style}>
|
||||
<div style={{flex:1, overflowY: 'auto'}}>
|
||||
{items}
|
||||
</div>
|
||||
<div style={{flex:0}}>
|
||||
{syncButton}
|
||||
{syncReportComp}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -597,6 +756,8 @@ const mapStateToProps = state => {
|
||||
collapsedFolderIds: state.collapsedFolderIds,
|
||||
decryptionWorker: state.decryptionWorker,
|
||||
resourceFetcher: state.resourceFetcher,
|
||||
windowCommand: state.windowCommand,
|
||||
sidebarVisibility: state.sidebarVisibility,
|
||||
};
|
||||
};
|
||||
|
||||
|
137
ElectronClient/app/gui/utils/NoteListUtils.js
Normal file
137
ElectronClient/app/gui/utils/NoteListUtils.js
Normal file
@@ -0,0 +1,137 @@
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const BaseModel = require('lib/BaseModel');
|
||||
const markJsUtils = require('lib/markJsUtils');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
const Menu = bridge().Menu;
|
||||
const MenuItem = bridge().MenuItem;
|
||||
const eventManager = require('../../eventManager');
|
||||
const InteropService = require('lib/services/InteropService');
|
||||
const InteropServiceHelper = require('../../InteropServiceHelper.js');
|
||||
const Search = require('lib/models/Search');
|
||||
const Note = require('lib/models/Note');
|
||||
const SearchEngine = require('lib/services/SearchEngine');
|
||||
const { replaceRegexDiacritics, pregQuote, substrWithEllipsis } = require('lib/string-utils');
|
||||
|
||||
class NoteListUtils {
|
||||
|
||||
static makeContextMenu(noteIds, props) {
|
||||
const notes = noteIds.map((id) => BaseModel.byId(props.notes, id));
|
||||
|
||||
let hasEncrypted = false;
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
if (!!notes[i].encryption_applied) hasEncrypted = true;
|
||||
}
|
||||
|
||||
const menu = new Menu()
|
||||
|
||||
if (!hasEncrypted) {
|
||||
menu.append(new MenuItem({label: _('Add or remove tags'), enabled: noteIds.length === 1, click: async () => {
|
||||
props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'setTags',
|
||||
noteId: noteIds[0],
|
||||
});
|
||||
}}));
|
||||
|
||||
menu.append(new MenuItem({label: _('Duplicate'), click: async () => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
await Note.duplicate(noteIds[i], {
|
||||
uniqueTitle: _('%s - Copy', note.title),
|
||||
});
|
||||
}
|
||||
}}));
|
||||
|
||||
if (noteIds.length <= 1) {
|
||||
menu.append(new MenuItem({label: _('Switch between note and to-do type'), click: async () => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
await Note.save(Note.toggleIsTodo(note), { userSideValidation: true });
|
||||
eventManager.emit('noteTypeToggle', { noteId: note.id });
|
||||
}
|
||||
}}));
|
||||
} else {
|
||||
const switchNoteType = async (noteIds, type) => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
const newNote = Note.changeNoteType(note, type);
|
||||
if (newNote === note) continue;
|
||||
await Note.save(newNote, { userSideValidation: true });
|
||||
eventManager.emit('noteTypeToggle', { noteId: note.id });
|
||||
}
|
||||
}
|
||||
|
||||
menu.append(new MenuItem({label: _('Switch to note type'), click: async () => {
|
||||
await switchNoteType(noteIds, 'note');
|
||||
}}));
|
||||
|
||||
menu.append(new MenuItem({label: _('Switch to to-do type'), click: async () => {
|
||||
await switchNoteType(noteIds, 'todo');
|
||||
}}));
|
||||
}
|
||||
|
||||
menu.append(new MenuItem({label: _('Copy Markdown link'), click: async () => {
|
||||
const { clipboard } = require('electron');
|
||||
const links = [];
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
links.push(Note.markdownTag(note));
|
||||
}
|
||||
clipboard.writeText(links.join(' '));
|
||||
}}));
|
||||
|
||||
const exportMenu = new Menu();
|
||||
|
||||
const ioService = new InteropService();
|
||||
const ioModules = ioService.modules();
|
||||
for (let i = 0; i < ioModules.length; i++) {
|
||||
const module = ioModules[i];
|
||||
if (module.type !== 'exporter') continue;
|
||||
|
||||
exportMenu.append(new MenuItem({ label: module.fullLabel() , click: async () => {
|
||||
await InteropServiceHelper.export(props.dispatch.bind(this), module, { sourceNoteIds: noteIds });
|
||||
}}));
|
||||
}
|
||||
|
||||
if (noteIds.length === 1) {
|
||||
exportMenu.append(new MenuItem({ label: 'PDF - ' + _('PDF File') , click: () => {
|
||||
props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'exportPdf',
|
||||
});
|
||||
}}));
|
||||
}
|
||||
|
||||
const exportMenuItem = new MenuItem({label: _('Export'), submenu: exportMenu});
|
||||
|
||||
menu.append(exportMenuItem);
|
||||
}
|
||||
|
||||
menu.append(new MenuItem({label: _('Delete'), click: async () => {
|
||||
await this.confirmDeleteNotes(noteIds);
|
||||
}}));
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
static async confirmDeleteNotes(noteIds) {
|
||||
if (!noteIds.length) return;
|
||||
|
||||
let msg = '';
|
||||
if (noteIds.length === 1) {
|
||||
const note = await Note.load(noteIds[0]);
|
||||
if (!note) return;
|
||||
msg = _('Delete note "%s"?', substrWithEllipsis(note.title, 0, 32));
|
||||
} else {
|
||||
msg = _('Delete these %d notes?', noteIds.length);
|
||||
}
|
||||
|
||||
const ok = bridge().showConfirmMessageBox(msg);
|
||||
if (!ok) return;
|
||||
await Note.batchDelete(noteIds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = NoteListUtils;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
50
ElectronClient/app/package-lock.json
generated
50
ElectronClient/app/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.0.124",
|
||||
"version": "1.0.126",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -59,16 +59,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz",
|
||||
"integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg=="
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz",
|
||||
"integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.0.tgz",
|
||||
"integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg=="
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz",
|
||||
"integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.5.0",
|
||||
@@ -1720,12 +1720,12 @@
|
||||
}
|
||||
},
|
||||
"data-urls": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz",
|
||||
"integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
|
||||
"integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
|
||||
"requires": {
|
||||
"abab": "^2.0.0",
|
||||
"whatwg-mimetype": "^2.1.0",
|
||||
"whatwg-mimetype": "^2.2.0",
|
||||
"whatwg-url": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -3992,9 +3992,9 @@
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"joplin-turndown": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.9.tgz",
|
||||
"integrity": "sha512-8MOxX4t5Ai22muHhXPMGNoKc/AB7gSo0eUvNh6dyd6b3vcSiMIRZE8UHpMjS9ruJQ+8e+8TtJXc0nfbexeHwrA==",
|
||||
"version": "4.0.11",
|
||||
"resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.11.tgz",
|
||||
"integrity": "sha512-2oiwWX0nKYi1NVcaprSsrXQkYdGoRtPWFmnXdWQnQW44jlgjFV38B4VrgliwX5ZMq7cbx6A9IBwfXcBL2YV2NA==",
|
||||
"requires": {
|
||||
"jsdom": "^11.9.0"
|
||||
}
|
||||
@@ -4594,7 +4594,7 @@
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
||||
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA=="
|
||||
},
|
||||
"nanomatch": {
|
||||
@@ -6651,17 +6651,17 @@
|
||||
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
|
||||
},
|
||||
"whatwg-encoding": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz",
|
||||
"integrity": "sha512-vM9KWN6MP2mIHZ86ytcyIv7e8Cj3KTfO2nd2c8PFDqcI4bxFmQp83ibq4wadq7rL9l9sZV6o9B0LTt8ygGAAXg==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
|
||||
"integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
|
||||
"requires": {
|
||||
"iconv-lite": "0.4.23"
|
||||
"iconv-lite": "0.4.24"
|
||||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
|
||||
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
@@ -6674,9 +6674,9 @@
|
||||
"integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
|
||||
},
|
||||
"whatwg-mimetype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz",
|
||||
"integrity": "sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw=="
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
|
||||
"integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "6.5.0",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.0.124",
|
||||
"version": "1.0.126",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@@ -96,7 +96,7 @@
|
||||
"highlight.js": "^9.12.0",
|
||||
"html-entities": "^1.2.1",
|
||||
"image-type": "^3.0.0",
|
||||
"joplin-turndown": "^4.0.9",
|
||||
"joplin-turndown": "^4.0.11",
|
||||
"joplin-turndown-plugin-gfm": "^1.0.7",
|
||||
"jssha": "^2.3.1",
|
||||
"katex": "^0.10.0",
|
||||
|
@@ -36,7 +36,9 @@ globalStyle.lineInput = {
|
||||
fontFamily: globalStyle.fontFamily,
|
||||
};
|
||||
|
||||
globalStyle.headerStyle = {};
|
||||
globalStyle.headerStyle = {
|
||||
fontFamily: globalStyle.fontFamily,
|
||||
};
|
||||
|
||||
globalStyle.inputStyle = {
|
||||
border: '1px solid',
|
||||
@@ -50,6 +52,11 @@ globalStyle.containerStyle = {
|
||||
globalStyle.buttonStyle = {
|
||||
marginRight: 10,
|
||||
border: '1px solid',
|
||||
minHeight: 30,
|
||||
minWidth: 80,
|
||||
maxWidth: 160,
|
||||
paddingLeft: 12,
|
||||
paddingRight: 12,
|
||||
};
|
||||
|
||||
const lightStyle = {
|
||||
@@ -74,15 +81,14 @@ const lightStyle = {
|
||||
|
||||
warningBackgroundColor: "#FFD08D",
|
||||
|
||||
codeColor: "#EFF0F1",
|
||||
codeBorderColor: '#CBCBCB',
|
||||
|
||||
htmlColor:'black', // Note: CSS in WebView component only supports named colors or rgb() notation
|
||||
htmlColor:'#222222',
|
||||
htmlBackgroundColor: 'white',
|
||||
htmlDividerColor: 'rgb(150,150,150)',
|
||||
htmlLinkColor: 'blue',
|
||||
htmlCodeColor: 'rgb(239, 240, 241)',
|
||||
htmlCodeBorderColor: 'rgb(203, 203, 203)',
|
||||
htmlDividerColor: 'rgb(230,230,230)',
|
||||
htmlLinkColor: 'rgb(80,130,190)',
|
||||
htmlTableBackgroundColor: 'rgb(247, 247, 247)',
|
||||
htmlCodeBackgroundColor: 'rgb(243, 243, 243)',
|
||||
htmlCodeBorderColor: 'rgb(220, 220, 220)',
|
||||
htmlCodeColor: 'rgb(0,0,0)',
|
||||
|
||||
editorTheme: "chrome",
|
||||
codeThemeCss: "atom-one-light.css",
|
||||
@@ -111,14 +117,13 @@ const darkStyle = {
|
||||
|
||||
warningBackgroundColor: "#CC6600",
|
||||
|
||||
codeColor: "#2F3031",
|
||||
codeBorderColor: '#464646',
|
||||
|
||||
htmlColor: 'rgb(220,220,220)', // Note: CSS in WebView component only supports named colors or rgb() notation
|
||||
htmlColor: 'rgb(220,220,220)',
|
||||
htmlBackgroundColor: 'rgb(29,32,36)',
|
||||
htmlDividerColor: 'rgb(150,150,150)',
|
||||
htmlDividerColor: '#3D444E',
|
||||
htmlCodeColor: '#ffffff',
|
||||
htmlLinkColor: 'rgb(166,166,255)',
|
||||
htmlCodeColor: 'rgb(47, 48, 49)',
|
||||
htmlTableBackgroundColor: 'rgb(40, 41, 42)',
|
||||
htmlCodeBackgroundColor: 'rgb(47, 48, 49)',
|
||||
htmlCodeBorderColor: 'rgb(70, 70, 70)',
|
||||
|
||||
editorTheme: 'twilight',
|
||||
@@ -192,7 +197,6 @@ function addExtraStyles(style) {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
@@ -213,8 +217,10 @@ function themeStyle(theme) {
|
||||
textAreaLineHeight: Math.round(17 * editorFontSize / 12),
|
||||
|
||||
// For WebView - must correspond to the properties above
|
||||
htmlFontSize: Math.round(12 * zoomRatio) + 'px',
|
||||
htmlLineHeight: Math.round(20 * zoomRatio) + 'px'
|
||||
htmlFontSize: Math.round(15 * zoomRatio) + 'px',
|
||||
htmlLineHeight: '1.6em', //Math.round(20 * zoomRatio) + 'px'
|
||||
|
||||
htmlCodeFontSize: '.9em',
|
||||
}
|
||||
|
||||
let output = {};
|
||||
|
53
README.md
53
README.md
@@ -36,7 +36,7 @@ wget -O - https://raw.githubusercontent.com/laurent22/joplin/master/Joplin_insta
|
||||
|
||||
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://joplin.cozic.net/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.235/joplin-v1.0.235.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://joplin.cozic.net/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.236/joplin-v1.0.236.apk)
|
||||
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://joplin.cozic.net/images/BadgeIOS.png'/></a> | -
|
||||
|
||||
## Terminal application
|
||||
@@ -184,6 +184,7 @@ WebDAV-compatible services that are known to work with Joplin:
|
||||
- [OwnCloud](https://owncloud.org/)
|
||||
- [Seafile](https://www.seafile.com/)
|
||||
- [Stack](https://www.transip.nl/stack/)
|
||||
- [WebDAV Nav](https://www.schimera.com/products/webdav-nav-server/), a macOS server.
|
||||
- [Zimbra](https://www.zimbra.com/)
|
||||
|
||||
## OneDrive synchronisation
|
||||
@@ -200,6 +201,10 @@ Joplin supports end-to-end encryption (E2EE) on all the applications. E2EE is a
|
||||
|
||||
For a more technical description, mostly relevant for development or to review the method being used, please see the [Encryption specification](https://joplin.cozic.net/spec).
|
||||
|
||||
# External text editor
|
||||
|
||||
Joplin notes can be opened and edited using an external editor of your choice. It can be a simple text editor like Notepad++ or Sublime Text or an actual Markdown editor like Typora. In that case, images will also be displayed within the editor. To open the note in an external editor, click on the icon in the toolbar or press Ctrl+E (or Cmd+E). Your default text editor will be used to open the note. If needed, you can also specify the editor directly in the General Options, under "Text editor command".
|
||||
|
||||
# Attachments / Resources
|
||||
|
||||
Any kind of file can be attached to a note. In Markdown, links to these files are represented as a simple ID to the resource. In the note viewer, these files, if they are images, will be displayed or, if they are other files (PDF, text files, etc.) they will be displayed as links. Clicking on this link will open the file in the default application.
|
||||
@@ -284,7 +289,7 @@ It is generally recommended to enter the notes as Markdown as it makes the notes
|
||||
|
||||
## 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.
|
||||
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. 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.
|
||||
|
||||
# Searching
|
||||
|
||||
@@ -335,29 +340,29 @@ Current translations:
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
| Language | Po File | Last translator | Percent done
|
||||
---|---|---|---|---
|
||||
 | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 59%
|
||||
 | Catalan | [ca](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ca.po) | jmontane, 2018 | 84%
|
||||
 | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić (trbuhom@net.hr) | 48%
|
||||
 | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt (lukas@aiya.cz) | 75%
|
||||
 | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér (mjjzf@syntaktisk. | 76%
|
||||
 | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Michael Sonntag (ms@editorei.de) | 98%
|
||||
 | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 25%
|
||||
 | Catalan | [ca](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ca.po) | jmontane, 2018 | 10%
|
||||
 | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić (trbuhom@net.hr) | 33%
|
||||
 | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt (lukas@aiya.cz) | 17%
|
||||
 | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér (mjjzf@syntaktisk. | 15%
|
||||
 | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Michael Sonntag (ms@editorei.de) | 2%
|
||||
 | English | [en_GB](https://github.com/laurent22/joplin/blob/master/CliClient/locales/en_GB.po) | | 100%
|
||||
 | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín (f@mrtn.es) | 90%
|
||||
 | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 100%
|
||||
 | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans (marcoslansgarza@gmail.com) | 75%
|
||||
 | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 93%
|
||||
 | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 60%
|
||||
 | Nederlands | [nl_NL](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_NL.po) | Heimen Stoffels (vistausss@outlook.com) | 90%
|
||||
 | Norwegian | [nb_NO](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nb_NO.po) | Mats Estensen (code@mxe.no) | 97%
|
||||
 | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos (rnbastos@gmail.com) | 97%
|
||||
 | Română | [ro](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ro.po) | | 59%
|
||||
 | Slovenian | [sl_SI](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sl_SI.po) | | 74%
|
||||
 | Svenska | [sv](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sv.po) | Jonatan Nyberg (jonatan@autistici.org) | 89%
|
||||
 | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov (artyom.karlov@gmail.com) | 77%
|
||||
 | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 93%
|
||||
 | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_TW.po) | penguinsam (samliu@gmail.com) | 90%
|
||||
 | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | AWASHIRO Ikuya (ikunya@gmail.com) | 97%
|
||||
 | 한국말 | [ko](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ko.po) | | 90%
|
||||
 | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín (f@mrtn.es) | 6%
|
||||
 | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 0%
|
||||
 | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans (marcoslansgarza@gmail.com) | 17%
|
||||
 | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 5%
|
||||
 | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 26%
|
||||
 | Nederlands | [nl_NL](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_NL.po) | Heimen Stoffels (vistausss@outlook.com) | 6%
|
||||
 | Norwegian | [nb_NO](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nb_NO.po) | Mats Estensen (code@mxe.no) | 1%
|
||||
 | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos (rnbastos@gmail.com) | 2%
|
||||
 | Română | [ro](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ro.po) | | 38%
|
||||
 | Slovenian | [sl_SI](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sl_SI.po) | | 17%
|
||||
 | Svenska | [sv](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sv.po) | Jonatan Nyberg (jonatan@autistici.org) | 7%
|
||||
 | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov (artyom.karlov@gmail.com) | 14%
|
||||
 | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 0%
|
||||
 | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_TW.po) | penguinsam (samliu@gmail.com) | 6%
|
||||
 | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | AWASHIRO Ikuya (ikunya@gmail.com) | 2%
|
||||
 | 한국말 | [ko](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ko.po) | | 1%
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
|
||||
# Known bugs
|
||||
|
@@ -90,8 +90,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097471
|
||||
versionName "1.0.235"
|
||||
versionCode 2097472
|
||||
versionName "1.0.236"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
@@ -166,8 +166,8 @@ dependencies {
|
||||
implementation project(':react-native-version-info')
|
||||
implementation "com.facebook.react:react-native:+"
|
||||
|
||||
implementation "com.google.android.gms:play-services-base:16.0.1" // For Firebase
|
||||
implementation 'me.leolin:ShortcutBadger:1.1.21@aar' // For Firebase - this line if you wish to use badge on Android
|
||||
// implementation "com.google.android.gms:play-services-base:16.0.1" // For Firebase
|
||||
// implementation 'me.leolin:ShortcutBadger:1.1.21@aar' // For Firebase - this line if you wish to use badge on Android
|
||||
|
||||
// To fix the error below, which happened after adding react-native-camera.
|
||||
// Doesn't make any sense since rn-camera neither defines v26 nor 27 but
|
||||
|
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>10.0.28</string>
|
||||
<string>10.0.29</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>28</string>
|
||||
<string>29</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
|
@@ -237,9 +237,30 @@ class BaseApplication {
|
||||
id: state.selectedNoteIds && state.selectedNoteIds.length ? state.selectedNoteIds[0] : null,
|
||||
});
|
||||
} else {
|
||||
const lastSelectedNoteIds = stateUtils.lastSelectedNoteIds(state);
|
||||
const foundIds = [];
|
||||
for (let i = 0; i < lastSelectedNoteIds.length; i++) {
|
||||
const noteId = lastSelectedNoteIds[i];
|
||||
let found = false;
|
||||
for (let j = 0; j < notes.length; j++) {
|
||||
if (notes[j].id === noteId) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) foundIds.push(noteId);
|
||||
}
|
||||
|
||||
let selectedNoteId = null;
|
||||
if (foundIds.length) {
|
||||
selectedNoteId = foundIds[0];
|
||||
} else {
|
||||
selectedNoteId = notes.length ? notes[0].id : null;
|
||||
}
|
||||
|
||||
this.store().dispatch({
|
||||
type: 'NOTE_SELECT',
|
||||
id: notes.length ? notes[0].id : null,
|
||||
id: selectedNoteId,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -543,8 +564,6 @@ class BaseApplication {
|
||||
if (!currentFolder) currentFolder = await Folder.defaultFolder();
|
||||
Setting.setValue('activeFolderId', currentFolder ? currentFolder.id : '');
|
||||
|
||||
// await this.testing();process.exit();
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
@@ -44,6 +44,23 @@ class BaseModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
static modelIndexById(items, id) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].id == id) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static modelsByIds(items, ids) {
|
||||
const output = [];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (ids.indexOf(items[i].id) >= 0) {
|
||||
output.push(items[i]);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Prefer the use of this function to compare IDs as it handles the case where
|
||||
// one ID is null and the other is "", in which case they are actually considered to be the same.
|
||||
static idsEqual(id1, id2) {
|
||||
|
@@ -145,7 +145,7 @@ class ClipperServer {
|
||||
const execRequest = async (request, body = '', files = []) => {
|
||||
try {
|
||||
const response = await this.api_.route(request.method, url.pathname, url.query, body, files);
|
||||
writeResponse(200, response);
|
||||
writeResponse(200, response ? response : '');
|
||||
} catch (error) {
|
||||
this.logger().error(error);
|
||||
writeResponse(error.httpCode ? error.httpCode : 500, error.message);
|
||||
|
@@ -525,7 +525,7 @@ class MdToHtml {
|
||||
b,strong{font-weight:bolder}small{font-size:80%}img{border-style:none}
|
||||
`;
|
||||
|
||||
const fontFamily = 'sans-serif';
|
||||
const fontFamily = "'Avenir', 'Arial', sans-serif";
|
||||
|
||||
const css = `
|
||||
body {
|
||||
@@ -535,28 +535,44 @@ class MdToHtml {
|
||||
background-color: ` + style.htmlBackgroundColor + `;
|
||||
font-family: ` + fontFamily + `;
|
||||
padding-bottom: ` + options.paddingBottom + `;
|
||||
/* So that, for example, highlighted text or background images are printed too, otherwise browsers tend not to print these things */
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
p, h1, h2, h3, h4, h5, h6, ul, table {
|
||||
margin-top: 0;
|
||||
margin-bottom: 14px;
|
||||
margin-top: .6em;
|
||||
margin-bottom: .65em;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
line-height: 1.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid ` + style.htmlDividerColor + `;
|
||||
padding-bottom: .3em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.2em;
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
/ *border-bottom: 1px solid ` + style.htmlDividerColor + `;
|
||||
padding-bottom: .1em; */
|
||||
}
|
||||
h3, h4, h5, h6 {
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
h4, h5, h6 {
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
a {
|
||||
color: ` + style.htmlLinkColor + `
|
||||
color: ` + style.htmlLinkColor + `;
|
||||
}
|
||||
ul {
|
||||
padding-left: 1.3em;
|
||||
ul, ol {
|
||||
padding-left: 0;
|
||||
margin-left: 1.7em;
|
||||
}
|
||||
li {
|
||||
margin-bottom: .4em;
|
||||
}
|
||||
li p {
|
||||
margin-bottom: 0;
|
||||
@@ -567,7 +583,7 @@ class MdToHtml {
|
||||
top: .5em;
|
||||
text-decoration: none;
|
||||
width: 1.15em;
|
||||
height: 1.5em;
|
||||
height: 1.45em;
|
||||
margin-right: 0.4em;
|
||||
background-color: ` + style.htmlColor + `;
|
||||
/* Awesome Font file */
|
||||
@@ -590,30 +606,51 @@ class MdToHtml {
|
||||
/* Awesome Font check-square-o */
|
||||
-webkit-mask: url("data:image/svg+xml;utf8,<svg viewBox='0 0 1792 1792' xmlns='http://www.w3.org/2000/svg'><path d='M1472 930v318q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q63 0 117 25 15 7 18 23 3 17-9 29l-49 49q-10 10-23 10-3 0-9-2-23-6-45-6h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-254q0-13 9-22l64-64q10-10 23-10 6 0 12 3 20 8 20 29zm231-489l-814 814q-24 24-57 24t-57-24l-430-430q-24-24-24-57t24-57l110-110q24-24 57-24t57 24l263 263 647-647q24-24 57-24t57 24l110 110q24 24 24 57t-24 57z'/></svg>");
|
||||
}
|
||||
blockquote {
|
||||
border-left: 4px solid ` + style.htmlCodeBorderColor + `;
|
||||
padding-left: 1.2em;
|
||||
margin-left: 0;
|
||||
opacity: .7;
|
||||
}
|
||||
table {
|
||||
text-align: left-align;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid ` + style.htmlCodeBorderColor + `;
|
||||
background-color: ` + style.htmlBackgroundColor + `;
|
||||
}
|
||||
td, th {
|
||||
border: 1px solid silver;
|
||||
padding: .5em 1em .5em 1em;
|
||||
font-size: ` + style.htmlFontSize + `;
|
||||
color: ` + style.htmlColor + `;
|
||||
background-color: ` + style.htmlBackgroundColor + `;
|
||||
font-family: ` + fontFamily + `;
|
||||
}
|
||||
td {
|
||||
border: 1px solid ` + style.htmlCodeBorderColor + `;
|
||||
}
|
||||
th {
|
||||
border: 1px solid ` + style.htmlCodeBorderColor + `;
|
||||
border-bottom: 2px solid ` + style.htmlCodeBorderColor + `;
|
||||
background-color: ` + style.htmlTableBackgroundColor + `;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: ` + style.htmlTableBackgroundColor + `;
|
||||
}
|
||||
hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid ` + style.htmlDividerColor + `;
|
||||
border-bottom: 2px solid ` + style.htmlDividerColor + `;
|
||||
}
|
||||
img {
|
||||
/* width: auto; */
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.inline-code {
|
||||
border: 1px solid ` + style.htmlCodeBorderColor + `;
|
||||
background-color: ` + style.htmlCodeColor + `;
|
||||
background-color: ` + style.htmlCodeBackgroundColor + `;
|
||||
padding-right: .2em;
|
||||
padding-left: .2em;
|
||||
border-radius: .25em;
|
||||
color: ` + style.htmlCodeColor + `;
|
||||
font-size: ` + style.htmlCodeFontSize + `;
|
||||
}
|
||||
|
||||
.highlighted-keyword {
|
||||
@@ -635,24 +672,9 @@ class MdToHtml {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
a.checkbox {
|
||||
border: 1pt solid ` + style.htmlColor + `;
|
||||
border-radius: 2pt;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
line-height: 1em;
|
||||
text-align: center;
|
||||
top: .4em;
|
||||
}
|
||||
|
||||
a.checkbox.tick:after {
|
||||
content: "X";
|
||||
}
|
||||
|
||||
a.checkbox.tick {
|
||||
top: 0;
|
||||
left: -0.02em;
|
||||
color: ` + style.htmlColor + `;
|
||||
/* Checkbox ticks are displayed upside down when printed for some reason */
|
||||
transform: scaleY(-1);
|
||||
}
|
||||
|
||||
pre {
|
||||
@@ -665,10 +687,35 @@ class MdToHtml {
|
||||
}
|
||||
`;
|
||||
|
||||
// To style the checkboxes in print when webkit-print-color-adjust is not enabled.
|
||||
// Keep it there for now in case that CSS parameter needs to be removed.
|
||||
|
||||
// a.checkbox {
|
||||
// border: 1pt solid ` + style.htmlColor + `;
|
||||
// border-radius: 2pt;
|
||||
// width: 1em;
|
||||
// height: 1em;
|
||||
// line-height: 1em;
|
||||
// text-align: center;
|
||||
// top: .4em;
|
||||
// }
|
||||
|
||||
// a.checkbox.tick:after {
|
||||
// content: "X";
|
||||
// }
|
||||
|
||||
// a.checkbox.tick {
|
||||
// top: 0;
|
||||
// left: -0.02em;
|
||||
// color: ` + style.htmlColor + `;
|
||||
// }
|
||||
|
||||
const styleHtml = '<style>' + normalizeCss + "\n" + css + '</style>';
|
||||
|
||||
const output = styleHtml + renderedBody;
|
||||
|
||||
// console.info('<!DOCTYPE html><html><head><meta charset="UTF-8">' + output + '</body></html>');
|
||||
|
||||
this.cachedContent_ = output;
|
||||
this.cachedContentKey_ = cacheKey;
|
||||
return this.cachedContent_;
|
||||
|
@@ -41,7 +41,7 @@ class WebDavApi {
|
||||
}
|
||||
|
||||
baseUrl() {
|
||||
return this.options_.baseUrl();
|
||||
return rtrimSlashes(this.options_.baseUrl());
|
||||
}
|
||||
|
||||
relativeBaseUrl() {
|
||||
@@ -216,7 +216,71 @@ class WebDavApi {
|
||||
output.push(url);
|
||||
|
||||
return output.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
handleNginxHack_(jsonResponse, newErrorHandler) {
|
||||
// Trying to fix 404 error issue with Nginx WebDAV server.
|
||||
// https://github.com/laurent22/joplin/issues/624
|
||||
// https://github.com/laurent22/joplin/issues/808
|
||||
// Not tested but someone confirmed it worked - https://github.com/laurent22/joplin/issues/808#issuecomment-443552858
|
||||
// and fix is narrowly scoped so shouldn't affect anything outside this particular edge case.
|
||||
//
|
||||
// The issue is that instead of an HTTP 404 status code, Nginx returns 200 but with this response:
|
||||
//
|
||||
// <?xml version="1.0" encoding="utf-8" ?>
|
||||
// <D:multistatus xmlns:D="DAV:">
|
||||
// <D:response>
|
||||
// <D:href>/notes/ecd4027a5271483984b00317433e2c66.md</D:href>
|
||||
// <D:propstat>
|
||||
// <D:prop/>
|
||||
// <D:status>HTTP/1.1 404 Not Found</D:status>
|
||||
// </D:propstat>
|
||||
// </D:response>
|
||||
// </D:multistatus>
|
||||
//
|
||||
// So we need to parse this and find that it is in fact a 404 error.
|
||||
//
|
||||
// HOWEVER, some implementations also return 404 for missing props, for example SeaFile:
|
||||
// (indicates that the props "getlastmodified" is not present, but this call is only
|
||||
// used when checking the conf, so we don't really need it)
|
||||
// https://github.com/laurent22/joplin/issues/1137
|
||||
//
|
||||
// <?xml version='1.0' encoding='UTF-8'?>
|
||||
// <ns0:multistatus xmlns:ns0="DAV:">
|
||||
// <ns0:response>
|
||||
// <ns0:href>/seafdav/joplin/</ns0:href>
|
||||
// <ns0:propstat>
|
||||
// <ns0:prop>
|
||||
// <ns0:getlastmodified/>
|
||||
// </ns0:prop>
|
||||
// <ns0:status>HTTP/1.1 404 Not Found</ns0:status>
|
||||
// </ns0:propstat>
|
||||
// <ns0:propstat>
|
||||
// <ns0:prop>
|
||||
// <ns0:resourcetype>
|
||||
// <ns0:collection/>
|
||||
// </ns0:resourcetype>
|
||||
// </ns0:prop>
|
||||
// <ns0:status>HTTP/1.1 200 OK</ns0:status>
|
||||
// </ns0:propstat>
|
||||
// </ns0:response>
|
||||
// </ns0:multistatus>
|
||||
//
|
||||
// As a simple fix for now it's enough to check if ALL the statuses are 404 - in that case
|
||||
// it really means that the file doesn't exist. Otherwise we can proceed as usual.
|
||||
const responseArray = this.arrayFromJson(jsonResponse, ['d:multistatus', 'd:response']);
|
||||
if (responseArray && responseArray.length === 1) {
|
||||
const propStats = this.arrayFromJson(jsonResponse, ['d:multistatus', 'd:response', 0, 'd:propstat']);
|
||||
if (!propStats.length) return;
|
||||
let count404 = 0;
|
||||
for (let i = 0; i < propStats.length; i++) {
|
||||
const status = this.arrayFromJson(jsonResponse, ['d:multistatus', 'd:response', 0, 'd:propstat', i, 'd:status']);
|
||||
if (status && status.length && status[0].indexOf('404') >= 0) count404++;
|
||||
}
|
||||
|
||||
if (count404 === propStats.length) throw newErrorHandler('Not found', 404);
|
||||
}
|
||||
}
|
||||
|
||||
// curl -u admin:123456 'http://nextcloud.local/remote.php/dav/files/admin/' -X PROPFIND --data '<?xml version="1.0" encoding="UTF-8"?>
|
||||
// <d:propfind xmlns:d="DAV:">
|
||||
@@ -321,17 +385,7 @@ class WebDavApi {
|
||||
if (['MKCOL', 'DELETE', 'PUT', 'MOVE'].indexOf(method) >= 0) return null;
|
||||
|
||||
const output = await loadResponseJson();
|
||||
|
||||
// Trying to fix 404 error issue with Nginx WebDAV server.
|
||||
// https://github.com/laurent22/joplin/issues/624
|
||||
// https://github.com/laurent22/joplin/issues/808
|
||||
// Not tested but someone confirmed it worked - https://github.com/laurent22/joplin/issues/808#issuecomment-443552858
|
||||
// and fix is narrowly scoped so shouldn't affect anything outside this particular edge case.
|
||||
const responseArray = this.arrayFromJson(output, ['d:multistatus', 'd:response']);
|
||||
if (responseArray && responseArray.length === 1) {
|
||||
const status = this.stringFromJson(output, ['d:multistatus', 'd:response', 0, 'd:propstat', 0, 'd:status', 0]);
|
||||
if (status && status.indexOf('404') >= 0) throw newError('Not found', 404);
|
||||
}
|
||||
this.handleNginxHack_(output, newError);
|
||||
|
||||
// Check that we didn't get for example an HTML page (as an error) instead of the JSON response
|
||||
// null responses are possible, for example for DELETE calls
|
||||
|
118
ReactNativeClient/lib/WelcomeUtils.js
Normal file
118
ReactNativeClient/lib/WelcomeUtils.js
Normal file
@@ -0,0 +1,118 @@
|
||||
const welcomeAssets = require('./welcomeAssets');
|
||||
const Note = require('lib/models/Note');
|
||||
const Setting = require('lib/models/Setting');
|
||||
const Folder = require('lib/models/Folder');
|
||||
const Tag = require('lib/models/Tag');
|
||||
const Resource = require('lib/models/Resource');
|
||||
const { shim } = require('lib/shim');
|
||||
const { uuid } = require('lib/uuid');
|
||||
const { fileExtension, basename} = require('lib/path-utils');
|
||||
const { pregQuote } = require('lib/string-utils');
|
||||
|
||||
class WelcomeUtils {
|
||||
|
||||
static async createWelcomeItems() {
|
||||
const overwriteExisting = Setting.value('env') === 'dev';
|
||||
|
||||
const output = {
|
||||
defaultFolderId: null,
|
||||
};
|
||||
|
||||
const noteAssets = welcomeAssets.notes;
|
||||
const folderAssets = welcomeAssets.folders;
|
||||
const tempDir = Setting.value('resourceDir');
|
||||
|
||||
for (let i = 0; i < folderAssets.length; i++) {
|
||||
const folderAsset = folderAssets[i];
|
||||
const folderId = folderAsset.id;
|
||||
|
||||
if (!output.defaultFolderId) output.defaultFolderId = folderId;
|
||||
|
||||
let existingFolder = await Folder.load(folderId);
|
||||
|
||||
if (existingFolder && overwriteExisting) {
|
||||
await Folder.delete(existingFolder.id);
|
||||
existingFolder = null;
|
||||
}
|
||||
|
||||
if (existingFolder) continue;
|
||||
|
||||
await Folder.save({
|
||||
id: folderId,
|
||||
title: folderAsset.title,
|
||||
}, { isNew: true });
|
||||
}
|
||||
|
||||
for (let i = noteAssets.length - 1; i >= 0; i--) {
|
||||
const noteAsset = noteAssets[i];
|
||||
|
||||
const noteId = noteAsset.id;
|
||||
|
||||
let existingNote = await Note.load(noteId);
|
||||
|
||||
if (existingNote && overwriteExisting) {
|
||||
await Note.delete(existingNote.id);
|
||||
existingNote = null;
|
||||
}
|
||||
|
||||
if (existingNote) continue;
|
||||
|
||||
let noteBody = noteAsset.body;
|
||||
|
||||
for (let resourceUrl in noteAsset.resources) {
|
||||
if (!noteAsset.resources.hasOwnProperty(resourceUrl)) continue;
|
||||
const resourceAsset = noteAsset.resources[resourceUrl];
|
||||
const resourceId = resourceAsset.id;
|
||||
|
||||
let existingResource = await Resource.load(resourceId);
|
||||
|
||||
if (existingResource && overwriteExisting) {
|
||||
await Resource.delete(resourceId);
|
||||
existingResource = null;
|
||||
}
|
||||
|
||||
if (!existingResource) {
|
||||
const ext = fileExtension(resourceUrl);
|
||||
const tempFilePath = tempDir + '/' + uuid.create() + '.tmp.' + ext;
|
||||
await shim.fsDriver().writeFile(tempFilePath, resourceAsset.body, 'base64');
|
||||
await shim.createResourceFromPath(tempFilePath, {
|
||||
id: resourceId,
|
||||
title: basename(resourceUrl),
|
||||
});
|
||||
await shim.fsDriver().remove(tempFilePath);
|
||||
}
|
||||
|
||||
const regex = new RegExp(pregQuote('(' + resourceUrl + ')'), 'g');
|
||||
noteBody = noteBody.replace(regex, '(:/' + resourceId + ')');
|
||||
}
|
||||
|
||||
await Note.save({
|
||||
id: noteId,
|
||||
parent_id: noteAsset.parent_id,
|
||||
title: noteAsset.title,
|
||||
body: noteBody,
|
||||
}, { isNew: true });
|
||||
|
||||
if (noteAsset.tags) await Tag.setNoteTagsByTitles(noteId, noteAsset.tags);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static async install(dispatch) {
|
||||
if (!Setting.value('welcome.wasBuilt')) {
|
||||
const result = await WelcomeUtils.createWelcomeItems();
|
||||
Setting.setValue('welcome.wasBuilt', true);
|
||||
|
||||
dispatch({
|
||||
type: 'FOLDER_SELECT',
|
||||
id: result.defaultFolderId,
|
||||
});
|
||||
|
||||
Setting.setValue('activeFolderId', result.defaultFolderId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = WelcomeUtils;
|
@@ -27,11 +27,15 @@ const globalStyle = {
|
||||
|
||||
// For WebView - must correspond to the properties above
|
||||
htmlFontSize: '16px',
|
||||
htmlColor: 'black', // Note: CSS in WebView component only supports named colors or rgb() notation
|
||||
htmlColor: '#222222',
|
||||
htmlBackgroundColor: 'white',
|
||||
htmlDividerColor: 'Gainsboro',
|
||||
htmlLinkColor: 'blue',
|
||||
htmlLineHeight: '20px',
|
||||
htmlDividerColor: 'rgb(230,230,230)',
|
||||
htmlLinkColor: 'rgb(80,130,190)',
|
||||
htmlLineHeight: '1.6em',
|
||||
|
||||
htmlCodeBackgroundColor: 'rgb(243, 243, 243)',
|
||||
htmlCodeBorderColor: 'rgb(220, 220, 220)',
|
||||
htmlCodeColor: 'rgb(0,0,0)',
|
||||
};
|
||||
|
||||
globalStyle.marginRight = globalStyle.margin;
|
||||
@@ -40,28 +44,6 @@ globalStyle.marginTop = globalStyle.margin;
|
||||
globalStyle.marginBottom = globalStyle.margin;
|
||||
globalStyle.htmlMarginLeft = ((globalStyle.marginLeft / 10) * 0.6).toFixed(2) + 'em';
|
||||
|
||||
// globalStyle.icon = {
|
||||
// color: globalStyle.color,
|
||||
// fontSize: 30,
|
||||
// };
|
||||
|
||||
// globalStyle.lineInput = {
|
||||
// color: globalStyle.color,
|
||||
// backgroundColor: globalStyle.backgroundColor,
|
||||
// };
|
||||
|
||||
// globalStyle.buttonRow = {
|
||||
// flexDirection: 'row',
|
||||
// borderTopWidth: 1,
|
||||
// borderTopColor: globalStyle.dividerColor,
|
||||
// paddingTop: 10,
|
||||
// };
|
||||
|
||||
// globalStyle.normalText = {
|
||||
// color: globalStyle.color,
|
||||
// fontSize: globalStyle.fontSize,
|
||||
// };
|
||||
|
||||
let themeCache_ = {};
|
||||
|
||||
function addExtraStyles(style) {
|
||||
@@ -79,8 +61,8 @@ function addExtraStyles(style) {
|
||||
};
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
style.lineInput.borderBottomWidth = 1;
|
||||
style.lineInput.borderBottomColor = style.dividerColor;
|
||||
delete style.lineInput.borderBottomWidth;
|
||||
delete style.lineInput.borderColor;
|
||||
}
|
||||
|
||||
style.buttonRow = {
|
||||
@@ -130,6 +112,12 @@ function themeStyle(theme) {
|
||||
output.htmlBackgroundColor = 'rgb(29,32,36)';
|
||||
output.htmlLinkColor = 'rgb(166,166,255)';
|
||||
|
||||
output.htmlDividerColor = '#3D444E';
|
||||
output.htmlLinkColor = 'rgb(166,166,255)';
|
||||
output.htmlCodeColor = '#ffffff';
|
||||
output.htmlCodeBackgroundColor = 'rgb(47, 48, 49)';
|
||||
output.htmlCodeBorderColor = 'rgb(70, 70, 70)';
|
||||
|
||||
output.colorUrl = '#7B81FF';
|
||||
|
||||
themeCache_[theme] = output;
|
||||
|
@@ -71,15 +71,17 @@ class SearchScreenComponent extends BaseScreenComponent {
|
||||
this.isMounted_ = false;
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(newProps) {
|
||||
let newState = {};
|
||||
if ('query' in newProps) newState.query = newProps.query;
|
||||
// UNSAFE_componentWillReceiveProps(newProps) {
|
||||
// console.info('UNSAFE_componentWillReceiveProps', newProps);
|
||||
|
||||
if (Object.getOwnPropertyNames(newState).length) {
|
||||
this.setState(newState);
|
||||
this.refreshSearch(newState.query);
|
||||
}
|
||||
}
|
||||
// let newState = {};
|
||||
// if ('query' in newProps && !this.state.query) newState.query = newProps.query;
|
||||
|
||||
// if (Object.getOwnPropertyNames(newState).length) {
|
||||
// this.setState(newState);
|
||||
// this.refreshSearch(newState.query);
|
||||
// }
|
||||
// }
|
||||
|
||||
searchTextInput_submit() {
|
||||
const query = this.state.query.trim();
|
||||
@@ -89,6 +91,9 @@ class SearchScreenComponent extends BaseScreenComponent {
|
||||
type: 'SEARCH_QUERY',
|
||||
query: query,
|
||||
});
|
||||
|
||||
this.setState({ query: query });
|
||||
this.refreshSearch(query);
|
||||
}
|
||||
|
||||
clearButton_press() {
|
||||
@@ -96,6 +101,9 @@ class SearchScreenComponent extends BaseScreenComponent {
|
||||
type: 'SEARCH_QUERY',
|
||||
query: '',
|
||||
});
|
||||
|
||||
this.setState({ query: '' });
|
||||
this.refreshSearch('');
|
||||
}
|
||||
|
||||
async refreshSearch(query = null) {
|
||||
|
@@ -79,4 +79,31 @@ shared.settingsToComponents = function(comp, device, settings) {
|
||||
return settingComps
|
||||
}
|
||||
|
||||
shared.settingsToComponents2 = function(comp, device, settings) {
|
||||
const keys = Setting.keys(true, device);
|
||||
const sectionComps = [];
|
||||
const metadatas = [];
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
if (!Setting.isPublic(key)) continue;
|
||||
|
||||
const md = Setting.settingMetadata(key);
|
||||
if (md.show && !md.show(settings)) continue;
|
||||
|
||||
metadatas.push(md);
|
||||
}
|
||||
|
||||
const sections = Setting.groupMetadatasBySections(metadatas);
|
||||
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const section = sections[i];
|
||||
const sectionComp = comp.sectionToComponent(section.name, section, settings);
|
||||
if (!sectionComp) continue;
|
||||
sectionComps.push(sectionComp);
|
||||
}
|
||||
|
||||
return sectionComps
|
||||
}
|
||||
|
||||
module.exports = shared;
|
@@ -3,15 +3,22 @@ const Folder = require('lib/models/Folder.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Mutex = require('async-mutex').Mutex;
|
||||
|
||||
const shared = {};
|
||||
|
||||
// If saveNoteButton_press is called multiple times in short intervals, it might result in
|
||||
// the same new note being created twice, so we need to a mutex to access this function.
|
||||
const saveNoteMutex_ = new Mutex();
|
||||
|
||||
shared.noteExists = async function(noteId) {
|
||||
const existingNote = await Note.load(noteId);
|
||||
return !!existingNote;
|
||||
}
|
||||
|
||||
shared.saveNoteButton_press = async function(comp, folderId = null) {
|
||||
const releaseMutex = await saveNoteMutex_.acquire();
|
||||
|
||||
let note = Object.assign({}, comp.state.note);
|
||||
|
||||
// Note has been deleted while user was modifying it. In that case, we
|
||||
@@ -24,7 +31,7 @@ shared.saveNoteButton_press = async function(comp, folderId = null) {
|
||||
const activeFolderId = Setting.value('activeFolderId');
|
||||
let folder = await Folder.load(activeFolderId);
|
||||
if (!folder) folder = await Folder.defaultFolder();
|
||||
if (!folder) return;
|
||||
if (!folder) return releaseMutex();
|
||||
note.parent_id = folder.id;
|
||||
}
|
||||
|
||||
@@ -46,7 +53,7 @@ shared.saveNoteButton_press = async function(comp, folderId = null) {
|
||||
const stateNote = comp.state.note;
|
||||
|
||||
// Note was reloaded while being saved.
|
||||
if (!isNew && (!stateNote || stateNote.id !== savedNote.id)) return;
|
||||
if (!isNew && (!stateNote || stateNote.id !== savedNote.id)) return releaseMutex();
|
||||
|
||||
// Re-assign any property that might have changed during saving (updated_time, etc.)
|
||||
note = Object.assign(note, savedNote);
|
||||
@@ -105,6 +112,8 @@ shared.saveNoteButton_press = async function(comp, folderId = null) {
|
||||
id: savedNote.id,
|
||||
});
|
||||
}
|
||||
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
shared.saveOneProperty = async function(comp, name, value) {
|
||||
|
@@ -26,43 +26,61 @@ function folderIsVisible(folders, folderId, collapsedFolderIds) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function renderFoldersRecursive_(props, renderItem, items, parentId, depth) {
|
||||
function renderFoldersRecursive_(props, renderItem, items, parentId, depth, order) {
|
||||
const folders = props.folders;
|
||||
for (let i = 0; i < folders.length; i++) {
|
||||
let folder = folders[i];
|
||||
if (!Folder.idsEqual(folder.parent_id, parentId)) continue;
|
||||
if (!folderIsVisible(props.folders, folder.id, props.collapsedFolderIds)) continue;
|
||||
const hasChildren = folderHasChildren_(folders, folder.id);
|
||||
order.push(folder.id);
|
||||
items.push(renderItem(folder, props.selectedFolderId == folder.id && props.notesParentType == 'Folder', hasChildren, depth));
|
||||
if (hasChildren) items = renderFoldersRecursive_(props, renderItem, items, folder.id, depth + 1);
|
||||
if (hasChildren) {
|
||||
const result = renderFoldersRecursive_(props, renderItem, items, folder.id, depth + 1, order);
|
||||
items = result.items;
|
||||
order = result.order;
|
||||
}
|
||||
}
|
||||
return items;
|
||||
return {
|
||||
items: items,
|
||||
order: order,
|
||||
};
|
||||
}
|
||||
|
||||
shared.renderFolders = function(props, renderItem) {
|
||||
return renderFoldersRecursive_(props, renderItem, [], '', 0);
|
||||
return renderFoldersRecursive_(props, renderItem, [], '', 0, []);
|
||||
}
|
||||
|
||||
shared.renderTags = function(props, renderItem) {
|
||||
let tags = props.tags.slice();
|
||||
tags.sort((a, b) => { return a.title < b.title ? -1 : +1; });
|
||||
let tagItems = [];
|
||||
const order = [];
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
const tag = tags[i];
|
||||
order.push(tag.id);
|
||||
tagItems.push(renderItem(tag, props.selectedTagId == tag.id && props.notesParentType == 'Tag'));
|
||||
}
|
||||
return tagItems;
|
||||
return {
|
||||
items: tagItems,
|
||||
order: order,
|
||||
};
|
||||
}
|
||||
|
||||
shared.renderSearches = function(props, renderItem) {
|
||||
let searches = props.searches.slice();
|
||||
let searchItems = [];
|
||||
for (let i = 0; i < searches.length; i++) {
|
||||
const search = searches[i];
|
||||
searchItems.push(renderItem(search, props.selectedSearchId == search.id && props.notesParentType == 'Search'));
|
||||
}
|
||||
return searchItems;
|
||||
}
|
||||
// shared.renderSearches = function(props, renderItem) {
|
||||
// let searches = props.searches.slice();
|
||||
// let searchItems = [];
|
||||
// const order = [];
|
||||
// for (let i = 0; i < searches.length; i++) {
|
||||
// const search = searches[i];
|
||||
// order.push(search.id);
|
||||
// searchItems.push(renderItem(search, props.selectedSearchId == search.id && props.notesParentType == 'Search'));
|
||||
// }
|
||||
// return {
|
||||
// items: searchItems,
|
||||
// order: order,
|
||||
// };
|
||||
// }
|
||||
|
||||
shared.synchronize_press = async function(comp) {
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
|
@@ -200,13 +200,15 @@ class SideMenuContentComponent extends Component {
|
||||
items.push(<View style={{ height: globalStyle.marginTop }} key='bottom_top_hack'/>);
|
||||
|
||||
if (this.props.folders.length) {
|
||||
const folderItems = shared.renderFolders(this.props, this.folderItem.bind(this));
|
||||
const result = shared.renderFolders(this.props, this.folderItem.bind(this));
|
||||
const folderItems = result.items;
|
||||
items = items.concat(folderItems);
|
||||
if (items.length) items.push(this.makeDivider('divider_1'));
|
||||
}
|
||||
|
||||
if (this.props.tags.length) {
|
||||
const tagItems = shared.renderTags(this.props, this.tagItem.bind(this));
|
||||
const result = shared.renderTags(this.props, this.tagItem.bind(this));
|
||||
const tagItems = result.items;
|
||||
|
||||
items.push(
|
||||
<View style={this.styles().tagItemList} key="tag_items">
|
||||
|
@@ -364,7 +364,7 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
|
||||
note.longitude = noteAttributes.longitude;
|
||||
note.altitude = noteAttributes.altitude;
|
||||
note.author = noteAttributes.author;
|
||||
note.is_todo = !!noteAttributes['reminder-order'];
|
||||
note.is_todo = noteAttributes['reminder-order'] !== '0' && !!noteAttributes['reminder-order'];
|
||||
note.todo_due = dateToTimestamp(noteAttributes['reminder-time'], true);
|
||||
note.todo_completed = dateToTimestamp(noteAttributes['reminder-done-time'], true);
|
||||
note.order = dateToTimestamp(noteAttributes['reminder-order'], true);
|
||||
|
@@ -4,6 +4,8 @@ const BaseItem = require('lib/models/BaseItem.js');
|
||||
const ItemChange = require('lib/models/ItemChange.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const { pregQuote } = require('lib/string-utils.js');
|
||||
const { toSystemSlashes } = require('lib/path-utils.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const ArrayUtils = require('lib/ArrayUtils.js');
|
||||
@@ -27,7 +29,7 @@ class Note extends BaseItem {
|
||||
}
|
||||
|
||||
static async serializeForEdit(note) {
|
||||
return super.serialize(note, ['title', 'body']);
|
||||
return this.replaceResourceInternalToExternalLinks(await super.serialize(note, ['title', 'body']));
|
||||
}
|
||||
|
||||
static async unserializeForEdit(content) {
|
||||
@@ -35,6 +37,7 @@ class Note extends BaseItem {
|
||||
let output = await super.unserialize(content);
|
||||
if (!output.title) output.title = '';
|
||||
if (!output.body) output.body = '';
|
||||
output.body = await this.replaceResourceExternalToInternalLinks(output.body);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -165,6 +168,30 @@ class Note extends BaseItem {
|
||||
return await this.linkedItemIdsByType(BaseModel.TYPE_RESOURCE, body);
|
||||
}
|
||||
|
||||
static async replaceResourceInternalToExternalLinks(body) {
|
||||
const resourceIds = await this.linkedResourceIds(body);
|
||||
const Resource = this.getClass('Resource');
|
||||
|
||||
for (let i = 0; i < resourceIds.length; i++) {
|
||||
const id = resourceIds[i];
|
||||
const resource = await Resource.load(id);
|
||||
if (!resource) continue;
|
||||
body = body.replace(new RegExp(':/' + id, 'gi'), toSystemSlashes(Resource.fullPath(resource)));
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
static async replaceResourceExternalToInternalLinks(body) {
|
||||
const reString = pregQuote(toSystemSlashes(Resource.baseDirectoryPath() + '/')) + '[a-zA-Z0-9\.]+';
|
||||
const re = new RegExp(reString, 'gi');
|
||||
body = body.replace(re, (match) => {
|
||||
const id = Resource.pathToId(match);
|
||||
return ':/' + id;
|
||||
});
|
||||
return body;
|
||||
}
|
||||
|
||||
static new(parentId = '') {
|
||||
let output = super.new();
|
||||
output.parent_id = parentId;
|
||||
@@ -447,6 +474,19 @@ class Note extends BaseItem {
|
||||
return this.changeNoteType(note, !!note.is_todo ? 'note' : 'todo');
|
||||
}
|
||||
|
||||
static toggleTodoCompleted(note) {
|
||||
if (!('todo_completed' in note)) throw new Error('Missing "todo_completed" property');
|
||||
|
||||
note = Object.assign({}, note);
|
||||
if (note.todo_completed) {
|
||||
note.todo_completed = 0;
|
||||
} else {
|
||||
note.todo_completed = Date.now();
|
||||
}
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
static async duplicate(noteId, options = null) {
|
||||
const changes = options && options.changes;
|
||||
const uniqueTitle = options && options.uniqueTitle;
|
||||
|
@@ -63,6 +63,10 @@ class Resource extends BaseItem {
|
||||
return output + extension;
|
||||
}
|
||||
|
||||
static baseDirectoryPath() {
|
||||
return Setting.value('resourceDir');
|
||||
}
|
||||
|
||||
static fullPath(resource, encryptedBlob = false) {
|
||||
return Setting.value('resourceDir') + '/' + this.filename(resource, encryptedBlob);
|
||||
}
|
||||
|
@@ -53,15 +53,15 @@ class Setting extends BaseModel {
|
||||
options[Setting.TIME_FORMAT_2] = time.formatMsToLocal(now, Setting.TIME_FORMAT_2);
|
||||
return options;
|
||||
}},
|
||||
'theme': { value: Setting.THEME_LIGHT, type: Setting.TYPE_INT, public: true, appTypes: ['mobile', 'desktop'], isEnum: true, label: () => _('Theme'), options: () => {
|
||||
'theme': { value: Setting.THEME_LIGHT, type: Setting.TYPE_INT, public: true, appTypes: ['mobile', 'desktop'], isEnum: true, label: () => _('Theme'), section: 'appearance', options: () => {
|
||||
let output = {};
|
||||
output[Setting.THEME_LIGHT] = _('Light');
|
||||
output[Setting.THEME_DARK] = _('Dark');
|
||||
return output;
|
||||
}},
|
||||
'uncompletedTodosOnTop': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['cli'], label: () => _('Uncompleted to-dos on top') },
|
||||
'showCompletedTodos': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['cli'], label: () => _('Show completed to-dos') },
|
||||
'notes.sortOrder.field': { value: 'user_updated_time', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['cli'], label: () => _('Sort notes by'), options: () => {
|
||||
'uncompletedTodosOnTop': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, appTypes: ['cli'], label: () => _('Uncompleted to-dos on top') },
|
||||
'showCompletedTodos': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, appTypes: ['cli'], label: () => _('Show completed to-dos') },
|
||||
'notes.sortOrder.field': { value: 'user_updated_time', type: Setting.TYPE_STRING, section: 'note', isEnum: true, public: true, appTypes: ['cli'], label: () => _('Sort notes by'), options: () => {
|
||||
const Note = require('lib/models/Note');
|
||||
const noteSortFields = ['user_updated_time', 'user_created_time', 'title'];
|
||||
const options = {};
|
||||
@@ -70,15 +70,15 @@ class Setting extends BaseModel {
|
||||
}
|
||||
return options;
|
||||
}},
|
||||
'notes.sortOrder.reverse': { value: true, type: Setting.TYPE_BOOL, public: true, label: () => _('Reverse sort order'), appTypes: ['cli'] },
|
||||
'trackLocation': { value: true, type: Setting.TYPE_BOOL, public: true, label: () => _('Save geo-location with notes') },
|
||||
'newTodoFocus': { value: 'title', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new to-do:'), options: () => {
|
||||
'notes.sortOrder.reverse': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, label: () => _('Reverse sort order'), appTypes: ['cli'] },
|
||||
'trackLocation': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, label: () => _('Save geo-location with notes') },
|
||||
'newTodoFocus': { value: 'title', type: Setting.TYPE_STRING, section: 'note', isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new to-do:'), options: () => {
|
||||
return {
|
||||
'title': _('Focus title'),
|
||||
'body': _('Focus body'),
|
||||
};
|
||||
}},
|
||||
'newNoteFocus': { value: 'body', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new note:'), options: () => {
|
||||
'newNoteFocus': { value: 'body', type: Setting.TYPE_STRING, section: 'note', isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new note:'), options: () => {
|
||||
return {
|
||||
'title': _('Focus title'),
|
||||
'body': _('Focus body'),
|
||||
@@ -89,11 +89,11 @@ class Setting extends BaseModel {
|
||||
// http://www.webupd8.org/2017/04/fix-appindicator-not-working-for.html
|
||||
// Might be fixed in Electron 18.x but no non-beta release yet. So for now
|
||||
// by default we disable it on Linux.
|
||||
'showTrayIcon': { value: platform !== 'linux', type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Show tray icon'), description: () => {
|
||||
'showTrayIcon': { value: platform !== 'linux', type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Show tray icon'), description: () => {
|
||||
return platform === 'linux' ? _('Note: Does not work in all desktop environments.') : _('This will allow Joplin to run in the background. It is recommended to enable this setting so that your notes are constantly being synchronised, thus reducing the number of conflicts.');
|
||||
}},
|
||||
|
||||
'startMinimized': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Start application minimised in the tray icon') },
|
||||
'startMinimized': { value: false, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Start application minimised in the tray icon') },
|
||||
|
||||
'collapsedFolderIds': { value: [], type: Setting.TYPE_ARRAY, public: false },
|
||||
|
||||
@@ -101,13 +101,13 @@ class Setting extends BaseModel {
|
||||
'encryption.enabled': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
'encryption.activeMasterKeyId': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
'encryption.passwordCache': { value: {}, type: Setting.TYPE_OBJECT, public: false, secure: true },
|
||||
'style.zoom': {value: 100, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], label: () => _('Global zoom percentage'), minimum: 50, maximum: 500, step: 10},
|
||||
'style.editor.fontSize': {value: 12, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], label: () => _('Editor font size'), minimum: 4, maximum: 50, step: 1},
|
||||
'style.editor.fontFamily': {value: "", type: Setting.TYPE_STRING, public: true, appTypes: ['desktop'], label: () => _('Editor font family'), description: () => _('This must be *monospace* font or it will not work properly. If the font is incorrect or empty, it will default to a generic monospace font.')},
|
||||
'autoUpdateEnabled': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Automatically update the application') },
|
||||
'autoUpdate.includePreReleases': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Get pre-releases when checking for updates'), description: () => _('See the pre-release page for more details: %s', 'https://joplin.cozic.net/prereleases') },
|
||||
'style.zoom': {value: 100, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Global zoom percentage'), minimum: 50, maximum: 500, step: 10},
|
||||
'style.editor.fontSize': {value: 13, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Editor font size'), minimum: 4, maximum: 50, step: 1},
|
||||
'style.editor.fontFamily': {value: "", type: Setting.TYPE_STRING, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Editor font family'), description: () => _('This must be *monospace* font or it will not work properly. If the font is incorrect or empty, it will default to a generic monospace font.')},
|
||||
'autoUpdateEnabled': { value: true, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Automatically update the application') },
|
||||
'autoUpdate.includePreReleases': { value: false, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Get pre-releases when checking for updates'), description: () => _('See the pre-release page for more details: %s', 'https://joplin.cozic.net/prereleases') },
|
||||
'clipperServer.autoStart': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
'sync.interval': { value: 300, type: Setting.TYPE_INT, isEnum: true, public: true, label: () => _('Synchronisation interval'), options: () => {
|
||||
'sync.interval': { value: 300, type: Setting.TYPE_INT, section:'sync', isEnum: true, public: true, label: () => _('Synchronisation interval'), options: () => {
|
||||
return {
|
||||
0: _('Disabled'),
|
||||
300: _('%d minutes', 5),
|
||||
@@ -122,13 +122,13 @@ class Setting extends BaseModel {
|
||||
'sidebarVisibility': { value: true, type: Setting.TYPE_BOOL, public: false, appTypes: ['desktop'] },
|
||||
'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, 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.') },
|
||||
'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.') },
|
||||
'showAdvancedOptions': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['mobile' ], label: () => _('Show advanced options') },
|
||||
'sync.target': { value: SyncTargetRegistry.nameToId('dropbox'), type: Setting.TYPE_INT, isEnum: true, public: true, label: () => _('Synchronisation target'), description: (appType) => { return appType !== 'cli' ? null : _('The target to synchonise to. Each sync target may have additional parameters which are named as `sync.NUM.NAME` (all documented below).') }, options: () => {
|
||||
'sync.target': { value: SyncTargetRegistry.nameToId('dropbox'), type: Setting.TYPE_INT, isEnum: true, public: true, section:'sync', label: () => _('Synchronisation target'), description: (appType) => { return appType !== 'cli' ? null : _('The target to synchonise to. Each sync target may have additional parameters which are named as `sync.NUM.NAME` (all documented below).') }, options: () => {
|
||||
return SyncTargetRegistry.idAndLabelPlainObject();
|
||||
}},
|
||||
|
||||
'sync.2.path': { value: '', type: Setting.TYPE_STRING, show: (settings) => {
|
||||
'sync.2.path': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => {
|
||||
try {
|
||||
return settings['sync.target'] == SyncTargetRegistry.nameToId('filesystem')
|
||||
} catch (error) {
|
||||
@@ -138,13 +138,13 @@ class Setting extends BaseModel {
|
||||
return value ? rtrimSlashes(value) : '';
|
||||
}, public: true, label: () => _('Directory to synchronise with (absolute path)'), description: (appType) => { return appType !== 'cli' ? null : _('The path to synchronise with when file system synchronisation is enabled. See `sync.target`.'); } },
|
||||
|
||||
'sync.5.path': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.5.username': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud username') },
|
||||
'sync.5.password': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud password'), secure: true },
|
||||
'sync.5.path': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.5.username': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud username') },
|
||||
'sync.5.password': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud password'), secure: true },
|
||||
|
||||
'sync.6.path': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.6.username': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV username') },
|
||||
'sync.6.password': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV password'), secure: true },
|
||||
'sync.6.path': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.6.username': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV username') },
|
||||
'sync.6.password': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV password'), secure: true },
|
||||
|
||||
'sync.3.auth': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
'sync.4.auth': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
@@ -157,14 +157,15 @@ class Setting extends BaseModel {
|
||||
'sync.6.context': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
'sync.7.context': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
|
||||
'net.customCertificates': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Custom TLS certificates'), description: () => _('Comma-separated list of paths to directories to load the certificates from, or path to individual cert files. For example: /my/cert_dir, /other/custom.pem. Note that if you make changes to the TLS settings, you must save your changes before clicking on "Check synchronisation configuration".') },
|
||||
'net.ignoreTlsErrors': { value: false, type: Setting.TYPE_BOOL, show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Ignore TLS certificate errors') },
|
||||
'net.customCertificates': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Custom TLS certificates'), description: () => _('Comma-separated list of paths to directories to load the certificates from, or path to individual cert files. For example: /my/cert_dir, /other/custom.pem. Note that if you make changes to the TLS settings, you must save your changes before clicking on "Check synchronisation configuration".') },
|
||||
'net.ignoreTlsErrors': { value: false, type: Setting.TYPE_BOOL, section:'sync', show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Ignore TLS certificate errors') },
|
||||
|
||||
'api.token': { value: null, type: Setting.TYPE_STRING, public: false },
|
||||
|
||||
'resourceService.lastProcessedChangeId': { value: 0, type: Setting.TYPE_INT, public: false },
|
||||
'searchEngine.lastProcessedChangeId': { value: 0, type: Setting.TYPE_INT, public: false },
|
||||
'searchEngine.initialIndexingDone': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
'welcome.wasBuilt': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
};
|
||||
|
||||
return this.metadata_;
|
||||
@@ -527,6 +528,36 @@ class Setting extends BaseModel {
|
||||
if (typeId === Setting.TYPE_OBJECT) return 'object';
|
||||
}
|
||||
|
||||
static groupMetadatasBySections(metadatas) {
|
||||
let sections = [];
|
||||
const generalSection = { name: 'general', metadatas: [] };
|
||||
const nameToSections = {};
|
||||
nameToSections['general'] = generalSection;
|
||||
sections.push(generalSection);
|
||||
for (let i = 0; i < metadatas.length; i++) {
|
||||
const md = metadatas[i];
|
||||
if (!md.section) {
|
||||
generalSection.metadatas.push(md);
|
||||
} else {
|
||||
if (!nameToSections[md.section]) {
|
||||
nameToSections[md.section] = { name: md.section, metadatas: [] };
|
||||
sections.push(nameToSections[md.section]);
|
||||
}
|
||||
nameToSections[md.section].metadatas.push(md);
|
||||
}
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
static sectionNameToLabel(name) {
|
||||
if (name === 'general') return _('General');
|
||||
if (name === 'sync') return _('Synchronisation');
|
||||
if (name === 'appearance') return _('Appearance');
|
||||
if (name === 'note') return _('Note');
|
||||
if (name === 'application') return _('Application');
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Setting.TYPE_INT = 1;
|
||||
|
@@ -114,4 +114,43 @@ function ltrimSlashes(path) {
|
||||
return path.replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
module.exports = { basename, dirname, filename, isHidden, fileExtension, safeFilename, friendlySafeFilename, safeFileExtension, toSystemSlashes, rtrimSlashes, ltrimSlashes };
|
||||
function quotePath(path) {
|
||||
if (!path) return '';
|
||||
if (path.indexOf('"') < 0 && path.indexOf(' ') < 0) return path;
|
||||
path = path.replace(/"/, '\\"');
|
||||
return '"' + path + '"';
|
||||
}
|
||||
|
||||
function unquotePath(path) {
|
||||
if (!path.length) return '';
|
||||
if (path.length && path[0] === '"') {
|
||||
path = path.substr(1, path.length - 2);
|
||||
}
|
||||
path = path.replace(/\\"/, '"');
|
||||
return path;
|
||||
}
|
||||
|
||||
function extractExecutablePath(cmd) {
|
||||
if (!cmd.length) return '';
|
||||
|
||||
const quoteType = ['"', "'"].indexOf(cmd[0]) >= 0 ? cmd[0] : '';
|
||||
|
||||
let output = '';
|
||||
for (let i = 0; i < cmd.length; i++) {
|
||||
const c = cmd[i];
|
||||
if (quoteType) {
|
||||
if (i > 0 && c === quoteType) {
|
||||
output += c;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (c === ' ') break;
|
||||
}
|
||||
|
||||
output += c;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
module.exports = { extractExecutablePath, basename, dirname, filename, isHidden, fileExtension, safeFilename, friendlySafeFilename, safeFileExtension, toSystemSlashes, rtrimSlashes, ltrimSlashes, quotePath, unquotePath };
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user