diff --git a/.eslintrc.js b/.eslintrc.js index e8231cc4b2..8a585b6820 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -76,6 +76,7 @@ module.exports = { 'no-array-constructor': ['error'], 'radix': ['error'], + 'eqeqeq': ['error', 'always'], // Warn only for now because fixing everything would take too much // refactoring, but new code should try to stick to it. diff --git a/packages/app-cli/app/app-gui.js b/packages/app-cli/app/app-gui.js index a85ab91b2b..5a8903e230 100644 --- a/packages/app-cli/app/app-gui.js +++ b/packages/app-cli/app/app-gui.js @@ -412,7 +412,7 @@ class AppGui { const widget = this.widget('mainWindow').focusedWidget; if (!widget) return null; - if (widget.name == 'noteList' || widget.name == 'folderList') { + if (widget.name === 'noteList' || widget.name === 'folderList') { return widget.currentItem; } @@ -521,11 +521,11 @@ class AppGui { const args = splitCommandString(cmd); for (let i = 0; i < args.length; i++) { - if (args[i] == '$n') { + if (args[i] === '$n') { args[i] = note ? note.id : ''; - } else if (args[i] == '$b') { + } else if (args[i] === '$b') { args[i] = folder ? folder.id : ''; - } else if (args[i] == '$c') { + } else if (args[i] === '$c') { const item = this.activeListItem(); args[i] = item ? item.id : ''; } diff --git a/packages/app-cli/app/app.js b/packages/app-cli/app/app.js index 17e78fcb89..444f635beb 100644 --- a/packages/app-cli/app/app.js +++ b/packages/app-cli/app/app.js @@ -81,21 +81,21 @@ class Application extends BaseApplication { pattern = pattern ? pattern.toString() : ''; - if (type == BaseModel.TYPE_FOLDER && (pattern == Folder.conflictFolderTitle() || pattern == Folder.conflictFolderId())) return [Folder.conflictFolder()]; + if (type === BaseModel.TYPE_FOLDER && (pattern === Folder.conflictFolderTitle() || pattern === Folder.conflictFolderId())) return [Folder.conflictFolder()]; if (!options) options = {}; const parent = options.parent ? options.parent : app().currentFolder(); const ItemClass = BaseItem.itemClass(type); - if (type == BaseModel.TYPE_NOTE && pattern.indexOf('*') >= 0) { + if (type === BaseModel.TYPE_NOTE && pattern.indexOf('*') >= 0) { // Handle it as pattern if (!parent) throw new Error(_('No notebook selected.')); return await Note.previews(parent.id, { titlePattern: pattern }); } else { // Single item let item = null; - if (type == BaseModel.TYPE_NOTE) { + if (type === BaseModel.TYPE_NOTE) { if (!parent) throw new Error(_('No notebook has been specified.')); item = await ItemClass.loadFolderNoteByField(parent.id, 'title', pattern); } else { @@ -137,7 +137,7 @@ class Application extends BaseApplication { if (!options.booleanAnswerDefault) options.booleanAnswerDefault = 'y'; if (!options.answers) options.answers = options.booleanAnswerDefault === 'y' ? [_('Y'), _('n')] : [_('N'), _('y')]; - if (options.type == 'boolean') { + if (options.type === 'boolean') { message += ` (${options.answers.join('/')})`; } @@ -146,7 +146,7 @@ class Application extends BaseApplication { if (options.type === 'boolean') { if (answer === null) return false; // Pressed ESCAPE if (!answer) answer = options.answers[0]; - const positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1; + const positiveIndex = options.booleanAnswerDefault === 'y' ? 0 : 1; return answer.toLowerCase() === options.answers[positiveIndex].toLowerCase(); } else { return answer; @@ -181,7 +181,7 @@ class Application extends BaseApplication { fs.readdirSync(__dirname).forEach(path => { if (path.indexOf('command-') !== 0) return; const ext = fileExtension(path); - if (ext != 'js') return; + if (ext !== 'js') return; const CommandClass = require(`./${path}`); let cmd = new CommandClass(); diff --git a/packages/app-cli/app/autocompletion.js b/packages/app-cli/app/autocompletion.js index d197378a49..61f2965a84 100644 --- a/packages/app-cli/app/autocompletion.js +++ b/packages/app-cli/app/autocompletion.js @@ -12,7 +12,7 @@ async function handleAutocompletionPromise(line) { const words = getArguments(line); // If there is only one word and it is not already a command name then you // should look for commands it could be - if (words.length == 1) { + if (words.length === 1) { if (names.indexOf(words[0]) === -1) { const x = names.filter(n => n.indexOf(words[0]) === 0); if (x.length === 1) { @@ -78,38 +78,38 @@ async function handleAutocompletionPromise(line) { const currentFolder = app().currentFolder(); - if (argName == 'note' || argName == 'note-pattern') { + if (argName === 'note' || argName === 'note-pattern') { const notes = currentFolder ? await Note.previews(currentFolder.id, { titlePattern: `${next}*` }) : []; l.push(...notes.map(n => n.title)); } - if (argName == 'notebook') { + if (argName === 'notebook') { const folders = await Folder.search({ titlePattern: `${next}*` }); l.push(...folders.map(n => n.title)); } - if (argName == 'item') { + if (argName === 'item') { const notes = currentFolder ? await Note.previews(currentFolder.id, { titlePattern: `${next}*` }) : []; const folders = await Folder.search({ titlePattern: `${next}*` }); l.push(...notes.map(n => n.title), folders.map(n => n.title)); } - if (argName == 'tag') { + if (argName === 'tag') { const tags = await Tag.search({ titlePattern: `${next}*` }); l.push(...tags.map(n => n.title)); } - if (argName == 'file') { + if (argName === 'file') { const files = await fs.readdir('.'); l.push(...files); } - if (argName == 'tag-command') { + if (argName === 'tag-command') { const c = filterList(['add', 'remove', 'list', 'notetags'], next); l.push(...c); } - if (argName == 'todo-command') { + if (argName === 'todo-command') { const c = filterList(['toggle', 'clear'], next); l.push(...c); } diff --git a/packages/app-cli/app/build-doc.js b/packages/app-cli/app/build-doc.js index bcc0a84d93..8f7e4ec8fd 100644 --- a/packages/app-cli/app/build-doc.js +++ b/packages/app-cli/app/build-doc.js @@ -52,7 +52,7 @@ function getCommands() { fs.readdirSync(__dirname).forEach(path => { if (path.indexOf('command-') !== 0) return; const ext = fileExtension(path); - if (ext != 'js') return; + if (ext !== 'js') return; const CommandClass = require(`./${path}`); const cmd = new CommandClass(); diff --git a/packages/app-cli/app/cli-integration-tests.js b/packages/app-cli/app/cli-integration-tests.js index c536ace1d9..2d5619dd28 100644 --- a/packages/app-cli/app/cli-integration-tests.js +++ b/packages/app-cli/app/cli-integration-tests.js @@ -222,7 +222,7 @@ async function main() { for (const n in testUnits) { if (!testUnits.hasOwnProperty(n)) continue; - if (onlyThisTest && n != onlyThisTest) continue; + if (onlyThisTest && n !== onlyThisTest) continue; await clearDatabase(); const testName = n.substr(4).toLowerCase(); diff --git a/packages/app-cli/app/cli-utils.js b/packages/app-cli/app/cli-utils.js index 108e47bedd..98eb5d5ed1 100644 --- a/packages/app-cli/app/cli-utils.js +++ b/packages/app-cli/app/cli-utils.js @@ -21,7 +21,7 @@ cliUtils.printArray = function(logFunction, rows) { for (let j = 0; j < row.length; j++) { const item = row[j]; const width = item ? item.toString().length : 0; - const align = typeof item == 'number' ? ALIGN_RIGHT : ALIGN_LEFT; + const align = typeof item === 'number' ? ALIGN_RIGHT : ALIGN_LEFT; if (!colWidths[j] || colWidths[j] < width) colWidths[j] = width; if (colAligns.length <= j) colAligns[j] = align; } @@ -32,7 +32,7 @@ cliUtils.printArray = function(logFunction, rows) { for (let col = 0; col < colWidths.length; col++) { const item = rows[row][col]; const width = colWidths[col]; - const dir = colAligns[col] == ALIGN_LEFT ? stringPadding.RIGHT : stringPadding.LEFT; + const dir = colAligns[col] === ALIGN_LEFT ? stringPadding.RIGHT : stringPadding.LEFT; line.push(stringPadding(item, width, ' ', dir)); } logFunction(line.join(' ')); @@ -45,13 +45,13 @@ cliUtils.parseFlags = function(flags) { for (let i = 0; i < flags.length; i++) { let f = flags[i].trim(); - if (f.substr(0, 2) == '--') { + if (f.substr(0, 2) === '--') { f = f.split(' '); output.long = f[0].substr(2).trim(); - if (f.length == 2) { + if (f.length === 2) { output.arg = cliUtils.parseCommandArg(f[1].trim()); } - } else if (f.substr(0, 1) == '-') { + } else if (f.substr(0, 1) === '-') { output.short = f.substr(1); } } @@ -65,9 +65,9 @@ cliUtils.parseCommandArg = function(arg) { const c2 = arg[arg.length - 1]; const name = arg.substr(1, arg.length - 2); - if (c1 == '<' && c2 == '>') { + if (c1 === '<' && c2 === '>') { return { required: true, name: name }; - } else if (c1 == '[' && c2 == ']') { + } else if (c1 === '[' && c2 === ']') { return { required: false, name: name }; } else { throw new Error(`Invalid command arg: ${arg}`); @@ -83,7 +83,7 @@ cliUtils.makeCommandArgs = function(cmd, argv) { const booleanFlags = []; const aliases = {}; for (let i = 0; i < options.length; i++) { - if (options[i].length != 2) throw new Error(`Invalid options: ${options[i]}`); + if (options[i].length !== 2) throw new Error(`Invalid options: ${options[i]}`); let flags = options[i][0]; flags = cliUtils.parseFlags(flags); @@ -117,7 +117,7 @@ cliUtils.makeCommandArgs = function(cmd, argv) { const argOptions = {}; for (const key in args) { if (!args.hasOwnProperty(key)) continue; - if (key == '_') continue; + if (key === '_') continue; argOptions[key] = args[key]; } @@ -170,7 +170,7 @@ cliUtils.promptConfirm = function(message, answers = null) { return new Promise((resolve) => { rl.question(`${message} `, answer => { - const ok = !answer || answer.toLowerCase() == answers[0].toLowerCase(); + const ok = !answer || answer.toLowerCase() === answers[0].toLowerCase(); rl.close(); resolve(ok); }); diff --git a/packages/app-cli/app/command-config.js b/packages/app-cli/app/command-config.js index e16379f6a7..50b626d6f1 100644 --- a/packages/app-cli/app/command-config.js +++ b/packages/app-cli/app/command-config.js @@ -122,7 +122,7 @@ class Command extends BaseCommand { } - if (args.name == 'locale') { + if (args.name === 'locale') { setLocale(Setting.value('locale')); } diff --git a/packages/app-cli/app/command-ls.js b/packages/app-cli/app/command-ls.js index 1776c89c46..e7687c21d7 100644 --- a/packages/app-cli/app/command-ls.js +++ b/packages/app-cli/app/command-ls.js @@ -44,7 +44,7 @@ class Command extends BaseCommand { queryOptions.orderBy = options.sort; queryOptions.orderByDir = 'ASC'; } - if (options.reverse === true) queryOptions.orderByDir = queryOptions.orderByDir == 'ASC' ? 'DESC' : 'ASC'; + if (options.reverse === true) queryOptions.orderByDir = queryOptions.orderByDir === 'ASC' ? 'DESC' : 'ASC'; queryOptions.caseInsensitive = true; if (options.type) { queryOptions.itemTypes = []; @@ -55,7 +55,7 @@ class Command extends BaseCommand { queryOptions.uncompletedTodosOnTop = Setting.value('uncompletedTodosOnTop'); let modelType = null; - if (pattern == '/' || !app().currentFolder()) { + if (pattern === '/' || !app().currentFolder()) { queryOptions.includeConflictFolder = true; items = await Folder.all(queryOptions); modelType = Folder.modelType(); @@ -65,7 +65,7 @@ class Command extends BaseCommand { modelType = Note.modelType(); } - if (options.format && options.format == 'json') { + if (options.format && options.format === 'json') { this.stdout(JSON.stringify(items)); } else { let hasTodos = false; @@ -88,7 +88,7 @@ class Command extends BaseCommand { row.push(BaseModel.shortId(item.id)); shortIdShown = true; - if (modelType == Folder.modelType()) { + if (modelType === Folder.modelType()) { row.push(await Folder.noteCount(item.id)); } diff --git a/packages/app-cli/app/command-sync.ts b/packages/app-cli/app/command-sync.ts index 894f395996..123f6066c8 100644 --- a/packages/app-cli/app/command-sync.ts +++ b/packages/app-cli/app/command-sync.ts @@ -133,7 +133,7 @@ class Command extends BaseCommand { this.releaseLockFn_ = await Command.lockFile(lockFilePath); } catch (error) { - if (error.code == 'ELOCKED') { + if (error.code === 'ELOCKED') { const msg = _('Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at "%s" and resume the operation.', error.file); this.stdout(msg); return; @@ -222,7 +222,7 @@ class Command extends BaseCommand { const newContext = await sync.start(options); Setting.setValue(contextKey, JSON.stringify(newContext)); } catch (error) { - if (error.code == 'alreadyStarted') { + if (error.code === 'alreadyStarted') { this.stdout(error.message); } else { throw error; diff --git a/packages/app-cli/app/command-tag.js b/packages/app-cli/app/command-tag.js index e979b6f7e8..bd49f50a63 100644 --- a/packages/app-cli/app/command-tag.js +++ b/packages/app-cli/app/command-tag.js @@ -30,21 +30,21 @@ class Command extends BaseCommand { const command = args['tag-command']; - if (command == 'remove' && !tag) throw new Error(_('Cannot find "%s".', args.tag)); + if (command === 'remove' && !tag) throw new Error(_('Cannot find "%s".', args.tag)); - if (command == 'add') { + if (command === 'add') { if (!notes.length) throw new Error(_('Cannot find "%s".', args.note)); if (!tag) tag = await Tag.save({ title: args.tag }, { userSideValidation: true }); for (let i = 0; i < notes.length; i++) { await Tag.addNote(tag.id, notes[i].id); } - } else if (command == 'remove') { + } else if (command === 'remove') { if (!tag) throw new Error(_('Cannot find "%s".', args.tag)); if (!notes.length) throw new Error(_('Cannot find "%s".', args.note)); for (let i = 0; i < notes.length; i++) { await Tag.removeNote(tag.id, notes[i].id); } - } else if (command == 'list') { + } else if (command === 'list') { if (tag) { const notes = await Tag.notes(tag.id); notes.map(note => { @@ -75,7 +75,7 @@ class Command extends BaseCommand { this.stdout(tag.title); }); } - } else if (command == 'notetags') { + } else if (command === 'notetags') { if (args.tag) { const note = await app().loadItem(BaseModel.TYPE_NOTE, args.tag); if (!note) throw new Error(_('Cannot find "%s".', args.tag)); diff --git a/packages/app-cli/app/command-todo.js b/packages/app-cli/app/command-todo.js index 2d50e8f0c7..90a810396d 100644 --- a/packages/app-cli/app/command-todo.js +++ b/packages/app-cli/app/command-todo.js @@ -29,13 +29,13 @@ class Command extends BaseCommand { id: note.id, }; - if (action == 'toggle') { + if (action === 'toggle') { if (!note.is_todo) { toSave = Note.toggleIsTodo(note); } else { toSave.todo_completed = note.todo_completed ? 0 : time.unixMs(); } - } else if (action == 'clear') { + } else if (action === 'clear') { toSave.is_todo = 0; } diff --git a/packages/app-cli/app/fuzzing.js b/packages/app-cli/app/fuzzing.js index 2b91505548..c89dbf4d30 100644 --- a/packages/app-cli/app/fuzzing.js +++ b/packages/app-cli/app/fuzzing.js @@ -2071,7 +2071,7 @@ function execCommand(client, command, options = {}) { return new Promise((resolve, reject) => { const childProcess = exec(cmd, (error, stdout, stderr) => { if (error) { - if (error.signal == 'SIGTERM') { + if (error.signal === 'SIGTERM') { resolve('Process was killed'); } else { logger.error(stderr); @@ -2103,7 +2103,7 @@ async function clientItems(client) { function randomTag(items) { const tags = []; for (let i = 0; i < items.length; i++) { - if (items[i].type_ != 5) continue; + if (items[i].type_ !== 5) continue; tags.push(items[i]); } @@ -2113,7 +2113,7 @@ function randomTag(items) { function randomNote(items) { const notes = []; for (let i = 0; i < items.length; i++) { - if (items[i].type_ != 1) continue; + if (items[i].type_ !== 1) continue; notes.push(items[i]); } @@ -2131,11 +2131,11 @@ async function execRandomCommand(client) { const item = randomElement(items); if (!item) return; - if (item.type_ == 1) { + if (item.type_ === 1) { return execCommand(client, `rm -f ${item.id}`); - } else if (item.type_ == 2) { + } else if (item.type_ === 2) { return execCommand(client, `rm -r -f ${item.id}`); - } else if (item.type_ == 5) { + } else if (item.type_ === 5) { // tag } else { throw new Error(`Unknown type: ${item.type_}`); @@ -2213,7 +2213,7 @@ function randomNextCheckTime() { function findItem(items, itemId) { for (let i = 0; i < items.length; i++) { - if (items[i].id == itemId) return items[i]; + if (items[i].id === itemId) return items[i]; } return null; } @@ -2225,7 +2225,7 @@ function compareItems(item1, item2) { const p1 = item1[n]; const p2 = item2[n]; - if (n == 'notes_') { + if (n === 'notes_') { p1.sort(); p2.sort(); if (JSON.stringify(p1) !== JSON.stringify(p2)) { @@ -2246,7 +2246,7 @@ function findMissingItems_(items1, items2) { let found = false; for (let j = 0; j < items2.length; j++) { const item2 = items2[j]; - if (item1.id == item2.id) { + if (item1.id === item2.id) { found = true; break; } @@ -2340,9 +2340,9 @@ async function main() { let state = 'commands'; setInterval(async () => { - if (state == 'waitForSyncCheck') return; + if (state === 'waitForSyncCheck') return; - if (state == 'syncCheck') { + if (state === 'syncCheck') { state = 'waitForSyncCheck'; const clientItems = []; // Up to 3 sync operations must be performed by each clients in order for them @@ -2371,7 +2371,7 @@ async function main() { return; } - if (state == 'waitForClients') { + if (state === 'waitForClients') { for (let i = 0; i < clients.length; i++) { if (clients[i].activeCommandCount > 0) return; } @@ -2380,7 +2380,7 @@ async function main() { return; } - if (state == 'commands') { + if (state === 'commands') { if (nextSyncCheckTime <= time.unixMs()) { state = 'waitForClients'; return; diff --git a/packages/app-cli/app/main.js b/packages/app-cli/app/main.js index 9d29637ea1..dd2d691017 100644 --- a/packages/app-cli/app/main.js +++ b/packages/app-cli/app/main.js @@ -82,13 +82,13 @@ if (process.platform === 'win32') { process.stdout.on('error', function(err) { // https://stackoverflow.com/questions/12329816/error-write-epipe-when-piping-node-output-to-head#15884508 - if (err.code == 'EPIPE') { + if (err.code === 'EPIPE') { process.exit(0); } }); application.start(process.argv).catch(error => { - if (error.code == 'flagError') { + if (error.code === 'flagError') { console.error(error.message); console.error(_('Type `joplin help` for usage information.')); } else { diff --git a/packages/app-cli/tests/feature_NoteHistory.js b/packages/app-cli/tests/feature_NoteHistory.js index 84b6350568..ca07340fd3 100644 --- a/packages/app-cli/tests/feature_NoteHistory.js +++ b/packages/app-cli/tests/feature_NoteHistory.js @@ -30,7 +30,7 @@ describe('feature_NoteHistory', function() { }); afterEach(async (done) => { - if (testApp !== null) await testApp.destroy(); + if (testApp) await testApp.destroy(); testApp = null; done(); }); diff --git a/packages/app-clipper/content_scripts/index.js b/packages/app-clipper/content_scripts/index.js index 3ccc01b1f5..2714c5911c 100644 --- a/packages/app-clipper/content_scripts/index.js +++ b/packages/app-clipper/content_scripts/index.js @@ -352,7 +352,7 @@ } function isPagePdf() { - return document.contentType == 'application/pdf'; + return document.contentType === 'application/pdf'; } function embedPageUrl() { diff --git a/packages/app-clipper/popup/scripts/start.js b/packages/app-clipper/popup/scripts/start.js index 76e0d3d4f6..d5fd9cba9f 100644 --- a/packages/app-clipper/popup/scripts/start.js +++ b/packages/app-clipper/popup/scripts/start.js @@ -67,7 +67,7 @@ checkBrowsers(paths.appPath, isInteractive) return choosePort(HOST, DEFAULT_PORT); }) .then(port => { - if (port == null) { + if (!port) { // We have not found a port. return; } diff --git a/packages/app-desktop/app.ts b/packages/app-desktop/app.ts index dbd465b91d..4abffde5a0 100644 --- a/packages/app-desktop/app.ts +++ b/packages/app-desktop/app.ts @@ -104,22 +104,22 @@ class Application extends BaseApplication { } protected async generalMiddleware(store: any, next: any, action: any) { - if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'locale' || action.type == 'SETTING_UPDATE_ALL') { + if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'locale' || action.type === 'SETTING_UPDATE_ALL') { setLocale(Setting.value('locale')); // The bridge runs within the main process, with its own instance of locale.js // so it needs to be set too here. bridge().setLocale(Setting.value('locale')); } - if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'showTrayIcon' || action.type == 'SETTING_UPDATE_ALL') { + if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'showTrayIcon' || action.type === 'SETTING_UPDATE_ALL') { this.updateTray(); } - if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'style.editor.fontFamily' || action.type == 'SETTING_UPDATE_ALL') { + if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'style.editor.fontFamily' || action.type === 'SETTING_UPDATE_ALL') { this.updateEditorFont(); } - if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'windowContentZoomFactor' || action.type == 'SETTING_UPDATE_ALL') { + if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'windowContentZoomFactor' || action.type === 'SETTING_UPDATE_ALL') { webFrame.setZoomFactor(Setting.value('windowContentZoomFactor') / 100); } @@ -142,7 +142,7 @@ class Application extends BaseApplication { await Folder.expandTree(newState.folders, action.folderId); } - if (this.hasGui() && ((action.type == 'SETTING_UPDATE_ONE' && ['themeAutoDetect', 'theme', 'preferredLightTheme', 'preferredDarkTheme'].includes(action.key)) || action.type == 'SETTING_UPDATE_ALL')) { + if (this.hasGui() && ((action.type === 'SETTING_UPDATE_ONE' && ['themeAutoDetect', 'theme', 'preferredLightTheme', 'preferredDarkTheme'].includes(action.key)) || action.type === 'SETTING_UPDATE_ALL')) { this.handleThemeAutoDetect(); } @@ -387,7 +387,7 @@ class Application extends BaseApplication { PerFolderSortOrderService.initialize(); - CommandService.instance().initialize(this.store(), Setting.value('env') == 'dev', stateToWhenClauseContext); + CommandService.instance().initialize(this.store(), Setting.value('env') === 'dev', stateToWhenClauseContext); for (const command of commands) { CommandService.instance().registerDeclaration(command.declaration); diff --git a/packages/app-desktop/checkForUpdates.ts b/packages/app-desktop/checkForUpdates.ts index 4858b3f239..5f6100d37a 100644 --- a/packages/app-desktop/checkForUpdates.ts +++ b/packages/app-desktop/checkForUpdates.ts @@ -86,7 +86,7 @@ async function fetchLatestRelease(options: CheckForUpdateOptions) { const ext = fileExtension(asset.name); if (platform === 'win32' && ext === 'exe') { if (shim.isPortable()) { - found = asset.name == 'JoplinPortable.exe'; + found = asset.name === 'JoplinPortable.exe'; } else { found = !!asset.name.match(/^Joplin-Setup-[\d.]+\.exe$/); } diff --git a/packages/app-desktop/generateSha512.js b/packages/app-desktop/generateSha512.js index 11af79d7c6..900580948f 100644 --- a/packages/app-desktop/generateSha512.js +++ b/packages/app-desktop/generateSha512.js @@ -4,7 +4,7 @@ const os = require('os'); const sha512 = require('js-sha512'); const generateChecksumFile = () => { - if (os.platform() != 'linux') { + if (os.platform() !== 'linux') { return []; // SHA-512 is only for AppImage } const distDirName = 'dist'; @@ -18,7 +18,7 @@ const generateChecksumFile = () => { break; } } - if (appImageName == '') { + if (appImageName === '') { throw 'AppImage not found!'; } const appImagePath = path.join(distPath, appImageName); 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 04a7b31daa..6f55cb58eb 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts @@ -37,7 +37,7 @@ export default function useEditorSearch(CodeMirror: any) { return { token: function(stream: any) { query.lastIndex = stream.pos; const match = query.exec(stream.string); - if (match && match.index == stream.pos) { + if (match && match.index === stream.pos) { stream.pos += match[0].length || 1; return 'search-marker'; } else if (match) { @@ -126,7 +126,7 @@ export default function useEditorSearch(CodeMirror: any) { // SEARCHOVERLAY // We only want to highlight all matches when there is only 1 search term - if (keywords.length !== 1 || keywords[0].value == '') { + if (keywords.length !== 1 || keywords[0].value === '') { clearOverlay(this); const prev = keywords.length > 1 ? keywords[0].value : ''; setPreviousKeywordValue(prev); diff --git a/packages/app-mobile/components/app-nav.js b/packages/app-mobile/components/app-nav.js index daa092166e..9bbd89887b 100644 --- a/packages/app-mobile/components/app-nav.js +++ b/packages/app-mobile/components/app-nav.js @@ -48,9 +48,9 @@ class AppNavComponent extends Component { let notesScreenVisible = false; let searchScreenVisible = false; - if (route.routeName == 'Notes') { + if (route.routeName === 'Notes') { notesScreenVisible = true; - } else if (route.routeName == 'Search') { + } else if (route.routeName === 'Search') { searchScreenVisible = true; } else { Screen = this.props.screens[route.routeName].screen; @@ -59,7 +59,7 @@ class AppNavComponent extends Component { // Keep the search screen loaded if the user is viewing a note from that search screen // so that if the back button is pressed, the screen is still loaded. However, unload // it if navigating away. - const searchScreenLoaded = searchScreenVisible || (this.previousRouteName_ == 'Search' && route.routeName == 'Note'); + const searchScreenLoaded = searchScreenVisible || (this.previousRouteName_ === 'Search' && route.routeName === 'Note'); this.previousRouteName_ = route.routeName; diff --git a/packages/app-mobile/components/note-list.js b/packages/app-mobile/components/note-list.js index 29226c3e30..9fb309aaf3 100644 --- a/packages/app-mobile/components/note-list.js +++ b/packages/app-mobile/components/note-list.js @@ -57,7 +57,7 @@ class NoteListComponent extends Component { filterNotes(notes) { const todoFilter = 'all'; // Setting.value('todoFilter'); - if (todoFilter == 'all') return notes; + if (todoFilter === 'all') return notes; const now = time.unixMs(); const maxInterval = 1000 * 60 * 60 * 24; @@ -67,8 +67,8 @@ class NoteListComponent extends Component { for (let i = 0; i < notes.length; i++) { const note = notes[i]; if (note.is_todo) { - if (todoFilter == 'recent' && note.user_updated_time < notRecentTime && !!note.todo_completed) continue; - if (todoFilter == 'nonCompleted' && !!note.todo_completed) continue; + if (todoFilter === 'recent' && note.user_updated_time < notRecentTime && !!note.todo_completed) continue; + if (todoFilter === 'nonCompleted' && !!note.todo_completed) continue; } output.push(note); } @@ -77,7 +77,7 @@ class NoteListComponent extends Component { UNSAFE_componentWillReceiveProps(newProps) { // Make sure scroll position is reset when switching from one folder to another or to a tag list. - if (this.rootRef_ && newProps.notesSource != this.props.notesSource) { + if (this.rootRef_ && newProps.notesSource !== this.props.notesSource) { this.rootRef_.scrollToOffset({ offset: 0, animated: false }); } } diff --git a/packages/app-mobile/components/screen-header.js b/packages/app-mobile/components/screen-header.js index 3a1c668973..442702b7ac 100644 --- a/packages/app-mobile/components/screen-header.js +++ b/packages/app-mobile/components/screen-header.js @@ -197,7 +197,7 @@ class ScreenHeaderComponent extends React.PureComponent { } menu_select(value) { - if (typeof value == 'function') { + if (typeof value === 'function') { value(); } } diff --git a/packages/app-mobile/components/screens/ConfigScreen.tsx b/packages/app-mobile/components/screens/ConfigScreen.tsx index 6b31cc85a1..47bffc457d 100644 --- a/packages/app-mobile/components/screens/ConfigScreen.tsx +++ b/packages/app-mobile/components/screens/ConfigScreen.tsx @@ -469,7 +469,7 @@ class ConfigScreenComponent extends BaseScreenComponent { {descriptionComp} ); - } else if (md.type == Setting.TYPE_BOOL) { + } else if (md.type === Setting.TYPE_BOOL) { return this.renderToggle(key, md.label(), value, updateSettingValue, descriptionComp); // return ( // @@ -482,7 +482,7 @@ class ConfigScreenComponent extends BaseScreenComponent { // {descriptionComp} // // ); - } else if (md.type == Setting.TYPE_INT) { + } else if (md.type === Setting.TYPE_INT) { const unitLabel = md.unitLabel ? md.unitLabel(value) : value; // Note: Do NOT add the minimumTrackTintColor and maximumTrackTintColor props // on the Slider as they are buggy and can crash the app on certain devices. @@ -499,7 +499,7 @@ class ConfigScreenComponent extends BaseScreenComponent { ); - } else if (md.type == Setting.TYPE_STRING) { + } else if (md.type === Setting.TYPE_STRING) { if (md.key === 'sync.2.path' && Platform.OS === 'android' && Platform.Version > 28) { return ( diff --git a/packages/app-mobile/components/screens/Note.tsx b/packages/app-mobile/components/screens/Note.tsx index c3bd7005f3..47da9164cf 100644 --- a/packages/app-mobile/components/screens/Note.tsx +++ b/packages/app-mobile/components/screens/Note.tsx @@ -103,8 +103,8 @@ class NoteScreenComponent extends BaseScreenComponent { if (this.isModified()) { const buttonId = await dialogs.pop(this, _('This note has been modified:'), [{ text: _('Save changes'), id: 'save' }, { text: _('Discard changes'), id: 'discard' }, { text: _('Cancel'), id: 'cancel' }]); - if (buttonId == 'cancel') return true; - if (buttonId == 'save') await this.saveNoteButton_press(); + if (buttonId === 'cancel') return true; + if (buttonId === 'save') await this.saveNoteButton_press(); } return false; @@ -126,7 +126,7 @@ class NoteScreenComponent extends BaseScreenComponent { return false; } - if (this.state.mode == 'edit') { + if (this.state.mode === 'edit') { Keyboard.dismiss(); this.setState({ @@ -603,7 +603,7 @@ class NoteScreenComponent extends BaseScreenComponent { reg.logger().info('New dimensions ', dimensions); - const format = mimeType == 'image/png' ? 'PNG' : 'JPEG'; + const format = mimeType === 'image/png' ? 'PNG' : 'JPEG'; reg.logger().info(`Resizing image ${localFilePath}`); const resizedImage = await ImageResizer.createResizedImage(localFilePath, dimensions.width, dimensions.height, format, 85); // , 0, targetPath); @@ -676,7 +676,7 @@ class NoteScreenComponent extends BaseScreenComponent { const targetPath = Resource.fullPath(resource); try { - if (mimeType == 'image/jpeg' || mimeType == 'image/jpg' || mimeType == 'image/png') { + if (mimeType === 'image/jpeg' || mimeType === 'image/jpg' || mimeType === 'image/png') { const done = await this.resizeImage(localFilePath, targetPath, mimeType); if (!done) return; } else { @@ -711,7 +711,7 @@ class NoteScreenComponent extends BaseScreenComponent { const newNote = Object.assign({}, this.state.note); - if (this.state.mode == 'edit' && !!this.selection) { + if (this.state.mode === 'edit' && !!this.selection) { const newText = `\n${resourceTag}\n`; const prefix = newNote.body.substring(0, this.selection.start); @@ -1068,7 +1068,7 @@ class NoteScreenComponent extends BaseScreenComponent { const keywords = this.props.searchQuery && !!this.props.ftsEnabled ? this.props.highlightedWords : emptyArray; let bodyComponent = null; - if (this.state.mode == 'view') { + if (this.state.mode === 'view') { // Note: as of 2018-12-29 it's important not to display the viewer if the note body is empty, // to avoid the HACK_webviewLoadingState related bug. bodyComponent = @@ -1154,7 +1154,7 @@ class NoteScreenComponent extends BaseScreenComponent { }, }); - if (this.state.mode == 'edit') return null; + if (this.state.mode === 'edit') return null; return ; }; @@ -1162,7 +1162,7 @@ class NoteScreenComponent extends BaseScreenComponent { const actionButtonComp = renderActionButton(); // Save button is not really needed anymore with the improved save logic - const showSaveButton = false; // this.state.mode == 'edit' || this.isModified() || this.saveButtonHasBeenShown_; + const showSaveButton = false; // this.state.mode === 'edit' || this.isModified() || this.saveButtonHasBeenShown_; const saveButtonDisabled = true;// !this.isModified(); if (showSaveButton) this.saveButtonHasBeenShown_ = true; diff --git a/packages/app-mobile/components/screens/log.js b/packages/app-mobile/components/screens/log.js index 41241a8968..0cd92b7ec5 100644 --- a/packages/app-mobile/components/screens/log.js +++ b/packages/app-mobile/components/screens/log.js @@ -83,8 +83,8 @@ class LogScreenComponent extends BaseScreenComponent { render() { const renderRow = ({ item }) => { let textStyle = this.styles().rowText; - if (item.level == Logger.LEVEL_WARN) textStyle = this.styles().rowTextWarn; - if (item.level == Logger.LEVEL_ERROR) textStyle = this.styles().rowTextError; + if (item.level === Logger.LEVEL_WARN) textStyle = this.styles().rowTextWarn; + if (item.level === Logger.LEVEL_ERROR) textStyle = this.styles().rowTextError; return ( diff --git a/packages/app-mobile/components/screens/notes.js b/packages/app-mobile/components/screens/notes.js index 2d47f634fb..b513d498b6 100644 --- a/packages/app-mobile/components/screens/notes.js +++ b/packages/app-mobile/components/screens/notes.js @@ -109,7 +109,7 @@ class NotesScreenComponent extends BaseScreenComponent { } async componentDidUpdate(prevProps) { - if (prevProps.notesOrder !== this.props.notesOrder || prevProps.selectedFolderId != this.props.selectedFolderId || prevProps.selectedTagId != this.props.selectedTagId || prevProps.selectedSmartFilterId != this.props.selectedSmartFilterId || prevProps.notesParentType != this.props.notesParentType) { + if (prevProps.notesOrder !== this.props.notesOrder || prevProps.selectedFolderId !== this.props.selectedFolderId || prevProps.selectedTagId !== this.props.selectedTagId || prevProps.selectedSmartFilterId !== this.props.selectedSmartFilterId || prevProps.notesParentType !== this.props.notesParentType) { await this.refreshNotes(this.props); } } @@ -132,7 +132,7 @@ class NotesScreenComponent extends BaseScreenComponent { parentId: parent.id, }); - if (source == props.notesSource) return; + if (source === props.notesSource) return; let notes = []; if (props.notesParentType === 'Folder') { @@ -180,11 +180,11 @@ class NotesScreenComponent extends BaseScreenComponent { if (!props) props = this.props; let output = null; - if (props.notesParentType == 'Folder') { + if (props.notesParentType === 'Folder') { output = Folder.byId(props.folders, props.selectedFolderId); - } else if (props.notesParentType == 'Tag') { + } else if (props.notesParentType === 'Tag') { output = Tag.byId(props.tags, props.selectedTagId); - } else if (props.notesParentType == 'SmartFilter') { + } else if (props.notesParentType === 'SmartFilter') { output = { id: this.props.selectedSmartFilterId, title: _('All notes') }; } else { return null; @@ -230,7 +230,7 @@ class NotesScreenComponent extends BaseScreenComponent { const icon = Folder.unserializeIcon(parent.icon); const iconString = icon ? `${icon.emoji} ` : ''; - let buttonFolderId = this.props.selectedFolderId != Folder.conflictFolderId() ? this.props.selectedFolderId : null; + let buttonFolderId = this.props.selectedFolderId !== Folder.conflictFolderId() ? this.props.selectedFolderId : null; if (!buttonFolderId) buttonFolderId = this.props.activeFolderId; const addFolderNoteButtons = !!buttonFolderId; diff --git a/packages/app-mobile/root.tsx b/packages/app-mobile/root.tsx index d937c0dfa3..cfac4ed4db 100644 --- a/packages/app-mobile/root.tsx +++ b/packages/app-mobile/root.tsx @@ -126,7 +126,7 @@ const generalMiddleware = (store: any) => (next: any) => async (action: any) => await reduxSharedMiddleware(store, next, action); - if (action.type == 'NAV_GO') Keyboard.dismiss(); + if (action.type === 'NAV_GO') Keyboard.dismiss(); if (['NOTE_UPDATE_ONE', 'NOTE_DELETE', 'FOLDER_UPDATE_ONE', 'FOLDER_DELETE'].indexOf(action.type) >= 0) { if (!await reg.syncTarget().syncStarted()) void reg.scheduleSync(5 * 1000, { syncSteps: ['update_remote', 'delete_remote'] }, true); @@ -137,20 +137,20 @@ const generalMiddleware = (store: any) => (next: any) => async (action: any) => await AlarmService.updateNoteNotification(action.id, action.type === 'NOTE_DELETE'); } - if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'sync.interval' || action.type == 'SETTING_UPDATE_ALL') { + if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'sync.interval' || action.type === 'SETTING_UPDATE_ALL') { reg.setupRecurrentSync(); } - if ((action.type == 'SETTING_UPDATE_ONE' && (action.key == 'dateFormat' || action.key == 'timeFormat')) || (action.type == 'SETTING_UPDATE_ALL')) { + if ((action.type === 'SETTING_UPDATE_ONE' && (action.key === 'dateFormat' || action.key === 'timeFormat')) || (action.type === 'SETTING_UPDATE_ALL')) { time.setDateFormat(Setting.value('dateFormat')); time.setTimeFormat(Setting.value('timeFormat')); } - if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'locale' || action.type == 'SETTING_UPDATE_ALL') { + if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'locale' || action.type === 'SETTING_UPDATE_ALL') { setLocale(Setting.value('locale')); } - if ((action.type == 'SETTING_UPDATE_ONE' && (action.key.indexOf('encryption.') === 0)) || (action.type == 'SETTING_UPDATE_ALL')) { + if ((action.type === 'SETTING_UPDATE_ONE' && (action.key.indexOf('encryption.') === 0)) || (action.type === 'SETTING_UPDATE_ALL')) { await loadMasterKeysFromSettings(EncryptionService.instance()); void DecryptionWorker.instance().scheduleStart(); const loadedMasterKeyIds = EncryptionService.instance().loadedMasterKeyIds(); @@ -165,7 +165,7 @@ const generalMiddleware = (store: any) => (next: any) => async (action: any) => void reg.scheduleSync(null, null, true); } - if (action.type == 'NAV_GO' && action.routeName == 'Notes') { + if (action.type === 'NAV_GO' && action.routeName === 'Notes') { Setting.setValue('activeFolderId', newState.selectedFolderId); } @@ -224,7 +224,7 @@ const appReducer = (state = appDefaultState, action: any) => { let newAction = null; while (navHistory.length) { newAction = navHistory.pop(); - if (newAction.routeName != state.route.routeName) break; + if (newAction.routeName !== state.route.routeName) break; } action = newAction ? newAction : navHistory.pop(); @@ -243,7 +243,7 @@ const appReducer = (state = appDefaultState, action: any) => { // If the route *name* is the same (even if the other parameters are different), we // overwrite the last route in the history with the current one. If the route name // is different, we push a new history entry. - if (currentRoute.routeName == action.routeName) { + if (currentRoute.routeName === action.routeName) { // nothing } else { navHistory.push(currentRoute); @@ -258,7 +258,7 @@ const appReducer = (state = appDefaultState, action: any) => { // is probably not a common workflow. for (let i = 0; i < navHistory.length; i++) { const n = navHistory[i]; - if (n.routeName == action.routeName) { + if (n.routeName === action.routeName) { navHistory[i] = Object.assign({}, action); } } @@ -416,7 +416,7 @@ async function initialize(dispatch: Function) { mainLogger.addTarget(TargetType.Database, { database: logDatabase, source: 'm' }); mainLogger.setLevel(Logger.LEVEL_INFO); - if (Setting.value('env') == 'dev') { + if (Setting.value('env') === 'dev') { mainLogger.addTarget(TargetType.Console); mainLogger.setLevel(Logger.LEVEL_DEBUG); } @@ -434,7 +434,7 @@ async function initialize(dispatch: Function) { const dbLogger = new Logger(); dbLogger.addTarget(TargetType.Database, { database: logDatabase, source: 'm' }); - if (Setting.value('env') == 'dev') { + if (Setting.value('env') === 'dev') { dbLogger.addTarget(TargetType.Console); dbLogger.setLevel(Logger.LEVEL_INFO); // Set to LEVEL_DEBUG for full SQL queries } else { @@ -473,7 +473,7 @@ async function initialize(dispatch: Function) { setRSA(RSA); try { - if (Setting.value('env') == 'prod') { + if (Setting.value('env') === 'prod') { await db.open({ name: 'joplin.sqlite' }); } else { await db.open({ name: 'joplin-1.sqlite' }); @@ -672,7 +672,7 @@ async function initialize(dispatch: Function) { // call will throw an error, alerting us of the issue. Otherwise it will // just print some messages in the console. // ---------------------------------------------------------------------------- - if (Setting.value('env') == 'dev') await runIntegrationTests(); + if (Setting.value('env') === 'dev') await runIntegrationTests(); reg.logger().info('Application initialized'); } @@ -697,7 +697,7 @@ class AppComponent extends React.Component { }; this.handleOpenURL_ = (event: any) => { - if (event.url == ShareExtension.shareURL) { + if (event.url === ShareExtension.shareURL) { void this.handleShareData(); } }; @@ -723,7 +723,7 @@ class AppComponent extends React.Component { // https://discourse.joplinapp.org/t/webdav-config-encryption-config-randomly-lost-on-android/11364 // https://discourse.joplinapp.org/t/android-keeps-on-resetting-my-sync-and-theme/11443 public async componentDidMount() { - if (this.props.appState == 'starting') { + if (this.props.appState === 'starting') { this.props.dispatch({ type: 'APP_STATE_SET', state: 'initializing', @@ -829,7 +829,7 @@ class AppComponent extends React.Component { } public UNSAFE_componentWillReceiveProps(newProps: any) { - if (newProps.syncStarted != this.lastSyncStarted_) { + if (newProps.syncStarted !== this.lastSyncStarted_) { if (!newProps.syncStarted) FoldersScreenUtils.refreshFolders(); this.lastSyncStarted_ = newProps.syncStarted; } @@ -844,7 +844,7 @@ class AppComponent extends React.Component { } public render() { - if (this.props.appState != 'ready') return null; + if (this.props.appState !== 'ready') return null; const theme = themeStyle(this.props.themeId); let sideMenuContent = null; diff --git a/packages/app-mobile/utils/geolocation-react.js b/packages/app-mobile/utils/geolocation-react.js index 9d53df909a..1a85bed9f7 100644 --- a/packages/app-mobile/utils/geolocation-react.js +++ b/packages/app-mobile/utils/geolocation-react.js @@ -19,7 +19,7 @@ class GeolocationReact { } static currentPosition(options = null) { - if (Setting.value('env') == 'dev') return this.currentPosition_testResponse(); + if (Setting.value('env') === 'dev') return this.currentPosition_testResponse(); if (!options) options = {}; if (!('enableHighAccuracy' in options)) options.enableHighAccuracy = true; diff --git a/packages/lib/ArrayUtils.ts b/packages/lib/ArrayUtils.ts index 0522928204..5c275e29fe 100644 --- a/packages/lib/ArrayUtils.ts +++ b/packages/lib/ArrayUtils.ts @@ -18,7 +18,7 @@ export const binarySearch = function(items: any[], value: any) { stopIndex = items.length - 1, middle = Math.floor((stopIndex + startIndex) / 2); - while (items[middle] != value && startIndex < stopIndex) { + while (items[middle] !== value && startIndex < stopIndex) { // adjust search area if (value < items[middle]) { stopIndex = middle - 1; @@ -31,7 +31,7 @@ export const binarySearch = function(items: any[], value: any) { } // make sure it's the right value - return items[middle] != value ? -1 : middle; + return items[middle] !== value ? -1 : middle; }; export const findByKey = function(array: any[], key: any, value: any) { diff --git a/packages/lib/BaseApplication.ts b/packages/lib/BaseApplication.ts index 0297ec005e..52c31b6a7e 100644 --- a/packages/lib/BaseApplication.ts +++ b/packages/lib/BaseApplication.ts @@ -166,57 +166,57 @@ export default class BaseApplication { const arg = argv[0]; const nextArg = argv.length >= 2 ? argv[1] : null; - if (arg == '--profile') { + if (arg === '--profile') { if (!nextArg) throw new JoplinError(_('Usage: %s', '--profile '), 'flagError'); matched.profileDir = nextArg; argv.splice(0, 2); continue; } - if (arg == '--no-welcome') { + if (arg === '--no-welcome') { matched.welcomeDisabled = true; argv.splice(0, 1); continue; } - if (arg == '--env') { + if (arg === '--env') { if (!nextArg) throw new JoplinError(_('Usage: %s', '--env '), 'flagError'); matched.env = nextArg; argv.splice(0, 2); continue; } - if (arg == '--is-demo') { + if (arg === '--is-demo') { Setting.setConstant('isDemo', true); argv.splice(0, 1); continue; } - if (arg == '--open-dev-tools') { + if (arg === '--open-dev-tools') { Setting.setConstant('flagOpenDevTools', true); argv.splice(0, 1); continue; } - if (arg == '--debug') { + if (arg === '--debug') { // Currently only handled by ElectronAppWrapper (isDebugMode property) argv.splice(0, 1); continue; } - if (arg == '--update-geolocation-disabled') { + if (arg === '--update-geolocation-disabled') { Note.updateGeolocationEnabled_ = false; argv.splice(0, 1); continue; } - if (arg == '--stack-trace-enabled') { + if (arg === '--stack-trace-enabled') { this.showStackTraces_ = true; argv.splice(0, 1); continue; } - if (arg == '--log-level') { + if (arg === '--log-level') { if (!nextArg) throw new JoplinError(_('Usage: %s', '--log-level '), 'flagError'); matched.logLevel = Logger.levelStringToId(nextArg); argv.splice(0, 2); @@ -277,7 +277,7 @@ export default class BaseApplication { continue; } - if (arg.length && arg[0] == '-') { + if (arg.length && arg[0] === '-') { throw new JoplinError(_('Unknown flag: %s', arg), 'flagError'); } else { break; @@ -538,12 +538,12 @@ export default class BaseApplication { refreshFolders = true; } - if (action.type == 'HISTORY_BACKWARD' || action.type == 'HISTORY_FORWARD') { + if (action.type === 'HISTORY_BACKWARD' || action.type === 'HISTORY_FORWARD') { refreshNotes = true; refreshNotesUseSelectedNoteId = true; } - if (action.type == 'HISTORY_BACKWARD' || action.type == 'HISTORY_FORWARD' || action.type == 'FOLDER_SELECT' || action.type === 'FOLDER_DELETE' || action.type === 'FOLDER_AND_NOTE_SELECT' || (action.type === 'SEARCH_UPDATE' && newState.notesParentType === 'Folder')) { + if (action.type === 'HISTORY_BACKWARD' || action.type === 'HISTORY_FORWARD' || action.type === 'FOLDER_SELECT' || action.type === 'FOLDER_DELETE' || action.type === 'FOLDER_AND_NOTE_SELECT' || (action.type === 'SEARCH_UPDATE' && newState.notesParentType === 'Folder')) { Setting.setValue('activeFolderId', newState.selectedFolderId); this.currentFolder_ = newState.selectedFolderId ? await Folder.load(newState.selectedFolderId) : null; refreshNotes = true; @@ -554,23 +554,23 @@ export default class BaseApplication { } } - if (this.hasGui() && (action.type == 'NOTE_IS_INSERTING_NOTES' && !action.value)) { + if (this.hasGui() && (action.type === 'NOTE_IS_INSERTING_NOTES' && !action.value)) { refreshNotes = true; } - if (this.hasGui() && ((action.type == 'SETTING_UPDATE_ONE' && action.key == 'uncompletedTodosOnTop') || action.type == 'SETTING_UPDATE_ALL')) { + if (this.hasGui() && ((action.type === 'SETTING_UPDATE_ONE' && action.key === 'uncompletedTodosOnTop') || action.type === 'SETTING_UPDATE_ALL')) { refreshNotes = true; } - if (this.hasGui() && ((action.type == 'SETTING_UPDATE_ONE' && action.key == 'showCompletedTodos') || action.type == 'SETTING_UPDATE_ALL')) { + if (this.hasGui() && ((action.type === 'SETTING_UPDATE_ONE' && action.key === 'showCompletedTodos') || action.type === 'SETTING_UPDATE_ALL')) { refreshNotes = true; } - if (this.hasGui() && ((action.type == 'SETTING_UPDATE_ONE' && action.key.indexOf('notes.sortOrder') === 0) || action.type == 'SETTING_UPDATE_ALL')) { + if (this.hasGui() && ((action.type === 'SETTING_UPDATE_ONE' && action.key.indexOf('notes.sortOrder') === 0) || action.type === 'SETTING_UPDATE_ALL')) { refreshNotes = true; } - if (action.type == 'SMART_FILTER_SELECT') { + if (action.type === 'SMART_FILTER_SELECT') { refreshNotes = true; refreshNotesUseSelectedNoteId = true; } @@ -583,11 +583,11 @@ export default class BaseApplication { refreshNotes = true; } - if (action.type == 'SEARCH_SELECT' || action.type === 'SEARCH_DELETE') { + if (action.type === 'SEARCH_SELECT' || action.type === 'SEARCH_DELETE') { refreshNotes = true; } - if (action.type == 'NOTE_TAG_REMOVE') { + if (action.type === 'NOTE_TAG_REMOVE') { if (newState.notesParentType === 'Tag' && newState.selectedTagId === action.item.id) { if (newState.notes.length === newState.selectedNoteIds.length) { await this.refreshCurrentFolder(); @@ -615,14 +615,14 @@ export default class BaseApplication { refreshFolders = true; } - if (this.hasGui() && action.type == 'SETTING_UPDATE_ALL') { + if (this.hasGui() && action.type === 'SETTING_UPDATE_ALL') { refreshFolders = 'now'; } - if (this.hasGui() && action.type == 'SETTING_UPDATE_ONE' && ( + if (this.hasGui() && action.type === 'SETTING_UPDATE_ONE' && ( action.key.indexOf('folders.sortOrder') === 0 || - action.key == 'showNoteCounts' || - action.key == 'showCompletedTodos')) { + action.key === 'showNoteCounts' || + action.key === 'showCompletedTodos')) { refreshFolders = 'now'; } @@ -634,9 +634,9 @@ export default class BaseApplication { void ResourceFetcher.instance().autoAddResources(); } - if (action.type == 'SETTING_UPDATE_ONE') { + if (action.type === 'SETTING_UPDATE_ONE') { await this.applySettingsSideEffects(action); - } else if (action.type == 'SETTING_UPDATE_ALL') { + } else if (action.type === 'SETTING_UPDATE_ALL') { await this.applySettingsSideEffects(); } @@ -728,7 +728,7 @@ export default class BaseApplication { let initArgs = startFlags.matched; if (argv.length) this.showPromptString_ = false; - let appName = initArgs.env == 'dev' ? 'joplindev' : 'joplin'; + let appName = initArgs.env === 'dev' ? 'joplindev' : 'joplin'; if (Setting.value('appId').indexOf('-desktop') >= 0) appName += '-desktop'; Setting.setConstant('appName', appName); diff --git a/packages/lib/BaseModel.ts b/packages/lib/BaseModel.ts index e1f05d82e8..e8cc8a5c34 100644 --- a/packages/lib/BaseModel.ts +++ b/packages/lib/BaseModel.ts @@ -123,7 +123,7 @@ class BaseModel { static byId(items: any[], id: string) { for (let i = 0; i < items.length; i++) { - if (items[i].id == id) return items[i]; + if (items[i].id === id) return items[i]; } return null; } @@ -138,7 +138,7 @@ class BaseModel { static modelIndexById(items: any[], id: string) { for (let i = 0; i < items.length; i++) { - if (items[i].id == id) return i; + if (items[i].id === id) return i; } return -1; } @@ -200,7 +200,7 @@ class BaseModel { static fieldType(name: string, defaultValue: any = null) { const fields = this.fields(); for (let i = 0; i < fields.length; i++) { - if (fields[i].name == name) return fields[i].type; + if (fields[i].name === name) return fields[i].type; } if (defaultValue !== null) return defaultValue; throw new Error(`Unknown field: ${name}`); @@ -391,7 +391,7 @@ class BaseModel { const output = []; for (const n in newModel) { if (!newModel.hasOwnProperty(n)) continue; - if (n == 'type_') continue; + if (n === 'type_') continue; if (!(n in oldModel) || newModel[n] !== oldModel[n]) { output.push(n); } diff --git a/packages/lib/BaseSyncTarget.ts b/packages/lib/BaseSyncTarget.ts index e199ae0318..10c93a05b6 100644 --- a/packages/lib/BaseSyncTarget.ts +++ b/packages/lib/BaseSyncTarget.ts @@ -104,15 +104,15 @@ export default class BaseSyncTarget { public async synchronizer(): Promise { if (this.synchronizer_) return this.synchronizer_; - if (this.initState_ == 'started') { + if (this.initState_ === 'started') { // Synchronizer is already being initialized, so wait here till it's done. return new Promise((resolve, reject) => { const iid = shim.setInterval(() => { - if (this.initState_ == 'ready') { + if (this.initState_ === 'ready') { shim.clearInterval(iid); resolve(this.synchronizer_); } - if (this.initState_ == 'error') { + if (this.initState_ === 'error') { shim.clearInterval(iid); reject(new Error('Could not initialise synchroniser')); } @@ -141,6 +141,6 @@ export default class BaseSyncTarget { if (!this.synchronizer_) return false; if (!(await this.isAuthenticated())) return false; const sync = await this.synchronizer(); - return sync.state() != 'idle'; + return sync.state() !== 'idle'; } } diff --git a/packages/lib/DropboxApi.js b/packages/lib/DropboxApi.js index b00ef0fa90..7ff89518a6 100644 --- a/packages/lib/DropboxApi.js +++ b/packages/lib/DropboxApi.js @@ -139,9 +139,9 @@ class DropboxApi { // console.info(method + ' ' + url); - if (options.source == 'file' && (method == 'POST' || method == 'PUT')) { + if (options.source === 'file' && (method === 'POST' || method === 'PUT')) { response = await shim.uploadBlob(url, fetchOptions); - } else if (options.target == 'string') { + } else if (options.target === 'string') { response = await shim.fetch(url, fetchOptions); } else { // file diff --git a/packages/lib/JoplinDatabase.ts b/packages/lib/JoplinDatabase.ts index 7c34dada29..6e09cf4eb3 100644 --- a/packages/lib/JoplinDatabase.ts +++ b/packages/lib/JoplinDatabase.ts @@ -296,19 +296,19 @@ export default class JoplinDatabase extends Database { const chain = []; for (let i = 0; i < tableRows.length; i++) { const tableName = tableRows[i].name; - if (tableName == 'android_metadata') continue; - if (tableName == 'table_fields') continue; - if (tableName == 'sqlite_sequence') continue; + if (tableName === 'android_metadata') continue; + if (tableName === 'table_fields') continue; + if (tableName === 'sqlite_sequence') continue; if (tableName.indexOf('notes_fts') === 0) continue; - if (tableName == 'notes_spellfix') continue; - if (tableName == 'search_aux') continue; + if (tableName === 'notes_spellfix') continue; + if (tableName === 'search_aux') continue; chain.push(() => { return this.selectAll(`PRAGMA table_info("${tableName}")`).then(pragmas => { for (let i = 0; i < pragmas.length; i++) { const item = pragmas[i]; // In SQLite, if the default value is a string it has double quotes around it, so remove them here let defaultValue = item.dflt_value; - if (typeof defaultValue == 'string' && defaultValue.length >= 2 && defaultValue[0] == '"' && defaultValue[defaultValue.length - 1] == '"') { + if (typeof defaultValue === 'string' && defaultValue.length >= 2 && defaultValue[0] === '"' && defaultValue[defaultValue.length - 1] === '"') { defaultValue = defaultValue.substr(1, defaultValue.length - 2); } const q = Database.insertQuery('table_fields', { @@ -367,7 +367,7 @@ export default class JoplinDatabase extends Database { this.logger().info(`Upgrading database from version ${fromVersion}`); - if (currentVersionIndex == existingDatabaseVersions.length - 1) return fromVersion; + if (currentVersionIndex === existingDatabaseVersions.length - 1) return fromVersion; let latestVersion = fromVersion; @@ -377,11 +377,11 @@ export default class JoplinDatabase extends Database { let queries: any[] = []; - if (targetVersion == 1) { + if (targetVersion === 1) { queries = this.wrapQueries(this.sqlStringToLines(structureSql)); } - if (targetVersion == 2) { + if (targetVersion === 2) { const newTableSql = ` CREATE TABLE deleted_items ( id INTEGER PRIMARY KEY, @@ -397,16 +397,16 @@ export default class JoplinDatabase extends Database { queries.push({ sql: 'CREATE INDEX deleted_items_sync_target ON deleted_items (sync_target)' }); } - if (targetVersion == 3) { + if (targetVersion === 3) { queries = this.alterColumnQueries('settings', { key: 'TEXT PRIMARY KEY', value: 'TEXT' }); } - if (targetVersion == 4) { + if (targetVersion === 4) { queries.push('INSERT INTO settings (`key`, `value`) VALUES (\'sync.3.context\', (SELECT `value` FROM settings WHERE `key` = \'sync.context\'))'); queries.push('DELETE FROM settings WHERE `key` = "sync.context"'); } - if (targetVersion == 5) { + if (targetVersion === 5) { const tableNames = ['notes', 'folders', 'tags', 'note_tags', 'resources']; for (let i = 0; i < tableNames.length; i++) { const n = tableNames[i]; @@ -418,21 +418,21 @@ export default class JoplinDatabase extends Database { } } - if (targetVersion == 6) { + if (targetVersion === 6) { queries.push('CREATE TABLE alarms (id INTEGER PRIMARY KEY AUTOINCREMENT, note_id TEXT NOT NULL, trigger_time INT NOT NULL)'); queries.push('CREATE INDEX alarm_note_id ON alarms (note_id)'); } - if (targetVersion == 7) { + if (targetVersion === 7) { queries.push('ALTER TABLE resources ADD COLUMN file_extension TEXT NOT NULL DEFAULT ""'); } - if (targetVersion == 8) { + if (targetVersion === 8) { queries.push('ALTER TABLE sync_items ADD COLUMN sync_disabled INT NOT NULL DEFAULT "0"'); queries.push('ALTER TABLE sync_items ADD COLUMN sync_disabled_reason TEXT NOT NULL DEFAULT ""'); } - if (targetVersion == 9) { + if (targetVersion === 9) { const newTableSql = ` CREATE TABLE master_keys ( id TEXT PRIMARY KEY, @@ -490,11 +490,11 @@ export default class JoplinDatabase extends Database { queries.push({ sql: 'INSERT INTO item_changes (item_type, item_id, type, created_time) SELECT 1, id, 1, ? FROM notes', params: [Date.now()] }); }; - if (targetVersion == 10) { + if (targetVersion === 10) { upgradeVersion10(); } - if (targetVersion == 11) { + if (targetVersion === 11) { // This trick was needed because Electron Builder incorrectly released a dev branch containing v10 as it was // still being developed, and the db schema was not final at that time. So this v11 was created to // make sure any invalid db schema that was accidentally created was deleted and recreated. @@ -503,17 +503,17 @@ export default class JoplinDatabase extends Database { upgradeVersion10(); } - if (targetVersion == 12) { + if (targetVersion === 12) { queries.push('ALTER TABLE folders ADD COLUMN parent_id TEXT NOT NULL DEFAULT ""'); } - if (targetVersion == 13) { + if (targetVersion === 13) { queries.push('ALTER TABLE resources ADD COLUMN fetch_status INT NOT NULL DEFAULT "2"'); queries.push('ALTER TABLE resources ADD COLUMN fetch_error TEXT NOT NULL DEFAULT ""'); queries.push({ sql: 'UPDATE resources SET fetch_status = ?', params: [Resource.FETCH_STATUS_DONE] }); } - if (targetVersion == 14) { + if (targetVersion === 14) { const resourceLocalStates = ` CREATE TABLE resource_local_states ( id INTEGER PRIMARY KEY, @@ -548,7 +548,7 @@ export default class JoplinDatabase extends Database { ); } - if (targetVersion == 15) { + if (targetVersion === 15) { queries.push('CREATE VIRTUAL TABLE notes_fts USING fts4(content="notes", notindexed="id", id, title, body)'); queries.push('INSERT INTO notes_fts(docid, id, title, body) SELECT rowid, id, title, body FROM notes WHERE is_conflict = 0 AND encryption_applied = 0'); @@ -572,7 +572,7 @@ export default class JoplinDatabase extends Database { END;`); } - if (targetVersion == 18) { + if (targetVersion === 18) { const notesNormalized = ` CREATE TABLE notes_normalized ( id TEXT NOT NULL, @@ -613,7 +613,7 @@ export default class JoplinDatabase extends Database { END;`); } - if (targetVersion == 19) { + if (targetVersion === 19) { const newTableSql = ` CREATE TABLE revisions ( id TEXT PRIMARY KEY, @@ -642,7 +642,7 @@ export default class JoplinDatabase extends Database { queries.push('ALTER TABLE item_changes ADD COLUMN before_change_item TEXT NOT NULL DEFAULT ""'); } - if (targetVersion == 20) { + if (targetVersion === 20) { const newTableSql = ` CREATE TABLE migrations ( id INTEGER PRIMARY KEY, @@ -657,11 +657,11 @@ export default class JoplinDatabase extends Database { queries.push(this.addMigrationFile(20)); } - if (targetVersion == 21) { + if (targetVersion === 21) { queries.push('ALTER TABLE sync_items ADD COLUMN item_location INT NOT NULL DEFAULT 1'); } - if (targetVersion == 22) { + if (targetVersion === 22) { const newTableSql = ` CREATE TABLE resources_to_download ( id INTEGER PRIMARY KEY, @@ -676,7 +676,7 @@ export default class JoplinDatabase extends Database { queries.push('CREATE INDEX resources_to_download_updated_time ON resources_to_download (updated_time)'); } - if (targetVersion == 23) { + if (targetVersion === 23) { const newTableSql = ` CREATE TABLE key_values ( id INTEGER PRIMARY KEY, @@ -691,11 +691,11 @@ export default class JoplinDatabase extends Database { queries.push('CREATE UNIQUE INDEX key_values_key ON key_values (key)'); } - if (targetVersion == 24) { + if (targetVersion === 24) { queries.push('ALTER TABLE notes ADD COLUMN `markup_language` INT NOT NULL DEFAULT 1'); // 1: Markdown, 2: HTML } - if (targetVersion == 25) { + if (targetVersion === 25) { queries.push(`CREATE VIEW tags_with_note_count AS SELECT tags.id as id, tags.title as title, tags.created_time as created_time, tags.updated_time as updated_time, COUNT(notes.id) as note_count FROM tags @@ -705,7 +705,7 @@ export default class JoplinDatabase extends Database { GROUP BY tags.id`); } - if (targetVersion == 26) { + if (targetVersion === 26) { const tableNames = ['notes', 'folders', 'tags', 'note_tags', 'resources']; for (let i = 0; i < tableNames.length; i++) { const n = tableNames[i]; @@ -713,19 +713,19 @@ export default class JoplinDatabase extends Database { } } - if (targetVersion == 27) { + if (targetVersion === 27) { queries.push(this.addMigrationFile(27)); } - if (targetVersion == 28) { + if (targetVersion === 28) { queries.push('CREATE INDEX resources_size ON resources(size)'); } - if (targetVersion == 29) { + if (targetVersion === 29) { queries.push('ALTER TABLE version ADD COLUMN table_fields_version INT NOT NULL DEFAULT 0'); } - if (targetVersion == 30) { + if (targetVersion === 30) { // Change the type of the "order" field from INT to NUMERIC // Making it a float provides a much bigger range when inserting notes. // For example, with an INT, inserting a note C between note A with order 1000 and @@ -762,7 +762,7 @@ export default class JoplinDatabase extends Database { ); } - if (targetVersion == 31) { + if (targetVersion === 31) { // This empty version is due to the revert of the hierarchical tag feature // We need to keep the version for the users who have upgraded using // the pre-release @@ -772,7 +772,7 @@ export default class JoplinDatabase extends Database { // queries.push(this.addMigrationFile(31)); } - if (targetVersion == 32) { + if (targetVersion === 32) { // This is the same as version 25 - this is to complete the // revert of the hierarchical tag feature. queries.push(`CREATE VIEW IF NOT EXISTS tags_with_note_count AS @@ -784,7 +784,7 @@ export default class JoplinDatabase extends Database { GROUP BY tags.id`); } - if (targetVersion == 33) { + if (targetVersion === 33) { queries.push('DROP TRIGGER notes_fts_before_update'); queries.push('DROP TRIGGER notes_fts_before_delete'); queries.push('DROP TRIGGER notes_after_update'); @@ -867,24 +867,24 @@ export default class JoplinDatabase extends Database { queries.push(this.addMigrationFile(33)); } - if (targetVersion == 34) { + if (targetVersion === 34) { queries.push('CREATE VIRTUAL TABLE search_aux USING fts4aux(notes_fts)'); queries.push('CREATE VIRTUAL TABLE notes_spellfix USING spellfix1'); } - if (targetVersion == 35) { + if (targetVersion === 35) { queries.push('ALTER TABLE notes_normalized ADD COLUMN todo_due INT NOT NULL DEFAULT 0'); queries.push('CREATE INDEX notes_normalized_todo_due ON notes_normalized (todo_due)'); queries.push(this.addMigrationFile(35)); } - if (targetVersion == 36) { + if (targetVersion === 36) { queries.push('ALTER TABLE folders ADD COLUMN share_id TEXT NOT NULL DEFAULT ""'); queries.push('ALTER TABLE notes ADD COLUMN share_id TEXT NOT NULL DEFAULT ""'); queries.push('ALTER TABLE resources ADD COLUMN share_id TEXT NOT NULL DEFAULT ""'); } - if (targetVersion == 38) { + if (targetVersion === 38) { queries.push('DROP VIEW tags_with_note_count'); queries.push(`CREATE VIEW tags_with_note_count AS SELECT tags.id as id, tags.title as title, tags.created_time as created_time, tags.updated_time as updated_time, COUNT(notes.id) as note_count, @@ -896,17 +896,17 @@ export default class JoplinDatabase extends Database { GROUP BY tags.id`); } - if (targetVersion == 39) { + if (targetVersion === 39) { queries.push('ALTER TABLE `notes` ADD COLUMN conflict_original_id TEXT NOT NULL DEFAULT ""'); } - if (targetVersion == 40) { + if (targetVersion === 40) { queries.push('ALTER TABLE `folders` ADD COLUMN master_key_id TEXT NOT NULL DEFAULT ""'); queries.push('ALTER TABLE `notes` ADD COLUMN master_key_id TEXT NOT NULL DEFAULT ""'); queries.push('ALTER TABLE `resources` ADD COLUMN master_key_id TEXT NOT NULL DEFAULT ""'); } - if (targetVersion == 41) { + if (targetVersion === 41) { queries.push('ALTER TABLE `folders` ADD COLUMN icon TEXT NOT NULL DEFAULT ""'); } diff --git a/packages/lib/JoplinServerApi.ts b/packages/lib/JoplinServerApi.ts index 05cc505687..ffb89fe6b7 100644 --- a/packages/lib/JoplinServerApi.ts +++ b/packages/lib/JoplinServerApi.ts @@ -177,13 +177,13 @@ export default class JoplinServerApi { let response: any = null; - if (options.source == 'file' && (method == 'POST' || method == 'PUT')) { + if (options.source === 'file' && (method === 'POST' || method === 'PUT')) { if (fetchOptions.path) { const fileStat = await shim.fsDriver().stat(fetchOptions.path); if (fileStat) fetchOptions.headers['Content-Length'] = `${fileStat.size}`; } response = await shim.uploadBlob(url, fetchOptions); - } else if (options.target == 'string') { + } else if (options.target === 'string') { if (typeof body === 'string') fetchOptions.headers['Content-Length'] = `${shim.stringByteLength(body)}`; response = await shim.fetch(url, fetchOptions); } else { diff --git a/packages/lib/Logger.ts b/packages/lib/Logger.ts index b8226b0b3d..ad83628152 100644 --- a/packages/lib/Logger.ts +++ b/packages/lib/Logger.ts @@ -168,7 +168,7 @@ class Logger { for (let i = 0; i < this.targets_.length; i++) { const target = this.targets_[i]; - if (target.type == 'database') { + if (target.type === 'database') { let sql = `SELECT * FROM logs WHERE level IN (${options.levels.join(',')}) ORDER BY timestamp DESC`; if (limit !== null) sql += ` LIMIT ${limit}`; return await target.database.selectAll(sql); @@ -191,11 +191,11 @@ class Logger { if (this.targetLevel(target) < level) continue; - if (target.type == 'console') { + if (target.type === 'console') { let fn = 'log'; - if (level == LogLevel.Error) fn = 'error'; - if (level == LogLevel.Warn) fn = 'warn'; - if (level == LogLevel.Info) fn = 'info'; + if (level === LogLevel.Error) fn = 'error'; + if (level === LogLevel.Warn) fn = 'warn'; + if (level === LogLevel.Info) fn = 'info'; const consoleObj = target.console ? target.console : console; let items: any[] = []; @@ -217,7 +217,7 @@ class Logger { } consoleObj[fn](...items); - } else if (target.type == 'file') { + } else if (target.type === 'file') { const timestamp = moment().format('YYYY-MM-DD HH:mm:ss'); const line = [timestamp]; if (targetPrefix) line.push(targetPrefix); @@ -239,7 +239,7 @@ class Logger { }).finally(() => { if (release) release(); }); - } else if (target.type == 'database') { + } else if (target.type === 'database') { const msg = []; if (targetPrefix) msg.push(targetPrefix); msg.push(this.objectsToString(...object)); @@ -280,20 +280,20 @@ class Logger { } static levelStringToId(s: string) { - if (s == 'none') return LogLevel.None; - if (s == 'error') return LogLevel.Error; - if (s == 'warn') return LogLevel.Warn; - if (s == 'info') return LogLevel.Info; - if (s == 'debug') return LogLevel.Debug; + if (s === 'none') return LogLevel.None; + if (s === 'error') return LogLevel.Error; + if (s === 'warn') return LogLevel.Warn; + if (s === 'info') return LogLevel.Info; + if (s === 'debug') return LogLevel.Debug; throw new Error(`Unknown log level: ${s}`); } static levelIdToString(id: LogLevel) { - if (id == LogLevel.None) return 'none'; - if (id == LogLevel.Error) return 'error'; - if (id == LogLevel.Warn) return 'warn'; - if (id == LogLevel.Info) return 'info'; - if (id == LogLevel.Debug) return 'debug'; + if (id === LogLevel.None) return 'none'; + if (id === LogLevel.Error) return 'error'; + if (id === LogLevel.Warn) return 'warn'; + if (id === LogLevel.Info) return 'info'; + if (id === LogLevel.Debug) return 'debug'; throw new Error(`Unknown level ID: ${id}`); } diff --git a/packages/lib/SyncTargetOneDrive.ts b/packages/lib/SyncTargetOneDrive.ts index 7d5f24e76e..fa4e22bbc3 100644 --- a/packages/lib/SyncTargetOneDrive.ts +++ b/packages/lib/SyncTargetOneDrive.ts @@ -67,7 +67,7 @@ export default class SyncTargetOneDrive extends BaseSyncTarget { if (this.api_) return this.api_; - const isPublic = Setting.value('appType') != 'cli' && Setting.value('appType') != 'desktop'; + const isPublic = Setting.value('appType') !== 'cli' && Setting.value('appType') !== 'desktop'; this.api_ = new OneDriveApi(this.oneDriveParameters().id, this.oneDriveParameters().secret, isPublic); diff --git a/packages/lib/Synchronizer.ts b/packages/lib/Synchronizer.ts index 4d35d466e3..098f2c3d86 100644 --- a/packages/lib/Synchronizer.ts +++ b/packages/lib/Synchronizer.ts @@ -241,12 +241,12 @@ export default class Synchronizer { logger.info('Operations completed: '); for (const n in report) { if (!report.hasOwnProperty(n)) continue; - if (n == 'errors') continue; - if (n == 'starting') continue; - if (n == 'finished') continue; - if (n == 'state') continue; - if (n == 'startTime') continue; - if (n == 'completedTime') continue; + if (n === 'errors') continue; + if (n === 'starting') continue; + if (n === 'finished') continue; + if (n === 'state') continue; + if (n === 'startTime') continue; + if (n === 'completedTime') continue; logger.info(`${n}: ${report[n] ? report[n] : '-'}`); } const folderCount = await Folder.count(); @@ -266,7 +266,7 @@ export default class Synchronizer { } async cancel() { - if (this.cancelling_ || this.state() == 'idle') return; + if (this.cancelling_ || this.state() === 'idle') return; // Stop queue but don't set it to null as it may be used to // retrieve the last few downloads. @@ -277,7 +277,7 @@ export default class Synchronizer { return new Promise((resolve) => { const iid = shim.setInterval(() => { - if (this.state() == 'idle') { + if (this.state() === 'idle') { shim.clearInterval(iid); resolve(null); } @@ -360,7 +360,7 @@ export default class Synchronizer { public async start(options: any = null) { if (!options) options = {}; - if (this.state() != 'idle') { + if (this.state() !== 'idle') { const error: any = new Error(sprintf('Synchronisation is already in progress. State: %s', this.state())); error.code = 'alreadyStarted'; throw error; @@ -641,7 +641,7 @@ export default class Synchronizer { this.logSyncOperation(action, local, remote, reason); - if (local.type_ == BaseModel.TYPE_RESOURCE && (action == 'createRemote' || action === 'updateRemote')) { + if (local.type_ === BaseModel.TYPE_RESOURCE && (action === 'createRemote' || action === 'updateRemote')) { const localState = await Resource.localState(local.id); if (localState.fetch_status !== Resource.FETCH_STATUS_DONE) { // This condition normally shouldn't happen @@ -703,7 +703,7 @@ export default class Synchronizer { } } - if (action == 'createRemote' || action == 'updateRemote') { + if (action === 'createRemote' || action === 'updateRemote') { let canSync = true; try { if (this.testingHooks_.indexOf('notesRejectedByTarget') >= 0 && local.type_ === BaseModel.TYPE_NOTE) throw new JoplinError('Testing rejectedByTarget', 'rejectedByTarget'); @@ -739,7 +739,7 @@ export default class Synchronizer { await ItemClass.saveSyncTime(syncTargetId, local, local.updated_time); } - } else if (action == 'itemConflict') { + } else if (action === 'itemConflict') { // ------------------------------------------------------------------------------ // For non-note conflicts, we take the remote version (i.e. the version that was // synced first) and overwrite the local content. @@ -756,7 +756,7 @@ export default class Synchronizer { trackDeleted: false, }); } - } else if (action == 'noteConflict') { + } else if (action === 'noteConflict') { // ------------------------------------------------------------------------------ // First find out if the conflict matters. For example, if the conflict is on the title or body // we want to preserve all the changes. If it's on todo_completed it doesn't really matter @@ -776,7 +776,7 @@ export default class Synchronizer { if (mustHandleConflict) { await Note.createConflictNote(local, ItemChange.SOURCE_SYNC); } - } else if (action == 'resourceConflict') { + } else if (action === 'resourceConflict') { // ------------------------------------------------------------------------------ // Unlike notes we always handle the conflict for resources // ------------------------------------------------------------------------------ @@ -951,7 +951,7 @@ export default class Synchronizer { this.logSyncOperation(action, local, remote, reason); - if (action == 'createLocal' || action == 'updateLocal') { + if (action === 'createLocal' || action === 'updateLocal') { if (content === null) { logger.warn(`Remote has been deleted between now and the delta() call? In that case it will be handled during the next sync: ${path}`); continue; @@ -971,10 +971,10 @@ export default class Synchronizer { nextQueries: BaseItem.updateSyncTimeQueries(syncTargetId, content, time.unixMs()), changeSource: ItemChange.SOURCE_SYNC, }; - if (action == 'createLocal') options.isNew = true; - if (action == 'updateLocal') options.oldItem = local; + if (action === 'createLocal') options.isNew = true; + if (action === 'updateLocal') options.oldItem = local; - const creatingOrUpdatingResource = content.type_ == BaseModel.TYPE_RESOURCE && (action == 'createLocal' || action == 'updateLocal'); + const creatingOrUpdatingResource = content.type_ === BaseModel.TYPE_RESOURCE && (action === 'createLocal' || action === 'updateLocal'); if (creatingOrUpdatingResource) { if (content.size >= this.maxResourceSize()) { @@ -1018,8 +1018,8 @@ export default class Synchronizer { // } if (content.encryption_applied) this.dispatch({ type: 'SYNC_GOT_ENCRYPTED_ITEM' }); - } else if (action == 'deleteLocal') { - if (local.type_ == BaseModel.TYPE_FOLDER) { + } else if (action === 'deleteLocal') { + if (local.type_ === BaseModel.TYPE_FOLDER) { localFoldersToDelete.push(local); continue; } diff --git a/packages/lib/WebDavApi.js b/packages/lib/WebDavApi.js index 61d08a2435..36d394856b 100644 --- a/packages/lib/WebDavApi.js +++ b/packages/lib/WebDavApi.js @@ -90,7 +90,7 @@ class WebDavApi { // Check if the current name is within the DAV namespace. If it is, normalise it // by moving it to the "d:" namespace, which is what all the functions are using. const p = name.split(':'); - if (p.length == 2) { + if (p.length === 2) { const ns = p[0]; if (davNamespaces.indexOf(ns) >= 0) { name = `d:${p[1]}`; @@ -386,13 +386,13 @@ class WebDavApi { // console.info('WebDAV Call', `${method} ${url}`, headers, options); // console.info(this.requestToCurl_(url, fetchOptions)); - if (options.source == 'file' && (method == 'POST' || method == 'PUT')) { + if (options.source === 'file' && (method === 'POST' || method === 'PUT')) { if (fetchOptions.path) { const fileStat = await shim.fsDriver().stat(fetchOptions.path); if (fileStat) fetchOptions.headers['Content-Length'] = `${fileStat.size}`; } response = await shim.uploadBlob(url, fetchOptions); - } else if (options.target == 'string') { + } else if (options.target === 'string') { if (typeof body === 'string') fetchOptions.headers['Content-Length'] = `${shim.stringByteLength(body)}`; response = await shim.fetch(url, fetchOptions); } else { diff --git a/packages/lib/commands/synchronize.ts b/packages/lib/commands/synchronize.ts index c878a26391..23887059a2 100644 --- a/packages/lib/commands/synchronize.ts +++ b/packages/lib/commands/synchronize.ts @@ -53,7 +53,7 @@ export const runtime = (): CommandRuntime => { return 'error'; } - if (action == 'cancel') { + if (action === 'cancel') { sync.cancel(); return 'cancel'; } else { diff --git a/packages/lib/components/shared/reduxSharedMiddleware.js b/packages/lib/components/shared/reduxSharedMiddleware.js index 6c25682b5e..31ad5411e4 100644 --- a/packages/lib/components/shared/reduxSharedMiddleware.js +++ b/packages/lib/components/shared/reduxSharedMiddleware.js @@ -14,7 +14,7 @@ const reduxSharedMiddleware = async function(store, next, action) { let refreshTags = false; - if (action.type == 'FOLDER_SET_COLLAPSED' || action.type == 'FOLDER_TOGGLE') { + if (action.type === 'FOLDER_SET_COLLAPSED' || action.type === 'FOLDER_TOGGLE') { Setting.setValue('collapsedFolderIds', newState.collapsedFolderIds); } @@ -43,16 +43,16 @@ const reduxSharedMiddleware = async function(store, next, action) { DecryptionWorker.instance().scheduleStart(); } - if (action.type == 'NOTE_DELETE' || - action.type == 'NOTE_UPDATE_ALL' || - action.type == 'NOTE_TAG_REMOVE' || - action.type == 'TAG_UPDATE_ONE') { + if (action.type === 'NOTE_DELETE' || + action.type === 'NOTE_UPDATE_ALL' || + action.type === 'NOTE_TAG_REMOVE' || + action.type === 'TAG_UPDATE_ONE') { refreshTags = true; } // handle the case when the selected note has been moved to another // folder and a new one is now selected, need to show correct tags for it - if (action.type == 'NOTE_UPDATE_ONE' && action.changedFields.indexOf('parent_id') >= 0) { + if (action.type === 'NOTE_UPDATE_ONE' && action.changedFields.indexOf('parent_id') >= 0) { refreshTags = true; } diff --git a/packages/lib/components/shared/side-menu-shared.js b/packages/lib/components/shared/side-menu-shared.js index 9e8a2548e8..7600db75d8 100644 --- a/packages/lib/components/shared/side-menu-shared.js +++ b/packages/lib/components/shared/side-menu-shared.js @@ -32,7 +32,7 @@ function renderFoldersRecursive_(props, renderItem, items, parentId, depth, orde if (!folderIsVisible(props.folders, folder.id, props.collapsedFolderIds)) continue; const hasChildren = folderHasChildren_(folders, folder.id); order.push(folder.id); - items.push(renderItem(folder, props.selectedFolderId == folder.id && props.notesParentType == 'Folder', hasChildren, depth)); + items.push(renderItem(folder, props.selectedFolderId === folder.id && props.notesParentType === 'Folder', hasChildren, depth)); if (hasChildren) { const result = renderFoldersRecursive_(props, renderItem, items, folder.id, depth + 1, order); items = result.items; @@ -69,7 +69,7 @@ shared.renderTags = function(props, renderItem) { for (let i = 0; i < tags.length; i++) { const tag = tags[i]; order.push(tag.id); - tagItems.push(renderItem(tag, props.selectedTagId == tag.id && props.notesParentType == 'Tag')); + tagItems.push(renderItem(tag, props.selectedTagId === tag.id && props.notesParentType === 'Tag')); } return { items: tagItems, @@ -123,7 +123,7 @@ shared.synchronize_press = async function(comp) { return 'error'; } - if (action == 'cancel') { + if (action === 'cancel') { sync.cancel(); return 'cancel'; } else { diff --git a/packages/lib/database.ts b/packages/lib/database.ts index aec89c72ac..39771c78cf 100644 --- a/packages/lib/database.ts +++ b/packages/lib/database.ts @@ -69,16 +69,16 @@ export default class Database { } public escapeField(field: string) { - if (field == '*') return '*'; + if (field === '*') return '*'; const p = field.split('.'); - if (p.length == 1) return `\`${field}\``; - if (p.length == 2) return `${p[0]}.\`${p[1]}\``; + if (p.length === 1) return `\`${field}\``; + if (p.length === 2) return `${p[0]}.\`${p[1]}\``; throw new Error(`Invalid field format: ${field}`); } public escapeFields(fields: string[] | string): string[] | string { - if (fields == '*') return '*'; + if (fields === '*') return '*'; const output = []; for (let i = 0; i < fields.length; i++) { @@ -137,7 +137,7 @@ export default class Database { return result; // No exception was thrown } catch (error) { - if (error && (error.code == 'SQLITE_IOERR' || error.code == 'SQLITE_BUSY')) { + if (error && (error.code === 'SQLITE_IOERR' || error.code === 'SQLITE_BUSY')) { if (totalWaitTime >= 20000) throw this.sqliteErrorToJsError(error, sql, params); // NOTE: don't put logger statements here because it might log to the database, which // could result in an error being thrown again. @@ -193,7 +193,7 @@ export default class Database { async transactionExecBatch(queries: StringOrSqlQuery[]) { if (queries.length <= 0) return; - if (queries.length == 1) { + if (queries.length === 1) { const q = this.wrapQuery(queries[0]); await this.exec(q.sql, q.params); return; @@ -220,20 +220,20 @@ export default class Database { } static enumId(type: string, s: string) { - if (type == 'settings') { - if (s == 'int') return 1; - if (s == 'string') return 2; + if (type === 'settings') { + if (s === 'int') return 1; + if (s === 'string') return 2; } - if (type == 'fieldType') { + if (type === 'fieldType') { if (s) s = s.toUpperCase(); - if (s == 'INTEGER') s = 'INT'; + if (s === 'INTEGER') s = 'INT'; if (!(`TYPE_${s}` in this)) throw new Error(`Unkonwn fieldType: ${s}`); return (this as any)[`TYPE_${s}`]; } - if (type == 'syncTarget') { - if (s == 'memory') return 1; - if (s == 'filesystem') return 2; - if (s == 'onedrive') return 3; + if (type === 'syncTarget') { + if (s === 'memory') return 1; + if (s === 'filesystem') return 2; + if (s === 'onedrive') return 3; } throw new Error(`Unknown enum type or value: ${type}, ${s}`); } @@ -253,9 +253,9 @@ export default class Database { static formatValue(type: number, value: any) { if (value === null || value === undefined) return null; - if (type == this.TYPE_INT) return Number(value); - if (type == this.TYPE_TEXT) return value; - if (type == this.TYPE_NUMERIC) return Number(value); + if (type === this.TYPE_INT) return Number(value); + if (type === this.TYPE_TEXT) return value; + if (type === this.TYPE_NUMERIC) return Number(value); throw new Error(`Unknown type: ${type}`); } @@ -265,11 +265,11 @@ export default class Database { let statement = ''; for (let i = 0; i < lines.length; i++) { const line = lines[i]; - if (line == '') continue; - if (line.substr(0, 2) == '--') continue; + if (line === '') continue; + if (line.substr(0, 2) === '--') continue; statement += line.trim(); - if (line[line.length - 1] == ',') statement += ' '; - if (line[line.length - 1] == ';') { + if (line[line.length - 1] === ',') statement += ' '; + if (line[line.length - 1] === ';') { output.push(statement); statement = ''; } @@ -299,9 +299,9 @@ export default class Database { const params = []; for (const key in data) { if (!data.hasOwnProperty(key)) continue; - if (key[key.length - 1] == '_') continue; - if (keySql != '') keySql += ', '; - if (valueSql != '') valueSql += ', '; + if (key[key.length - 1] === '_') continue; + if (keySql !== '') keySql += ', '; + if (valueSql !== '') valueSql += ', '; keySql += `\`${key}\``; valueSql += '?'; params.push(data[key]); @@ -319,13 +319,13 @@ export default class Database { const params = []; for (const key in data) { if (!data.hasOwnProperty(key)) continue; - if (key[key.length - 1] == '_') continue; - if (sql != '') sql += ', '; + if (key[key.length - 1] === '_') continue; + if (sql !== '') sql += ', '; sql += `\`${key}\`=?`; params.push(data[key]); } - if (typeof where != 'string') { + if (typeof where !== 'string') { const s = []; for (const n in where) { if (!where.hasOwnProperty(n)) continue; diff --git a/packages/lib/file-api-driver-onedrive.js b/packages/lib/file-api-driver-onedrive.js index e016f174b7..be719155cb 100644 --- a/packages/lib/file-api-driver-onedrive.js +++ b/packages/lib/file-api-driver-onedrive.js @@ -53,7 +53,7 @@ class FileApiDriverOneDrive { try { item = await this.api_.execJson('GET', this.makePath_(path), this.itemFilter_()); } catch (error) { - if (error.code == 'itemNotFound') return null; + if (error.code === 'itemNotFound') return null; throw error; } return item; @@ -107,7 +107,7 @@ class FileApiDriverOneDrive { if (!options) options = {}; try { - if (options.target == 'file') { + if (options.target === 'file') { const response = await this.api_.exec('GET', `${this.makePath_(path)}:/content`, null, null, options); return response; } else { @@ -115,7 +115,7 @@ class FileApiDriverOneDrive { return content; } } catch (error) { - if (error.code == 'itemNotFound') return null; + if (error.code === 'itemNotFound') return null; throw error; } } @@ -140,7 +140,7 @@ class FileApiDriverOneDrive { // We need to check the file size as files > 4 MBs are uploaded in a different way than files < 4 MB (see https://docs.microsoft.com/de-de/onedrive/developer/rest-api/concepts/upload?view=odsp-graph-online) let byteSize = null; - if (options.source == 'file') { + if (options.source === 'file') { byteSize = (await shim.fsDriver().stat(options.path)).size; } else { options.headers = { 'Content-Type': 'text/plain' }; diff --git a/packages/lib/import-enex-html-gen.js b/packages/lib/import-enex-html-gen.js index ef0ac21255..4e09b8e71d 100644 --- a/packages/lib/import-enex-html-gen.js +++ b/packages/lib/import-enex-html-gen.js @@ -16,10 +16,8 @@ function addResourceTag(lines, resource, attributes) { if (resourceUtils.isImageMimeType(resource.mime)) { lines.push(resourceUtils.imgElement({ src, attributes })); } else if (resource.mime === 'audio/x-m4a') { - /** - * TODO: once https://github.com/laurent22/joplin/issues/1794 is resolved, - * come back to this and make sure it works. - */ + // TODO: once https://github.com/laurent22/joplin/issues/1794 is resolved, + // come back to this and make sure it works. lines.push(resourceUtils.audioElement({ src, alt: attributes.alt, @@ -90,7 +88,7 @@ function enexXmlToHtml_(stream, resources) { let resource = null; for (let i = 0; i < resources.length; i++) { const r = resources[i]; - if (r.id == hash) { + if (r.id === hash) { resource = r; removeRemainingResource(r.id); break; @@ -122,9 +120,9 @@ function enexXmlToHtml_(stream, resources) { if (resource && !!resource.id) { section.lines = addResourceTag(section.lines, resource, nodeAttributes); } - } else if (tagName == 'en-todo') { + } else if (tagName === 'en-todo') { const nodeAttributes = attributeToLowerCase(node); - const checkedHtml = nodeAttributes.checked && nodeAttributes.checked.toLowerCase() == 'true' ? ' checked="checked" ' : ' '; + const checkedHtml = nodeAttributes.checked && nodeAttributes.checked.toLowerCase() === 'true' ? ' checked="checked" ' : ' '; section.lines.push(``); } else if (htmlUtils.isSelfClosingTag(tagName)) { section.lines.push(`<${tagName}${attributesStr}/>`); diff --git a/packages/lib/import-enex-md-gen.ts b/packages/lib/import-enex-md-gen.ts index 0dd84951ea..6bb73c9886 100644 --- a/packages/lib/import-enex-md-gen.ts +++ b/packages/lib/import-enex-md-gen.ts @@ -58,11 +58,11 @@ interface EnexXmlToMdArrayResult { } function processMdArrayNewLines(md: string[]): string { - while (md.length && md[0] == BLOCK_OPEN) { + while (md.length && md[0] === BLOCK_OPEN) { md.shift(); } - while (md.length && md[md.length - 1] == BLOCK_CLOSE) { + while (md.length && md[md.length - 1] === BLOCK_CLOSE) { md.pop(); } @@ -70,7 +70,7 @@ function processMdArrayNewLines(md: string[]): string { let last = ''; for (let i = 0; i < md.length; i++) { const v = md[i]; - if (isNewLineBlock(last) && isNewLineBlock(v) && last == v) { + if (isNewLineBlock(last) && isNewLineBlock(v) && last === v) { // Skip it } else { temp.push(v); @@ -83,7 +83,7 @@ function processMdArrayNewLines(md: string[]): string { last = ''; for (let i = 0; i < md.length; i++) { const v = md[i]; - if (last == BLOCK_CLOSE && v == BLOCK_OPEN) { + if (last === BLOCK_CLOSE && v === BLOCK_OPEN) { temp.pop(); temp.push(NEWLINE_MERGED); } else { @@ -97,7 +97,7 @@ function processMdArrayNewLines(md: string[]): string { last = ''; for (let i = 0; i < md.length; i++) { const v = md[i]; - if (last == NEWLINE && (v == NEWLINE_MERGED || v == BLOCK_CLOSE)) { + if (last === NEWLINE && (v === NEWLINE_MERGED || v === BLOCK_CLOSE)) { // Skip it } else { temp.push(v); @@ -111,7 +111,7 @@ function processMdArrayNewLines(md: string[]): string { last = ''; for (let i = 0; i < md.length; i++) { const v = md[i]; - if (last == NEWLINE && (v == NEWLINE_MERGED || v == BLOCK_OPEN)) { + if (last === NEWLINE && (v === NEWLINE_MERGED || v === BLOCK_OPEN)) { // Skip it } else { temp.push(v); @@ -121,7 +121,7 @@ function processMdArrayNewLines(md: string[]): string { md = temp; if (md.length > 2) { - if (md[md.length - 2] == NEWLINE_MERGED && md[md.length - 1] == NEWLINE) { + if (md[md.length - 2] === NEWLINE_MERGED && md[md.length - 1] === NEWLINE) { md.pop(); } } @@ -132,10 +132,10 @@ function processMdArrayNewLines(md: string[]): string { for (let i = 0; i < md.length; i++) { const v = md[i]; let add = ''; - if (v == BLOCK_CLOSE || v == BLOCK_OPEN || v == NEWLINE || v == NEWLINE_MERGED) { + if (v === BLOCK_CLOSE || v === BLOCK_OPEN || v === NEWLINE || v === NEWLINE_MERGED) { add = '\n'; - } else if (v == SPACE) { - if (previous == SPACE || previous == '\n' || start) { + } else if (v === SPACE) { + if (previous === SPACE || previous === '\n' || start) { continue; // skip } else { add = ' '; @@ -285,7 +285,7 @@ function formatMdLayout(lines: string[]) { } function isWhiteSpace(c: string): boolean { - return c == '\n' || c == '\r' || c == '\v' || c == '\f' || c == '\t' || c == ' '; + return c === '\n' || c === '\r' || c === '\v' || c === '\f' || c === '\t' || c === ' '; } // Like QString::simpified(), except that it preserves non-breaking spaces (which @@ -315,16 +315,16 @@ function collapseWhiteSpaceAndAppend(lines: string[], state: any, text: string) lines.push(text); } else { // Remove all \n and \r from the left and right of the text - while (text.length && (text[0] == '\n' || text[0] == '\r')) text = text.substr(1); - while (text.length && (text[text.length - 1] == '\n' || text[text.length - 1] == '\r')) text = text.substr(0, text.length - 1); + while (text.length && (text[0] === '\n' || text[0] === '\r')) text = text.substr(1); + while (text.length && (text[text.length - 1] === '\n' || text[text.length - 1] === '\r')) text = text.substr(0, text.length - 1); // Collapse all white spaces to just one. If there are spaces to the left and right of the string // also collapse them to just one space. - const spaceLeft = text.length && text[0] == ' '; - const spaceRight = text.length && text[text.length - 1] == ' '; + const spaceLeft = text.length && text[0] === ' '; + const spaceRight = text.length && text[text.length - 1] === ' '; text = simplifyString(text); - if (!spaceLeft && !spaceRight && text == '') return lines; + if (!spaceLeft && !spaceRight && text === '') return lines; if (state.inQuote) { // Add a ">" at the beginning of the block then at the beginning of each lines. So it turns this: @@ -380,19 +380,19 @@ function isBlockTag(n: string) { } function isStrongTag(n: string) { - return n == 'strong' || n == 'b' || n == 'big'; + return n === 'strong' || n === 'b' || n === 'big'; } function isStrikeTag(n: string) { - return n == 'strike' || n == 's' || n == 'del'; + return n === 'strike' || n === 's' || n === 'del'; } function isEmTag(n: string) { - return n == 'em' || n == 'i' || n == 'u'; + return n === 'em' || n === 'i' || n === 'u'; } function isAnchor(n: string) { - return n == 'a'; + return n === 'a'; } function isIgnoredEndTag(n: string) { @@ -400,7 +400,7 @@ function isIgnoredEndTag(n: string) { } function isListTag(n: string) { - return n == 'ol' || n == 'ul'; + return n === 'ol' || n === 'ul'; } // Elements that don't require any special treatment beside adding a newline character @@ -413,7 +413,7 @@ function isInlineCodeTag(n: string) { } function isNewLineBlock(s: string) { - return s == BLOCK_OPEN || s == BLOCK_CLOSE; + return s === BLOCK_OPEN || s === BLOCK_CLOSE; } function attributeToLowerCase(node: any) { @@ -467,7 +467,7 @@ function trimBlockOpenAndClose(lines: string[]): string[] { } function isSpanWithStyle(attributes: any) { - if (attributes != undefined) { + if (attributes) { if ('style' in attributes) { return true; } else { @@ -484,7 +484,7 @@ function isSpanStyleBold(attributes: any) { style = style.replace(/\s+/g, ''); if (style.includes('font-weight:bold') || style.includes('font-weight:700') || style.includes('font-weight:800') || style.includes('font-weight:900')) { return true; - } else if (style.search(/font-family:.*,Bold.*;/) != -1) { + } else if (style.search(/font-family:.*,Bold.*;/) !== -1) { return true; } else { return false; @@ -647,9 +647,9 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise tag outside of a table'); // return; } @@ -685,13 +685,13 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise tag outside of a '); // return; } - if (n == 'th') section.isHeader = true; + if (n === 'th') section.isHeader = true; const newSection: Section = { type: SectionType.Td, @@ -701,8 +701,8 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise tag outside of a '); } @@ -739,7 +739,7 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise tag without being inside a list'); @@ -750,7 +750,7 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise'); } else if (isInlineCodeTag(n)) { section.lines.push('`'); - } else if (n == 'q') { + } else if (n === 'q') { section.lines.push('"'); - } else if (n == 'img') { + } else if (n === 'img') { if (nodeAttributes.src) { // Many (most?) img tags don't have no source associated, especially when they were imported from HTML let s = '!['; @@ -781,48 +781,48 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise and the first sub-tag - } else if (n == 'content') { + } else if (n === 'content') { // Ignore - white space between the opening tag and the { return n.id; @@ -323,7 +323,7 @@ export default class BaseItem extends BaseModel { } static unserialize_format(type: ModelType, propName: string, propValue: any) { - if (propName[propName.length - 1] == '_') return propValue; // Private property + if (propName[propName.length - 1] === '_') return propValue; // Private property const ItemClass = this.itemClass(type); @@ -372,7 +372,7 @@ export default class BaseItem extends BaseModel { for (let i = 0; i < shownKeys.length; i++) { let key = shownKeys[i]; - if (key == 'title' || key == 'body') continue; + if (key === 'title' || key === 'body') continue; let value = null; if (typeof key === 'function') { @@ -483,10 +483,10 @@ export default class BaseItem extends BaseModel { for (let i = lines.length - 1; i >= 0; i--) { let line = lines[i]; - if (state == 'readingProps') { + if (state === 'readingProps') { line = line.trim(); - if (line == '') { + if (line === '') { state = 'readingBody'; continue; } @@ -496,7 +496,7 @@ export default class BaseItem extends BaseModel { const key = line.substr(0, p).trim(); const value = line.substr(p + 1).trim(); output[key] = value; - } else if (state == 'readingBody') { + } else if (state === 'readingBody') { body.splice(0, 0, line); } } @@ -628,8 +628,8 @@ export default class BaseItem extends BaseModel { // 'SELECT * FROM [ITEMS] items JOIN sync_items s ON s.item_id = items.id WHERE sync_target = ? AND' let extraWhere: any = []; - if (className == 'Note') extraWhere.push('is_conflict = 0'); - if (className == 'Resource') extraWhere.push('encryption_blob_encrypted = 0'); + if (className === 'Note') extraWhere.push('is_conflict = 0'); + if (className === 'Resource') extraWhere.push('encryption_blob_encrypted = 0'); if (ItemClass.encryptionSupported()) extraWhere.push('encryption_applied = 0'); extraWhere = extraWhere.length ? `AND ${extraWhere.join(' AND ')}` : ''; @@ -727,7 +727,7 @@ export default class BaseItem extends BaseModel { static modelTypeToClassName(type: number) { for (let i = 0; i < BaseItem.syncItemDefinitions_.length; i++) { - if (BaseItem.syncItemDefinitions_[i].type == type) return BaseItem.syncItemDefinitions_[i].className; + if (BaseItem.syncItemDefinitions_[i].type === type) return BaseItem.syncItemDefinitions_[i].className; } throw new Error(`Invalid type: ${type}`); } @@ -795,7 +795,7 @@ export default class BaseItem extends BaseModel { const ItemClass = this.getClass(className); let selectSql = `SELECT id FROM ${ItemClass.tableName()}`; - if (ItemClass.modelType() == this.TYPE_NOTE) selectSql += ' WHERE is_conflict = 0'; + if (ItemClass.modelType() === this.TYPE_NOTE) selectSql += ' WHERE is_conflict = 0'; queries.push(`DELETE FROM sync_items WHERE item_location = ${BaseItem.SYNC_ITEM_LOCATION_LOCAL} AND item_type = ${ItemClass.modelType()} AND item_id NOT IN (${selectSql})`); } diff --git a/packages/lib/models/Folder.ts b/packages/lib/models/Folder.ts index 2a84316d74..ea3c1d59d9 100644 --- a/packages/lib/models/Folder.ts +++ b/packages/lib/models/Folder.ts @@ -552,7 +552,7 @@ export default class Folder extends BaseItem { for (let i = 0; i < length; i++) { const model = models[i]; - if (model.parent_id == parentId) { + if (model.parent_id === parentId) { const children = getNestedChildren(models, model.id); if (children.length > 0) { @@ -666,7 +666,7 @@ export default class Folder extends BaseItem { } static load(id: string, _options: any = null): Promise { - if (id == this.conflictFolderId()) return Promise.resolve(this.conflictFolder()); + if (id === this.conflictFolderId()) return Promise.resolve(this.conflictFolder()); return super.load(id); } @@ -681,7 +681,7 @@ export default class Folder extends BaseItem { if (isRootSharedFolder(folder)) return false; const conflictFolderId = Folder.conflictFolderId(); - if (folderId == conflictFolderId || targetFolderId == conflictFolderId) return false; + if (folderId === conflictFolderId || targetFolderId === conflictFolderId) return false; if (!targetFolderId) return true; @@ -728,7 +728,7 @@ export default class Folder extends BaseItem { } if (options.stripLeftSlashes === true && o.title) { - while (o.title.length && (o.title[0] == '/' || o.title[0] == '\\')) { + while (o.title.length && (o.title[0] === '/' || o.title[0] === '\\')) { o.title = o.title.substr(1); } } @@ -748,7 +748,7 @@ export default class Folder extends BaseItem { // } if (options.reservedTitleCheck === true && o.title) { - if (o.title == Folder.conflictFolderTitle()) throw new Error(_('Notebooks cannot be named "%s", which is a reserved title.', o.title)); + if (o.title === Folder.conflictFolderTitle()) throw new Error(_('Notebooks cannot be named "%s", which is a reserved title.', o.title)); } syncDebugLog.info('Folder Save:', o); diff --git a/packages/lib/models/Note.ts b/packages/lib/models/Note.ts index aa087e29ce..b67e9cae48 100644 --- a/packages/lib/models/Note.ts +++ b/packages/lib/models/Note.ts @@ -300,7 +300,7 @@ export default class Note extends BaseItem { if (aProp < bProp) r = +1; if (aProp > bProp) r = -1; } - if (order.dir == 'ASC') r = -r; + if (order.dir === 'ASC') r = -r; if (r !== 0) return r; } @@ -365,7 +365,7 @@ export default class Note extends BaseItem { // it's confusing to have conflicts but with an empty conflict folder. if (parentId === Folder.conflictFolderId()) options.showCompletedTodos = true; - if (parentId == Folder.conflictFolderId()) { + if (parentId === Folder.conflictFolderId()) { options.conditions.push('is_conflict = 1'); } else { options.conditions.push('is_conflict = 0'); @@ -527,7 +527,7 @@ export default class Note extends BaseItem { } static async copyToFolder(noteId: string, folderId: string) { - if (folderId == this.getClass('Folder').conflictFolderId()) throw new Error(_('Cannot copy note to "%s" notebook', this.getClass('Folder').conflictFolderTitle())); + if (folderId === this.getClass('Folder').conflictFolderId()) throw new Error(_('Cannot copy note to "%s" notebook', this.getClass('Folder').conflictFolderTitle())); return Note.duplicate(noteId, { changes: { @@ -539,7 +539,7 @@ export default class Note extends BaseItem { } static async moveToFolder(noteId: string, folderId: string) { - if (folderId == this.getClass('Folder').conflictFolderId()) throw new Error(_('Cannot move note to "%s" notebook', this.getClass('Folder').conflictFolderTitle())); + if (folderId === this.getClass('Folder').conflictFolderId()) throw new Error(_('Cannot move note to "%s" notebook', this.getClass('Folder').conflictFolderTitle())); // When moving a note to a different folder, the user timestamp is not updated. // However updated_time is updated so that the note can be synced later on. diff --git a/packages/lib/models/Setting.ts b/packages/lib/models/Setting.ts index af48f1afa2..469f4aa1fb 100644 --- a/packages/lib/models/Setting.ts +++ b/packages/lib/models/Setting.ts @@ -452,7 +452,7 @@ class Setting extends BaseModel { section: 'sync', show: (settings: any) => { try { - return settings['sync.target'] == SyncTargetRegistry.nameToId('filesystem'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('filesystem'); } catch (error) { return false; } @@ -471,7 +471,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('nextcloud'); }, public: true, label: () => _('Nextcloud WebDAV URL'), @@ -483,7 +483,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('nextcloud'); }, public: true, label: () => _('Nextcloud username'), @@ -494,7 +494,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('nextcloud'); }, public: true, label: () => _('Nextcloud password'), @@ -506,7 +506,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('webdav'); }, public: true, label: () => _('WebDAV URL'), @@ -518,7 +518,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('webdav'); }, public: true, label: () => _('WebDAV username'), @@ -529,7 +529,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('webdav'); }, public: true, label: () => _('WebDAV password'), @@ -542,7 +542,7 @@ class Setting extends BaseModel { section: 'sync', show: (settings: any) => { try { - return settings['sync.target'] == SyncTargetRegistry.nameToId('amazon_s3'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('amazon_s3'); } catch (error) { return false; } @@ -560,7 +560,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('amazon_s3'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('amazon_s3'); }, filter: value => { return value ? value.trim() : ''; @@ -574,7 +574,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('amazon_s3'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('amazon_s3'); }, filter: value => { return value ? value.trim() : ''; @@ -588,7 +588,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('amazon_s3'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('amazon_s3'); }, public: true, label: () => _('S3 access key'), @@ -599,7 +599,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('amazon_s3'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('amazon_s3'); }, public: true, label: () => _('S3 secret key'), @@ -610,7 +610,7 @@ class Setting extends BaseModel { type: SettingItemType.Bool, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('amazon_s3'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('amazon_s3'); }, public: true, label: () => _('Force path style'), @@ -621,7 +621,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('joplinServer'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('joplinServer'); }, public: true, label: () => _('Joplin Server URL'), @@ -639,7 +639,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('joplinServer'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('joplinServer'); }, public: true, label: () => _('Joplin Server email'), @@ -650,7 +650,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('joplinServer'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('joplinServer'); }, public: true, label: () => _('Joplin Server password'), @@ -678,7 +678,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('joplinCloud'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('joplinCloud'); }, public: true, label: () => _('Joplin Cloud email'), @@ -689,7 +689,7 @@ class Setting extends BaseModel { type: SettingItemType.String, section: 'sync', show: (settings: any) => { - return settings['sync.target'] == SyncTargetRegistry.nameToId('joplinCloud'); + return settings['sync.target'] === SyncTargetRegistry.nameToId('joplinCloud'); }, public: true, label: () => _('Joplin Cloud password'), @@ -1856,7 +1856,7 @@ class Setting extends BaseModel { for (let i = 0; i < this.cache_.length; i++) { const c = this.cache_[i]; - if (c.key == key) { + if (c.key === key) { const md = this.settingMetadata(key); if (md.isEnum === true) { @@ -1973,11 +1973,11 @@ class Setting extends BaseModel { static valueToString(key: string, value: any) { const md = this.settingMetadata(key); value = this.formatValue(key, value); - if (md.type == SettingItemType.Int) return value.toFixed(0); - if (md.type == SettingItemType.Bool) return value ? '1' : '0'; - if (md.type == SettingItemType.Array) return value ? JSON.stringify(value) : '[]'; - if (md.type == SettingItemType.Object) return value ? JSON.stringify(value) : '{}'; - if (md.type == SettingItemType.String) return value ? `${value}` : ''; + if (md.type === SettingItemType.Int) return value.toFixed(0); + if (md.type === SettingItemType.Bool) return value ? '1' : '0'; + if (md.type === SettingItemType.Array) return value ? JSON.stringify(value) : '[]'; + if (md.type === SettingItemType.Object) return value ? JSON.stringify(value) : '{}'; + if (md.type === SettingItemType.String) return value ? `${value}` : ''; throw new Error(`Unhandled value type: ${md.type}`); } @@ -1990,9 +1990,9 @@ class Setting extends BaseModel { static formatValue(key: string, value: any) { const md = this.settingMetadata(key); - if (md.type == SettingItemType.Int) return !value ? 0 : Math.floor(Number(value)); + if (md.type === SettingItemType.Int) return !value ? 0 : Math.floor(Number(value)); - if (md.type == SettingItemType.Bool) { + if (md.type === SettingItemType.Bool) { if (typeof value === 'string') { value = value.toLowerCase(); if (value === 'true') return true; @@ -2039,14 +2039,14 @@ class Setting extends BaseModel { if (key in this.constants_) { const v = (this.constants_ as any)[key]; const output = typeof v === 'function' ? v() : v; - if (output == 'SET_ME') throw new Error(`SET_ME constant has not been set: ${key}`); + if (output === 'SET_ME') throw new Error(`SET_ME constant has not been set: ${key}`); return output; } if (!this.cache_) throw new Error('Settings have not been initialized!'); for (let i = 0; i < this.cache_.length; i++) { - if (this.cache_[i].key == key) { + if (this.cache_[i].key === key) { return copyIfNeeded(this.cache_[i].value); } } @@ -2079,7 +2079,7 @@ class Setting extends BaseModel { static enumOptionLabel(key: string, value: any) { const options = this.enumOptions(key); for (const n in options) { - if (n == value) return options[n]; + if (n === value) return options[n]; } return ''; } diff --git a/packages/lib/onedrive-api.ts b/packages/lib/onedrive-api.ts index 452fe627c8..6c1346dabb 100644 --- a/packages/lib/onedrive-api.ts +++ b/packages/lib/onedrive-api.ts @@ -236,11 +236,11 @@ export default class OneDriveApi { if (!options.headers) options.headers = {}; if (!options.target) options.target = 'string'; - if (method != 'GET') { + if (method !== 'GET') { options.method = method; } - if (method == 'PATCH' || method == 'POST') { + if (method === 'PATCH' || method === 'POST') { options.headers['Content-Type'] = 'application/json'; if (data) data = JSON.stringify(data); } @@ -279,9 +279,9 @@ export default class OneDriveApi { try { if (path.includes('/createUploadSession')) { response = await this.uploadBigFile(url, options); - } else if (options.source == 'file' && (method == 'POST' || method == 'PUT')) { + } else if (options.source === 'file' && (method === 'POST' || method === 'PUT')) { response = await shim.uploadBlob(url, options); - } else if (options.target == 'string') { + } else if (options.target === 'string') { response = await shim.fetch(url, options); } else { // file @@ -311,11 +311,11 @@ export default class OneDriveApi { const error = this.oneDriveErrorResponseToError(errorResponse); - if (error.code == 'InvalidAuthenticationToken' || error.code == 'unauthenticated') { + if (error.code === 'InvalidAuthenticationToken' || error.code === 'unauthenticated') { logger.info('Token expired: refreshing...'); await this.refreshAccessToken(); continue; - } else if (error && ((error.error && error.error.code == 'generalException') || error.code == 'generalException' || error.code == 'EAGAIN')) { + } else if (error && ((error.error && error.error.code === 'generalException') || error.code === 'generalException' || error.code === 'EAGAIN')) { // Rare error (one Google hit) - I guess the request can be repeated // { error: // { code: 'generalException', @@ -351,7 +351,7 @@ export default class OneDriveApi { logger.info(`OneDrive Throttle, sync thread sleeping for ${sleepSeconds} seconds...`); await handleRequestRepeat(error, Number(sleepSeconds)); continue; - } else if (error.code == 'itemNotFound' && method == 'DELETE') { + } else if (error.code === 'itemNotFound' && method === 'DELETE') { // Deleting a non-existing item is ok - noop return; } else { diff --git a/packages/lib/reducer.test.js b/packages/lib/reducer.test.js index 85b6b53264..1ef34a28eb 100644 --- a/packages/lib/reducer.test.js +++ b/packages/lib/reducer.test.js @@ -6,26 +6,26 @@ const { defaultState, MAX_HISTORY } = require('./reducer'); function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, tags = null, selectedTagIndex = null) { let state = defaultState; - if (selectedFolderIndex != null) { + if (selectedFolderIndex !== null) { state = reducer(state, { type: 'FOLDER_SELECT', id: folders[selectedFolderIndex].id }); } - if (folders != null) { + if (folders !== null) { state = reducer(state, { type: 'FOLDER_UPDATE_ALL', items: folders }); } - if (notes != null) { + if (notes !== null) { state = reducer(state, { type: 'NOTE_UPDATE_ALL', notes: notes, noteSource: 'test' }); } - if (selectedNoteIndexes != null) { + if (selectedNoteIndexes !== null) { const selectedIds = []; for (let i = 0; i < selectedNoteIndexes.length; i++) { selectedIds.push(notes[selectedNoteIndexes[i]].id); } state = reducer(state, { type: 'NOTE_SELECT', ids: selectedIds }); } - if (tags != null) { + if (tags !== null) { state = reducer(state, { type: 'TAG_UPDATE_ALL', items: tags }); } - if (selectedTagIndex != null) { + if (selectedTagIndex !== null) { state = reducer(state, { type: 'TAG_SELECT', id: tags[selectedTagIndex].id }); } @@ -33,7 +33,7 @@ function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, } function goToNote(notes, selectedNoteIndexes, state) { - if (selectedNoteIndexes != null) { + if (selectedNoteIndexes !== null) { const selectedIds = []; for (let i = 0; i < selectedNoteIndexes.length; i++) { selectedIds.push(notes[selectedNoteIndexes[i]].id); @@ -74,7 +74,7 @@ function createExpectedState(items, keepIndexes, selectedIndexes) { function getIds(items, indexes = null) { const ids = []; for (let i = 0; i < items.length; i++) { - if (indexes == null || i in indexes) { + if (!indexes || i in indexes) { ids.push(items[i].id); } } diff --git a/packages/lib/reducer.ts b/packages/lib/reducer.ts index 1244ab31b1..9390222817 100644 --- a/packages/lib/reducer.ts +++ b/packages/lib/reducer.ts @@ -358,7 +358,7 @@ function handleItemDelete(draft: Draft, action: any) { if (isSelected) { // the selected item is deleted so select the following item // if multiple items are selected then just use the first one - if (selectedItemKeys[0] == item.id) { + if (selectedItemKeys[0] === item.id) { newSelectedIndexes.push(newItems.length); } } else { @@ -367,16 +367,16 @@ function handleItemDelete(draft: Draft, action: any) { newSelectedIndexes.push(newItems.length); } } - if (item.id == action.id) { + if (item.id === action.id) { continue; } newItems.push(item); } - if (newItems.length == 0) { + if (newItems.length === 0) { newSelectedIndexes = []; // no remaining items so no selection - } else if (newSelectedIndexes.length == 0) { + } else if (newSelectedIndexes.length === 0) { newSelectedIndexes.push(0); // no selection exists so select the top } else { @@ -397,7 +397,7 @@ function handleItemDelete(draft: Draft, action: any) { } (draft as any)[selectedItemKey] = isSingular ? newIds[0] : newIds; - if ((newIds.length == 0) && draft.notesParentType !== 'Folder') { + if ((newIds.length === 0) && draft.notesParentType !== 'Folder') { draft.notesParentType = 'Folder'; } } @@ -416,7 +416,7 @@ function updateOneItem(draft: Draft, action: any, keyName: string = '') { let found = false; for (let i = 0; i < newItems.length; i++) { const n = newItems[i]; - if (n.id == item.id) { + if (n.id === item.id) { newItems[i] = Object.assign({}, newItems[i], item); found = true; break; @@ -552,9 +552,9 @@ const getContextFromHistory = (ctx: any) => { function getNoteHistoryInfo(state: State) { const selectedNoteIds = state.selectedNoteIds; const notes = state.notes; - if (selectedNoteIds != null && selectedNoteIds.length > 0) { + if (selectedNoteIds && selectedNoteIds.length > 0) { const currNote = notes.find(note => note.id === selectedNoteIds[0]); - if (currNote != null) { + if (currNote) { return { id: currNote.id, parent_id: currNote.parent_id, @@ -575,7 +575,7 @@ function handleHistory(draft: Draft, action: any) { switch (action.type) { case 'HISTORY_BACKWARD': { const note = draft.backwardHistoryNotes[draft.backwardHistoryNotes.length - 1]; - if (currentNote != null && (draft.forwardHistoryNotes.length === 0 || currentNote.id != draft.forwardHistoryNotes[draft.forwardHistoryNotes.length - 1].id)) { + if (currentNote && (draft.forwardHistoryNotes.length === 0 || currentNote.id !== draft.forwardHistoryNotes[draft.forwardHistoryNotes.length - 1].id)) { draft.forwardHistoryNotes = draft.forwardHistoryNotes.concat(currentNote).slice(-MAX_HISTORY); } @@ -591,7 +591,7 @@ function handleHistory(draft: Draft, action: any) { case 'HISTORY_FORWARD': { const note = draft.forwardHistoryNotes[draft.forwardHistoryNotes.length - 1]; - if (currentNote != null && (draft.backwardHistoryNotes.length === 0 || currentNote.id != draft.backwardHistoryNotes[draft.backwardHistoryNotes.length - 1].id)) { + if (currentNote && (draft.backwardHistoryNotes.length === 0 || currentNote.id !== draft.backwardHistoryNotes[draft.backwardHistoryNotes.length - 1].id)) { draft.backwardHistoryNotes = draft.backwardHistoryNotes.concat(currentNote).slice(-MAX_HISTORY); } @@ -606,12 +606,12 @@ function handleHistory(draft: Draft, action: any) { break; } case 'NOTE_SELECT': - if (currentNote != null && action.id != currentNote.id) { + if (currentNote && action.id !== currentNote.id) { draft.forwardHistoryNotes = []; draft.backwardHistoryNotes = draft.backwardHistoryNotes.concat(currentNote).slice(-MAX_HISTORY); } // History should be free from duplicates. - if (draft.backwardHistoryNotes != null && draft.backwardHistoryNotes.length > 0 && + if (draft.backwardHistoryNotes && draft.backwardHistoryNotes.length > 0 && action.id === draft.backwardHistoryNotes[draft.backwardHistoryNotes.length - 1].id) { draft.backwardHistoryNotes.pop(); } @@ -619,7 +619,7 @@ function handleHistory(draft: Draft, action: any) { case 'TAG_SELECT': case 'FOLDER_AND_NOTE_SELECT': case 'FOLDER_SELECT': - if (currentNote != null) { + if (currentNote) { if (draft.forwardHistoryNotes.length) draft.forwardHistoryNotes = []; draft.backwardHistoryNotes = draft.backwardHistoryNotes.concat(currentNote).slice(-MAX_HISTORY); } @@ -644,22 +644,22 @@ function handleHistory(draft: Draft, action: any) { break; } case 'SEARCH_UPDATE': - if (currentNote != null && (draft.backwardHistoryNotes.length === 0 || - draft.backwardHistoryNotes[draft.backwardHistoryNotes.length - 1].id != currentNote.id)) { + if (currentNote && (draft.backwardHistoryNotes.length === 0 || + draft.backwardHistoryNotes[draft.backwardHistoryNotes.length - 1].id !== currentNote.id)) { if (draft.forwardHistoryNotes.length) draft.forwardHistoryNotes = []; draft.backwardHistoryNotes = draft.backwardHistoryNotes.concat(currentNote).slice(-MAX_HISTORY); } break; case 'FOLDER_DELETE': - draft.backwardHistoryNotes = draft.backwardHistoryNotes.filter(note => note.parent_id != action.id); - draft.forwardHistoryNotes = draft.forwardHistoryNotes.filter(note => note.parent_id != action.id); + draft.backwardHistoryNotes = draft.backwardHistoryNotes.filter(note => note.parent_id !== action.id); + draft.forwardHistoryNotes = draft.forwardHistoryNotes.filter(note => note.parent_id !== action.id); draft.backwardHistoryNotes = removeAdjacentDuplicates(draft.backwardHistoryNotes); draft.forwardHistoryNotes = removeAdjacentDuplicates(draft.forwardHistoryNotes); break; case 'NOTE_DELETE': { - draft.backwardHistoryNotes = draft.backwardHistoryNotes.filter(note => note.id != action.id); - draft.forwardHistoryNotes = draft.forwardHistoryNotes.filter(note => note.id != action.id); + draft.backwardHistoryNotes = draft.backwardHistoryNotes.filter(note => note.id !== action.id); + draft.forwardHistoryNotes = draft.forwardHistoryNotes.filter(note => note.id !== action.id); draft.backwardHistoryNotes = removeAdjacentDuplicates(draft.backwardHistoryNotes); draft.forwardHistoryNotes = removeAdjacentDuplicates(draft.forwardHistoryNotes); @@ -802,7 +802,7 @@ const reducer = produce((draft: Draft = defaultState, action: any) => { const noteIsInFolder = function(note: any, folderId: string) { if (note.is_conflict && isViewingConflictFolder) return true; - if (!('parent_id' in modNote) || note.parent_id == folderId) return true; + if (!('parent_id' in modNote) || note.parent_id === folderId) return true; return false; }; @@ -812,7 +812,7 @@ const reducer = produce((draft: Draft = defaultState, action: any) => { let found = false; for (let i = 0; i < newNotes.length; i++) { const n = newNotes[i]; - if (n.id == modNote.id) { + if (n.id === modNote.id) { if (n.is_conflict && !modNote.is_conflict) { // Note was a conflict but was moved outside of // the conflict folder diff --git a/packages/lib/services/synchronizer/Synchronizer.conflicts.test.ts b/packages/lib/services/synchronizer/Synchronizer.conflicts.test.ts index 68621a632c..b57fb0b627 100644 --- a/packages/lib/services/synchronizer/Synchronizer.conflicts.test.ts +++ b/packages/lib/services/synchronizer/Synchronizer.conflicts.test.ts @@ -42,11 +42,11 @@ describe('Synchronizer.conflicts', function() { // Other than the id (since the conflicted note is a duplicate), and the is_conflict property // the conflicted and original note must be the same in every way, to make sure no data has been lost. const conflictedNote = conflictedNotes[0]; - expect(conflictedNote.id == note2conf.id).toBe(false); + expect(conflictedNote.id === note2conf.id).toBe(false); expect(conflictedNote.conflict_original_id).toBe(note2conf.id); for (const n in conflictedNote) { if (!conflictedNote.hasOwnProperty(n)) continue; - if (n == 'id' || n == 'is_conflict' || n == 'conflict_original_id') continue; + if (n === 'id' || n === 'is_conflict' || n === 'conflict_original_id') continue; expect(conflictedNote[n]).toBe(note2conf[n]); } diff --git a/packages/lib/shim.ts b/packages/lib/shim.ts index 26dc7b1bf5..22610bdf85 100644 --- a/packages/lib/shim.ts +++ b/packages/lib/shim.ts @@ -41,7 +41,7 @@ const shim = { isNode: () => { if (typeof process === 'undefined') return false; if (shim.isElectron()) return true; - return process.title == 'node' || (process.title && process.title.indexOf('gulp') === 0); + return process.title === 'node' || (process.title && process.title.indexOf('gulp') === 0); }, isReactNative: () => { @@ -115,16 +115,16 @@ const shim = { // Unfortunately the error 'Network request failed' doesn't have a type // or error code, so hopefully that message won't change and is not localized - if (error.message == 'Network request failed') return true; + if (error.message === 'Network request failed') return true; // request to https://public-ch3302....1fab24cb1bd5f.md failed, reason: socket hang up" - if (error.code == 'ECONNRESET') return true; + if (error.code === 'ECONNRESET') return true; // OneDrive (or Node?) sometimes sends back a "not found" error for resources // that definitely exist and in this case repeating the request works. // Error is: // request to https://graph.microsoft.com/v1.0/drive/special/approot failed, reason: getaddrinfo ENOTFOUND graph.microsoft.com graph.microsoft.com:443 - if (error.code == 'ENOTFOUND') return true; + if (error.code === 'ENOTFOUND') return true; // network timeout at: https://public-ch3302...859f9b0e3ab.md if (error.message && error.message.indexOf('network timeout') === 0) return true; @@ -136,7 +136,7 @@ const shim = { // code: 'EAI_AGAIN' } } reason: { FetchError: request to https://api.ipify.org/?format=json failed, reason: getaddrinfo EAI_AGAIN api.ipify.org:443 // // It's a Microsoft error: "A temporary failure in name resolution occurred." - if (error.code == 'EAI_AGAIN') return true; + if (error.code === 'EAI_AGAIN') return true; // request to https://public-...8fd8bc6bb68e9c4d17a.md failed, reason: connect ETIMEDOUT 204.79.197.213:443 // Code: ETIMEDOUT diff --git a/packages/lib/string-utils.js b/packages/lib/string-utils.js index 3b361818fe..61365a5c4d 100644 --- a/packages/lib/string-utils.js +++ b/packages/lib/string-utils.js @@ -111,7 +111,7 @@ function escapeFilename(s, maxLength = 32) { output = output.replace(unsafe[i], '_'); } - if (output.toLowerCase() == 'nul') output = 'n_l'; // For Windows... + if (output.toLowerCase() === 'nul') output = 'n_l'; // For Windows... return output.substr(0, maxLength); } @@ -152,8 +152,8 @@ function splitCommandString(command, options = null) { for (let i = 0; i < command.length; i++) { const c = command[i]; - if (state == 'quotes') { - if (c != quote) { + if (state === 'quotes') { + if (c !== quote) { current += c; } else { args.push(current); @@ -169,19 +169,19 @@ function splitCommandString(command, options = null) { continue; } - if (c == '\\' && options.handleEscape) { + if (c === '\\' && options.handleEscape) { escapeNext = true; continue; } - if (c == '"' || c == '\'') { + if (c === '"' || c === '\'') { state = 'quotes'; quote = c; continue; } - if (state == 'arg') { - if (c == ' ' || c == '\t') { + if (state === 'arg') { + if (c === ' ' || c === '\t') { args.push(current); current = ''; state = 'start'; @@ -191,17 +191,17 @@ function splitCommandString(command, options = null) { continue; } - if (c != ' ' && c != '\t') { + if (c !== ' ' && c !== '\t') { state = 'arg'; current += c; } } - if (state == 'quotes') { + if (state === 'quotes') { throw new Error(`Unclosed quote in command line: ${command}`); } - if (current != '') { + if (current !== '') { args.push(current); } diff --git a/packages/lib/testing/test-utils.ts b/packages/lib/testing/test-utils.ts index 35d5b7ff1f..44878a8783 100644 --- a/packages/lib/testing/test-utils.ts +++ b/packages/lib/testing/test-utils.ts @@ -137,7 +137,7 @@ function setSyncTargetName(name: string) { const previousName = syncTargetName_; syncTargetName_ = name; syncTargetId_ = SyncTargetRegistry.nameToId(syncTargetName_); - sleepTime = syncTargetId_ == SyncTargetRegistry.nameToId('filesystem') ? 1001 : 100;// 400; + sleepTime = syncTargetId_ === SyncTargetRegistry.nameToId('filesystem') ? 1001 : 100;// 400; isNetworkSyncTarget_ = ['nextcloud', 'dropbox', 'onedrive', 'amazon_s3', 'joplinServer'].includes(syncTargetName_); synchronizers_ = []; return previousName; @@ -563,13 +563,13 @@ async function initFileApi() { if (fileApis_[syncTargetId_]) return; let fileApi = null; - if (syncTargetId_ == SyncTargetRegistry.nameToId('filesystem')) { + if (syncTargetId_ === SyncTargetRegistry.nameToId('filesystem')) { fs.removeSync(syncDir); fs.mkdirpSync(syncDir); fileApi = new FileApi(syncDir, new FileApiDriverLocal()); - } else if (syncTargetId_ == SyncTargetRegistry.nameToId('memory')) { + } else if (syncTargetId_ === SyncTargetRegistry.nameToId('memory')) { fileApi = new FileApi('/root', new FileApiDriverMemory()); - } else if (syncTargetId_ == SyncTargetRegistry.nameToId('nextcloud')) { + } else if (syncTargetId_ === SyncTargetRegistry.nameToId('nextcloud')) { const options = require(`${oldTestDir}/support/nextcloud-auth.json`); const api = new WebDavApi({ baseUrl: () => options.baseUrl, @@ -577,7 +577,7 @@ async function initFileApi() { password: () => options.password, }); fileApi = new FileApi('', new FileApiDriverWebDav(api)); - } else if (syncTargetId_ == SyncTargetRegistry.nameToId('dropbox')) { + } else if (syncTargetId_ === SyncTargetRegistry.nameToId('dropbox')) { // To get a token, go to the App Console: // https://www.dropbox.com/developers/apps/ // Then select "JoplinTest" and click "Generated access token" @@ -587,7 +587,7 @@ async function initFileApi() { if (!authToken) throw new Error(`Dropbox auth token missing in ${authTokenPath}`); api.setAuthToken(authToken); fileApi = new FileApi('', new FileApiDriverDropbox(api)); - } else if (syncTargetId_ == SyncTargetRegistry.nameToId('onedrive')) { + } else if (syncTargetId_ === SyncTargetRegistry.nameToId('onedrive')) { // To get a token, open the URL below corresponding to your account type, // then copy the *complete* redirection URL in onedrive-auth.txt. Keep in mind that auth // data only lasts 1h for OneDrive. @@ -620,7 +620,7 @@ async function initFileApi() { const appDir = await api.appDirectory(); fileApi = new FileApi(appDir, new FileApiDriverOneDrive(api)); - } else if (syncTargetId_ == SyncTargetRegistry.nameToId('amazon_s3')) { + } else if (syncTargetId_ === SyncTargetRegistry.nameToId('amazon_s3')) { // We make sure for S3 tests run in band because tests // share the same directory which will cause locking errors. @@ -632,7 +632,7 @@ async function initFileApi() { if (!amazonS3Creds || !amazonS3Creds.credentials) throw new Error(`AWS auth JSON missing in ${amazonS3CredsPath} format should be: { "credentials": { "accessKeyId": "", "secretAccessKey": "", } "bucket": "mybucket", region: "", forcePathStyle: ""}`); const api = new S3Client({ region: amazonS3Creds.region, credentials: amazonS3Creds.credentials, s3UseArnRegion: true, forcePathStyle: amazonS3Creds.forcePathStyle, endpoint: amazonS3Creds.endpoint }); fileApi = new FileApi('', new FileApiDriverAmazonS3(api, amazonS3Creds.bucket)); - } else if (syncTargetId_ == SyncTargetRegistry.nameToId('joplinServer')) { + } else if (syncTargetId_ === SyncTargetRegistry.nameToId('joplinServer')) { mustRunInBand(); const joplinServerAuth = JSON.parse(await readCredentialFile('joplin-server-test-units-2.json')); diff --git a/packages/tools/tool-utils.ts b/packages/tools/tool-utils.ts index 1a706b8cdb..4ba13ad1ee 100644 --- a/packages/tools/tool-utils.ts +++ b/packages/tools/tool-utils.ts @@ -137,7 +137,7 @@ export function execCommand(command: string, options: any = null): Promise { exec(command, options, (error: any, stdout: any, stderr: any) => { if (error) { - if (error.signal == 'SIGTERM') { + if (error.signal === 'SIGTERM') { resolve('Process was killed'); } else { reject(error); @@ -301,9 +301,9 @@ export function fileExists(filePath: string) { return new Promise((resolve, reject) => { fs.stat(filePath, function(err: any) { - if (err == null) { + if (!err) { resolve(true); - } else if (err.code == 'ENOENT') { + } else if (err.code === 'ENOENT') { resolve(false); } else { reject(err);