mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
Merge branch 'master' into dev
# Conflicts: # src/routes/api/sender.js # src/services/import/enex.js
This commit is contained in:
commit
edbb60f2b5
@ -13,10 +13,10 @@
|
|||||||
"url": "https://github.com/zadam/trilium.git"
|
"url": "https://github.com/zadam/trilium.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev node ./src/www",
|
"start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 node ./src/www",
|
||||||
"start-server-no-dir": "cross-env TRILIUM_ENV=dev node ./src/www",
|
"start-server-no-dir": "cross-env TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 node ./src/www",
|
||||||
"start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev electron --inspect=5858 .",
|
"start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
|
||||||
"start-electron-no-dir": "cross-env TRILIUM_ENV=dev electron --inspect=5858 .",
|
"start-electron-no-dir": "cross-env TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
|
||||||
"switch-server": "rm -rf ./node_modules/better-sqlite3 && npm install",
|
"switch-server": "rm -rf ./node_modules/better-sqlite3 && npm install",
|
||||||
"switch-electron": "rm -rf ./node_modules/better-sqlite3 && npm install && ./node_modules/.bin/electron-rebuild",
|
"switch-electron": "rm -rf ./node_modules/better-sqlite3 && npm install && ./node_modules/.bin/electron-rebuild",
|
||||||
"build-api-docs": "./bin/build-api-docs.sh",
|
"build-api-docs": "./bin/build-api-docs.sh",
|
||||||
|
@ -477,13 +477,13 @@ export default class TabManager extends Component {
|
|||||||
this.openAndActivateEmptyTab();
|
this.openAndActivateEmptyTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeAllTabsCommand() {
|
async closeAllTabsCommand() {
|
||||||
for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) {
|
for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) {
|
||||||
await this.removeNoteContext(ntxIdToRemove);
|
await this.removeNoteContext(ntxIdToRemove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeAllTabsExceptForThisCommand({ntxId}) {
|
async closeOtherTabsCommand({ntxId}) {
|
||||||
for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) {
|
for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) {
|
||||||
if (ntxIdToRemove !== ntxId) {
|
if (ntxIdToRemove !== ntxId) {
|
||||||
await this.removeNoteContext(ntxIdToRemove);
|
await this.removeNoteContext(ntxIdToRemove);
|
||||||
@ -491,6 +491,10 @@ export default class TabManager extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async closeTabCommand({ntxId}) {
|
||||||
|
await this.removeNoteContext(ntxId);
|
||||||
|
}
|
||||||
|
|
||||||
async moveTabToNewWindowCommand({ntxId}) {
|
async moveTabToNewWindowCommand({ntxId}) {
|
||||||
const {notePath, hoistedNoteId} = this.getNoteContextById(ntxId);
|
const {notePath, hoistedNoteId} = this.getNoteContextById(ntxId);
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import openService from "./open.js";
|
|||||||
import froca from "./froca.js";
|
import froca from "./froca.js";
|
||||||
import utils from "./utils.js";
|
import utils from "./utils.js";
|
||||||
import linkService from "./link.js";
|
import linkService from "./link.js";
|
||||||
|
import treeService from "./tree.js";
|
||||||
|
|
||||||
let idCounter = 1;
|
let idCounter = 1;
|
||||||
|
|
||||||
@ -31,6 +32,17 @@ async function getRenderedContent(note, options = {}) {
|
|||||||
|
|
||||||
renderMathInElement($renderedContent[0], {trust: true});
|
renderMathInElement($renderedContent[0], {trust: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getNoteIdFromLink = el => treeService.getNoteIdFromNotePath($(el).attr('href'));
|
||||||
|
const referenceLinks = $renderedContent.find("a.reference-link");
|
||||||
|
const noteIdsToPrefetch = referenceLinks.map(el => getNoteIdFromLink(el));
|
||||||
|
await froca.getNotes(noteIdsToPrefetch);
|
||||||
|
|
||||||
|
for (const el of referenceLinks) {
|
||||||
|
const noteId = getNoteIdFromLink(el);
|
||||||
|
|
||||||
|
await linkService.loadReferenceLinkTitle(noteId, $(el));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await renderChildrenList($renderedContent, note);
|
await renderChildrenList($renderedContent, note);
|
||||||
|
@ -460,7 +460,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||||
const files = [...dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
|
const files = [...dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
|
||||||
|
|
||||||
const importService = await import('../services/import');
|
const importService = await import('../services/import.js');
|
||||||
|
|
||||||
importService.uploadFiles(node.data.noteId, files, {
|
importService.uploadFiles(node.data.noteId, files, {
|
||||||
safeImport: true,
|
safeImport: true,
|
||||||
|
@ -262,9 +262,10 @@ export default class TabRowWidget extends BasicWidget {
|
|||||||
x: e.pageX,
|
x: e.pageX,
|
||||||
y: e.pageY,
|
y: e.pageY,
|
||||||
items: [
|
items: [
|
||||||
{title: "Move this tab to a new window", command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"},
|
{title: "Close", command: "closeTab", uiIcon: "bx bx-x"},
|
||||||
{title: "Close all tabs", command: "removeAllTabs", uiIcon: "bx bx-x"},
|
{title: "Close other tabs", command: "closeOtherTabs", uiIcon: "bx bx-x"},
|
||||||
{title: "Close all tabs except for this", command: "removeAllTabsExceptForThis", uiIcon: "bx bx-x"},
|
{title: "Close all tabs", command: "closeAllTabs", uiIcon: "bx bx-x"},
|
||||||
|
{title: "Move this tab to a new window", command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"}
|
||||||
],
|
],
|
||||||
selectMenuItemHandler: ({command}) => {
|
selectMenuItemHandler: ({command}) => {
|
||||||
this.triggerCommand(command, {ntxId});
|
this.triggerCommand(command, {ntxId});
|
||||||
|
@ -126,7 +126,7 @@ export default class TocWidget extends RightPanelWidget {
|
|||||||
getToc(html) {
|
getToc(html) {
|
||||||
// Regular expression for headings <h1>...</h1> using non-greedy
|
// Regular expression for headings <h1>...</h1> using non-greedy
|
||||||
// matching and backreferences
|
// matching and backreferences
|
||||||
const headingTagsRegex = /<h(\d+)>(.*?)<\/h\1>/g;
|
const headingTagsRegex = /<h(\d+)[^>]*>(.*?)<\/h\1>/gi;
|
||||||
|
|
||||||
// Use jquery to build the table rather than html text, since it makes
|
// Use jquery to build the table rather than html text, since it makes
|
||||||
// it easier to set the onclick event that will be executed with the
|
// it easier to set the onclick event that will be executed with the
|
||||||
@ -151,7 +151,8 @@ export default class TocWidget extends RightPanelWidget {
|
|||||||
}
|
}
|
||||||
} else if (levelDelta < 0) {
|
} else if (levelDelta < 0) {
|
||||||
// Close as many lists as curLevel - newLevel
|
// Close as many lists as curLevel - newLevel
|
||||||
for (let i = 0; i < -levelDelta; ++i) {
|
// be careful not to empty $ols completely, the root element should stay (could happen with a rogue h1 element)
|
||||||
|
for (let i = 0; i < -levelDelta && $ols.length > 1; ++i) {
|
||||||
$ols.pop();
|
$ols.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
this.watchdog.editor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate());
|
this.watchdog.editor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate());
|
||||||
|
|
||||||
if (glob.isDev && ENABLE_INSPECTOR) {
|
if (glob.isDev && ENABLE_INSPECTOR) {
|
||||||
await import(/* webpackIgnore: true */'../../../libraries/ckeditor/inspector');
|
await import(/* webpackIgnore: true */'../../../libraries/ckeditor/inspector.js');
|
||||||
CKEditorInspector.attach(this.watchdog.editor);
|
CKEditorInspector.attach(this.watchdog.editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
const imageType = require('image-type');
|
const imageType = require('image-type');
|
||||||
const imageService = require('../../services/image');
|
const imageService = require('../../services/image');
|
||||||
const dateNoteService = require('../../services/date_notes');
|
|
||||||
const noteService = require('../../services/notes');
|
const noteService = require('../../services/notes');
|
||||||
const attributeService = require('../../services/attributes');
|
const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name.js");
|
||||||
const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name");
|
const specialNotesService = require("../../services/special_notes.js");
|
||||||
|
|
||||||
function uploadImage(req) {
|
function uploadImage(req) {
|
||||||
const file = req.file;
|
const file = req.file;
|
||||||
@ -16,7 +15,7 @@ function uploadImage(req) {
|
|||||||
|
|
||||||
const originalName = `Sender image.${imageType(file.buffer).ext}`;
|
const originalName = `Sender image.${imageType(file.buffer).ext}`;
|
||||||
|
|
||||||
const parentNote = dateNoteService.getDayNote(req.headers['x-local-date']);
|
const parentNote = specialNotesService.getInboxNote(req.headers['x-local-date']);
|
||||||
|
|
||||||
const {note, noteId} = imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);
|
const {note, noteId} = imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ function uploadImage(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function saveNote(req) {
|
function saveNote(req) {
|
||||||
const parentNote = dateNoteService.getDayNote(req.headers['x-local-date']);
|
const parentNote = specialNotesService.getInboxNote(req.headers['x-local-date']);
|
||||||
|
|
||||||
const {note, branch} = noteService.createNewNote({
|
const {note, branch} = noteService.createNewNote({
|
||||||
parentNoteId: parentNote.noteId,
|
parentNoteId: parentNote.noteId,
|
||||||
|
@ -8,13 +8,19 @@ const noteService = require("../notes");
|
|||||||
const imageService = require("../image");
|
const imageService = require("../image");
|
||||||
const protectedSessionService = require('../protected_session');
|
const protectedSessionService = require('../protected_session');
|
||||||
const htmlSanitizer = require("../html_sanitizer");
|
const htmlSanitizer = require("../html_sanitizer");
|
||||||
const attributeService = require("../attributes");
|
const {sanitizeAttributeName} = require("../sanitize_attribute_name.js");
|
||||||
const {sanitizeAttributeName} = require("../sanitize_attribute_name");
|
|
||||||
|
|
||||||
// date format is e.g. 20181121T193703Z
|
/**
|
||||||
|
* date format is e.g. 20181121T193703Z or 2013-04-14T16:19:00.000Z (Mac evernote, see #3496)
|
||||||
|
* @returns trilium date format, e.g. 2013-04-14 16:19:00.000Z
|
||||||
|
*/
|
||||||
function parseDate(text) {
|
function parseDate(text) {
|
||||||
// insert - and : to make it ISO format
|
// convert ISO format to the "20181121T193703Z" format
|
||||||
text = `${text.substr(0, 4)}-${text.substr(4, 2)}-${text.substr(6, 2)} ${text.substr(9, 2)}:${text.substr(11, 2)}:${text.substr(13, 2)}.000Z`;
|
text = text.replace(/[-:]/g, "");
|
||||||
|
|
||||||
|
// insert - and : to convert it to trilium format
|
||||||
|
text = text.substr(0, 4) + "-" + text.substr(4, 2) + "-" + text.substr(6, 2)
|
||||||
|
+ " " + text.substr(9, 2) + ":" + text.substr(11, 2) + ":" + text.substr(13, 2) + ".000Z";
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -263,7 +269,7 @@ function importEnex(taskContext, file, parentNote) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mediaRegex = new RegExp(`<en-media hash="${hash}"[^>]*>`, 'g');
|
const mediaRegex = new RegExp(`<en-media [^>]*hash="${hash}"[^>]*>`, 'g');
|
||||||
|
|
||||||
resource.mime = resource.mime || "application/octet-stream";
|
resource.mime = resource.mime || "application/octet-stream";
|
||||||
|
|
||||||
|
@ -15,7 +15,9 @@ function get(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getSyncServerHost: () => get('syncServerHost'),
|
// env variable is the easiest way to guarantee we won't overwrite prod data during development
|
||||||
|
// after copying prod document/data directory
|
||||||
|
getSyncServerHost: () => process.env.TRILIUM_SYNC_SERVER_HOST || get('syncServerHost'),
|
||||||
isSyncSetup: () => {
|
isSyncSetup: () => {
|
||||||
const syncServerHost = get('syncServerHost');
|
const syncServerHost = get('syncServerHost');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user