diff --git a/.eslintignore b/.eslintignore index 77b8d0ac4..f068e85e8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -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 diff --git a/.github/scripts/run_ci.sh b/.github/scripts/run_ci.sh index cdeca0421..6db4364ad 100755 --- a/.github/scripts/run_ci.sh +++ b/.github/scripts/run_ci.sh @@ -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 diff --git a/.gitignore b/.gitignore index 3a4304426..e8edeb8f0 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.yarn/patches/husky-npm-3.1.0-5cc13e4e34.patch b/.yarn/patches/husky-npm-3.1.0-5cc13e4e34.patch new file mode 100644 index 000000000..8c5a1e0d6 --- /dev/null +++ b/.yarn/patches/husky-npm-3.1.0-5cc13e4e34.patch @@ -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; + } + }); diff --git a/README.md b/README.md index 6bf0e1c8f..6ff4ca106 100644 --- a/README.md +++ b/README.md @@ -39,11 +39,12 @@ Please see the [donation page](https://github.com/laurent22/joplin/blob/dev/read | | | | | | :---: | :---: | :---: | :---: | -|
[avanderberg](https://github.com/avanderberg) |
[chr15m](https://github.com/chr15m) |
[CyberXZT](https://github.com/CyberXZT) |
[dbrandonjohnson](https://github.com/dbrandonjohnson) | -|
[dchecks](https://github.com/dchecks) |
[fats](https://github.com/fats) |
[Galliver7](https://github.com/Galliver7) |
[Hegghammer](https://github.com/Hegghammer) | -|
[jknowles](https://github.com/jknowles) |
[KentBrockman](https://github.com/KentBrockman) |
[konishi-t](https://github.com/konishi-t) |
[marcdw1289](https://github.com/marcdw1289) | -|
[matmoly](https://github.com/matmoly) |
[maxtruxa](https://github.com/maxtruxa) |
[mu88](https://github.com/mu88) |
[saarantras](https://github.com/saarantras) | -|
[sif](https://github.com/sif) |
[taskcruncher](https://github.com/taskcruncher) |
[tateisu](https://github.com/tateisu) | | +|
[andypiper](https://github.com/andypiper) |
[avanderberg](https://github.com/avanderberg) |
[chr15m](https://github.com/chr15m) |
[CyberXZT](https://github.com/CyberXZT) | +|
[dbrandonjohnson](https://github.com/dbrandonjohnson) |
[dchecks](https://github.com/dchecks) |
[fats](https://github.com/fats) |
[Galliver7](https://github.com/Galliver7) | +|
[Hegghammer](https://github.com/Hegghammer) |
[jamesandariese](https://github.com/jamesandariese) |
[jknowles](https://github.com/jknowles) |
[KentBrockman](https://github.com/KentBrockman) | +|
[konishi-t](https://github.com/konishi-t) |
[marcdw1289](https://github.com/marcdw1289) |
[matmoly](https://github.com/matmoly) |
[maxtruxa](https://github.com/maxtruxa) | +|
[mu88](https://github.com/mu88) |
[saarantras](https://github.com/saarantras) |
[sif](https://github.com/sif) |
[taskcruncher](https://github.com/taskcruncher) | +|
[tateisu](https://github.com/tateisu) | | | | # Community diff --git a/cspell.json b/cspell.json index fb618b0fd..da09f745e 100644 --- a/cspell.json +++ b/cspell.json @@ -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" + ] } diff --git a/lint-staged.config.js b/lint-staged.config.js index ec2637268..4b350298d 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -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', }; diff --git a/package.json b/package.json index fe935fdee..694d34f0e 100644 --- a/package.json +++ b/package.json @@ -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" } } diff --git a/packages/app-cli/app/command-apidoc.ts b/packages/app-cli/app/command-apidoc.ts index 4d4f0d3fb..2b794dc5b 100644 --- a/packages/app-cli/app/command-apidoc.ts +++ b/packages/app-cli/app/command-apidoc.ts @@ -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('---- | -----'); diff --git a/packages/app-cli/app/command-sync.ts b/packages/app-cli/app/command-sync.ts index 468752aa0..f6f90c4ea 100644 --- a/packages/app-cli/app/command-sync.ts +++ b/packages/app-cli/app/command-sync.ts @@ -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; } diff --git a/packages/app-cli/tests/services/keychain/KeychainService.ts b/packages/app-cli/tests/services/keychain/KeychainService.ts index cff8d3d86..3881931e0 100644 --- a/packages/app-cli/tests/services/keychain/KeychainService.ts +++ b/packages/app-cli/tests/services/keychain/KeychainService.ts @@ -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'); diff --git a/packages/app-clipper/background.js b/packages/app-clipper/background.js index 295d775e6..8fec06044 100644 --- a/packages/app-clipper/background.js +++ b/packages/app-clipper/background.js @@ -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, diff --git a/packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.tsx b/packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.tsx index 1a54cf5c9..350a858ac 100644 --- a/packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.tsx +++ b/packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.tsx @@ -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); } } }; diff --git a/packages/app-desktop/gui/MainScreen/MainScreen.tsx b/packages/app-desktop/gui/MainScreen/MainScreen.tsx index bd81cf53a..bb9e73932 100644 --- a/packages/app-desktop/gui/MainScreen/MainScreen.tsx +++ b/packages/app-desktop/gui/MainScreen/MainScreen.tsx @@ -237,7 +237,7 @@ class MainScreenComponent extends React.Component { 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 { 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. diff --git a/packages/app-desktop/gui/MainScreen/commands/setTags.ts b/packages/app-desktop/gui/MainScreen/commands/setTags.ts index 494bf1311..46b004b6f 100644 --- a/packages/app-desktop/gui/MainScreen/commands/setTags.ts +++ b/packages/app-desktop/gui/MainScreen/commands/setTags.ts @@ -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' }); }); diff --git a/packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.test.ts b/packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.test.ts new file mode 100644 index 000000000..a9403eb65 --- /dev/null +++ b/packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.test.ts @@ -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 = { + 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 = { + 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 = { + 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'); + + }); +}); diff --git a/packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.ts b/packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.ts index f52aaf8d0..8d9dcd452 100644 --- a/packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.ts +++ b/packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.ts @@ -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(', '); }, }; diff --git a/packages/app-desktop/gui/MenuBar.tsx b/packages/app-desktop/gui/MenuBar.tsx index aa24c2fb8..c96506979 100644 --- a/packages/app-desktop/gui/MenuBar.tsx +++ b/packages/app-desktop/gui/MenuBar.tsx @@ -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 - // will open this menu. It's needed becase electron + // 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: [{ diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.ts b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.ts index 86002e236..6289d8419 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.ts +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.ts @@ -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 diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts index 5ea54beb6..942c03106 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts @@ -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); diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollHandler.ts b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollHandler.ts index 1a1443502..d1b5d8ad5 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollHandler.ts +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollHandler.ts @@ -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 diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/CodeMirror.tsx b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/CodeMirror.tsx index 9174523c0..5b9ded4cf 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/CodeMirror.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/CodeMirror.tsx @@ -507,7 +507,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: ForwardedRef { 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() : ''; diff --git a/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx b/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx index de9185b38..3176a01cf 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx @@ -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, }; diff --git a/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.test.ts b/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.test.ts index 0d2b16734..6b6a78443 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.test.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.test.ts @@ -38,7 +38,7 @@ describe('clipboardUtils', () => { expect(copyableContent.html).toEqual(`
`); }); - 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'; diff --git a/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.ts b/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.ts index 99660398f..2e28da830 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.ts @@ -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) => { diff --git a/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts b/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts index 96a330dc8..11e5faae8 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts @@ -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(0); + const [formNoteRefreshScheduled, setFormNoteRefreshScheduled] = useState(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 diff --git a/packages/app-desktop/gui/NoteList/utils/useScroll.ts b/packages/app-desktop/gui/NoteList/utils/useScroll.ts index feecbf41f..450569b79 100644 --- a/packages/app-desktop/gui/NoteList/utils/useScroll.ts +++ b/packages/app-desktop/gui/NoteList/utils/useScroll.ts @@ -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 diff --git a/packages/app-desktop/gui/NoteListItem.tsx b/packages/app-desktop/gui/NoteListItem.tsx index 05003d577..9cf78479d 100644 --- a/packages/app-desktop/gui/NoteListItem.tsx +++ b/packages/app-desktop/gui/NoteListItem.tsx @@ -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); diff --git a/packages/app-desktop/gui/NoteListItem/utils/getNoteTitleHtml.ts b/packages/app-desktop/gui/NoteListItem/utils/getNoteTitleHtml.ts index fe38c5e89..39e20d4db 100644 --- a/packages/app-desktop/gui/NoteListItem/utils/getNoteTitleHtml.ts +++ b/packages/app-desktop/gui/NoteListItem/utils/getNoteTitleHtml.ts @@ -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); diff --git a/packages/app-desktop/gui/NoteRevisionViewer.tsx b/packages/app-desktop/gui/NoteRevisionViewer.tsx index 47e5b7f21..e4a827686 100644 --- a/packages/app-desktop/gui/NoteRevisionViewer.tsx +++ b/packages/app-desktop/gui/NoteRevisionViewer.tsx @@ -155,7 +155,7 @@ class NoteRevisionViewerComponent extends React.PureComponent { } 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. diff --git a/packages/app-desktop/gui/PromptDialog.tsx b/packages/app-desktop/gui/PromptDialog.tsx index 26ff02d3c..e28bdf2d4 100644 --- a/packages/app-desktop/gui/PromptDialog.tsx +++ b/packages/app-desktop/gui/PromptDialog.tsx @@ -245,7 +245,7 @@ export default class PromptDialog extends React.Component { 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 diff --git a/packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.ts b/packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.ts index 9788c1708..f9c1b7abb 100644 --- a/packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.ts +++ b/packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.ts @@ -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; diff --git a/packages/app-desktop/gui/ResizableLayout/utils/validateLayout.ts b/packages/app-desktop/gui/ResizableLayout/utils/validateLayout.ts index 16fbe2518..e56504060 100644 --- a/packages/app-desktop/gui/ResizableLayout/utils/validateLayout.ts +++ b/packages/app-desktop/gui/ResizableLayout/utils/validateLayout.ts @@ -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); diff --git a/packages/app-desktop/gui/StatusScreen/StatusScreen.tsx b/packages/app-desktop/gui/StatusScreen/StatusScreen.tsx index 4e9a1d3c4..4f95f3a14 100644 --- a/packages/app-desktop/gui/StatusScreen/StatusScreen.tsx +++ b/packages/app-desktop/gui/StatusScreen/StatusScreen.tsx @@ -41,14 +41,14 @@ async function exportDebugReportClick() { function StatusScreen(props: Props) { const [report, setReport] = useState([]); - 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 = ( diff --git a/packages/app-desktop/gui/StyleSheets/StyleSheetContainer.tsx b/packages/app-desktop/gui/StyleSheets/StyleSheetContainer.tsx index 079c9cb30..462dc3145 100644 --- a/packages/app-desktop/gui/StyleSheets/StyleSheetContainer.tsx +++ b/packages/app-desktop/gui/StyleSheets/StyleSheetContainer.tsx @@ -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'; diff --git a/packages/app-desktop/gui/note-viewer/index.html b/packages/app-desktop/gui/note-viewer/index.html index 137177429..192b65b78 100644 --- a/packages/app-desktop/gui/note-viewer/index.html +++ b/packages/app-desktop/gui/note-viewer/index.html @@ -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() { diff --git a/packages/app-desktop/package.json b/packages/app-desktop/package.json index a5a3f168b..af4136447 100644 --- a/packages/app-desktop/package.json +++ b/packages/app-desktop/package.json @@ -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, diff --git a/packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.ts b/packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.ts index 006dda633..2e04da295 100644 --- a/packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.ts +++ b/packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.ts @@ -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'); }); diff --git a/packages/app-desktop/services/sortOrder/notesSortOrderUtils.ts b/packages/app-desktop/services/sortOrder/notesSortOrderUtils.ts index 482f5d7e2..139b954e2 100644 --- a/packages/app-desktop/services/sortOrder/notesSortOrderUtils.ts +++ b/packages/app-desktop/services/sortOrder/notesSortOrderUtils.ts @@ -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; diff --git a/packages/app-desktop/tools/copy7Zip.ts b/packages/app-desktop/tools/copy7Zip.ts index 531dc01d7..e24f3ffbc 100644 --- a/packages/app-desktop/tools/copy7Zip.ts +++ b/packages/app-desktop/tools/copy7Zip.ts @@ -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. diff --git a/packages/app-desktop/utils/restartInSafeModeFromMain.test.ts b/packages/app-desktop/utils/restartInSafeModeFromMain.test.ts index ebbb7aa28..20b7ecbea 100644 --- a/packages/app-desktop/utils/restartInSafeModeFromMain.test.ts +++ b/packages/app-desktop/utils/restartInSafeModeFromMain.test.ts @@ -15,7 +15,7 @@ jest.doMock('../bridge', () => ({ '--profile', currentProfileDirectory, ], env: () => 'dev', - appName: () => 'joplin-destkop', + appName: () => 'joplin-desktop', }), })); diff --git a/packages/app-mobile/android/app/build.gradle b/packages/app-mobile/android/app/build.gradle index c5ece0f7f..c7141c5c4 100644 --- a/packages/app-mobile/android/app/build.gradle +++ b/packages/app-mobile/android/app/build.gradle @@ -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" } diff --git a/packages/app-mobile/components/ExtendedWebView.tsx b/packages/app-mobile/components/ExtendedWebView.tsx index c0ec25828..d9b2ba4d1 100644 --- a/packages/app-mobile/components/ExtendedWebView.tsx +++ b/packages/app-mobile/components/ExtendedWebView.tsx @@ -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) => { - const theme: Theme = themeStyle(props.themeId); const webviewRef = useRef(null); const [source, setSource] = useState(undefined); @@ -135,7 +130,10 @@ const ExtendedWebView = (props: Props, ref: Ref) => { return ( void; } -const webViewStyle = { - backgroundColor: 'transparent', -}; - export default function NoteBodyViewer(props: Props) { const dialogBoxRef = useRef(null); const webviewRef = useRef(null); @@ -103,8 +99,6 @@ export default function NoteBodyViewer(props: Props) { { } /* 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 ( { const minDimen = 45; diff --git a/packages/app-mobile/components/NoteEditor/NoteEditor.tsx b/packages/app-mobile/components/NoteEditor/NoteEditor.tsx index 11e91bfab..c207db87c 100644 --- a/packages/app-mobile/components/NoteEditor/NoteEditor.tsx +++ b/packages/app-mobile/components/NoteEditor/NoteEditor.tsx @@ -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) { }}> { 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, ) => { diff --git a/packages/app-mobile/components/app-nav.tsx b/packages/app-mobile/components/app-nav.tsx index d55d49474..85ba4c8d8 100644 --- a/packages/app-mobile/components/app-nav.tsx +++ b/packages/app-mobile/components/app-nav.tsx @@ -64,7 +64,7 @@ class AppNavComponent extends Component { 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 { 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; diff --git a/packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.tsx b/packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.tsx index 925fa47c4..8b41257ef 100644 --- a/packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.tsx +++ b/packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.tsx @@ -80,7 +80,7 @@ class ConfigScreenComponent extends BaseScreenComponent { - // 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 => { + private handleNavigateToNewScreen = async (): Promise => { await this.promptSaveChanges(); // Continue navigation @@ -306,14 +306,14 @@ class ConfigScreenComponent extends BaseScreenComponent void, options: any = null) { diff --git a/packages/app-mobile/components/screens/LogScreen.tsx b/packages/app-mobile/components/screens/LogScreen.tsx index 9f97d410d..4788dd2e5 100644 --- a/packages/app-mobile/components/screens/LogScreen.tsx +++ b/packages/app-mobile/components/screens/LogScreen.tsx @@ -67,13 +67,13 @@ class LogScreenComponent extends BaseScreenComponent { } 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 { 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 { } 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 {