mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	Merge branch 'master' into dev
# Conflicts: # src/routes/api/sender.js # src/services/import/enex.js
This commit is contained in:
		| @@ -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}); | ||||||
|   | |||||||
| @@ -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'); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user