1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-07 22:03:09 +02:00

Tools: Enforce and apply eslint rules prefer-const and no-var

This commit is contained in:
Laurent Cozic
2020-03-13 23:46:14 +00:00
parent 92bee549a1
commit d0d2bad7f4
189 changed files with 1387 additions and 1377 deletions

View File

@ -54,16 +54,20 @@ module.exports = {
// This error is always a false positive so far since it detects // This error is always a false positive so far since it detects
// possible race conditions in contexts where we know it cannot happen. // possible race conditions in contexts where we know it cannot happen.
"require-atomic-updates": 0, "require-atomic-updates": 0,
"prefer-const": ["error"],
"no-var": ["error"],
// Checks rules of Hooks // Checks rules of Hooks
"react-hooks/rules-of-hooks": "error", "react-hooks/rules-of-hooks": "error",
// Checks effect dependencies // Checks effect dependencies
"react-hooks/exhaustive-deps": "warn", // Disable because of this: https://github.com/facebook/react/issues/16265
// "react-hooks/exhaustive-deps": "warn",
// ------------------------------- // -------------------------------
// Formatting // Formatting
// ------------------------------- // -------------------------------
"space-in-parens": ["error", "never"], "space-in-parens": ["error", "never"],
"space-infix-ops": ["error"],
"semi": ["error", "always"], "semi": ["error", "always"],
"eol-last": ["error", "always"], "eol-last": ["error", "always"],
"quotes": ["error", "single"], "quotes": ["error", "single"],
@ -92,7 +96,7 @@ module.exports = {
"multiline-comment-style": ["error", "separate-lines"], "multiline-comment-style": ["error", "separate-lines"],
"space-before-blocks": "error", "space-before-blocks": "error",
"spaced-comment": ["error", "always"], "spaced-comment": ["error", "always"],
"keyword-spacing": ["error", { "before": true, "after": true }] "keyword-spacing": ["error", { "before": true, "after": true }],
}, },
"plugins": [ "plugins": [
"react", "react",

View File

@ -134,7 +134,7 @@ class AppGui {
const item = folderList.currentItem; const item = folderList.currentItem;
if (item === '-') { if (item === '-') {
let newIndex = event.currentIndex + (event.previousIndex < event.currentIndex ? +1 : -1); const newIndex = event.currentIndex + (event.previousIndex < event.currentIndex ? +1 : -1);
let nextItem = folderList.itemAt(newIndex); let nextItem = folderList.itemAt(newIndex);
if (!nextItem) nextItem = folderList.itemAt(event.previousIndex); if (!nextItem) nextItem = folderList.itemAt(event.previousIndex);
@ -186,7 +186,7 @@ class AppGui {
borderRightWidth: 1, borderRightWidth: 1,
}; };
noteList.on('currentItemChange', async () => { noteList.on('currentItemChange', async () => {
let note = noteList.currentItem; const note = noteList.currentItem;
this.store_.dispatch({ this.store_.dispatch({
type: 'NOTE_SELECT', type: 'NOTE_SELECT',
id: note ? note.id : null, id: note ? note.id : null,
@ -338,7 +338,7 @@ class AppGui {
if (consoleWidget.isMaximized__ === doMaximize) return; if (consoleWidget.isMaximized__ === doMaximize) return;
let constraints = { const constraints = {
type: 'stretch', type: 'stretch',
factor: !doMaximize ? 1 : 4, factor: !doMaximize ? 1 : 4,
}; };
@ -415,10 +415,10 @@ class AppGui {
async handleModelAction(action) { async handleModelAction(action) {
this.logger().info('Action:', action); this.logger().info('Action:', action);
let state = Object.assign({}, defaultState); const state = Object.assign({}, defaultState);
state.notes = this.widget('noteList').items; state.notes = this.widget('noteList').items;
let newState = reducer(state, action); const newState = reducer(state, action);
if (newState !== state) { if (newState !== state) {
this.widget('noteList').items = newState.notes; this.widget('noteList').items = newState.notes;
@ -485,9 +485,9 @@ class AppGui {
// this.logger().debug('Got command: ' + cmd); // this.logger().debug('Got command: ' + cmd);
try { try {
let note = this.widget('noteList').currentItem; const note = this.widget('noteList').currentItem;
let folder = this.widget('folderList').currentItem; const folder = this.widget('folderList').currentItem;
let args = splitCommandString(cmd); const args = splitCommandString(cmd);
for (let i = 0; i < args.length; i++) { for (let i = 0; i < args.length; i++) {
if (args[i] == '$n') { if (args[i] == '$n') {
@ -548,7 +548,7 @@ class AppGui {
stdout(text) { stdout(text) {
if (text === null || text === undefined) return; if (text === null || text === undefined) return;
let lines = text.split('\n'); const lines = text.split('\n');
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
const v = typeof lines[i] === 'object' ? JSON.stringify(lines[i]) : lines[i]; const v = typeof lines[i] === 'object' ? JSON.stringify(lines[i]) : lines[i];
this.widget('console').addLine(v); this.widget('console').addLine(v);
@ -626,7 +626,7 @@ class AppGui {
if (link.type === 'item') { if (link.type === 'item') {
const itemId = link.id; const itemId = link.id;
let item = await BaseItem.loadItemById(itemId); const item = await BaseItem.loadItemById(itemId);
if (!item) throw new Error(`No item with ID ${itemId}`); // Should be nearly impossible if (!item) throw new Error(`No item with ID ${itemId}`); // Should be nearly impossible
if (item.type_ === BaseModel.TYPE_RESOURCE) { if (item.type_ === BaseModel.TYPE_RESOURCE) {
@ -750,7 +750,7 @@ class AppGui {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const shortcutKey = this.currentShortcutKeys_.join(''); const shortcutKey = this.currentShortcutKeys_.join('');
let keymapItem = this.keymapItemByKey(shortcutKey); const keymapItem = this.keymapItemByKey(shortcutKey);
// If this command is an alias to another command, resolve to the actual command // If this command is an alias to another command, resolve to the actual command
@ -766,7 +766,7 @@ class AppGui {
if (keymapItem.type === 'function') { if (keymapItem.type === 'function') {
this.processFunctionCommand(keymapItem.command); this.processFunctionCommand(keymapItem.command);
} else if (keymapItem.type === 'prompt') { } else if (keymapItem.type === 'prompt') {
let promptOptions = {}; const promptOptions = {};
if ('cursorPosition' in keymapItem) promptOptions.cursorPosition = keymapItem.cursorPosition; if ('cursorPosition' in keymapItem) promptOptions.cursorPosition = keymapItem.cursorPosition;
const commandString = await statusBar.prompt(keymapItem.command ? keymapItem.command : '', null, promptOptions); const commandString = await statusBar.prompt(keymapItem.command ? keymapItem.command : '', null, promptOptions);
this.addCommandToConsole(commandString); this.addCommandToConsole(commandString);

View File

@ -47,7 +47,7 @@ class Application extends BaseApplication {
} }
async loadItem(type, pattern, options = null) { async loadItem(type, pattern, options = null) {
let output = await this.loadItems(type, pattern, options); const output = await this.loadItems(type, pattern, options);
if (output.length > 1) { if (output.length > 1) {
// output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; }); // output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; });
@ -144,7 +144,7 @@ class Application extends BaseApplication {
if (options.type === 'boolean') { if (options.type === 'boolean') {
if (answer === null) return false; // Pressed ESCAPE if (answer === null) return false; // Pressed ESCAPE
if (!answer) answer = options.answers[0]; if (!answer) answer = options.answers[0];
let positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1; const positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1;
return answer.toLowerCase() === options.answers[positiveIndex].toLowerCase(); return answer.toLowerCase() === options.answers[positiveIndex].toLowerCase();
} else { } else {
return answer; return answer;
@ -181,7 +181,7 @@ class Application extends BaseApplication {
const ext = fileExtension(path); const ext = fileExtension(path);
if (ext != 'js') return; if (ext != 'js') return;
let CommandClass = require(`./${path}`); const CommandClass = require(`./${path}`);
let cmd = new CommandClass(); let cmd = new CommandClass();
if (!cmd.enabled()) return; if (!cmd.enabled()) return;
cmd = this.setupCommand(cmd); cmd = this.setupCommand(cmd);
@ -192,8 +192,8 @@ class Application extends BaseApplication {
} }
if (uiType !== null) { if (uiType !== null) {
let temp = []; const temp = [];
for (let n in this.commands_) { for (const n in this.commands_) {
if (!this.commands_.hasOwnProperty(n)) continue; if (!this.commands_.hasOwnProperty(n)) continue;
const c = this.commands_[n]; const c = this.commands_[n];
if (!c.supportsUi(uiType)) continue; if (!c.supportsUi(uiType)) continue;
@ -207,8 +207,8 @@ class Application extends BaseApplication {
async commandNames() { async commandNames() {
const metadata = await this.commandMetadata(); const metadata = await this.commandMetadata();
let output = []; const output = [];
for (let n in metadata) { for (const n in metadata) {
if (!metadata.hasOwnProperty(n)) continue; if (!metadata.hasOwnProperty(n)) continue;
output.push(n); output.push(n);
} }
@ -227,7 +227,7 @@ class Application extends BaseApplication {
const commands = this.commands(); const commands = this.commands();
output = {}; output = {};
for (let n in commands) { for (const n in commands) {
if (!commands.hasOwnProperty(n)) continue; if (!commands.hasOwnProperty(n)) continue;
const cmd = commands[n]; const cmd = commands[n];
output[n] = cmd.metadata(); output[n] = cmd.metadata();
@ -251,7 +251,7 @@ class Application extends BaseApplication {
CommandClass = require(`${__dirname}/command-${name}.js`); CommandClass = require(`${__dirname}/command-${name}.js`);
} catch (error) { } catch (error) {
if (error.message && error.message.indexOf('Cannot find module') >= 0) { if (error.message && error.message.indexOf('Cannot find module') >= 0) {
let e = new Error(_('No such command: %s', name)); const e = new Error(_('No such command: %s', name));
e.type = 'notFound'; e.type = 'notFound';
throw e; throw e;
} else { } else {
@ -362,7 +362,7 @@ class Application extends BaseApplication {
} }
const output = []; const output = [];
for (let n in itemsByCommand) { for (const n in itemsByCommand) {
if (!itemsByCommand.hasOwnProperty(n)) continue; if (!itemsByCommand.hasOwnProperty(n)) continue;
output.push(itemsByCommand[n]); output.push(itemsByCommand[n]);
} }

View File

@ -1,20 +1,20 @@
var { app } = require('./app.js'); const { app } = require('./app.js');
var Note = require('lib/models/Note.js'); const Note = require('lib/models/Note.js');
var Folder = require('lib/models/Folder.js'); const Folder = require('lib/models/Folder.js');
var Tag = require('lib/models/Tag.js'); const Tag = require('lib/models/Tag.js');
var { cliUtils } = require('./cli-utils.js'); const { cliUtils } = require('./cli-utils.js');
var yargParser = require('yargs-parser'); const yargParser = require('yargs-parser');
var fs = require('fs-extra'); const fs = require('fs-extra');
async function handleAutocompletionPromise(line) { async function handleAutocompletionPromise(line) {
// Auto-complete the command name // Auto-complete the command name
const names = await app().commandNames(); const names = await app().commandNames();
let words = getArguments(line); const words = getArguments(line);
// If there is only one word and it is not already a command name then you // If there is only one word and it is not already a command name then you
// should look for commands it could be // should look for commands it could be
if (words.length == 1) { if (words.length == 1) {
if (names.indexOf(words[0]) === -1) { if (names.indexOf(words[0]) === -1) {
let x = names.filter(n => n.indexOf(words[0]) === 0); const x = names.filter(n => n.indexOf(words[0]) === 0);
if (x.length === 1) { if (x.length === 1) {
return `${x[0]} `; return `${x[0]} `;
} }
@ -36,8 +36,8 @@ async function handleAutocompletionPromise(line) {
} }
// complete an option // complete an option
let next = words.length > 1 ? words[words.length - 1] : ''; const next = words.length > 1 ? words[words.length - 1] : '';
let l = []; const l = [];
if (next[0] === '-') { if (next[0] === '-') {
for (let i = 0; i < metadata.options.length; i++) { for (let i = 0; i < metadata.options.length; i++) {
const options = metadata.options[i][0].split(' '); const options = metadata.options[i][0].split(' ');
@ -60,7 +60,7 @@ async function handleAutocompletionPromise(line) {
if (l.length === 0) { if (l.length === 0) {
return line; return line;
} }
let ret = l.map(a => toCommandLine(a)); const ret = l.map(a => toCommandLine(a));
ret.prefix = `${toCommandLine(words.slice(0, -1))} `; ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
return ret; return ret;
} }
@ -69,7 +69,7 @@ async function handleAutocompletionPromise(line) {
// words that don't start with a - less one for the command name // words that don't start with a - less one for the command name
const positionalArgs = words.filter(a => a.indexOf('-') !== 0).length - 1; const positionalArgs = words.filter(a => a.indexOf('-') !== 0).length - 1;
let cmdUsage = yargParser(metadata.usage)['_']; const cmdUsage = yargParser(metadata.usage)['_'];
cmdUsage.splice(0, 1); cmdUsage.splice(0, 1);
if (cmdUsage.length >= positionalArgs) { if (cmdUsage.length >= positionalArgs) {
@ -95,29 +95,29 @@ async function handleAutocompletionPromise(line) {
} }
if (argName == 'tag') { if (argName == 'tag') {
let tags = await Tag.search({ titlePattern: `${next}*` }); const tags = await Tag.search({ titlePattern: `${next}*` });
l.push(...tags.map(n => n.title)); l.push(...tags.map(n => n.title));
} }
if (argName == 'file') { if (argName == 'file') {
let files = await fs.readdir('.'); const files = await fs.readdir('.');
l.push(...files); l.push(...files);
} }
if (argName == 'tag-command') { if (argName == 'tag-command') {
let c = filterList(['add', 'remove', 'list', 'notetags'], next); const c = filterList(['add', 'remove', 'list', 'notetags'], next);
l.push(...c); l.push(...c);
} }
if (argName == 'todo-command') { if (argName == 'todo-command') {
let c = filterList(['toggle', 'clear'], next); const c = filterList(['toggle', 'clear'], next);
l.push(...c); l.push(...c);
} }
} }
if (l.length === 1) { if (l.length === 1) {
return toCommandLine([...words.slice(0, -1), l[0]]); return toCommandLine([...words.slice(0, -1), l[0]]);
} else if (l.length > 1) { } else if (l.length > 1) {
let ret = l.map(a => toCommandLine(a)); const ret = l.map(a => toCommandLine(a));
ret.prefix = `${toCommandLine(words.slice(0, -1))} `; ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
return ret; return ret;
} }
@ -155,7 +155,7 @@ function getArguments(line) {
let inSingleQuotes = false; let inSingleQuotes = false;
let inDoubleQuotes = false; let inDoubleQuotes = false;
let currentWord = ''; let currentWord = '';
let parsed = []; const parsed = [];
for (let i = 0; i < line.length; i++) { for (let i = 0; i < line.length; i++) {
if (line[i] === '"') { if (line[i] === '"') {
if (inDoubleQuotes) { if (inDoubleQuotes) {
@ -192,7 +192,7 @@ function getArguments(line) {
return parsed; return parsed;
} }
function filterList(list, next) { function filterList(list, next) {
let output = []; const output = [];
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
if (list[i].indexOf(next) !== 0) continue; if (list[i].indexOf(next) !== 0) continue;
output.push(list[i]); output.push(list[i]);

View File

@ -50,7 +50,7 @@ class BaseCommand {
async cancel() {} async cancel() {}
name() { name() {
let r = this.usage().split(' '); const r = this.usage().split(' ');
return r[0]; return r[0];
} }

View File

@ -15,11 +15,11 @@ function wrap(text, indent) {
} }
function renderOptions(options) { function renderOptions(options) {
let output = []; const output = [];
const optionColWidth = getOptionColWidth(options); const optionColWidth = getOptionColWidth(options);
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
let option = options[i]; const option = options[i];
const flag = option[0]; const flag = option[0];
const indent = INDENT + INDENT + ' '.repeat(optionColWidth + 2); const indent = INDENT + INDENT + ' '.repeat(optionColWidth + 2);
@ -33,7 +33,7 @@ function renderOptions(options) {
} }
function renderCommand(cmd) { function renderCommand(cmd) {
let output = []; const output = [];
output.push(INDENT + cmd.usage()); output.push(INDENT + cmd.usage());
output.push(''); output.push('');
output.push(wrap(cmd.description(), INDENT + INDENT)); output.push(wrap(cmd.description(), INDENT + INDENT));
@ -48,14 +48,14 @@ function renderCommand(cmd) {
} }
function getCommands() { function getCommands() {
let output = []; const output = [];
fs.readdirSync(__dirname).forEach(path => { fs.readdirSync(__dirname).forEach(path => {
if (path.indexOf('command-') !== 0) return; if (path.indexOf('command-') !== 0) return;
const ext = fileExtension(path); const ext = fileExtension(path);
if (ext != 'js') return; if (ext != 'js') return;
let CommandClass = require(`./${path}`); const CommandClass = require(`./${path}`);
let cmd = new CommandClass(); const cmd = new CommandClass();
if (!cmd.enabled()) return; if (!cmd.enabled()) return;
if (cmd.hidden()) return; if (cmd.hidden()) return;
output.push(cmd); output.push(cmd);
@ -73,7 +73,7 @@ function getOptionColWidth(options) {
} }
function getHeader() { function getHeader() {
let output = []; const output = [];
output.push('NAME'); output.push('NAME');
output.push(''); output.push('');
@ -84,7 +84,7 @@ function getHeader() {
output.push('DESCRIPTION'); output.push('DESCRIPTION');
output.push(''); output.push('');
let description = []; const description = [];
description.push('Joplin is a note taking and to-do application, which can handle a large number of notes organised into notebooks.'); description.push('Joplin is a note taking and to-do application, which can handle a large number of notes organised into notebooks.');
description.push('The notes are searchable, can be copied, tagged and modified with your own text editor.'); description.push('The notes are searchable, can be copied, tagged and modified with your own text editor.');
description.push('\n\n'); description.push('\n\n');
@ -98,7 +98,7 @@ function getHeader() {
} }
function getFooter() { function getFooter() {
let output = []; const output = [];
output.push('WEBSITE'); output.push('WEBSITE');
output.push(''); output.push('');
@ -120,10 +120,10 @@ async function main() {
// setLocale('fr_FR'); // setLocale('fr_FR');
const commands = getCommands(); const commands = getCommands();
let commandBlocks = []; const commandBlocks = [];
for (let i = 0; i < commands.length; i++) { for (let i = 0; i < commands.length; i++) {
let cmd = commands[i]; const cmd = commands[i];
commandBlocks.push(renderCommand(cmd)); commandBlocks.push(renderCommand(cmd));
} }

View File

@ -40,8 +40,8 @@ function createClient(id) {
const client = createClient(1); const client = createClient(1);
function execCommand(client, command) { function execCommand(client, command) {
let exePath = `node ${joplinAppPath}`; const exePath = `node ${joplinAppPath}`;
let cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`; const cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`;
logger.info(`${client.id}: ${command}`); logger.info(`${client.id}: ${command}`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -129,8 +129,8 @@ testUnits.testCat = async () => {
await execCommand(client, 'mkbook nb1'); await execCommand(client, 'mkbook nb1');
await execCommand(client, 'mknote mynote'); await execCommand(client, 'mknote mynote');
let folder = await Folder.loadByTitle('nb1'); const folder = await Folder.loadByTitle('nb1');
let note = await Note.loadFolderNoteByField(folder.id, 'title', 'mynote'); const note = await Note.loadFolderNoteByField(folder.id, 'title', 'mynote');
let r = await execCommand(client, 'cat mynote'); let r = await execCommand(client, 'cat mynote');
assertTrue(r.indexOf('mynote') >= 0); assertTrue(r.indexOf('mynote') >= 0);
@ -149,7 +149,7 @@ testUnits.testConfig = async () => {
await Setting.load(); await Setting.load();
assertEquals('subl', Setting.value('editor')); assertEquals('subl', Setting.value('editor'));
let r = await execCommand(client, 'config'); const r = await execCommand(client, 'config');
assertTrue(r.indexOf('editor') >= 0); assertTrue(r.indexOf('editor') >= 0);
assertTrue(r.indexOf('subl') >= 0); assertTrue(r.indexOf('subl') >= 0);
}; };
@ -161,14 +161,14 @@ testUnits.testCp = async () => {
await execCommand(client, 'cp n1'); await execCommand(client, 'cp n1');
let f1 = await Folder.loadByTitle('nb1'); const f1 = await Folder.loadByTitle('nb1');
let f2 = await Folder.loadByTitle('nb2'); const f2 = await Folder.loadByTitle('nb2');
let notes = await Note.previews(f1.id); let notes = await Note.previews(f1.id);
assertEquals(2, notes.length); assertEquals(2, notes.length);
await execCommand(client, 'cp n1 nb2'); await execCommand(client, 'cp n1 nb2');
let notesF1 = await Note.previews(f1.id); const notesF1 = await Note.previews(f1.id);
assertEquals(2, notesF1.length); assertEquals(2, notesF1.length);
notes = await Note.previews(f2.id); notes = await Note.previews(f2.id);
assertEquals(1, notes.length); assertEquals(1, notes.length);
@ -179,7 +179,7 @@ testUnits.testLs = async () => {
await execCommand(client, 'mkbook nb1'); await execCommand(client, 'mkbook nb1');
await execCommand(client, 'mknote note1'); await execCommand(client, 'mknote note1');
await execCommand(client, 'mknote note2'); await execCommand(client, 'mknote note2');
let r = await execCommand(client, 'ls'); const r = await execCommand(client, 'ls');
assertTrue(r.indexOf('note1') >= 0); assertTrue(r.indexOf('note1') >= 0);
assertTrue(r.indexOf('note2') >= 0); assertTrue(r.indexOf('note2') >= 0);
@ -191,8 +191,8 @@ testUnits.testMv = async () => {
await execCommand(client, 'mknote n1'); await execCommand(client, 'mknote n1');
await execCommand(client, 'mv n1 nb2'); await execCommand(client, 'mv n1 nb2');
let f1 = await Folder.loadByTitle('nb1'); const f1 = await Folder.loadByTitle('nb1');
let f2 = await Folder.loadByTitle('nb2'); const f2 = await Folder.loadByTitle('nb2');
let notes1 = await Note.previews(f1.id); let notes1 = await Note.previews(f1.id);
let notes2 = await Note.previews(f2.id); let notes2 = await Note.previews(f2.id);
@ -224,12 +224,12 @@ async function main() {
let onlyThisTest = 'testMv'; let onlyThisTest = 'testMv';
onlyThisTest = ''; onlyThisTest = '';
for (let n in testUnits) { for (const n in testUnits) {
if (!testUnits.hasOwnProperty(n)) continue; if (!testUnits.hasOwnProperty(n)) continue;
if (onlyThisTest && n != onlyThisTest) continue; if (onlyThisTest && n != onlyThisTest) continue;
await clearDatabase(); await clearDatabase();
let testName = n.substr(4).toLowerCase(); const testName = n.substr(4).toLowerCase();
process.stdout.write(`${testName}: `); process.stdout.write(`${testName}: `);
await testUnits[n](); await testUnits[n]();
console.info(''); console.info('');

View File

@ -11,27 +11,27 @@ cliUtils.printArray = function(logFunction, rows) {
const ALIGN_LEFT = 0; const ALIGN_LEFT = 0;
const ALIGN_RIGHT = 1; const ALIGN_RIGHT = 1;
let colWidths = []; const colWidths = [];
let colAligns = []; const colAligns = [];
for (let i = 0; i < rows.length; i++) { for (let i = 0; i < rows.length; i++) {
let row = rows[i]; const row = rows[i];
for (let j = 0; j < row.length; j++) { for (let j = 0; j < row.length; j++) {
let item = row[j]; const item = row[j];
let width = item ? item.toString().length : 0; const width = item ? item.toString().length : 0;
let 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 (!colWidths[j] || colWidths[j] < width) colWidths[j] = width;
if (colAligns.length <= j) colAligns[j] = align; if (colAligns.length <= j) colAligns[j] = align;
} }
} }
for (let row = 0; row < rows.length; row++) { for (let row = 0; row < rows.length; row++) {
let line = []; const line = [];
for (let col = 0; col < colWidths.length; col++) { for (let col = 0; col < colWidths.length; col++) {
let item = rows[row][col]; const item = rows[row][col];
let width = colWidths[col]; const width = colWidths[col];
let 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)); line.push(stringPadding(item, width, ' ', dir));
} }
logFunction(line.join(' ')); logFunction(line.join(' '));
@ -39,7 +39,7 @@ cliUtils.printArray = function(logFunction, rows) {
}; };
cliUtils.parseFlags = function(flags) { cliUtils.parseFlags = function(flags) {
let output = {}; const output = {};
flags = flags.split(','); flags = flags.split(',');
for (let i = 0; i < flags.length; i++) { for (let i = 0; i < flags.length; i++) {
let f = flags[i].trim(); let f = flags[i].trim();
@ -76,11 +76,11 @@ cliUtils.parseCommandArg = function(arg) {
cliUtils.makeCommandArgs = function(cmd, argv) { cliUtils.makeCommandArgs = function(cmd, argv) {
let cmdUsage = cmd.usage(); let cmdUsage = cmd.usage();
cmdUsage = yargParser(cmdUsage); cmdUsage = yargParser(cmdUsage);
let output = {}; const output = {};
let options = cmd.options(); const options = cmd.options();
let booleanFlags = []; const booleanFlags = [];
let aliases = {}; const aliases = {};
for (let i = 0; i < options.length; i++) { 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]; let flags = options[i][0];
@ -97,7 +97,7 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
} }
} }
let args = yargParser(argv, { const args = yargParser(argv, {
boolean: booleanFlags, boolean: booleanFlags,
alias: aliases, alias: aliases,
string: ['_'], string: ['_'],
@ -113,8 +113,8 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
} }
} }
let argOptions = {}; const argOptions = {};
for (let key in args) { for (const key in args) {
if (!args.hasOwnProperty(key)) continue; if (!args.hasOwnProperty(key)) continue;
if (key == '_') continue; if (key == '_') continue;
argOptions[key] = args[key]; argOptions[key] = args[key];
@ -134,7 +134,7 @@ cliUtils.promptMcq = function(message, answers) {
}); });
message += '\n\n'; message += '\n\n';
for (let n in answers) { for (const n in answers) {
if (!answers.hasOwnProperty(n)) continue; if (!answers.hasOwnProperty(n)) continue;
message += `${_('%s: %s', n, answers[n])}\n`; message += `${_('%s: %s', n, answers[n])}\n`;
} }

View File

@ -14,9 +14,9 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let title = args['note']; const title = args['note'];
let note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() }); const note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
this.encryptionCheck(note); this.encryptionCheck(note);
if (!note) throw new Error(_('Cannot find "%s".', title)); if (!note) throw new Error(_('Cannot find "%s".', title));

View File

@ -18,9 +18,9 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let title = args['note']; const title = args['note'];
let item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() }); const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
if (!item) throw new Error(_('Cannot find "%s".', title)); if (!item) throw new Error(_('Cannot find "%s".', title));
const content = args.options.verbose ? await Note.serialize(item) : await Note.serializeForEdit(item); const content = args.options.verbose ? await Note.serialize(item) : await Note.serializeForEdit(item);

View File

@ -35,7 +35,7 @@ class Command extends BaseCommand {
}); });
inputStream.on('end', () => { inputStream.on('end', () => {
let json = chunks.join(''); const json = chunks.join('');
let settingsObj; let settingsObj;
try { try {
settingsObj = JSON.parse(json); settingsObj = JSON.parse(json);
@ -83,7 +83,7 @@ class Command extends BaseCommand {
}; };
if (isExport || (!isImport && !args.value)) { if (isExport || (!isImport && !args.value)) {
let keys = Setting.keys(!verbose, 'cli'); const keys = Setting.keys(!verbose, 'cli');
keys.sort(); keys.sort();
if (isExport) { if (isExport) {

View File

@ -18,15 +18,15 @@ class Command extends BaseCommand {
async action() { async action() {
let items = []; let items = [];
let folders = await Folder.all(); const folders = await Folder.all();
for (let i = 0; i < folders.length; i++) { for (let i = 0; i < folders.length; i++) {
let folder = folders[i]; const folder = folders[i];
let notes = await Note.previews(folder.id); const notes = await Note.previews(folder.id);
items.push(folder); items.push(folder);
items = items.concat(notes); items = items.concat(notes);
} }
let tags = await Tag.all(); const tags = await Tag.all();
for (let i = 0; i < tags.length; i++) { for (let i = 0; i < tags.length; i++) {
tags[i].notes_ = await Tag.noteIds(tags[i].id); tags[i].notes_ = await Tag.noteIds(tags[i].id);
} }

View File

@ -138,7 +138,7 @@ class Command extends BaseCommand {
if (!targetPath) throw new Error('Please specify the sync target path.'); if (!targetPath) throw new Error('Please specify the sync target path.');
const dirPaths = function(targetPath) { const dirPaths = function(targetPath) {
let paths = []; const paths = [];
fs.readdirSync(targetPath).forEach(path => { fs.readdirSync(targetPath).forEach(path => {
paths.push(path); paths.push(path);
}); });
@ -151,10 +151,10 @@ class Command extends BaseCommand {
let encryptedResourceCount = 0; let encryptedResourceCount = 0;
let otherItemCount = 0; let otherItemCount = 0;
let encryptedPaths = []; const encryptedPaths = [];
let decryptedPaths = []; const decryptedPaths = [];
let paths = dirPaths(targetPath); const paths = dirPaths(targetPath);
for (let i = 0; i < paths.length; i++) { for (let i = 0; i < paths.length; i++) {
const path = paths[i]; const path = paths[i];
@ -164,7 +164,7 @@ class Command extends BaseCommand {
// this.stdout(fullPath); // this.stdout(fullPath);
if (path === '.resource') { if (path === '.resource') {
let resourcePaths = dirPaths(fullPath); const resourcePaths = dirPaths(fullPath);
for (let j = 0; j < resourcePaths.length; j++) { for (let j = 0; j < resourcePaths.length; j++) {
const resourcePath = resourcePaths[j]; const resourcePath = resourcePaths[j];
resourceCount++; resourceCount++;

View File

@ -35,7 +35,7 @@ class Command extends BaseCommand {
// Load note or create it if it doesn't exist // Load note or create it if it doesn't exist
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
let title = args['note']; const title = args['note'];
if (!app().currentFolder()) throw new Error(_('No active notebook.')); if (!app().currentFolder()) throw new Error(_('No active notebook.'));
let note = await app().loadItem(BaseModel.TYPE_NOTE, title); let note = await app().loadItem(BaseModel.TYPE_NOTE, title);
@ -91,7 +91,7 @@ class Command extends BaseCommand {
const updatedContent = await fs.readFile(tempFilePath, 'utf8'); const updatedContent = await fs.readFile(tempFilePath, 'utf8');
if (updatedContent !== originalContent) { if (updatedContent !== originalContent) {
let updatedNote = await Note.unserializeForEdit(updatedContent); const updatedNote = await Note.unserializeForEdit(updatedContent);
updatedNote.id = note.id; updatedNote.id = note.id;
await Note.save(updatedNote); await Note.save(updatedNote);
this.stdout(_('Note has been saved.')); this.stdout(_('Note has been saved.'));

View File

@ -24,7 +24,7 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let exportOptions = {}; const exportOptions = {};
exportOptions.path = args.path; exportOptions.path = args.path;
exportOptions.format = args.options.format ? args.options.format : 'jex'; exportOptions.format = args.options.format ? args.options.format : 'jex';

View File

@ -14,9 +14,9 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let title = args['note']; const title = args['note'];
let item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() }); const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
if (!item) throw new Error(_('Cannot find "%s".', title)); if (!item) throw new Error(_('Cannot find "%s".', title));
const url = Note.geolocationUrl(item); const url = Note.geolocationUrl(item);
this.stdout(url); this.stdout(url);

View File

@ -15,8 +15,8 @@ class Command extends BaseCommand {
allCommands() { allCommands() {
const commands = app().commands(app().uiType()); const commands = app().commands(app().uiType());
let output = []; const output = [];
for (let n in commands) { for (const n in commands) {
if (!commands.hasOwnProperty(n)) continue; if (!commands.hasOwnProperty(n)) continue;
const command = commands[n]; const command = commands[n];
if (command.hidden()) continue; if (command.hidden()) continue;
@ -48,7 +48,7 @@ class Command extends BaseCommand {
.gui() .gui()
.keymap(); .keymap();
let rows = []; const rows = [];
for (let i = 0; i < keymap.length; i++) { for (let i = 0; i < keymap.length; i++) {
const item = keymap[i]; const item = keymap[i];

View File

@ -25,7 +25,7 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook); const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook);
if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook)); if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook));
@ -39,7 +39,7 @@ class Command extends BaseCommand {
// onProgress/onError supported by Enex import only // onProgress/onError supported by Enex import only
importOptions.onProgress = progressState => { importOptions.onProgress = progressState => {
let line = []; const line = [];
line.push(_('Found: %d.', progressState.loaded)); line.push(_('Found: %d.', progressState.loaded));
line.push(_('Created: %d.', progressState.created)); line.push(_('Created: %d.', progressState.created));
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated)); if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
@ -51,7 +51,7 @@ class Command extends BaseCommand {
}; };
importOptions.onError = error => { importOptions.onError = error => {
let s = error.trace ? error.trace : error.toString(); const s = error.trace ? error.trace : error.toString();
this.stdout(s); this.stdout(s);
}; };

View File

@ -34,11 +34,11 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let pattern = args['note-pattern']; const pattern = args['note-pattern'];
let items = []; let items = [];
let options = args.options; const options = args.options;
let queryOptions = {}; const queryOptions = {};
if (options.limit) queryOptions.limit = options.limit; if (options.limit) queryOptions.limit = options.limit;
if (options.sort) { if (options.sort) {
queryOptions.orderBy = options.sort; queryOptions.orderBy = options.sort;
@ -70,19 +70,19 @@ class Command extends BaseCommand {
} else { } else {
let hasTodos = false; let hasTodos = false;
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
let item = items[i]; const item = items[i];
if (item.is_todo) { if (item.is_todo) {
hasTodos = true; hasTodos = true;
break; break;
} }
} }
let seenTitles = []; const seenTitles = [];
let rows = []; const rows = [];
let shortIdShown = false; let shortIdShown = false;
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
let item = items[i]; const item = items[i];
let row = []; const row = [];
if (options.long) { if (options.long) {
row.push(BaseModel.shortId(item.id)); row.push(BaseModel.shortId(item.id));

View File

@ -13,7 +13,7 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let folder = await Folder.save({ title: args['new-notebook'] }, { userSideValidation: true }); const folder = await Folder.save({ title: args['new-notebook'] }, { userSideValidation: true });
app().switchCurrentFolder(folder); app().switchCurrentFolder(folder);
} }
} }

View File

@ -26,7 +26,7 @@ class Command extends BaseCommand {
const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'), { booleanAnswerDefault: 'n' }); const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'), { booleanAnswerDefault: 'n' });
if (!ok) return; if (!ok) return;
let ids = notes.map(n => n.id); const ids = notes.map(n => n.id);
await Note.batchDelete(ids); await Note.batchDelete(ids);
} }
} }

View File

@ -18,8 +18,8 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let pattern = args['pattern']; const pattern = args['pattern'];
let folderTitle = args['notebook']; const folderTitle = args['notebook'];
let folder = null; let folder = null;
if (folderTitle) { if (folderTitle) {

View File

@ -23,18 +23,18 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let title = args['note']; const title = args['note'];
let propName = args['name']; const propName = args['name'];
let propValue = args['value']; let propValue = args['value'];
if (!propValue) propValue = ''; if (!propValue) propValue = '';
let notes = await app().loadItems(BaseModel.TYPE_NOTE, title); const notes = await app().loadItems(BaseModel.TYPE_NOTE, title);
if (!notes.length) throw new Error(_('Cannot find "%s".', title)); if (!notes.length) throw new Error(_('Cannot find "%s".', title));
for (let i = 0; i < notes.length; i++) { for (let i = 0; i < notes.length; i++) {
this.encryptionCheck(notes[i]); this.encryptionCheck(notes[i]);
let newNote = { const newNote = {
id: notes[i].id, id: notes[i].id,
type_: notes[i].type_, type_: notes[i].type_,
}; };

View File

@ -14,20 +14,20 @@ class Command extends BaseCommand {
} }
async action() { async action() {
let service = new ReportService(); const service = new ReportService();
let report = await service.status(Setting.value('sync.target')); const report = await service.status(Setting.value('sync.target'));
for (let i = 0; i < report.length; i++) { for (let i = 0; i < report.length; i++) {
let section = report[i]; const section = report[i];
if (i > 0) this.stdout(''); if (i > 0) this.stdout('');
this.stdout(`# ${section.title}`); this.stdout(`# ${section.title}`);
this.stdout(''); this.stdout('');
for (let n in section.body) { for (const n in section.body) {
if (!section.body.hasOwnProperty(n)) continue; if (!section.body.hasOwnProperty(n)) continue;
let line = section.body[n]; const line = section.body[n];
this.stdout(line); this.stdout(line);
} }
} }

View File

@ -161,9 +161,9 @@ class Command extends BaseCommand {
const sync = await syncTarget.synchronizer(); const sync = await syncTarget.synchronizer();
let options = { const options = {
onProgress: report => { onProgress: report => {
let lines = Synchronizer.reportToLines(report); const lines = Synchronizer.reportToLines(report);
if (lines.length) cliUtils.redraw(lines.join(' ')); if (lines.length) cliUtils.redraw(lines.join(' '));
}, },
onMessage: msg => { onMessage: msg => {
@ -185,7 +185,7 @@ class Command extends BaseCommand {
options.context = context; options.context = context;
try { try {
let newContext = await sync.start(options); const newContext = await sync.start(options);
Setting.setValue(contextKey, JSON.stringify(newContext)); Setting.setValue(contextKey, JSON.stringify(newContext));
} catch (error) { } catch (error) {
if (error.code == 'alreadyStarted') { if (error.code == 'alreadyStarted') {

View File

@ -20,7 +20,7 @@ class Command extends BaseCommand {
async action(args) { async action(args) {
let tag = null; let tag = null;
let options = args.options; const options = args.options;
if (args.tag) tag = await app().loadItem(BaseModel.TYPE_TAG, args.tag); if (args.tag) tag = await app().loadItem(BaseModel.TYPE_TAG, args.tag);
let notes = []; let notes = [];
@ -46,7 +46,7 @@ class Command extends BaseCommand {
} }
} else if (command == 'list') { } else if (command == 'list') {
if (tag) { if (tag) {
let notes = await Tag.notes(tag.id); const notes = await Tag.notes(tag.id);
notes.map(note => { notes.map(note => {
let line = ''; let line = '';
if (options.long) { if (options.long) {
@ -70,7 +70,7 @@ class Command extends BaseCommand {
this.stdout(line); this.stdout(line);
}); });
} else { } else {
let tags = await Tag.all(); const tags = await Tag.all();
tags.map(tag => { tags.map(tag => {
this.stdout(tag.title); this.stdout(tag.title);
}); });

View File

@ -17,7 +17,7 @@ class Command extends BaseCommand {
} }
async action(args) { async action(args) {
let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']); const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']);
if (!folder) throw new Error(_('Cannot find "%s".', args['notebook'])); if (!folder) throw new Error(_('Cannot find "%s".', args['notebook']));
app().switchCurrentFolder(folder); app().switchCurrentFolder(folder);
} }

View File

@ -12,7 +12,7 @@ const fs = require('fs-extra');
const baseDir = `${dirname(__dirname)}/tests/fuzzing`; const baseDir = `${dirname(__dirname)}/tests/fuzzing`;
const syncDir = `${baseDir}/sync`; const syncDir = `${baseDir}/sync`;
const joplinAppPath = `${__dirname}/main.js`; const joplinAppPath = `${__dirname}/main.js`;
let syncDurations = []; const syncDurations = [];
const fsDriver = new FsDriverNode(); const fsDriver = new FsDriverNode();
Logger.fsDriver_ = fsDriver; Logger.fsDriver_ = fsDriver;
@ -34,10 +34,10 @@ function createClient(id) {
} }
async function createClients() { async function createClients() {
let output = []; const output = [];
let promises = []; const promises = [];
for (let clientId = 0; clientId < 2; clientId++) { for (let clientId = 0; clientId < 2; clientId++) {
let client = createClient(clientId); const client = createClient(clientId);
promises.push(fs.remove(client.profileDir)); promises.push(fs.remove(client.profileDir));
promises.push( promises.push(
execCommand(client, 'config sync.target 2').then(() => { execCommand(client, 'config sync.target 2').then(() => {
@ -2064,8 +2064,8 @@ function randomWord() {
} }
function execCommand(client, command, options = {}) { function execCommand(client, command, options = {}) {
let exePath = `node ${joplinAppPath}`; const exePath = `node ${joplinAppPath}`;
let cmd = `${exePath} --update-geolocation-disabled --env dev --log-level debug --profile ${client.profileDir} ${command}`; const cmd = `${exePath} --update-geolocation-disabled --env dev --log-level debug --profile ${client.profileDir} ${command}`;
logger.info(`${client.id}: ${command}`); logger.info(`${client.id}: ${command}`);
if (options.killAfter) { if (options.killAfter) {
@ -2073,7 +2073,7 @@ function execCommand(client, command, options = {}) {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let childProcess = exec(cmd, (error, stdout, stderr) => { const childProcess = exec(cmd, (error, stdout, stderr) => {
if (error) { if (error) {
if (error.signal == 'SIGTERM') { if (error.signal == 'SIGTERM') {
resolve('Process was killed'); resolve('Process was killed');
@ -2096,7 +2096,7 @@ function execCommand(client, command, options = {}) {
} }
async function clientItems(client) { async function clientItems(client) {
let itemsJson = await execCommand(client, 'dump'); const itemsJson = await execCommand(client, 'dump');
try { try {
return JSON.parse(itemsJson); return JSON.parse(itemsJson);
} catch (error) { } catch (error) {
@ -2105,7 +2105,7 @@ async function clientItems(client) {
} }
function randomTag(items) { function randomTag(items) {
let tags = []; const tags = [];
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (items[i].type_ != 5) continue; if (items[i].type_ != 5) continue;
tags.push(items[i]); tags.push(items[i]);
@ -2115,7 +2115,7 @@ function randomTag(items) {
} }
function randomNote(items) { function randomNote(items) {
let notes = []; const notes = [];
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (items[i].type_ != 1) continue; if (items[i].type_ != 1) continue;
notes.push(items[i]); notes.push(items[i]);
@ -2125,14 +2125,14 @@ function randomNote(items) {
} }
async function execRandomCommand(client) { async function execRandomCommand(client) {
let possibleCommands = [ const possibleCommands = [
['mkbook {word}', 40], // CREATE FOLDER ['mkbook {word}', 40], // CREATE FOLDER
['mknote {word}', 70], // CREATE NOTE ['mknote {word}', 70], // CREATE NOTE
[ [
async () => { async () => {
// DELETE RANDOM ITEM // DELETE RANDOM ITEM
let items = await clientItems(client); const items = await clientItems(client);
let item = randomElement(items); const item = randomElement(items);
if (!item) return; if (!item) return;
if (item.type_ == 1) { if (item.type_ == 1) {
@ -2150,8 +2150,8 @@ async function execRandomCommand(client) {
[ [
async () => { async () => {
// SYNC // SYNC
let avgSyncDuration = averageSyncDuration(); const avgSyncDuration = averageSyncDuration();
let options = {}; const options = {};
if (!isNaN(avgSyncDuration)) { if (!isNaN(avgSyncDuration)) {
if (Math.random() >= 0.5) { if (Math.random() >= 0.5) {
options.killAfter = avgSyncDuration * Math.random(); options.killAfter = avgSyncDuration * Math.random();
@ -2164,8 +2164,8 @@ async function execRandomCommand(client) {
[ [
async () => { async () => {
// UPDATE RANDOM ITEM // UPDATE RANDOM ITEM
let items = await clientItems(client); const items = await clientItems(client);
let item = randomNote(items); const item = randomNote(items);
if (!item) return; if (!item) return;
return execCommand(client, `set ${item.id} title "${randomWord()}"`); return execCommand(client, `set ${item.id} title "${randomWord()}"`);
@ -2175,12 +2175,12 @@ async function execRandomCommand(client) {
[ [
async () => { async () => {
// ADD TAG // ADD TAG
let items = await clientItems(client); const items = await clientItems(client);
let note = randomNote(items); const note = randomNote(items);
if (!note) return; if (!note) return;
let tag = randomTag(items); const tag = randomTag(items);
let tagTitle = !tag || Math.random() >= 0.9 ? `tag-${randomWord()}` : tag.title; const tagTitle = !tag || Math.random() >= 0.9 ? `tag-${randomWord()}` : tag.title;
return execCommand(client, `tag add ${tagTitle} ${note.id}`); return execCommand(client, `tag add ${tagTitle} ${note.id}`);
}, },
@ -2191,7 +2191,7 @@ async function execRandomCommand(client) {
let cmd = null; let cmd = null;
while (true) { while (true) {
cmd = randomElement(possibleCommands); cmd = randomElement(possibleCommands);
let r = 1 + Math.floor(Math.random() * 100); const r = 1 + Math.floor(Math.random() * 100);
if (r <= cmd[1]) break; if (r <= cmd[1]) break;
} }
@ -2210,7 +2210,7 @@ function averageSyncDuration() {
} }
function randomNextCheckTime() { function randomNextCheckTime() {
let output = time.unixMs() + 1000 + Math.random() * 1000 * 120; const output = time.unixMs() + 1000 + Math.random() * 1000 * 120;
logger.info(`Next sync check: ${time.unixMsToIso(output)} (${Math.round((output - time.unixMs()) / 1000)} sec.)`); logger.info(`Next sync check: ${time.unixMsToIso(output)} (${Math.round((output - time.unixMs()) / 1000)} sec.)`);
return output; return output;
} }
@ -2223,11 +2223,11 @@ function findItem(items, itemId) {
} }
function compareItems(item1, item2) { function compareItems(item1, item2) {
let output = []; const output = [];
for (let n in item1) { for (const n in item1) {
if (!item1.hasOwnProperty(n)) continue; if (!item1.hasOwnProperty(n)) continue;
let p1 = item1[n]; const p1 = item1[n];
let p2 = item2[n]; const p2 = item2[n];
if (n == 'notes_') { if (n == 'notes_') {
p1.sort(); p1.sort();
@ -2243,13 +2243,13 @@ function compareItems(item1, item2) {
} }
function findMissingItems_(items1, items2) { function findMissingItems_(items1, items2) {
let output = []; const output = [];
for (let i = 0; i < items1.length; i++) { for (let i = 0; i < items1.length; i++) {
let item1 = items1[i]; const item1 = items1[i];
let found = false; let found = false;
for (let j = 0; j < items2.length; j++) { for (let j = 0; j < items2.length; j++) {
let item2 = items2[j]; const item2 = items2[j];
if (item1.id == item2.id) { if (item1.id == item2.id) {
found = true; found = true;
break; break;
@ -2269,33 +2269,33 @@ function findMissingItems(items1, items2) {
} }
async function compareClientItems(clientItems) { async function compareClientItems(clientItems) {
let itemCounts = []; const itemCounts = [];
for (let i = 0; i < clientItems.length; i++) { for (let i = 0; i < clientItems.length; i++) {
let items = clientItems[i]; const items = clientItems[i];
itemCounts.push(items.length); itemCounts.push(items.length);
} }
logger.info(`Item count: ${itemCounts.join(', ')}`); logger.info(`Item count: ${itemCounts.join(', ')}`);
let missingItems = findMissingItems(clientItems[0], clientItems[1]); const missingItems = findMissingItems(clientItems[0], clientItems[1]);
if (missingItems[0].length || missingItems[1].length) { if (missingItems[0].length || missingItems[1].length) {
logger.error('Items are different'); logger.error('Items are different');
logger.error(missingItems); logger.error(missingItems);
process.exit(1); process.exit(1);
} }
let differences = []; const differences = [];
let items = clientItems[0]; const items = clientItems[0];
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
let item1 = items[i]; const item1 = items[i];
for (let clientId = 1; clientId < clientItems.length; clientId++) { for (let clientId = 1; clientId < clientItems.length; clientId++) {
let item2 = findItem(clientItems[clientId], item1.id); const item2 = findItem(clientItems[clientId], item1.id);
if (!item2) { if (!item2) {
logger.error(`Item not found on client ${clientId}:`); logger.error(`Item not found on client ${clientId}:`);
logger.error(item1); logger.error(item1);
process.exit(1); process.exit(1);
} }
let diff = compareItems(item1, item2); const diff = compareItems(item1, item2);
if (diff.length) { if (diff.length) {
differences.push({ differences.push({
item1: JSON.stringify(item1), item1: JSON.stringify(item1),
@ -2315,7 +2315,7 @@ async function compareClientItems(clientItems) {
async function main() { async function main() {
await fs.remove(syncDir); await fs.remove(syncDir);
let clients = await createClients(); const clients = await createClients();
let clientId = 0; let clientId = 0;
for (let i = 0; i < clients.length; i++) { for (let i = 0; i < clients.length; i++) {
@ -2348,7 +2348,7 @@ async function main() {
if (state == 'syncCheck') { if (state == 'syncCheck') {
state = 'waitForSyncCheck'; state = 'waitForSyncCheck';
let clientItems = []; const clientItems = [];
// Up to 3 sync operations must be performed by each clients in order for them // Up to 3 sync operations must be performed by each clients in order for them
// to be perfectly in sync - in order for each items to send their changes // to be perfectly in sync - in order for each items to send their changes
// and get those from the other clients, and to also get changes that are // and get those from the other clients, and to also get changes that are
@ -2356,12 +2356,12 @@ async function main() {
// with another one). // with another one).
for (let loopCount = 0; loopCount < 3; loopCount++) { for (let loopCount = 0; loopCount < 3; loopCount++) {
for (let i = 0; i < clients.length; i++) { for (let i = 0; i < clients.length; i++) {
let beforeTime = time.unixMs(); const beforeTime = time.unixMs();
await execCommand(clients[i], 'sync'); await execCommand(clients[i], 'sync');
syncDurations.push(time.unixMs() - beforeTime); syncDurations.push(time.unixMs() - beforeTime);
if (syncDurations.length > 20) syncDurations.splice(0, 1); if (syncDurations.length > 20) syncDurations.splice(0, 1);
if (loopCount === 2) { if (loopCount === 2) {
let dump = await execCommand(clients[i], 'dump'); const dump = await execCommand(clients[i], 'dump');
clientItems[i] = JSON.parse(dump); clientItems[i] = JSON.parse(dump);
} }
} }

View File

@ -20,7 +20,7 @@ class FolderListWidget extends ListWidget {
this.trimItemTitle = false; this.trimItemTitle = false;
this.itemRenderer = item => { this.itemRenderer = item => {
let output = []; const output = [];
if (item === '-') { if (item === '-') {
output.push('-'.repeat(this.innerWidth)); output.push('-'.repeat(this.innerWidth));
} else if (item.type_ === Folder.modelType()) { } else if (item.type_ === Folder.modelType()) {
@ -121,7 +121,7 @@ class FolderListWidget extends ListWidget {
folderHasChildren_(folders, folderId) { folderHasChildren_(folders, folderId) {
for (let i = 0; i < folders.length; i++) { for (let i = 0; i < folders.length; i++) {
let folder = folders[i]; const folder = folders[i];
if (folder.parent_id === folderId) return true; if (folder.parent_id === folderId) return true;
} }
return false; return false;

View File

@ -106,7 +106,7 @@ class StatusBarWidget extends BaseWidget {
const isSecurePrompt = !!this.promptState_.secure; const isSecurePrompt = !!this.promptState_.secure;
let options = { const options = {
cancelable: true, cancelable: true,
history: this.history, history: this.history,
default: this.promptState_.initialText, default: this.promptState_.initialText,

View File

@ -6,11 +6,11 @@ const MAX_WIDTH = 78;
const INDENT = ' '; const INDENT = ' ';
function renderTwoColumnData(options, baseIndent, width) { function renderTwoColumnData(options, baseIndent, width) {
let output = []; const output = [];
const optionColWidth = getOptionColWidth(options); const optionColWidth = getOptionColWidth(options);
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
let option = options[i]; const option = options[i];
const flag = option[0]; const flag = option[0];
const indent = baseIndent + INDENT + ' '.repeat(optionColWidth + 2); const indent = baseIndent + INDENT + ' '.repeat(optionColWidth + 2);
@ -28,7 +28,7 @@ function renderCommandHelp(cmd, width = null) {
const baseIndent = ''; const baseIndent = '';
let output = []; const output = [];
output.push(baseIndent + cmd.usage()); output.push(baseIndent + cmd.usage());
output.push(''); output.push('');
output.push(wrap(cmd.description(), baseIndent + INDENT, width)); output.push(wrap(cmd.description(), baseIndent + INDENT, width));
@ -42,7 +42,7 @@ function renderCommandHelp(cmd, width = null) {
if (cmd.name() === 'config') { if (cmd.name() === 'config') {
const renderMetadata = md => { const renderMetadata = md => {
let desc = []; const desc = [];
if (md.label) { if (md.label) {
let label = md.label(); let label = md.label();
@ -77,7 +77,7 @@ function renderCommandHelp(cmd, width = null) {
output.push(_('Possible keys/values:')); output.push(_('Possible keys/values:'));
output.push(''); output.push('');
let keysValues = []; const keysValues = [];
const keys = Setting.keys(true, 'cli'); const keys = Setting.keys(true, 'cli');
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
if (keysValues.length) keysValues.push(['', '']); if (keysValues.length) keysValues.push(['', '']);

View File

@ -54,7 +54,7 @@ shimInit();
const application = app(); const application = app();
if (process.platform === 'win32') { if (process.platform === 'win32') {
var rl = require('readline').createInterface({ const rl = require('readline').createInterface({
input: process.stdin, input: process.stdin,
output: process.stdout, output: process.stdout,
}); });

View File

@ -14,14 +14,14 @@ describe('InteropService_Importer_Md: importLocalImages', function() {
it('should import linked files and modify tags appropriately', async function() { it('should import linked files and modify tags appropriately', async function() {
const tagNonExistentFile = '![does not exist](does_not_exist.png)'; const tagNonExistentFile = '![does not exist](does_not_exist.png)';
const note = await importer.importFile(`${__dirname}/md_to_md/sample.md`, 'notebook'); const note = await importer.importFile(`${__dirname}/md_to_md/sample.md`, 'notebook');
let items = await Note.linkedItems(note.body); const items = await Note.linkedItems(note.body);
expect(items.length).toBe(2); expect(items.length).toBe(2);
const inexistentLinkUnchanged = note.body.includes(tagNonExistentFile); const inexistentLinkUnchanged = note.body.includes(tagNonExistentFile);
expect(inexistentLinkUnchanged).toBe(true); expect(inexistentLinkUnchanged).toBe(true);
}); });
it('should only create 1 resource for duplicate links, all tags should be updated', async function() { it('should only create 1 resource for duplicate links, all tags should be updated', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-duplicate-links.md`, 'notebook'); const note = await importer.importFile(`${__dirname}/md_to_md/sample-duplicate-links.md`, 'notebook');
let items = await Note.linkedItems(note.body); const items = await Note.linkedItems(note.body);
expect(items.length).toBe(1); expect(items.length).toBe(1);
const reg = new RegExp(items[0].id, 'g'); const reg = new RegExp(items[0].id, 'g');
const matched = note.body.match(reg); const matched = note.body.match(reg);
@ -29,12 +29,12 @@ describe('InteropService_Importer_Md: importLocalImages', function() {
}); });
it('should import linked files and modify tags appropriately when link is also in alt text', async function() { it('should import linked files and modify tags appropriately when link is also in alt text', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-link-in-alt-text.md`, 'notebook'); const note = await importer.importFile(`${__dirname}/md_to_md/sample-link-in-alt-text.md`, 'notebook');
let items = await Note.linkedItems(note.body); const items = await Note.linkedItems(note.body);
expect(items.length).toBe(1); expect(items.length).toBe(1);
}); });
it('should passthrough unchanged if no links present', async function() { it('should passthrough unchanged if no links present', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-no-links.md`, 'notebook'); const note = await importer.importFile(`${__dirname}/md_to_md/sample-no-links.md`, 'notebook');
let items = await Note.linkedItems(note.body); const items = await Note.linkedItems(note.body);
expect(items.length).toBe(0); expect(items.length).toBe(0);
expect(note.body).toContain('Unidentified vessel travelling at sub warp speed, bearing 235.7. Fluctuations in energy readings from it, Captain. All transporters off.'); expect(note.body).toContain('Unidentified vessel travelling at sub warp speed, bearing 235.7. Fluctuations in energy readings from it, Captain. All transporters off.');
}); });

View File

@ -44,19 +44,19 @@ describe('integration_ShowAllNotes', function() {
it('should show all notes', asyncTest(async () => { it('should show all notes', asyncTest(async () => {
// setup // setup
let folders = await createNTestFolders(3); const folders = await createNTestFolders(3);
Folder.moveToFolder(id(folders[2]), id(folders[1])); // subfolder Folder.moveToFolder(id(folders[2]), id(folders[1])); // subfolder
await time.msleep(100); await time.msleep(100);
let notes0 = await createNTestNotes(3, folders[0]); const notes0 = await createNTestNotes(3, folders[0]);
let notes1 = await createNTestNotes(3, folders[1]); const notes1 = await createNTestNotes(3, folders[1]);
let notes2 = await createNTestNotes(3, folders[2]); const notes2 = await createNTestNotes(3, folders[2]);
// TEST ACTION: View all-notes // TEST ACTION: View all-notes
testApp.dispatch({ type: 'SMART_FILTER_SELECT', id: ALL_NOTES_FILTER_ID }); testApp.dispatch({ type: 'SMART_FILTER_SELECT', id: ALL_NOTES_FILTER_ID });
await time.msleep(100); await time.msleep(100);
// check: all the notes are shown // check: all the notes are shown
let state = testApp.store().getState(); const state = testApp.store().getState();
expect(state.notesParentType).toEqual('SmartFilter'); expect(state.notesParentType).toEqual('SmartFilter');
expect(state.selectedSmartFilterId).toEqual(ALL_NOTES_FILTER_ID); expect(state.selectedSmartFilterId).toEqual(ALL_NOTES_FILTER_ID);
expect(sortedIds(state.notes)).toEqual(sortedIds(notes0.concat(notes1).concat(notes2))); expect(sortedIds(state.notes)).toEqual(sortedIds(notes0.concat(notes1).concat(notes2)));
@ -64,9 +64,9 @@ describe('integration_ShowAllNotes', function() {
it('should show retain note selection when going from a folder to all-notes', asyncTest(async () => { it('should show retain note selection when going from a folder to all-notes', asyncTest(async () => {
// setup // setup
let folders = await createNTestFolders(2); const folders = await createNTestFolders(2);
let notes0 = await createNTestNotes(3, folders[0]); const notes0 = await createNTestNotes(3, folders[0]);
let notes1 = await createNTestNotes(3, folders[1]); const notes1 = await createNTestNotes(3, folders[1]);
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[1]) }); testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[1]) });
await time.msleep(100); await time.msleep(100);
testApp.dispatch({ type: 'NOTE_SELECT', id: id(notes1[1]) }); testApp.dispatch({ type: 'NOTE_SELECT', id: id(notes1[1]) });

View File

@ -8,27 +8,27 @@ const Tag = require('lib/models/Tag.js');
const { time } = require('lib/time-utils.js'); const { time } = require('lib/time-utils.js');
async function createNTestFolders(n) { async function createNTestFolders(n) {
let folders = []; const folders = [];
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
let folder = await Folder.save({ title: 'folder' }); const folder = await Folder.save({ title: 'folder' });
folders.push(folder); folders.push(folder);
} }
return folders; return folders;
} }
async function createNTestNotes(n, folder) { async function createNTestNotes(n, folder) {
let notes = []; const notes = [];
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
let note = await Note.save({ title: 'note', parent_id: folder.id, is_conflict: 0 }); const note = await Note.save({ title: 'note', parent_id: folder.id, is_conflict: 0 });
notes.push(note); notes.push(note);
} }
return notes; return notes;
} }
async function createNTestTags(n) { async function createNTestTags(n) {
let tags = []; const tags = [];
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
let tag = await Tag.save({ title: 'tag' }); const tag = await Tag.save({ title: 'tag' });
tags.push(tag); tags.push(tag);
} }
return tags; return tags;
@ -58,9 +58,9 @@ describe('integration_TagList', function() {
// the tag list should be cleared if the next note has no tags // the tag list should be cleared if the next note has no tags
it('should clear tag list when a note is deleted', asyncTest(async () => { it('should clear tag list when a note is deleted', asyncTest(async () => {
// setup and select the note // setup and select the note
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let tags = await createNTestTags(3); const tags = await createNTestTags(3);
await Tag.addNote(tags[2].id, notes[2].id); await Tag.addNote(tags[2].id, notes[2].id);
@ -96,9 +96,9 @@ describe('integration_TagList', function() {
// the tag list should be updated if the next note has tags // the tag list should be updated if the next note has tags
it('should update tag list when a note is deleted', asyncTest(async () => { it('should update tag list when a note is deleted', asyncTest(async () => {
// set up and select the note // set up and select the note
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let tags = await createNTestTags(3); const tags = await createNTestTags(3);
await Tag.addNote(tags[1].id, notes[1].id); await Tag.addNote(tags[1].id, notes[1].id);
await Tag.addNote(tags[0].id, notes[0].id); await Tag.addNote(tags[0].id, notes[0].id);
@ -130,8 +130,8 @@ describe('integration_TagList', function() {
// check the tag list is updated // check the tag list is updated
state = testApp.store().getState(); state = testApp.store().getState();
let tagIds = state.selectedNoteTags.map(n => n.id).sort(); const tagIds = state.selectedNoteTags.map(n => n.id).sort();
let expectedTagIds = [tags[0].id, tags[2].id].sort(); const expectedTagIds = [tags[0].id, tags[2].id].sort();
expect(state.selectedNoteTags.length).toEqual(2); expect(state.selectedNoteTags.length).toEqual(2);
expect(tagIds).toEqual(expectedTagIds); expect(tagIds).toEqual(expectedTagIds);
})); }));

View File

@ -16,8 +16,8 @@ process.on('unhandledRejection', (reason, p) => {
}); });
async function allItems() { async function allItems() {
let folders = await Folder.all(); const folders = await Folder.all();
let notes = await Note.all(); const notes = await Note.all();
return folders.concat(notes); return folders.concat(notes);
} }
@ -32,27 +32,27 @@ describe('models_BaseItem', function() {
// This is to handle the case where a property is removed from a BaseItem table - in that case files in // This is to handle the case where a property is removed from a BaseItem table - in that case files in
// the sync target will still have the old property but we don't need it locally. // the sync target will still have the old property but we don't need it locally.
it('should ignore properties that are present in sync file but not in database when serialising', asyncTest(async () => { it('should ignore properties that are present in sync file but not in database when serialising', asyncTest(async () => {
let folder = await Folder.save({ title: 'folder1' }); const folder = await Folder.save({ title: 'folder1' });
let serialized = await Folder.serialize(folder); let serialized = await Folder.serialize(folder);
serialized += '\nignore_me: true'; serialized += '\nignore_me: true';
let unserialized = await Folder.unserialize(serialized); const unserialized = await Folder.unserialize(serialized);
expect('ignore_me' in unserialized).toBe(false); expect('ignore_me' in unserialized).toBe(false);
})); }));
it('should not modify title when unserializing', asyncTest(async () => { it('should not modify title when unserializing', asyncTest(async () => {
let folder1 = await Folder.save({ title: '' }); const folder1 = await Folder.save({ title: '' });
let folder2 = await Folder.save({ title: 'folder1' }); const folder2 = await Folder.save({ title: 'folder1' });
let serialized1 = await Folder.serialize(folder1); const serialized1 = await Folder.serialize(folder1);
let unserialized1 = await Folder.unserialize(serialized1); const unserialized1 = await Folder.unserialize(serialized1);
expect(unserialized1.title).toBe(folder1.title); expect(unserialized1.title).toBe(folder1.title);
let serialized2 = await Folder.serialize(folder2); const serialized2 = await Folder.serialize(folder2);
let unserialized2 = await Folder.unserialize(serialized2); const unserialized2 = await Folder.unserialize(serialized2);
expect(unserialized2.title).toBe(folder2.title); expect(unserialized2.title).toBe(folder2.title);
})); }));

View File

@ -14,8 +14,8 @@ process.on('unhandledRejection', (reason, p) => {
}); });
async function allItems() { async function allItems() {
let folders = await Folder.all(); const folders = await Folder.all();
let notes = await Note.all(); const notes = await Note.all();
return folders.concat(notes); return folders.concat(notes);
} }
@ -28,10 +28,10 @@ describe('models_Folder', function() {
}); });
it('should tell if a notebook can be nested under another one', asyncTest(async () => { it('should tell if a notebook can be nested under another one', asyncTest(async () => {
let f1 = await Folder.save({ title: 'folder1' }); const f1 = await Folder.save({ title: 'folder1' });
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id }); const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
let f4 = await Folder.save({ title: 'folder4' }); const f4 = await Folder.save({ title: 'folder4' });
expect(await Folder.canNestUnder(f1.id, f2.id)).toBe(false); expect(await Folder.canNestUnder(f1.id, f2.id)).toBe(false);
expect(await Folder.canNestUnder(f2.id, f2.id)).toBe(false); expect(await Folder.canNestUnder(f2.id, f2.id)).toBe(false);
@ -44,9 +44,9 @@ describe('models_Folder', function() {
})); }));
it('should recursively delete notes and sub-notebooks', asyncTest(async () => { it('should recursively delete notes and sub-notebooks', asyncTest(async () => {
let f1 = await Folder.save({ title: 'folder1' }); const f1 = await Folder.save({ title: 'folder1' });
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
let n1 = await Note.save({ title: 'note1', parent_id: f2.id }); const n1 = await Note.save({ title: 'note1', parent_id: f2.id });
await Folder.delete(f1.id); await Folder.delete(f1.id);
@ -57,10 +57,10 @@ describe('models_Folder', function() {
it('should sort by last modified, based on content', asyncTest(async () => { it('should sort by last modified, based on content', asyncTest(async () => {
let folders; let folders;
let f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1); const f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1);
let f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1); const f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1);
let f3 = await Folder.save({ title: 'folder3' }); await sleep(0.1); const f3 = await Folder.save({ title: 'folder3' }); await sleep(0.1);
let n1 = await Note.save({ title: 'note1', parent_id: f2.id }); const n1 = await Note.save({ title: 'note1', parent_id: f2.id });
folders = await Folder.orderByLastModified(await Folder.all(), 'desc'); folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
expect(folders.length).toBe(3); expect(folders.length).toBe(3);
@ -68,7 +68,7 @@ describe('models_Folder', function() {
expect(folders[1].id).toBe(f3.id); expect(folders[1].id).toBe(f3.id);
expect(folders[2].id).toBe(f1.id); expect(folders[2].id).toBe(f1.id);
let n2 = await Note.save({ title: 'note1', parent_id: f1.id }); const n2 = await Note.save({ title: 'note1', parent_id: f1.id });
folders = await Folder.orderByLastModified(await Folder.all(), 'desc'); folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
expect(folders[0].id).toBe(f1.id); expect(folders[0].id).toBe(f1.id);
@ -91,10 +91,10 @@ describe('models_Folder', function() {
it('should sort by last modified, based on content (sub-folders too)', asyncTest(async () => { it('should sort by last modified, based on content (sub-folders too)', asyncTest(async () => {
let folders; let folders;
let f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1); const f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1);
let f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1); const f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1);
let f3 = await Folder.save({ title: 'folder3', parent_id: f1.id }); await sleep(0.1); const f3 = await Folder.save({ title: 'folder3', parent_id: f1.id }); await sleep(0.1);
let n1 = await Note.save({ title: 'note1', parent_id: f3.id }); const n1 = await Note.save({ title: 'note1', parent_id: f3.id });
folders = await Folder.orderByLastModified(await Folder.all(), 'desc'); folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
expect(folders.length).toBe(3); expect(folders.length).toBe(3);
@ -102,7 +102,7 @@ describe('models_Folder', function() {
expect(folders[1].id).toBe(f3.id); expect(folders[1].id).toBe(f3.id);
expect(folders[2].id).toBe(f2.id); expect(folders[2].id).toBe(f2.id);
let n2 = await Note.save({ title: 'note2', parent_id: f2.id }); const n2 = await Note.save({ title: 'note2', parent_id: f2.id });
folders = await Folder.orderByLastModified(await Folder.all(), 'desc'); folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
expect(folders[0].id).toBe(f2.id); expect(folders[0].id).toBe(f2.id);
@ -116,8 +116,8 @@ describe('models_Folder', function() {
expect(folders[1].id).toBe(f3.id); expect(folders[1].id).toBe(f3.id);
expect(folders[2].id).toBe(f2.id); expect(folders[2].id).toBe(f2.id);
let f4 = await Folder.save({ title: 'folder4', parent_id: f1.id }); await sleep(0.1); const f4 = await Folder.save({ title: 'folder4', parent_id: f1.id }); await sleep(0.1);
let n3 = await Note.save({ title: 'note3', parent_id: f4.id }); const n3 = await Note.save({ title: 'note3', parent_id: f4.id });
folders = await Folder.orderByLastModified(await Folder.all(), 'desc'); folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
expect(folders.length).toBe(4); expect(folders.length).toBe(4);
@ -128,14 +128,14 @@ describe('models_Folder', function() {
})); }));
it('should add node counts', asyncTest(async () => { it('should add node counts', asyncTest(async () => {
let f1 = await Folder.save({ title: 'folder1' }); const f1 = await Folder.save({ title: 'folder1' });
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id }); const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
let f4 = await Folder.save({ title: 'folder4' }); const f4 = await Folder.save({ title: 'folder4' });
let n1 = await Note.save({ title: 'note1', parent_id: f3.id }); const n1 = await Note.save({ title: 'note1', parent_id: f3.id });
let n2 = await Note.save({ title: 'note1', parent_id: f3.id }); const n2 = await Note.save({ title: 'note1', parent_id: f3.id });
let n3 = await Note.save({ title: 'note1', parent_id: f1.id }); const n3 = await Note.save({ title: 'note1', parent_id: f1.id });
const folders = await Folder.all(); const folders = await Folder.all();
await Folder.addNoteCounts(folders); await Folder.addNoteCounts(folders);
@ -152,17 +152,17 @@ describe('models_Folder', function() {
it('should not count completed to-dos', asyncTest(async () => { it('should not count completed to-dos', asyncTest(async () => {
let f1 = await Folder.save({ title: 'folder1' }); const f1 = await Folder.save({ title: 'folder1' });
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id }); const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
let f4 = await Folder.save({ title: 'folder4' }); const f4 = await Folder.save({ title: 'folder4' });
let n1 = await Note.save({ title: 'note1', parent_id: f3.id }); const n1 = await Note.save({ title: 'note1', parent_id: f3.id });
let n2 = await Note.save({ title: 'note2', parent_id: f3.id }); const n2 = await Note.save({ title: 'note2', parent_id: f3.id });
let n3 = await Note.save({ title: 'note3', parent_id: f1.id }); const n3 = await Note.save({ title: 'note3', parent_id: f1.id });
let n4 = await Note.save({ title: 'note4', parent_id: f3.id, is_todo: true, todo_completed: 0 }); const n4 = await Note.save({ title: 'note4', parent_id: f3.id, is_todo: true, todo_completed: 0 });
let n5 = await Note.save({ title: 'note5', parent_id: f3.id, is_todo: true, todo_completed: 999 }); const n5 = await Note.save({ title: 'note5', parent_id: f3.id, is_todo: true, todo_completed: 999 });
let n6 = await Note.save({ title: 'note6', parent_id: f3.id, is_todo: true, todo_completed: 999 }); const n6 = await Note.save({ title: 'note6', parent_id: f3.id, is_todo: true, todo_completed: 999 });
const folders = await Folder.all(); const folders = await Folder.all();
await Folder.addNoteCounts(folders, false); await Folder.addNoteCounts(folders, false);
@ -179,9 +179,9 @@ describe('models_Folder', function() {
it('should recursively find folder path', asyncTest(async () => { it('should recursively find folder path', asyncTest(async () => {
let f1 = await Folder.save({ title: 'folder1' }); const f1 = await Folder.save({ title: 'folder1' });
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id }); const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
const folders = await Folder.all(); const folders = await Folder.all();
const folderPath = await Folder.folderPath(folders, f3.id); const folderPath = await Folder.folderPath(folders, f3.id);

View File

@ -23,8 +23,8 @@ describe('models_Note', function() {
}); });
it('should find resource and note IDs', asyncTest(async () => { it('should find resource and note IDs', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id }); let note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id });
let items = await Note.linkedItems(note2.body); let items = await Note.linkedItems(note2.body);
@ -69,7 +69,7 @@ describe('models_Note', function() {
})); }));
it('should change the type of notes', asyncTest(async () => { it('should change the type of notes', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
@ -90,7 +90,7 @@ describe('models_Note', function() {
})); }));
it('should serialize and unserialize without modifying data', asyncTest(async () => { it('should serialize and unserialize without modifying data', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
const testCases = [ const testCases = [
[{ title: '', body: 'Body and no title\nSecond line\nThird Line', parent_id: folder1.id }, [{ title: '', body: 'Body and no title\nSecond line\nThird Line', parent_id: folder1.id },
'', 'Body and no title\nSecond line\nThird Line'], '', 'Body and no title\nSecond line\nThird Line'],
@ -107,9 +107,9 @@ describe('models_Note', function() {
const expectedTitle = t[1]; const expectedTitle = t[1];
const expectedBody = t[1]; const expectedBody = t[1];
let note1 = await Note.save(input); const note1 = await Note.save(input);
let serialized = await Note.serialize(note1); const serialized = await Note.serialize(note1);
let unserialized = await Note.unserialize(serialized); const unserialized = await Note.unserialize(serialized);
expect(unserialized.title).toBe(input.title); expect(unserialized.title).toBe(input.title);
expect(unserialized.body).toBe(input.body); expect(unserialized.body).toBe(input.body);
@ -117,10 +117,10 @@ describe('models_Note', function() {
})); }));
it('should reset fields for a duplicate', asyncTest(async () => { it('should reset fields for a duplicate', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'note', parent_id: folder1.id });
let duplicatedNote = await Note.duplicate(note1.id); const duplicatedNote = await Note.duplicate(note1.id);
expect(duplicatedNote !== note1).toBe(true); expect(duplicatedNote !== note1).toBe(true);
expect(duplicatedNote.created_time !== note1.created_time).toBe(true); expect(duplicatedNote.created_time !== note1.created_time).toBe(true);

View File

@ -27,30 +27,30 @@ describe('models_Resource', function() {
}); });
it('should have a "done" fetch_status when created locally', asyncTest(async () => { it('should have a "done" fetch_status when created locally', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, testImagePath); await shim.attachFileToNote(note1, testImagePath);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
let ls = await Resource.localState(resource1); const ls = await Resource.localState(resource1);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE); expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
})); }));
it('should have a default local state', asyncTest(async () => { it('should have a default local state', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, testImagePath); await shim.attachFileToNote(note1, testImagePath);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
let ls = await Resource.localState(resource1); const ls = await Resource.localState(resource1);
expect(!ls.id).toBe(true); expect(!ls.id).toBe(true);
expect(ls.resource_id).toBe(resource1.id); expect(ls.resource_id).toBe(resource1.id);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE); expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
})); }));
it('should save and delete local state', asyncTest(async () => { it('should save and delete local state', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, testImagePath); await shim.attachFileToNote(note1, testImagePath);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
await Resource.setLocalState(resource1, { fetch_status: Resource.FETCH_STATUS_IDLE }); await Resource.setLocalState(resource1, { fetch_status: Resource.FETCH_STATUS_IDLE });
let ls = await Resource.localState(resource1); let ls = await Resource.localState(resource1);
@ -63,13 +63,13 @@ describe('models_Resource', function() {
})); }));
it('should resize the resource if the image is below the required dimensions', asyncTest(async () => { it('should resize the resource if the image is below the required dimensions', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
const previousMax = Resource.IMAGE_MAX_DIMENSION; const previousMax = Resource.IMAGE_MAX_DIMENSION;
Resource.IMAGE_MAX_DIMENSION = 5; Resource.IMAGE_MAX_DIMENSION = 5;
await shim.attachFileToNote(note1, testImagePath); await shim.attachFileToNote(note1, testImagePath);
Resource.IMAGE_MAX_DIMENSION = previousMax; Resource.IMAGE_MAX_DIMENSION = previousMax;
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
const originalStat = await shim.fsDriver().stat(testImagePath); const originalStat = await shim.fsDriver().stat(testImagePath);
const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1)); const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1));
@ -78,10 +78,10 @@ describe('models_Resource', function() {
})); }));
it('should not resize the resource if the image is below the required dimensions', asyncTest(async () => { it('should not resize the resource if the image is below the required dimensions', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, testImagePath); await shim.attachFileToNote(note1, testImagePath);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
const originalStat = await shim.fsDriver().stat(testImagePath); const originalStat = await shim.fsDriver().stat(testImagePath);
const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1)); const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1));

View File

@ -24,8 +24,8 @@ describe('models_Tag', function() {
}); });
it('should add tags by title', asyncTest(async () => { it('should add tags by title', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']); await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']);
@ -34,8 +34,8 @@ describe('models_Tag', function() {
})); }));
it('should not allow renaming tag to existing tag names', asyncTest(async () => { it('should not allow renaming tag to existing tag names', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']); await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']);
@ -46,8 +46,8 @@ describe('models_Tag', function() {
})); }));
it('should not return tags without notes', asyncTest(async () => { it('should not return tags without notes', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await Tag.setNoteTagsByTitles(note1.id, ['un']); await Tag.setNoteTagsByTitles(note1.id, ['un']);
let tags = await Tag.allWithNotes(); let tags = await Tag.allWithNotes();
@ -60,9 +60,9 @@ describe('models_Tag', function() {
})); }));
it('should return tags with note counts', asyncTest(async () => { it('should return tags with note counts', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id }); const note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id });
await Tag.setNoteTagsByTitles(note1.id, ['un']); await Tag.setNoteTagsByTitles(note1.id, ['un']);
await Tag.setNoteTagsByTitles(note2.id, ['un']); await Tag.setNoteTagsByTitles(note2.id, ['un']);
@ -83,10 +83,10 @@ describe('models_Tag', function() {
})); }));
it('should load individual tags with note count', asyncTest(async () => { it('should load individual tags with note count', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id }); const note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id });
let tag = await Tag.save({ title: 'mytag' }); const tag = await Tag.save({ title: 'mytag' });
await Tag.addNote(tag.id, note1.id); await Tag.addNote(tag.id, note1.id);
let tagWithCount = await Tag.loadWithCount(tag.id); let tagWithCount = await Tag.loadWithCount(tag.id);
@ -98,16 +98,16 @@ describe('models_Tag', function() {
})); }));
it('should get common tags for set of notes', asyncTest(async () => { it('should get common tags for set of notes', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let taga = await Tag.save({ title: 'mytaga' }); const taga = await Tag.save({ title: 'mytaga' });
let tagb = await Tag.save({ title: 'mytagb' }); const tagb = await Tag.save({ title: 'mytagb' });
let tagc = await Tag.save({ title: 'mytagc' }); const tagc = await Tag.save({ title: 'mytagc' });
let tagd = await Tag.save({ title: 'mytagd' }); const tagd = await Tag.save({ title: 'mytagd' });
let note0 = await Note.save({ title: 'ma note 0', parent_id: folder1.id }); const note0 = await Note.save({ title: 'ma note 0', parent_id: folder1.id });
let note1 = await Note.save({ title: 'ma note 1', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note 1', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma note 2', parent_id: folder1.id }); const note2 = await Note.save({ title: 'ma note 2', parent_id: folder1.id });
let note3 = await Note.save({ title: 'ma note 3', parent_id: folder1.id }); const note3 = await Note.save({ title: 'ma note 3', parent_id: folder1.id });
await Tag.addNote(taga.id, note1.id); await Tag.addNote(taga.id, note1.id);

View File

@ -7,7 +7,7 @@ const Note = require('lib/models/Note.js');
const Tag = require('lib/models/Tag.js'); const Tag = require('lib/models/Tag.js');
const { reducer, defaultState, stateUtils } = require('lib/reducer.js'); const { reducer, defaultState, stateUtils } = require('lib/reducer.js');
function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, tags=null, selectedTagIndex=null) { function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, tags = null, selectedTagIndex = null) {
let state = defaultState; let state = defaultState;
if (selectedFolderIndex != null) { if (selectedFolderIndex != null) {
@ -20,7 +20,7 @@ function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes,
state = reducer(state, { type: 'NOTE_UPDATE_ALL', notes: notes, noteSource: 'test' }); state = reducer(state, { type: 'NOTE_UPDATE_ALL', notes: notes, noteSource: 'test' });
} }
if (selectedNoteIndexes != null) { if (selectedNoteIndexes != null) {
let selectedIds = []; const selectedIds = [];
for (let i = 0; i < selectedNoteIndexes.length; i++) { for (let i = 0; i < selectedNoteIndexes.length; i++) {
selectedIds.push(notes[selectedNoteIndexes[i]].id); selectedIds.push(notes[selectedNoteIndexes[i]].id);
} }
@ -37,7 +37,7 @@ function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes,
} }
function createExpectedState(items, keepIndexes, selectedIndexes) { function createExpectedState(items, keepIndexes, selectedIndexes) {
let expected = { items: [], selectedIds: [] }; const expected = { items: [], selectedIds: [] };
for (let i = 0; i < selectedIndexes.length; i++) { for (let i = 0; i < selectedIndexes.length; i++) {
expected.selectedIds.push(items[selectedIndexes[i]].id); expected.selectedIds.push(items[selectedIndexes[i]].id);
@ -48,8 +48,8 @@ function createExpectedState(items, keepIndexes, selectedIndexes) {
return expected; return expected;
} }
function getIds(items, indexes=null) { function getIds(items, indexes = null) {
let ids = []; const ids = [];
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (indexes == null || i in indexes) { if (indexes == null || i in indexes) {
ids.push(items[i].id); ids.push(items[i].id);
@ -76,9 +76,9 @@ describe('Reducer', function() {
// tests for NOTE_DELETE // tests for NOTE_DELETE
it('should delete selected note', asyncTest(async () => { it('should delete selected note', asyncTest(async () => {
// create 1 folder // create 1 folder
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
// create 5 notes // create 5 notes
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
// select the 1st folder and the 3rd note // select the 1st folder and the 3rd note
let state = initTestState(folders, 0, notes, [2]); let state = initTestState(folders, 0, notes, [2]);
@ -87,7 +87,7 @@ describe('Reducer', function() {
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
// expect that the third note is missing, and the 4th note is now selected // expect that the third note is missing, and the 4th note is now selected
let expected = createExpectedState(notes, [0,1,3,4], [3]); const expected = createExpectedState(notes, [0,1,3,4], [3]);
// check the ids of all the remaining notes // check the ids of all the remaining notes
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
@ -96,136 +96,136 @@ describe('Reducer', function() {
})); }));
it('should delete selected note at top', asyncTest(async () => { it('should delete selected note at top', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [1]); let state = initTestState(folders, 0, notes, [1]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id });
let expected = createExpectedState(notes, [1,2,3,4], [1]); const expected = createExpectedState(notes, [1,2,3,4], [1]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete last remaining note', asyncTest(async () => { it('should delete last remaining note', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(1, folders[0]); const notes = await createNTestNotes(1, folders[0]);
let state = initTestState(folders, 0, notes, [0]); let state = initTestState(folders, 0, notes, [0]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id });
let expected = createExpectedState(notes, [], []); const expected = createExpectedState(notes, [], []);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete selected note at bottom', asyncTest(async () => { it('should delete selected note at bottom', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [4]); let state = initTestState(folders, 0, notes, [4]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
let expected = createExpectedState(notes, [0,1,2,3], [3]); const expected = createExpectedState(notes, [0,1,2,3], [3]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete note when a note below is selected', asyncTest(async () => { it('should delete note when a note below is selected', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [3]); let state = initTestState(folders, 0, notes, [3]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
let expected = createExpectedState(notes, [0,2,3,4], [3]); const expected = createExpectedState(notes, [0,2,3,4], [3]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete note when a note above is selected', asyncTest(async () => { it('should delete note when a note above is selected', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [1]); let state = initTestState(folders, 0, notes, [1]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
let expected = createExpectedState(notes, [0,1,2,4], [1]); const expected = createExpectedState(notes, [0,1,2,4], [1]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete selected notes', asyncTest(async () => { it('should delete selected notes', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [1,2]); let state = initTestState(folders, 0, notes, [1,2]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
let expected = createExpectedState(notes, [0,3,4], [3]); const expected = createExpectedState(notes, [0,3,4], [3]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete note when a notes below it are selected', asyncTest(async () => { it('should delete note when a notes below it are selected', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [3,4]); let state = initTestState(folders, 0, notes, [3,4]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
let expected = createExpectedState(notes, [0,2,3,4], [3,4]); const expected = createExpectedState(notes, [0,2,3,4], [3,4]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete note when a notes above it are selected', asyncTest(async () => { it('should delete note when a notes above it are selected', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [1,2]); let state = initTestState(folders, 0, notes, [1,2]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
let expected = createExpectedState(notes, [0,1,2,4], [1,2]); const expected = createExpectedState(notes, [0,1,2,4], [1,2]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete notes at end', asyncTest(async () => { it('should delete notes at end', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [3,4]); let state = initTestState(folders, 0, notes, [3,4]);
// test action // test action
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
let expected = createExpectedState(notes, [0,1,2], [2]); const expected = createExpectedState(notes, [0,1,2], [2]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
})); }));
it('should delete notes when non-contiguous selection', asyncTest(async () => { it('should delete notes when non-contiguous selection', asyncTest(async () => {
let folders = await createNTestFolders(1); const folders = await createNTestFolders(1);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 0, notes, [0,2,4]); let state = initTestState(folders, 0, notes, [0,2,4]);
// test action // test action
@ -233,7 +233,7 @@ describe('Reducer', function() {
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id }); state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
let expected = createExpectedState(notes, [1,3], [1]); const expected = createExpectedState(notes, [1,3], [1]);
expect(getIds(state.notes)).toEqual(getIds(expected.items)); expect(getIds(state.notes)).toEqual(getIds(expected.items));
expect(state.selectedNoteIds).toEqual(expected.selectedIds); expect(state.selectedNoteIds).toEqual(expected.selectedIds);
@ -241,42 +241,42 @@ describe('Reducer', function() {
// tests for FOLDER_DELETE // tests for FOLDER_DELETE
it('should delete selected notebook', asyncTest(async () => { it('should delete selected notebook', asyncTest(async () => {
let folders = await createNTestFolders(5); const folders = await createNTestFolders(5);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 2, notes, [2]); let state = initTestState(folders, 2, notes, [2]);
// test action // test action
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id }); state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
let expected = createExpectedState(folders, [0,1,3,4], [3]); const expected = createExpectedState(folders, [0,1,3,4], [3]);
expect(getIds(state.folders)).toEqual(getIds(expected.items)); expect(getIds(state.folders)).toEqual(getIds(expected.items));
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]); expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
})); }));
it('should delete notebook when a book above is selected', asyncTest(async () => { it('should delete notebook when a book above is selected', asyncTest(async () => {
let folders = await createNTestFolders(5); const folders = await createNTestFolders(5);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 1, notes, [2]); let state = initTestState(folders, 1, notes, [2]);
// test action // test action
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id }); state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
let expected = createExpectedState(folders, [0,1,3,4], [1]); const expected = createExpectedState(folders, [0,1,3,4], [1]);
expect(getIds(state.folders)).toEqual(getIds(expected.items)); expect(getIds(state.folders)).toEqual(getIds(expected.items));
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]); expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
})); }));
it('should delete notebook when a book below is selected', asyncTest(async () => { it('should delete notebook when a book below is selected', asyncTest(async () => {
let folders = await createNTestFolders(5); const folders = await createNTestFolders(5);
let notes = await createNTestNotes(5, folders[0]); const notes = await createNTestNotes(5, folders[0]);
let state = initTestState(folders, 4, notes, [2]); let state = initTestState(folders, 4, notes, [2]);
// test action // test action
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id }); state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
let expected = createExpectedState(folders, [0,1,3,4], [4]); const expected = createExpectedState(folders, [0,1,3,4], [4]);
expect(getIds(state.folders)).toEqual(getIds(expected.items)); expect(getIds(state.folders)).toEqual(getIds(expected.items));
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]); expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
@ -284,47 +284,47 @@ describe('Reducer', function() {
// tests for TAG_DELETE // tests for TAG_DELETE
it('should delete selected tag', asyncTest(async () => { it('should delete selected tag', asyncTest(async () => {
let tags = await createNTestTags(5); const tags = await createNTestTags(5);
let state = initTestState(null, null, null, null, tags, [2]); let state = initTestState(null, null, null, null, tags, [2]);
// test action // test action
state = reducer(state, { type: 'TAG_DELETE', id: tags[2].id }); state = reducer(state, { type: 'TAG_DELETE', id: tags[2].id });
let expected = createExpectedState(tags, [0,1,3,4], [3]); const expected = createExpectedState(tags, [0,1,3,4], [3]);
expect(getIds(state.tags)).toEqual(getIds(expected.items)); expect(getIds(state.tags)).toEqual(getIds(expected.items));
expect(state.selectedTagId).toEqual(expected.selectedIds[0]); expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
})); }));
it('should delete tag when a tag above is selected', asyncTest(async () => { it('should delete tag when a tag above is selected', asyncTest(async () => {
let tags = await createNTestTags(5); const tags = await createNTestTags(5);
let state = initTestState(null, null, null, null, tags, [2]); let state = initTestState(null, null, null, null, tags, [2]);
// test action // test action
state = reducer(state, { type: 'TAG_DELETE', id: tags[4].id }); state = reducer(state, { type: 'TAG_DELETE', id: tags[4].id });
let expected = createExpectedState(tags, [0,1,2,3], [2]); const expected = createExpectedState(tags, [0,1,2,3], [2]);
expect(getIds(state.tags)).toEqual(getIds(expected.items)); expect(getIds(state.tags)).toEqual(getIds(expected.items));
expect(state.selectedTagId).toEqual(expected.selectedIds[0]); expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
})); }));
it('should delete tag when a tag below is selected', asyncTest(async () => { it('should delete tag when a tag below is selected', asyncTest(async () => {
let tags = await createNTestTags(5); const tags = await createNTestTags(5);
let state = initTestState(null, null, null, null, tags, [2]); let state = initTestState(null, null, null, null, tags, [2]);
// test action // test action
state = reducer(state, { type: 'TAG_DELETE', id: tags[0].id }); state = reducer(state, { type: 'TAG_DELETE', id: tags[0].id });
let expected = createExpectedState(tags, [1,2,3,4], [2]); const expected = createExpectedState(tags, [1,2,3,4], [2]);
expect(getIds(state.tags)).toEqual(getIds(expected.items)); expect(getIds(state.tags)).toEqual(getIds(expected.items));
expect(state.selectedTagId).toEqual(expected.selectedIds[0]); expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
})); }));
it('should select all notes', asyncTest(async () => { it('should select all notes', asyncTest(async () => {
let folders = await createNTestFolders(2); const folders = await createNTestFolders(2);
let notes = []; const notes = [];
for (let i = 0; i < folders.length; i++) { for (let i = 0; i < folders.length; i++) {
notes.push(...await createNTestNotes(3, folders[i])); notes.push(...await createNTestNotes(3, folders[i]));
} }

View File

@ -94,7 +94,7 @@ describe('services_EncryptionService', function() {
})); }));
it('should not upgrade master key if invalid password', asyncTest(async () => { it('should not upgrade master key if invalid password', asyncTest(async () => {
let masterKey = await service.generateMasterKey('123456', { const masterKey = await service.generateMasterKey('123456', {
encryptionMethod: EncryptionService.METHOD_SJCL_2, encryptionMethod: EncryptionService.METHOD_SJCL_2,
}); });
@ -207,7 +207,7 @@ describe('services_EncryptionService', function() {
await service.unloadMasterKey(masterKey); await service.unloadMasterKey(masterKey);
let hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText)); const hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText));
expect(hasThrown).toBe(true); expect(hasThrown).toBe(true);
})); }));
@ -222,7 +222,7 @@ describe('services_EncryptionService', function() {
let cipherText = await service.encryptString('some secret'); let cipherText = await service.encryptString('some secret');
cipherText += 'ABCDEFGHIJ'; cipherText += 'ABCDEFGHIJ';
let hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText)); const hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText));
expect(hasThrown).toBe(true); expect(hasThrown).toBe(true);
})); }));
@ -232,10 +232,10 @@ describe('services_EncryptionService', function() {
masterKey = await MasterKey.save(masterKey); masterKey = await MasterKey.save(masterKey);
await service.loadMasterKey_(masterKey, '123456', true); await service.loadMasterKey_(masterKey, '123456', true);
let folder = await Folder.save({ title: 'folder' }); const folder = await Folder.save({ title: 'folder' });
let note = await Note.save({ title: 'encrypted note', body: 'something', parent_id: folder.id }); const note = await Note.save({ title: 'encrypted note', body: 'something', parent_id: folder.id });
let serialized = await Note.serializeForSync(note); const serialized = await Note.serializeForSync(note);
let deserialized = Note.filter(await Note.unserialize(serialized)); const deserialized = Note.filter(await Note.unserialize(serialized));
// Check that required properties are not encrypted // Check that required properties are not encrypted
expect(deserialized.id).toBe(note.id); expect(deserialized.id).toBe(note.id);

View File

@ -59,7 +59,7 @@ describe('services_InteropService', function() {
// Check that a new folder, with a new ID, has been created // Check that a new folder, with a new ID, has been created
expect(await Folder.count()).toBe(1); expect(await Folder.count()).toBe(1);
let folder2 = (await Folder.all())[0]; const folder2 = (await Folder.all())[0];
expect(folder2.id).not.toBe(folder1.id); expect(folder2.id).not.toBe(folder1.id);
expect(folder2.title).toBe(folder1.title); expect(folder2.title).toBe(folder1.title);
@ -68,7 +68,7 @@ describe('services_InteropService', function() {
// As there was already a folder with the same title, check that the new one has been renamed // As there was already a folder with the same title, check that the new one has been renamed
await Folder.delete(folder2.id); await Folder.delete(folder2.id);
let folder3 = (await Folder.all())[0]; const folder3 = (await Folder.all())[0];
expect(await Folder.count()).toBe(1); expect(await Folder.count()).toBe(1);
expect(folder3.title).not.toBe(folder2.title); expect(folder3.title).not.toBe(folder2.title);
@ -81,7 +81,7 @@ describe('services_InteropService', function() {
it('should export and import folders and notes', asyncTest(async () => { it('should export and import folders and notes', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
@ -95,7 +95,7 @@ describe('services_InteropService', function() {
expect(await Note.count()).toBe(1); expect(await Note.count()).toBe(1);
let note2 = (await Note.all())[0]; let note2 = (await Note.all())[0];
let folder2 = (await Folder.all())[0]; const folder2 = (await Folder.all())[0];
expect(note1.parent_id).not.toBe(note2.parent_id); expect(note1.parent_id).not.toBe(note2.parent_id);
expect(note1.id).not.toBe(note2.id); expect(note1.id).not.toBe(note2.id);
@ -110,7 +110,7 @@ describe('services_InteropService', function() {
await service.import({ path: filePath }); await service.import({ path: filePath });
note2 = (await Note.all())[0]; note2 = (await Note.all())[0];
let note3 = (await Note.all())[1]; const note3 = (await Note.all())[1];
expect(note2.id).not.toBe(note3.id); expect(note2.id).not.toBe(note3.id);
expect(note2.parent_id).not.toBe(note3.parent_id); expect(note2.parent_id).not.toBe(note3.parent_id);
@ -120,7 +120,7 @@ describe('services_InteropService', function() {
it('should export and import notes to specific folder', asyncTest(async () => { it('should export and import notes to specific folder', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
@ -140,8 +140,8 @@ describe('services_InteropService', function() {
it('should export and import tags', asyncTest(async () => { it('should export and import tags', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let tag1 = await Tag.save({ title: 'mon tag' }); let tag1 = await Tag.save({ title: 'mon tag' });
tag1 = await Tag.load(tag1.id); tag1 = await Tag.load(tag1.id);
await Tag.addNote(tag1.id, note1.id); await Tag.addNote(tag1.id, note1.id);
@ -155,8 +155,8 @@ describe('services_InteropService', function() {
await service.import({ path: filePath }); await service.import({ path: filePath });
expect(await Tag.count()).toBe(1); expect(await Tag.count()).toBe(1);
let tag2 = (await Tag.all())[0]; const tag2 = (await Tag.all())[0];
let note2 = (await Note.all())[0]; const note2 = (await Note.all())[0];
expect(tag1.id).not.toBe(tag2.id); expect(tag1.id).not.toBe(tag2.id);
let fieldNames = Note.fieldNames(); let fieldNames = Note.fieldNames();
@ -180,12 +180,12 @@ describe('services_InteropService', function() {
it('should export and import resources', asyncTest(async () => { it('should export and import resources', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
let resourceIds = await Note.linkedResourceIds(note1.body); let resourceIds = await Note.linkedResourceIds(note1.body);
let resource1 = await Resource.load(resourceIds[0]); const resource1 = await Resource.load(resourceIds[0]);
await service.export({ path: filePath }); await service.export({ path: filePath });
@ -195,11 +195,11 @@ describe('services_InteropService', function() {
expect(await Resource.count()).toBe(2); expect(await Resource.count()).toBe(2);
let note2 = (await Note.all())[0]; const note2 = (await Note.all())[0];
expect(note2.body).not.toBe(note1.body); expect(note2.body).not.toBe(note1.body);
resourceIds = await Note.linkedResourceIds(note2.body); resourceIds = await Note.linkedResourceIds(note2.body);
expect(resourceIds.length).toBe(1); expect(resourceIds.length).toBe(1);
let resource2 = await Resource.load(resourceIds[0]); const resource2 = await Resource.load(resourceIds[0]);
expect(resource2.id).not.toBe(resource1.id); expect(resource2.id).not.toBe(resource1.id);
let fieldNames = Note.fieldNames(); let fieldNames = Note.fieldNames();
@ -216,8 +216,8 @@ describe('services_InteropService', function() {
it('should export and import single notes', asyncTest(async () => { it('should export and import single notes', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await service.export({ path: filePath, sourceNoteIds: [note1.id] }); await service.export({ path: filePath, sourceNoteIds: [note1.id] });
@ -229,15 +229,15 @@ describe('services_InteropService', function() {
expect(await Note.count()).toBe(1); expect(await Note.count()).toBe(1);
expect(await Folder.count()).toBe(1); expect(await Folder.count()).toBe(1);
let folder2 = (await Folder.all())[0]; const folder2 = (await Folder.all())[0];
expect(folder2.title).toBe('test'); expect(folder2.title).toBe('test');
})); }));
it('should export and import single folders', asyncTest(async () => { it('should export and import single folders', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await service.export({ path: filePath, sourceFolderIds: [folder1.id] }); await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
@ -249,7 +249,7 @@ describe('services_InteropService', function() {
expect(await Note.count()).toBe(1); expect(await Note.count()).toBe(1);
expect(await Folder.count()).toBe(1); expect(await Folder.count()).toBe(1);
let folder2 = (await Folder.all())[0]; const folder2 = (await Folder.all())[0];
expect(folder2.title).toBe('folder1'); expect(folder2.title).toBe('folder1');
})); }));
@ -257,11 +257,11 @@ describe('services_InteropService', function() {
const service = new InteropService(); const service = new InteropService();
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id }); const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let folder3 = await Folder.save({ title: 'folder3', parent_id: folder2.id }); const folder3 = await Folder.save({ title: 'folder3', parent_id: folder2.id });
let folder4 = await Folder.save({ title: 'folder4', parent_id: folder2.id }); const folder4 = await Folder.save({ title: 'folder4', parent_id: folder2.id });
let note1 = await Note.save({ title: 'ma note', parent_id: folder4.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder4.id });
await service.export({ path: filePath, sourceFolderIds: [folder1.id] }); await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
@ -276,11 +276,11 @@ describe('services_InteropService', function() {
expect(await Note.count()).toBe(1); expect(await Note.count()).toBe(1);
expect(await Folder.count()).toBe(4); expect(await Folder.count()).toBe(4);
let folder1_2 = await Folder.loadByTitle('folder1'); const folder1_2 = await Folder.loadByTitle('folder1');
let folder2_2 = await Folder.loadByTitle('folder2'); const folder2_2 = await Folder.loadByTitle('folder2');
let folder3_2 = await Folder.loadByTitle('folder3'); const folder3_2 = await Folder.loadByTitle('folder3');
let folder4_2 = await Folder.loadByTitle('folder4'); const folder4_2 = await Folder.loadByTitle('folder4');
let note1_2 = await Note.loadByTitle('ma note'); const note1_2 = await Note.loadByTitle('ma note');
expect(folder2_2.parent_id).toBe(folder1_2.id); expect(folder2_2.parent_id).toBe(folder1_2.id);
expect(folder3_2.parent_id).toBe(folder2_2.id); expect(folder3_2.parent_id).toBe(folder2_2.id);
@ -291,9 +291,9 @@ describe('services_InteropService', function() {
it('should export and import links to notes', asyncTest(async () => { it('should export and import links to notes', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
const filePath = `${exportDir()}/test.jex`; const filePath = `${exportDir()}/test.jex`;
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id }); const note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id });
await service.export({ path: filePath, sourceFolderIds: [folder1.id] }); await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
@ -306,15 +306,15 @@ describe('services_InteropService', function() {
expect(await Note.count()).toBe(2); expect(await Note.count()).toBe(2);
expect(await Folder.count()).toBe(1); expect(await Folder.count()).toBe(1);
let note1_2 = await Note.loadByTitle('ma note'); const note1_2 = await Note.loadByTitle('ma note');
let note2_2 = await Note.loadByTitle('ma deuxième note'); const note2_2 = await Note.loadByTitle('ma deuxième note');
expect(note2_2.body.indexOf(note1_2.id) >= 0).toBe(true); expect(note2_2.body.indexOf(note1_2.id) >= 0).toBe(true);
})); }));
it('should export into json format', asyncTest(async () => { it('should export into json format', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
const filePath = exportDir(); const filePath = exportDir();
@ -325,8 +325,8 @@ describe('services_InteropService', function() {
const items = [folder1, note1]; const items = [folder1, note1];
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
const jsonFile = `${filePath}/${items[i].id}.json`; const jsonFile = `${filePath}/${items[i].id}.json`;
let json = await fs.readFile(jsonFile, 'utf-8'); const json = await fs.readFile(jsonFile, 'utf-8');
let obj = JSON.parse(json); const obj = JSON.parse(json);
expect(obj.id).toBe(items[i].id); expect(obj.id).toBe(items[i].id);
expect(obj.type_).toBe(items[i].type_); expect(obj.type_).toBe(items[i].type_);
expect(obj.title).toBe(items[i].title); expect(obj.title).toBe(items[i].title);
@ -336,7 +336,7 @@ describe('services_InteropService', function() {
it('should export selected notes in md format', asyncTest(async () => { it('should export selected notes in md format', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note11 = await Note.save({ title: 'title note11', parent_id: folder1.id }); let note11 = await Note.save({ title: 'title note11', parent_id: folder1.id });
note11 = await Note.load(note11.id); note11 = await Note.load(note11.id);
let note12 = await Note.save({ title: 'title note12', parent_id: folder1.id }); let note12 = await Note.save({ title: 'title note12', parent_id: folder1.id });
@ -365,15 +365,15 @@ describe('services_InteropService', function() {
it('should export MD with unicode filenames', asyncTest(async () => { it('should export MD with unicode filenames', asyncTest(async () => {
const service = new InteropService(); const service = new InteropService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let folder2 = await Folder.save({ title: 'ジョプリン' }); const folder2 = await Folder.save({ title: 'ジョプリン' });
let note1 = await Note.save({ title: '生活', parent_id: folder1.id }); const note1 = await Note.save({ title: '生活', parent_id: folder1.id });
let note2 = await Note.save({ title: '生活', parent_id: folder1.id }); const note2 = await Note.save({ title: '生活', parent_id: folder1.id });
let note2b = await Note.save({ title: '生活', parent_id: folder1.id }); const note2b = await Note.save({ title: '生活', parent_id: folder1.id });
let note3 = await Note.save({ title: '', parent_id: folder1.id }); const note3 = await Note.save({ title: '', parent_id: folder1.id });
let note4 = await Note.save({ title: '', parent_id: folder1.id }); const note4 = await Note.save({ title: '', parent_id: folder1.id });
let note5 = await Note.save({ title: 'salut, ça roule ?', parent_id: folder1.id }); const note5 = await Note.save({ title: 'salut, ça roule ?', parent_id: folder1.id });
let note6 = await Note.save({ title: 'ジョプリン', parent_id: folder2.id }); const note6 = await Note.save({ title: 'ジョプリン', parent_id: folder2.id });
const outDir = exportDir(); const outDir = exportDir();

View File

@ -49,9 +49,9 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id }); let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder1.id }); const note2 = await Note.save({ title: 'note2', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id); queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
@ -59,7 +59,7 @@ describe('services_InteropService_Exporter_Md', function() {
queueExportItem(BaseModel.TYPE_NOTE, note2); queueExportItem(BaseModel.TYPE_NOTE, note2);
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]); queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]);
let folder2 = await Folder.save({ title: 'folder2' }); const folder2 = await Folder.save({ title: 'folder2' });
let note3 = await Note.save({ title: 'note3', parent_id: folder2.id }); let note3 = await Note.save({ title: 'note3', parent_id: folder2.id });
await shim.attachFileToNote(note3, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note3, `${__dirname}/../tests/support/photo.jpg`);
note3 = await Note.load(note3.id); note3 = await Note.load(note3.id);
@ -91,9 +91,9 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id }); const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
let note1_2 = await Note.save({ title: 'note1', parent_id: folder1.id }); const note1_2 = await Note.save({ title: 'note1', parent_id: folder1.id });
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id); queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1); queueExportItem(BaseModel.TYPE_NOTE, note1);
queueExportItem(BaseModel.TYPE_NOTE, note1_2); queueExportItem(BaseModel.TYPE_NOTE, note1_2);
@ -118,8 +118,8 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id }); const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id); queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1); queueExportItem(BaseModel.TYPE_NOTE, note1);
@ -145,23 +145,23 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id }); let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id); queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1); queueExportItem(BaseModel.TYPE_NOTE, note1);
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]); queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]);
let resource1 = await Resource.load(itemsToExport[2].itemOrId); const resource1 = await Resource.load(itemsToExport[2].itemOrId);
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id }); const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id }); let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
note2 = await Note.load(note2.id); note2 = await Note.load(note2.id);
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id); queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
queueExportItem(BaseModel.TYPE_NOTE, note2); queueExportItem(BaseModel.TYPE_NOTE, note2);
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note2.body))[0]); queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note2.body))[0]);
let resource2 = await Resource.load(itemsToExport[5].itemOrId); const resource2 = await Resource.load(itemsToExport[5].itemOrId);
await exporter.processResource(resource1, Resource.fullPath(resource1)); await exporter.processResource(resource1, Resource.fullPath(resource1));
await exporter.processResource(resource2, Resource.fullPath(resource2)); await exporter.processResource(resource2, Resource.fullPath(resource2));
@ -182,13 +182,13 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id }); const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id }); const note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
queueExportItem(BaseModel.TYPE_NOTE, note2); queueExportItem(BaseModel.TYPE_NOTE, note2);
let folder3 = await Folder.save({ title: 'folder3', parent_id: folder1.id }); const folder3 = await Folder.save({ title: 'folder3', parent_id: folder1.id });
queueExportItem(BaseModel.TYPE_FOLDER, folder3.id); queueExportItem(BaseModel.TYPE_FOLDER, folder3.id);
await exporter.processItem(Folder, folder2); await exporter.processItem(Folder, folder2);
@ -213,18 +213,18 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id }); const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id); queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1); queueExportItem(BaseModel.TYPE_NOTE, note1);
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id }); const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id }); const note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id); queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
queueExportItem(BaseModel.TYPE_NOTE, note2); queueExportItem(BaseModel.TYPE_NOTE, note2);
let folder3 = await Folder.save({ title: 'folder3' }); const folder3 = await Folder.save({ title: 'folder3' });
let note3 = await Note.save({ title: 'note3', parent_id: folder3.id }); const note3 = await Note.save({ title: 'note3', parent_id: folder3.id });
queueExportItem(BaseModel.TYPE_FOLDER, folder3.id); queueExportItem(BaseModel.TYPE_FOLDER, folder3.id);
queueExportItem(BaseModel.TYPE_NOTE, note3); queueExportItem(BaseModel.TYPE_NOTE, note3);
@ -250,24 +250,24 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id }); let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await Note.load(note1.id); note1 = await Note.load(note1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1); queueExportItem(BaseModel.TYPE_NOTE, note1);
let resource1 = await Resource.load((await Note.linkedResourceIds(note1.body))[0]); const resource1 = await Resource.load((await Note.linkedResourceIds(note1.body))[0]);
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id }); const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id }); let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
note2 = await Note.load(note2.id); note2 = await Note.load(note2.id);
queueExportItem(BaseModel.TYPE_NOTE, note2); queueExportItem(BaseModel.TYPE_NOTE, note2);
let resource2 = await Resource.load((await Note.linkedResourceIds(note2.body))[0]); const resource2 = await Resource.load((await Note.linkedResourceIds(note2.body))[0]);
await exporter.processItem(Folder, folder1); await exporter.processItem(Folder, folder1);
await exporter.processItem(Folder, folder2); await exporter.processItem(Folder, folder2);
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport); await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
let context = { const context = {
resourcePaths: {}, resourcePaths: {},
}; };
context.resourcePaths[resource1.id] = 'resource1.jpg'; context.resourcePaths[resource1.id] = 'resource1.jpg';
@ -276,8 +276,8 @@ describe('services_InteropService_Exporter_Md', function() {
await exporter.processItem(Note, note1); await exporter.processItem(Note, note1);
await exporter.processItem(Note, note2); await exporter.processItem(Note, note2);
let note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`); const note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
let note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`); const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
expect(note1_body).toContain('](../_resources/resource1.jpg)', 'Resource id should be replaced with a relative path.'); expect(note1_body).toContain('](../_resources/resource1.jpg)', 'Resource id should be replaced with a relative path.');
expect(note2_body).toContain('](../../_resources/resource2.jpg)', 'Resource id should be replaced with a relative path.'); expect(note2_body).toContain('](../../_resources/resource2.jpg)', 'Resource id should be replaced with a relative path.');
@ -301,13 +301,13 @@ describe('services_InteropService_Exporter_Md', function() {
return await Note.load(note.id); return await Note.load(note.id);
}; };
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id }); let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id }); const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id }); let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
let folder3 = await Folder.save({ title: 'folder3' }); const folder3 = await Folder.save({ title: 'folder3' });
let note3 = await Note.save({ title: 'note3', parent_id: folder3.id }); let note3 = await Note.save({ title: 'note3', parent_id: folder3.id });
note1 = await changeNoteBodyAndReload(note1, `# Some text \n\n [A link to note3](:/${note3.id})`); note1 = await changeNoteBodyAndReload(note1, `# Some text \n\n [A link to note3](:/${note3.id})`);
@ -325,9 +325,9 @@ describe('services_InteropService_Exporter_Md', function() {
await exporter.processItem(Note, note2); await exporter.processItem(Note, note2);
await exporter.processItem(Note, note3); await exporter.processItem(Note, note3);
let note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`); const note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
let note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`); const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
let note3_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note3.id]}`); const note3_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note3.id]}`);
expect(note1_body).toContain('](../folder3/note3.md)', 'Note id should be replaced with a relative path.'); expect(note1_body).toContain('](../folder3/note3.md)', 'Note id should be replaced with a relative path.');
expect(note2_body).toContain('](../../folder3/note3.md)', 'Resource id should be replaced with a relative path.'); expect(note2_body).toContain('](../../folder3/note3.md)', 'Resource id should be replaced with a relative path.');
@ -347,9 +347,9 @@ describe('services_InteropService_Exporter_Md', function() {
}); });
}; };
let folder1 = await Folder.save({ title: 'folder with space1' }); const folder1 = await Folder.save({ title: 'folder with space1' });
let note1 = await Note.save({ title: 'note1 name with space', parent_id: folder1.id }); const note1 = await Note.save({ title: 'note1 name with space', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder1.id, body: `[link](:/${note1.id})` }); const note2 = await Note.save({ title: 'note2', parent_id: folder1.id, body: `[link](:/${note1.id})` });
queueExportItem(BaseModel.TYPE_NOTE, note1); queueExportItem(BaseModel.TYPE_NOTE, note1);
queueExportItem(BaseModel.TYPE_NOTE, note2); queueExportItem(BaseModel.TYPE_NOTE, note2);
@ -358,7 +358,7 @@ describe('services_InteropService_Exporter_Md', function() {
await exporter.processItem(Note, note1); await exporter.processItem(Note, note1);
await exporter.processItem(Note, note2); await exporter.processItem(Note, note2);
let note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`); const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
expect(note2_body).toContain('[link](../folder%20with%20space1/note1%20name%20with%20space.md)', 'Whitespace in URL should be encoded'); expect(note2_body).toContain('[link](../folder%20with%20space1/note1%20name%20with%20space.md)', 'Whitespace in URL should be encoded');
})); }));
}); });

View File

@ -48,10 +48,10 @@ describe('services_ResourceService', function() {
it('should delete orphaned resources', asyncTest(async () => { it('should delete orphaned resources', asyncTest(async () => {
const service = new ResourceService(); const service = new ResourceService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
const resourcePath = Resource.fullPath(resource1); const resourcePath = Resource.fullPath(resource1);
await service.indexNoteResources(); await service.indexNoteResources();
@ -79,11 +79,11 @@ describe('services_ResourceService', function() {
it('should not delete resource if still associated with at least one note', asyncTest(async () => { it('should not delete resource if still associated with at least one note', asyncTest(async () => {
const service = new ResourceService(); const service = new ResourceService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma deuxième note', parent_id: folder1.id }); const note2 = await Note.save({ title: 'ma deuxième note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
await service.indexNoteResources(); await service.indexNoteResources();
@ -113,10 +113,10 @@ describe('services_ResourceService', function() {
it('should not delete resource if it is used in an IMG tag', asyncTest(async () => { it('should not delete resource if it is used in an IMG tag', asyncTest(async () => {
const service = new ResourceService(); const service = new ResourceService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
await service.indexNoteResources(); await service.indexNoteResources();
@ -132,10 +132,10 @@ describe('services_ResourceService', function() {
it('should not process twice the same change', asyncTest(async () => { it('should not process twice the same change', asyncTest(async () => {
const service = new ResourceService(); const service = new ResourceService();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
await service.indexNoteResources(); await service.indexNoteResources();
@ -169,8 +169,8 @@ describe('services_ResourceService', function() {
const masterKey = await loadEncryptionMasterKey(); const masterKey = await loadEncryptionMasterKey();
await encryptionService().enableEncryption(masterKey, '123456'); await encryptionService().enableEncryption(masterKey, '123456');
await encryptionService().loadMasterKeysFromSettings(); await encryptionService().loadMasterKeysFromSettings();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); // R1 await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); // R1
await resourceService().indexNoteResources(); await resourceService().indexNoteResources();
await synchronizer().start(); await synchronizer().start();
@ -199,7 +199,7 @@ describe('services_ResourceService', function() {
it('should double-check if the resource is still linked before deleting it', asyncTest(async () => { it('should double-check if the resource is still linked before deleting it', asyncTest(async () => {
SearchEngine.instance().setDb(db()); // /!\ Note that we use the global search engine here, which we shouldn't but will work for now SearchEngine.instance().setDb(db()); // /!\ Note that we use the global search engine here, which we shouldn't but will work for now
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await resourceService().indexNoteResources(); await resourceService().indexNoteResources();

View File

@ -1,4 +1,5 @@
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
/* eslint prefer-const: 0*/
require('app-module-path').addPath(__dirname); require('app-module-path').addPath(__dirname);

View File

@ -37,26 +37,26 @@ describe('services_rest_Api', function() {
})); }));
it('should get folders', asyncTest(async () => { it('should get folders', asyncTest(async () => {
let f1 = await Folder.save({ title: 'mon carnet' }); const f1 = await Folder.save({ title: 'mon carnet' });
const response = await api.route('GET', 'folders'); const response = await api.route('GET', 'folders');
expect(response.length).toBe(1); expect(response.length).toBe(1);
})); }));
it('should update folders', asyncTest(async () => { it('should update folders', asyncTest(async () => {
let f1 = await Folder.save({ title: 'mon carnet' }); const f1 = await Folder.save({ title: 'mon carnet' });
const response = await api.route('PUT', `folders/${f1.id}`, null, JSON.stringify({ const response = await api.route('PUT', `folders/${f1.id}`, null, JSON.stringify({
title: 'modifié', title: 'modifié',
})); }));
let f1b = await Folder.load(f1.id); const f1b = await Folder.load(f1.id);
expect(f1b.title).toBe('modifié'); expect(f1b.title).toBe('modifié');
})); }));
it('should delete folders', asyncTest(async () => { it('should delete folders', asyncTest(async () => {
let f1 = await Folder.save({ title: 'mon carnet' }); const f1 = await Folder.save({ title: 'mon carnet' });
await api.route('DELETE', `folders/${f1.id}`); await api.route('DELETE', `folders/${f1.id}`);
let f1b = await Folder.load(f1.id); const f1b = await Folder.load(f1.id);
expect(!f1b).toBe(true); expect(!f1b).toBe(true);
})); }));
@ -67,13 +67,13 @@ describe('services_rest_Api', function() {
expect(!!response.id).toBe(true); expect(!!response.id).toBe(true);
let f = await Folder.all(); const f = await Folder.all();
expect(f.length).toBe(1); expect(f.length).toBe(1);
expect(f[0].title).toBe('from api'); expect(f[0].title).toBe('from api');
})); }));
it('should get one folder', asyncTest(async () => { it('should get one folder', asyncTest(async () => {
let f1 = await Folder.save({ title: 'mon carnet' }); const f1 = await Folder.save({ title: 'mon carnet' });
const response = await api.route('GET', `folders/${f1.id}`); const response = await api.route('GET', `folders/${f1.id}`);
expect(response.id).toBe(f1.id); expect(response.id).toBe(f1.id);
@ -82,7 +82,7 @@ describe('services_rest_Api', function() {
})); }));
it('should get the folder notes', asyncTest(async () => { it('should get the folder notes', asyncTest(async () => {
let f1 = await Folder.save({ title: 'mon carnet' }); const f1 = await Folder.save({ title: 'mon carnet' });
const response2 = await api.route('GET', `folders/${f1.id}/notes`); const response2 = await api.route('GET', `folders/${f1.id}/notes`);
expect(response2.length).toBe(0); expect(response2.length).toBe(0);

View File

@ -27,8 +27,8 @@ process.on('unhandledRejection', (reason, p) => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000 + 30000; // The first test is slow because the database needs to be built jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000 + 30000; // The first test is slow because the database needs to be built
async function allNotesFolders() { async function allNotesFolders() {
let folders = await Folder.all(); const folders = await Folder.all();
let notes = await Note.all(); const notes = await Note.all();
return folders.concat(notes); return folders.concat(notes);
} }
@ -66,9 +66,9 @@ async function localNotesFoldersSameAsRemote(locals, expect) {
expect(locals.length).toBe(nf.length); expect(locals.length).toBe(nf.length);
for (let i = 0; i < locals.length; i++) { for (let i = 0; i < locals.length; i++) {
let dbItem = locals[i]; const dbItem = locals[i];
let path = BaseItem.systemPath(dbItem); const path = BaseItem.systemPath(dbItem);
let remote = await fileApi().stat(path); const remote = await fileApi().stat(path);
expect(!!remote).toBe(true); expect(!!remote).toBe(true);
if (!remote) continue; if (!remote) continue;
@ -101,10 +101,10 @@ describe('synchronizer', function() {
}); });
it('should create remote items', asyncTest(async () => { it('should create remote items', asyncTest(async () => {
let folder = await Folder.save({ title: 'folder1' }); const folder = await Folder.save({ title: 'folder1' });
await Note.save({ title: 'un', parent_id: folder.id }); await Note.save({ title: 'un', parent_id: folder.id });
let all = await allNotesFolders(); const all = await allNotesFolders();
await synchronizer().start(); await synchronizer().start();
@ -112,20 +112,20 @@ describe('synchronizer', function() {
})); }));
it('should update remote items', asyncTest(async () => { it('should update remote items', asyncTest(async () => {
let folder = await Folder.save({ title: 'folder1' }); const folder = await Folder.save({ title: 'folder1' });
let note = await Note.save({ title: 'un', parent_id: folder.id }); const note = await Note.save({ title: 'un', parent_id: folder.id });
await synchronizer().start(); await synchronizer().start();
await Note.save({ title: 'un UPDATE', id: note.id }); await Note.save({ title: 'un UPDATE', id: note.id });
let all = await allNotesFolders(); const all = await allNotesFolders();
await synchronizer().start(); await synchronizer().start();
await localNotesFoldersSameAsRemote(all, expect); await localNotesFoldersSameAsRemote(all, expect);
})); }));
it('should create local items', asyncTest(async () => { it('should create local items', asyncTest(async () => {
let folder = await Folder.save({ title: 'folder1' }); const folder = await Folder.save({ title: 'folder1' });
await Note.save({ title: 'un', parent_id: folder.id }); await Note.save({ title: 'un', parent_id: folder.id });
await synchronizer().start(); await synchronizer().start();
@ -133,14 +133,14 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let all = await allNotesFolders(); const all = await allNotesFolders();
await localNotesFoldersSameAsRemote(all, expect); await localNotesFoldersSameAsRemote(all, expect);
})); }));
it('should update local items', asyncTest(async () => { it('should update local items', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -160,14 +160,14 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let all = await allNotesFolders(); const all = await allNotesFolders();
await localNotesFoldersSameAsRemote(all, expect); await localNotesFoldersSameAsRemote(all, expect);
})); }));
it('should resolve note conflicts', asyncTest(async () => { it('should resolve note conflicts', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -186,29 +186,29 @@ describe('synchronizer', function() {
await Note.save(note2conf); await Note.save(note2conf);
note2conf = await Note.load(note1.id); note2conf = await Note.load(note1.id);
await synchronizer().start(); await synchronizer().start();
let conflictedNotes = await Note.conflictedNotes(); const conflictedNotes = await Note.conflictedNotes();
expect(conflictedNotes.length).toBe(1); expect(conflictedNotes.length).toBe(1);
// Other than the id (since the conflicted note is a duplicate), and the is_conflict property // 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. // the conflicted and original note must be the same in every way, to make sure no data has been lost.
let conflictedNote = conflictedNotes[0]; const conflictedNote = conflictedNotes[0];
expect(conflictedNote.id == note2conf.id).toBe(false); expect(conflictedNote.id == note2conf.id).toBe(false);
for (let n in conflictedNote) { for (const n in conflictedNote) {
if (!conflictedNote.hasOwnProperty(n)) continue; if (!conflictedNote.hasOwnProperty(n)) continue;
if (n == 'id' || n == 'is_conflict') continue; if (n == 'id' || n == 'is_conflict') continue;
expect(conflictedNote[n]).toBe(note2conf[n], `Property: ${n}`); expect(conflictedNote[n]).toBe(note2conf[n], `Property: ${n}`);
} }
let noteUpdatedFromRemote = await Note.load(note1.id); const noteUpdatedFromRemote = await Note.load(note1.id);
for (let n in noteUpdatedFromRemote) { for (const n in noteUpdatedFromRemote) {
if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue; if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue;
expect(noteUpdatedFromRemote[n]).toBe(note2[n], `Property: ${n}`); expect(noteUpdatedFromRemote[n]).toBe(note2[n], `Property: ${n}`);
} }
})); }));
it('should resolve folders conflicts', asyncTest(async () => { it('should resolve folders conflicts', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); // ---------------------------------- await switchClient(2); // ----------------------------------
@ -235,13 +235,13 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let folder1_final = await Folder.load(folder1.id); const folder1_final = await Folder.load(folder1.id);
expect(folder1_final.title).toBe(folder1_modRemote.title); expect(folder1_final.title).toBe(folder1_modRemote.title);
})); }));
it('should delete remote notes', asyncTest(async () => { it('should delete remote notes', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -258,13 +258,13 @@ describe('synchronizer', function() {
expect(remotes.length).toBe(1); expect(remotes.length).toBe(1);
expect(remotes[0].id).toBe(folder1.id); expect(remotes[0].id).toBe(folder1.id);
let deletedItems = await BaseItem.deletedItems(syncTargetId()); const deletedItems = await BaseItem.deletedItems(syncTargetId());
expect(deletedItems.length).toBe(0); expect(deletedItems.length).toBe(0);
})); }));
it('should not created deleted_items entries for items deleted via sync', asyncTest(async () => { it('should not created deleted_items entries for items deleted via sync', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -276,7 +276,7 @@ describe('synchronizer', function() {
await switchClient(1); await switchClient(1);
await synchronizer().start(); await synchronizer().start();
let deletedItems = await BaseItem.deletedItems(syncTargetId()); const deletedItems = await BaseItem.deletedItems(syncTargetId());
expect(deletedItems.length).toBe(0); expect(deletedItems.length).toBe(0);
})); }));
@ -285,9 +285,9 @@ describe('synchronizer', function() {
// property of the basicDelta() function is cleared properly at the end of a sync operation. If it is not cleared // property of the basicDelta() function is cleared properly at the end of a sync operation. If it is not cleared
// it means items will no longer be deleted locally via sync. // it means items will no longer be deleted locally via sync.
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
let note2 = await Note.save({ title: 'deux', parent_id: folder1.id }); const note2 = await Note.save({ title: 'deux', parent_id: folder1.id });
let context1 = await synchronizer().start(); let context1 = await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -299,17 +299,17 @@ describe('synchronizer', function() {
await switchClient(1); await switchClient(1);
context1 = await synchronizer().start({ context: context1 }); context1 = await synchronizer().start({ context: context1 });
let items = await allNotesFolders(); const items = await allNotesFolders();
expect(items.length).toBe(2); expect(items.length).toBe(2);
let deletedItems = await BaseItem.deletedItems(syncTargetId()); const deletedItems = await BaseItem.deletedItems(syncTargetId());
expect(deletedItems.length).toBe(0); expect(deletedItems.length).toBe(0);
await Note.delete(note2.id); await Note.delete(note2.id);
context1 = await synchronizer().start({ context: context1 }); context1 = await synchronizer().start({ context: context1 });
})); }));
it('should delete remote folder', asyncTest(async () => { it('should delete remote folder', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let folder2 = await Folder.save({ title: 'folder2' }); const folder2 = await Folder.save({ title: 'folder2' });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -322,30 +322,30 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let all = await allNotesFolders(); const all = await allNotesFolders();
await localNotesFoldersSameAsRemote(all, expect); await localNotesFoldersSameAsRemote(all, expect);
})); }));
it('should delete local folder', asyncTest(async () => { it('should delete local folder', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let folder2 = await Folder.save({ title: 'folder2' }); const folder2 = await Folder.save({ title: 'folder2' });
let context1 = await synchronizer().start(); const context1 = await synchronizer().start();
await switchClient(2); await switchClient(2);
let context2 = await synchronizer().start(); const context2 = await synchronizer().start();
await Folder.delete(folder2.id); await Folder.delete(folder2.id);
await synchronizer().start({ context: context2 }); await synchronizer().start({ context: context2 });
await switchClient(1); await switchClient(1);
await synchronizer().start({ context: context1 }); await synchronizer().start({ context: context1 });
let items = await allNotesFolders(); const items = await allNotesFolders();
await localNotesFoldersSameAsRemote(items, expect); await localNotesFoldersSameAsRemote(items, expect);
})); }));
it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', asyncTest(async () => { it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -356,17 +356,17 @@ describe('synchronizer', function() {
await switchClient(1); await switchClient(1);
let note = await Note.save({ title: 'note1', parent_id: folder1.id }); const note = await Note.save({ title: 'note1', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
let items = await allNotesFolders(); const items = await allNotesFolders();
expect(items.length).toBe(1); expect(items.length).toBe(1);
expect(items[0].title).toBe('note1'); expect(items[0].title).toBe('note1');
expect(items[0].is_conflict).toBe(1); expect(items[0].is_conflict).toBe(1);
})); }));
it('should resolve conflict if note has been deleted remotely and locally', asyncTest(async () => { it('should resolve conflict if note has been deleted remotely and locally', asyncTest(async () => {
let folder = await Folder.save({ title: 'folder' }); const folder = await Folder.save({ title: 'folder' });
let note = await Note.save({ title: 'note', parent_id: folder.title }); const note = await Note.save({ title: 'note', parent_id: folder.title });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -380,7 +380,7 @@ describe('synchronizer', function() {
await Note.delete(note.id); await Note.delete(note.id);
await synchronizer().start(); await synchronizer().start();
let items = await allNotesFolders(); const items = await allNotesFolders();
expect(items.length).toBe(1); expect(items.length).toBe(1);
expect(items[0].title).toBe('folder'); expect(items[0].title).toBe('folder');
@ -391,8 +391,8 @@ describe('synchronizer', function() {
// If client1 and 2 have two folders, client 1 deletes item 1 and client // If client1 and 2 have two folders, client 1 deletes item 1 and client
// 2 deletes item 2, they should both end up with no items after sync. // 2 deletes item 2, they should both end up with no items after sync.
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let folder2 = await Folder.save({ title: 'folder2' }); const folder2 = await Folder.save({ title: 'folder2' });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -413,21 +413,21 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let items2 = await allNotesFolders(); const items2 = await allNotesFolders();
await switchClient(1); await switchClient(1);
await synchronizer().start(); await synchronizer().start();
let items1 = await allNotesFolders(); const items1 = await allNotesFolders();
expect(items1.length).toBe(0); expect(items1.length).toBe(0);
expect(items1.length).toBe(items2.length); expect(items1.length).toBe(items2.length);
})); }));
it('should handle conflict when remote note is deleted then local note is modified', asyncTest(async () => { it('should handle conflict when remote note is deleted then local note is modified', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -442,25 +442,25 @@ describe('synchronizer', function() {
await switchClient(1); await switchClient(1);
let newTitle = 'Modified after having been deleted'; const newTitle = 'Modified after having been deleted';
await Note.save({ id: note1.id, title: newTitle }); await Note.save({ id: note1.id, title: newTitle });
await synchronizer().start(); await synchronizer().start();
let conflictedNotes = await Note.conflictedNotes(); const conflictedNotes = await Note.conflictedNotes();
expect(conflictedNotes.length).toBe(1); expect(conflictedNotes.length).toBe(1);
expect(conflictedNotes[0].title).toBe(newTitle); expect(conflictedNotes[0].title).toBe(newTitle);
let unconflictedNotes = await Note.unconflictedNotes(); const unconflictedNotes = await Note.unconflictedNotes();
expect(unconflictedNotes.length).toBe(0); expect(unconflictedNotes.length).toBe(0);
})); }));
it('should handle conflict when remote folder is deleted then local folder is renamed', asyncTest(async () => { it('should handle conflict when remote folder is deleted then local folder is renamed', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let folder2 = await Folder.save({ title: 'folder2' }); const folder2 = await Folder.save({ title: 'folder2' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -477,18 +477,18 @@ describe('synchronizer', function() {
await sleep(0.1); await sleep(0.1);
let newTitle = 'Modified after having been deleted'; const newTitle = 'Modified after having been deleted';
await Folder.save({ id: folder1.id, title: newTitle }); await Folder.save({ id: folder1.id, title: newTitle });
await synchronizer().start(); await synchronizer().start();
let items = await allNotesFolders(); const items = await allNotesFolders();
expect(items.length).toBe(1); expect(items.length).toBe(1);
})); }));
it('should allow duplicate folder titles', asyncTest(async () => { it('should allow duplicate folder titles', asyncTest(async () => {
let localF1 = await Folder.save({ title: 'folder' }); const localF1 = await Folder.save({ title: 'folder' });
await switchClient(2); await switchClient(2);
@ -501,7 +501,7 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let localF2 = await Folder.load(remoteF2.id); const localF2 = await Folder.load(remoteF2.id);
expect(localF2.title == remoteF2.title).toBe(true); expect(localF2.title == remoteF2.title).toBe(true);
@ -528,10 +528,10 @@ describe('synchronizer', function() {
masterKey = await loadEncryptionMasterKey(); masterKey = await loadEncryptionMasterKey();
} }
let f1 = await Folder.save({ title: 'folder' }); const f1 = await Folder.save({ title: 'folder' });
let n1 = await Note.save({ title: 'mynote' }); const n1 = await Note.save({ title: 'mynote' });
let n2 = await Note.save({ title: 'mynote2' }); const n2 = await Note.save({ title: 'mynote2' });
let tag = await Tag.save({ title: 'mytag' }); const tag = await Tag.save({ title: 'mytag' });
let context1 = await synchronizer().start(); let context1 = await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -540,10 +540,10 @@ describe('synchronizer', function() {
if (withEncryption) { if (withEncryption) {
const masterKey_2 = await MasterKey.load(masterKey.id); const masterKey_2 = await MasterKey.load(masterKey.id);
await encryptionService().loadMasterKey_(masterKey_2, '123456', true); await encryptionService().loadMasterKey_(masterKey_2, '123456', true);
let t = await Tag.load(tag.id); const t = await Tag.load(tag.id);
await Tag.decrypt(t); await Tag.decrypt(t);
} }
let remoteTag = await Tag.loadByTitle(tag.title); const remoteTag = await Tag.loadByTitle(tag.title);
expect(!!remoteTag).toBe(true); expect(!!remoteTag).toBe(true);
expect(remoteTag.id).toBe(tag.id); expect(remoteTag.id).toBe(tag.id);
await Tag.addNote(remoteTag.id, n1.id); await Tag.addNote(remoteTag.id, n1.id);
@ -579,22 +579,22 @@ describe('synchronizer', function() {
})); }));
it('should not sync notes with conflicts', asyncTest(async () => { it('should not sync notes with conflicts', asyncTest(async () => {
let f1 = await Folder.save({ title: 'folder' }); const f1 = await Folder.save({ title: 'folder' });
let n1 = await Note.save({ title: 'mynote', parent_id: f1.id, is_conflict: 1 }); const n1 = await Note.save({ title: 'mynote', parent_id: f1.id, is_conflict: 1 });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
await synchronizer().start(); await synchronizer().start();
let notes = await Note.all(); const notes = await Note.all();
let folders = await Folder.all(); const folders = await Folder.all();
expect(notes.length).toBe(0); expect(notes.length).toBe(0);
expect(folders.length).toBe(1); expect(folders.length).toBe(1);
})); }));
it('should not try to delete on remote conflicted notes that have been deleted', asyncTest(async () => { it('should not try to delete on remote conflicted notes that have been deleted', asyncTest(async () => {
let f1 = await Folder.save({ title: 'folder' }); const f1 = await Folder.save({ title: 'folder' });
let n1 = await Note.save({ title: 'mynote', parent_id: f1.id }); const n1 = await Note.save({ title: 'mynote', parent_id: f1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -613,8 +613,8 @@ describe('synchronizer', function() {
await loadEncryptionMasterKey(); await loadEncryptionMasterKey();
} }
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -625,7 +625,7 @@ describe('synchronizer', function() {
await decryptionWorker().start(); await decryptionWorker().start();
} }
let note2 = await Note.load(note1.id); let note2 = await Note.load(note1.id);
note2.todo_completed = time.unixMs()-1; note2.todo_completed = time.unixMs() - 1;
await Note.save(note2); await Note.save(note2);
note2 = await Note.load(note2.id); note2 = await Note.load(note2.id);
await synchronizer().start(); await synchronizer().start();
@ -646,10 +646,10 @@ describe('synchronizer', function() {
// but in practice it doesn't matter, we can just take the date when the // but in practice it doesn't matter, we can just take the date when the
// todo was marked as "done" the first time. // todo was marked as "done" the first time.
let conflictedNotes = await Note.conflictedNotes(); const conflictedNotes = await Note.conflictedNotes();
expect(conflictedNotes.length).toBe(0); expect(conflictedNotes.length).toBe(0);
let notes = await Note.all(); const notes = await Note.all();
expect(notes.length).toBe(1); expect(notes.length).toBe(1);
expect(notes[0].id).toBe(note1.id); expect(notes[0].id).toBe(note1.id);
expect(notes[0].todo_completed).toBe(note2.todo_completed); expect(notes[0].todo_completed).toBe(note2.todo_completed);
@ -658,10 +658,10 @@ describe('synchronizer', function() {
// smart conflict resolving since we don't know the content, so in that // smart conflict resolving since we don't know the content, so in that
// case it's handled as a regular conflict. // case it's handled as a regular conflict.
let conflictedNotes = await Note.conflictedNotes(); const conflictedNotes = await Note.conflictedNotes();
expect(conflictedNotes.length).toBe(1); expect(conflictedNotes.length).toBe(1);
let notes = await Note.all(); const notes = await Note.all();
expect(notes.length).toBe(2); expect(notes.length).toBe(2);
} }
} }
@ -675,14 +675,14 @@ describe('synchronizer', function() {
})); }));
it('items should be downloaded again when user cancels in the middle of delta operation', asyncTest(async () => { it('items should be downloaded again when user cancels in the middle of delta operation', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
synchronizer().testingHooks_ = ['cancelDeltaLoop2']; synchronizer().testingHooks_ = ['cancelDeltaLoop2'];
let context = await synchronizer().start(); const context = await synchronizer().start();
let notes = await Note.all(); let notes = await Note.all();
expect(notes.length).toBe(0); expect(notes.length).toBe(0);
@ -693,8 +693,8 @@ describe('synchronizer', function() {
})); }));
it('should skip items that cannot be synced', asyncTest(async () => { it('should skip items that cannot be synced', asyncTest(async () => {
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
const noteId = note1.id; const noteId = note1.id;
await synchronizer().start(); await synchronizer().start();
let disabledItems = await BaseItem.syncDisabledItems(syncTargetId()); let disabledItems = await BaseItem.syncDisabledItems(syncTargetId());
@ -708,7 +708,7 @@ describe('synchronizer', function() {
await switchClient(2); await switchClient(2);
await synchronizer().start(); await synchronizer().start();
let notes = await Note.all(); const notes = await Note.all();
expect(notes.length).toBe(1); expect(notes.length).toBe(1);
expect(notes[0].title).toBe('un'); expect(notes[0].title).toBe('un');
@ -721,7 +721,7 @@ describe('synchronizer', function() {
it('notes and folders should get encrypted when encryption is enabled', asyncTest(async () => { it('notes and folders should get encrypted when encryption is enabled', asyncTest(async () => {
Setting.setValue('encryption.enabled', true); Setting.setValue('encryption.enabled', true);
const masterKey = await loadEncryptionMasterKey(); const masterKey = await loadEncryptionMasterKey();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', body: 'to be encrypted', parent_id: folder1.id }); let note1 = await Note.save({ title: 'un', body: 'to be encrypted', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
// After synchronisation, remote items should be encrypted but local ones remain plain text // After synchronisation, remote items should be encrypted but local ones remain plain text
@ -733,7 +733,7 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let folder1_2 = await Folder.load(folder1.id); let folder1_2 = await Folder.load(folder1.id);
let note1_2 = await Note.load(note1.id); let note1_2 = await Note.load(note1.id);
let masterKey_2 = await MasterKey.load(masterKey.id); const masterKey_2 = await MasterKey.load(masterKey.id);
// On this side however it should be received encrypted // On this side however it should be received encrypted
expect(!note1_2.title).toBe(true); expect(!note1_2.title).toBe(true);
expect(!folder1_2.title).toBe(true); expect(!folder1_2.title).toBe(true);
@ -820,7 +820,7 @@ describe('synchronizer', function() {
it('should encrypt existing notes too when enabling E2EE', asyncTest(async () => { it('should encrypt existing notes too when enabling E2EE', asyncTest(async () => {
// First create a folder, without encryption enabled, and sync it // First create a folder, without encryption enabled, and sync it
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
await synchronizer().start(); await synchronizer().start();
let files = await fileApi().list(); let files = await fileApi().list();
let content = await fileApi().get(files.items[0].path); let content = await fileApi().get(files.items[0].path);
@ -848,18 +848,18 @@ describe('synchronizer', function() {
it('should sync resources', asyncTest(async () => { it('should sync resources', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(500); while (insideBeforeEach) await time.msleep(500);
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
let resourcePath1 = Resource.fullPath(resource1); const resourcePath1 = Resource.fullPath(resource1);
await synchronizer().start(); await synchronizer().start();
expect((await remoteNotesFoldersResources()).length).toBe(3); expect((await remoteNotesFoldersResources()).length).toBe(3);
await switchClient(2); await switchClient(2);
await synchronizer().start(); await synchronizer().start();
let allResources = await Resource.all(); const allResources = await Resource.all();
expect(allResources.length).toBe(1); expect(allResources.length).toBe(1);
let resource1_2 = allResources[0]; let resource1_2 = allResources[0];
let ls = await Resource.localState(resource1_2); let ls = await Resource.localState(resource1_2);
@ -874,18 +874,18 @@ describe('synchronizer', function() {
ls = await Resource.localState(resource1_2); ls = await Resource.localState(resource1_2);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE); expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
let resourcePath1_2 = Resource.fullPath(resource1_2); const resourcePath1_2 = Resource.fullPath(resource1_2);
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true); expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
})); }));
it('should handle resource download errors', asyncTest(async () => { it('should handle resource download errors', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(500); while (insideBeforeEach) await time.msleep(500);
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; let resource1 = (await Resource.all())[0];
let resourcePath1 = Resource.fullPath(resource1); const resourcePath1 = Resource.fullPath(resource1);
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -902,7 +902,7 @@ describe('synchronizer', function() {
await fetcher.waitForAllFinished(); await fetcher.waitForAllFinished();
resource1 = await Resource.load(resource1.id); resource1 = await Resource.load(resource1.id);
let ls = await Resource.localState(resource1); const ls = await Resource.localState(resource1);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_ERROR); expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_ERROR);
expect(ls.fetch_error).toBe('did not work'); expect(ls.fetch_error).toBe('did not work');
})); }));
@ -910,8 +910,8 @@ describe('synchronizer', function() {
it('should set the resource file size if it is missing', asyncTest(async () => { it('should set the resource file size if it is missing', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(500); while (insideBeforeEach) await time.msleep(500);
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await synchronizer().start(); await synchronizer().start();
@ -933,11 +933,11 @@ describe('synchronizer', function() {
it('should delete resources', asyncTest(async () => { it('should delete resources', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(500); while (insideBeforeEach) await time.msleep(500);
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
let resourcePath1 = Resource.fullPath(resource1); const resourcePath1 = Resource.fullPath(resource1);
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -945,7 +945,7 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
let allResources = await Resource.all(); let allResources = await Resource.all();
expect(allResources.length).toBe(1); expect(allResources.length).toBe(1);
let all = await fileApi().list(); const all = await fileApi().list();
expect((await remoteNotesFoldersResources()).length).toBe(3); expect((await remoteNotesFoldersResources()).length).toBe(3);
await Resource.delete(resource1.id); await Resource.delete(resource1.id);
await synchronizer().start(); await synchronizer().start();
@ -967,11 +967,11 @@ describe('synchronizer', function() {
Setting.setValue('encryption.enabled', true); Setting.setValue('encryption.enabled', true);
const masterKey = await loadEncryptionMasterKey(); const masterKey = await loadEncryptionMasterKey();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
let resourcePath1 = Resource.fullPath(resource1); const resourcePath1 = Resource.fullPath(resource1);
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -986,7 +986,7 @@ describe('synchronizer', function() {
let resource1_2 = (await Resource.all())[0]; let resource1_2 = (await Resource.all())[0];
resource1_2 = await Resource.decrypt(resource1_2); resource1_2 = await Resource.decrypt(resource1_2);
let resourcePath1_2 = Resource.fullPath(resource1_2); const resourcePath1_2 = Resource.fullPath(resource1_2);
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true); expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
})); }));
@ -995,7 +995,7 @@ describe('synchronizer', function() {
Setting.setValue('encryption.enabled', true); Setting.setValue('encryption.enabled', true);
const masterKey = await loadEncryptionMasterKey(); const masterKey = await loadEncryptionMasterKey();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
await synchronizer().start(); await synchronizer().start();
let allEncrypted = await allSyncTargetItemsEncrypted(); let allEncrypted = await allSyncTargetItemsEncrypted();
@ -1016,7 +1016,7 @@ describe('synchronizer', function() {
Setting.setValue('encryption.enabled', true); Setting.setValue('encryption.enabled', true);
const masterKey = await loadEncryptionMasterKey(); const masterKey = await loadEncryptionMasterKey();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -1049,12 +1049,12 @@ describe('synchronizer', function() {
Setting.setValue('encryption.enabled', true); Setting.setValue('encryption.enabled', true);
const masterKey = await loadEncryptionMasterKey(); const masterKey = await loadEncryptionMasterKey();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
await Resource.setFileSizeOnly(resource1.id, -1); await Resource.setFileSizeOnly(resource1.id, -1);
let resourcePath1 = Resource.fullPath(resource1); const resourcePath1 = Resource.fullPath(resource1);
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -1075,8 +1075,8 @@ describe('synchronizer', function() {
it('should encrypt remote resources after encryption has been enabled', asyncTest(async () => { it('should encrypt remote resources after encryption has been enabled', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(100); while (insideBeforeEach) await time.msleep(100);
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await synchronizer().start(); await synchronizer().start();
@ -1094,22 +1094,22 @@ describe('synchronizer', function() {
it('should upload encrypted resource, but it should not mark the blob as encrypted locally', asyncTest(async () => { it('should upload encrypted resource, but it should not mark the blob as encrypted locally', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(100); while (insideBeforeEach) await time.msleep(100);
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
const masterKey = await loadEncryptionMasterKey(); const masterKey = await loadEncryptionMasterKey();
await encryptionService().enableEncryption(masterKey, '123456'); await encryptionService().enableEncryption(masterKey, '123456');
await encryptionService().loadMasterKeysFromSettings(); await encryptionService().loadMasterKeysFromSettings();
await synchronizer().start(); await synchronizer().start();
let resource1 = (await Resource.all())[0]; const resource1 = (await Resource.all())[0];
expect(resource1.encryption_blob_encrypted).toBe(0); expect(resource1.encryption_blob_encrypted).toBe(0);
})); }));
it('should create remote items with UTF-8 content', asyncTest(async () => { it('should create remote items with UTF-8 content', asyncTest(async () => {
let folder = await Folder.save({ title: 'Fahrräder' }); const folder = await Folder.save({ title: 'Fahrräder' });
await Note.save({ title: 'Fahrräder', body: 'Fahrräder', parent_id: folder.id }); await Note.save({ title: 'Fahrräder', body: 'Fahrräder', parent_id: folder.id });
let all = await allNotesFolders(); const all = await allNotesFolders();
await synchronizer().start(); await synchronizer().start();
@ -1117,8 +1117,8 @@ describe('synchronizer', function() {
})); }));
it('should update remote items but not pull remote changes', asyncTest(async () => { it('should update remote items but not pull remote changes', asyncTest(async () => {
let folder = await Folder.save({ title: 'folder1' }); const folder = await Folder.save({ title: 'folder1' });
let note = await Note.save({ title: 'un', parent_id: folder.id }); const note = await Note.save({ title: 'un', parent_id: folder.id });
await synchronizer().start(); await synchronizer().start();
await switchClient(2); await switchClient(2);
@ -1131,13 +1131,13 @@ describe('synchronizer', function() {
await Note.save({ title: 'un UPDATE', id: note.id }); await Note.save({ title: 'un UPDATE', id: note.id });
await synchronizer().start({ syncSteps: ['update_remote'] }); await synchronizer().start({ syncSteps: ['update_remote'] });
let all = await allNotesFolders(); const all = await allNotesFolders();
expect(all.length).toBe(2); expect(all.length).toBe(2);
await switchClient(2); await switchClient(2);
await synchronizer().start(); await synchronizer().start();
let note2 = await Note.load(note.id); const note2 = await Note.load(note.id);
expect(note2.title).toBe('un UPDATE'); expect(note2.title).toBe('un UPDATE');
})); }));
@ -1544,8 +1544,8 @@ describe('synchronizer', function() {
Setting.setValue('encryption.enabled', true); Setting.setValue('encryption.enabled', true);
await loadEncryptionMasterKey(); await loadEncryptionMasterKey();
let folder1 = await Folder.save({ title: 'folder1' }); const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'un', parent_id: folder1.id }); const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
let note2 = await Note.save({ title: 'deux', parent_id: folder1.id }); let note2 = await Note.save({ title: 'deux', parent_id: folder1.id });
await synchronizer().start(); await synchronizer().start();
@ -1570,12 +1570,12 @@ describe('synchronizer', function() {
await synchronizer().start(); await synchronizer().start();
// The shared note should be decrypted // The shared note should be decrypted
let note2_2 = await Note.load(note2.id); const note2_2 = await Note.load(note2.id);
expect(note2_2.title).toBe('deux'); expect(note2_2.title).toBe('deux');
expect(note2_2.is_shared).toBe(1); expect(note2_2.is_shared).toBe(1);
// The non-shared note should be encrypted // The non-shared note should be encrypted
let note1_2 = await Note.load(note1.id); const note1_2 = await Note.load(note1.id);
expect(note1_2.title).toBe(''); expect(note1_2.title).toBe('');
})); }));

View File

@ -3,7 +3,7 @@
const fs = require('fs-extra'); const fs = require('fs-extra');
const { JoplinDatabase } = require('lib/joplin-database.js'); const { JoplinDatabase } = require('lib/joplin-database.js');
const { DatabaseDriverNode } = require('lib/database-driver-node.js'); const { DatabaseDriverNode } = require('lib/database-driver-node.js');
const { BaseApplication }= require('lib/BaseApplication.js'); const { BaseApplication } = require('lib/BaseApplication.js');
const BaseModel = require('lib/BaseModel.js'); const BaseModel = require('lib/BaseModel.js');
const Folder = require('lib/models/Folder.js'); const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js'); const Note = require('lib/models/Note.js');
@ -41,13 +41,13 @@ const KvStore = require('lib/services/KvStore.js');
const WebDavApi = require('lib/WebDavApi'); const WebDavApi = require('lib/WebDavApi');
const DropboxApi = require('lib/DropboxApi'); const DropboxApi = require('lib/DropboxApi');
let databases_ = []; const databases_ = [];
let synchronizers_ = []; const synchronizers_ = [];
let encryptionServices_ = []; const encryptionServices_ = [];
let revisionServices_ = []; const revisionServices_ = [];
let decryptionWorkers_ = []; const decryptionWorkers_ = [];
let resourceServices_ = []; const resourceServices_ = [];
let kvStores_ = []; const kvStores_ = [];
let fileApi_ = null; let fileApi_ = null;
let currentClient_ = 1; let currentClient_ = 1;
@ -341,7 +341,7 @@ function fileApi() {
function objectsEqual(o1, o2) { function objectsEqual(o1, o2) {
if (Object.getOwnPropertyNames(o1).length !== Object.getOwnPropertyNames(o2).length) return false; if (Object.getOwnPropertyNames(o1).length !== Object.getOwnPropertyNames(o2).length) return false;
for (let n in o1) { for (const n in o1) {
if (!o1.hasOwnProperty(n)) continue; if (!o1.hasOwnProperty(n)) continue;
if (o1[n] !== o2[n]) return false; if (o1[n] !== o2[n]) return false;
} }
@ -427,7 +427,7 @@ function sortedIds(a) {
} }
function at(a, indexes) { function at(a, indexes) {
let out = []; const out = [];
for (let i = 0; i < indexes.length; i++) { for (let i = 0; i < indexes.length; i++) {
out.push(a[indexes[i]]); out.push(a[indexes[i]]);
} }
@ -435,19 +435,19 @@ function at(a, indexes) {
} }
async function createNTestFolders(n) { async function createNTestFolders(n) {
let folders = []; const folders = [];
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
let folder = await Folder.save({ title: 'folder' }); const folder = await Folder.save({ title: 'folder' });
folders.push(folder); folders.push(folder);
} }
return folders; return folders;
} }
async function createNTestNotes(n, folder, tagIds = null, title = 'note') { async function createNTestNotes(n, folder, tagIds = null, title = 'note') {
let notes = []; const notes = [];
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
let title_ = n > 1 ? `${title}${i}` : title; const title_ = n > 1 ? `${title}${i}` : title;
let note = await Note.save({ title: title_, parent_id: folder.id, is_conflict: 0 }); const note = await Note.save({ title: title_, parent_id: folder.id, is_conflict: 0 });
notes.push(note); notes.push(note);
} }
if (tagIds) { if (tagIds) {
@ -459,9 +459,9 @@ async function createNTestNotes(n, folder, tagIds = null, title = 'note') {
} }
async function createNTestTags(n) { async function createNTestTags(n) {
let tags = []; const tags = [];
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
let tag = await Tag.save({ title: 'tag' }); const tag = await Tag.save({ title: 'tag' });
tags.push(tag); tags.push(tag);
} }
return tags; return tags;

View File

@ -290,8 +290,8 @@
// option to clip pages as HTML. // option to clip pages as HTML.
function getStyleSheets(doc) { function getStyleSheets(doc) {
const output = []; const output = [];
for (var i=0; i<doc.styleSheets.length; i++) { for (let i = 0; i < doc.styleSheets.length; i++) {
var sheet = doc.styleSheets[i]; const sheet = doc.styleSheets[i];
try { try {
for (const cssRule of sheet.cssRules) { for (const cssRule of sheet.cssRules) {
output.push({ type: 'text', value: cssRule.cssText }); output.push({ type: 'text', value: cssRule.cssText });
@ -530,7 +530,7 @@
} else if (command.name === 'pageUrl') { } else if (command.name === 'pageUrl') {
let url = pageLocationOrigin() + location.pathname + location.search; const url = pageLocationOrigin() + location.pathname + location.search;
return clippedContentResponse(pageTitle(), url, getImageSizes(document), getAnchorNames(document)); return clippedContentResponse(pageTitle(), url, getImageSizes(document), getAnchorNames(document));
} else { } else {

View File

@ -18,7 +18,7 @@ require('../config/env');
const jest = require('jest'); const jest = require('jest');
const execSync = require('child_process').execSync; const execSync = require('child_process').execSync;
let argv = process.argv.slice(2); const argv = process.argv.slice(2);
function isInGitRepository() { function isInGitRepository() {
try { try {

View File

@ -85,7 +85,7 @@ class Application extends BaseApplication {
const currentRoute = state.route; const currentRoute = state.route;
newState = Object.assign({}, state); newState = Object.assign({}, state);
let newNavHistory = state.navHistory.slice(); const newNavHistory = state.navHistory.slice();
if (goingBack) { if (goingBack) {
let newAction = null; let newAction = null;
@ -115,7 +115,7 @@ class Application extends BaseApplication {
{ {
newState = Object.assign({}, state); newState = Object.assign({}, state);
let command = Object.assign({}, action); const command = Object.assign({}, action);
delete command.type; delete command.type;
newState.windowCommand = command.name ? command : null; newState.windowCommand = command.name ? command : null;
} }
@ -143,13 +143,13 @@ class Application extends BaseApplication {
const currentLayoutIndex = paneOptions.indexOf(currentLayout); const currentLayoutIndex = paneOptions.indexOf(currentLayout);
const nextLayoutIndex = currentLayoutIndex === paneOptions.length - 1 ? 0 : currentLayoutIndex + 1; const nextLayoutIndex = currentLayoutIndex === paneOptions.length - 1 ? 0 : currentLayoutIndex + 1;
let nextLayout = paneOptions[nextLayoutIndex]; const nextLayout = paneOptions[nextLayoutIndex];
return nextLayout === 'both' ? ['editor', 'viewer'] : [nextLayout]; return nextLayout === 'both' ? ['editor', 'viewer'] : [nextLayout];
}; };
newState = Object.assign({}, state); newState = Object.assign({}, state);
let panes = state.noteVisiblePanes.slice(); const panes = state.noteVisiblePanes.slice();
newState.noteVisiblePanes = getNextLayout(panes); newState.noteVisiblePanes = getNextLayout(panes);
} }
break; break;
@ -328,7 +328,7 @@ class Application extends BaseApplication {
const sortNoteFolderItems = (type) => { const sortNoteFolderItems = (type) => {
const sortItems = []; const sortItems = [];
const sortOptions = Setting.enumOptions(`${type}.sortOrder.field`); const sortOptions = Setting.enumOptions(`${type}.sortOrder.field`);
for (let field in sortOptions) { for (const field in sortOptions) {
if (!sortOptions.hasOwnProperty(field)) continue; if (!sortOptions.hasOwnProperty(field)) continue;
sortItems.push({ sortItems.push({
label: sortOptions[field], label: sortOptions[field],
@ -650,7 +650,7 @@ class Application extends BaseApplication {
gitInfo = _('Revision: %s (%s)', p.git.hash, p.git.branch); gitInfo = _('Revision: %s (%s)', p.git.hash, p.git.branch);
} }
const copyrightText = 'Copyright © 2016-YYYY Laurent Cozic'; const copyrightText = 'Copyright © 2016-YYYY Laurent Cozic';
let message = [ const message = [
p.description, p.description,
'', '',
copyrightText.replace('YYYY', new Date().getFullYear()), copyrightText.replace('YYYY', new Date().getFullYear()),
@ -1119,7 +1119,7 @@ class Application extends BaseApplication {
const pluginMenuItems = PluginManager.instance().menuItems(); const pluginMenuItems = PluginManager.instance().menuItems();
for (const item of pluginMenuItems) { for (const item of pluginMenuItems) {
let itemParent = rootMenus[item.parent] ? rootMenus[item.parent] : 'tools'; const itemParent = rootMenus[item.parent] ? rootMenus[item.parent] : 'tools';
itemParent.submenu.push(item); itemParent.submenu.push(item);
} }
@ -1155,7 +1155,7 @@ class Application extends BaseApplication {
} }
// Remove empty separator for now empty sections // Remove empty separator for now empty sections
let temp = []; const temp = [];
let previous = null; let previous = null;
for (let i = 0; i < output.length; i++) { for (let i = 0; i < output.length; i++) {
const t = Object.assign({}, output[i]); const t = Object.assign({}, output[i]);
@ -1171,7 +1171,7 @@ class Application extends BaseApplication {
return output; return output;
} }
let screenTemplate = removeUnwantedItems(template, screen); const screenTemplate = removeUnwantedItems(template, screen);
const menu = Menu.buildFromTemplate(screenTemplate); const menu = Menu.buildFromTemplate(screenTemplate);
Menu.setApplicationMenu(menu); Menu.setApplicationMenu(menu);

View File

@ -57,7 +57,7 @@ class ClipperConfigScreenComponent extends React.Component {
backgroundColor: theme.backgroundColor, backgroundColor: theme.backgroundColor,
}; };
let webClipperStatusComps = []; const webClipperStatusComps = [];
if (this.props.clipperServerAutoStart) { if (this.props.clipperServerAutoStart) {
webClipperStatusComps.push( webClipperStatusComps.push(

View File

@ -92,8 +92,8 @@ class ConfigScreenComponent extends React.Component {
} }
keyValueToArray(kv) { keyValueToArray(kv) {
let output = []; const output = [];
for (let k in kv) { for (const k in kv) {
if (!kv.hasOwnProperty(k)) continue; if (!kv.hasOwnProperty(k)) continue;
output.push({ output.push({
key: k, key: k,
@ -205,7 +205,7 @@ class ConfigScreenComponent extends React.Component {
} }
let advancedSettingsButton = null; let advancedSettingsButton = null;
let advancedSettingsSectionStyle = { display: 'none' }; const advancedSettingsSectionStyle = { display: 'none' };
if (advancedSettingComps.length) { if (advancedSettingComps.length) {
const iconName = this.state.showAdvancedSettings ? 'fa fa-toggle-up' : 'fa fa-toggle-down'; const iconName = this.state.showAdvancedSettings ? 'fa fa-toggle-up' : 'fa fa-toggle-down';
@ -227,7 +227,7 @@ class ConfigScreenComponent extends React.Component {
settingToComponent(key, value) { settingToComponent(key, value) {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
let output = null; const output = null;
const rowStyle = this.rowStyle_; const rowStyle = this.rowStyle_;
@ -283,9 +283,9 @@ class ConfigScreenComponent extends React.Component {
const descriptionComp = descriptionText ? <div style={descriptionStyle}>{descriptionText}</div> : null; const descriptionComp = descriptionText ? <div style={descriptionStyle}>{descriptionText}</div> : null;
if (md.isEnum) { if (md.isEnum) {
let items = []; const items = [];
const settingOptions = md.options(); const settingOptions = md.options();
let array = this.keyValueToArray(settingOptions); const array = this.keyValueToArray(settingOptions);
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
const e = array[i]; const e = array[i];
items.push( items.push(
@ -547,7 +547,7 @@ class ConfigScreenComponent extends React.Component {
} }
); );
let settings = this.state.settings; const settings = this.state.settings;
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0, display: 'flex', flex: 1 }); const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0, display: 'flex', flex: 1 });

View File

@ -149,7 +149,7 @@ class EncryptionConfigScreenComponent extends React.Component {
}); });
const mkComps = []; const mkComps = [];
let nonExistingMasterKeyIds = this.props.notLoadedMasterKeys.slice(); const nonExistingMasterKeyIds = this.props.notLoadedMasterKeys.slice();
for (let i = 0; i < masterKeys.length; i++) { for (let i = 0; i < masterKeys.length; i++) {
const mk = masterKeys[i]; const mk = masterKeys[i];

View File

@ -149,7 +149,7 @@ class HeaderComponent extends React.Component {
} }
const isEnabled = !('enabled' in options) || options.enabled; const isEnabled = !('enabled' in options) || options.enabled;
let classes = ['button']; const classes = ['button'];
if (!isEnabled) classes.push('disabled'); if (!isEnabled) classes.push('disabled');
const finalStyle = Object.assign({}, style, { const finalStyle = Object.assign({}, style, {

View File

@ -15,7 +15,7 @@ class HelpButtonComponent extends React.Component {
render() { render() {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
let style = Object.assign({}, this.props.style, { color: theme.color, textDecoration: 'none' }); const style = Object.assign({}, this.props.style, { color: theme.color, textDecoration: 'none' });
const helpIconStyle = { flex: 0, width: 16, height: 16, marginLeft: 10 }; const helpIconStyle = { flex: 0, width: 16, height: 16, marginLeft: 10 };
const extraProps = {}; const extraProps = {};
if (this.props.tip) extraProps['data-tip'] = this.props.tip; if (this.props.tip) extraProps['data-tip'] = this.props.tip;

View File

@ -46,9 +46,9 @@ class ImportScreenComponent extends React.Component {
} }
uniqueMessages() { uniqueMessages() {
let output = []; const output = [];
const messages = this.state.messages.slice(); const messages = this.state.messages.slice();
let foundKeys = []; const foundKeys = [];
for (let i = messages.length - 1; i >= 0; i--) { for (let i = messages.length - 1; i >= 0; i--) {
const msg = messages[i]; const msg = messages[i];
if (foundKeys.indexOf(msg.key) >= 0) continue; if (foundKeys.indexOf(msg.key) >= 0) continue;
@ -68,7 +68,7 @@ class ImportScreenComponent extends React.Component {
const options = { const options = {
onProgress: progressState => { onProgress: progressState => {
let line = []; const line = [];
line.push(_('Found: %d.', progressState.loaded)); line.push(_('Found: %d.', progressState.loaded));
line.push(_('Created: %d.', progressState.created)); line.push(_('Created: %d.', progressState.created));
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated)); if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));

View File

@ -83,7 +83,7 @@ class ItemList extends React.Component {
return <div key={key} style={{ height: height }}></div>; return <div key={key} style={{ height: height }}></div>;
}; };
let itemComps = [blankItem('top', this.state.topItemIndex * this.props.itemHeight)]; const itemComps = [blankItem('top', this.state.topItemIndex * this.props.itemHeight)];
for (let i = this.state.topItemIndex; i <= this.state.bottomItemIndex; i++) { for (let i = this.state.topItemIndex; i <= this.state.bottomItemIndex; i++) {
const itemComp = this.props.itemRenderer(items[i]); const itemComp = this.props.itemRenderer(items[i]);
@ -92,7 +92,7 @@ class ItemList extends React.Component {
itemComps.push(blankItem('bottom', (items.length - this.state.bottomItemIndex - 1) * this.props.itemHeight)); itemComps.push(blankItem('bottom', (items.length - this.state.bottomItemIndex - 1) * this.props.itemHeight));
let classes = ['item-list']; const classes = ['item-list'];
if (this.props.className) classes.push(this.props.className); if (this.props.className) classes.push(this.props.className);
return ( return (

View File

@ -324,7 +324,7 @@ class MainScreenComponent extends React.Component {
} else if (command.name === 'editAlarm') { } else if (command.name === 'editAlarm') {
const note = await Note.load(command.noteId); const note = await Note.load(command.noteId);
let defaultDate = new Date(Date.now() + 2 * 3600 * 1000); const defaultDate = new Date(Date.now() + 2 * 3600 * 1000);
defaultDate.setMinutes(0); defaultDate.setMinutes(0);
defaultDate.setSeconds(0); defaultDate.setSeconds(0);

View File

@ -7,7 +7,7 @@ class NavigatorComponent extends Component {
UNSAFE_componentWillReceiveProps(newProps) { UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.route) { if (newProps.route) {
const screenInfo = this.props.screens[newProps.route.routeName]; const screenInfo = this.props.screens[newProps.route.routeName];
let windowTitle = ['Joplin']; const windowTitle = ['Joplin'];
if (screenInfo.title) { if (screenInfo.title) {
windowTitle.push(screenInfo.title()); windowTitle.push(screenInfo.title());
} }

View File

@ -64,7 +64,7 @@ export default function NoteContentPropertiesDialog(props:NoteContentPropertiesD
}; };
if (textProperties) { if (textProperties) {
for (let key in textProperties) { for (const key in textProperties) {
if (!textProperties.hasOwnProperty(key)) continue; if (!textProperties.hasOwnProperty(key)) continue;
const comp = createItemField(key, textProperties[key]); const comp = createItemField(key, textProperties[key]);
textComps.push(comp); textComps.push(comp);

View File

@ -34,7 +34,7 @@ class NoteListComponent extends React.Component {
// Pull request: https://github.com/laurent22/joplin/pull/2062 // Pull request: https://github.com/laurent22/joplin/pull/2062
const itemWidth = '100%'; const itemWidth = '100%';
let style = { const style = {
root: { root: {
backgroundColor: theme.backgroundColor, backgroundColor: theme.backgroundColor,
}, },
@ -184,7 +184,7 @@ class NoteListComponent extends React.Component {
listItemTitleStyle.paddingLeft = !checkbox ? hPadding : 4; listItemTitleStyle.paddingLeft = !checkbox ? hPadding : 4;
if (item.is_todo && !!item.todo_completed) listItemTitleStyle = Object.assign(listItemTitleStyle, this.style().listItemTitleCompleted); if (item.is_todo && !!item.todo_completed) listItemTitleStyle = Object.assign(listItemTitleStyle, this.style().listItemTitleCompleted);
let displayTitle = Note.displayTitle(item); const displayTitle = Note.displayTitle(item);
let titleComp = null; let titleComp = null;
if (highlightedWords.length) { if (highlightedWords.length) {
@ -435,7 +435,7 @@ class NoteListComponent extends React.Component {
render() { render() {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
const style = this.props.style; const style = this.props.style;
let notes = this.props.notes.slice(); const notes = this.props.notes.slice();
if (!notes.length) { if (!notes.length) {
const padding = 10; const padding = 10;

View File

@ -361,7 +361,7 @@ class NotePropertiesDialog extends React.Component {
const noteComps = []; const noteComps = [];
if (formNote) { if (formNote) {
for (let key in formNote) { for (const key in formNote) {
if (!formNote.hasOwnProperty(key)) continue; if (!formNote.hasOwnProperty(key)) continue;
const comp = this.createNoteField(key, formNote[key]); const comp = this.createNoteField(key, formNote[key]);
noteComps.push(comp); noteComps.push(comp);

View File

@ -40,7 +40,7 @@ class NoteRevisionViewerComponent extends React.PureComponent {
style() { style() {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
let style = { const style = {
root: { root: {
backgroundColor: theme.backgroundColor, backgroundColor: theme.backgroundColor,
display: 'flex', display: 'flex',

View File

@ -19,7 +19,7 @@ class NoteSearchBarComponent extends React.Component {
style() { style() {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
let style = { const style = {
root: Object.assign({}, theme.textStyle, { root: Object.assign({}, theme.textStyle, {
backgroundColor: theme.backgroundColor, backgroundColor: theme.backgroundColor,
color: theme.colorFaded, color: theme.colorFaded,
@ -130,7 +130,7 @@ class NoteSearchBarComponent extends React.Component {
if (this.backgroundColor === undefined) { if (this.backgroundColor === undefined) {
this.backgroundColor = theme.backgroundColor; this.backgroundColor = theme.backgroundColor;
} }
let buttonEnabled = (this.backgroundColor === theme.backgroundColor); const buttonEnabled = (this.backgroundColor === theme.backgroundColor);
const closeButton = this.buttonIconComponent('fa-times', this.closeButton_click, true); const closeButton = this.buttonIconComponent('fa-times', this.closeButton_click, true);
const previousButton = this.buttonIconComponent('fa-chevron-up', this.previousButton_click, buttonEnabled); const previousButton = this.buttonIconComponent('fa-chevron-up', this.previousButton_click, buttonEnabled);

View File

@ -7,7 +7,7 @@ class NoteStatusBarComponent extends React.Component {
style() { style() {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
let style = { const style = {
root: Object.assign({}, theme.textStyle, { root: Object.assign({}, theme.textStyle, {
backgroundColor: theme.backgroundColor, backgroundColor: theme.backgroundColor,
color: theme.colorFaded, color: theme.colorFaded,

View File

@ -543,22 +543,22 @@ class NoteTextComponent extends React.Component {
this.setState({ loading: true }); this.setState({ loading: true });
const stateNoteId = this.state.note ? this.state.note.id : null; const stateNoteId = this.state.note ? this.state.note.id : null;
let noteId = props.noteId; const noteId = props.noteId;
let parentFolder = null; let parentFolder = null;
const isProvisionalNote = this.props.provisionalNoteIds.includes(noteId); const isProvisionalNote = this.props.provisionalNoteIds.includes(noteId);
let scrollPercent = this.props.lastEditorScrollPercents[noteId]; let scrollPercent = this.props.lastEditorScrollPercents[noteId];
if (!scrollPercent) scrollPercent = 0; if (!scrollPercent) scrollPercent = 0;
let loadingNewNote = stateNoteId !== noteId; const loadingNewNote = stateNoteId !== noteId;
this.lastLoadedNoteId_ = noteId; this.lastLoadedNoteId_ = noteId;
let note = noteId ? await Note.load(noteId) : null; const note = noteId ? await Note.load(noteId) : null;
if (noteId !== this.lastLoadedNoteId_) return defer(); // Race condition - current note was changed while this one was loading if (noteId !== this.lastLoadedNoteId_) return defer(); // Race condition - current note was changed while this one was loading
if (options.noReloadIfLocalChanges && this.isModified()) return defer(); if (options.noReloadIfLocalChanges && this.isModified()) return defer();
// If the note hasn't been changed, exit now // If the note hasn't been changed, exit now
if (this.state.note && note) { if (this.state.note && note) {
let diff = Note.diffObjects(this.state.note, note); const diff = Note.diffObjects(this.state.note, note);
delete diff.type_; delete diff.type_;
if (!Object.getOwnPropertyNames(diff).length) return defer(); if (!Object.getOwnPropertyNames(diff).length) return defer();
} }
@ -622,7 +622,7 @@ class NoteTextComponent extends React.Component {
parentFolder = Folder.byId(props.folders, note.parent_id); parentFolder = Folder.byId(props.folders, note.parent_id);
} }
let newState = { const newState = {
note: note, note: note,
lastSavedNote: Object.assign({}, note), lastSavedNote: Object.assign({}, note),
webviewReady: webviewReady, webviewReady: webviewReady,
@ -686,9 +686,9 @@ class NoteTextComponent extends React.Component {
for (let i = 0; i < newTags.length; ++i) { for (let i = 0; i < newTags.length; ++i) {
let found = false; let found = false;
let currNewTag = newTags[i]; const currNewTag = newTags[i];
for (let j = 0; j < oldTags.length; ++j) { for (let j = 0; j < oldTags.length; ++j) {
let currOldTag = oldTags[j]; const currOldTag = oldTags[j];
if (currOldTag.id === currNewTag.id) { if (currOldTag.id === currNewTag.id) {
found = true; found = true;
if (currOldTag.updated_time !== currNewTag.updated_time) { if (currOldTag.updated_time !== currNewTag.updated_time) {
@ -1299,7 +1299,7 @@ class NoteTextComponent extends React.Component {
try { try {
if (!this.state.note && !args.noteIds) throw new Error('No notes selected for pdf export'); if (!this.state.note && !args.noteIds) throw new Error('No notes selected for pdf export');
let noteIds = args.noteIds ? args.noteIds : [this.state.note.id]; const noteIds = args.noteIds ? args.noteIds : [this.state.note.id];
let path = null; let path = null;
if (noteIds.length === 1) { if (noteIds.length === 1) {
@ -1452,14 +1452,14 @@ class NoteTextComponent extends React.Component {
if (selection && selection.start !== selection.end) { if (selection && selection.start !== selection.end) {
const selectedLines = replacementText !== null ? replacementText : this.state.note.body.substr(selection.start, selection.end - selection.start); const selectedLines = replacementText !== null ? replacementText : this.state.note.body.substr(selection.start, selection.end - selection.start);
let selectedStrings = byLine ? selectedLines.split(/\r?\n/) : [selectedLines]; const selectedStrings = byLine ? selectedLines.split(/\r?\n/) : [selectedLines];
newBody = this.state.note.body.substr(0, selection.start); newBody = this.state.note.body.substr(0, selection.start);
for (let i = 0; i < selectedStrings.length; i++) { for (let i = 0; i < selectedStrings.length; i++) {
if (byLine == false) { if (byLine == false) {
let start = selectedStrings[i].search(/[^\s]/); const start = selectedStrings[i].search(/[^\s]/);
let end = selectedStrings[i].search(/[^\s](?=[\s]*$)/); const end = selectedStrings[i].search(/[^\s](?=[\s]*$)/);
newBody += selectedStrings[i].substr(0, start) + string1 + selectedStrings[i].substr(start, end - start + 1) + string2 + selectedStrings[i].substr(end + 1); newBody += selectedStrings[i].substr(0, start) + string1 + selectedStrings[i].substr(start, end - start + 1) + string2 + selectedStrings[i].substr(end + 1);
if (this.state.note.body.substr(selection.end) === '') newBody = newBody.trim(); if (this.state.note.body.substr(selection.end) === '') newBody = newBody.trim();
} else { newBody += string1 + selectedStrings[i] + string2; } } else { newBody += string1 + selectedStrings[i] + string2; }
@ -1498,7 +1498,7 @@ class NoteTextComponent extends React.Component {
editor.focus(); editor.focus();
}); });
} else { } else {
let middleText = replacementText !== null ? replacementText : defaultText; const middleText = replacementText !== null ? replacementText : defaultText;
const textOffset = this.currentTextOffset(); const textOffset = this.currentTextOffset();
const s1 = this.state.note.body.substr(0, textOffset); const s1 = this.state.note.body.substr(0, textOffset);
const s2 = this.state.note.body.substr(textOffset); const s2 = this.state.note.body.substr(textOffset);
@ -1541,9 +1541,9 @@ class NoteTextComponent extends React.Component {
toggleWrapSelection(strings1, strings2, defaultText) { toggleWrapSelection(strings1, strings2, defaultText) {
const selection = this.textOffsetSelection(); const selection = this.textOffsetSelection();
let string = this.state.note.body.substr(selection.start, selection.end - selection.start); const string = this.state.note.body.substr(selection.start, selection.end - selection.start);
let replaced = false; let replaced = false;
for (var i = 0; i < strings1.length; i++) { for (let i = 0; i < strings1.length; i++) {
if (string.startsWith(strings1[i]) && string.endsWith(strings1[i])) { if (string.startsWith(strings1[i]) && string.endsWith(strings1[i])) {
this.wrapSelectionWithStrings('', '', '', string.substr(strings1[i].length, selection.end - selection.start - (2 * strings1[i].length))); this.wrapSelectionWithStrings('', '', '', string.substr(strings1[i].length, selection.end - selection.start - (2 * strings1[i].length)));
replaced = true; replaced = true;
@ -1570,10 +1570,10 @@ class NoteTextComponent extends React.Component {
commandTextCode() { commandTextCode() {
const selection = this.textOffsetSelection(); const selection = this.textOffsetSelection();
let string = this.state.note.body.substr(selection.start, selection.end - selection.start); const string = this.state.note.body.substr(selection.start, selection.end - selection.start);
// Look for newlines // Look for newlines
let match = string.match(/\r?\n/); const match = string.match(/\r?\n/);
if (match && match.length > 0) { if (match && match.length > 0) {
// Follow the same newline style // Follow the same newline style
@ -1591,7 +1591,7 @@ class NoteTextComponent extends React.Component {
this.wrapSelectionWithStrings(TemplateUtils.render(value)); this.wrapSelectionWithStrings(TemplateUtils.render(value));
} }
addListItem(string1, string2 = '', defaultText = '', byLine=false) { addListItem(string1, string2 = '', defaultText = '', byLine = false) {
let newLine = '\n'; let newLine = '\n';
const range = this.selectionRange_; const range = this.selectionRange_;
if (!range || (range.start.row === range.end.row && !this.selectionRangeCurrentLine())) { if (!range || (range.start.row === range.end.row && !this.selectionRangeCurrentLine())) {
@ -1949,7 +1949,7 @@ class NoteTextComponent extends React.Component {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
const visiblePanes = this.props.visiblePanes || ['editor', 'viewer']; const visiblePanes = this.props.visiblePanes || ['editor', 'viewer'];
const isTodo = note && !!note.is_todo; const isTodo = note && !!note.is_todo;
var keyboardMode = this.props.keyboardMode; let keyboardMode = this.props.keyboardMode;
if (keyboardMode === 'default' || !keyboardMode) { if (keyboardMode === 'default' || !keyboardMode) {
keyboardMode = null; keyboardMode = null;
} }
@ -2006,7 +2006,7 @@ class NoteTextComponent extends React.Component {
paddingRight: 8, paddingRight: 8,
marginRight: rootStyle.paddingLeft, marginRight: rootStyle.paddingLeft,
color: theme.textStyle.color, color: theme.textStyle.color,
fontSize: theme.textStyle.fontSize * 1.25 *1.5, fontSize: theme.textStyle.fontSize * 1.25 * 1.5,
backgroundColor: theme.backgroundColor, backgroundColor: theme.backgroundColor,
border: '1px solid', border: '1px solid',
borderColor: theme.dividerColor, borderColor: theme.dividerColor,
@ -2083,11 +2083,11 @@ class NoteTextComponent extends React.Component {
} }
if (this.state.webviewReady && this.webviewRef_.current) { if (this.state.webviewReady && this.webviewRef_.current) {
let html = this.state.bodyHtml; const html = this.state.bodyHtml;
const htmlHasChanged = this.lastSetHtml_ !== html; const htmlHasChanged = this.lastSetHtml_ !== html;
if (htmlHasChanged) { if (htmlHasChanged) {
let options = { const options = {
pluginAssets: this.state.lastRenderPluginAssets, pluginAssets: this.state.lastRenderPluginAssets,
downloadResources: Setting.value('sync.resourceDownloadMode'), downloadResources: Setting.value('sync.resourceDownloadMode'),
}; };

View File

@ -57,7 +57,7 @@ class NoteTextViewerComponent extends React.Component {
}; };
} }
for (let n in this.webviewListeners_) { for (const n in this.webviewListeners_) {
if (!this.webviewListeners_.hasOwnProperty(n)) continue; if (!this.webviewListeners_.hasOwnProperty(n)) continue;
const fn = this.webviewListeners_[n]; const fn = this.webviewListeners_[n];
wv.addEventListener(n, fn); wv.addEventListener(n, fn);
@ -70,7 +70,7 @@ class NoteTextViewerComponent extends React.Component {
const wv = this.webviewRef_.current; const wv = this.webviewRef_.current;
if (!wv || !this.initialized_) return; if (!wv || !this.initialized_) return;
for (let n in this.webviewListeners_) { for (const n in this.webviewListeners_) {
if (!this.webviewListeners_.hasOwnProperty(n)) continue; if (!this.webviewListeners_.hasOwnProperty(n)) continue;
const fn = this.webviewListeners_[n]; const fn = this.webviewListeners_[n];
wv.removeEventListener(n, fn); wv.removeEventListener(n, fn);

View File

@ -73,7 +73,7 @@ export default function ShareNoteDialog(props:ShareNoteDialogProps) {
useEffect(() => { useEffect(() => {
async function fetchNotes() { async function fetchNotes() {
const result = []; const result = [];
for (let noteId of props.noteIds) { for (const noteId of props.noteIds) {
result.push(await Note.load(noteId)); result.push(await Note.load(noteId));
} }
setNotes(result); setNotes(result);
@ -180,7 +180,7 @@ export default function ShareNoteDialog(props:ShareNoteDialogProps) {
const renderNoteList = (notes:any) => { const renderNoteList = (notes:any) => {
const noteComps = []; const noteComps = [];
for (let noteId of Object.keys(notes)) { for (const noteId of Object.keys(notes)) {
noteComps.push(renderNote(notes[noteId])); noteComps.push(renderNote(notes[noteId]));
} }
return <div style={styles.noteList}>{noteComps}</div>; return <div style={styles.noteList}>{noteComps}</div>;

View File

@ -107,7 +107,7 @@ class SideBarComponent extends React.Component {
const itemHeight = 25; const itemHeight = 25;
let style = { const style = {
root: { root: {
backgroundColor: theme.backgroundColor2, backgroundColor: theme.backgroundColor2,
}, },
@ -459,8 +459,8 @@ class SideBarComponent extends React.Component {
let containerStyle = Object.assign({}, this.style(depth).listItemContainer); let containerStyle = Object.assign({}, this.style(depth).listItemContainer);
if (selected) containerStyle = Object.assign(containerStyle, this.style().listItemSelected); if (selected) containerStyle = Object.assign(containerStyle, this.style().listItemSelected);
let expandLinkStyle = Object.assign({}, this.style().listItemExpandIcon); const expandLinkStyle = Object.assign({}, this.style().listItemExpandIcon);
let expandIconStyle = { const expandIconStyle = {
visibility: hasChildren ? 'visible' : 'hidden', visibility: hasChildren ? 'visible' : 'hidden',
paddingLeft: 8 + depth * 10, paddingLeft: 8 + depth * 10,
}; };
@ -562,18 +562,18 @@ class SideBarComponent extends React.Component {
style.cursor = 'pointer'; style.cursor = 'pointer';
} }
let headerClick = extraProps.onClick || null; const headerClick = extraProps.onClick || null;
delete extraProps.onClick; delete extraProps.onClick;
// check if toggling option is set. // check if toggling option is set.
let toggleIcon = null; let toggleIcon = null;
const toggleKey = `${key}IsExpanded`; const toggleKey = `${key}IsExpanded`;
if (extraProps.toggleblock) { if (extraProps.toggleblock) {
let isExpanded = this.state[toggleKey]; const isExpanded = this.state[toggleKey];
toggleIcon = <i className={`fa ${isExpanded ? 'fa-chevron-down' : 'fa-chevron-left'}`} style={{ fontSize: style.fontSize * 0.75, marginRight: 12, marginLeft: 5, marginTop: style.fontSize * 0.125 }}></i>; toggleIcon = <i className={`fa ${isExpanded ? 'fa-chevron-down' : 'fa-chevron-left'}`} style={{ fontSize: style.fontSize * 0.75, marginRight: 12, marginLeft: 5, marginTop: style.fontSize * 0.125 }}></i>;
} }
if (extraProps.selected) { if (extraProps.selected) {
style.backgroundColor =this.style().listItemSelected.backgroundColor; style.backgroundColor = this.style().listItemSelected.backgroundColor;
} }
const ref = this.anchorItemRef('headers', key); const ref = this.anchorItemRef('headers', key);
@ -645,7 +645,7 @@ class SideBarComponent extends React.Component {
const focusItem = focusItems[newIndex]; const focusItem = focusItems[newIndex];
let actionName = `${focusItem.type.toUpperCase()}_SELECT`; const actionName = `${focusItem.type.toUpperCase()}_SELECT`;
this.props.dispatch({ this.props.dispatch({
type: actionName, type: actionName,
@ -712,7 +712,7 @@ class SideBarComponent extends React.Component {
const style = Object.assign({}, this.style().button, { marginBottom: 5 }); const style = Object.assign({}, this.style().button, { marginBottom: 5 });
const iconName = 'fa-refresh'; const iconName = 'fa-refresh';
const label = type === 'sync' ? _('Synchronise') : _('Cancel'); const label = type === 'sync' ? _('Synchronise') : _('Cancel');
let iconStyle = { fontSize: style.fontSize, marginRight: 5 }; const iconStyle = { fontSize: style.fontSize, marginRight: 5 };
if (type !== 'sync') { if (type !== 'sync') {
iconStyle.animation = 'icon-infinite-rotation 1s linear infinite'; iconStyle.animation = 'icon-infinite-rotation 1s linear infinite';
@ -743,7 +743,7 @@ class SideBarComponent extends React.Component {
flexDirection: 'column', flexDirection: 'column',
}); });
let items = []; const items = [];
items.push( items.push(
this.makeHeader('allNotesHeader', _('All notes'), 'fa-clone', { this.makeHeader('allNotesHeader', _('All notes'), 'fa-clone', {
onClick: this.onAllNotesClick_, onClick: this.onAllNotesClick_,
@ -798,7 +798,7 @@ class SideBarComponent extends React.Component {
resourceFetcherText = _('Fetching resources: %d/%d', this.props.resourceFetcher.fetchingCount, this.props.resourceFetcher.toFetchCount); resourceFetcherText = _('Fetching resources: %d/%d', this.props.resourceFetcher.fetchingCount, this.props.resourceFetcher.toFetchCount);
} }
let lines = Synchronizer.reportToLines(this.props.syncReport); const lines = Synchronizer.reportToLines(this.props.syncReport);
if (resourceFetcherText) lines.push(resourceFetcherText); if (resourceFetcherText) lines.push(resourceFetcherText);
if (decryptionReportText) lines.push(decryptionReportText); if (decryptionReportText) lines.push(decryptionReportText);
const syncReportText = []; const syncReportText = [];

View File

@ -64,13 +64,13 @@ class StatusScreenComponent extends React.Component {
} }
const renderSectionHtml = (key, section) => { const renderSectionHtml = (key, section) => {
let itemsHtml = []; const itemsHtml = [];
itemsHtml.push(renderSectionTitleHtml(section.title, section.title)); itemsHtml.push(renderSectionTitleHtml(section.title, section.title));
for (let n in section.body) { for (const n in section.body) {
if (!section.body.hasOwnProperty(n)) continue; if (!section.body.hasOwnProperty(n)) continue;
let item = section.body[n]; const item = section.body[n];
let text = ''; let text = '';
let retryLink = null; let retryLink = null;
@ -106,10 +106,10 @@ class StatusScreenComponent extends React.Component {
}; };
function renderBodyHtml(report) { function renderBodyHtml(report) {
let sectionsHtml = []; const sectionsHtml = [];
for (let i = 0; i < report.length; i++) { for (let i = 0; i < report.length; i++) {
let section = report[i]; const section = report[i];
if (!section.body.length) continue; if (!section.body.length) continue;
sectionsHtml.push(renderSectionHtml(i, section)); sectionsHtml.push(renderSectionHtml(i, section));
} }
@ -117,7 +117,7 @@ class StatusScreenComponent extends React.Component {
return <div>{sectionsHtml}</div>; return <div>{sectionsHtml}</div>;
} }
let body = renderBodyHtml(this.state.report); const body = renderBodyHtml(this.state.report);
return ( return (
<div style={style}> <div style={style}>

View File

@ -21,7 +21,7 @@ class ToolbarButton extends React.Component {
} }
const isEnabled = !('enabled' in this.props) || this.props.enabled === true; const isEnabled = !('enabled' in this.props) || this.props.enabled === true;
let classes = ['button']; const classes = ['button'];
if (!isEnabled) classes.push('disabled'); if (!isEnabled) classes.push('disabled');
const finalStyle = Object.assign({}, style, { const finalStyle = Object.assign({}, style, {

View File

@ -100,7 +100,7 @@ app().start(bridge().processArgv()).then(() => {
} else { } else {
// If something goes wrong at this stage we don't have a console or a log file // If something goes wrong at this stage we don't have a console or a log file
// so display the error in a message box. // so display the error in a message box.
let msg = ['Fatal error:', error.message]; const msg = ['Fatal error:', error.message];
if (error.fileName) msg.push(error.fileName); if (error.fileName) msg.push(error.fileName);
if (error.lineNumber) msg.push(error.lineNumber); if (error.lineNumber) msg.push(error.lineNumber);
if (error.stack) msg.push(error.stack); if (error.stack) msg.push(error.stack);

View File

@ -385,13 +385,13 @@ function addExtraStyles(style) {
return style; return style;
} }
let themeCache_ = {}; const themeCache_ = {};
function themeStyle(theme) { function themeStyle(theme) {
if (!theme) throw new Error('Theme must be specified'); if (!theme) throw new Error('Theme must be specified');
var zoomRatio = 1; // Setting.value('style.zoom') / 100; const zoomRatio = 1; // Setting.value('style.zoom') / 100;
var editorFontSize = Setting.value('style.editor.fontSize'); const editorFontSize = Setting.value('style.editor.fontSize');
const cacheKey = [theme, zoomRatio, editorFontSize].join('-'); const cacheKey = [theme, zoomRatio, editorFontSize].join('-');
if (themeCache_[cacheKey]) return themeCache_[cacheKey]; if (themeCache_[cacheKey]) return themeCache_[cacheKey];
@ -399,7 +399,7 @@ function themeStyle(theme) {
// Font size are not theme specific, but they must be referenced // Font size are not theme specific, but they must be referenced
// and computed here to allow them to respond to settings changes // and computed here to allow them to respond to settings changes
// without the need to restart // without the need to restart
let fontSizes = { const fontSizes = {
fontSize: Math.round(globalStyle.fontSize * zoomRatio), fontSize: Math.round(globalStyle.fontSize * zoomRatio),
editorFontSize: editorFontSize, editorFontSize: editorFontSize,
textAreaLineHeight: Math.round(globalStyle.textAreaLineHeight * editorFontSize / 12), textAreaLineHeight: Math.round(globalStyle.textAreaLineHeight * editorFontSize / 12),

View File

@ -7,7 +7,7 @@ const execSync = require('child_process').execSync;
const packageInfo = require(`${__dirname}/../package.json`); const packageInfo = require(`${__dirname}/../package.json`);
module.exports = async function() { module.exports = async function() {
let removeKeys = ['scripts', 'devDependencies', 'optionalDependencies', 'dependencies']; const removeKeys = ['scripts', 'devDependencies', 'optionalDependencies', 'dependencies'];
for (let i = 0; i < removeKeys.length; i++) { for (let i = 0; i < removeKeys.length; i++) {
delete packageInfo[removeKeys[i]]; delete packageInfo[removeKeys[i]];

View File

@ -36,7 +36,7 @@ export default class PluginAssetsLoader {
this.logger().info(`PluginAssetsLoader: Importing assets to ${destDir}`); this.logger().info(`PluginAssetsLoader: Importing assets to ${destDir}`);
try { try {
for (let name in pluginAssets.files) { for (const name in pluginAssets.files) {
const dataBase64 = pluginAssets.files[name].data; const dataBase64 = pluginAssets.files[name].data;
const destPath = `${destDir}/${name}`; const destPath = `${destDir}/${name}`;
await shim.fsDriver().mkdir(dirname(destPath)); await shim.fsDriver().mkdir(dirname(destPath));

View File

@ -16,7 +16,7 @@ ArrayUtils.removeElement = function(array, element) {
// https://stackoverflow.com/a/10264318/561309 // https://stackoverflow.com/a/10264318/561309
ArrayUtils.binarySearch = function(items, value) { ArrayUtils.binarySearch = function(items, value) {
var startIndex = 0, let startIndex = 0,
stopIndex = items.length - 1, stopIndex = items.length - 1,
middle = Math.floor((stopIndex + startIndex) / 2); middle = Math.floor((stopIndex + startIndex) / 2);

View File

@ -111,13 +111,13 @@ class BaseApplication {
// Handles the initial flags passed to main script and // Handles the initial flags passed to main script and
// returns the remaining args. // returns the remaining args.
async handleStartFlags_(argv, setDefaults = true) { async handleStartFlags_(argv, setDefaults = true) {
let matched = {}; const matched = {};
argv = argv.slice(0); argv = argv.slice(0);
argv.splice(0, 2); // First arguments are the node executable, and the node JS file argv.splice(0, 2); // First arguments are the node executable, and the node JS file
while (argv.length) { while (argv.length) {
let arg = argv[0]; const arg = argv[0];
let nextArg = argv.length >= 2 ? argv[1] : null; const nextArg = argv.length >= 2 ? argv[1] : null;
if (arg == '--profile') { if (arg == '--profile') {
if (!nextArg) throw new JoplinError(_('Usage: %s', '--profile <dir-path>'), 'flagError'); if (!nextArg) throw new JoplinError(_('Usage: %s', '--profile <dir-path>'), 'flagError');
@ -245,7 +245,7 @@ class BaseApplication {
this.logger().debug('Refreshing notes:', parentType, parentId); this.logger().debug('Refreshing notes:', parentType, parentId);
let options = { const options = {
order: stateUtils.notesOrder(state.settings), order: stateUtils.notesOrder(state.settings),
uncompletedTodosOnTop: Setting.value('uncompletedTodosOnTop'), uncompletedTodosOnTop: Setting.value('uncompletedTodosOnTop'),
showCompletedTodos: Setting.value('showCompletedTodos'), showCompletedTodos: Setting.value('showCompletedTodos'),
@ -333,7 +333,7 @@ class BaseApplication {
} }
reducerActionToString(action) { reducerActionToString(action) {
let o = [action.type]; const o = [action.type];
if ('id' in action) o.push(action.id); if ('id' in action) o.push(action.id);
if ('noteId' in action) o.push(action.noteId); if ('noteId' in action) o.push(action.noteId);
if ('folderId' in action) o.push(action.folderId); if ('folderId' in action) o.push(action.folderId);
@ -580,7 +580,7 @@ class BaseApplication {
} }
async start(argv) { async start(argv) {
let startFlags = await this.handleStartFlags_(argv); const startFlags = await this.handleStartFlags_(argv);
argv = startFlags.argv; argv = startFlags.argv;
let initArgs = startFlags.matched; let initArgs = startFlags.matched;
@ -712,7 +712,7 @@ class BaseApplication {
SearchEngine.instance().setLogger(reg.logger()); SearchEngine.instance().setLogger(reg.logger());
SearchEngine.instance().scheduleSyncTables(); SearchEngine.instance().scheduleSyncTables();
let currentFolderId = Setting.value('activeFolderId'); const currentFolderId = Setting.value('activeFolderId');
let currentFolder = null; let currentFolder = null;
if (currentFolderId) currentFolder = await Folder.load(currentFolderId); if (currentFolderId) currentFolder = await Folder.load(currentFolderId);
if (!currentFolder) currentFolder = await Folder.defaultFolder(); if (!currentFolder) currentFolder = await Folder.defaultFolder();

View File

@ -16,7 +16,7 @@ class BaseModel {
if (!model) return model; if (!model) return model;
if (Array.isArray(model)) { if (Array.isArray(model)) {
let output = []; const output = [];
for (let i = 0; i < model.length; i++) { for (let i = 0; i < model.length; i++) {
output.push(this.addModelMd(model[i])); output.push(this.addModelMd(model[i]));
} }
@ -87,16 +87,16 @@ class BaseModel {
} }
static hasField(name) { static hasField(name) {
let fields = this.fieldNames(); const fields = this.fieldNames();
return fields.indexOf(name) >= 0; return fields.indexOf(name) >= 0;
} }
static fieldNames(withPrefix = false) { static fieldNames(withPrefix = false) {
let output = this.db().tableFieldNames(this.tableName()); const output = this.db().tableFieldNames(this.tableName());
if (!withPrefix) return output; if (!withPrefix) return output;
let p = withPrefix === true ? this.tableName() : withPrefix; const p = withPrefix === true ? this.tableName() : withPrefix;
let temp = []; const temp = [];
for (let i = 0; i < output.length; i++) { for (let i = 0; i < output.length; i++) {
temp.push(`${p}.${output[i]}`); temp.push(`${p}.${output[i]}`);
} }
@ -105,7 +105,7 @@ class BaseModel {
} }
static fieldType(name, defaultValue = null) { static fieldType(name, defaultValue = null) {
let fields = this.fields(); const fields = this.fields();
for (let i = 0; i < fields.length; i++) { 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;
} }
@ -119,7 +119,7 @@ class BaseModel {
static removeUnknownFields(model) { static removeUnknownFields(model) {
const newModel = {}; const newModel = {};
for (let n in model) { for (const n in model) {
if (!model.hasOwnProperty(n)) continue; if (!model.hasOwnProperty(n)) continue;
if (!this.hasField(n) && n !== 'type_') continue; if (!this.hasField(n) && n !== 'type_') continue;
newModel[n] = model[n]; newModel[n] = model[n];
@ -128,10 +128,10 @@ class BaseModel {
} }
static new() { static new() {
let fields = this.fields(); const fields = this.fields();
let output = {}; const output = {};
for (let i = 0; i < fields.length; i++) { for (let i = 0; i < fields.length; i++) {
let f = fields[i]; const f = fields[i];
output[f.name] = f.default; output[f.name] = f.default;
} }
return output; return output;
@ -175,7 +175,7 @@ class BaseModel {
if (!options) options = {}; if (!options) options = {};
if (options.order && options.order.length) { if (options.order && options.order.length) {
let items = []; const items = [];
for (let i = 0; i < options.order.length; i++) { for (let i = 0; i < options.order.length; i++) {
const o = options.order[i]; const o = options.order[i];
let item = o.by; let item = o.by;
@ -192,7 +192,7 @@ class BaseModel {
} }
static async allIds(options = null) { static async allIds(options = null) {
let q = this.applySqlOptions(options, `SELECT id FROM \`${this.tableName()}\``); const q = this.applySqlOptions(options, `SELECT id FROM \`${this.tableName()}\``);
const rows = await this.db().selectAll(q.sql, q.params); const rows = await this.db().selectAll(q.sql, q.params);
return rows.map(r => r.id); return rows.map(r => r.id);
} }
@ -208,7 +208,7 @@ class BaseModel {
if (options.whereParams) params = params.concat(options.whereParams); if (options.whereParams) params = params.concat(options.whereParams);
} }
let q = this.applySqlOptions(options, sql, params); const q = this.applySqlOptions(options, sql, params);
return this.modelSelectAll(q.sql, q.params); return this.modelSelectAll(q.sql, q.params);
} }
@ -219,7 +219,7 @@ class BaseModel {
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``; let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``;
sql += ` WHERE id IN ("${ids.join('","')}")`; sql += ` WHERE id IN ("${ids.join('","')}")`;
let q = this.applySqlOptions(options, sql); const q = this.applySqlOptions(options, sql);
return this.modelSelectAll(q.sql); return this.modelSelectAll(q.sql);
} }
@ -227,11 +227,11 @@ class BaseModel {
if (!options) options = {}; if (!options) options = {};
if (!options.fields) options.fields = '*'; if (!options.fields) options.fields = '*';
let conditions = options.conditions ? options.conditions.slice(0) : []; const conditions = options.conditions ? options.conditions.slice(0) : [];
let params = options.conditionsParams ? options.conditionsParams.slice(0) : []; const params = options.conditionsParams ? options.conditionsParams.slice(0) : [];
if (options.titlePattern) { if (options.titlePattern) {
let pattern = options.titlePattern.replace(/\*/g, '%'); const pattern = options.titlePattern.replace(/\*/g, '%');
conditions.push('title LIKE ?'); conditions.push('title LIKE ?');
params.push(pattern); params.push(pattern);
} }
@ -241,7 +241,7 @@ class BaseModel {
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``; let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``;
if (conditions.length) sql += ` WHERE ${conditions.join(' AND ')}`; if (conditions.length) sql += ` WHERE ${conditions.join(' AND ')}`;
let query = this.applySqlOptions(options, sql, params); const query = this.applySqlOptions(options, sql, params);
return this.modelSelectAll(query.sql, query.params); return this.modelSelectAll(query.sql, query.params);
} }
@ -277,7 +277,7 @@ class BaseModel {
} }
static diffObjects(oldModel, newModel) { static diffObjects(oldModel, newModel) {
let output = {}; const output = {};
const fields = this.diffObjectsFields(oldModel, newModel); const fields = this.diffObjectsFields(oldModel, newModel);
for (let i = 0; i < fields.length; i++) { for (let i = 0; i < fields.length; i++) {
output[fields[i]] = newModel[fields[i]]; output[fields[i]] = newModel[fields[i]];
@ -287,8 +287,8 @@ class BaseModel {
} }
static diffObjectsFields(oldModel, newModel) { static diffObjectsFields(oldModel, newModel) {
let output = []; const output = [];
for (let n in newModel) { for (const n in newModel) {
if (!newModel.hasOwnProperty(n)) continue; if (!newModel.hasOwnProperty(n)) continue;
if (n == 'type_') continue; if (n == 'type_') continue;
if (!(n in oldModel) || newModel[n] !== oldModel[n]) { if (!(n in oldModel) || newModel[n] !== oldModel[n]) {
@ -313,7 +313,7 @@ class BaseModel {
if (!modelOrId) return noLockMutex; if (!modelOrId) return noLockMutex;
let modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id; const modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id;
if (!modelId) return noLockMutex; if (!modelId) return noLockMutex;
@ -329,11 +329,11 @@ class BaseModel {
if (!release) return; if (!release) return;
if (!modelOrId) return release(); if (!modelOrId) return release();
let modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id; const modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id;
if (!modelId) return release(); if (!modelId) return release();
let mutex = BaseModel.saveMutexes_[modelId]; const mutex = BaseModel.saveMutexes_[modelId];
if (!mutex) return release(); if (!mutex) return release();
delete BaseModel.saveMutexes_[modelId]; delete BaseModel.saveMutexes_[modelId];
@ -342,9 +342,9 @@ class BaseModel {
static saveQuery(o, options) { static saveQuery(o, options) {
let temp = {}; let temp = {};
let fieldNames = this.fieldNames(); const fieldNames = this.fieldNames();
for (let i = 0; i < fieldNames.length; i++) { for (let i = 0; i < fieldNames.length; i++) {
let n = fieldNames[i]; const n = fieldNames[i];
if (n in o) temp[n] = o[n]; if (n in o) temp[n] = o[n];
} }
@ -354,7 +354,7 @@ class BaseModel {
// id also will stay. // id also will stay.
if (!options.isNew && options.fields) { if (!options.isNew && options.fields) {
const filtered = {}; const filtered = {};
for (let k in temp) { for (const k in temp) {
if (!temp.hasOwnProperty(k)) continue; if (!temp.hasOwnProperty(k)) continue;
if (k !== 'id' && options.fields.indexOf(k) < 0) continue; if (k !== 'id' && options.fields.indexOf(k) < 0) continue;
filtered[k] = temp[k]; filtered[k] = temp[k];
@ -404,8 +404,8 @@ class BaseModel {
query = Database.insertQuery(this.tableName(), o); query = Database.insertQuery(this.tableName(), o);
} else { } else {
let where = { id: o.id }; const where = { id: o.id };
let temp = Object.assign({}, o); const temp = Object.assign({}, o);
delete temp.id; delete temp.id;
query = Database.updateQuery(this.tableName(), temp, where); query = Database.updateQuery(this.tableName(), temp, where);
@ -445,8 +445,8 @@ class BaseModel {
o = this.filter(o); o = this.filter(o);
let queries = []; let queries = [];
let saveQuery = this.saveQuery(o, options); const saveQuery = this.saveQuery(o, options);
let modelId = saveQuery.id; const modelId = saveQuery.id;
queries.push(saveQuery); queries.push(saveQuery);
@ -473,7 +473,7 @@ class BaseModel {
o = this.addModelMd(o); o = this.addModelMd(o);
if (isDiffSaving) { if (isDiffSaving) {
for (let n in options.oldItem) { for (const n in options.oldItem) {
if (!options.oldItem.hasOwnProperty(n)) continue; if (!options.oldItem.hasOwnProperty(n)) continue;
if (n in o) continue; if (n in o) continue;
o[n] = options.oldItem[n]; o[n] = options.oldItem[n];
@ -499,7 +499,7 @@ class BaseModel {
} }
static filterArray(models) { static filterArray(models) {
let output = []; const output = [];
for (let i = 0; i < models.length; i++) { for (let i = 0; i < models.length; i++) {
output.push(this.filter(models[i])); output.push(this.filter(models[i]));
} }
@ -509,8 +509,8 @@ class BaseModel {
static filter(model) { static filter(model) {
if (!model) return model; if (!model) return model;
let output = Object.assign({}, model); const output = Object.assign({}, model);
for (let n in output) { for (const n in output) {
if (!output.hasOwnProperty(n)) continue; if (!output.hasOwnProperty(n)) continue;
// The SQLite database doesn't have booleans so cast everything to int // The SQLite database doesn't have booleans so cast everything to int

View File

@ -51,11 +51,11 @@ class DropboxApi {
} }
requestToCurl_(url, options) { requestToCurl_(url, options) {
let output = []; const output = [];
output.push('curl'); output.push('curl');
if (options.method) output.push(`-X ${options.method}`); if (options.method) output.push(`-X ${options.method}`);
if (options.headers) { if (options.headers) {
for (let n in options.headers) { for (const n in options.headers) {
if (!options.headers.hasOwnProperty(n)) continue; if (!options.headers.hasOwnProperty(n)) continue;
output.push(`${'-H ' + '\''}${n}: ${options.headers[n]}'`); output.push(`${'-H ' + '\''}${n}: ${options.headers[n]}'`);
} }
@ -74,10 +74,10 @@ class DropboxApi {
client_secret: this.clientSecret(), client_secret: this.clientSecret(),
}; };
var formBody = []; let formBody = [];
for (var property in postData) { for (const property in postData) {
var encodedKey = encodeURIComponent(property); const encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(postData[property]); const encodedValue = encodeURIComponent(postData[property]);
formBody.push(`${encodedKey}=${encodedValue}`); formBody.push(`${encodedKey}=${encodedValue}`);
} }
formBody = formBody.join('&'); formBody = formBody.join('&');

View File

@ -6,7 +6,7 @@ class EventDispatcher {
dispatch(eventName, event = null) { dispatch(eventName, event = null) {
if (!this.listeners_[eventName]) return; if (!this.listeners_[eventName]) return;
let ls = this.listeners_[eventName]; const ls = this.listeners_[eventName];
for (let i = 0; i < ls.length; i++) { for (let i = 0; i < ls.length; i++) {
ls[i](event); ls[i](event);
} }
@ -20,7 +20,7 @@ class EventDispatcher {
off(eventName, callback) { off(eventName, callback) {
if (!this.listeners_[eventName]) return; if (!this.listeners_[eventName]) return;
let ls = this.listeners_[eventName]; const ls = this.listeners_[eventName];
for (let i = 0; i < ls.length; i++) { for (let i = 0; i < ls.length; i++) {
if (ls[i] === callback) { if (ls[i] === callback) {
ls.splice(i, 1); ls.splice(i, 1);

View File

@ -83,12 +83,12 @@ export default class JoplinServerApi {
} }
requestToCurl_(url:string, options:any) { requestToCurl_(url:string, options:any) {
let output = []; const output = [];
output.push('curl'); output.push('curl');
output.push('-v'); output.push('-v');
if (options.method) output.push(`-X ${options.method}`); if (options.method) output.push(`-X ${options.method}`);
if (options.headers) { if (options.headers) {
for (let n in options.headers) { for (const n in options.headers) {
if (!options.headers.hasOwnProperty(n)) continue; if (!options.headers.hasOwnProperty(n)) continue;
output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`); output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`);
} }
@ -129,7 +129,7 @@ export default class JoplinServerApi {
const responseText = await response.text(); const responseText = await response.text();
let responseJson_:any = null; const responseJson_:any = null;
const loadResponseJson = async () => { const loadResponseJson = async () => {
if (!responseText) return null; if (!responseText) return null;
if (responseJson_) return responseJson_; if (responseJson_) return responseJson_;

View File

@ -2,7 +2,7 @@ const ObjectUtils = {};
ObjectUtils.sortByValue = function(object) { ObjectUtils.sortByValue = function(object) {
const temp = []; const temp = [];
for (let k in object) { for (const k in object) {
if (!object.hasOwnProperty(k)) continue; if (!object.hasOwnProperty(k)) continue;
temp.push({ temp.push({
key: k, key: k,
@ -31,7 +31,7 @@ ObjectUtils.sortByValue = function(object) {
ObjectUtils.fieldsEqual = function(o1, o2) { ObjectUtils.fieldsEqual = function(o1, o2) {
if ((!o1 || !o2) && o1 !== o2) return false; if ((!o1 || !o2) && o1 !== o2) return false;
for (let k in o1) { for (const k in o1) {
if (!o1.hasOwnProperty(k)) continue; if (!o1.hasOwnProperty(k)) continue;
if (o1[k] !== o2[k]) return false; if (o1[k] !== o2[k]) return false;
} }
@ -46,7 +46,7 @@ ObjectUtils.fieldsEqual = function(o1, o2) {
ObjectUtils.convertValuesToFunctions = function(o) { ObjectUtils.convertValuesToFunctions = function(o) {
const output = {}; const output = {};
for (let n in o) { for (const n in o) {
if (!o.hasOwnProperty(n)) continue; if (!o.hasOwnProperty(n)) continue;
output[n] = () => { output[n] = () => {
return typeof o[n] === 'function' ? o[n]() : o[n]; return typeof o[n] === 'function' ? o[n]() : o[n];

View File

@ -16,7 +16,7 @@ class SyncTargetRegistry {
} }
static nameToId(name) { static nameToId(name) {
for (let n in this.reg_) { for (const n in this.reg_) {
if (!this.reg_.hasOwnProperty(n)) continue; if (!this.reg_.hasOwnProperty(n)) continue;
if (this.reg_[n].name === name) return this.reg_[n].id; if (this.reg_[n].name === name) return this.reg_[n].id;
} }
@ -24,7 +24,7 @@ class SyncTargetRegistry {
} }
static idToMetadata(id) { static idToMetadata(id) {
for (let n in this.reg_) { for (const n in this.reg_) {
if (!this.reg_.hasOwnProperty(n)) continue; if (!this.reg_.hasOwnProperty(n)) continue;
if (this.reg_[n].id === id) return this.reg_[n]; if (this.reg_[n].id === id) return this.reg_[n];
} }
@ -36,8 +36,8 @@ class SyncTargetRegistry {
} }
static idAndLabelPlainObject(os) { static idAndLabelPlainObject(os) {
let output = {}; const output = {};
for (let n in this.reg_) { for (const n in this.reg_) {
if (!this.reg_.hasOwnProperty(n)) continue; if (!this.reg_.hasOwnProperty(n)) continue;
const info = this.reg_[n]; const info = this.reg_[n];
if (info.classRef.unsupportedPlatforms().indexOf(os) >= 0) { if (info.classRef.unsupportedPlatforms().indexOf(os) >= 0) {

View File

@ -30,7 +30,7 @@ TemplateUtils.render = function(input) {
}; };
TemplateUtils.loadTemplates = async function(filePath) { TemplateUtils.loadTemplates = async function(filePath) {
let templates = []; const templates = [];
let files = []; let files = [];
if (await shim.fsDriver().exists(filePath)) { if (await shim.fsDriver().exists(filePath)) {
@ -50,7 +50,7 @@ TemplateUtils.loadTemplates = async function(filePath) {
files.forEach(async file => { files.forEach(async file => {
if (file.path.endsWith('.md')) { if (file.path.endsWith('.md')) {
try { try {
let fileString = await shim.fsDriver().readFile(`${filePath}/${file.path}`, 'utf-8'); const fileString = await shim.fsDriver().readFile(`${filePath}/${file.path}`, 'utf-8');
templates.push({ label: file.path, value: fileString }); templates.push({ label: file.path, value: fileString });
} catch (error) { } catch (error) {
let msg = error.message ? error.message : ''; let msg = error.message ? error.message : '';

View File

@ -83,7 +83,7 @@ class WebDavApi {
} }
async xmlToJson(xml) { async xmlToJson(xml) {
let davNamespaces = []; // Yes, there can be more than one... xmlns:a="DAV:" xmlns:D="DAV:" const davNamespaces = []; // Yes, there can be more than one... xmlns:a="DAV:" xmlns:D="DAV:"
const nameProcessor = name => { const nameProcessor = name => {
if (name.indexOf('xmlns') !== 0) { if (name.indexOf('xmlns') !== 0) {
@ -247,12 +247,12 @@ class WebDavApi {
} }
requestToCurl_(url, options) { requestToCurl_(url, options) {
let output = []; const output = [];
output.push('curl'); output.push('curl');
output.push('-v'); output.push('-v');
if (options.method) output.push(`-X ${options.method}`); if (options.method) output.push(`-X ${options.method}`);
if (options.headers) { if (options.headers) {
for (let n in options.headers) { for (const n in options.headers) {
if (!options.headers.hasOwnProperty(n)) continue; if (!options.headers.hasOwnProperty(n)) continue;
output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`); output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`);
} }

View File

@ -30,7 +30,7 @@ class WelcomeUtils {
let noteBody = noteAsset.body; let noteBody = noteAsset.body;
for (let resourceUrl in noteAsset.resources) { for (const resourceUrl in noteAsset.resources) {
if (!noteAsset.resources.hasOwnProperty(resourceUrl)) continue; if (!noteAsset.resources.hasOwnProperty(resourceUrl)) continue;
const resourceAsset = noteAsset.resources[resourceUrl]; const resourceAsset = noteAsset.resources[resourceUrl];
const ext = fileExtension(resourceUrl); const ext = fileExtension(resourceUrl);

View File

@ -107,10 +107,10 @@ class CameraView extends Component {
} }
fitRectIntoBounds(rect, bounds) { fitRectIntoBounds(rect, bounds) {
var rectRatio = rect.width / rect.height; const rectRatio = rect.width / rect.height;
var boundsRatio = bounds.width / bounds.height; const boundsRatio = bounds.width / bounds.height;
var newDimensions = {}; const newDimensions = {};
// Rect is more landscape than bounds - fit to width // Rect is more landscape than bounds - fit to width
if (rectRatio > boundsRatio) { if (rectRatio > boundsRatio) {

View File

@ -16,7 +16,7 @@ class ModalDialog extends React.Component {
if (this.styles_[themeId]) return this.styles_[themeId]; if (this.styles_[themeId]) return this.styles_[themeId];
this.styles_ = {}; this.styles_ = {};
let styles = { const styles = {
modalWrapper: { modalWrapper: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',

View File

@ -56,7 +56,7 @@ class ActionButtonComponent extends React.Component {
} }
render() { render() {
let buttons = this.props.buttons ? this.props.buttons : []; const buttons = this.props.buttons ? this.props.buttons : [];
if (this.props.addFolderNoteButtons) { if (this.props.addFolderNoteButtons) {
if (this.props.folders.length) { if (this.props.folders.length) {
@ -80,11 +80,11 @@ class ActionButtonComponent extends React.Component {
} }
} }
let buttonComps = []; const buttonComps = [];
for (let i = 0; i < buttons.length; i++) { for (let i = 0; i < buttons.length; i++) {
let button = buttons[i]; const button = buttons[i];
let buttonTitle = button.title ? button.title : ''; const buttonTitle = button.title ? button.title : '';
let key = `${buttonTitle.replace(/\s/g, '_')}_${button.icon}`; const key = `${buttonTitle.replace(/\s/g, '_')}_${button.icon}`;
buttonComps.push( buttonComps.push(
<ReactNativeActionButton.Item key={key} buttonColor={button.color} title={buttonTitle} onPress={button.onPress}> <ReactNativeActionButton.Item key={key} buttonColor={button.color} title={buttonTitle} onPress={button.onPress}>
<Icon name={button.icon} style={styles.actionButtonIcon} /> <Icon name={button.icon} style={styles.actionButtonIcon} />
@ -96,14 +96,14 @@ class ActionButtonComponent extends React.Component {
return <ReactNativeActionButton style={{ display: 'none' }} />; return <ReactNativeActionButton style={{ display: 'none' }} />;
} }
let mainButton = this.props.mainButton ? this.props.mainButton : {}; const mainButton = this.props.mainButton ? this.props.mainButton : {};
let mainIcon = mainButton.icon ? <Icon name={mainButton.icon} style={styles.actionButtonIcon} /> : <Icon name="md-add" style={styles.actionButtonIcon} />; const mainIcon = mainButton.icon ? <Icon name={mainButton.icon} style={styles.actionButtonIcon} /> : <Icon name="md-add" style={styles.actionButtonIcon} />;
if (this.props.multiStates) { if (this.props.multiStates) {
if (!this.props.buttons || !this.props.buttons.length) throw new Error('Multi-state button requires at least one state'); if (!this.props.buttons || !this.props.buttons.length) throw new Error('Multi-state button requires at least one state');
if (this.state.buttonIndex < 0 || this.state.buttonIndex >= this.props.buttons.length) throw new Error(`Button index out of bounds: ${this.state.buttonIndex}/${this.props.buttons.length}`); if (this.state.buttonIndex < 0 || this.state.buttonIndex >= this.props.buttons.length) throw new Error(`Button index out of bounds: ${this.state.buttonIndex}/${this.props.buttons.length}`);
let button = this.props.buttons[this.state.buttonIndex]; const button = this.props.buttons[this.state.buttonIndex];
let mainIcon = <Icon name={button.icon} style={styles.actionButtonIcon} />; const mainIcon = <Icon name={button.icon} style={styles.actionButtonIcon} />;
return ( return (
<ReactNativeActionButton <ReactNativeActionButton
icon={mainIcon} icon={mainIcon}

View File

@ -43,7 +43,7 @@ class AppNavComponent extends Component {
// Note: certain screens are kept into memory, in particular Notes and Search // Note: certain screens are kept into memory, in particular Notes and Search
// so that the scroll position is not lost when the user navigate away from them. // so that the scroll position is not lost when the user navigate away from them.
let route = this.props.route; const route = this.props.route;
let Screen = null; let Screen = null;
let notesScreenVisible = false; let notesScreenVisible = false;
let searchScreenVisible = false; let searchScreenVisible = false;
@ -59,7 +59,7 @@ class AppNavComponent extends Component {
// Keep the search screen loaded if the user is viewing a note from that search screen // 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 // so that if the back button is pressed, the screen is still loaded. However, unload
// it if navigating away. // it if navigating away.
let searchScreenLoaded = searchScreenVisible || (this.previousRouteName_ == 'Search' && route.routeName == 'Note'); const searchScreenLoaded = searchScreenVisible || (this.previousRouteName_ == 'Search' && route.routeName == 'Note');
this.previousRouteName_ = route.routeName; this.previousRouteName_ = route.routeName;

View File

@ -12,7 +12,7 @@ const styleObject_ = {
const styles_ = StyleSheet.create(styleObject_); const styles_ = StyleSheet.create(styleObject_);
let rootStyles_ = {}; const rootStyles_ = {};
class BaseScreenComponent extends React.Component { class BaseScreenComponent extends React.Component {
styles() { styles() {

View File

@ -31,7 +31,7 @@ class Checkbox extends Component {
} }
onPress() { onPress() {
let newChecked = !this.state.checked; const newChecked = !this.state.checked;
this.setState({ checked: newChecked }); this.setState({ checked: newChecked });
if (this.props.onChange) this.props.onChange(newChecked); if (this.props.onChange) this.props.onChange(newChecked);
} }
@ -39,11 +39,11 @@ class Checkbox extends Component {
render() { render() {
const iconName = this.state.checked ? 'md-checkbox-outline' : 'md-square-outline'; const iconName = this.state.checked ? 'md-checkbox-outline' : 'md-square-outline';
let style = this.props.style ? Object.assign({}, this.props.style) : {}; const style = this.props.style ? Object.assign({}, this.props.style) : {};
style.justifyContent = 'center'; style.justifyContent = 'center';
style.alignItems = 'center'; style.alignItems = 'center';
let checkboxIconStyle = Object.assign({}, styles.checkboxIcon); const checkboxIconStyle = Object.assign({}, styles.checkboxIcon);
if (style.color) checkboxIconStyle.color = style.color; if (style.color) checkboxIconStyle.color = style.color;
if (style.paddingTop) checkboxIconStyle.marginTop = style.paddingTop; if (style.paddingTop) checkboxIconStyle.marginTop = style.paddingTop;

View File

@ -47,7 +47,7 @@ globalStyle.marginTop = globalStyle.margin;
globalStyle.marginBottom = globalStyle.margin; globalStyle.marginBottom = globalStyle.margin;
globalStyle.htmlMarginLeft = `${((globalStyle.marginLeft / 10) * 0.6).toFixed(2)}em`; globalStyle.htmlMarginLeft = `${((globalStyle.marginLeft / 10) * 0.6).toFixed(2)}em`;
let themeCache_ = {}; const themeCache_ = {};
function addExtraStyles(style) { function addExtraStyles(style) {
style.icon = { style.icon = {
@ -122,7 +122,7 @@ function themeStyle(theme) {
if (themeCache_[theme]) return themeCache_[theme]; if (themeCache_[theme]) return themeCache_[theme];
let output = Object.assign({}, globalStyle); const output = Object.assign({}, globalStyle);
if (theme == Setting.THEME_LIGHT) return addExtraStyles(output); if (theme == Setting.THEME_LIGHT) return addExtraStyles(output);
else if (theme == Setting.THEME_OLED_DARK) { else if (theme == Setting.THEME_OLED_DARK) {
output.backgroundColor = '#000000'; output.backgroundColor = '#000000';

View File

@ -62,7 +62,7 @@ class NoteBodyViewer extends Component {
postMessageSyntax: 'window.ReactNativeWebView.postMessage', postMessageSyntax: 'window.ReactNativeWebView.postMessage',
}; };
let result = await this.markupToHtml_.render(note.markup_language, bodyToRender, this.props.webViewStyle, mdOptions); const result = await this.markupToHtml_.render(note.markup_language, bodyToRender, this.props.webViewStyle, mdOptions);
let html = result.html; let html = result.html;
const resourceDownloadMode = Setting.value('sync.resourceDownloadMode'); const resourceDownloadMode = Setting.value('sync.resourceDownloadMode');
@ -188,7 +188,7 @@ class NoteBodyViewer extends Component {
// https://github.com/react-native-community/react-native-webview/issues/312#issuecomment-503754654 // https://github.com/react-native-community/react-native-webview/issues/312#issuecomment-503754654
let webViewStyle = { backgroundColor: this.props.webViewStyle.backgroundColor }; const webViewStyle = { backgroundColor: this.props.webViewStyle.backgroundColor };
// On iOS, the onLoadEnd() event is never fired so always // On iOS, the onLoadEnd() event is never fired so always
// display the webview (don't do the little trick // display the webview (don't do the little trick
// to avoid the white flash). // to avoid the white flash).

View File

@ -27,7 +27,7 @@ class NoteItemComponent extends Component {
if (this.styles_[this.props.theme]) return this.styles_[this.props.theme]; if (this.styles_[this.props.theme]) return this.styles_[this.props.theme];
this.styles_ = {}; this.styles_ = {};
let styles = { const styles = {
listItem: { listItem: {
flexDirection: 'row', flexDirection: 'row',
// height: 40, // height: 40,
@ -110,7 +110,7 @@ class NoteItemComponent extends Component {
const theme = themeStyle(this.props.theme); const theme = themeStyle(this.props.theme);
// IOS: display: none crashes the app // IOS: display: none crashes the app
let checkboxStyle = !isTodo ? { display: 'none' } : { color: theme.color }; const checkboxStyle = !isTodo ? { display: 'none' } : { color: theme.color };
if (isTodo) { if (isTodo) {
checkboxStyle.paddingRight = 10; checkboxStyle.paddingRight = 10;

View File

@ -28,7 +28,7 @@ class NoteListComponent extends Component {
if (this.styles_[themeId]) return this.styles_[themeId]; if (this.styles_[themeId]) return this.styles_[themeId];
this.styles_ = {}; this.styles_ = {};
let styles = { const styles = {
noItemMessage: { noItemMessage: {
paddingLeft: theme.marginLeft, paddingLeft: theme.marginLeft,
paddingRight: theme.marginRight, paddingRight: theme.marginRight,
@ -63,7 +63,7 @@ class NoteListComponent extends Component {
const maxInterval = 1000 * 60 * 60 * 24; const maxInterval = 1000 * 60 * 60 * 24;
const notRecentTime = now - maxInterval; const notRecentTime = now - maxInterval;
let output = []; const output = [];
for (let i = 0; i < notes.length; i++) { for (let i = 0; i < notes.length; i++) {
const note = notes[i]; const note = notes[i];
if (note.is_todo) { if (note.is_todo) {

View File

@ -36,7 +36,7 @@ class ScreenHeaderComponent extends React.PureComponent {
const theme = themeStyle(themeId); const theme = themeStyle(themeId);
let styleObject = { const styleObject = {
container: { container: {
flexDirection: 'column', flexDirection: 'column',
backgroundColor: theme.raisedBackgroundColor, backgroundColor: theme.raisedBackgroundColor,
@ -299,11 +299,11 @@ class ScreenHeaderComponent extends React.PureComponent {
} }
let key = 0; let key = 0;
let menuOptionComponents = []; const menuOptionComponents = [];
if (!this.props.noteSelectionEnabled) { if (!this.props.noteSelectionEnabled) {
for (let i = 0; i < this.props.menuOptions.length; i++) { for (let i = 0; i < this.props.menuOptions.length; i++) {
let o = this.props.menuOptions[i]; const o = this.props.menuOptions[i];
if (o.isDivider) { if (o.isDivider) {
menuOptionComponents.push(<View key={`menuOption_${key++}`} style={this.styles().divider} />); menuOptionComponents.push(<View key={`menuOption_${key++}`} style={this.styles().divider} />);
@ -408,7 +408,7 @@ class ScreenHeaderComponent extends React.PureComponent {
/> />
); );
} else { } else {
let title = 'title' in this.props && this.props.title !== null ? this.props.title : ''; const title = 'title' in this.props && this.props.title !== null ? this.props.title : '';
return <Text style={this.styles().titleText}>{title}</Text>; return <Text style={this.styles().titleText}>{title}</Text>;
} }
}; };

View File

@ -122,7 +122,7 @@ class NoteTagsDialogComponent extends React.Component {
if (this.styles_[themeId]) return this.styles_[themeId]; if (this.styles_[themeId]) return this.styles_[themeId];
this.styles_ = {}; this.styles_ = {};
let styles = { const styles = {
tag: { tag: {
padding: 10, padding: 10,
borderBottomWidth: 1, borderBottomWidth: 1,

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