1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-11-19 20:31:46 +02:00

Chore: Implement cSpell to detect spelling mistakes in codebase (#10001)

Co-authored-by: Helmut K. C. Tessarek <tessarek@evermeet.cx>
Co-authored-by: Henry Heino <46334387+personalizedrefrigerator@users.noreply.github.com>
This commit is contained in:
Laurent Cozic 2024-02-26 10:16:23 +00:00 committed by GitHub
parent 69cbd45782
commit 47f95cb294
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
187 changed files with 511 additions and 288 deletions

View File

@ -5,13 +5,19 @@
"**/*.min.*",
"**/*.svg",
"/_mydocs",
"**/*.d.ts",
"/_releases",
"/.git",
"/.yarn",
"/Assets",
"cspell.json",
"/packages/app-cli/app/fuzzing.js",
"/packages/app-cli/build",
"/packages/generator-joplin/generators/app/templates/api/",
"/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,16 +26,25 @@
"/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/vendor/",
"/packages/app-mobile/lib/rnInjectedJs",
"/packages/app-mobile/pluginAssets",
"/packages/doc-builder/build",
"/packages/doc-builder/i18n/",
"/packages/fork-sax/examples",
"/packages/fork-sax/lib/sax.js",
"/packages/app-mobile/ios/Pods/",
"/packages/renderer/highlight.ts",
"/packages/fork-sax/test",
"/packages/app-mobile/utils/fs-driver/runOnDeviceTests.ts",
"/packages/fork-uslug",
"/packages/default-plugins/plugin-sources/",
"/packages/app-desktop/utils/checkForUpdatesUtilsTestData.ts",
"/packages/lib/locales",
"/packages/lib/mime-utils-types.js",
"/packages/server/src/utils/testing/randomWords.ts",
"/packages/lib/parameters.js",
"/packages/lib/plugin_types",
"/packages/lib/resourceUtils.js",
@ -38,6 +53,8 @@
"/packages/lib/welcomeAssets.js",
"/packages/turndown-plugin-gfm/config",
"/packages/turndown/config",
"/readme/_i18n",
"/readme/i18n",
"node_modules"
],
"words": [
@ -63,13 +80,16 @@
"ambrt",
"Amharic",
"amothc",
"anchorpage",
"andrejilderda",
"anki",
"annotatescrollbar",
"Antarctique",
"antarctiques",
"Antártico",
"anymore",
"apidoc",
"apos",
"appiconset",
"applewebkit",
"approot",
@ -77,23 +97,36 @@
"Aragonés",
"ARITIM",
"armeabi",
"asdfasf",
"asterix",
"atest",
"atestb",
"atleast",
"attribname",
"attribvalue",
"authcode",
"autocompleteitem",
"autocompleter",
"Autocompleter",
"autocompletions",
"AUTOEXEC",
"autohide",
"Persistable",
"centered",
"invlaid",
"automatch",
"autoresize",
"Autoresize",
"Avenir",
"avif",
"awaiter",
"Ayiti",
"azamah",
"Azərbaycan",
"backoff",
"Bangla",
"bbox",
"Bbox",
"Bêafrîka",
"beforeinput",
"België",
@ -106,10 +139,14 @@
"Bislama",
"blabla",
"blablablabla",
"blockid",
"bonjour",
"Bonjour",
"boohay",
"Bosna",
"Bouvet",
"Bouvetøya",
"Bpcy",
"browserslist",
"bthqu",
"btns",
@ -136,26 +173,35 @@
"cdatastart",
"cdot",
"ceaf",
"ceea",
"centrafricaine",
"Centrafrican",
"Česká",
"changedtitle",
"Charcode",
"charcodes",
"checkboxclick",
"checkmark",
"chemfive",
"childs",
"choiceitem",
"chromedriver",
"chromeframe",
"chromeos",
"Città",
"Clearable",
"closebrackets",
"Cmds",
"codemirror",
"codepoint",
"codesample",
"Colorful",
"colorinput",
"colorpicker",
"colorswatch",
"colspan",
"committerdate",
"commmand",
"commmmmand",
"commonmark",
"COMMONMARK",
@ -164,6 +210,7 @@
"compositionstart",
"compositionupdate",
"conflicter",
"connectionstring",
"contenteditable",
"contextform",
"contextformbutton",
@ -194,12 +241,15 @@
"dataimg",
"datauri",
"Datauri",
"dataurl",
"datetime",
"Datetime",
"davris",
"dbuuid",
"DDTHH",
"deaccelerates",
"deflist",
"deindent",
"deinit",
"Démocratique",
"deselector",
@ -209,11 +259,15 @@
"dialogs",
"Dialogs",
"DIALOGS",
"Dimen",
"Dismisable",
"Distill",
"dists",
"Divs",
"docid",
"docsize",
"doctypes",
"docu",
"doesnotwork",
"doesntexist",
"doesntlookright",
@ -223,9 +277,12 @@
"domutils",
"DONATELINKS",
"downarrow",
"dragcursor",
"dragdrop",
"draggesture",
"dropdownalert",
"dünn",
"Dups",
"dylib",
"dynamiclib",
"ecuatorial",
@ -241,13 +298,16 @@
"elems",
"ellipsize",
"ELOCKED",
"emptylist",
"encryptable",
"endregion",
"enex",
"Enex",
"ENEX",
"ENSCOCOAERRORDOMAIN",
"enumber",
"eqeqeq",
"eqnsw",
"équatoriale",
"Erro",
"errorish",
@ -269,21 +329,34 @@
"Fahrräder",
"FAILSAFE",
"fallbacks",
"falsey",
"fancymenuitem",
"fancytype",
"favorites",
"fhash",
"Fiber",
"filepicker",
"Flavored",
"flusing",
"foldericon",
"folderid",
"folderkey",
"foldertest",
"foldl",
"fontawesome",
"fontface",
"foobar",
"Foobar",
"forall",
"forcewake",
"forecolor",
"formatcoords",
"Føroyar",
"fortawesome",
"française",
"françaises",
"FULLNAME",
"Fullpath",
"Gabuutih",
"gedit",
"geoip",
@ -292,6 +365,7 @@
"geoplugin",
"getlastmodified",
"gettext",
"Ghpcy",
"githubusercontent",
"Gora",
"gotchas",
@ -313,16 +387,22 @@
"Haïti",
"hanlder",
"Hausa",
"hdpi",
"headerless",
"Heino",
"Heisenbug",
"héllô",
"Hercegovina",
"hideothers",
"hift",
"highjack",
"highlited",
"historyhas",
"HMRKG",
"hocr",
"hoge",
"homenote",
"horiz",
"hotfolder",
"Howver",
"hpagent",
@ -335,6 +415,7 @@
"icns",
"iconset",
"iconutil",
"ified",
"Iforgot",
"iframes",
"ihack",
@ -342,6 +423,7 @@
"iìíîïī",
"IÌÍÎÏĪ",
"ijkl",
"imageeditor",
"imagelink",
"imagetools",
"immer",
@ -372,21 +454,27 @@
"itunes",
"Jabuuti",
"jackgruber",
"jianguoyun",
"joeattardi",
"jopext",
"joplinapp",
"JOPLINAPP",
"joplinbot",
"joplincloud",
"joplindev",
"JOPLINMOD",
"joplintest",
"joplinusercontent",
"jsbundles",
"jsdraw",
"Jsons",
"justtesting",
"Kalaallit",
"kalba",
"kanban",
"Kashmiri",
"katex",
"keybind",
"keychain",
"keycodes",
"keymaps",
@ -396,12 +484,15 @@
"Kirundi",
"Ködörösêse",
"Komori",
"Kopiuj",
"Kpck",
"Kūki",
"Laothian",
"lastmod",
"Latviešu",
"Latvija",
"lcov",
"ldapts",
"leaft",
"leftarrow",
"leftequilibrium",
@ -409,13 +500,17 @@
"Lettish",
"Lëtzebuerg",
"Levithan",
"lezer",
"Liban",
"Libérez",
"libz",
"Lietuva",
"Lietuvių",
"lifecyle",
"lineheight",
"Lingala",
"linkg",
"linki",
"linkurl",
"listbox",
"listfile",
@ -425,16 +520,20 @@
"longpress",
"longpresscancel",
"looooooong",
"LSTM",
"ltrim",
"Luxemburg",
"Maarten",
"macosm",
"Madagasikara",
"Magyarország",
"majax",
"managebutton",
"Mardown",
"markdowncalc",
"Maroc",
"MASTERKEY",
"matchesonscrollbar",
"matchinfo",
"mathchoice",
"mathjax",
@ -449,10 +548,12 @@
"Mayen",
"mchem",
"mechanim",
"MEDIUMINT",
"mediumtext",
"menubutton",
"mergeff",
"Metadatas",
"Metadatum",
"México",
"mhchem",
"middlewares",
@ -463,9 +564,11 @@
"mknote",
"mktodo",
"MMYY",
"mnop",
"modifié",
"monokai",
"MONOSPACE",
"mscz",
"msgctxt",
"msgfmt",
"msgmerge",
@ -494,7 +597,9 @@
"nanoid",
"Neaus",
"Nederlands",
"needpassword",
"nestedmenuitem",
"netinfo",
"newone",
"Nextcloud",
"njstrace",
@ -506,13 +611,18 @@
"noexpand",
"nojs",
"nolongershared",
"noneditable",
"nonlatin",
"NONLATIN",
"Noreg",
"Norge",
"nospecialcharacters",
"notaduration",
"notanumber",
"notarization",
"notarytool",
"notesnook",
"Notesnook",
"notetags",
"Notif",
"notindexed",
@ -520,9 +630,12 @@
"nounce",
"Nounce",
"Nounces",
"nplurals",
"npmignore",
"npmpackagejsonlintrc",
"numadd",
"numbersareok",
"reconsume",
"numdec",
"numdiv",
"numlist",
@ -548,6 +661,7 @@
"ondeclaration",
"onedrive",
"onelink",
"onfoo",
"onformat",
"onmatch",
"onopentag",
@ -557,6 +671,7 @@
"onprocessinginstruction",
"onselfclosingtag",
"ontext",
"ontouch",
"oòóôõöøō",
"OÒÓÔÕÖØŌ",
"opentag",
@ -570,12 +685,17 @@
"overidding",
"overriden",
"padd",
"PAGEDOWN",
"PAGEUP",
"pandoc",
"paperclip",
"partageable",
"partageables",
"passthrough",
"Päth",
"Pbuild",
"pbxproj",
"pcloud",
"pcmag",
"pcnalx",
"pddv",
@ -584,6 +704,7 @@
"père",
"Perú",
"pfff",
"pgdg",
"PGPASSWORD",
"pidfile",
"PLUGINLEGACY",
@ -591,7 +712,13 @@
"Polska",
"Polski",
"Polynésie",
"popover",
"Popover",
"popperjs",
"Português",
"positionals",
"Postprocess",
"postprocessing",
"Potoczny's",
"powerpoint",
"Prakash",
@ -601,6 +728,7 @@
"prerelease",
"Prerelease",
"presigner",
"Pressable",
"prettycron",
"pricetag",
"Príncipe",
@ -627,18 +755,27 @@
"reencrypted",
"Reencrypting",
"reencrypts",
"Reformatter",
"regexes",
"Regexs",
"Relavent",
"relayouted",
"rels",
"renamings",
"Renderable",
"renderered",
"Renderered",
"Replit's",
"replit",
"reponame",
"República",
"republika",
"République",
"requestheaders",
"resourceid",
"resourceidhere",
"resourcekey",
"resourcetest",
"resourcetype",
"resynced",
"Rhaeto",
@ -651,6 +788,7 @@
"rmusin",
"rnfs",
"RNFS",
"RNSAF",
"robocopy",
"Roboto",
"România",
@ -662,22 +800,33 @@
"rseidelsohn",
"rtrim",
"safeext",
"safemode",
"Safx",
"salut",
"Sangho",
"sasss",
"Sauvegardez",
"SAVEPOINT",
"schtroumpf",
"Schweiz",
"screenreader",
"Scrolllock",
"scrollmap",
"scrollview",
"sdcard",
"seafdav",
"Seafile",
"searchbar",
"searchcursor",
"searchengine",
"searchlimit",
"SEARCHOVERLAY",
"searchreplace",
"securerandom",
"segdir",
"seiyab",
"selectbox",
"selectedtext",
"Sénégal",
"Serializers",
"setext",
@ -688,12 +837,16 @@
"Shoft",
"shouldntendwithit",
"shouldstartwiththis",
"showpasswordbutton",
"Shqip",
"Shqipëria",
"Sicen",
"sidemenu",
"sidemenus",
"simplemath",
"Siswati",
"sizeinput",
"sizer",
"SJCL",
"Slovenčina",
"Slovenija",
@ -701,8 +854,13 @@
"softbreaks",
"Solarised",
"SOLARIZED",
"someclass",
"someid",
"someidhere",
"someresourceid",
"somethingrandom",
"somewhereelse",
"sourcecode",
"sourceurl",
"SPACEBAR",
"spaceno",
@ -711,6 +869,7 @@
"spellfix",
"sphemy",
"splitbutton",
"splitted",
"sprintf",
"sqlts",
"srcfolder",
@ -722,6 +881,7 @@
"stex",
"stilltryingtohack",
"strack",
"Strikethrough",
"Stringifiable",
"subdir",
"subl",
@ -741,9 +901,12 @@
"taga",
"tagb",
"tagc",
"tagkey",
"tagtest",
"Tajik",
"takesover",
"targetfolder",
"tbtn",
"Tchad",
"Teardown",
"termi",
@ -754,12 +917,15 @@
"Testb",
"testcreate",
"testexportfolder",
"testid",
"testingconnection",
"testingkeychain",
"testocr",
"testunit",
"texify",
"Texify",
"textareas",
"Textcolor",
"textexportnote",
"textstyle",
"thaaaaaaan",
@ -772,16 +938,23 @@
"Tiếng",
"Tigrinya",
"tiiitlllle",
"TINYINT",
"tinymce",
"tippy",
"titi",
"titlecontent",
"titletitle",
"tkwidget",
"tkwidgets",
"Todos",
"toggleblock",
"togglebutton",
"togglemenuitem",
"toolip",
"toolwidget",
"tooshort",
"Traduis",
"treshold",
"treymo",
"tripledash",
"tsmerge",
@ -798,9 +971,12 @@
"Typora",
"tzip",
"uastring",
"udostępnialne",
"udostępnialny",
"uglifycss",
"uglifyjs",
"Uighur",
"Uiid",
"unconflicted",
"underbrace",
"Undos",
@ -808,12 +984,15 @@
"unhighlighted",
"unixlike",
"unmocked",
"Unnormalized",
"unoverriding",
"unserialize",
"unserialized",
"unserializes",
"unserializing",
"unshares",
"unsharing",
"unspell",
"unusued",
"uparrow",
"uphy",
@ -831,9 +1010,11 @@
"UÙÚÛÜŮŪ",
"valign",
"Valign",
"valpha",
"vars",
"Vars",
"Vaticano",
"vbscript",
"vers",
"verylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongidverylongid",
"veryverylongclientidveryverylongclientidveryverylongclientidveryverylongclientid",
@ -842,16 +1023,24 @@
"viewbox",
"Volapuk",
"Volívia",
"vosk",
"Vosk",
"votearrow",
"watchedicon",
"webclipper",
"webdav",
"webfonts",
"welc",
"whitespaces",
"widder",
"Wifi",
"Withéàö",
"Withflags",
"withs",
"Wolof",
"WONTFIX",
"wordcount",
"wraping",
"wrongclienttype",
"wrongpassword",
"wrongtype",
@ -863,6 +1052,7 @@
"xcrun",
"xgettext",
"xlink",
"Xmark",
"xzvf",
"yarg",
"yosay",
@ -949,6 +1139,8 @@
"ประเทศไทย",
"ປະຊາຊົນລາວ",
"မြန်မာ",
"កម្ពុជា"
]
"កម្ពុជា",
"clike"
],
"enabled": true
}

View File

@ -12,7 +12,7 @@ module.exports = {
// '**/*.ts?(x)': () => 'npm run tsc',
'*.{js,jsx,ts,tsx}': [
'yarn checkIgnoredFiles',
// 'yarn checkLibPaths',
'yarn spellcheck',
'yarn packageJsonLint',
'yarn linter-precommit',
],

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",
@ -52,6 +51,7 @@
"releaseServer": "node packages/tools/release-server.js",
"setupNewRelease": "node ./packages/tools/setupNewRelease",
"spellcheck": "node packages/tools/spellcheck.js",
"spellcheck-base": "cspell --no-progress --no-summary --config cspell.json",
"tagServerLatest": "node packages/tools/tagServerLatest.js",
"test-ci": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test-ci",
"test": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test",

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

@ -563,7 +563,7 @@ 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 because electron

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

@ -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

@ -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

@ -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,

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;
}

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

@ -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

@ -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

@ -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

@ -86,7 +86,7 @@ describe('Should detect list items', () => {
test('should NOT detect `1)` as empty list item ', () => {
expect(markdownUtils.isEmptyListItem('1)')).toBe(false);
});
// checbox list
// checkbox list
test('should NOT detect `+ [x]` as empty list item ', () => {
expect(markdownUtils.isEmptyListItem('+ [x]')).toBe(false);
});

View File

@ -145,7 +145,7 @@ export default class BaseItem extends BaseModel {
const ItemClass = this.itemClass(this.modelType());
const itemType = ItemClass.modelType();
// The fact that we don't check if the item_id still exist in the corresponding item table, means
// that the returned number might be innaccurate (for example if a sync operation was cancelled)
// that the returned number might be inaccurate (for example if a sync operation was cancelled)
const sql = 'SELECT count(*) as total FROM sync_items WHERE sync_target = ? AND item_type = ?';
const r = await this.db().selectOne(sql, [syncTarget, itemType]);
return r.total;

View File

@ -682,7 +682,7 @@ export default class Folder extends BaseItem {
rootFolders.push(folder);
} else {
if (!idToFolders[folder.parent_id]) {
// It means the notebook is refering a folder that doesn't exist. In theory it shouldn't happen
// It means the notebook is referring a folder that doesn't exist. In theory it shouldn't happen
// but sometimes does - https://github.com/laurent22/joplin/issues/1068#issuecomment-450594708
rootFolders.push(folder);
} else {

View File

@ -414,7 +414,7 @@ describe('models/Note', () => {
expect(movedNote.conflict_original_id).toBe('');
}));
function testResourceReplacment(body: string, pathsToTry: string[], expected: string) {
function testResourceReplacement(body: string, pathsToTry: string[], expected: string) {
expect(Note['replaceResourceExternalToInternalLinks_'](pathsToTry, body)).toBe(expected);
}
@ -422,28 +422,28 @@ describe('models/Note', () => {
const body = '![image.png](file:///C:Users/Username/resources/849eae4dade045298c107fc706b6d2bc.png?t=1655192326803)';
const pathsToTry = ['file:///C:Users/Username/resources'];
const expected = '![image.png](:/849eae4dade045298c107fc706b6d2bc)';
testResourceReplacment(body, pathsToTry, expected);
testResourceReplacement(body, pathsToTry, expected);
});
test('replacement with spaces', () => {
const body = '![image.png](file:///C:Users/Username%20with%20spaces/resources/849eae4dade045298c107fc706b6d2bc.png?t=1655192326803)';
const pathsToTry = ['file:///C:Users/Username with spaces/resources'];
const expected = '![image.png](:/849eae4dade045298c107fc706b6d2bc)';
testResourceReplacment(body, pathsToTry, expected);
testResourceReplacement(body, pathsToTry, expected);
});
test('replacement with Non-ASCII', () => {
const body = '![image.png](file:///C:Users/UsernameWith%C3%A9%C3%A0%C3%B6/resources/849eae4dade045298c107fc706b6d2bc.png?t=1655192326803)';
const pathsToTry = ['file:///C:Users/UsernameWithéàö/resources'];
const expected = '![image.png](:/849eae4dade045298c107fc706b6d2bc)';
testResourceReplacment(body, pathsToTry, expected);
testResourceReplacement(body, pathsToTry, expected);
});
test('replacement with Non-ASCII and spaces', () => {
const body = '![image.png](file:///C:Users/Username%20With%20%C3%A9%C3%A0%C3%B6/resources/849eae4dade045298c107fc706b6d2bc.png?t=1655192326803)';
const pathsToTry = ['file:///C:Users/Username With éàö/resources'];
const expected = '![image.png](:/849eae4dade045298c107fc706b6d2bc)';
testResourceReplacment(body, pathsToTry, expected);
testResourceReplacement(body, pathsToTry, expected);
});
it('should not allow modifying a read-only note', async () => {

View File

@ -854,7 +854,7 @@ export default class Note extends BaseItem {
}
// This method will disable the NOTE_UPDATE_ONE action to prevent a lot
// of unecessary updates, so it's the caller's responsability to update
// of unnecessary updates, so it's the caller's responsibility to update
// the UI once the call is finished. This is done by listening to the
// NOTE_IS_INSERTING_NOTES action in the application middleware.
public static async insertNotesAt(folderId: string, noteIds: string[], index: number, uncompletedTodosOnTop: boolean, showCompletedTodos: boolean) {
@ -950,19 +950,19 @@ export default class Note extends BaseItem {
// and the increment between the order values of each inserted notes.
let newOrder = 0;
let intervalBetweenNotes = 0;
const defaultIntevalBetweeNotes = 60 * 60 * 1000;
const defaultIntevalBetweenNotes = 60 * 60 * 1000;
if (!relevantExistingNoteCount) { // If there's no (relevant) notes in the target notebook
newOrder = Date.now();
intervalBetweenNotes = defaultIntevalBetweeNotes;
intervalBetweenNotes = defaultIntevalBetweenNotes;
} else if (index > lastRelevantNoteIndex) { // Insert at the end (of relevant group)
intervalBetweenNotes = notes[lastRelevantNoteIndex].order / (noteIds.length + 1);
newOrder = notes[lastRelevantNoteIndex].order - intervalBetweenNotes;
} else if (index <= firstRelevantNoteIndex) { // Insert at the beginning (of relevant group)
const firstNoteOrder = notes[firstRelevantNoteIndex].order;
if (firstNoteOrder >= Date.now()) {
intervalBetweenNotes = defaultIntevalBetweeNotes;
newOrder = firstNoteOrder + defaultIntevalBetweeNotes;
intervalBetweenNotes = defaultIntevalBetweenNotes;
newOrder = firstNoteOrder + defaultIntevalBetweenNotes;
} else {
intervalBetweenNotes = (Date.now() - firstNoteOrder) / (noteIds.length + 1);
newOrder = firstNoteOrder + intervalBetweenNotes * noteIds.length;
@ -976,7 +976,7 @@ export default class Note extends BaseItem {
for (let i = index; i >= 0; i--) {
const n = notes[i];
if (n.order <= previousOrder) {
const o = previousOrder + defaultIntevalBetweeNotes;
const o = previousOrder + defaultIntevalBetweenNotes;
const updatedNote = await this.updateNoteOrder_(n, o);
notes[i] = { ...n, ...updatedNote };
previousOrder = o;

View File

@ -5,7 +5,7 @@ import { LoadOptions } from './utils/types';
// - If is_associated = 1, note_resources indicates which note_id is currently associated with the given resource_id
// - If is_associated = 0, note_resources indicates which note_id *was* associated with the given resource_id
// - last_seen_time tells the last time that reosurce was associated with this note.
// - last_seen_time tells the last time that resource was associated with this note.
// - If last_seen_time is 0, it means the resource has never been associated with any note.
export default class NoteResource extends BaseModel {
@ -134,7 +134,7 @@ export default class NoteResource extends BaseModel {
// If the resource is not associated with any note, and has never
// been synced, it means it's a local resource that was removed from
// a note (or the note was deleted). In which case, we set a
// "last_seen_time", so that it can be considered an orphan reosurce
// "last_seen_time", so that it can be considered an orphan resource
// that can be auto-deleted.
//
// https://github.com/laurent22/joplin/issues/932#issuecomment-933736405

View File

@ -204,6 +204,7 @@ describe('models/Revision', () => {
expect(newRevs[2].id).toBe('789');
}));
// cSpell:disable
it('should create patch stats', (async () => {
const tests = [
{
@ -240,5 +241,6 @@ describe('models/Revision', () => {
expect(stats.added).toBe(test.expected[1]);
}
}));
// cSpell:enable
});

View File

@ -202,7 +202,7 @@ export const MAX_HISTORY = 200;
const derivedStateCache_: any = {};
// Allows, for a given state, to return the same derived
// objects, to prevent unecessary updates on calling components.
// objects, to prevent unnecessary updates on calling components.
const cacheEnabledOutput = (key: string, output: any) => {
key = `${key}_${JSON.stringify(output)}`;
if (derivedStateCache_[key]) return derivedStateCache_[key];

View File

@ -170,7 +170,7 @@ export default class DecryptionWorker {
this.dispatchReport({ state: 'started' });
try {
const notLoadedMasterKeyDisptaches = [];
const notLoadedMasterKeyDispatches = [];
while (true) {
const result: ItemsThatNeedDecryptionResult = await BaseItem.itemsThatNeedDecryption(excludedIds);
@ -230,12 +230,12 @@ export default class DecryptionWorker {
excludedIds.push(item.id);
if (error.code === 'masterKeyNotLoaded' && options.masterKeyNotLoadedHandler === 'dispatch') {
if (notLoadedMasterKeyDisptaches.indexOf(error.masterKeyId) < 0) {
if (notLoadedMasterKeyDispatches.indexOf(error.masterKeyId) < 0) {
this.dispatch({
type: 'MASTERKEY_ADD_NOT_LOADED',
id: error.masterKeyId,
});
notLoadedMasterKeyDisptaches.push(error.masterKeyId);
notLoadedMasterKeyDispatches.push(error.masterKeyId);
}
await clearDecryptionCounter();
continue;

View File

@ -267,7 +267,7 @@ export default class KeymapService extends BaseService {
this.defaultKeymapItems.forEach(({ command, accelerator }) => {
const currentAccelerator = this.getAccelerator(command);
// Only the customized/changed keymap items are neccessary for the custom keymap
// Only the customized/changed keymap items are necessary for the custom keymap
// Customizations can be merged with the original keymap at the runtime
if (this.getAccelerator(command) !== accelerator) {
customkeymapItems.push({ command, accelerator: currentAccelerator });

View File

@ -21,13 +21,13 @@ enum ReportItemType {
CloseList = 'closeList',
}
type RerportItemOrString = ReportItem | string;
type ReportItemOrString = ReportItem | string;
export type RetryAllHandler = ()=> void;
export interface ReportSection {
title: string;
body: RerportItemOrString[];
body: ReportItemOrString[];
name?: string;
canRetryAll?: boolean;
retryAllHandler?: RetryAllHandler;
@ -149,7 +149,7 @@ export default class ReportService {
const retryHandlers: Function[] = [];
for (let i = 0; i < section.body.length; i++) {
const item: RerportItemOrString = section.body[i];
const item: ReportItemOrString = section.body[i];
if (typeof item !== 'string' && item.canRetry) {
retryHandlers.push(item.retryHandler);
}

View File

@ -151,7 +151,7 @@ export default class ResourceEditWatcher {
//
// We also need this because some events are handled twice - once in the "all" event
// handle and once in the "raw" event handler, due to a bug in chokidar. So having
// this check means we don't unecessarily save the resource twice when the file is
// this check means we don't unnecessarily save the resource twice when the file is
// modified by the user.
this.logger().debug(`ResourceEditWatcher: No timestamp and file size change - skip: ${resourceId}`);
return;

View File

@ -236,11 +236,11 @@ describe('services/ResourceService', () => {
}));
// it('should auto-delete resource even if the associated note was deleted immediately', (async () => {
// // Previoulsy, when a resource was be attached to a note, then the
// // Previously, when a resource was be attached to a note, then the
// // note was immediately deleted, the ResourceService would not have
// // time to quick in an index the resource/note relation. It means
// // that when doing the orphan resource deletion job, those
// // resources would permanently stay behing.
// // resources would permanently stay behind.
// // https://github.com/laurent22/joplin/issues/932
// const service = new ResourceService();

View File

@ -257,7 +257,7 @@ describe('services/RevisionService', () => {
}
}));
it('should create a revision for notes that get deleted (recyle bin)', (async () => {
it('should create a revision for notes that get deleted (recycle bin)', (async () => {
const n1 = await Note.save({ title: 'hello' });
const noteId = n1.id;

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,7 @@ interface TestData {
ciphertext: string;
}
// This is conveninent to quickly generate some data to verify for example that
// This is convenient to quickly generate some data to verify for example that
// react-native-rsa can decrypt data from node-rsa and vice-versa.
export async function createTestData() {
const plaintext = 'just testing';
@ -84,6 +84,8 @@ export async function checkTestData(data: TestData, options: CheckTestDataOption
}
}
// cSpell:disable
// Data generated on mobile using react-native-rsa-native
const mobileData = {
'publicKey': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlEVSnwMpmGC+YaRw3B37BP1IBth02OFCrlZjlkn14OijnmQaOKGxhJtthvlVVEOEc50D+MMKZ1mJleER4FnD3CoGHaVZmZRa3wnuTblctF/in0mgywFJ6HlEXngUrWt2TkCnkwg4nP0IKlQ4URBxWGllVbWUgqUs5uAtV4mkrx+Ke68j+suoN8w5BF9WnYJCclDCplUOFx77llw1Z/7O8UjkgbfYKOnwMEpxlO1SVutNQNgD4BOtGn73ai0qjHKq5as8SKJb/ch+uAX95bJHlOOvBrHw718gcbnxkn6PEN3vl4/HbmHFj/V4zxG8ZF82+oTOh6m/HGdPPLpF8e98dQIDAQAB\n-----END PUBLIC KEY-----',
@ -100,6 +102,8 @@ const desktopData = {
'ciphertext': 'PRqiQjxnQMukoYPA9XtlGcgAjwuDJd24GtJ3iO2qhh0HnbPnx3c8ZaGWJyV1ejZCwIWv509js7sCTHtXqeGkZr//Db6oOIyi77VzRwvzPxReHPefF0rX62uMh+zTmQW7KSrFeAvtnpWiDcyynUtwycgrZcQCHZoEmSSyc3cyj09HgqEoSQb0BOc8daR0aXwOpgXsB8ypf3+m23U1gZmIyl0glymTN9h1jopV9dRtw5ufcc4ve/hHKp0gbaT2OaRKOLr6AXmbDGwkF5bsvjV+v4tTkj96OUjoG9qUMQh/JYRMl7mxJriUB3Jc6WHEKRVPQYAIZODfEOy3rkHwWAcYjA==',
};
// cSpell:enable
// This can be used to run integration tests directly on device. It will throw
// an error if something cannot be decrypted, or else print info messages.
export const runIntegrationTests = async (silent = false) => {

View File

@ -36,7 +36,7 @@ export async function setupAndEnableEncryption(service: EncryptionService, maste
export async function setupAndDisableEncryption(service: EncryptionService) {
// Allow disabling encryption even if some items are still encrypted, because whether E2EE is enabled or disabled
// should not affect whether items will enventually be decrypted or not (DecryptionWorker will still work as
// should not affect whether items will eventually be decrypted or not (DecryptionWorker will still work as
// long as there are encrypted items). Also even if decryption is disabled, it's possible that encrypted items
// will still be received via synchronisation.
@ -113,7 +113,7 @@ export async function migrateMasterPassword() {
}
}
// All master keys normally should be decryped with the master password, however
// All master keys normally should be decrypted with the master password, however
// previously any master key could be encrypted with any password, so to support
// this legacy case, we first check if the MK decrypts with the master password.
// If not, try with the master key specific password, if any is defined.

View File

@ -189,7 +189,7 @@ export default class InteropService {
}
// Find the module that matches the given type ("importer" or "exporter")
// and the given format. Some formats can have multiple assocated importers
// and the given format. Some formats can have multiple associated importers
// or exporters, such as ENEX. In this case, the one marked as "isDefault"
// is returned. This is useful to auto-detect the module based on the format.
// For more precise matching, newModuleFromPath_ should be used.

View File

@ -39,7 +39,7 @@ export default class InteropService_Exporter_Md extends InteropService_Exporter_
}
}
private async relaceLinkedItemIdsByRelativePaths_(item: any) {
private async replaceLinkedItemIdsByRelativePaths_(item: any) {
const relativePathToRoot = await this.makeDirPath_(item, '..');
const newBody = await this.replaceResourceIdsByRelativePaths_(item.body, relativePathToRoot);
@ -130,7 +130,7 @@ export default class InteropService_Exporter_Md extends InteropService_Exporter_
const notePaths = this.context() && this.context().notePaths ? this.context().notePaths : {};
const noteFilePath = `${this.destDir_}/${notePaths[item.id]}`;
const noteBody = await this.relaceLinkedItemIdsByRelativePaths_(item);
const noteBody = await this.replaceLinkedItemIdsByRelativePaths_(item);
const modNote = { ...item, body: noteBody };
const noteContent = await this.getNoteExportContent_(modNote);
await shim.fsDriver().mkdir(dirname(noteFilePath));

View File

@ -99,7 +99,7 @@ export default class InteropService_Exporter_Md_frontmatter extends InteropServi
private extractMetadata(note: NoteEntity) {
const md: MdFrontMatterExport = {};
// Every variable needs to be converted seperately, so they will be handles in groups
// Every variable needs to be converted separately, so they will be handles in groups
//
// title
if (note.title) { md['title'] = note.title; }

View File

@ -140,7 +140,7 @@ export default class InteropService_Importer_Md extends InteropService_Importer_
}
// The first is a normal link, the second is supports the <link> and [](<link with spaces>) syntax
// Only opening patterns are consider in order to cover all occurances
// Only opening patterns are consider in order to cover all occurrences
// We need to use the encoded link as well because some links (link's with spaces)
// will appear encoded in the source. Other links (unicode chars) will not
const linksToReplace = [this.trimAnchorLink(link), this.trimAnchorLink(encodedLink)];

View File

@ -171,7 +171,9 @@ describe('InteropService_Importer_Md_frontmatter: importMetadata', () => {
it('should import a note that contains an image in DataUrl format', async () => {
const note = await importTestFile('note_with_dataurl_image.md');
// cSpell:disable
expect(note.body).toBe('<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2023%2038%22%3E%3Cpath%20d%3D%22M16.6%2038.1h-5.5l-.2-2.9-.2%202.9h-5.5L5%2025.3l-.8%202a1.53%201.53%200%2001-1.9.9l-1.2-.4a1.58%201.58%200%2001-1-1.9v-.1c.3-.9%203.1-11.2%203.1-11.2a2.66%202.66%200%20012.3-2l.6-.5a6.93%206.93%200%20014.7-12%206.8%206.8%200%20014.9%202%207%207%200%20012%204.9%206.65%206.65%200%2001-2.2%205l.7.5a2.78%202.78%200%20012.4%202s2.9%2011.2%202.9%2011.3a1.53%201.53%200%2001-.9%201.9l-1.3.4a1.63%201.63%200%2001-1.9-.9l-.7-1.8-.1%2012.7zm-3.6-2h1.7L14.9%2020.3l1.9-.3%202.4%206.3.3-.1c-.2-.8-.8-3.2-2.8-10.9a.63.63%200%2000-.6-.5h-.6l-1.1-.9h-1.9l-.3-2a4.83%204.83%200%20003.5-4.7A4.78%204.78%200%200011%202.3H10.8a4.9%204.9%200%2000-1.4%209.6l-.3%202h-1.9l-1%20.9h-.6a.74.74%200%2000-.6.5c-2%207.5-2.7%2010-3%2010.9l.3.1L4.8%2020l1.9.3.2%2015.8h1.6l.6-8.4a1.52%201.52%200%20011.5-1.4%201.5%201.5%200%20011.5%201.4l.9%208.4zm-10.9-9.6zm17.5-.1z%22%20style%3D%22isolation%3Aisolate%22%20fill%3D%22%23333%22%20opacity%3D%22.7%22/%3E%3Cpath%20d%3D%22M5.9%2013.6l1.1-.9h7.8l1.2.9%22%20fill%3D%22%23ce592c%22/%3E%3Cellipse%20cx%3D%2210.9%22%20cy%3D%2213.1%22%20rx%3D%222.7%22%20ry%3D%22.3%22%20style%3D%22isolation%3Aisolate%22%20fill%3D%22%23ce592c%22%20opacity%3D%22.5%22/%3E%3Cpath%20d%3D%22M20.6%2026.1l-2.9-11.3a1.71%201.71%200%2000-1.6-1.2H5.699999999999999a1.69%201.69%200%2000-1.5%201.3l-3.1%2011.3a.61.61%200%2000.3.7l1.1.4a.61.61%200%2000.7-.3l2.7-6.7.2%2016.8h3.6l.6-9.3a.47.47%200%2001.44-.5h.06c.4%200%20.4.2.5.5l.6%209.3h3.6L15.7%2020.3l2.5%206.6a.52.52%200%2000.66.31l1.2-.4a.57.57%200%2000.5-.7z%22%20fill%3D%22%23fdbf2d%22/%3E%3Cpath%20d%3D%22M7%2013.6l3.9%206.7%203.9-6.7%22%20style%3D%22isolation%3Aisolate%22%20fill%3D%22%23cf572e%22%20opacity%3D%22.6%22/%3E%3Ccircle%20cx%3D%2210.9%22%20cy%3D%227%22%20r%3D%225.9%22%20fill%3D%22%23fdbf2d%22/%3E%3C/svg%3E" alt="Street View Pegman Control" style="height:30px;width:30px;position:absolute;transform:translate(-50%,-50%);pointer-events:none">');
// cSpell:enable
});
it('should recognize frontmatter in a file that starts with a UTF8 byte order mark', async () => {

View File

@ -28,7 +28,7 @@ function normalizeYamlWhitespace(yaml: string[]): string[] {
});
}
// This is a helper functon to convert an arbitrary author variable into a string
// This is a helper function to convert an arbitrary author variable into a string
// the use case is for loading from r-markdown/pandoc style notes
// references:
// https://pandoc.org/MANUAL.html#extension-yaml_metadata_block
@ -143,7 +143,7 @@ export default class InteropService_Importer_Md_frontmatter extends InteropServi
}
}
// Tags are handled seperately from typical metadata
// Tags are handled separately from typical metadata
let tags: string[] = [];
if ('tags' in md) {
// Only create unique tags

View File

@ -161,7 +161,7 @@ describe('OcrService', () => {
const service = newOcrService();
// The service will print a warnign so we disable it in tests
// The service will print a warning so we disable it in tests
Logger.globalLogger.enabled = false;
await service.processResources();
Logger.globalLogger.enabled = true;
@ -210,7 +210,7 @@ describe('OcrService', () => {
const service2 = newOcrService();
await service2.processResources();
await synchronizerStart();
const expectedResouceUpatedTime = (await Resource.all())[0].updated_time;
const expectedResourceUpdatedTime = (await Resource.all())[0].updated_time;
await switchClient(1);
@ -226,7 +226,7 @@ describe('OcrService', () => {
expect(resource.ocr_text).toBe('Dummy PDF file');
expect(resource.ocr_error).toBe('');
expect(resource.ocr_status).toBe(ResourceOcrStatus.Done);
expect(resource.updated_time).toBe(expectedResouceUpatedTime);
expect(resource.updated_time).toBe(expectedResourceUpdatedTime);
}
await service1.dispose();

View File

@ -20,7 +20,7 @@ import { Path } from './types';
* In general you would use the methods in this class as if you were using a REST API. There are four methods that map to GET, POST, PUT and DELETE calls.
* And each method takes these parameters:
*
* * `path`: This is an array that represents the path to the resource in the form `["resouceName", "resourceId", "resourceLink"]` (eg. ["tags", ":id", "notes"]). The "resources" segment is the name of the resources you want to access (eg. "notes", "folders", etc.). If not followed by anything, it will refer to all the resources in that collection. The optional "resourceId" points to a particular resources within the collection. Finally, an optional "link" can be present, which links the resource to a collection of resources. This can be used in the API for example to retrieve all the notes associated with a tag.
* * `path`: This is an array that represents the path to the resource in the form `["resourceName", "resourceId", "resourceLink"]` (eg. ["tags", ":id", "notes"]). The "resources" segment is the name of the resources you want to access (eg. "notes", "folders", etc.). If not followed by anything, it will refer to all the resources in that collection. The optional "resourceId" points to a particular resources within the collection. Finally, an optional "link" can be present, which links the resource to a collection of resources. This can be used in the API for example to retrieve all the notes associated with a tag.
* * `query`: (Optional) The query parameters. In a URL, this is the part after the question mark "?". In this case, it should be an object with key/value pairs.
* * `data`: (Optional) Applies to PUT and POST calls only. The request body contains the data you want to create or modify, for example the content of a note or folder.
* * `files`: (Optional) Used to create new resources and associate them with files.

View File

@ -101,9 +101,9 @@ export default class JoplinImaging {
return this.cacheImage(resizedImage);
}
public async crop(handle: Handle, rectange: Rectangle) {
public async crop(handle: Handle, rectangle: Rectangle) {
const image = this.imageByHandle(handle);
const croppedImage = image.data.crop(rectange);
const croppedImage = image.data.crop(rectangle);
return this.cacheImage(croppedImage);
}

View File

@ -68,7 +68,7 @@ export interface ListRenderer {
/**
* The size of each item must be specified in advance for performance
* reasons, and cannot be changed afterwards. If the item flow is top to
* bottom, you only need to specificy the item height (the width will be
* bottom, you only need to specify the item height (the width will be
* ignored).
*/
itemSize: Size;
@ -155,7 +155,7 @@ export interface ListRenderer {
onRenderNote: OnRenderNoteHandler;
/**
* This handler allows adding some interacivity to the note renderer -
* This handler allows adding some interactivity to the note renderer -
* whenever an input element within the item is changed (for example, when a
* checkbox is clicked, or a text input is changed), this `onChange` handler
* is going to be called.

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;
}
@ -553,7 +553,7 @@ export interface CodeMirrorControl {
* registers the given [CompletionSource](https://codemirror.net/docs/ref/#autocomplete.CompletionSource).
*
* Use this extension rather than the built-in CodeMirror [`autocompletion`](https://codemirror.net/docs/ref/#autocomplete.autocompletion)
* if you don't want to use [langaugeData-based autocompletion](https://codemirror.net/docs/ref/#autocomplete.autocompletion^config.override).
* if you don't want to use [languageData-based autocompletion](https://codemirror.net/docs/ref/#autocomplete.autocompletion^config.override).
*
* Using `autocompletion({ override: [ ... ]})` causes errors when done by multiple plugins.
*/

View File

@ -58,7 +58,7 @@ export const defaultState: State = {
export const utils = {
// It is best to use viewsByType instead as this method creates new objects
// which might trigger unecessary renders even when plugin and views haven't changed.
// which might trigger unnecessary renders even when plugin and views haven't changed.
viewInfosByType: function(plugins: PluginStates, type: string): ViewInfo[] {
const output: ViewInfo[] = [];

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