mirror of
https://github.com/zadam/trilium.git
synced 2025-10-27 16:26:31 +01:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
402e5c4d81 | ||
|
|
5157fc15e9 | ||
|
|
4bd87b1796 | ||
|
|
ce33eb3abd | ||
|
|
f988935a33 | ||
|
|
9b05d30b47 | ||
|
|
9e97fdcc49 | ||
|
|
8e8148ce42 |
3
.idea/codeStyles/Project.xml
generated
3
.idea/codeStyles/Project.xml
generated
@@ -6,9 +6,6 @@
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</value>
|
||||
</option>
|
||||
<H2CodeStyleSettings version="5">
|
||||
<option name="USE_GENERAL_STYLE" value="false" />
|
||||
</H2CodeStyleSettings>
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="USE_EXPLICIT_JS_EXTENSION" value="TRUE" />
|
||||
</JSCodeStyleSettings>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2
libraries/boxicons/css/boxicons.min.css
vendored
2
libraries/boxicons/css/boxicons.min.css
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 912 KiB After Width: | Height: | Size: 952 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
2
libraries/ckeditor/ckeditor.js
vendored
2
libraries/ckeditor/ckeditor.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
56
package-lock.json
generated
56
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"version": "0.45.1",
|
||||
"version": "0.45.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -586,11 +586,6 @@
|
||||
"defer-to-connect": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@tokenizer/token": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz",
|
||||
"integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w=="
|
||||
},
|
||||
"@tootallnate/once": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.0.0.tgz",
|
||||
@@ -611,7 +606,8 @@
|
||||
"@types/debug": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
|
||||
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ=="
|
||||
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "7.2.4",
|
||||
@@ -2658,9 +2654,9 @@
|
||||
}
|
||||
},
|
||||
"electron": {
|
||||
"version": "9.3.3",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-9.3.3.tgz",
|
||||
"integrity": "sha512-xghKeUY1qgnEcJ5w2rXo/toH+8NT2Dktx2aAxBNPV7CIJr3mejJJAPwLbycwtddzr37tgKxHeHlc8ivfKtMkJQ==",
|
||||
"version": "9.3.4",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-9.3.4.tgz",
|
||||
"integrity": "sha512-OHP8qMKgW8D8GtH+altB22WJw/lBOyyVdoz5e8D0/iPBmJU3Jm93vO4z4Eh/9DvdSXlH8bMHUCMLL9PVW6f+tw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@electron/get": "^1.0.1",
|
||||
@@ -3680,17 +3676,6 @@
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"file-type": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-16.0.0.tgz",
|
||||
"integrity": "sha512-0u4D11yDu0NXF+8qp1eiQ/6cOwPI7sbu9/bGzUOhlwzKbB9FYFivgTtsVPtlkXAakfByWjOsLp2/Jx927OVetg==",
|
||||
"requires": {
|
||||
"readable-web-to-node-stream": "^2.0.0",
|
||||
"strtok3": "^6.0.3",
|
||||
"token-types": "^2.0.0",
|
||||
"typedarray-to-buffer": "^3.1.5"
|
||||
}
|
||||
},
|
||||
"file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
@@ -5882,11 +5867,6 @@
|
||||
"pify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"peek-readable": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.0.tgz",
|
||||
"integrity": "sha512-KGuODSTV6hcgdZvDrIDBUkN0utcAVj1LL7FfGbM0viKTtCHmtZcuEJ+lGqsp0fTFkGqesdtemV2yUSMeyy3ddA=="
|
||||
},
|
||||
"pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
@@ -6229,11 +6209,6 @@
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"readable-web-to-node-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-+oZJurc4hXpaaqsN68GoZGQAQIA3qr09Or4fqEsargABnbe5Aau8hFn6ISVleT3cpY/0n/8drn7huyyEvTbghA=="
|
||||
},
|
||||
"rechoir": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz",
|
||||
@@ -7005,16 +6980,6 @@
|
||||
"resolved": "https://registry.npmjs.org/striptags/-/striptags-3.1.1.tgz",
|
||||
"integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0="
|
||||
},
|
||||
"strtok3": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.4.tgz",
|
||||
"integrity": "sha512-rqWMKwsbN9APU47bQTMEYTPcwdpKDtmf1jVhHzNW2cL1WqAxaM9iBb9t5P2fj+RV2YsErUWgQzHD5JwV0uCTEQ==",
|
||||
"requires": {
|
||||
"@tokenizer/token": "^0.1.1",
|
||||
"@types/debug": "^4.1.5",
|
||||
"peek-readable": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
@@ -7293,15 +7258,6 @@
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"token-types": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/token-types/-/token-types-2.0.0.tgz",
|
||||
"integrity": "sha512-WWvu8sGK8/ZmGusekZJJ5NM6rRVTTDO7/bahz4NGiSDb/XsmdYBn6a1N/bymUHuWYTWeuLUg98wUzvE4jPdCZw==",
|
||||
"requires": {
|
||||
"@tokenizer/token": "^0.1.0",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.3",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
@@ -76,7 +76,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "7.0.2",
|
||||
"electron": "9.3.3",
|
||||
"electron": "9.3.4",
|
||||
"electron-builder": "22.9.1",
|
||||
"electron-packager": "15.1.0",
|
||||
"electron-rebuild": "2.3.2",
|
||||
|
||||
@@ -3,6 +3,7 @@ import utils from "../services/utils.js";
|
||||
import ws from "../services/ws.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import treeCache from "../services/tree_cache.js";
|
||||
import openService from "../services/open.js";
|
||||
|
||||
const $dialog = $("#export-dialog");
|
||||
const $form = $("#export-form");
|
||||
@@ -73,9 +74,9 @@ $form.on('submit', () => {
|
||||
function exportBranch(branchId, type, format, version) {
|
||||
taskId = utils.randomString(10);
|
||||
|
||||
const url = utils.getUrlForDownload(`api/notes/${branchId}/export/${type}/${format}/${version}/${taskId}`);
|
||||
const url = openService.getUrlForDownload(`api/notes/${branchId}/export/${type}/${format}/${version}/${taskId}`);
|
||||
|
||||
utils.download(url);
|
||||
openService.download(url);
|
||||
}
|
||||
|
||||
$('input[name=export-type]').on('change', function () {
|
||||
@@ -133,4 +134,4 @@ ws.subscribeToMessages(async message => {
|
||||
|
||||
toastService.showPersistent(toast);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,8 @@ import utils from '../services/utils.js';
|
||||
import server from '../services/server.js';
|
||||
import toastService from "../services/toast.js";
|
||||
import appContext from "../services/app_context.js";
|
||||
import libraryLoader from "../services/library_loader.js";
|
||||
import openService from "../services/open.js";
|
||||
|
||||
const $dialog = $("#note-revisions-dialog");
|
||||
const $list = $("#note-revision-list");
|
||||
@@ -120,11 +122,7 @@ async function setContentPane() {
|
||||
|
||||
const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>');
|
||||
|
||||
$downloadButton.on('click', () => {
|
||||
const url = utils.getUrlForDownload(`api/notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}/download`);
|
||||
|
||||
utils.download(url);
|
||||
});
|
||||
$downloadButton.on('click', () => openService.downloadNoteRevision(revisionItem.noteId, revisionItem.noteRevisionId));
|
||||
|
||||
$titleButtons.append($downloadButton);
|
||||
|
||||
@@ -132,6 +130,12 @@ async function setContentPane() {
|
||||
|
||||
if (revisionItem.type === 'text') {
|
||||
$content.html(fullNoteRevision.content);
|
||||
|
||||
if ($content.find('span.math-tex').length > 0) {
|
||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
||||
|
||||
renderMathInElement($content[0], {});
|
||||
}
|
||||
}
|
||||
else if (revisionItem.type === 'code') {
|
||||
$content.html($("<pre>").text(fullNoteRevision.content));
|
||||
|
||||
@@ -81,7 +81,7 @@ export default class KeyboardShortcutsOptions {
|
||||
.filter(shortcut => !!shortcut);
|
||||
|
||||
const opts = {};
|
||||
opts['keyboardShortcuts' + actionName] = JSON.stringify(shortcuts);
|
||||
opts['keyboardShortcuts' + actionName.substr(0, 1).toUpperCase() + actionName.substr(1)] = JSON.stringify(shortcuts);
|
||||
|
||||
server.put('options', opts);
|
||||
});
|
||||
@@ -138,4 +138,4 @@ export default class KeyboardShortcutsOptions {
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class NoteShort {
|
||||
/** @param {string} content-type, e.g. "application/json" */
|
||||
this.mime = row.mime;
|
||||
/** @param {boolean} */
|
||||
this.isDeleted = row.isDeleted;
|
||||
this.isDeleted = !!row.isDeleted;
|
||||
}
|
||||
|
||||
addParent(parentNoteId, branchId) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import server from "./server.js";
|
||||
import utils from "./utils.js";
|
||||
import renderService from "./render.js";
|
||||
import protectedSessionService from "./protected_session.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import libraryLoader from "./library_loader.js";
|
||||
import openService from "./open.js";
|
||||
|
||||
async function getRenderedContent(note) {
|
||||
const type = getRenderingType(note);
|
||||
@@ -32,24 +32,11 @@ async function getRenderedContent(note) {
|
||||
.css("max-width", "100%");
|
||||
}
|
||||
else if (type === 'file' || type === 'pdf') {
|
||||
function getFileUrl() {
|
||||
return utils.getUrlForDownload("api/notes/" + note.noteId + "/download");
|
||||
}
|
||||
|
||||
const $downloadButton = $('<button class="file-download btn btn-primary" type="button">Download</button>');
|
||||
const $openButton = $('<button class="file-open btn btn-primary" type="button">Open</button>');
|
||||
|
||||
$downloadButton.on('click', () => utils.download(getFileUrl()));
|
||||
$openButton.on('click', () => {
|
||||
if (utils.isElectron()) {
|
||||
const open = utils.dynamicRequire("open");
|
||||
|
||||
open(getFileUrl(), {url: true});
|
||||
}
|
||||
else {
|
||||
window.location.href = getFileUrl();
|
||||
}
|
||||
});
|
||||
$downloadButton.on('click', () => openService.downloadFileNote(note.noteId));
|
||||
$openButton.on('click', () => openService.openFileNote(note.noteId));
|
||||
|
||||
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
||||
$openButton.toggle(!note.isProtected);
|
||||
@@ -58,7 +45,7 @@ async function getRenderedContent(note) {
|
||||
|
||||
if (type === 'pdf') {
|
||||
const $pdfPreview = $('<iframe class="pdf-preview" style="width: 100%; flex-grow: 100;"></iframe>');
|
||||
$pdfPreview.attr("src", utils.getUrlForDownload("api/notes/" + note.noteId + "/open"));
|
||||
$pdfPreview.attr("src", openService.getUrlForDownload("api/notes/" + note.noteId + "/open"));
|
||||
|
||||
$rendered.append($pdfPreview);
|
||||
}
|
||||
|
||||
71
src/public/app/services/open.js
Normal file
71
src/public/app/services/open.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import utils from "./utils.js";
|
||||
import server from "./server.js";
|
||||
|
||||
function getFileUrl(noteId) {
|
||||
return getUrlForDownload("api/notes/" + noteId + "/download");
|
||||
}
|
||||
|
||||
function download(url) {
|
||||
if (utils.isElectron()) {
|
||||
const remote = utils.dynamicRequire('electron').remote;
|
||||
|
||||
remote.getCurrentWebContents().downloadURL(url);
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
function downloadFileNote(noteId) {
|
||||
const url = getFileUrl(noteId) + '?' + Date.now(); // don't use cache
|
||||
|
||||
download(url);
|
||||
}
|
||||
|
||||
async function openFileNote(noteId) {
|
||||
if (utils.isElectron()) {
|
||||
const resp = await server.post("notes/" + noteId + "/saveToTmpDir");
|
||||
|
||||
const electron = utils.dynamicRequire('electron');
|
||||
const res = await electron.shell.openPath(resp.tmpFilePath);
|
||||
|
||||
if (res) {
|
||||
// fallback in case there's no default application for this file
|
||||
open(getFileUrl(noteId), {url: true});
|
||||
}
|
||||
}
|
||||
else {
|
||||
window.location.href = getFileUrl(noteId);
|
||||
}
|
||||
}
|
||||
|
||||
function downloadNoteRevision(noteId, noteRevisionId) {
|
||||
const url = getUrlForDownload(`api/notes/${noteId}/revisions/${noteRevisionId}/download`);
|
||||
|
||||
download(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url - should be without initial slash!!!
|
||||
*/
|
||||
function getUrlForDownload(url) {
|
||||
if (utils.isElectron()) {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return getHost() + '/' + url;
|
||||
}
|
||||
else {
|
||||
// web server can be deployed on subdomain so we need to use relative path
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
function getHost() {
|
||||
const url = new URL(window.location.href);
|
||||
return url.protocol + "//" + url.hostname + ":" + url.port;
|
||||
}
|
||||
|
||||
export default {
|
||||
downloadFileNote,
|
||||
openFileNote,
|
||||
downloadNoteRevision,
|
||||
getUrlForDownload
|
||||
}
|
||||
@@ -105,24 +105,6 @@ function formatLabel(label) {
|
||||
return str;
|
||||
}
|
||||
|
||||
function getHost() {
|
||||
const url = new URL(window.location.href);
|
||||
return url.protocol + "//" + url.hostname + ":" + url.port;
|
||||
}
|
||||
|
||||
function download(url) {
|
||||
url += '?' + Date.now(); // don't use cache
|
||||
|
||||
if (isElectron()) {
|
||||
const remote = dynamicRequire('electron').remote;
|
||||
|
||||
remote.getCurrentWebContents().downloadURL(url);
|
||||
}
|
||||
else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
function toObject(array, fn) {
|
||||
const obj = {};
|
||||
|
||||
@@ -294,20 +276,6 @@ async function clearBrowserCache() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url - should be without initial slash!!!
|
||||
*/
|
||||
function getUrlForDownload(url) {
|
||||
if (isElectron()) {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return getHost() + '/' + url;
|
||||
}
|
||||
else {
|
||||
// web server can be deployed on subdomain so we need to use relative path
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
function copySelectionToClipboard() {
|
||||
const text = window.getSelection().toString();
|
||||
if (navigator.clipboard) {
|
||||
@@ -366,7 +334,6 @@ export default {
|
||||
escapeHtml,
|
||||
stopWatch,
|
||||
formatLabel,
|
||||
download,
|
||||
toObject,
|
||||
randomString,
|
||||
bindGlobalShortcut,
|
||||
@@ -384,7 +351,6 @@ export default {
|
||||
focusSavedElement,
|
||||
isHtmlEmpty,
|
||||
clearBrowserCache,
|
||||
getUrlForDownload,
|
||||
normalizeShortcut,
|
||||
copySelectionToClipboard,
|
||||
isCKEditorInitialized,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import utils from "../../services/utils.js";
|
||||
import openService from "../../services/open.js";
|
||||
import server from "../../services/server.js";
|
||||
import toastService from "../../services/toast.js";
|
||||
import TypeWidget from "./type_widget.js";
|
||||
@@ -73,24 +74,8 @@ export default class FileTypeWidget extends TypeWidget {
|
||||
this.$uploadNewRevisionButton = this.$widget.find(".file-upload-new-revision");
|
||||
this.$uploadNewRevisionInput = this.$widget.find(".file-upload-new-revision-input");
|
||||
|
||||
this.$downloadButton.on('click', () => utils.download(this.getFileUrl()));
|
||||
|
||||
this.$openButton.on('click', async () => {
|
||||
if (utils.isElectron()) {
|
||||
const resp = await server.post("notes/" + this.noteId + "/saveToTmpDir");
|
||||
|
||||
const electron = utils.dynamicRequire('electron');
|
||||
const res = await electron.shell.openPath(resp.tmpFilePath);
|
||||
|
||||
if (res) {
|
||||
// fallback in case there's no default application for this file
|
||||
open(this.getFileUrl(), {url: true});
|
||||
}
|
||||
}
|
||||
else {
|
||||
window.location.href = this.getFileUrl();
|
||||
}
|
||||
});
|
||||
this.$downloadButton.on('click', () => openService.downloadFileNote(this.noteId));
|
||||
this.$openButton.on('click', () => openService.openFileNote(this.noteId));
|
||||
|
||||
this.$uploadNewRevisionButton.on("click", () => {
|
||||
this.$uploadNewRevisionInput.trigger("click");
|
||||
@@ -146,14 +131,10 @@ export default class FileTypeWidget extends TypeWidget {
|
||||
}
|
||||
else if (note.mime === 'application/pdf') {
|
||||
this.$pdfPreview.show();
|
||||
this.$pdfPreview.attr("src", utils.getUrlForDownload("api/notes/" + this.noteId + "/open"));
|
||||
this.$pdfPreview.attr("src", openService.getUrlForDownload("api/notes/" + this.noteId + "/open"));
|
||||
}
|
||||
|
||||
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
||||
this.$openButton.toggle(!note.isProtected);
|
||||
}
|
||||
|
||||
getFileUrl() {
|
||||
return utils.getUrlForDownload("api/notes/" + this.noteId + "/download");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import utils from "../../services/utils.js";
|
||||
import toastService from "../../services/toast.js";
|
||||
import server from "../../services/server.js";
|
||||
import openService from "../../services/open.js";
|
||||
import TypeWidget from "./type_widget.js";
|
||||
|
||||
const TPL = `
|
||||
@@ -64,7 +65,7 @@ class ImageTypeWidget extends TypeWidget {
|
||||
this.$fileSize = this.$widget.find(".image-filesize");
|
||||
|
||||
this.$imageDownloadButton = this.$widget.find(".image-download");
|
||||
this.$imageDownloadButton.on('click', () => utils.download(this.getFileUrl()));
|
||||
this.$imageDownloadButton.on('click', () => openService.downloadFileNote(this.noteId));
|
||||
|
||||
this.$copyToClipboardButton.on('click',() => {
|
||||
this.$imageWrapper.attr('contenteditable','true');
|
||||
@@ -145,10 +146,6 @@ class ImageTypeWidget extends TypeWidget {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
getFileUrl() {
|
||||
return utils.getUrlForDownload(`api/notes/${this.noteId}/download`);
|
||||
}
|
||||
}
|
||||
|
||||
export default ImageTypeWidget
|
||||
|
||||
@@ -59,7 +59,7 @@ ul.fancytree-container {
|
||||
font-size: x-large;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
content: "\ea1d";
|
||||
content: "\e9b2";
|
||||
position: relative;
|
||||
top: -2px;
|
||||
margin-right: 5px;
|
||||
@@ -72,7 +72,7 @@ ul.fancytree-container {
|
||||
|
||||
.fancytree-node.fancytree-expanded .fancytree-expander:before {
|
||||
font-family: 'boxicons' !important;
|
||||
content: "\ea17";
|
||||
content: "\e9ac";
|
||||
}
|
||||
|
||||
/** some common text styling for cssClass label */
|
||||
|
||||
@@ -12,6 +12,10 @@ async function handleRequest(req, res) {
|
||||
const attrs = repository.getEntities("SELECT * FROM attributes WHERE isDeleted = 0 AND type = 'label' AND name IN ('customRequestHandler', 'customResourceProvider')");
|
||||
|
||||
for (const attr of attrs) {
|
||||
if (!attr.value.trim()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const regex = new RegExp(attr.value);
|
||||
let match;
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = { buildDate:"2020-10-29T22:57:25+01:00", buildRevision: "4f75b6aaafef8144080fd17f403a605f61f5590d" };
|
||||
module.exports = { buildDate:"2020-11-10T22:54:39+01:00", buildRevision: "5157fc15e9f7fa960ee35685426868d5599933dc" };
|
||||
|
||||
@@ -5,8 +5,7 @@ const sanitizeHtml = require('sanitize-html');
|
||||
function sanitize(dirtyHtml) {
|
||||
return sanitizeHtml(dirtyHtml, {
|
||||
allowedTags: [
|
||||
// h1 is removed since that should be note's title
|
||||
'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
||||
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
||||
'li', 'b', 'i', 'strong', 'em', 'strike', 'abbr', 'code', 'hr', 'br', 'div',
|
||||
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'section', 'img',
|
||||
'figure', 'span', 'label', 'input'
|
||||
|
||||
@@ -117,6 +117,8 @@ function convertTextToHtml(text) {
|
||||
}
|
||||
|
||||
function importMarkdown(taskContext, file, parentNote) {
|
||||
const title = utils.getNoteTitle(file.originalname, taskContext.data.replaceUnderscoresWithSpaces);
|
||||
|
||||
const markdownContent = file.buffer.toString("UTF-8");
|
||||
|
||||
const reader = new commonmark.Parser();
|
||||
@@ -127,7 +129,7 @@ function importMarkdown(taskContext, file, parentNote) {
|
||||
|
||||
htmlContent = htmlSanitizer.sanitize(htmlContent);
|
||||
|
||||
const title = utils.getNoteTitle(file.originalname, taskContext.data.replaceUnderscoresWithSpaces);
|
||||
htmlContent = handleH1(htmlContent, title);
|
||||
|
||||
const {note} = noteService.createNewNote({
|
||||
parentNoteId: parentNote.noteId,
|
||||
@@ -143,12 +145,25 @@ function importMarkdown(taskContext, file, parentNote) {
|
||||
return note;
|
||||
}
|
||||
|
||||
function handleH1(content, title) {
|
||||
content = content.replace(/<h1>([^<]*)<\/h1>/gi, (match, text) => {
|
||||
if (title.trim() === text.trim()) {
|
||||
return ""; // remove whole H1 tag
|
||||
} else {
|
||||
return `<h2>${text}</h2>`;
|
||||
}
|
||||
});
|
||||
return content;
|
||||
}
|
||||
|
||||
function importHtml(taskContext, file, parentNote) {
|
||||
const title = utils.getNoteTitle(file.originalname, taskContext.data.replaceUnderscoresWithSpaces);
|
||||
let content = file.buffer.toString("UTF-8");
|
||||
|
||||
content = htmlSanitizer.sanitize(content);
|
||||
|
||||
content = handleH1(content, title);
|
||||
|
||||
const {note} = noteService.createNewNote({
|
||||
parentNoteId: parentNote.noteId,
|
||||
title,
|
||||
|
||||
@@ -275,7 +275,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
|
||||
return ""; // remove whole H1 tag
|
||||
}
|
||||
else {
|
||||
return match;
|
||||
return `<h2>${text}</h2>`;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -365,7 +365,7 @@ const DEFAULT_KEYBOARD_ACTIONS = [
|
||||
},
|
||||
{
|
||||
actionName: "openDevTools",
|
||||
defaultShortcuts: ["CommandOrControl+Shift+I"],
|
||||
defaultShortcuts: isElectron ? ["CommandOrControl+Shift+I"] : [],
|
||||
scope: "window"
|
||||
},
|
||||
{
|
||||
@@ -408,13 +408,7 @@ for (const action of DEFAULT_KEYBOARD_ACTIONS) {
|
||||
}
|
||||
}
|
||||
|
||||
let cachedActions = null;
|
||||
|
||||
function getKeyboardActions() {
|
||||
if (cachedActions) {
|
||||
return cachedActions;
|
||||
}
|
||||
|
||||
const actions = JSON.parse(JSON.stringify(DEFAULT_KEYBOARD_ACTIONS));
|
||||
|
||||
for (const action of actions) {
|
||||
@@ -442,8 +436,6 @@ function getKeyboardActions() {
|
||||
}
|
||||
}
|
||||
|
||||
cachedActions = actions;
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
|
||||
@@ -687,7 +687,7 @@ function eraseDeletedNotes() {
|
||||
|
||||
sql.executeMany(`
|
||||
UPDATE notes
|
||||
SET title = '[deleted]',
|
||||
SET title = '[erased]',
|
||||
isProtected = 0,
|
||||
isErased = 1
|
||||
WHERE noteId IN (???)`, noteIdsToErase);
|
||||
|
||||
Reference in New Issue
Block a user