mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +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" | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev node ./src/www", | ||||
|     "start-server-no-dir": "cross-env TRILIUM_ENV=dev node ./src/www", | ||||
|     "start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev electron --inspect=5858 .", | ||||
|     "start-electron-no-dir": "cross-env TRILIUM_ENV=dev electron --inspect=5858 .", | ||||
|     "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 TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 node ./src/www", | ||||
|     "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 TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .", | ||||
|     "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", | ||||
|     "build-api-docs": "./bin/build-api-docs.sh", | ||||
|   | ||||
| @@ -477,13 +477,13 @@ export default class TabManager extends Component { | ||||
|         this.openAndActivateEmptyTab(); | ||||
|     } | ||||
|  | ||||
|     async removeAllTabsCommand() { | ||||
|     async closeAllTabsCommand() { | ||||
|         for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) { | ||||
|             await this.removeNoteContext(ntxIdToRemove); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async removeAllTabsExceptForThisCommand({ntxId}) { | ||||
|     async closeOtherTabsCommand({ntxId}) { | ||||
|         for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) { | ||||
|             if (ntxIdToRemove !== ntxId) { | ||||
|                 await this.removeNoteContext(ntxIdToRemove); | ||||
| @@ -491,6 +491,10 @@ export default class TabManager extends Component { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async closeTabCommand({ntxId}) { | ||||
|         await this.removeNoteContext(ntxId); | ||||
|     } | ||||
|  | ||||
|     async moveTabToNewWindowCommand({ntxId}) { | ||||
|         const {notePath, hoistedNoteId} = this.getNoteContextById(ntxId); | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import openService from "./open.js"; | ||||
| import froca from "./froca.js"; | ||||
| import utils from "./utils.js"; | ||||
| import linkService from "./link.js"; | ||||
| import treeService from "./tree.js"; | ||||
|  | ||||
| let idCounter = 1; | ||||
|  | ||||
| @@ -31,6 +32,17 @@ async function getRenderedContent(note, options = {}) { | ||||
|  | ||||
|                 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 { | ||||
|             await renderChildrenList($renderedContent, note); | ||||
|   | ||||
| @@ -460,7 +460,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { | ||||
|                     if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { | ||||
|                         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, { | ||||
|                             safeImport: true, | ||||
|   | ||||
| @@ -262,9 +262,10 @@ export default class TabRowWidget extends BasicWidget { | ||||
|                 x: e.pageX, | ||||
|                 y: e.pageY, | ||||
|                 items: [ | ||||
|                     {title: "Move this tab to a new window", command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"}, | ||||
|                     {title: "Close all tabs", command: "removeAllTabs", uiIcon: "bx bx-x"}, | ||||
|                     {title: "Close all tabs except for this", command: "removeAllTabsExceptForThis", uiIcon: "bx bx-x"}, | ||||
|                     {title: "Close", command: "closeTab", uiIcon: "bx bx-x"}, | ||||
|                     {title: "Close other tabs", command: "closeOtherTabs", 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}) => { | ||||
|                     this.triggerCommand(command, {ntxId}); | ||||
|   | ||||
| @@ -126,7 +126,7 @@ export default class TocWidget extends RightPanelWidget { | ||||
|     getToc(html) { | ||||
|         // Regular expression for headings <h1>...</h1> using non-greedy | ||||
|         // 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 | ||||
|         // 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) { | ||||
|                 // 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(); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -172,7 +172,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | ||||
|         this.watchdog.editor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate()); | ||||
|  | ||||
|         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); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -2,10 +2,9 @@ | ||||
|  | ||||
| const imageType = require('image-type'); | ||||
| const imageService = require('../../services/image'); | ||||
| const dateNoteService = require('../../services/date_notes'); | ||||
| const noteService = require('../../services/notes'); | ||||
| const attributeService = require('../../services/attributes'); | ||||
| const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name"); | ||||
| const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name.js"); | ||||
| const specialNotesService = require("../../services/special_notes.js"); | ||||
|  | ||||
| function uploadImage(req) { | ||||
|     const file = req.file; | ||||
| @@ -16,7 +15,7 @@ function uploadImage(req) { | ||||
|  | ||||
|     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); | ||||
|  | ||||
| @@ -38,7 +37,7 @@ function uploadImage(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({ | ||||
|         parentNoteId: parentNote.noteId, | ||||
|   | ||||
| @@ -8,13 +8,19 @@ const noteService = require("../notes"); | ||||
| const imageService = require("../image"); | ||||
| const protectedSessionService = require('../protected_session'); | ||||
| const htmlSanitizer = require("../html_sanitizer"); | ||||
| const attributeService = require("../attributes"); | ||||
| const {sanitizeAttributeName} = require("../sanitize_attribute_name"); | ||||
| const {sanitizeAttributeName} = require("../sanitize_attribute_name.js"); | ||||
|  | ||||
| // 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) { | ||||
|     // insert - and : to make it ISO 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`; | ||||
|     // convert ISO format to the "20181121T193703Z" format | ||||
|     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; | ||||
| } | ||||
| @@ -263,7 +269,7 @@ function importEnex(taskContext, file, parentNote) { | ||||
|                 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"; | ||||
|  | ||||
|   | ||||
| @@ -15,7 +15,9 @@ function get(name) { | ||||
| } | ||||
|  | ||||
| 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: () => { | ||||
|         const syncServerHost = get('syncServerHost'); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user