2017-11-05 07:38:50 +08:00
|
|
|
"use strict";
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
const utils = (function() {
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
throw new Error("Can't parse date from " + str + ": " + e.stack);
|
2017-12-24 01:19:15 +08:00
|
|
|
}
|
2017-12-24 00:02:38 +08:00
|
|
|
}
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function padNum(num) {
|
|
|
|
return (num <= 9 ? "0" : "") + num;
|
2017-12-24 00:02:38 +08:00
|
|
|
}
|
2017-12-24 01:19:15 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function formatTime(date) {
|
|
|
|
return padNum(date.getHours()) + ":" + padNum(date.getMinutes());
|
|
|
|
}
|
2017-12-24 01:19:15 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function formatTimeWithSeconds(date) {
|
|
|
|
return padNum(date.getHours()) + ":" + padNum(date.getMinutes()) + ":" + padNum(date.getSeconds());
|
|
|
|
}
|
2017-12-29 08:00:31 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function formatDate(date) {
|
|
|
|
return padNum(date.getDate()) + ". " + padNum(date.getMonth() + 1) + ". " + date.getFullYear();
|
|
|
|
}
|
2018-01-23 12:18:08 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function formatDateISO(date) {
|
|
|
|
return date.getFullYear() + "-" + padNum(date.getMonth() + 1) + "-" + padNum(date.getDate());
|
|
|
|
}
|
2018-01-23 12:18:08 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function formatDateTime(date) {
|
|
|
|
return formatDate(date) + " " + formatTime(date);
|
|
|
|
}
|
2018-01-23 12:18:08 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function now() {
|
|
|
|
return formatTimeWithSeconds(new Date());
|
|
|
|
}
|
2018-01-23 12:18:08 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function isElectron() {
|
|
|
|
return window && window.process && window.process.type;
|
|
|
|
}
|
2018-01-23 12:18:08 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function assertArguments() {
|
|
|
|
for (const i in arguments) {
|
|
|
|
if (!arguments[i]) {
|
|
|
|
throwError(`Argument idx#${i} should not be falsy: ${arguments[i]}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-26 12:49:03 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function assert(expr, message) {
|
|
|
|
if (!expr) {
|
|
|
|
throwError(message);
|
|
|
|
}
|
|
|
|
}
|
2018-03-07 12:04:35 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function isTopLevelNode(node) {
|
|
|
|
return isRootNode(node.getParent());
|
|
|
|
}
|
2018-02-05 09:23:30 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
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();
|
2018-02-05 09:23:30 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
console.log(`${what} took ${tookMs}ms`);
|
2018-02-05 09:23:30 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
return ret;
|
2018-02-05 09:23:30 +08:00
|
|
|
}
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
async function executeBundle(bundle) {
|
|
|
|
const apiContext = ScriptContext(bundle.note, bundle.allNotes);
|
2018-02-20 11:02:03 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
return await (function () {
|
|
|
|
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
|
|
|
}.call(apiContext));
|
|
|
|
}
|
2018-02-20 11:02:03 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function formatValueWithWhitespace(val) {
|
|
|
|
return /[^\w_-]/.test(val) ? '"' + val + '"' : val;
|
|
|
|
}
|
2018-02-21 12:24:55 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function formatLabel(attr) {
|
|
|
|
let str = "@" + formatValueWithWhitespace(attr.name);
|
2018-02-22 09:30:15 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
if (attr.value !== "") {
|
|
|
|
str += "=" + formatValueWithWhitespace(attr.value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
2018-02-20 11:02:03 +08:00
|
|
|
}
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
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);
|
|
|
|
}
|
2018-02-20 11:02:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
const dynamicallyLoadedScripts = [];
|
2018-02-22 09:30:15 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
async function requireScript(url) {
|
|
|
|
if (!dynamicallyLoadedScripts.includes(url)) {
|
|
|
|
dynamicallyLoadedScripts.push(url);
|
2018-02-20 11:02:03 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
return await $.ajax({
|
|
|
|
url: url,
|
|
|
|
dataType: "script",
|
|
|
|
cache: true
|
|
|
|
})
|
|
|
|
}
|
2018-02-20 11:02:03 +08:00
|
|
|
}
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
async function requireCss(url) {
|
|
|
|
const css = Array
|
|
|
|
.from(document.querySelectorAll('link'))
|
|
|
|
.map(scr => scr.href);
|
2018-02-20 11:02:03 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
if (!css.includes(url)) {
|
|
|
|
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url));
|
|
|
|
}
|
2018-02-20 11:02:03 +08:00
|
|
|
}
|
2018-02-25 23:55:21 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function getHost() {
|
|
|
|
const url = new URL(window.location.href);
|
|
|
|
return url.protocol + "//" + url.hostname + ":" + url.port;
|
|
|
|
}
|
2018-02-25 23:55:21 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function download(url) {
|
|
|
|
if (isElectron()) {
|
|
|
|
const remote = require('electron').remote;
|
2018-02-25 23:55:21 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
remote.getCurrentWebContents().downloadURL(url);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
window.location.href = url;
|
|
|
|
}
|
2018-02-25 23:55:21 +08:00
|
|
|
}
|
2018-03-05 12:28:26 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function toObject(array, fn) {
|
|
|
|
const obj = {};
|
2018-03-05 12:28:26 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
for (const item of array) {
|
|
|
|
const ret = fn(item);
|
2018-03-05 12:28:26 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
obj[ret[0]] = ret[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
2018-03-05 12:28:26 +08:00
|
|
|
}
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
function randomString(len) {
|
|
|
|
let text = "";
|
|
|
|
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
2018-03-13 11:27:21 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
for (let i = 0; i < len; i++) {
|
|
|
|
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
|
|
}
|
2018-03-13 11:27:21 +08:00
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
return text;
|
2018-03-13 11:27:21 +08:00
|
|
|
}
|
|
|
|
|
2018-03-25 11:37:55 +08:00
|
|
|
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
|
|
|
|
};
|
|
|
|
})();
|