Merge branch 'dev' into file-mirror

file-mirror
Laurent Cozic 2024-02-27 16:41:36 +00:00
commit 03f9ac47de
289 changed files with 17738 additions and 15669 deletions

View File

@ -230,6 +230,7 @@ packages/app-desktop/gui/MainScreen/commands/showNoteProperties.js
packages/app-desktop/gui/MainScreen/commands/showPrompt.js
packages/app-desktop/gui/MainScreen/commands/showShareFolderDialog.js
packages/app-desktop/gui/MainScreen/commands/showShareNoteDialog.js
packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.test.js
packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js

View File

@ -207,6 +207,22 @@ if [ "$RUN_TESTS" == "1" ]; then
fi
fi
# =============================================================================
# Spellchecking
# =============================================================================
if [ "$IS_PULL_REQUEST" == "1" ]; then
if [ "$IS_LINUX" == "1" ]; then
echo "Step: Spellchecking..."
yarn spellcheck --all
testResult=$?
if [ $testResult -ne 0 ]; then
exit $testResult
fi
fi
fi
# =============================================================================
# Find out if we should run the build or not. Electron-builder gets stuck when
# building PRs so we disable it in this case. The Linux build should provide

1
.gitignore vendored
View File

@ -210,6 +210,7 @@ packages/app-desktop/gui/MainScreen/commands/showNoteProperties.js
packages/app-desktop/gui/MainScreen/commands/showPrompt.js
packages/app-desktop/gui/MainScreen/commands/showShareFolderDialog.js
packages/app-desktop/gui/MainScreen/commands/showShareNoteDialog.js
packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.test.js
packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js

View File

@ -0,0 +1,33 @@
diff --git a/lib/runner/index.js b/lib/runner/index.js
index 87e3b3957619728e3ed1ca61e2d83df1c49f928f..6d5ab905415da0577341c8f5b67d4806adcf7549 100644
--- a/lib/runner/index.js
+++ b/lib/runner/index.js
@@ -68,15 +68,19 @@ function run([, scriptPath, hookName = '', HUSKY_GIT_PARAMS], getStdinFn = get_s
return 0;
}
catch (err) {
- const noVerifyMessage = [
- 'commit-msg',
- 'pre-commit',
- 'pre-rebase',
- 'pre-push'
- ].includes(hookName)
- ? '(add --no-verify to bypass)'
- : '(cannot be bypassed with --no-verify due to Git specs)';
- console.log(`husky > ${hookName} hook failed ${noVerifyMessage}`);
+ // We do not want to print this "add --no-verify to bypass" message because that's
+ // literally what some developers do instead of trying to fix the errors.
+
+ // const noVerifyMessage = [
+ // 'commit-msg',
+ // 'pre-commit',
+ // 'pre-rebase',
+ // 'pre-push'
+ // ].includes(hookName)
+ // ? '(add --no-verify to bypass)'
+ // : '(cannot be bypassed with --no-verify due to Git specs)';
+
+ console.log(`husky > ${hookName} hook failed (Please fix the errors listed above and try again)`);
return err.code;
}
});

View File

@ -39,11 +39,12 @@ Please see the [donation page](https://github.com/laurent22/joplin/blob/dev/read
<!-- SPONSORS-GITHUB -->
| | | | |
| :---: | :---: | :---: | :---: |
| <img width="50" src="https://avatars2.githubusercontent.com/u/215668?s=96&v=4"/></br>[avanderberg](https://github.com/avanderberg) | <img width="50" src="https://avatars2.githubusercontent.com/u/67130?s=96&v=4"/></br>[chr15m](https://github.com/chr15m) | <img width="50" src="https://avatars2.githubusercontent.com/u/2793530?s=96&v=4"/></br>[CyberXZT](https://github.com/CyberXZT) | <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[dbrandonjohnson](https://github.com/dbrandonjohnson) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/14873877?s=96&v=4"/></br>[dchecks](https://github.com/dchecks) | <img width="50" src="https://avatars2.githubusercontent.com/u/56287?s=96&v=4"/></br>[fats](https://github.com/fats) | <img width="50" src="https://avatars2.githubusercontent.com/u/8030470?s=96&v=4"/></br>[Galliver7](https://github.com/Galliver7) | <img width="50" src="https://avatars2.githubusercontent.com/u/64712218?s=96&v=4"/></br>[Hegghammer](https://github.com/Hegghammer) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/1310474?s=96&v=4"/></br>[jknowles](https://github.com/jknowles) | <img width="50" src="https://avatars2.githubusercontent.com/u/11947658?s=96&v=4"/></br>[KentBrockman](https://github.com/KentBrockman) | <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[konishi-t](https://github.com/konishi-t) | <img width="50" src="https://avatars2.githubusercontent.com/u/42319182?s=96&v=4"/></br>[marcdw1289](https://github.com/marcdw1289) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/126279083?s=96&v=4"/></br>[matmoly](https://github.com/matmoly) | <img width="50" src="https://avatars2.githubusercontent.com/u/1788010?s=96&v=4"/></br>[maxtruxa](https://github.com/maxtruxa) | <img width="50" src="https://avatars2.githubusercontent.com/u/4560672?s=96&v=4"/></br>[mu88](https://github.com/mu88) | <img width="50" src="https://avatars2.githubusercontent.com/u/31054972?s=96&v=4"/></br>[saarantras](https://github.com/saarantras) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/327998?s=96&v=4"/></br>[sif](https://github.com/sif) | <img width="50" src="https://avatars2.githubusercontent.com/u/765564?s=96&v=4"/></br>[taskcruncher](https://github.com/taskcruncher) | <img width="50" src="https://avatars2.githubusercontent.com/u/333944?s=96&v=4"/></br>[tateisu](https://github.com/tateisu) | |
| <img width="50" src="https://avatars2.githubusercontent.com/u/552452?s=96&v=4"/></br>[andypiper](https://github.com/andypiper) | <img width="50" src="https://avatars2.githubusercontent.com/u/215668?s=96&v=4"/></br>[avanderberg](https://github.com/avanderberg) | <img width="50" src="https://avatars2.githubusercontent.com/u/67130?s=96&v=4"/></br>[chr15m](https://github.com/chr15m) | <img width="50" src="https://avatars2.githubusercontent.com/u/2793530?s=96&v=4"/></br>[CyberXZT](https://github.com/CyberXZT) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[dbrandonjohnson](https://github.com/dbrandonjohnson) | <img width="50" src="https://avatars2.githubusercontent.com/u/14873877?s=96&v=4"/></br>[dchecks](https://github.com/dchecks) | <img width="50" src="https://avatars2.githubusercontent.com/u/56287?s=96&v=4"/></br>[fats](https://github.com/fats) | <img width="50" src="https://avatars2.githubusercontent.com/u/8030470?s=96&v=4"/></br>[Galliver7](https://github.com/Galliver7) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/64712218?s=96&v=4"/></br>[Hegghammer](https://github.com/Hegghammer) | <img width="50" src="https://avatars2.githubusercontent.com/u/2583421?s=96&v=4"/></br>[jamesandariese](https://github.com/jamesandariese) | <img width="50" src="https://avatars2.githubusercontent.com/u/1310474?s=96&v=4"/></br>[jknowles](https://github.com/jknowles) | <img width="50" src="https://avatars2.githubusercontent.com/u/11947658?s=96&v=4"/></br>[KentBrockman](https://github.com/KentBrockman) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[konishi-t](https://github.com/konishi-t) | <img width="50" src="https://avatars2.githubusercontent.com/u/42319182?s=96&v=4"/></br>[marcdw1289](https://github.com/marcdw1289) | <img width="50" src="https://avatars2.githubusercontent.com/u/126279083?s=96&v=4"/></br>[matmoly](https://github.com/matmoly) | <img width="50" src="https://avatars2.githubusercontent.com/u/1788010?s=96&v=4"/></br>[maxtruxa](https://github.com/maxtruxa) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/4560672?s=96&v=4"/></br>[mu88](https://github.com/mu88) | <img width="50" src="https://avatars2.githubusercontent.com/u/31054972?s=96&v=4"/></br>[saarantras](https://github.com/saarantras) | <img width="50" src="https://avatars2.githubusercontent.com/u/327998?s=96&v=4"/></br>[sif](https://github.com/sif) | <img width="50" src="https://avatars2.githubusercontent.com/u/765564?s=96&v=4"/></br>[taskcruncher](https://github.com/taskcruncher) |
| <img width="50" src="https://avatars2.githubusercontent.com/u/333944?s=96&v=4"/></br>[tateisu](https://github.com/tateisu) | | | |
<!-- SPONSORS-GITHUB -->
# Community

View File

@ -1,7 +1,13 @@
{
"version": "0.2",
"language": "en_GB",
"ignoreRegExpList": [
"\\[.*?\\]\\(https:\\/\\/github.com\\/.*?\\)",
"by .*?\\)",
"\\| (.*?) \\| \\d\\d%"
],
"ignorePaths": [
"**/*.d.ts",
"**/*.min.*",
"**/*.svg",
"/_mydocs",
@ -11,7 +17,10 @@
"/Assets",
"/packages/app-cli/app/fuzzing.js",
"/packages/app-cli/build",
"/packages/app-cli/tests/enex_to_md/",
"/packages/app-cli/tests/html_to_md/",
"/packages/app-cli/tests/support",
"/packages/app-cli/tests/sync",
"/packages/app-cli/tests/test data",
"/packages/app-cli/tests/tmp",
"/packages/app-clipper/content_scripts/JSDOMParser.js",
@ -20,14 +29,24 @@
"/packages/app-clipper/popup/build/js/0.chunk.js",
"/packages/app-clipper/popup/build/js/bundle.js",
"/packages/app-clipper/popup/build/js/main.chunk.js",
"/packages/app-clipper/popup/build/js/main.chunk.js",
"/packages/app-clipper/popup/config",
"/packages/app-desktop/build/",
"/packages/app-desktop/utils/checkForUpdatesUtilsTestData.ts",
"/packages/app-desktop/vendor/",
"/packages/app-mobile/ios/Pods/",
"/packages/app-mobile/lib/rnInjectedJs",
"/packages/app-mobile/pluginAssets",
"/packages/app-mobile/utils/fs-driver/runOnDeviceTests.ts",
"/packages/default-plugins/plugin-sources/",
"/packages/doc-builder/build",
"/packages/doc-builder/help/",
"/packages/doc-builder/i18n/",
"/packages/doc-builder/news/",
"/packages/fork-sax/examples",
"/packages/fork-sax/lib/sax.js",
"/packages/fork-sax/test",
"/packages/fork-uslug",
"/packages/generator-joplin/generators/app/templates/api/",
"/packages/lib/locales",
"/packages/lib/mime-utils-types.js",
"/packages/lib/parameters.js",
@ -36,919 +55,38 @@
"/packages/lib/services/joplinServer/personalizedUserContentBaseUrl.ts",
"/packages/lib/vendor",
"/packages/lib/welcomeAssets.js",
"/packages/renderer/highlight.ts",
"/packages/server/src/utils/testing/randomWords.ts",
"/packages/turndown-plugin-gfm/config",
"/packages/turndown/config",
"/readme/_i18n",
"/readme/about/changelog/desktop.md",
"/readme/i18n",
"cspell.json",
"node_modules"
],
"words": [
"aàáâãäåāą",
"AÀÁÂÃÄÅĀĄ",
"abbrev",
"ABCDEFGHIJ",
"Abhishek",
"Abkhazian",
"accel",
"accum",
"actualkeyword",
"adata",
"advlist",
"AGSFE",
"Aland",
"Åland",
"alertbanner",
"Allaire",
"alse",
"altool",
"aman",
"ambrt",
"Amharic",
"amothc",
"andrejilderda",
"anki",
"Antarctique",
"antarctiques",
"Antártico",
"anymore",
"apidoc",
"appiconset",
"applewebkit",
"approot",
"arableague",
"Aragonés",
"ARITIM",
"armeabi",
"asterix",
"atest",
"atestb",
"attribname",
"attribvalue",
"authcode",
"autocompleteitem",
"autocompleter",
"Autocompleter",
"AUTOEXEC",
"autohide",
"Avenir",
"Ayiti",
"azamah",
"Azərbaycan",
"backoff",
"Bangla",
"Bêafrîka",
"beforeinput",
"België",
"Belgien",
"Belgique",
"Bénin",
"Bhutani",
"bibtex",
"Bihari",
"Bislama",
"blabla",
"blablablabla",
"boohay",
"Bosna",
"Bouvet",
"Bouvetøya",
"browserslist",
"bthqu",
"btns",
"Bulibiya",
"bullist",
"bulma",
"Byelorussian",
"calebjohn",
"Calédonie",
"Caligraphic",
"callsites",
"Cameroun",
"cantdothat",
"Capslock",
"cardcontainer",
"cardimage",
"cardmenuitem",
"cardtext",
"Caribisch",
"CAUTOEXEC",
"cçćč",
"CÇĆČ",
"cdataend",
"cdatastart",
"cdot",
"ceaf",
"centrafricaine",
"Centrafrican",
"Česká",
"changedtitle",
"charcodes",
"checkboxclick",
"checkmark",
"chemfive",
"choiceitem",
"chromedriver",
"chromeframe",
"chromeos",
"Città",
"Cmds",
"codepoint",
"colorinput",
"colorpicker",
"colorswatch",
"colspan",
"committerdate",
"commmmmand",
"commonmark",
"COMMONMARK",
"Comores",
"compositionend",
"compositionstart",
"compositionupdate",
"conflicter",
"contenteditable",
"contextform",
"contextformbutton",
"contextformtogglebutton",
"contextkey",
"contexttoolbar",
"continuelist",
"Contrl",
"Conv",
"convo",
"copytags",
"cozic",
"Cozic",
"createdb",
"Creds",
"Crna",
"cronspec",
"cros",
"crypted",
"Curaçao",
"curso",
"customeditor",
"customkeymap",
"cyingfan",
"d'Ivoire",
"Danmark",
"Dansk",
"dataimg",
"datauri",
"Datauri",
"datetime",
"Datetime",
"davris",
"dbuuid",
"DDTHH",
"deflist",
"deinit",
"Démocratique",
"deselector",
"deuxième",
"dflt",
"dialogbox",
"dialogs",
"Dialogs",
"DIALOGS",
"Distill",
"dists",
"docid",
"docsize",
"doctypes",
"doesnotwork",
"doesntexist",
"doesntlookright",
"domelementtype",
"domhandler",
"Dominicana",
"domutils",
"DONATELINKS",
"downarrow",
"dragdrop",
"draggesture",
"dünn",
"dylib",
"dynamiclib",
"ecuatorial",
"eèéêëěēę",
"EÈÉÊËĚĒĘ",
"Eesti",
"effet",
"efgh",
"égalité",
"Éire",
"elem",
"elementpath",
"elems",
"ellipsize",
"ELOCKED",
"encryptable",
"endregion",
"enex",
"Enex",
"ENEX",
"enumber",
"eqeqeq",
"équatoriale",
"Erro",
"errorish",
"escapeplus",
"eslintignore",
"España",
"étiquette",
"EUNSPECIFIED",
"eventname",
"evermeet",
"evernote",
"Evernote",
"execa",
"expando",
"expirable",
"Expirable",
"expval",
"Færøerne",
"Fahrräder",
"FAILSAFE",
"fallbacks",
"fancymenuitem",
"fancytype",
"favorites",
"Fiber",
"filepicker",
"folderid",
"foldl",
"fontawesome",
"fontface",
"forall",
"forcewake",
"Føroyar",
"fortawesome",
"française",
"françaises",
"Gabuutih",
"gedit",
"geoip",
"Geoip",
"geoloc",
"geoplugin",
"getlastmodified",
"gettext",
"githubusercontent",
"Gora",
"gotchas",
"gradlew",
"Grønland",
"grouptoolbarbutton",
"Gruber",
"gsoc",
"gttest",
"Guåhån",
"guarentee",
"guarentees",
"Guiena",
"Guiné",
"Guinée",
"gulpfile",
"Guyane",
"gvim",
"Haïti",
"hanlder",
"Hausa",
"headerless",
"Heisenbug",
"Hercegovina",
"hift",
"highjack",
"highlited",
"historyhas",
"HMRKG",
"hoge",
"homenote",
"hotfolder",
"Howver",
"hpagent",
"Hrvatska",
"htmlentities",
"htmlfile",
"htmlpack",
"htmlpanel",
"ʻĀirani",
"icns",
"iconset",
"iconutil",
"Iforgot",
"iframes",
"ihack",
"iife",
"iìíîïī",
"IÌÍÎÏĪ",
"ijkl",
"imagelink",
"imagetools",
"immer",
"iname",
"Incl",
"infint",
"inflim",
"infty",
"inputi",
"inserttable",
"Interlingue",
"Interp",
"interupting",
"Inteval",
"Inuktitut",
"Inupiak",
"Invididual",
"IOERR",
"Ionicons",
"IPHONEOS",
"ipify",
"ipwhois",
"iscompleted",
"Ísland",
"Italiano",
"Itoophiyaa",
"itsgone",
"itunes",
"Jabuuti",
"jackgruber",
"joeattardi",
"jopext",
"joplinapp",
"JOPLINAPP",
"joplincloud",
"joplindev",
"JOPLINMOD",
"joplintest",
"jsbundles",
"justtesting",
"Kalaallit",
"kalba",
"kanban",
"Kashmiri",
"katex",
"keychain",
"keycodes",
"keymaps",
"keytar",
"Kibris",
"Kinyarwanda",
"Kirundi",
"Ködörösêse",
"Komori",
"Kpck",
"Kūki",
"Laothian",
"lastmod",
"Latvija",
"lcov",
"leaft",
"leftarrow",
"leftequilibrium",
"leftrightarrow",
"Lettish",
"Lëtzebuerg",
"Levithan",
"Liban",
"libz",
"Lietuva",
"Lietuvių",
"lineheight",
"Lingala",
"linkg",
"linkurl",
"listbox",
"listfile",
"listpreview",
"loglevel",
"longclick",
"longpress",
"longpresscancel",
"looooooong",
"ltrim",
"Luxemburg",
"Maarten",
"Madagasikara",
"Magyarország",
"majax",
"Mardown",
"markdowncalc",
"Maroc",
"MASTERKEY",
"matchinfo",
"mathchoice",
"mathjax",
"Mathjax",
"MATHJAX",
"mathllap",
"mathml",
"mathrlap",
"mathrm",
"Mauritanie",
"Maxiumm",
"Mayen",
"mchem",
"mechanim",
"mediumtext",
"menubutton",
"mergeff",
"Metadatas",
"México",
"mhchem",
"middlewares",
"migth",
"mkbook",
"MKCOL",
"mkdirp",
"mknote",
"mktodo",
"MMYY",
"modifié",
"monokai",
"MONOSPACE",
"msgctxt",
"msgfmt",
"msgmerge",
"msgstr",
"msleep",
"mtext",
"mult",
"multicursor",
"multimarkdown",
"multimd",
"multistatus",
"multitable",
"mybucket",
"mydir",
"myfile",
"mynote",
"myplugin",
"mytag",
"mytaga",
"mytagb",
"mytagc",
"mytagd",
"mytest",
"mytoken",
"myvalue",
"nanoid",
"Neaus",
"Nederlands",
"nestedmenuitem",
"newone",
"Nextcloud",
"njstrace",
"nñňń",
"NÑŇŃ",
"NOCASE",
"nodechange",
"nodir",
"noexpand",
"nojs",
"nolongershared",
"nonlatin",
"NONLATIN",
"Noreg",
"Norge",
"nospecialcharacters",
"notanumber",
"notarization",
"notetags",
"Notif",
"notindexed",
"notthere",
"nounce",
"Nounce",
"Nounces",
"npmignore",
"numadd",
"numbersareok",
"numdec",
"numdiv",
"numlist",
"Numlock",
"nummult",
"numsub",
"Nunaat",
"obelix",
"odata",
"ohno",
"OHNO",
"oldppk",
"onattribdata",
"onattribend",
"onattribname",
"onattribute",
"oncdata",
"oncdataend",
"oncdatastart",
"onclosetag",
"oncomment",
"oncommentend",
"ondeclaration",
"onedrive",
"onelink",
"onformat",
"onmatch",
"onopentag",
"onopentagend",
"onopentagname",
"onparserinit",
"onprocessinginstruction",
"onselfclosingtag",
"ontext",
"oòóôõöøō",
"OÒÓÔÕÖØŌ",
"opentag",
"opentagname",
"Opptionn",
"orignal",
"Oromo",
"Österreich",
"otherpackage",
"outdented",
"overidding",
"overriden",
"padd",
"pandoc",
"paperclip",
"passthrough",
"Päth",
"Pbuild",
"pbxproj",
"pcmag",
"pcnalx",
"pddv",
"Pehr",
"Percents",
"père",
"Perú",
"pfff",
"PGPASSWORD",
"pidfile",
"PLUGINLEGACY",
"pocount",
"Polska",
"Polski",
"Polynésie",
"Português",
"Potoczny's",
"powerpoint",
"Prakash",
"precommit",
"pred",
"preg",
"prerelease",
"Prerelease",
"presigner",
"prettycron",
"pricetag",
"Príncipe",
"privkey",
"processinginstruction",
"programatically",
"propfind",
"PROPFIND",
"propname",
"propstat",
"protcol",
"pseudoclass",
"pseudos",
"Pushto",
"quot",
"qwer",
"raisebox",
"rbga",
"readerable",
"Readerable",
"READERABLE",
"Redownload",
"reencrypt",
"reencrypted",
"Reencrypting",
"reencrypts",
"regexes",
"Regexs",
"Relavent",
"relayouted",
"rels",
"renamings",
"renderered",
"Renderered",
"República",
"republika",
"République",
"requestheaders",
"resourcetype",
"resynced",
"Rhaeto",
"rightarrow",
"rightequilibrium",
"rightleftarrows",
"rightleftharpoons",
"rmbook",
"rmnote",
"rmusin",
"rnfs",
"RNFS",
"robocopy",
"Roboto",
"România",
"roule",
"rowid",
"ROWID",
"ROWIDs",
"rowspan",
"rseidelsohn",
"rtrim",
"safeext",
"salut",
"Sangho",
"sasss",
"SAVEPOINT",
"schtroumpf",
"Schweiz",
"Scrolllock",
"scrollmap",
"seafdav",
"Seafile",
"searchengine",
"searchlimit",
"SEARCHOVERLAY",
"securerandom",
"segdir",
"selectbox",
"Sénégal",
"Serializers",
"setext",
"settingschema",
"shantanugoel",
"sharee",
"Shiftt",
"Shoft",
"shouldntendwithit",
"shouldstartwiththis",
"Shqip",
"Shqipëria",
"Sicen",
"simplemath",
"Siswati",
"sizeinput",
"SJCL",
"Slovenčina",
"Slovenija",
"Slovensko",
"softbreaks",
"Solarised",
"SOLARIZED",
"someid",
"somewhereelse",
"sourceurl",
"SPACEBAR",
"spaceno",
"Spacify",
"spdfgh",
"spellfix",
"sphemy",
"splitbutton",
"sprintf",
"sqlts",
"srcfolder",
"SSSZ",
"starttls",
"Starttls",
"stepsize",
"stevenlevithan",
"stex",
"stilltryingtohack",
"strack",
"Stringifiable",
"subdir",
"subl",
"Suomi",
"Sūriyya",
"Svenska",
"Sverige",
"svgs",
"Svizra",
"Svizzera",
"synclock",
"synclog",
"syswide",
"syswidecas",
"taboverride",
"tabpanel",
"taga",
"tagb",
"tagc",
"Tajik",
"takesover",
"targetfolder",
"Tchad",
"Teardown",
"termi",
"termutils",
"Terres",
"Tessarek",
"tessus",
"Testb",
"testcreate",
"testexportfolder",
"testingconnection",
"testingkeychain",
"testunit",
"texify",
"Texify",
"textareas",
"textexportnote",
"textstyle",
"thaaaaaaan",
"thatsok",
"thatsreallylongthatsreallylongthatsreallylongthats",
"thatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylong",
"Thevenard",
"thisisfine",
"Thmmss",
"Tiếng",
"Tigrinya",
"tiiitlllle",
"tinymce",
"titi",
"titletitle",
"tkwidget",
"tkwidgets",
"Todos",
"togglebutton",
"togglemenuitem",
"toolip",
"tooshort",
"treymo",
"tripledash",
"tsmerge",
"Tsonga",
"tttest",
"Tunisie",
"Türkçe",
"Türkiye",
"Türkmenistan",
"turndown",
"Turndown",
"TWCO",
"typeahead",
"Typora",
"tzip",
"uastring",
"uglifycss",
"uglifyjs",
"Uighur",
"unconflicted",
"underbrace",
"Undos",
"unescaping",
"unhighlighted",
"unixlike",
"unmocked",
"unserialize",
"unserialized",
"unserializes",
"unserializing",
"unshares",
"unsharing",
"unusued",
"uparrow",
"uphy",
"urlconverter",
"urlinput",
"userchrome",
"usercontent",
"userstyle",
"uslug",
"Ustd",
"utems",
"uuidgen",
"uuidv",
"uùúûüůū",
"UÙÚÛÜŮŪ",
"valign",
"Valign",
"vars",
"Vars",
"Vaticano",
"vers",
"verylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongid",
"veryverylongclientidveryverylongclientidveryverylongclientidveryverylongclientid",
"veryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitleveryverylongtitle",
"Việt",
"viewbox",
"Volapuk",
"Volívia",
"votearrow",
"webclipper",
"webdav",
"webfonts",
"whitespaces",
"widder",
"Wifi",
"Withflags",
"Wolof",
"WONTFIX",
"wrongclienttype",
"wrongpassword",
"wrongtype",
"Wuliwya",
"wxyz",
"xcallbackurl",
"xcassets",
"xcodeproj",
"xcrun",
"xgettext",
"xlink",
"xzvf",
"yarg",
"yosay",
"yufzkns",
"YYYYMMDDTHH",
"zxcvbn",
"zžżź",
"ZŽŻŹ",
"Ελλάδα",
"Ελληνικά",
"Κύπρος",
"Агентство",
"Антарктике",
"Беларусь",
"България",
"Гора",
"језик",
"Казахстан",
"Киргизия",
"Книги",
"Кыргызстан",
"Қазақстан",
"Македонија",
"Молдавия",
"Монгол",
"номер",
"рейтер",
"Рейтер",
"Россия",
"Русский",
"Северна",
"сообщило",
"СООБЩИЛО",
"Србија",
"српски",
"Україна",
"Црна",
"საქართველო",
"Հայաստան",
"ישראל",
"עיברית",
"إرتريا",
"اسلامي",
"اسلامی",
"افغانستان",
"الأُرْدُن",
"الإمارات",
"البحرين",
"الجزائر",
"السعودية",
"السودان",
"الصومال",
"العراق",
"العربيّة",
"ﺍﻟﻘﻤﺮي",
"الكويت",
"المتّحدة",
"المغرب",
"اليَمَن",
"ایران",
"پاکستان",
"تشاد",
"تونس",
"جمهوری",
"جيبوتي",
"دولة",
"دولتدولت",
"سلطنة",
"سوريا",
"عُمان",
"لبنان",
"ليبيا",
"موريتانيا",
"ⵍⵎⵖⵔⵉⴱ",
"ኢትዮጵያ",
"ኤርትራ",
"भारत",
"গণপ্রজাতন্ত্রী",
"লাদেশ",
"இலங்கை",
"ලංකා",
"คือค",
"คือคนไทย",
"ประเทศไทย",
"ປະຊາຊົນລາວ",
"မြန်မာ",
"កម្ពុជា"
]
"dictionaryDefinitions": [
{
"name": "dictionary1",
"path": "packages/tools/cspell/dictionary1.txt"
},
{
"name": "dictionary2",
"path": "packages/tools/cspell/dictionary2.txt"
},
{
"name": "dictionary3",
"path": "packages/tools/cspell/dictionary3.txt"
},
{
"name": "dictionary4",
"path": "packages/tools/cspell/dictionary4.txt"
}
],
"dictionaries": [
"dictionary1",
"dictionary2",
"dictionary3",
"dictionary4"
]
}

View File

@ -1,19 +1,27 @@
module.exports = {
// Don't compile when committing as it will process all TS files in the
// monorepo, which is too slow. Errors should be checked during development
// using `npm run watch`.
// # About TypeScript compilation
//
// Don't compile when committing as it will process all TS files in the monorepo, which is too
// slow. Errors should be checked during development using `yarn watch`.
//
// Or if we add this back, we could do something like this:
// https://stackoverflow.com/a/44748041/561309
//
// The script would check where the TS file is located, then use the right
// tsconfig.json file along with the tsconfig override.
// The script would check where the TS file is located, then use the right tsconfig.json file
// along with the tsconfig override.
//
// '**/*.ts?(x)': () => 'npm run tsc',
'*.{js,jsx,ts,tsx}': [
'yarn checkIgnoredFiles',
// 'yarn checkLibPaths',
'yarn packageJsonLint',
'yarn linter-precommit',
],
// # Running tasks in parallel
//
// lint-staged does not allow running concurrent tasks for the same extension, because multiple
// tasks might modify the same files. This doesn't apply to us because only one task modifies
// files (the linter task) while others only notify about errors. So to go around this we add
// this fake extension "task?" to make lint-staged think those are different extension tasks
// that can run in parallel.
//
// See https://github.com/lint-staged/lint-staged/issues/934#issuecomment-743299357
'*.{js,jsx,ts,tsx,task1}': 'yarn checkIgnoredFiles',
'*.{js,jsx,ts,tsx,task2}': 'yarn spellcheck',
'*.{js,jsx,ts,tsx,task3}': 'yarn packageJsonLint',
'*.{js,jsx,ts,tsx,task4}': 'yarn linter-precommit',
'*.{md,mdx}': 'yarn spellcheck',
};

View File

@ -29,7 +29,6 @@
"crowdin": "crowdin",
"crowdinDownload": "crowdin download",
"crowdinUpload": "crowdin upload",
"cspell": "cspell",
"dependencyTree": "madge",
"generateTypes": "node packages/tools/generate-database-types",
"linkChecker": "linkchecker https://joplinapp.org/ && linkchecker --check-extern https://joplinapp.org/api/references/plugin_api/classes/joplin.html",
@ -65,7 +64,7 @@
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
"pre-commit": "yarn lint-staged"
}
},
"devDependencies": {
@ -108,6 +107,7 @@
"react-native@0.71.10": "patch:react-native@npm%3A0.71.10#./.yarn/patches/react-native-animation-fix/react-native-npm-0.71.10-f9c32562d8.patch",
"nanoid": "patch:nanoid@npm%3A3.3.7#./.yarn/patches/nanoid-npm-3.3.7-98824ba130.patch",
"pdfjs-dist": "patch:pdfjs-dist@npm%3A3.11.174#./.yarn/patches/pdfjs-dist-npm-3.11.174-67f2fee6d6.patch",
"@react-native-community/slider": "patch:@react-native-community/slider@npm%3A4.4.4#./.yarn/patches/@react-native-community-slider-npm-4.4.4-d78e472f48.patch"
"@react-native-community/slider": "patch:@react-native-community/slider@npm%3A4.4.4#./.yarn/patches/@react-native-community-slider-npm-4.4.4-d78e472f48.patch",
"husky": "patch:husky@npm%3A3.1.0#./.yarn/patches/husky-npm-3.1.0-5cc13e4e34.patch"
}
}

View File

@ -82,7 +82,7 @@ class Command extends BaseCommand {
lines.push('## Authorisation');
lines.push('');
lines.push('To prevent unauthorised applications from accessing the API, the calls must be authentified. To do so, you must provide a token as a query parameter for each API call. You can get this token from the Joplin desktop application, on the Web Clipper Options screen.');
lines.push('To prevent unauthorised applications from accessing the API, the calls must be authenticated. To do so, you must provide a token as a query parameter for each API call. You can get this token from the Joplin desktop application, on the Web Clipper Options screen.');
lines.push('');
lines.push('This would be an example of valid cURL call using a token:');
lines.push('');
@ -149,7 +149,7 @@ class Command extends BaseCommand {
lines.push('');
lines.push('```shell\ncurl http://localhost:41184/notes?order_by=updated_time&order_dir=ASC&limit=10&page=2\n```');
lines.push('');
lines.push('Eventually you will get some results that do not contain an "has_more" paramater, at which point you will have retrieved all the results');
lines.push('Eventually you will get some results that do not contain an "has_more" parameter, at which point you will have retrieved all the results');
lines.push('');
lines.push('As an example the pseudo-code below could be used to fetch all the notes:');
lines.push('');
@ -199,7 +199,7 @@ async function fetchAllNotes() {
lines.push('## Item type IDs');
lines.push('');
lines.push('Item type IDs might be refered to in certain object you will retrieve from the API. This is the correspondance between name and ID:');
lines.push('Item type IDs might be referred to in certain objects you will retrieve from the API. This is the correspondence between name and ID:');
lines.push('');
lines.push('Name | Value');
lines.push('---- | -----');

View File

@ -86,7 +86,7 @@ class Command extends BaseCommand {
return true;
}
this.stdout(_('Not authentified with %s. Please provide any missing credentials.', syncTargetMd.label));
this.stdout(_('Not authenticated with %s. Please provide any missing credentials.', syncTargetMd.label));
return false;
}

View File

@ -52,7 +52,7 @@ describeIfCompatible('services_KeychainService', () => {
}));
it('should delete db settings if they have been saved in keychain', (async () => {
// First save some secure settings and make sure it ends up in the databse
// First save some secure settings and make sure it ends up in the database
KeychainService.instance().enabled = false;
Setting.setValue('sync.5.password', 'password');

View File

@ -26,7 +26,7 @@ async function browserCaptureVisibleTabs(windowId) {
// This is supposed to be the default quality, but in fact Firefox 82+
// clearly uses a much lower quality, closer to 20 or 30, so we have to
// set it here explicitely.
// set it here explicitly.
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/extensionTypes/ImageDetails
// https://discourse.joplinapp.org/t/clip-screenshot-image-quality/12302/4
quality: 92,

View File

@ -78,7 +78,7 @@ export const KeymapConfigScreen = ({ themeId }: KeymapConfigScreenProps) => {
// KeymapService is already synchronized with the in-state keymap
await keymapService.saveCustomKeymap(filePath);
} catch (error) {
bridge().showerrororMessageBox(error.message);
bridge().showErrorMessageBox(error.message);
}
}
};

View File

@ -237,7 +237,7 @@ class MainScreenComponent extends React.Component<Props, State> {
try {
output = loadLayout(Object.keys(userLayout).length ? userLayout : null, defaultLayout, rootLayoutSize);
// For unclear reasons, layout items sometimes end up witout a key.
// For unclear reasons, layout items sometimes end up without a key.
// In that case, we can't do anything with them, so remove them
// here. It could be due to the deprecated plugin API, which allowed
// creating panel without a key, although in this case it should
@ -264,7 +264,7 @@ class MainScreenComponent extends React.Component<Props, State> {
public setupAppCloseHandling() {
this.waitForNotesSavedIID_ = null;
// This event is dispached from the main process when the app is about
// This event is dispatched from the main process when the app is about
// to close. The renderer process must respond with the "appCloseReply"
// and tell the main process whether the app can really be closed or not.
// For example, it cannot be closed right away if a note is being saved.

View File

@ -19,7 +19,7 @@ export const runtime = (comp: any): CommandRuntime => {
return { value: a.id, label: a.title };
})
.sort((a: any, b: any) => {
// sensitivity accent will treat accented characters as differemt
// sensitivity accent will treat accented characters as different
// but treats caps as equal
return a.label.localeCompare(b.label, undefined, { sensitivity: 'accent' });
});
@ -28,7 +28,7 @@ export const runtime = (comp: any): CommandRuntime => {
return { value: a.id, label: a.title };
})
.sort((a: any, b: any) => {
// sensitivity accent will treat accented characters as differemt
// sensitivity accent will treat accented characters as different
// but treats caps as equal
return a.label.localeCompare(b.label, undefined, { sensitivity: 'accent' });
});

View File

@ -0,0 +1,51 @@
import { runtime } from './showSpellCheckerMenu';
import { AppState } from '../../../app.reducer';
jest.mock('../../../services/bridge', () => ({
__esModule: true,
default: () => ({
Menu: {
buildFromTemplate: jest.fn().mockReturnValue({
popup: jest.fn(),
}),
},
}),
}));
describe('mapStateToTitle', () => {
test('should return null if spellchecker.enabled is false', () => {
const mockState: Partial<AppState> = {
settings: {
'spellChecker.enabled': false,
'spellChecker.languages': ['en-GB'],
},
};
const result = runtime().mapStateToTitle(mockState);
expect(result).toBeNull();
});
test('should return null if spellChecker.languages is empty', () => {
const mockState: Partial<AppState> = {
settings: {
'spellChecker.enabled': true,
'spellChecker.languages': [],
},
};
const result = runtime().mapStateToTitle(mockState);
expect(result).toBeNull();
});
test('should return list of countryDisplayName with correct format', () => {
const mockState: Partial<AppState> = {
settings: {
'spellChecker.enabled': true,
'spellChecker.languages': ['en-GB', 'en-US', 'en-CA', 'es-ES', 'es-MX'],
},
};
const result = runtime().mapStateToTitle(mockState);
expect(result).toBe('en, es');
});
});

View File

@ -30,8 +30,10 @@ export const runtime = (): CommandRuntime => {
const s: string[] = [];
// eslint-disable-next-line github/array-foreach -- Old code before rule was applied
languages.forEach((language: string) => {
s.push(language.split('-')[0]);
const onlyLanguage = language.split('-')[0];
if (!s.includes(onlyLanguage)) { s.push(onlyLanguage); }
});
return s.join(', ');
},
};

View File

@ -563,10 +563,10 @@ function useMenu(props: Props) {
const rootMenuFile = {
// Using a dummy entry for macOS here, because first menu
// becomes 'Joplin' and we need a nenu called 'File' later.
// becomes 'Joplin' and we need a menu called 'File' later.
label: shim.isMac() ? '&JoplinMainMenu' : _('&File'),
// `&` before one of the char in the label name mean, that
// <Alt + F> will open this menu. It's needed becase electron
// <Alt + F> will open this menu. It's needed because electron
// opens the first menu on Alt press if no hotkey assigned.
// Issue: https://github.com/laurent22/joplin/issues/934
submenu: [{

View File

@ -117,7 +117,7 @@ const useContextMenu = (props: ContextMenuProps) => {
// CodeMirror 5 only:
// Typically CodeMirror handles all interactions itself (highlighting etc.)
// But in the case of clicking a mispelled word, we need electron to handle the click
// But in the case of clicking a misspelled word, we need electron to handle the click
// The result is that CodeMirror doesn't know what's been selected and doesn't
// move the cursor into the correct location.
// and when the user selects a new spelling it will be inserted in the wrong location

View File

@ -62,7 +62,7 @@ export default function useEditorSearch(CodeMirror: any) {
}
// Highlights the currently active found work
// It's possible to get tricky with this fucntions and just use findNext/findPrev
// It's possible to get tricky with this functions and just use findNext/findPrev
// but this is fast enough and works more naturally with the current search logic
function highlightSearch(cm: any, searchTerm: RegExp, index: number, scrollTo: boolean, withSelection: boolean) {
const cursor = cm.getSearchCursor(searchTerm);
@ -135,7 +135,7 @@ export default function useEditorSearch(CodeMirror: any) {
if (error.name !== 'SyntaxError') {
throw error;
}
// An error of 'Regular expression too large' might occour in the markJs library
// An error of 'Regular expression too large' might occur in the markJs library
// when the input is really big, this catch is here to avoid the application crashing
// https://github.com/laurent22/joplin/issues/7634
console.error('Error while trying to highlight words from search: ', error);

View File

@ -115,7 +115,7 @@ export default function useScrollHandler(editorRef: any, webviewRef: any, onScro
if (!isNaN(editorPercent)) {
// when switching to another note, the percent can sometimes be NaN
// this is coming from `gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.ts`
// when CodeMirror returns scroll info with heigth == clientHeigth
// when CodeMirror returns scroll info with height == clientHeight
// https://github.com/laurent22/joplin/issues/4797
if (!ignored) {
// calculates GUI-independent line-based percent

View File

@ -507,7 +507,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: ForwardedRef<NoteBodyEditor
color: ${theme.codeColor};
}
/* Negative margins are needed to componsate for the border */
/* Negative margins are needed to compensate for the border */
div.CodeMirror span.cm-comment.cm-jn-inline-code:not(.cm-search-marker):not(.cm-fat-cursor-mark):not(.cm-search-marker-selected):not(.CodeMirror-selectedtext) {
border: 1px solid ${theme.codeBorderColor};
background-color: ${codeBackgroundColor};

View File

@ -258,7 +258,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
if (joplinCommandToTinyMceCommands[cmd.name] === true) {
// Already handled in useWindowCommandHandlers.ts
} else if (joplinCommandToTinyMceCommands[cmd.name] === false) {
// Explicitely not supported
// explicitly not supported
} else {
const tinyMceCmd: TinyMceCommand = { ...(joplinCommandToTinyMceCommands[cmd.name] as TinyMceCommand) };
if (!('ui' in tinyMceCmd)) tinyMceCmd.ui = false;
@ -1126,7 +1126,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
//
// when pasting text with Ctrl+Shift+V, the format should be
// ignored. In this case,
// event.clopboardData.getData('text/html') returns an empty
// event.clipboardData.getData('text/html') returns an empty
// string, but the clipboard.readHTML() still returns the
// formatted text.
const pastedHtml = event.clipboardData.getData('text/html') ? clipboard.readHTML() : '';

View File

@ -468,7 +468,7 @@ function NoteEditor(props: NoteEditorProps) {
isSafeMode: props.isSafeMode,
useCustomPdfViewer: props.useCustomPdfViewer,
// We need it to identify the context for which media is rendered.
// It is currently used to remember pdf scroll position for each attacments of each note uniquely.
// It is currently used to remember pdf scroll position for each attachments of each note uniquely.
noteId: props.noteId,
};

View File

@ -38,7 +38,7 @@ describe('clipboardUtils', () => {
expect(copyableContent.html).toEqual(`<div><img src="${localImage}"></div>`);
});
test('should be able to process mutiple images', () => {
test('should be able to process multiple images', () => {
const localImage1 = 'file:///home/some/path/test1.jpg';
const localImage2 = 'file:///home/some/path/test2.jpg';
const localImage3 = 'file:///home/some/path/test3.jpg';

View File

@ -18,7 +18,7 @@ function htmlToMd(): HtmlToMd {
function removeImageUrlAttributes(htmlContent: string): string {
// We need to remove extra url params from the image URLs while copying
// because some offline edtors do not show the image if there is
// because some offline editors do not show the image if there is
// an extra parameter in it's path.
// Related to - https://github.com/laurent22/joplin/issues/4602
const removeParametersFromUrl = (url: string) => {

View File

@ -75,7 +75,7 @@ export default function useFormNote(dependencies: HookDependencies) {
// Increasing the value of this counter cancels any ongoing note refreshes and starts
// a new refresh.
const [formNoteRefeshScheduled, setFormNoteRefreshScheduled] = useState<number>(0);
const [formNoteRefreshScheduled, setFormNoteRefreshScheduled] = useState<number>(0);
async function initNoteState(n: any) {
let originalCss = '';
@ -114,7 +114,7 @@ export default function useFormNote(dependencies: HookDependencies) {
}
useEffect(() => {
if (formNoteRefeshScheduled <= 0) return () => {};
if (formNoteRefreshScheduled <= 0) return () => {};
reg.logger().info('Sync has finished and note has never been changed - reloading it');
@ -141,13 +141,13 @@ export default function useFormNote(dependencies: HookDependencies) {
return () => {
cancelled = true;
};
}, [formNoteRefeshScheduled, noteId]);
}, [formNoteRefreshScheduled, noteId]);
const refreshFormNote = useCallback(() => {
// Increase the counter to cancel any ongoing refresh attempts
// and start a new one.
setFormNoteRefreshScheduled(formNoteRefeshScheduled + 1);
}, [formNoteRefeshScheduled]);
setFormNoteRefreshScheduled(formNoteRefreshScheduled + 1);
}, [formNoteRefreshScheduled]);
useEffect(() => {
// Check that synchronisation has just finished - and

View File

@ -22,7 +22,7 @@ const useScroll = (itemsPerLine: number, noteCount: number, itemSize: Size, list
// check if it's correct), we forcefully set it multiple times over the next
// few milliseconds, hoping that maybe one of these attempts will stick.
//
// This is most likely a race condition in either Chromimum or Electron
// This is most likely a race condition in either Chromium or Electron
// although I couldn't find an upstream issue.
//
// Setting the value only once after a short time, for example 10ms, helps

View File

@ -138,7 +138,7 @@ function NoteListItem(props: NoteListItemProps, ref: any) {
if (error.name !== 'SyntaxError') {
throw error;
}
// An error of 'Regular expression too large' might occour in the markJs library
// An error of 'Regular expression too large' might occur in the markJs library
// when the input is really big, this catch is here to avoid the application crashing
// https://github.com/laurent22/joplin/issues/7634
console.error('Error while trying to highlight words from search: ', error);

View File

@ -25,7 +25,7 @@ const getNoteTitleHtml = (highlightedWords: string[], displayTitle: string) => {
if (error.name !== 'SyntaxError') {
throw error;
}
// An error of 'Regular expression too large' might occour in the markJs library
// An error of 'Regular expression too large' might occur in the markJs library
// when the input is really big, this catch is here to avoid the application crashing
// https://github.com/laurent22/joplin/issues/7634
// console.error('Error while trying to highlight words from search: ', error);

View File

@ -155,7 +155,7 @@ class NoteRevisionViewerComponent extends React.PureComponent<Props, State> {
}
private async webview_ipcMessage(event: any) {
// For the revision view, we only suppport a minimal subset of the IPC messages.
// For the revision view, we only support a minimal subset of the IPC messages.
// For example, we don't need interactive checkboxes or sync between viewer and editor view.
// We try to get most links work though, except for internal (joplin://) links.

View File

@ -245,7 +245,7 @@ export default class PromptDialog extends React.Component<Props, any> {
const onKeyDown = (event: any) => {
if (event.key === 'Enter') {
// If the dropdown is open, we don't close the dialog - instead
// the currently item will be selcted. If it is closed however
// the currently item will be selected. If it is closed however
// we confirm the dialog.
if ((this.props.inputType === 'tags' || this.props.inputType === 'dropdown') && this.menuIsOpened_) {
// Do nothing

View File

@ -11,7 +11,7 @@ export interface LayoutItemSizes {
}
// Container always take the full space while the items within it need to
// accomodate for the resize handle.
// accommodate for the resize handle.
export function itemSize(item: LayoutItem, parent: LayoutItem | null, sizes: LayoutItemSizes, isContainer: boolean): Size {
const parentResizableRight = !!parent && parent.resizableRight;
const parentResizableBottom = !!parent && parent.resizableBottom;

View File

@ -89,7 +89,7 @@ function itemShouldBeVisible(item: LayoutItem): boolean {
}
// If all children of a container are hidden, the container should be
// hidden too. A container visiblity cannot be changed by the user.
// hidden too. A container visibility cannot be changed by the user.
function updateContainerVisibility(_itemIndex: number, itemDraft: LayoutItem, _parent: LayoutItem) {
if (itemDraft.children) {
itemDraft.visible = itemShouldBeVisible(itemDraft);

View File

@ -41,14 +41,14 @@ async function exportDebugReportClick() {
function StatusScreen(props: Props) {
const [report, setReport] = useState<ReportSection[]>([]);
async function resfreshScreen() {
async function refreshScreen() {
const service = new ReportService();
const r = await service.status(Setting.value('sync.target'));
setReport(r);
}
useEffect(() => {
void resfreshScreen();
void refreshScreen();
}, []);
const theme = themeStyle(props.themeId);
@ -86,7 +86,7 @@ function StatusScreen(props: Props) {
if (section.canRetryAll) {
items.push(renderSectionRetryAll(`${key}_${section.title}`, async () => {
await section.retryAllHandler();
void resfreshScreen();
void refreshScreen();
}));
}
return items;
@ -112,7 +112,7 @@ function StatusScreen(props: Props) {
if (item.canRetry) {
const onClick = async () => {
await item.retryHandler();
void resfreshScreen();
void refreshScreen();
};
retryLink = (

View File

@ -5,7 +5,7 @@
// same effect.
//
// It's still reliable because the lifecyle of adding the CSS and removing on
// unmout is handled properly. There should only be one such component on the
// unmount is handled properly. There should only be one such component on the
// page.
import { useEffect, useState } from 'react';

View File

@ -109,7 +109,7 @@
let ignoreNextScrollEventCount_ = 0;
// ignoreNextScrollEvent() provides a way to skip scroll events for a certain duration.
// In general, it should be called whenever the scroll value is set explicitely (programmatically)
// In general, it should be called whenever the scroll value is set explicitly (programmatically)
// so as to differentiate scroll events generated by the user (when scrolling the view) and those
// generated by the application.
function ignoreNextScrollEvent() {

View File

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

View File

@ -15,7 +15,7 @@ describe('notesSortOrderUtils', () => {
expect(notesSortOrderFieldArray()).toStrictEqual(expected);
});
it('should provide the next field cyclicly', async () => {
it('should provide the next field cyclically', async () => {
expect(notesSortOrderNextField('user_updated_time')).toBe('user_created_time');
expect(notesSortOrderNextField('order')).toBe('user_updated_time');
});

View File

@ -22,7 +22,7 @@ export const notesSortOrderNextField = (currentField: string) => {
};
export const setNotesSortOrder = (field?: string, reverse?: boolean) => {
// field: Sort order's field. undefined means changing a field cyclicly.
// field: Sort order's field. undefined means changing a field cyclically.
// reverse: whether the sort order is reversed or not. undefined means toggling.
let nextField = field;
let nextReverse = reverse;

View File

@ -3,7 +3,7 @@ import { copy } from 'fs-extra';
import { dirname, join } from 'path';
const copy7Zip = async () => {
// We allow buildin for a different architecture/platform with
// We allow building for a different architecture/platform with
// the npm_config_target_arch and npm_config_target_platform environment variables.
//
// These are the same environment variables used by yarn when downloading dependencies.

View File

@ -15,7 +15,7 @@ jest.doMock('../bridge', () => ({
'--profile', currentProfileDirectory,
],
env: () => 'dev',
appName: () => 'joplin-destkop',
appName: () => 'joplin-desktop',
}),
}));

View File

@ -110,8 +110,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097738
versionName "2.14.8"
versionCode 2097739
versionName "2.14.9"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

View File

@ -9,8 +9,6 @@ import { WebView, WebViewMessageEvent } from 'react-native-webview';
import { WebViewErrorEvent, WebViewEvent, WebViewSource } from 'react-native-webview/lib/WebViewTypes';
import Setting from '@joplin/lib/models/Setting';
import { themeStyle } from '@joplin/lib/theme';
import { Theme } from '@joplin/lib/themes/type';
import shim from '@joplin/lib/shim';
import { StyleProp, ViewStyle } from 'react-native';
@ -34,8 +32,6 @@ type OnLoadEndCallback = (event: WebViewEvent)=> void;
type OnFileUpdateCallback = (event: SourceFileUpdateEvent)=> void;
interface Props {
themeId: number;
// A name to be associated with the WebView (e.g. NoteEditor)
// This name should be unique.
webviewInstanceId: string;
@ -67,7 +63,6 @@ interface Props {
}
const ExtendedWebView = (props: Props, ref: Ref<WebViewControl>) => {
const theme: Theme = themeStyle(props.themeId);
const webviewRef = useRef(null);
const [source, setSource] = useState<WebViewSource|undefined>(undefined);
@ -135,7 +130,10 @@ const ExtendedWebView = (props: Props, ref: Ref<WebViewControl>) => {
return (
<WebView
style={{
backgroundColor: theme.backgroundColor,
// `backgroundColor: transparent` prevents a white fhash on iOS.
// It seems that `backgroundColor: theme.backgroundColor` does not
// prevent the flash.
backgroundColor: 'transparent',
...(props.style as any),
}}
ref={webviewRef}

View File

@ -28,10 +28,6 @@ interface Props {
onLoadEnd?: ()=> void;
}
const webViewStyle = {
backgroundColor: 'transparent',
};
export default function NoteBodyViewer(props: Props) {
const dialogBoxRef = useRef(null);
const webviewRef = useRef<WebViewControl>(null);
@ -103,8 +99,6 @@ export default function NoteBodyViewer(props: Props) {
<ExtendedWebView
ref={webviewRef}
webviewInstanceId='NoteBodyViewer'
themeId={props.themeId}
style={webViewStyle}
html={html}
injectedJavaScript={injectedJs.join('\n')}
mixedContentMode="always"

View File

@ -18,7 +18,7 @@ export default function useOnMessage(
noteBody: string,
callbacks: MessageCallbacks,
) {
// Dectructure callbacks. Because we have that ({ a: 1 }) !== ({ a: 1 }),
// Destructure callbacks. Because we have that ({ a: 1 }) !== ({ a: 1 }),
// we can expect the `callbacks` variable from the last time useOnMessage was called to
// not equal the current` callbacks` variable, even if the callbacks themselves are the
// same.

View File

@ -75,7 +75,7 @@ export default function useSource(
// If a checkbox in a note is ticked, the body changes, which normally would
// trigger a re-render of this component, which has the unfortunate side
// effect of making the view scroll back to the top. This re-rendering
// however is uncessary since the component is already visually updated via
// however is unnecessary since the component is already visually updated via
// JS. So here, if the note has not changed, we prevent the component from
// updating. This fixes the above issue. A drawback of this is if the note
// is updated via sync, this change will not be displayed immediately.

View File

@ -5,7 +5,7 @@
// NoteEditor.tsx into the webview.
//
// In general, since this file is harder to debug due to the intermediate built
// step, it's better to keep it as light as possible - it shoud just be a light
// step, it's better to keep it as light as possible - it should just be a light
// wrapper to access CodeMirror functionalities. Anything else should be done
// from NoteEditor.tsx.

View File

@ -26,9 +26,8 @@
const initialText = 'Testing...';
const settings = {
katexEnabled: true,
themeData: {
fontSize: 1, // em
fontSize: 12, // px
fontFamily: 'serif',
backgroundColor: 'black',
color: 'white',
@ -40,6 +39,19 @@
color4: '#0ff',
appearance: 'dark',
},
themeId: 0,
spellcheckEnabled: true,
language: 'markdown',
katexEnabled: true,
useExternalSearch: false,
readOnly: false,
keymap: 'default',
automatchBraces: false,
ignoreModifiers: false,
indentWithTabs: false,
};
window.cm = codeMirrorBundle.initCodeMirror(parent, initialText, settings);

View File

@ -69,7 +69,7 @@ const useCss = (editorTheme: Theme) => {
}
/* Hide the save/close icons on small screens. This isn't done in the upstream
js-draw repository partially beause it isn't as well localized as Joplin
js-draw repository partially because it isn't as well localized as Joplin
(icons can be used to suggest the meaning of a button when a translation is
unavailable). */
.toolbar-edge-toolbar:not(.one-row) .toolwidget-tag--save .toolbar-icon,
@ -314,7 +314,6 @@ const ImageEditor = (props: Props) => {
return (
<ExtendedWebView
themeId={props.themeId}
html={html}
injectedJavaScript={injectedJavaScript}
allowFileAccessFromJs={true}

View File

@ -102,7 +102,7 @@ export const createJsDrawEditor = (
saveButton = toolbar.addSaveButton(saveNow);
// Load and save toolbar-realated state (e.g. pen sizes/colors).
// Load and save toolbar-related state (e.g. pen sizes/colors).
restoreToolbarState(toolbar, initialToolbarState);
listenToolbarState(editor, toolbar);

View File

@ -12,7 +12,7 @@ const watchEditorForTemplateChanges = (
if (!editor.image.getAutoresizeEnabled()) {
backgroundSize = editor.getImportExportRect().size;
// Constrain the size: Don't allow an extremely small or extremely large tempalte.
// Constrain the size: Don't allow an extremely small or extremely large template.
// Map components to constrained components.
backgroundSize = backgroundSize.map(component => {
const minDimen = 45;

View File

@ -92,7 +92,7 @@ function useHtml(css: string): string {
.cm-scroller {
overflow: none;
/* Ensure that the editor can be foused by clicking on the lower half of the screen.
/* Ensure that the editor can be focused by clicking on the lower half of the screen.
Don't use 100vh to prevent a scrollbar being present for empty notes. */
min-height: 80vh;
}
@ -488,7 +488,6 @@ function NoteEditor(props: Props, ref: any) {
}}>
<ExtendedWebView
webviewInstanceId='NoteEditor'
themeId={props.themeId}
scrollEnabled={true}
ref={webviewRef}
html={html}

View File

@ -152,7 +152,7 @@ export const SearchPanel = (props: SearchPanelProps) => {
control.setSearchState(newState);
};
// Creates a TextInut with the given parameters
// Creates a TextInput with the given parameters
const createInput = (
placeholder: string, value: string, onChange: OnChangeCallback, autoFocus: boolean,
) => {

View File

@ -64,7 +64,7 @@ class AppNavComponent extends Component<Props, State> {
private keyboardWillChangeFrame = (evt: KeyboardEvent) => {
const windowWidth = Dimensions.get('window').width;
// If the keyboard isn't as wide as the window, the floating keyboard is diabled.
// If the keyboard isn't as wide as the window, the floating keyboard is disabled.
// See https://github.com/facebook/react-native/issues/29473#issuecomment-696658937
this.setState({
floatingKeyboardEnabled: evt.endCoordinates.width < windowWidth,
@ -101,7 +101,7 @@ class AppNavComponent extends Component<Props, State> {
const style = { flex: 1, backgroundColor: theme.backgroundColor };
// When the floating keybaord is enabled, the KeyboardAvoidingView can have a very small
// When the floating keyboard is enabled, the KeyboardAvoidingView can have a very small
// height. Don't use the KeyboardAvoidingView when the floating keyboard is enabled.
// See https://github.com/facebook/react-native/issues/29473
const keyboardAvoidingViewEnabled = !this.state.floatingKeyboardEnabled;

View File

@ -80,7 +80,7 @@ class ConfigScreenComponent extends BaseScreenComponent<ConfigScreenProps, Confi
}
private checkSyncConfig_ = async () => {
// to ignore TLS erros we need to chage the global state of the app, if the check fails we need to restore the original state
// to ignore TLS errors we need to change the global state of the app, if the check fails we need to restore the original state
// this call sets the new value and returns the previous one which we can use later to revert the change
const prevIgnoreTlsErrors = await setIgnoreTlsErrors(this.state.settings['net.ignoreTlsErrors']);
const result = await shared.checkSyncConfig(this, this.state.settings);
@ -257,7 +257,7 @@ class ConfigScreenComponent extends BaseScreenComponent<ConfigScreenProps, Confi
});
}
private handleNavigateToNewScren = async (): Promise<boolean> => {
private handleNavigateToNewScreen = async (): Promise<boolean> => {
await this.promptSaveChanges();
// Continue navigation
@ -306,14 +306,14 @@ class ConfigScreenComponent extends BaseScreenComponent<ConfigScreenProps, Confi
}
BackButtonService.addHandler(this.handleBackButtonPress);
NavService.addHandler(this.handleNavigateToNewScren);
NavService.addHandler(this.handleNavigateToNewScreen);
Dimensions.addEventListener('change', this.updateSidebarWidth);
this.updateSidebarWidth();
}
public componentWillUnmount() {
BackButtonService.removeHandler(this.handleBackButtonPress);
NavService.removeHandler(this.handleNavigateToNewScren);
NavService.removeHandler(this.handleNavigateToNewScreen);
}
private renderButton(key: string, title: string, clickHandler: ()=> void, options: any = null) {

View File

@ -67,13 +67,13 @@ class LogScreenComponent extends BaseScreenComponent<Props, State> {
}
setTimeout(() => {
this.refreshLogTimeout = null;
void this.resfreshLogEntries();
void this.refreshLogEntries();
}, 600);
}
}
public override componentDidMount() {
void this.resfreshLogEntries();
void this.refreshLogEntries();
if (this.props.navigation.state.defaultFilter) {
this.setState({ filter: this.props.navigation.state.defaultFilter });
@ -155,7 +155,7 @@ class LogScreenComponent extends BaseScreenComponent<Props, State> {
return levels;
}
private async resfreshLogEntries(showErrorsOnly: boolean = null) {
private async refreshLogEntries(showErrorsOnly: boolean = null) {
if (showErrorsOnly === null) showErrorsOnly = this.state.showErrorsOnly;
const limit = 1000;
@ -168,7 +168,7 @@ class LogScreenComponent extends BaseScreenComponent<Props, State> {
}
private toggleErrorsOnly() {
void this.resfreshLogEntries(!this.state.showErrorsOnly);
void this.refreshLogEntries(!this.state.showErrorsOnly);
}
private formatLogEntry(item: any) {
@ -224,7 +224,7 @@ class LogScreenComponent extends BaseScreenComponent<Props, State> {
<Button
title={_('Refresh')}
onPress={() => {
void this.resfreshLogEntries();
void this.refreshLogEntries();
}}
/>
</View>

View File

@ -638,7 +638,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
this.scheduleSave();
}
private onPlainEdtiorSelectionChange = (event: NativeSyntheticEvent<any>) => {
private onPlainEditorSelectionChange = (event: NativeSyntheticEvent<any>) => {
this.selection = event.nativeEvent.selection;
};
@ -883,7 +883,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
}
private async attachPhoto_onPress() {
// the selection Limit should be specfied. I think 200 is enough?
// the selection Limit should be specified. I think 200 is enough?
const response: ImagePickerResponse = await launchImageLibrary({ mediaType: 'photo', includeBase64: false, selectionLimit: 200 });
if (response.errorCode) {
@ -938,7 +938,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
if (!resource) {
resource = await this.attachNewDrawing(svgData);
// Set resouce and file path to allow
// Set resource and file path to allow
// 1. subsequent saves to update the resource
// 2. the editor to load from the resource's filepath (can happen
// if the webview is reloaded).
@ -974,7 +974,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
if (this.state.mode === 'edit') {
// Create a new empty drawing and attach it now, before the image editor is opened.
// With the present structure of Note.tsx, the we can't use this.editorRef while
// the image editor is open, and thus can't attach drawings at the cursor locaiton.
// the image editor is open, and thus can't attach drawings at the cursor location.
const resource = await this.attachNewDrawing('');
await this.editDrawing(resource);
} else {
@ -1137,7 +1137,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
// On iOS, it will show "local files", which means certain files saved from the browser
// and the iCloud files, but it doesn't include photos and images from the CameraRoll
//
// On Android, it will depend on the phone, but usually it will allow browing all files and photos.
// On Android, it will depend on the phone, but usually it will allow browsing all files and photos.
buttons.push({ text: _('Attach file'), id: 'attachFile' });
// Disabled on Android because it doesn't work due to permission issues, but enabled on iOS
@ -1228,7 +1228,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
const output: MenuOptionType[] = [];
// The file attachement modules only work in Android >= 5 (Version 21)
// The file attachment modules only work in Android >= 5 (Version 21)
// https://github.com/react-community/react-native-image-picker/issues/606
// As of 2020-10-13, support for attaching images from the gallery is removed
@ -1490,7 +1490,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
// See https://github.com/laurent22/joplin/issues/3041
// IMPORTANT: The TextInput selection is unreliable and cannot be used in a controlled component
// context. In other words, the selection should be considered read-only. For example, if the seleciton
// context. In other words, the selection should be considered read-only. For example, if the selection
// is saved to the state in onSelectionChange and the current text in onChangeText, then set
// back in `selection` and `value` props, it will mostly work. But when typing fast, sooner or
// later the real selection will be different from what is stored in the state, thus making
@ -1508,7 +1508,7 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
multiline={true}
value={note.body}
onChangeText={(text: string) => this.body_changeText(text)}
onSelectionChange={this.onPlainEdtiorSelectionChange}
onSelectionChange={this.onPlainEditorSelectionChange}
blurOnSubmit={false}
selectionColor={theme.textSelectionColor}
keyboardAppearance={theme.keyboardAppearance}

View File

@ -10,12 +10,12 @@
## Configuring the Share Extension
1. Delete *ShareViewController.h* and *ShareViewController.m* from the project. (Select files and right click, then Delete)
2. On the confirmation popup, select Move to Trash
3. Now add *ShareViewController.h* and *ShareViewController.m* from *ShareExtension/Source/ShareExtenstion*. This can be done by right clicking on the *ShareExtension* folder in Xcode and selecting Add Files to "Joplin". Double check that the ShareExtension is checked for Add to targets and click Add.
3. Now add *ShareViewController.h* and *ShareViewController.m* from *ShareExtension/Source/ShareExtension*. This can be done by right clicking on the *ShareExtension* folder in Xcode and selecting Add Files to "Joplin". Double check that the ShareExtension is checked for Add to targets and click Add.
4. Switch over to git and reset the changes done to *ShareExtension/Base.lproj/Maininterface.storyboard* and *ShareExtension/Info.plist*, as Xcode generated new versions of these files and overwrote ours.
5. Now select the ShareExtension Target and go to Signing & Capabilities
6. Click the + Capability and search for App Groups and add it
7. Back in git reset *ShareExtension/ShareExtension.entitlements* as Xcode just overwrote it. Back in Xcode you should see the app group set
8. Now switch to General, just left of Signing & Capabilites
8. Now switch to General, just left of Signing & Capabilities
9. Under Deployment Info, change the iOS version to match the Joplin target version, which is 9.0
## Configuring Joplin

View File

@ -99,6 +99,7 @@
"@types/react-redux": "7.1.33",
"@types/tar-stream": "3.1.3",
"babel-jest": "29.7.0",
"babel-loader": "9.1.3",
"babel-plugin-module-resolver": "4.1.0",
"fs-extra": "11.2.0",
"gulp": "4.0.2",

View File

@ -27,10 +27,10 @@ class BackButtonService {
return this.handlers_.push(handler);
}
static removeHandler(hanlder) {
static removeHandler(handler) {
for (let i = this.handlers_.length - 1; i >= 0; i--) {
const h = this.handlers_[i];
if (h === hanlder) this.handlers_.splice(i, 1);
if (h === handler) this.handlers_.splice(i, 1);
}
}
}

View File

@ -28,6 +28,11 @@ export default class BundledFile {
const config: webpack.Configuration = {
mode,
entry: this.sourceFilePath,
// es5: Have Webpack's generated code target ES5. This doesn't apply to code not
// generated by Webpack.
target: ['web', 'es5'],
output: {
path: this.rootFileDirectory,
filename: `${this.bundleBaseName}.bundle.js`,
@ -46,6 +51,43 @@ export default class BundledFile {
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: (value) => {
const isModuleFile = !!(/node_modules/.exec(value));
// Some libraries don't work with older browsers/WebViews.
// Because Babel transpilation can be slow, we only transpile
// these libraries.
// For now, it's just Replit's CodeMirror-vim library. This library
// uses `a?.b` syntax, which seems to be unsupported in iOS 12 Safari.
const moduleNeedsTranspilation = !!(/.*node_modules.*replit.*\.[mc]?js$/.exec(value));
if (isModuleFile && !moduleNeedsTranspilation) {
return false;
}
const isJsFile = !!(/\.[cm]?js$/.exec(value));
if (isJsFile) {
console.log('Compiling with Babel:', value);
}
return isJsFile;
},
use: {
loader: 'babel-loader',
options: {
cacheDirectory: false,
// Disable using babel.config.js to prevent conflicts with React Native's
// Babel configuration.
babelrc: false,
configFile: false,
presets: [
['@babel/preset-env', { targets: { ios: 12, chrome: 80 } }],
],
},
},
},
],
},
// Increase the minimum size required

View File

@ -5,7 +5,7 @@
import createEditor from './createEditor';
import Setting from '@joplin/lib/models/Setting';
import { forceParsing } from '@codemirror/language';
import loadLangauges from './testUtil/loadLanguages';
import loadLanguages from './testUtil/loadLanguages';
import { expect, describe, it } from '@jest/globals';
import createEditorSettings from './testUtil/createEditorSettings';
@ -33,7 +33,7 @@ describe('createEditor', () => {
const initialText = `${headerLineText}\nThis is a test.`;
const editorSettings = createEditorSettings(Setting.THEME_LIGHT);
await loadLangauges();
await loadLanguages();
const editor = createEditor(document.body, {
initialText,
settings: editorSettings,

View File

@ -3,7 +3,7 @@ import { LanguageDescription, LanguageSupport, StreamLanguage } from '@codemirro
// To allow auto-indent to work in an unrecognised language, we define an
// empty language. Doing so seems to enable auto-indent in code blocks with
// that language.
const defaultLangauge = StreamLanguage.define({
const defaultLanguage = StreamLanguage.define({
token: (stream) => {
stream.next();
return null;
@ -12,7 +12,7 @@ const defaultLangauge = StreamLanguage.define({
const defaultLanguageDescription = LanguageDescription.of({
name: 'default',
support: new LanguageSupport(defaultLangauge),
support: new LanguageSupport(defaultLanguage),
});
export default defaultLanguageDescription;

View File

@ -131,7 +131,7 @@ const computeDecorations = (view: EditorView) => {
const decorations: DecorationDescription[] = [];
// Add a decoration to all lines between the document position [from] up to
// and includeing the position [to].
// and including the position [to].
const addDecorationToLines = (from: number, to: number, decoration: Decoration) => {
let pos = from;
while (pos <= to) {

View File

@ -278,10 +278,10 @@ export const toggleList = (listType: ListType): Command => {
const inBlockQuote = (lineContent !== line.text);
const indentation = lineContent.match(startingSpaceRegex)[0];
const wrongIndentaton = !isIndentationEquivalent(state, indentation, firstLineIndentation);
const wrongIndentation = !isIndentationEquivalent(state, indentation, firstLineIndentation);
// If not the right list level,
if (inBlockQuote !== firstLineInBlockQuote || wrongIndentaton) {
if (inBlockQuote !== firstLineInBlockQuote || wrongIndentation) {
// We'll be starting a new list
listItemCounter = 1;
continue;

View File

@ -454,7 +454,7 @@ export const toggleRegionFormatGlobally = (
const startMatch = blockSpec.matcher.start.exec(fromLineText);
const stopMatch = blockSpec.matcher.end.exec(toLineText);
if (startMatch && stopMatch) {
// Get start and stop indicies for the starting and ending matches
// Get start and stop indices for the starting and ending matches
const [fromMatchFrom, fromMatchTo] = getMatchEndPoints(startMatch, fromLine, inBlockQuote);
const [toMatchFrom, toMatchTo] = getMatchEndPoints(stopMatch, toLine, inBlockQuote);

View File

@ -50,7 +50,7 @@ describe('customEditorCompletion', () => {
expect(completionStatus(editor.state)).toBe(null);
});
test('should show langaugeData completions when languageData-based autocomplete is enabled', async () => {
test('should show languageData completions when languageData-based autocomplete is enabled', async () => {
const editorControl = createEditorControl('');
const completion = completeFromList(['function']);

View File

@ -5,7 +5,7 @@ import { SelectionRange, EditorSelection, EditorState, Extension } from '@codemi
import { EditorView } from '@codemirror/view';
import { MarkdownMathExtension } from '../markdown/markdownMathParser';
import forceFullParse from './forceFullParse';
import loadLangauges from './loadLanguages';
import loadLanguages from './loadLanguages';
// Creates and returns a minimal editor with markdown extensions. Waits to return the editor
// until all syntax tree tags in `expectedSyntaxTreeTags` exist.
@ -15,7 +15,7 @@ const createTestEditor = async (
expectedSyntaxTreeTags: string[],
extraExtensions: Extension[] = [],
): Promise<EditorView> => {
await loadLangauges();
await loadLanguages();
const editor = new EditorView({
doc: initialText,

View File

@ -1,10 +1,10 @@
import allLanguages from '../markdown/codeBlockLanguages/allLanguages';
// Ensure languages we use are loaded. Without this, tests may randomly fail (LanguageDescriptions
// are loaded asyncronously, in the background).
const loadLangauges = async () => {
// are loaded asynchronously, in the background).
const loadLanguages = async () => {
for (const lang of allLanguages) {
await lang.load();
}
};
export default loadLangauges;
export default loadLanguages;

View File

@ -99,8 +99,8 @@ export interface EditorControl {
}
export enum EditorLanguageType {
Markdown,
Html,
Markdown = 'markdown',
Html = 'html',
}
export enum EditorKeymap {

View File

@ -40,6 +40,8 @@ export { default as Tokenizer } from "./Tokenizer";
import * as ElementType from "domelementtype";
export { ElementType };
// cSpell:disable
/**
* List of all events that the parser emits.
*
@ -60,6 +62,8 @@ export const EVENTS = {
end: 0
};
// cSpell:enable
/*
All of the following exports exist for backwards-compatibility.
They should probably be removed eventually.

View File

@ -181,7 +181,7 @@ export interface ExportContext {
options: ExportOptions;
/**
* You can attach your own custom data using this propery - it will then be passed to each event handler, allowing you to keep state from one event to the next.
* You can attach your own custom data using this property - it will then be passed to each event handler, allowing you to keep state from one event to the next.
*/
userData?: any;
}

View File

@ -11,5 +11,6 @@
"keywords": [],
"categories": [],
"screenshots": [],
"icons": {}
}
"icons": {},
"promo_tile": {}
}

View File

@ -278,6 +278,7 @@ class BaseModel {
limit: options.limit,
order: options.order as any,
page: 1,
caseInsensitive: options.caseInsensitive,
})}`;
}

View File

@ -126,12 +126,12 @@ describe('EventDispatcher', () => {
const dispatcher = new Dispatcher();
let pass = false;
dispatcher.on('Evnt', () => {
dispatcher.on('Event', () => {
pass = true;
});
expect(pass).toBe(false);
dispatcher.dispatch('Evnt');
dispatcher.dispatch('Event');
expect(pass).toBe(true);
});
});

View File

@ -25,7 +25,7 @@ export default class EventDispatcher<EventKeyType extends string|symbol|number,
this.listeners[eventName].push(callback);
return {
// Retuns false if the listener has already been removed, true otherwise.
// Returns false if the listener has already been removed, true otherwise.
remove: (): boolean => {
const originalListeners = this.listeners[eventName];
this.off(eventName, callback);

View File

@ -36,7 +36,7 @@ export default class HtmlToMd {
disableEscapeContent: 'disableEscapeContent' in options ? options.disableEscapeContent : false,
};
if (options.convertEmbeddedPdfsToLinks) {
// Turndown ignores empty <object> tags, so we need to handle this case seperately
// Turndown ignores empty <object> tags, so we need to handle this case separately
// https://github.com/mixmark-io/turndown/issues/293#issuecomment-588984202
turndownOpts.blankReplacement = (content: string, node: any) => {
if (node.matches('object')) {
@ -52,7 +52,7 @@ export default class HtmlToMd {
const pdfRule = {
filter: ['embed', 'object'],
replacement: function(_content: string, node: any, _options: any) {
// We are setting embedded_pdf as name so that we can later distingish them from normal links and create resources for them.
// We are setting embedded_pdf as name so that we can later distinguish them from normal links and create resources for them.
if (node.matches('embed') && node.getAttribute('src') && pdfUrlRegex.test(node.getAttribute('src'))) {
return `[embedded_pdf](${node.getAttribute('src')})`;
} else if (node.matches('object') && node.getAttribute('data') && pdfUrlRegex.test(node.getAttribute('data'))) {

View File

@ -21,7 +21,7 @@ describe('InMemoryCache', () => {
it('should expire values', async () => {
const cache = new InMemoryCache();
// Check that the value is udefined once the cache has expired
// Check that the value is undefined once the cache has expired
cache.setValue('test', 'something', 500);
expect(cache.value('test')).toBe('something');
await time.msleep(510);

View File

@ -118,7 +118,7 @@ export default class SyncTargetOneDrive extends BaseSyncTarget {
public async initSynchronizer() {
try {
if (!(await this.isAuthenticated())) throw new Error('User is not authentified');
if (!(await this.isAuthenticated())) throw new Error('User is not authenticated');
return new Synchronizer(this.db(), await this.fileApi(), Setting.value('appType'));
} catch (error) {
BaseSyncTarget.dispatch({ type: 'SYNC_REPORT_UPDATE', report: { errors: [error] } });

View File

@ -670,7 +670,7 @@ export default class Synchronizer {
// up in this place either, because the action
// cannot be createRemote (because the
// resource has not been created locally) or
// updateRemote (because a resouce cannot be
// updateRemote (because a resource cannot be
// modified locally unless the blob is present
// too).
//
@ -1076,7 +1076,7 @@ export default class Synchronizer {
logger.info(error.message);
if (error.code === 'failSafe' || error.code === 'lockError') {
// Get the message to display on UI, but not in testing to avoid poluting stdout
// Get the message to display on UI, but not in testing to avoid polluting stdout
if (!shim.isTestingEnv()) this.progressReport_.errors.push(error.message);
this.logLastRequests();
}

View File

@ -187,7 +187,7 @@ export default class TaskQueue {
// In general it's not a big issue if some tasks are still running because
// it won't call anything unexpected in caller code, since the caller has
// to explicitely retrieve the results
// to explicitly retrieve the results
const startTime = Date.now();
while (Object.keys(this.processingTasks_).length) {
await time.sleep(0.1);

View File

@ -58,7 +58,7 @@ class WelcomeUtils {
const folderAssets = welcomeAssets.folders;
const tempDir = Setting.value('resourceDir');
// Actually we don't really support mutiple folders at this point, because not needed
// Actually we don't really support multiple folders at this point, because not needed
for (let i = 0; i < folderAssets.length; i++) {
const folder = await Folder.save({ title: _('Welcome!') });
if (!output.defaultFolderId) output.defaultFolderId = folder.id;

View File

@ -232,7 +232,7 @@ export const settingsSections = createSelector(
})));
}
// Ideallly we would also check if the user was able to synchronize
// Ideally we would also check if the user was able to synchronize
// but we don't have a way of doing that besides making a request to Joplin Cloud
const syncTargetIsJoplinCloud = settings['sync.target'] === SyncTargetRegistry.nameToId('joplinCloud');
if (syncTargetIsJoplinCloud) {

View File

@ -224,7 +224,7 @@ export default class Database {
if (type === 'fieldType') {
if (s) s = s.toUpperCase();
if (s === 'INTEGER') s = 'INT';
if (!(`TYPE_${s}` in this)) throw new Error(`Unkonwn fieldType: ${s}`);
if (!(`TYPE_${s}` in this)) throw new Error(`Unknown fieldType: ${s}`);
return (this as any)[`TYPE_${s}`];
}
if (type === 'syncTarget') {

View File

@ -27,6 +27,7 @@ export const waitForElement = async (parent: any, id: string): Promise<any> => {
// Imported from https://github.com/Moh-Snoussi/keyboard-event-key-type
// -----------------------------------------------------------------------
// cSpell:disable
type NumericKeypadKeys = 'Decimal' | 'Key11' | 'Key12' | 'Multiply' | 'Add' | 'Clear' | 'Divide' | 'Subtract' | 'Separator' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
type UpperAlpha = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
type LowerAlpha = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
@ -51,3 +52,4 @@ type KoreanKeyboardsOnly = 'HangulMode' | 'HanjaMode' | 'JunjaMode';
type SpecialValueKey = 'Unidentified';
export declare type KeyboardEventKey = SpecialValueKey | ModifierKeys | WhitespaceKeys | NavigationKeys | EditingKeys | UIKeys | DeviceKeys | IMECompositionKeys | LinuxDeadKeys | FunctionKeys | PhoneKeys | MultimediaKeys | TVControlKeys | MediaControllerKeys | SpeechRecognitionKeys | DocumentKeys | ApplicationSelectorKeys | BrowserControlKeys | NumericKeypadKeys | UpperAlpha | LowerAlpha | KoreanKeyboardsOnly;
// cSpell:enable

View File

@ -58,7 +58,7 @@ function requestCanBeRepeated(error: any) {
// permission issue, which won't be fixed by repeating the request.
if (errorCode === 403 || errorCode === 401) return false;
// The target is explicitely rejecting the item so repeating wouldn't make a difference.
// The target is explicitly rejecting the item so repeating wouldn't make a difference.
if (errorCode === 'rejectedByTarget' || errorCode === 'isReadOnly') return false;
// We don't repeat failSafe errors because it's an indication of an issue at the
@ -131,7 +131,7 @@ class FileApi {
// This can be true when the sync target timestamps (updated_time) provided
// in the delta call are guaranteed to be accurate. That requires
// explicitely setting the timestamp, which is not done anymore on any sync
// explicitly setting the timestamp, which is not done anymore on any sync
// target as it wasn't accurate (for example, the file system can't be
// relied on, and even OneDrive for some reason doesn't guarantee that the
// timestamp you set is what you get back).
@ -297,7 +297,7 @@ class FileApi {
return result;
}
// Deprectated
// Deprecated
public setTimestamp(path: string, timestampMs: number) {
logger.debug(`setTimestamp ${this.fullPath(path)}`);
return tryAndRepeat(() => this.driver_.setTimestamp(this.fullPath(path), timestampMs), this.requestRepeatCount());
@ -347,13 +347,13 @@ class FileApi {
return tryAndRepeat(() => this.driver_.delete(this.fullPath(path)), this.requestRepeatCount());
}
// Deprectated
// Deprecated
public move(oldPath: string, newPath: string) {
logger.debug(`move ${this.fullPath(oldPath)} => ${this.fullPath(newPath)}`);
return tryAndRepeat(() => this.driver_.move(this.fullPath(oldPath), this.fullPath(newPath)), this.requestRepeatCount());
}
// Deprectated
// Deprecated
public format() {
return tryAndRepeat(() => this.driver_.format(), this.requestRepeatCount());
}

View File

@ -117,7 +117,7 @@ function enexXmlToHtml_(stream, resources) {
}
// If the resource does not appear among the note's resources, it
// means it's an attachement. It will be appended along with the
// means it's an attachment. It will be appended along with the
// other remaining resources at the bottom of the markdown text.
if (resource && !!resource.id) {
section.lines = addResourceTag(section.lines, resource, nodeAttributes);

View File

@ -303,8 +303,8 @@ function isWhiteSpace(c: string): boolean {
return c === '\n' || c === '\r' || c === '\v' || c === '\f' || c === '\t' || c === ' ';
}
// Like QString::simpified(), except that it preserves non-breaking spaces (which
// Evernote uses for identation, etc.)
// Like QString::simplified(), except that it preserves non-breaking spaces (which
// Evernote uses for indentation, etc.)
function simplifyString(s: string): string {
let output = '';
let previousWhite = false;
@ -905,7 +905,7 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[], tasks: Extra
// <!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export2.dtd">
// <en-export export-date="20161221T203133Z" application="Evernote/Windows" version="6.x">
// <note>
// <title>Commande</title>
// <title>Command</title>
// <content>
// <![CDATA[
// <?xml version="1.0" encoding="UTF-8"?>
@ -951,7 +951,7 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[], tasks: Extra
}
// If the resource does not appear among the note's resources, it
// means it's an attachement. It will be appended along with the
// means it's an attachment. It will be appended along with the
// other remaining resources at the bottom of the markdown text.
if (resource && !!resource.id) {
section.lines = addResourceTag(section.lines, `:/${resource.id}`, resource.mime, {
@ -1080,7 +1080,7 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[], tasks: Extra
// it's interactive bits) and it's not user-generated content such as a URL that would appear in a comment.
// So in this case, we still want to preserve the information but display it in a discreet way as a simple [L].
// Need to pop everything inside the current [] because it can only be special chars that we don't want (they would create uncessary newlines)
// Need to pop everything inside the current [] because it can only be special chars that we don't want (they would create unnecessary newlines)
for (let i = section.lines.length - 1; i >= 0; i--) {
if (section.lines[i] !== '[') {
section.lines.pop();

View File

@ -631,7 +631,7 @@ export const parsePluralForm = (form: string): ParsePluralFormFunction => {
'return (plural === true ? 1 : plural ? plural : 0);',
].join('\n');
// eslint-disable-next-line no-new-func -- There's a regex to check the form but it's still slighlty unsafe, eventually we should automatically generate all the functions in advance in build-translations.ts
// eslint-disable-next-line no-new-func -- There's a regex to check the form but it's still slightly unsafe, eventually we should automatically generate all the functions in advance in build-translations.ts
return (new Function('n', code)) as ParsePluralFormFunction;
};

View File

@ -1667,6 +1667,9 @@
"Media player, math, diagrams, table of contents": [
""
],
"Minimise": [
""
],
"Missing Master Keys": [
"المفاتيح الرئيسة مفقودة"
],
@ -1784,7 +1787,7 @@
"Nord": [
"Nord"
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"لا يمكن المصادقة باستخدام %s. يرجى التزويد بأي من بيانات اعتماد الدخول المفقودة."
],
"Not downloaded": [

View File

@ -1256,6 +1256,9 @@
"Media player, math, diagrams, table of contents": [
""
],
"Minimise": [
""
],
"Missing Master Keys": [
"Липсващи главни ключове"
],
@ -1355,7 +1358,7 @@
"Nord": [
""
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"Не сме оторизирани за %s. Моля въведете липсващите оторизационни данни."
],
"Not downloaded": [

View File

@ -1262,6 +1262,9 @@
"Media player, math, diagrams, table of contents": [
""
],
"Minimise": [
""
],
"Missing Master Keys": [
"Nedostaju glavni ključevi"
],
@ -1361,7 +1364,7 @@
"Nord": [
"Nord"
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"Nije ovjereno sa %s. Molimo unesite podatke koji nedostaju."
],
"Not downloaded": [

View File

@ -1709,6 +1709,9 @@
"Media player, math, diagrams, table of contents": [
""
],
"Minimise": [
""
],
"Missing keys": [
"Claus que falten"
],
@ -1835,7 +1838,7 @@
"Nord": [
"Nord"
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"No esteu autenticats amb %s. Proporcioneu les credencials que falten."
],
"Not downloaded": [

View File

@ -1673,6 +1673,9 @@
"Media player, math, diagrams, table of contents": [
""
],
"Minimise": [
""
],
"Missing keys": [
"Chybějící klíče"
],
@ -1799,7 +1802,7 @@
"Nord": [
"Nord"
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"Nepřihlášeno k %s. Prosím vyplňte chybějící přihlašovací údaje."
],
"Not downloaded": [

View File

@ -1745,6 +1745,9 @@
"Media player, math, diagrams, table of contents": [
"Medieafspiller, matematik, diagrammer, indholdsfortegnelse"
],
"Minimise": [
""
],
"Missing keys": [
"Manglende nøgler"
],
@ -1871,7 +1874,7 @@
"Nord": [
"Nord"
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"Ikke godkendt med %s. Angiv venligst eventuelle manglende legitimationsoplysninger."
],
"Not downloaded": [

View File

@ -63,7 +63,7 @@
"%s = %s (%s)"
],
"%s is not optimised for synchronising many small files so your initial synchronisation will be slow.": [
""
"%s ist nicht für die Synchronisation kleiner Dateien optimiert, wodurch die erste Synchronisation langsam sein wird."
],
"%s: %d": [
"%s: %d"
@ -342,7 +342,7 @@
"Durchsuchen ..."
],
"Built-in": [
""
"Eingebaut"
],
"Bulleted List": [
"Aufzählung"
@ -471,7 +471,7 @@
"Auswahlliste schließen"
],
"Close the application, then delete your profile in \"%s\", and start the application again. Make sure you create a backup first by exporting all your notes as JEX.": [
""
"Schließe die Anwendung, lösche dein Profil in „%s“ und starte die Anwendung erneut. Stelle sicher, dass du zuerst ein Backup aller Notizen als JEX exportierst."
],
"Close Window": [
"Fenster schließen"
@ -787,7 +787,7 @@
"Erweiterung „%s“ löschen?"
],
"Delete profile \"%s\"": [
"Lösche Profil \"%s\""
"Lösche Profil „%s“"
],
"Delete selected notes": [
"Ausgewählte Notizen löschen"
@ -1075,7 +1075,7 @@
"Notizenverlauf aktivieren"
],
"Enable optical character recognition (OCR)": [
""
"Aktiviere die optische Zeichenerkennung (OCR)"
],
"Enable PDF viewer": [
"PDF-Betrachter aktivieren"
@ -1170,6 +1170,12 @@
"Evernote Export File (as Markdown)": [
"Evernote Export-Datei (als Markdown)"
],
"Evernote Export Files (Directory, as HTML)": [
"Evernote Export-Dateien (Verzeichnis, als HTML)"
],
"Evernote Export Files (Directory, as Markdown)": [
"Evernote Export-Dateien (Verzeichnis, als Markdown)"
],
"Exits the application.": [
"Beendet die Anwendung."
],
@ -1242,6 +1248,9 @@
"File system": [
"Dateisystem"
],
"Filter": [
"Filter"
],
"Filter tags": [
"Tags filtern"
],
@ -1360,6 +1369,9 @@
"Hide advanced": [
"Erweitertes verstecken"
],
"Hide Advanced Settings": [
"Erweiterte Einstellungen verstecken"
],
"Hide disabled": [
"Deaktiviertes verstecken"
],
@ -1439,7 +1451,7 @@
"Dazu muss dein gesamter Datensatz verschlüsselt und erneut synchronisiert werden. Starte diese Prozedur daher am besten nachts.\n\nBeachte dazu folgende Hinweise:\n\n1. Synchronisiere alle deine Geräte.\n2. Klicke auf „%s“.\n3. Lass es komplett durch laufen. Vermeide während der Ausführung das Ändern von Notizen auf anderen Geräten, um Konflikte zu vermeiden.\n4. Sobald die Synchronisierung auf diesem Gerät abgeschlossen ist, synchronisiere alle anderen Geräte und lass es komplett durchlaufen.\n\nWichtig: Du musst diese Prozedur nur EINMAL auf einem Gerät starten."
],
"In order to synchronise, please upgrade your application to version %s+": [
""
"Um zu synchronisieren, aktualisiere die Anwendung bitte auf Version %s+"
],
"In order to use file system synchronisation your permission to write to external storage is required.": [
"Deine Erlaubnis, auf externen Speicher zu schreiben, ist notwendig, um Synchronisation mit dem Dateisystem zu verwenden."
@ -1748,6 +1760,9 @@
"Media player, math, diagrams, table of contents": [
"Medienspieler, Mathematik, Diagramme, Inhaltsverzeichnis"
],
"Minimise": [
""
],
"Missing keys": [
"Fehlende Schlüssel"
],
@ -1874,7 +1889,7 @@
"Nord": [
"Nord"
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"Keine Authentifizierung mit %s. Gib bitte alle fehlenden Zugangsdaten an."
],
"Not downloaded": [
@ -2399,12 +2414,18 @@
"Search for...": [
"Suche nach..."
],
"Search hidden": [
"Suche versteckt"
],
"Search in all the notes": [
"Alle Notizen durchsuchen"
],
"Search in current note": [
"Aktuelle Notiz durchsuchen"
],
"Search shown": [
"Suche angezeigt"
],
"Search...": [
"Suchen ..."
],
@ -2547,10 +2568,10 @@
"Solarisiert hell"
],
"Some attachments could not be downloaded. Please try to download them again.": [
""
"Manche Anhänge konnten nicht heruntergeladen werden. Bitte versuche, sie erneut herunterzuladen."
],
"Some attachments need to be downloaded. Set the attachment download mode to \"always\" and try again.": [
""
"Manche Anhänge müssen heruntergeladen werden. Setze das Verhalten für das Herunterladen von Anhängen auf „Immer“ und versuche es erneut."
],
"Some items cannot be decrypted.": [
"Einige Elemente können nicht entschlüsselt werden."
@ -2561,6 +2582,9 @@
"Some items cannot be synchronised. Press for more info.": [
"Manche Einträge können nicht synchronisiert werden. Drücke um mehr Informationen zu erhalten."
],
"Some items could not be synchronised. Please try to synchronise them first.": [
"Manche Einträge konnten nicht synchronisiert werden. Bitte versuche zuerst, diese zu synchronisieren."
],
"Sort notebooks by": [
"Notizbücher sortieren nach"
],
@ -2774,6 +2798,9 @@
"Thank you! Your Joplin Cloud account is now setup and ready to use.": [
"Vielen Dank! Das Joplin Cloud-Konto ist nun eingerichtet und einsatzbereit."
],
"The [Web Clipper](%s) is a browser extension that allows you to save web pages and screenshots from your browser.": [
"Der [Web Clipper](%s) ist eine Browser-Erweiterung, welche dir erlaubt, Webseiten und Bildschirmfotos aus deinem Browser zu speichern."
],
"The active profile cannot be deleted. Switch to a different profile and try again.": [
"Das aktive Profil kann nicht gelöscht werden. Bitte wechsle in ein anderes Profil und versuche es erneut."
],
@ -2819,6 +2846,10 @@
"The factor property sets how the item will grow or shrink to fit the available space in its container with respect to the other items. Thus an item with a factor of 2 will take twice as much space as an item with a factor of 1.Restart app to see changes.": [
"Die Faktor-Eigenschaft legt fest, wie der Artikel wächst oder schrumpft, um dem verfügbaren Platz in seinem Container in Bezug auf die anderen Artikel zu entsprechen. Ein Element mit dem Faktor 2 benötigt also doppelt so viel Platz wie ein Element mit dem Faktor 1. Starte die App neu, um Änderungen zu sehen."
],
"The following attachment matches your search query:": [
"Der folgende Anhang entspricht deiner Suchanfrage:",
"Die folgenden Anhänge entsprechen deiner Suchanfrage:"
],
"The following attachments are being watched for changes:": [
"Die folgenden Anhänge werden auf Änderungen überwacht:"
],
@ -2856,7 +2887,7 @@
"Der Empfänger konnte nicht von der Liste entfernt werden. Bitte versuche es erneut.\n\nDer Fehler war: „%s“"
],
"The sync target cannot be changed for the following reason: %s\n\nIf the issue cannot be resolved, you may need to clear your data first by following these instructions:\n\n%s": [
""
"Das Synchronisationsziel konnte aus folgendem Grund nicht geändert werden: %s\n\nFalls der Fehler nicht behoben werden kann, musst du möglicherweise zuerst deine Daten löschen, indem du die folgenden Anweisungen befolgst:\n\n%s"
],
"The sync target needs to be upgraded before Joplin can sync. The operation may take a few minutes to complete and the app needs to be restarted. To proceed please click on the link.": [
"Das Synchronisationsziel muss aktualisiert werden, bevor Joplin synchronisiert werden kann. Der Vorgang kann einige Minuten dauern, und die App muss neu gestartet werden. Um fortzufahren, klicke bitte auf den Link."
@ -2919,7 +2950,7 @@
"Diese Erweiterungen erweitern den Markdown-Renderer um zusätzliche Funktionen. Bitte beachte, dass diese Funktionen zwar nützlich sein können, es sich dabei jedoch nicht um Standard-Markdown handelt und die meisten von ihnen daher nur in Joplin funktionieren. Außerdem sind einige von ihnen *inkompatibel* mit dem WYSIWYG-Editor. Wenn du eine Notiz, die eine dieser Erweiterungen verwendet, in diesem Editor öffnest, verlierst du die Formatierung der Erweiterung. Es ist unten angegeben, welche Erweiterungen mit dem WYSIWYG-Editor kompatibel sind oder nicht."
],
"This allows another user to share a notebook with you, and you can then both collaborate on it. It does not however allow you to share a notebook with someone else, unless you have the feature \"%s\".": [
"Dadurch können andere Nutzer ein Notizbuch zur gemeinsamen Bearbeitung mit dir teilen. Allerdings kannst du keine Notizbücher mit anderen teilen, wenn du die Funktion \"%s\" nicht hast."
"Dadurch können andere Nutzer ein Notizbuch zur gemeinsamen Bearbeitung mit dir teilen. Allerdings kannst du keine Notizbücher mit anderen teilen, wenn du die Funktion „%s“ nicht hast."
],
"This attachment is not downloaded or not decrypted yet": [
"Dieser Anhang wurde noch nicht heruntergeladen oder entschlüsselt"
@ -3108,7 +3139,7 @@
"Rückgängig"
],
"Uninstall and reinstall the application. Make sure you create a backup first by exporting all your notes as JEX from the desktop application.": [
""
"Deinstalliere die Anwendung und installieren sie dann neu. Stelle sicher, dass du zuerst ein Backup erstellst, indem du alle Notizen als JEX aus der Desktop-Anwendung exportierst."
],
"Unknown flag: %s": [
"Unbekanntes Argument: %s"
@ -3282,7 +3313,7 @@
"Wenn eine neue Aufgabe erstellt wird:"
],
"When enabled, the application will scan your attachments and extract the text from it. This will allow you to search for text in these attachments.": [
""
"Wenn aktiviert, wird die Anwendung deine Anhänge einlesen und Text aus ihnen extrahieren. Dies wird dir ermöglichen, nach Text innerhalb dieser Anhänge zu suchen."
],
"Window unresponsive.": [
"Fenster antwortet nicht."

View File

@ -1748,6 +1748,9 @@
"Media player, math, diagrams, table of contents": [
"Πολυμέσα, μαθηματικές παραστάσεις, διαγράμματα, πίνακας περιεχομένων"
],
"Minimise": [
""
],
"Missing keys": [
"Απουσία κλειδιών"
],
@ -1874,7 +1877,7 @@
"Nord": [
"Nord"
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"Δεν έγινε επαλήθευση με το %s. Παρακαλώ καταχωρίστε τα διαπιστευτήρια που λείπουν."
],
"Not downloaded": [

View File

@ -101,6 +101,9 @@
"&View": [
""
],
"&Window": [
""
],
"(%s)": [
""
],
@ -1760,6 +1763,9 @@
"Media player, math, diagrams, table of contents": [
""
],
"Minimise": [
""
],
"Missing keys": [
""
],
@ -1886,7 +1892,7 @@
"Nord": [
""
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
""
],
"Not downloaded": [

View File

@ -101,6 +101,9 @@
"&View": [
""
],
"&Window": [
""
],
"(%s)": [
""
],
@ -1760,6 +1763,9 @@
"Media player, math, diagrams, table of contents": [
""
],
"Minimise": [
""
],
"Missing keys": [
""
],
@ -1886,7 +1892,7 @@
"Nord": [
""
],
"Not authentified with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials.": [
"Not authenticated with %s. Please provide any missing credentials."
],
"Not downloaded": [

Some files were not shown because too many files have changed in this diff Show More