mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
refactoring utils into module
This commit is contained in:
parent
0f6b00e1c8
commit
c8e456cdb1
@ -3,8 +3,8 @@ function ScriptContext(startNote, allNotes) {
|
||||
|
||||
return {
|
||||
modules: modules,
|
||||
notes: toObject(allNotes, note => [note.noteId, note]),
|
||||
apis: toObject(allNotes, note => [note.noteId, ScriptApi(startNote, note)]),
|
||||
notes: utils.toObject(allNotes, note => [note.noteId, note]),
|
||||
apis: utils.toObject(allNotes, note => [note.noteId, ScriptApi(startNote, note)]),
|
||||
require: moduleNoteIds => {
|
||||
return moduleName => {
|
||||
const candidates = allNotes.filter(note => moduleNoteIds.includes(note.noteId));
|
||||
|
@ -26,7 +26,7 @@ const contextMenu = (function() {
|
||||
// just do nothing
|
||||
}
|
||||
else {
|
||||
throwError("Unrecognized clipboard mode=" + clipboardMode);
|
||||
utils.throwError("Unrecognized clipboard mode=" + clipboardMode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ const contextMenu = (function() {
|
||||
// just do nothing
|
||||
}
|
||||
else {
|
||||
throwError("Unrecognized clipboard mode=" + mode);
|
||||
utils.throwError("Unrecognized clipboard mode=" + mode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,14 +57,14 @@ const contextMenu = (function() {
|
||||
clipboardIds = nodes.map(node => node.data.noteId);
|
||||
clipboardMode = 'copy';
|
||||
|
||||
showMessage("Note(s) have been copied into clipboard.");
|
||||
utils.showMessage("Note(s) have been copied into clipboard.");
|
||||
}
|
||||
|
||||
function cut(nodes) {
|
||||
clipboardIds = nodes.map(node => node.key);
|
||||
clipboardMode = 'cut';
|
||||
|
||||
showMessage("Note(s) have been cut into clipboard.");
|
||||
utils.showMessage("Note(s) have been cut into clipboard.");
|
||||
}
|
||||
|
||||
const contextMenuSettings = {
|
||||
|
@ -18,7 +18,7 @@ const eventLog = (function() {
|
||||
$list.html('');
|
||||
|
||||
for (const event of result) {
|
||||
const dateTime = formatDateTime(parseDate(event.dateAdded));
|
||||
const dateTime = utils.formatDateTime(utils.parseDate(event.dateAdded));
|
||||
|
||||
if (event.noteId) {
|
||||
const noteLink = link.createNoteLink(event.noteId).prop('outerHTML');
|
||||
|
@ -17,7 +17,7 @@ const jumpToNote = (function() {
|
||||
});
|
||||
|
||||
await $autoComplete.autocomplete({
|
||||
source: await stopWatch("building autocomplete", treeService.getAutocompleteItems),
|
||||
source: await utils.stopWatch("building autocomplete", treeService.getAutocompleteItems),
|
||||
minLength: 0
|
||||
});
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ const labelsDialog = (function() {
|
||||
|
||||
addLastEmptyRow();
|
||||
|
||||
showMessage("Labels have been saved.");
|
||||
utils.showMessage("Labels have been saved.");
|
||||
|
||||
noteEditor.loadLabelList();
|
||||
};
|
||||
|
@ -28,11 +28,11 @@ const noteHistory = (function() {
|
||||
historyItems = await server.get('notes-history/' + noteId);
|
||||
|
||||
for (const item of historyItems) {
|
||||
const dateModified = parseDate(item.dateModifiedFrom);
|
||||
const dateModified = utils.parseDate(item.dateModifiedFrom);
|
||||
|
||||
$list.append($('<option>', {
|
||||
value: item.noteRevisionId,
|
||||
text: formatDateTime(dateModified)
|
||||
text: utils.formatDateTime(dateModified)
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,10 @@ const recentChanges = (function() {
|
||||
for (const [dateDay, dayChanges] of groupedByDate) {
|
||||
const changesListEl = $('<ul>');
|
||||
|
||||
const dayEl = $('<div>').append($('<b>').html(formatDate(dateDay))).append(changesListEl);
|
||||
const dayEl = $('<div>').append($('<b>').html(utils.formatDate(dateDay))).append(changesListEl);
|
||||
|
||||
for (const change of dayChanges) {
|
||||
const formattedTime = formatTime(parseDate(change.dateModifiedTo));
|
||||
const formattedTime = utils.formatTime(utils.parseDate(change.dateModifiedTo));
|
||||
|
||||
const revLink = $("<a>", {
|
||||
href: 'javascript:',
|
||||
@ -58,7 +58,7 @@ const recentChanges = (function() {
|
||||
const dayCache = {};
|
||||
|
||||
for (const row of result) {
|
||||
let dateDay = parseDate(row.dateModifiedTo);
|
||||
let dateDay = utils.parseDate(row.dateModifiedTo);
|
||||
dateDay.setHours(0);
|
||||
dateDay.setMinutes(0);
|
||||
dateDay.setSeconds(0);
|
||||
|
@ -36,7 +36,7 @@ const settings = (function() {
|
||||
value: settingValue
|
||||
});
|
||||
|
||||
showMessage("Settings change have been saved.");
|
||||
utils.showMessage("Settings change have been saved.");
|
||||
}
|
||||
|
||||
$showDialogButton.click(showDialog);
|
||||
@ -82,7 +82,7 @@ settings.addModule((function() {
|
||||
protected_session.resetProtectedSession();
|
||||
}
|
||||
else {
|
||||
showError(result.message);
|
||||
utils.showError(result.message);
|
||||
}
|
||||
});
|
||||
|
||||
@ -166,27 +166,27 @@ settings.addModule((async function () {
|
||||
$forceFullSyncButton.click(async () => {
|
||||
await server.post('sync/force-full-sync');
|
||||
|
||||
showMessage("Full sync triggered");
|
||||
utils.showMessage("Full sync triggered");
|
||||
});
|
||||
|
||||
$fillSyncRowsButton.click(async () => {
|
||||
await server.post('sync/fill-sync-rows');
|
||||
|
||||
showMessage("Sync rows filled successfully");
|
||||
utils.showMessage("Sync rows filled successfully");
|
||||
});
|
||||
|
||||
|
||||
$anonymizeButton.click(async () => {
|
||||
await server.post('anonymization/anonymize');
|
||||
|
||||
showMessage("Created anonymized database");
|
||||
utils.showMessage("Created anonymized database");
|
||||
});
|
||||
|
||||
$cleanupSoftDeletedButton.click(async () => {
|
||||
if (confirm("Do you really want to clean up soft-deleted items?")) {
|
||||
await server.post('cleanup/cleanup-soft-deleted-items');
|
||||
|
||||
showMessage("Soft deleted items have been cleaned up");
|
||||
utils.showMessage("Soft deleted items have been cleaned up");
|
||||
}
|
||||
});
|
||||
|
||||
@ -194,14 +194,14 @@ settings.addModule((async function () {
|
||||
if (confirm("Do you really want to clean up unused images?")) {
|
||||
await server.post('cleanup/cleanup-unused-images');
|
||||
|
||||
showMessage("Unused images have been cleaned up");
|
||||
utils.showMessage("Unused images have been cleaned up");
|
||||
}
|
||||
});
|
||||
|
||||
$vacuumDatabaseButton.click(async () => {
|
||||
await server.post('cleanup/vacuum-database');
|
||||
|
||||
showMessage("Database has been vacuumed");
|
||||
utils.showMessage("Database has been vacuumed");
|
||||
});
|
||||
|
||||
return {};
|
||||
|
@ -24,7 +24,7 @@ const sqlConsole = (function() {
|
||||
|
||||
async function initEditor() {
|
||||
if (!codeEditor) {
|
||||
await requireLibrary(CODE_MIRROR);
|
||||
await utils.requireLibrary(utils.CODE_MIRROR);
|
||||
|
||||
CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
|
||||
CodeMirror.keyMap.default["Tab"] = "indentMore";
|
||||
@ -60,11 +60,11 @@ const sqlConsole = (function() {
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
showError(result.error);
|
||||
utils.showError(result.error);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
showMessage("Query was executed successfully.");
|
||||
utils.showMessage("Query was executed successfully.");
|
||||
}
|
||||
|
||||
const rows = result.rows;
|
||||
|
@ -1,10 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
function exportSubTree(noteId) {
|
||||
const url = getHost() + "/api/export/" + noteId + "?protectedSessionId="
|
||||
const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId="
|
||||
+ encodeURIComponent(protected_session.getProtectedSessionId());
|
||||
|
||||
download(url);
|
||||
utils.download(url);
|
||||
}
|
||||
|
||||
let importNoteId;
|
||||
|
@ -14,7 +14,7 @@ $(document).bind('keydown', 'alt+m', e => {
|
||||
// hide (toggle) everything except for the note content for distraction free writing
|
||||
$(document).bind('keydown', 'alt+t', e => {
|
||||
const date = new Date();
|
||||
const dateString = formatDateTime(date);
|
||||
const dateString = utils.formatDateTime(date);
|
||||
|
||||
link.addTextToEditor(dateString);
|
||||
|
||||
@ -22,19 +22,19 @@ $(document).bind('keydown', 'alt+t', e => {
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'f5', () => {
|
||||
reloadApp();
|
||||
utils.reloadApp();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+r', () => {
|
||||
reloadApp();
|
||||
utils.reloadApp();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+shift+i', () => {
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
require('electron').remote.getCurrentWindow().toggleDevTools();
|
||||
|
||||
return false;
|
||||
@ -42,7 +42,7 @@ $(document).bind('keydown', 'ctrl+shift+i', () => {
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+f', () => {
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
const searchInPage = require('electron-in-page-search').default;
|
||||
const remote = require('electron').remote;
|
||||
|
||||
@ -73,7 +73,7 @@ $(document).bind('keydown', "ctrl+shift+down", () => {
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+-', () => {
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
const webFrame = require('electron').webFrame;
|
||||
|
||||
if (webFrame.getZoomFactor() > 0.2) {
|
||||
@ -85,7 +85,7 @@ $(document).bind('keydown', 'ctrl+-', () => {
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+=', () => {
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
const webFrame = require('electron').webFrame;
|
||||
|
||||
webFrame.setZoomFactor(webFrame.getZoomFactor() + 0.1);
|
||||
@ -198,17 +198,17 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
return false;
|
||||
};
|
||||
|
||||
$("#logout-button").toggle(!isElectron());
|
||||
$("#logout-button").toggle(!utils.isElectron());
|
||||
|
||||
$(document).ready(() => {
|
||||
server.get("script/startup").then(scriptBundles => {
|
||||
for (const bundle of scriptBundles) {
|
||||
executeBundle(bundle);
|
||||
utils.executeBundle(bundle);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
|
||||
// this might occur when day note had to be created
|
||||
if (!await treeService.noteExists(parentNoteId)) {
|
||||
|
@ -4,7 +4,7 @@ const messaging = (function() {
|
||||
const $changesToPushCount = $("#changes-to-push-count");
|
||||
|
||||
function logError(message) {
|
||||
console.log(now(), message); // needs to be separate from .trace()
|
||||
console.log(utils.now(), message); // needs to be separate from .trace()
|
||||
console.trace();
|
||||
|
||||
if (ws && ws.readyState === 1) {
|
||||
@ -22,7 +22,7 @@ const messaging = (function() {
|
||||
lastPingTs = new Date().getTime();
|
||||
|
||||
if (message.data.length > 0) {
|
||||
console.log(now(), "Sync data: ", message.data);
|
||||
console.log(utils.now(), "Sync data: ", message.data);
|
||||
|
||||
lastSyncId = message.data[message.data.length - 1].id;
|
||||
}
|
||||
@ -32,19 +32,19 @@ const messaging = (function() {
|
||||
if (syncData.some(sync => sync.entityName === 'branches')
|
||||
|| syncData.some(sync => sync.entityName === 'notes')) {
|
||||
|
||||
console.log(now(), "Reloading tree because of background changes");
|
||||
console.log(utils.now(), "Reloading tree because of background changes");
|
||||
|
||||
treeService.reload();
|
||||
}
|
||||
|
||||
if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === noteEditor.getCurrentNoteId())) {
|
||||
showMessage('Reloading note because of background changes');
|
||||
utils.showMessage('Reloading note because of background changes');
|
||||
|
||||
noteEditor.reload();
|
||||
}
|
||||
|
||||
if (syncData.some(sync => sync.entityName === 'recent_notes')) {
|
||||
console.log(now(), "Reloading recent notes because of background changes");
|
||||
console.log(utils.now(), "Reloading recent notes because of background changes");
|
||||
|
||||
recentNotes.reload();
|
||||
}
|
||||
@ -55,10 +55,10 @@ const messaging = (function() {
|
||||
$changesToPushCount.html(message.changesToPushCount);
|
||||
}
|
||||
else if (message.type === 'sync-hash-check-failed') {
|
||||
showError("Sync check failed!", 60000);
|
||||
utils.utils.showError("Sync check failed!", 60000);
|
||||
}
|
||||
else if (message.type === 'consistency-checks-failed') {
|
||||
showError("Consistency checks failed! See logs for details.", 50 * 60000);
|
||||
utils.showError("Consistency checks failed! See logs for details.", 50 * 60000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ const messaging = (function() {
|
||||
|
||||
// use wss for secure messaging
|
||||
const ws = new WebSocket(protocol + "://" + location.host);
|
||||
ws.onopen = event => console.log(now(), "Connected to server with WebSocket");
|
||||
ws.onopen = event => console.log(utils.now(), "Connected to server with WebSocket");
|
||||
ws.onmessage = messageHandler;
|
||||
ws.onclose = function(){
|
||||
// Try to reconnect in 5 seconds
|
||||
@ -100,7 +100,7 @@ const messaging = (function() {
|
||||
await connectionBrokenNotification.close();
|
||||
connectionBrokenNotification = null;
|
||||
|
||||
showMessage("Re-connected to server");
|
||||
utils.showMessage("Re-connected to server");
|
||||
}
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
|
@ -103,7 +103,7 @@ const noteEditor = (function() {
|
||||
// nothing
|
||||
}
|
||||
else {
|
||||
throwError("Unrecognized type: " + note.detail.type);
|
||||
utils.throwError("Unrecognized type: " + note.detail.type);
|
||||
}
|
||||
|
||||
const title = $noteTitle.val();
|
||||
@ -118,7 +118,7 @@ const noteEditor = (function() {
|
||||
|
||||
isNoteChanged = false;
|
||||
|
||||
showMessage("Saved!");
|
||||
utils.showMessage("Saved!");
|
||||
}
|
||||
|
||||
function setNoteBackgroundIfProtected(note) {
|
||||
@ -138,7 +138,7 @@ const noteEditor = (function() {
|
||||
async function setContent(content) {
|
||||
if (currentNote.detail.type === 'text') {
|
||||
if (!editor) {
|
||||
await requireLibrary(CKEDITOR);
|
||||
await utils.requireLibrary(utils.CKEDITOR);
|
||||
|
||||
editor = await BalloonEditor.create($noteDetail[0], {});
|
||||
|
||||
@ -152,7 +152,7 @@ const noteEditor = (function() {
|
||||
}
|
||||
else if (currentNote.detail.type === 'code') {
|
||||
if (!codeEditor) {
|
||||
await requireLibrary(CODE_MIRROR);
|
||||
await utils.requireLibrary(utils.CODE_MIRROR);
|
||||
|
||||
CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
|
||||
CodeMirror.keyMap.default["Tab"] = "indentMore";
|
||||
@ -248,7 +248,7 @@ const noteEditor = (function() {
|
||||
|
||||
$noteDetailRender.html(bundle.html);
|
||||
|
||||
executeBundle(bundle);
|
||||
utils.executeBundle(bundle);
|
||||
}
|
||||
else if (currentNote.detail.type === 'file') {
|
||||
$noteDetailAttachment.show();
|
||||
@ -281,7 +281,7 @@ const noteEditor = (function() {
|
||||
|
||||
if (labels.length > 0) {
|
||||
for (const attr of labels) {
|
||||
$labelListInner.append(formatLabel(attr) + " ");
|
||||
$labelListInner.append(utils.formatLabel(attr) + " ");
|
||||
}
|
||||
|
||||
$labelList.show();
|
||||
@ -312,7 +312,7 @@ const noteEditor = (function() {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
throwError('Unrecognized type: ' + note.detail.type);
|
||||
utils.throwError('Unrecognized type: ' + note.detail.type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,21 +330,21 @@ const noteEditor = (function() {
|
||||
if (currentNote.detail.mime.endsWith("env=frontend")) {
|
||||
const bundle = await server.get('script/bundle/' + getCurrentNoteId());
|
||||
|
||||
executeBundle(bundle);
|
||||
utils.executeBundle(bundle);
|
||||
}
|
||||
|
||||
if (currentNote.detail.mime.endsWith("env=backend")) {
|
||||
await server.post('script/run/' + getCurrentNoteId());
|
||||
}
|
||||
|
||||
showMessage("Note executed");
|
||||
utils.showMessage("Note executed");
|
||||
}
|
||||
}
|
||||
|
||||
$attachmentDownload.click(() => download(getAttachmentUrl()));
|
||||
$attachmentDownload.click(() => utils.download(getAttachmentUrl()));
|
||||
|
||||
$attachmentOpen.click(() => {
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
const open = require("open");
|
||||
|
||||
open(getAttachmentUrl());
|
||||
@ -356,7 +356,7 @@ const noteEditor = (function() {
|
||||
|
||||
function getAttachmentUrl() {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return getHost() + "/api/attachments/download/" + getCurrentNoteId()
|
||||
return utils.getHost() + "/api/attachments/download/" + getCurrentNoteId()
|
||||
+ "?protectedSessionId=" + encodeURIComponent(protected_session.getProtectedSessionId());
|
||||
}
|
||||
|
||||
|
@ -135,38 +135,22 @@ const treeService = (function() {
|
||||
const note = noteMap[noteId];
|
||||
|
||||
if (!note) {
|
||||
throwError("Can't find title for noteId='" + noteId + "'");
|
||||
utils.throwError("Can't find title for noteId='" + noteId + "'");
|
||||
}
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
function getBranchId(parentNoteId, childNoteId) {
|
||||
assertArguments(parentNoteId, childNoteId);
|
||||
|
||||
|
||||
|
||||
const key = parentNoteId + "-" + childNoteId;
|
||||
|
||||
// this can return undefined and client code should deal with it somehow
|
||||
|
||||
return parentChildToBranchId[key];
|
||||
}
|
||||
|
||||
function getNoteTitle(noteId, parentNoteId = null) {
|
||||
assertArguments(noteId);
|
||||
utils.assertArguments(noteId);
|
||||
|
||||
let title = treeCache.getNote(noteId).title;
|
||||
|
||||
if (parentNoteId !== null) {
|
||||
const branchId = getBranchId(parentNoteId, noteId);
|
||||
const branch = treeCache.getBranch(noteId, parentNoteId);
|
||||
|
||||
if (branchId) {
|
||||
const branch = branchMap[branchId];
|
||||
|
||||
if (branch.prefix) {
|
||||
title = branch.prefix + ' - ' + title;
|
||||
}
|
||||
if (branch && branch.prefix) {
|
||||
title = branch.prefix + ' - ' + title;
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,7 +169,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
function getNodesByBranchId(branchId) {
|
||||
assertArguments(branchId);
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
const branch = branchMap[branchId];
|
||||
|
||||
@ -193,14 +177,14 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
function getNodesByNoteId(noteId) {
|
||||
assertArguments(noteId);
|
||||
utils.assertArguments(noteId);
|
||||
|
||||
const list = getTree().getNodesByRef(noteId);
|
||||
return list ? list : []; // if no nodes with this refKey are found, fancy tree returns null
|
||||
}
|
||||
|
||||
function setPrefix(branchId, prefix) {
|
||||
assertArguments(branchId);
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
branchMap[branchId].prefix = prefix;
|
||||
|
||||
@ -215,11 +199,11 @@ const treeService = (function() {
|
||||
|
||||
const title = (prefix ? (prefix + " - ") : "") + noteTitle;
|
||||
|
||||
node.setTitle(escapeHtml(title));
|
||||
node.setTitle(utils.escapeHtml(title));
|
||||
}
|
||||
|
||||
function removeParentChildRelation(parentNoteId, childNoteId) {
|
||||
assertArguments(parentNoteId, childNoteId);
|
||||
utils.assertArguments(parentNoteId, childNoteId);
|
||||
|
||||
const parentNote = noteMap[parentNoteId];
|
||||
const childNote = noteMap[childNoteId];
|
||||
@ -228,7 +212,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
function setParentChildRelation(branchId, parentNoteId, childNoteId) {
|
||||
assertArguments(branchId, parentNoteId, childNoteId);
|
||||
utils.assertArguments(branchId, parentNoteId, childNoteId);
|
||||
|
||||
const parentNote = noteMap[parentNoteId];
|
||||
const childNote = noteMap[childNoteId];
|
||||
@ -237,7 +221,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function prepareBranch(noteRows, branchRows) {
|
||||
assertArguments(noteRows);
|
||||
utils.assertArguments(noteRows);
|
||||
|
||||
treeCache = new TreeCache(noteRows, branchRows);
|
||||
|
||||
@ -245,7 +229,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function getExtraClasses(note) {
|
||||
assertArguments(note);
|
||||
utils.assertArguments(note);
|
||||
|
||||
const extraClasses = [];
|
||||
|
||||
@ -263,7 +247,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function prepareBranchInner(parentNote) {
|
||||
assertArguments(parentNote);
|
||||
utils.assertArguments(parentNote);
|
||||
|
||||
const childBranches = await parentNote.getChildBranches();
|
||||
|
||||
@ -283,7 +267,7 @@ const treeService = (function() {
|
||||
parentNoteId: branch.parentNoteId,
|
||||
branchId: branch.branchId,
|
||||
isProtected: note.isProtected,
|
||||
title: escapeHtml(title),
|
||||
title: utils.escapeHtml(title),
|
||||
extraClasses: getExtraClasses(note),
|
||||
refKey: note.noteId,
|
||||
expanded: note.type !== 'search' && branch.isExpanded
|
||||
@ -309,7 +293,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function expandToNote(notePath, expandOpts) {
|
||||
assertArguments(notePath);
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const runPath = await getRunPath(notePath);
|
||||
|
||||
@ -332,7 +316,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function activateNode(notePath) {
|
||||
assertArguments(notePath);
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const node = await expandToNote(notePath);
|
||||
|
||||
@ -346,7 +330,7 @@ const treeService = (function() {
|
||||
* path change) or other corruption, in that case this will try to get some other valid path to the correct note.
|
||||
*/
|
||||
async function getRunPath(notePath) {
|
||||
assertArguments(notePath);
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const path = notePath.split("/").reverse();
|
||||
path.push('root');
|
||||
@ -372,10 +356,10 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
if (!parents.some(p => p.noteId === parentNoteId)) {
|
||||
console.log(now(), "Did not find parent " + parentNoteId + " for child " + childNoteId);
|
||||
console.log(utils.now(), "Did not find parent " + parentNoteId + " for child " + childNoteId);
|
||||
|
||||
if (parents.length > 0) {
|
||||
console.log(now(), "Available parents:", parents);
|
||||
console.log(utils.now(), "Available parents:", parents);
|
||||
|
||||
const someNotePath = await getSomeNotePath(parents[0]);
|
||||
|
||||
@ -409,13 +393,13 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function showParentList(noteId, node) {
|
||||
assertArguments(noteId, node);
|
||||
utils.assertArguments(noteId, node);
|
||||
|
||||
const note = treeCache.getNote(noteId);
|
||||
const parents = await note.getParentNotes();
|
||||
|
||||
if (!parents.length) {
|
||||
throwError("Can't find parents for noteId=" + noteId);
|
||||
utils.throwError("Can't find parents for noteId=" + noteId);
|
||||
}
|
||||
|
||||
if (parents.length <= 1) {
|
||||
@ -446,7 +430,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
function getNotePathTitle(notePath) {
|
||||
assertArguments(notePath);
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const titlePath = [];
|
||||
|
||||
@ -462,7 +446,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function getSomeNotePath(note) {
|
||||
assertArguments(note);
|
||||
utils.assertArguments(note);
|
||||
|
||||
const path = [];
|
||||
|
||||
@ -474,7 +458,7 @@ const treeService = (function() {
|
||||
const parents = await cur.getParentNotes();
|
||||
|
||||
if (!parents.length) {
|
||||
throwError("Can't find parents for " + cur);
|
||||
utils.throwError("Can't find parents for " + cur);
|
||||
}
|
||||
|
||||
cur = parents[0];
|
||||
@ -484,7 +468,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function setExpandedToServer(branchId, isExpanded) {
|
||||
assertArguments(branchId);
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
const expandedNum = isExpanded ? 1 : 0;
|
||||
|
||||
@ -492,7 +476,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
function setCurrentNotePathToHash(node) {
|
||||
assertArguments(node);
|
||||
utils.assertArguments(node);
|
||||
|
||||
const currentNotePath = treeUtils.getNotePath(node);
|
||||
const currentBranchId = node.data.branchId;
|
||||
@ -519,7 +503,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
function initFancyTree(branch) {
|
||||
assertArguments(branch);
|
||||
utils.assertArguments(branch);
|
||||
|
||||
const keybindings = {
|
||||
"del": node => {
|
||||
@ -621,7 +605,7 @@ const treeService = (function() {
|
||||
return false;
|
||||
},
|
||||
"backspace": node => {
|
||||
if (!isTopLevelNode(node)) {
|
||||
if (!utils.isTopLevelNode(node)) {
|
||||
node.getParent().setActive().then(() => clearSelectedNodes());
|
||||
}
|
||||
},
|
||||
@ -748,7 +732,7 @@ const treeService = (function() {
|
||||
const noteIds = await server.get('search/' + encodeURIComponent(json.searchString));
|
||||
|
||||
for (const noteId of noteIds) {
|
||||
const branchId = "virt" + randomString(10);
|
||||
const branchId = "virt" + utils.randomString(10);
|
||||
|
||||
branchMap[branchId] = {
|
||||
branchId: branchId,
|
||||
@ -874,7 +858,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
function setNoteTitle(noteId, title) {
|
||||
assertArguments(noteId);
|
||||
utils.assertArguments(noteId);
|
||||
|
||||
getNote(noteId).title = title;
|
||||
|
||||
@ -888,7 +872,7 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
async function createNote(node, parentNoteId, target, isProtected) {
|
||||
assertArguments(node, parentNoteId, target);
|
||||
utils.assertArguments(node, parentNoteId, target);
|
||||
|
||||
// if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted
|
||||
// but this is quite weird since user doesn't see WHERE the note is being created so it shouldn't occur often
|
||||
@ -946,12 +930,12 @@ const treeService = (function() {
|
||||
node.renderTitle();
|
||||
}
|
||||
else {
|
||||
throwError("Unrecognized target: " + target);
|
||||
utils.throwError("Unrecognized target: " + target);
|
||||
}
|
||||
|
||||
clearSelectedNodes(); // to unmark previously active node
|
||||
|
||||
showMessage("Created!");
|
||||
utils.showMessage("Created!");
|
||||
}
|
||||
|
||||
async function sortAlphabetically(noteId) {
|
||||
@ -1010,7 +994,7 @@ const treeService = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
$(document).bind('keydown', 'alt+left', e => {
|
||||
window.history.back();
|
||||
|
||||
|
@ -73,7 +73,7 @@ const noteType = (function() {
|
||||
// ignore and do nothing, "type" will be hidden since it's not possible to switch to and from search
|
||||
}
|
||||
else {
|
||||
throwError('Unrecognized type: ' + type);
|
||||
utils.throwError('Unrecognized type: ' + type);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ const protected_session = (function() {
|
||||
const response = await enterProtectedSession(password);
|
||||
|
||||
if (!response.success) {
|
||||
showError("Wrong password.");
|
||||
utils.showError("Wrong password.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ const protected_session = (function() {
|
||||
|
||||
// most secure solution - guarantees nothing remained in memory
|
||||
// since this expires because user doesn't use the app, it shouldn't be disruptive
|
||||
reloadApp();
|
||||
utils.reloadApp();
|
||||
}
|
||||
|
||||
function isProtectedSessionAvailable() {
|
||||
@ -153,7 +153,7 @@ const protected_session = (function() {
|
||||
|
||||
await server.put('notes/' + noteId + "/protect-sub-tree/" + (protect ? 1 : 0));
|
||||
|
||||
showMessage("Request to un/protect sub tree has finished successfully");
|
||||
utils.showMessage("Request to un/protect sub tree has finished successfully");
|
||||
|
||||
treeService.reload();
|
||||
noteEditor.reload();
|
||||
|
@ -35,14 +35,14 @@ const server = (function() {
|
||||
const reqResolves = {};
|
||||
|
||||
async function call(method, url, data) {
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
const ipc = require('electron').ipcRenderer;
|
||||
const requestId = i++;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
reqResolves[requestId] = resolve;
|
||||
|
||||
console.log(now(), "Request #" + requestId + " to " + method + " " + url);
|
||||
console.log(utils.now(), "Request #" + requestId + " to " + method + " " + url);
|
||||
|
||||
ipc.send('server-request', {
|
||||
requestId: requestId,
|
||||
@ -58,11 +58,11 @@ const server = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
const ipc = require('electron').ipcRenderer;
|
||||
|
||||
ipc.on('server-response', (event, arg) => {
|
||||
console.log(now(), "Response #" + arg.requestId + ": " + arg.statusCode);
|
||||
console.log(utils.now(), "Response #" + arg.requestId + ": " + arg.statusCode);
|
||||
|
||||
reqResolves[arg.requestId](arg.body);
|
||||
|
||||
@ -84,8 +84,8 @@ const server = (function() {
|
||||
|
||||
return await $.ajax(options).catch(e => {
|
||||
const message = "Error when calling " + method + " " + url + ": " + e.status + " - " + e.statusText;
|
||||
showError(message);
|
||||
throwError(message);
|
||||
utils.showError(message);
|
||||
utils.throwError(message);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,14 @@ async function syncNow() {
|
||||
const result = await server.post('sync/now');
|
||||
|
||||
if (result.success) {
|
||||
showMessage("Sync finished successfully.");
|
||||
utils.showMessage("Sync finished successfully.");
|
||||
}
|
||||
else {
|
||||
if (result.message.length > 50) {
|
||||
result.message = result.message.substr(0, 50);
|
||||
}
|
||||
|
||||
showError("Sync failed: " + result.message);
|
||||
utils.showError("Sync failed: " + result.message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,5 +20,5 @@ $("#sync-now-button").click(syncNow);
|
||||
async function forceNoteSync(noteId) {
|
||||
const result = await server.post('sync/force-note-sync/' + noteId);
|
||||
|
||||
showMessage("Note added to sync queue.");
|
||||
utils.showMessage("Note added to sync queue.");
|
||||
}
|
@ -72,7 +72,7 @@ const treeChanges = (function() {
|
||||
next = nodes[0].getPrevSibling();
|
||||
}
|
||||
|
||||
if (!next && !isTopLevelNode(nodes[0])) {
|
||||
if (!next && !utils.isTopLevelNode(nodes[0])) {
|
||||
next = nodes[0].getParent();
|
||||
}
|
||||
|
||||
@ -85,11 +85,11 @@ const treeChanges = (function() {
|
||||
|
||||
treeService.reload();
|
||||
|
||||
showMessage("Note(s) has been deleted.");
|
||||
utils.showMessage("Note(s) has been deleted.");
|
||||
}
|
||||
|
||||
async function moveNodeUpInHierarchy(node) {
|
||||
if (isTopLevelNode(node)) {
|
||||
if (utils.isTopLevelNode(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ const treeChanges = (function() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isTopLevelNode(node) && node.getParent().getChildren().length <= 1) {
|
||||
if (!utils.isTopLevelNode(node) && node.getParent().getChildren().length <= 1) {
|
||||
node.getParent().folder = false;
|
||||
node.getParent().renderTitle();
|
||||
}
|
||||
@ -109,13 +109,13 @@ const treeChanges = (function() {
|
||||
}
|
||||
|
||||
function changeNode(node, func) {
|
||||
assertArguments(node.data.parentNoteId, node.data.noteId);
|
||||
utils.assertArguments(node.data.parentNoteId, node.data.noteId);
|
||||
|
||||
treeService.removeParentChildRelation(node.data.parentNoteId, node.data.noteId);
|
||||
|
||||
func(node);
|
||||
|
||||
node.data.parentNoteId = isTopLevelNode(node) ? 'root' : node.getParent().data.noteId;
|
||||
node.data.parentNoteId = utils.isTopLevelNode(node) ? 'root' : node.getParent().data.noteId;
|
||||
|
||||
treeService.setParentChildRelation(node.data.branchId, node.data.parentNoteId, node.data.noteId);
|
||||
|
||||
|
@ -4,7 +4,7 @@ const treeUtils = (function() {
|
||||
const $tree = $("#tree");
|
||||
|
||||
function getParentProtectedStatus(node) {
|
||||
return isTopLevelNode(node) ? 0 : node.getParent().data.isProtected;
|
||||
return utils.isTopLevelNode(node) ? 0 : node.getParent().data.isProtected;
|
||||
}
|
||||
|
||||
function getNodeByKey(key) {
|
||||
@ -20,7 +20,7 @@ const treeUtils = (function() {
|
||||
function getNotePath(node) {
|
||||
const path = [];
|
||||
|
||||
while (node && !isRootNode(node)) {
|
||||
while (node && !utils.isRootNode(node)) {
|
||||
if (node.data.noteId) {
|
||||
path.push(node.data.noteId);
|
||||
}
|
||||
|
@ -1,233 +1,270 @@
|
||||
"use strict";
|
||||
|
||||
function reloadApp() {
|
||||
window.location.reload(true);
|
||||
}
|
||||
|
||||
function showMessage(message) {
|
||||
console.log(now(), "message: ", message);
|
||||
|
||||
$.notify({
|
||||
// options
|
||||
message: message
|
||||
},{
|
||||
// settings
|
||||
type: 'success',
|
||||
delay: 3000
|
||||
});
|
||||
}
|
||||
|
||||
function showError(message, delay = 10000) {
|
||||
console.log(now(), "error: ", message);
|
||||
|
||||
$.notify({
|
||||
// options
|
||||
message: message
|
||||
},{
|
||||
// settings
|
||||
type: 'danger',
|
||||
delay: delay
|
||||
});
|
||||
}
|
||||
|
||||
function throwError(message) {
|
||||
messaging.logError(message);
|
||||
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
function parseDate(str) {
|
||||
try {
|
||||
return new Date(Date.parse(str));
|
||||
const utils = (function() {
|
||||
function reloadApp() {
|
||||
window.location.reload(true);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error("Can't parse date from " + str + ": " + e.stack);
|
||||
|
||||
function showMessage(message) {
|
||||
console.log(now(), "message: ", message);
|
||||
|
||||
$.notify({
|
||||
// options
|
||||
message: message
|
||||
}, {
|
||||
// settings
|
||||
type: 'success',
|
||||
delay: 3000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function padNum(num) {
|
||||
return (num <= 9 ? "0" : "") + num;
|
||||
}
|
||||
function showError(message, delay = 10000) {
|
||||
console.log(now(), "error: ", message);
|
||||
|
||||
function formatTime(date) {
|
||||
return padNum(date.getHours()) + ":" + padNum(date.getMinutes());
|
||||
}
|
||||
$.notify({
|
||||
// options
|
||||
message: message
|
||||
}, {
|
||||
// settings
|
||||
type: 'danger',
|
||||
delay: delay
|
||||
});
|
||||
}
|
||||
|
||||
function formatTimeWithSeconds(date) {
|
||||
return padNum(date.getHours()) + ":" + padNum(date.getMinutes()) + ":" + padNum(date.getSeconds());
|
||||
}
|
||||
function throwError(message) {
|
||||
messaging.logError(message);
|
||||
|
||||
function formatDate(date) {
|
||||
return padNum(date.getDate()) + ". " + padNum(date.getMonth() + 1) + ". " + date.getFullYear();
|
||||
}
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
function formatDateISO(date) {
|
||||
return date.getFullYear() + "-" + padNum(date.getMonth() + 1) + "-" + padNum(date.getDate());
|
||||
}
|
||||
|
||||
function formatDateTime(date) {
|
||||
return formatDate(date) + " " + formatTime(date);
|
||||
}
|
||||
|
||||
function now() {
|
||||
return formatTimeWithSeconds(new Date());
|
||||
}
|
||||
|
||||
function isElectron() {
|
||||
return window && window.process && window.process.type;
|
||||
}
|
||||
|
||||
function assertArguments() {
|
||||
for (const i in arguments) {
|
||||
if (!arguments[i]) {
|
||||
throwError(`Argument idx#${i} should not be falsy: ${arguments[i]}`);
|
||||
function parseDate(str) {
|
||||
try {
|
||||
return new Date(Date.parse(str));
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error("Can't parse date from " + str + ": " + e.stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assert(expr, message) {
|
||||
if (!expr) {
|
||||
throwError(message);
|
||||
}
|
||||
}
|
||||
|
||||
function isTopLevelNode(node) {
|
||||
return isRootNode(node.getParent());
|
||||
}
|
||||
|
||||
function isRootNode(node) {
|
||||
return node.key === "root_1";
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
return $('<div/>').text(str).html();
|
||||
}
|
||||
|
||||
async function stopWatch(what, func) {
|
||||
const start = new Date();
|
||||
|
||||
const ret = await func();
|
||||
|
||||
const tookMs = new Date().getTime() - start.getTime();
|
||||
|
||||
console.log(`${what} took ${tookMs}ms`);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
async function executeBundle(bundle) {
|
||||
const apiContext = ScriptContext(bundle.note, bundle.allNotes);
|
||||
|
||||
return await (function() { return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`); }.call(apiContext));
|
||||
}
|
||||
|
||||
function formatValueWithWhitespace(val) {
|
||||
return /[^\w_-]/.test(val) ? '"' + val + '"' : val;
|
||||
}
|
||||
|
||||
function formatLabel(attr) {
|
||||
let str = "@" + formatValueWithWhitespace(attr.name);
|
||||
|
||||
if (attr.value !== "") {
|
||||
str += "=" + formatValueWithWhitespace(attr.value);
|
||||
function padNum(num) {
|
||||
return (num <= 9 ? "0" : "") + num;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
const CKEDITOR = { "js": ["libraries/ckeditor/ckeditor.js"] };
|
||||
|
||||
const CODE_MIRROR = {
|
||||
js: [
|
||||
"libraries/codemirror/codemirror.js",
|
||||
"libraries/codemirror/addon/mode/loadmode.js",
|
||||
"libraries/codemirror/addon/fold/xml-fold.js",
|
||||
"libraries/codemirror/addon/edit/matchbrackets.js",
|
||||
"libraries/codemirror/addon/edit/matchtags.js",
|
||||
"libraries/codemirror/addon/search/match-highlighter.js",
|
||||
"libraries/codemirror/mode/meta.js",
|
||||
"libraries/codemirror/addon/lint/lint.js",
|
||||
"libraries/codemirror/addon/lint/eslint.js"
|
||||
],
|
||||
css: [
|
||||
"libraries/codemirror/codemirror.css",
|
||||
"libraries/codemirror/addon/lint/lint.css"
|
||||
]
|
||||
};
|
||||
|
||||
const ESLINT = { js: [ "libraries/eslint.js" ] };
|
||||
|
||||
async function requireLibrary(library) {
|
||||
if (library.css) {
|
||||
library.css.map(cssUrl => requireCss(cssUrl));
|
||||
function formatTime(date) {
|
||||
return padNum(date.getHours()) + ":" + padNum(date.getMinutes());
|
||||
}
|
||||
|
||||
if (library.js) {
|
||||
for (const scriptUrl of library.js) {
|
||||
await requireScript(scriptUrl);
|
||||
function formatTimeWithSeconds(date) {
|
||||
return padNum(date.getHours()) + ":" + padNum(date.getMinutes()) + ":" + padNum(date.getSeconds());
|
||||
}
|
||||
|
||||
function formatDate(date) {
|
||||
return padNum(date.getDate()) + ". " + padNum(date.getMonth() + 1) + ". " + date.getFullYear();
|
||||
}
|
||||
|
||||
function formatDateISO(date) {
|
||||
return date.getFullYear() + "-" + padNum(date.getMonth() + 1) + "-" + padNum(date.getDate());
|
||||
}
|
||||
|
||||
function formatDateTime(date) {
|
||||
return formatDate(date) + " " + formatTime(date);
|
||||
}
|
||||
|
||||
function now() {
|
||||
return formatTimeWithSeconds(new Date());
|
||||
}
|
||||
|
||||
function isElectron() {
|
||||
return window && window.process && window.process.type;
|
||||
}
|
||||
|
||||
function assertArguments() {
|
||||
for (const i in arguments) {
|
||||
if (!arguments[i]) {
|
||||
throwError(`Argument idx#${i} should not be falsy: ${arguments[i]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dynamicallyLoadedScripts = [];
|
||||
|
||||
async function requireScript(url) {
|
||||
if (!dynamicallyLoadedScripts.includes(url)) {
|
||||
dynamicallyLoadedScripts.push(url);
|
||||
|
||||
return await $.ajax({
|
||||
url: url,
|
||||
dataType: "script",
|
||||
cache: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function requireCss(url) {
|
||||
const css = Array
|
||||
.from(document.querySelectorAll('link'))
|
||||
.map(scr => scr.href);
|
||||
|
||||
if (!css.includes(url)) {
|
||||
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url));
|
||||
}
|
||||
}
|
||||
|
||||
function getHost() {
|
||||
const url = new URL(window.location.href);
|
||||
return url.protocol + "//" + url.hostname + ":" + url.port;
|
||||
}
|
||||
|
||||
function download(url) {
|
||||
if (isElectron()) {
|
||||
const remote = require('electron').remote;
|
||||
|
||||
remote.getCurrentWebContents().downloadURL(url);
|
||||
}
|
||||
else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
function toObject(array, fn) {
|
||||
const obj = {};
|
||||
|
||||
for (const item of array) {
|
||||
const ret = fn(item);
|
||||
|
||||
obj[ret[0]] = ret[1];
|
||||
function assert(expr, message) {
|
||||
if (!expr) {
|
||||
throwError(message);
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function randomString(len) {
|
||||
let text = "";
|
||||
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
function isTopLevelNode(node) {
|
||||
return isRootNode(node.getParent());
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
function isRootNode(node) {
|
||||
return node.key === "root_1";
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
return $('<div/>').text(str).html();
|
||||
}
|
||||
|
||||
async function stopWatch(what, func) {
|
||||
const start = new Date();
|
||||
|
||||
const ret = await func();
|
||||
|
||||
const tookMs = new Date().getTime() - start.getTime();
|
||||
|
||||
console.log(`${what} took ${tookMs}ms`);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
async function executeBundle(bundle) {
|
||||
const apiContext = ScriptContext(bundle.note, bundle.allNotes);
|
||||
|
||||
return await (function () {
|
||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||
}.call(apiContext));
|
||||
}
|
||||
|
||||
function formatValueWithWhitespace(val) {
|
||||
return /[^\w_-]/.test(val) ? '"' + val + '"' : val;
|
||||
}
|
||||
|
||||
function formatLabel(attr) {
|
||||
let str = "@" + formatValueWithWhitespace(attr.name);
|
||||
|
||||
if (attr.value !== "") {
|
||||
str += "=" + formatValueWithWhitespace(attr.value);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
const CKEDITOR = {"js": ["libraries/ckeditor/ckeditor.js"]};
|
||||
|
||||
const CODE_MIRROR = {
|
||||
js: [
|
||||
"libraries/codemirror/codemirror.js",
|
||||
"libraries/codemirror/addon/mode/loadmode.js",
|
||||
"libraries/codemirror/addon/fold/xml-fold.js",
|
||||
"libraries/codemirror/addon/edit/matchbrackets.js",
|
||||
"libraries/codemirror/addon/edit/matchtags.js",
|
||||
"libraries/codemirror/addon/search/match-highlighter.js",
|
||||
"libraries/codemirror/mode/meta.js",
|
||||
"libraries/codemirror/addon/lint/lint.js",
|
||||
"libraries/codemirror/addon/lint/eslint.js"
|
||||
],
|
||||
css: [
|
||||
"libraries/codemirror/codemirror.css",
|
||||
"libraries/codemirror/addon/lint/lint.css"
|
||||
]
|
||||
};
|
||||
|
||||
const ESLINT = {js: ["libraries/eslint.js"]};
|
||||
|
||||
async function requireLibrary(library) {
|
||||
if (library.css) {
|
||||
library.css.map(cssUrl => requireCss(cssUrl));
|
||||
}
|
||||
|
||||
if (library.js) {
|
||||
for (const scriptUrl of library.js) {
|
||||
await requireScript(scriptUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dynamicallyLoadedScripts = [];
|
||||
|
||||
async function requireScript(url) {
|
||||
if (!dynamicallyLoadedScripts.includes(url)) {
|
||||
dynamicallyLoadedScripts.push(url);
|
||||
|
||||
return await $.ajax({
|
||||
url: url,
|
||||
dataType: "script",
|
||||
cache: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function requireCss(url) {
|
||||
const css = Array
|
||||
.from(document.querySelectorAll('link'))
|
||||
.map(scr => scr.href);
|
||||
|
||||
if (!css.includes(url)) {
|
||||
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url));
|
||||
}
|
||||
}
|
||||
|
||||
function getHost() {
|
||||
const url = new URL(window.location.href);
|
||||
return url.protocol + "//" + url.hostname + ":" + url.port;
|
||||
}
|
||||
|
||||
function download(url) {
|
||||
if (isElectron()) {
|
||||
const remote = require('electron').remote;
|
||||
|
||||
remote.getCurrentWebContents().downloadURL(url);
|
||||
}
|
||||
else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
function toObject(array, fn) {
|
||||
const obj = {};
|
||||
|
||||
for (const item of array) {
|
||||
const ret = fn(item);
|
||||
|
||||
obj[ret[0]] = ret[1];
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function randomString(len) {
|
||||
let text = "";
|
||||
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
return {
|
||||
reloadApp,
|
||||
showMessage,
|
||||
showError,
|
||||
throwError,
|
||||
parseDate,
|
||||
padNum,
|
||||
formatTime,
|
||||
formatTimeWithSeconds,
|
||||
formatDate,
|
||||
formatDateISO,
|
||||
formatDateTime,
|
||||
now,
|
||||
isElectron,
|
||||
assertArguments,
|
||||
assert,
|
||||
isTopLevelNode,
|
||||
isRootNode,
|
||||
escapeHtml,
|
||||
stopWatch,
|
||||
executeBundle,
|
||||
formatValueWithWhitespace,
|
||||
formatLabel,
|
||||
requireLibrary,
|
||||
CKEDITOR,
|
||||
CODE_MIRROR,
|
||||
ESLINT,
|
||||
getHost,
|
||||
download,
|
||||
toObject,
|
||||
randomString
|
||||
};
|
||||
})();
|
Loading…
x
Reference in New Issue
Block a user