mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	Compare commits
	
		
			16 Commits
		
	
	
		
			v0.61.8-be
			...
			v0.61.9-be
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d09d3f5a96 | ||
|  | 3d15aeae58 | ||
|  | 9765892d18 | ||
|  | 78f8a37587 | ||
|  | 86d62866f2 | ||
|  | 1dc3fafcbf | ||
|  | 7f06952d9e | ||
|  | 78b6614eea | ||
|  | 9665e872c2 | ||
|  | 9db0a062ed | ||
|  | 055bb39e4d | ||
|  | 1261a06a30 | ||
|  | 91eb3c45d5 | ||
|  | 3944235592 | ||
|  | 5be61e6142 | ||
|  | 62ccf798ee | 
							
								
								
									
										0
									
								
								bin/create-anonymization-script.js
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								bin/create-anonymization-script.js
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -1,160 +1,42 @@ | ||||
|  | ||||
| UPDATE etapi_tokens SET tokenHash = 'API token hash value'; | ||||
| UPDATE notes SET title = 'title' WHERE noteId != 'root' AND noteId NOT LIKE '\_%' ESCAPE '\'; | ||||
| UPDATE notes SET title = 'title' WHERE title NOT IN ('root', '_hidden', '_share'); | ||||
| UPDATE blobs SET content = 'text' WHERE content IS NOT NULL; | ||||
| UPDATE revisions SET title = 'title'; | ||||
|  | ||||
| UPDATE attributes SET name = 'name', value = 'value' | ||||
|                   WHERE type = 'label' | ||||
|                     AND name NOT IN ('inbox', | ||||
|                                      'disableVersioning', | ||||
|                                      'calendarRoot', | ||||
|                                      'archived', | ||||
|                                      'excludeFromExport', | ||||
|                                      'disableInclusion', | ||||
|                                      'appCss', | ||||
|                                      'appTheme', | ||||
|                                      'hidePromotedAttributes', | ||||
|                                      'readOnly', | ||||
|                                      'autoReadOnlyDisabled', | ||||
|                                      'cssClass', | ||||
|                                      'iconClass', | ||||
|                                      'keyboardShortcut', | ||||
|                                      'run', | ||||
|                                      'runOnInstance', | ||||
|                                      'runAtHour', | ||||
|                                      'customRequestHandler', | ||||
|                                      'customResourceProvider', | ||||
|                                      'widget', | ||||
|                                      'noteInfoWidgetDisabled', | ||||
|                                      'linkMapWidgetDisabled', | ||||
|                                      'revisionsWidgetDisabled', | ||||
|                                      'whatLinksHereWidgetDisabled', | ||||
|                                      'similarNotesWidgetDisabled', | ||||
|                                      'workspace', | ||||
|                                      'workspaceIconClass', | ||||
|                                      'workspaceTabBackgroundColor', | ||||
|                                      'searchHome', | ||||
|                                      'workspaceInbox', | ||||
|                                      'workspaceSearchHome', | ||||
|                                      'sqlConsoleHome', | ||||
|                                      'datePattern', | ||||
|                                      'pageSize', | ||||
|                                      'viewType', | ||||
|                                      'mapRootNoteId', | ||||
|                                      'bookmarkFolder', | ||||
|                                      'sorted', | ||||
|                                      'top', | ||||
|                                      'fullContentWidth', | ||||
|                                      'shareHiddenFromTree', | ||||
|                                      'shareAlias', | ||||
|                                      'shareOmitDefaultCss', | ||||
|                                      'shareRoot', | ||||
|                                      'internalLink', | ||||
|                                      'imageLink', | ||||
|                                      'relationMapLink', | ||||
|                                      'includeMapLink', | ||||
|                                      'runOnNoteCreation', | ||||
|                                      'runOnNoteTitleChange', | ||||
|                                      'runOnNoteContentChange', | ||||
|                                      'runOnNoteChange', | ||||
|                                      'runOnChildNoteCreation', | ||||
|                                      'runOnAttributeCreation', | ||||
|                                      'runOnAttributeChange', | ||||
|                                      'template', | ||||
|                                      'inherit', | ||||
|                                      'widget', | ||||
|                                      'renderNote', | ||||
|                                      'shareCss', | ||||
|                                      'shareJs', | ||||
|                                      'shareFavicon', | ||||
|                                      'executeButton', | ||||
|                                      'keepCurrentHoisting', | ||||
|                                      'color', | ||||
|                                      'toc', | ||||
|                                      'excludeFromNoteMap', | ||||
|                                      'docName', | ||||
|                                      'launcherType', | ||||
|                                      'builtinWidget', | ||||
|                                      'baseSize', | ||||
|                                      'growthFactor' | ||||
|                       ); | ||||
|  | ||||
| UPDATE attributes SET name = 'name' | ||||
|                     AND name NOT IN ('inbox', | ||||
|                                      'disableVersioning', | ||||
|                                      'calendarRoot', | ||||
|                                      'archived', | ||||
|                                      'excludeFromExport', | ||||
|                                      'disableInclusion', | ||||
|                                      'appCss', | ||||
|                                      'appTheme', | ||||
|                                      'hidePromotedAttributes', | ||||
|                                      'readOnly', | ||||
|                                      'autoReadOnlyDisabled', | ||||
|                                      'cssClass', | ||||
|                                      'iconClass', | ||||
|                                      'keyboardShortcut', | ||||
|                                      'run', | ||||
|                                      'runOnInstance', | ||||
|                                      'runAtHour', | ||||
|                                      'customRequestHandler', | ||||
|                                      'customResourceProvider', | ||||
|                                      'widget', | ||||
|                                      'noteInfoWidgetDisabled', | ||||
|                                      'linkMapWidgetDisabled', | ||||
|                                      'revisionsWidgetDisabled', | ||||
|                                      'whatLinksHereWidgetDisabled', | ||||
|                                      'similarNotesWidgetDisabled', | ||||
|                                      'workspace', | ||||
|                                      'workspaceIconClass', | ||||
|                                      'workspaceTabBackgroundColor', | ||||
|                                      'searchHome', | ||||
|                                      'workspaceInbox', | ||||
|                                      'workspaceSearchHome', | ||||
|                                      'sqlConsoleHome', | ||||
|                                      'datePattern', | ||||
|                                      'pageSize', | ||||
|                                      'viewType', | ||||
|                                      'mapRootNoteId', | ||||
|                                      'bookmarkFolder', | ||||
|                                      'sorted', | ||||
|                                      'top', | ||||
|                                      'fullContentWidth', | ||||
|                                      'shareHiddenFromTree', | ||||
|                                      'shareAlias', | ||||
|                                      'shareOmitDefaultCss', | ||||
|                                      'shareRoot', | ||||
|                                      'internalLink', | ||||
|                                      'imageLink', | ||||
|                                      'relationMapLink', | ||||
|                                      'includeMapLink', | ||||
|                                      'runOnNoteCreation', | ||||
|                                      'runOnNoteTitleChange', | ||||
|                                      'runOnNoteContentChange', | ||||
|                                      'runOnNoteChange', | ||||
|                                      'runOnChildNoteCreation', | ||||
|                                      'runOnAttributeCreation', | ||||
|                                      'runOnAttributeChange', | ||||
|                                      'template', | ||||
|                                      'inherit', | ||||
|                                      'widget', | ||||
|                                      'renderNote', | ||||
|                                      'shareCss', | ||||
|                                      'shareJs', | ||||
|                                      'shareFavicon', | ||||
|                                      'executeButton', | ||||
|                                      'keepCurrentHoisting', | ||||
|                                      'color', | ||||
|                                      'toc', | ||||
|                                      'excludeFromNoteMap', | ||||
|                                      'docName', | ||||
|                                      'launcherType', | ||||
|                                      'builtinWidget', | ||||
|                                      'baseSize', | ||||
|                                      'growthFactor' | ||||
|                                     ); | ||||
|  | ||||
| UPDATE attributes SET name  = 'name', value = 'value' WHERE type = 'label' | ||||
|   AND name NOT IN | ||||
|       ('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', | ||||
|        'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass', | ||||
|        'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', | ||||
|        'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled', | ||||
|        'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', | ||||
|        'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox', | ||||
|        'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', | ||||
|        'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top', | ||||
|        'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription', | ||||
|        'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate', | ||||
|        'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop', | ||||
|        'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', | ||||
|        'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation', | ||||
|        'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', | ||||
|        'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon'); | ||||
| UPDATE attributes SET name = 'name' WHERE type = 'relation' | ||||
|   AND name NOT IN | ||||
|       ('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', | ||||
|        'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass', | ||||
|        'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', | ||||
|        'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled', | ||||
|        'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', | ||||
|        'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox', | ||||
|        'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', | ||||
|        'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top', | ||||
|        'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription', | ||||
|        'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate', | ||||
|        'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop', | ||||
|        'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', | ||||
|        'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation', | ||||
|        'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', | ||||
|        'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon'); | ||||
| UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL AND prefix != 'recovered'; | ||||
| UPDATE options SET value = 'anonymized' WHERE name IN | ||||
|       ('documentId', 'documentSecret', 'encryptedDataKey', | ||||
|   | ||||
							
								
								
									
										1
									
								
								db/migrations/0226__rename_noteSize_label.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								db/migrations/0226__rename_noteSize_label.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| UPDATE attributes SET value = 'contentAndAttachmentsAndRevisionsSize' WHERE name = 'orderBy' AND value = 'noteSize'; | ||||
| @@ -1,3 +1,5 @@ | ||||
| # Running `docker-compose up` will create/use the "trilium-data" directory in the user home | ||||
| # Run `TRILIUM_DATA_DIR=/path/of/your/choice docker-compose up` to set a different directory | ||||
| version: '2.1' | ||||
| services: | ||||
|   trilium: | ||||
| @@ -8,7 +10,7 @@ services: | ||||
|     ports: | ||||
|       - "8080:8080" | ||||
|     volumes: | ||||
|       - trilium:/home/node/trilium-data | ||||
|       - ${TRILIUM_DATA_DIR:-~/trilium-data}:/home/node/trilium-data | ||||
|  | ||||
| volumes: | ||||
|   trilium: | ||||
|   | ||||
							
								
								
									
										148
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										148
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,12 +1,12 @@ | ||||
| { | ||||
|   "name": "trilium", | ||||
|   "version": "0.61.7-beta", | ||||
|   "version": "0.61.8-beta", | ||||
|   "lockfileVersion": 2, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "trilium", | ||||
|       "version": "0.61.7-beta", | ||||
|       "version": "0.61.8-beta", | ||||
|       "hasInstallScript": true, | ||||
|       "license": "AGPL-3.0-only", | ||||
|       "dependencies": { | ||||
| @@ -47,7 +47,7 @@ | ||||
|         "jimp": "0.22.10", | ||||
|         "joplin-turndown-plugin-gfm": "1.0.12", | ||||
|         "jsdom": "22.1.0", | ||||
|         "marked": "9.0.3", | ||||
|         "marked": "9.1.0", | ||||
|         "mime-types": "2.1.35", | ||||
|         "multer": "1.4.5-lts.1", | ||||
|         "node-abi": "3.47.0", | ||||
| @@ -57,11 +57,11 @@ | ||||
|         "react": "18.2.0", | ||||
|         "react-dom": "18.2.0", | ||||
|         "request": "2.88.2", | ||||
|         "rimraf": "5.0.1", | ||||
|         "rimraf": "5.0.5", | ||||
|         "safe-compare": "1.1.4", | ||||
|         "sanitize-filename": "1.6.3", | ||||
|         "sanitize-html": "2.11.0", | ||||
|         "sax": "1.2.4", | ||||
|         "sax": "1.3.0", | ||||
|         "semver": "7.5.4", | ||||
|         "serve-favicon": "2.5.0", | ||||
|         "session-file-store": "1.5.0", | ||||
| @@ -79,7 +79,7 @@ | ||||
|       }, | ||||
|       "devDependencies": { | ||||
|         "cross-env": "7.0.3", | ||||
|         "electron": "25.8.3", | ||||
|         "electron": "25.9.0", | ||||
|         "electron-builder": "24.6.4", | ||||
|         "electron-packager": "17.1.2", | ||||
|         "electron-rebuild": "3.2.9", | ||||
| @@ -4276,9 +4276,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/electron": { | ||||
|       "version": "25.8.3", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-25.8.3.tgz", | ||||
|       "integrity": "sha512-BdcTIrhQIf6YgsihCXYh3DgKobtLaNcFb1B5C/5euepxxXQ7qmTWC6WgNUm+IntLOFEDQO926rvm2nhRdSN+Nw==", | ||||
|       "version": "25.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-25.9.0.tgz", | ||||
|       "integrity": "sha512-wgscxf2ORHL/8mAQfy7l9rVDG//wrG9RUQndG508kCCMHRq9deFyZ4psOMzySheBRSfGMcFoRFYSlkAeZr8cFg==", | ||||
|       "hasInstallScript": true, | ||||
|       "dependencies": { | ||||
|         "@electron/get": "^2.0.0", | ||||
| @@ -7697,9 +7697,9 @@ | ||||
|       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" | ||||
|     }, | ||||
|     "node_modules/jackspeak": { | ||||
|       "version": "2.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", | ||||
|       "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", | ||||
|       "version": "2.3.6", | ||||
|       "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", | ||||
|       "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", | ||||
|       "dependencies": { | ||||
|         "@isaacs/cliui": "^8.0.2" | ||||
|       }, | ||||
| @@ -8946,9 +8946,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/marked": { | ||||
|       "version": "9.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", | ||||
|       "integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==", | ||||
|       "version": "9.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz", | ||||
|       "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==", | ||||
|       "bin": { | ||||
|         "marked": "bin/marked.js" | ||||
|       }, | ||||
| @@ -10106,12 +10106,12 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/path-scurry": { | ||||
|       "version": "1.9.2", | ||||
|       "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", | ||||
|       "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", | ||||
|       "version": "1.10.1", | ||||
|       "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", | ||||
|       "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", | ||||
|       "dependencies": { | ||||
|         "lru-cache": "^9.1.1", | ||||
|         "minipass": "^5.0.0 || ^6.0.2" | ||||
|         "lru-cache": "^9.1.1 || ^10.0.0", | ||||
|         "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=16 || 14 >=14.17" | ||||
| @@ -10947,14 +10947,14 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/rimraf": { | ||||
|       "version": "5.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", | ||||
|       "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", | ||||
|       "version": "5.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", | ||||
|       "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", | ||||
|       "dependencies": { | ||||
|         "glob": "^10.2.5" | ||||
|         "glob": "^10.3.7" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "rimraf": "dist/cjs/src/bin.js" | ||||
|         "rimraf": "dist/esm/bin.mjs" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=14" | ||||
| @@ -10972,18 +10972,18 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/rimraf/node_modules/glob": { | ||||
|       "version": "10.2.6", | ||||
|       "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", | ||||
|       "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", | ||||
|       "version": "10.3.10", | ||||
|       "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", | ||||
|       "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", | ||||
|       "dependencies": { | ||||
|         "foreground-child": "^3.1.0", | ||||
|         "jackspeak": "^2.0.3", | ||||
|         "jackspeak": "^2.3.5", | ||||
|         "minimatch": "^9.0.1", | ||||
|         "minipass": "^5.0.0 || ^6.0.2", | ||||
|         "path-scurry": "^1.7.0" | ||||
|         "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", | ||||
|         "path-scurry": "^1.10.1" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "glob": "dist/cjs/src/bin.js" | ||||
|         "glob": "dist/esm/bin.mjs" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=16 || 14 >=14.17" | ||||
| @@ -10993,9 +10993,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/rimraf/node_modules/minimatch": { | ||||
|       "version": "9.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", | ||||
|       "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", | ||||
|       "version": "9.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", | ||||
|       "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", | ||||
|       "dependencies": { | ||||
|         "brace-expansion": "^2.0.1" | ||||
|       }, | ||||
| @@ -11007,9 +11007,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/rimraf/node_modules/minipass": { | ||||
|       "version": "6.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", | ||||
|       "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", | ||||
|       "version": "7.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", | ||||
|       "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", | ||||
|       "engines": { | ||||
|         "node": ">=16 || 14 >=14.17" | ||||
|       } | ||||
| @@ -11290,9 +11290,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/sax": { | ||||
|       "version": "1.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", | ||||
|       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", | ||||
|       "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" | ||||
|     }, | ||||
|     "node_modules/saxes": { | ||||
|       "version": "6.0.0", | ||||
| @@ -16542,9 +16542,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "electron": { | ||||
|       "version": "25.8.3", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-25.8.3.tgz", | ||||
|       "integrity": "sha512-BdcTIrhQIf6YgsihCXYh3DgKobtLaNcFb1B5C/5euepxxXQ7qmTWC6WgNUm+IntLOFEDQO926rvm2nhRdSN+Nw==", | ||||
|       "version": "25.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-25.9.0.tgz", | ||||
|       "integrity": "sha512-wgscxf2ORHL/8mAQfy7l9rVDG//wrG9RUQndG508kCCMHRq9deFyZ4psOMzySheBRSfGMcFoRFYSlkAeZr8cFg==", | ||||
|       "requires": { | ||||
|         "@electron/get": "^2.0.0", | ||||
|         "@types/node": "^18.11.18", | ||||
| @@ -19062,9 +19062,9 @@ | ||||
|       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" | ||||
|     }, | ||||
|     "jackspeak": { | ||||
|       "version": "2.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", | ||||
|       "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", | ||||
|       "version": "2.3.6", | ||||
|       "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", | ||||
|       "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", | ||||
|       "requires": { | ||||
|         "@isaacs/cliui": "^8.0.2", | ||||
|         "@pkgjs/parseargs": "^0.11.0" | ||||
| @@ -19990,9 +19990,9 @@ | ||||
|       "requires": {} | ||||
|     }, | ||||
|     "marked": { | ||||
|       "version": "9.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", | ||||
|       "integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==" | ||||
|       "version": "9.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz", | ||||
|       "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==" | ||||
|     }, | ||||
|     "matcher": { | ||||
|       "version": "3.0.0", | ||||
| @@ -20873,12 +20873,12 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "path-scurry": { | ||||
|       "version": "1.9.2", | ||||
|       "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", | ||||
|       "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", | ||||
|       "version": "1.10.1", | ||||
|       "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", | ||||
|       "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", | ||||
|       "requires": { | ||||
|         "lru-cache": "^9.1.1", | ||||
|         "minipass": "^5.0.0 || ^6.0.2" | ||||
|         "lru-cache": "^9.1.1 || ^10.0.0", | ||||
|         "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "lru-cache": { | ||||
| @@ -21498,11 +21498,11 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "rimraf": { | ||||
|       "version": "5.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", | ||||
|       "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", | ||||
|       "version": "5.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", | ||||
|       "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", | ||||
|       "requires": { | ||||
|         "glob": "^10.2.5" | ||||
|         "glob": "^10.3.7" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "brace-expansion": { | ||||
| @@ -21514,29 +21514,29 @@ | ||||
|           } | ||||
|         }, | ||||
|         "glob": { | ||||
|           "version": "10.2.6", | ||||
|           "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", | ||||
|           "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", | ||||
|           "version": "10.3.10", | ||||
|           "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", | ||||
|           "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", | ||||
|           "requires": { | ||||
|             "foreground-child": "^3.1.0", | ||||
|             "jackspeak": "^2.0.3", | ||||
|             "jackspeak": "^2.3.5", | ||||
|             "minimatch": "^9.0.1", | ||||
|             "minipass": "^5.0.0 || ^6.0.2", | ||||
|             "path-scurry": "^1.7.0" | ||||
|             "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", | ||||
|             "path-scurry": "^1.10.1" | ||||
|           } | ||||
|         }, | ||||
|         "minimatch": { | ||||
|           "version": "9.0.1", | ||||
|           "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", | ||||
|           "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", | ||||
|           "version": "9.0.3", | ||||
|           "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", | ||||
|           "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", | ||||
|           "requires": { | ||||
|             "brace-expansion": "^2.0.1" | ||||
|           } | ||||
|         }, | ||||
|         "minipass": { | ||||
|           "version": "6.0.2", | ||||
|           "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", | ||||
|           "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==" | ||||
|           "version": "7.0.4", | ||||
|           "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", | ||||
|           "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
| @@ -21736,9 +21736,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "sax": { | ||||
|       "version": "1.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", | ||||
|       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", | ||||
|       "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" | ||||
|     }, | ||||
|     "saxes": { | ||||
|       "version": "6.0.0", | ||||
|   | ||||
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
|   "name": "trilium", | ||||
|   "productName": "Trilium Notes", | ||||
|   "description": "Trilium Notes", | ||||
|   "version": "0.61.8-beta", | ||||
|   "version": "0.61.9-beta", | ||||
|   "license": "AGPL-3.0-only", | ||||
|   "main": "electron.js", | ||||
|   "bin": { | ||||
| @@ -68,7 +68,7 @@ | ||||
|     "jimp": "0.22.10", | ||||
|     "joplin-turndown-plugin-gfm": "1.0.12", | ||||
|     "jsdom": "22.1.0", | ||||
|     "marked": "9.0.3", | ||||
|     "marked": "9.1.0", | ||||
|     "mime-types": "2.1.35", | ||||
|     "multer": "1.4.5-lts.1", | ||||
|     "node-abi": "3.47.0", | ||||
| @@ -78,11 +78,11 @@ | ||||
|     "react": "18.2.0", | ||||
|     "react-dom": "18.2.0", | ||||
|     "request": "2.88.2", | ||||
|     "rimraf": "5.0.1", | ||||
|     "rimraf": "5.0.5", | ||||
|     "safe-compare": "1.1.4", | ||||
|     "sanitize-filename": "1.6.3", | ||||
|     "sanitize-html": "2.11.0", | ||||
|     "sax": "1.2.4", | ||||
|     "sax": "1.3.0", | ||||
|     "semver": "7.5.4", | ||||
|     "serve-favicon": "2.5.0", | ||||
|     "session-file-store": "1.5.0", | ||||
| @@ -97,7 +97,7 @@ | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "cross-env": "7.0.3", | ||||
|     "electron": "25.8.3", | ||||
|     "electron": "25.9.0", | ||||
|     "electron-builder": "24.6.4", | ||||
|     "electron-packager": "17.1.2", | ||||
|     "electron-rebuild": "3.2.9", | ||||
|   | ||||
| @@ -132,11 +132,17 @@ class BNote extends AbstractBeccaEntity { | ||||
|          */ | ||||
|         this.contentSize = null; | ||||
|         /** | ||||
|          * size of the content and note revision contents in bytes | ||||
|          * size of the note content, attachment contents in bytes | ||||
|          * @type {int|null} | ||||
|          * @private | ||||
|          */ | ||||
|         this.noteSize = null; | ||||
|         this.contentAndAttachmentsSize = null; | ||||
|         /** | ||||
|          * size of the note content, attachment contents and revision contents in bytes | ||||
|          * @type {int|null} | ||||
|          * @private | ||||
|          */ | ||||
|         this.contentAndAttachmentsAndRevisionsSize = null; | ||||
|         /** | ||||
|          * number of note revisions for this note | ||||
|          * @type {int|null} | ||||
| @@ -1607,16 +1613,12 @@ class BNote extends AbstractBeccaEntity { | ||||
|  | ||||
|             revision.save(); // to generate revisionId, which is then used to save attachments | ||||
|  | ||||
|             if (this.type === 'text') { | ||||
|             for (const noteAttachment of this.getAttachments()) { | ||||
|                     if (noteAttachment.utcDateScheduledForErasureSince) { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                 const revisionAttachment = noteAttachment.copy(); | ||||
|                 revisionAttachment.ownerId = revision.revisionId; | ||||
|                 revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true}); | ||||
|  | ||||
|                 if (this.type === 'text') { | ||||
|                     // content is rewritten to point to the revision attachments | ||||
|                     noteContent = noteContent.replaceAll(`attachments/${noteAttachment.attachmentId}`, | ||||
|                         `attachments/${revisionAttachment.attachmentId}`); | ||||
|   | ||||
| @@ -86,6 +86,29 @@ class BRevision extends AbstractBeccaEntity { | ||||
|         return this._getContent(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @returns {*} | ||||
|      * @throws Error in case of invalid JSON */ | ||||
|     getJsonContent() { | ||||
|         const content = this.getContent(); | ||||
|  | ||||
|         if (!content || !content.trim()) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return JSON.parse(content); | ||||
|     } | ||||
|  | ||||
|     /** @returns {*|null} valid object or null if the content cannot be parsed as JSON */ | ||||
|     getJsonContentSafely() { | ||||
|         try { | ||||
|             return this.getJsonContent(); | ||||
|         } | ||||
|         catch (e) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param content | ||||
|      * @param {object} [opts] | ||||
| @@ -105,6 +128,45 @@ class BRevision extends AbstractBeccaEntity { | ||||
|             .map(row => new BAttachment(row)); | ||||
|     } | ||||
|  | ||||
|     /** @returns {BAttachment|null} */ | ||||
|     getAttachmentById(attachmentId, opts = {}) { | ||||
|         opts.includeContentLength = !!opts.includeContentLength; | ||||
|  | ||||
|         const query = opts.includeContentLength | ||||
|             ? `SELECT attachments.*, LENGTH(blobs.content) AS contentLength | ||||
|                FROM attachments  | ||||
|                JOIN blobs USING (blobId)  | ||||
|                WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0` | ||||
|             : `SELECT * FROM attachments WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`; | ||||
|  | ||||
|         return sql.getRows(query, [this.revisionId, attachmentId]) | ||||
|             .map(row => new BAttachment(row))[0]; | ||||
|     } | ||||
|  | ||||
|     /** @returns {BAttachment[]} */ | ||||
|     getAttachmentsByRole(role) { | ||||
|         return sql.getRows(` | ||||
|                 SELECT attachments.* | ||||
|                 FROM attachments  | ||||
|                 WHERE ownerId = ?  | ||||
|                   AND role = ? | ||||
|                   AND isDeleted = 0 | ||||
|                 ORDER BY position`, [this.revisionId, role]) | ||||
|             .map(row => new BAttachment(row)); | ||||
|     } | ||||
|  | ||||
|     /** @returns {BAttachment} */ | ||||
|     getAttachmentByTitle(title) { | ||||
|         return sql.getRows(` | ||||
|                 SELECT attachments.* | ||||
|                 FROM attachments  | ||||
|                 WHERE ownerId = ?  | ||||
|                   AND title = ? | ||||
|                   AND isDeleted = 0 | ||||
|                 ORDER BY position`, [this.revisionId, title]) | ||||
|             .map(row => new BAttachment(row))[0]; | ||||
|     } | ||||
|  | ||||
|     beforeSaving() { | ||||
|         super.beforeSaving(); | ||||
|  | ||||
|   | ||||
| @@ -127,7 +127,8 @@ paths: | ||||
|             - targetRelationCount | ||||
|             - targetRelationCountIncludingLinks | ||||
|             - contentSize | ||||
|             - noteSize | ||||
|             - contentAndAttachmentsSize | ||||
|             - contentAndAttachmentsAndRevisionsSize | ||||
|             - revisionCount | ||||
|         - name: orderDirection | ||||
|           in: query | ||||
|   | ||||
| @@ -32,8 +32,8 @@ export default class LauncherContextMenu { | ||||
|         const isVisibleItem = parentNoteId === '_lbVisibleLaunchers'; | ||||
|         const isAvailableItem = parentNoteId === '_lbAvailableLaunchers'; | ||||
|         const isItem = isVisibleItem || isAvailableItem; | ||||
|         const canBeDeleted = !note.isLaunchBarConfig(); | ||||
|         const canBeReset = note.isLaunchBarConfig(); | ||||
|         const canBeDeleted = !note.noteId.startsWith("_"); // fixed notes can't be deleted | ||||
|         const canBeReset = !canBeDeleted && note.isLaunchBarConfig();; | ||||
|  | ||||
|         return [ | ||||
|             (isVisibleRoot || isAvailableRoot) ? { title: 'Add a note launcher', command: 'addNoteLauncher', uiIcon: "bx bx-plus" } : null, | ||||
|   | ||||
| @@ -252,11 +252,15 @@ class NoteListRenderer { | ||||
|             if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(this.page - i) <= 2) { | ||||
|                 lastPrinted = true; | ||||
|  | ||||
|                 const startIndex = (i - 1) * this.pageSize + 1; | ||||
|                 const endIndex = Math.min(this.noteIds.length, i * this.pageSize); | ||||
|  | ||||
|                 $pager.append( | ||||
|                     i === this.page | ||||
|                         ? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold") | ||||
|                         : $('<a href="javascript:">') | ||||
|                             .text(i) | ||||
|                             .attr("title", `Page of ${startIndex} - ${endIndex}`) | ||||
|                             .on('click', () => { | ||||
|                                 this.page = i; | ||||
|                                 this.renderList(); | ||||
| @@ -270,6 +274,9 @@ class NoteListRenderer { | ||||
|                 lastPrinted = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // no need to distinguish "note" vs "notes" since in case of one result, there's no paging at all | ||||
|         $pager.append(`<span class="note-list-pager-total-count">(${this.noteIds.length} notes)</span>`); | ||||
|     } | ||||
|  | ||||
|     async renderNote(note, expand = false) { | ||||
|   | ||||
| @@ -45,6 +45,7 @@ const TPL = ` | ||||
|         <a class="dropdown-item export-note-button">Export note</a> | ||||
|         <a class="dropdown-item delete-note-button">Delete note</a> | ||||
|         <a data-trigger-command="printActiveNote" class="dropdown-item print-active-note-button"><kbd data-command="printActiveNote"></kbd> Print note</a> | ||||
|         <a data-trigger-command="forceSaveRevision" class="dropdown-item save-revision-button"><kbd data-command="forceSaveRevision"></kbd> Save revision</a> | ||||
|     </div> | ||||
| </div>`; | ||||
|  | ||||
|   | ||||
| @@ -274,26 +274,11 @@ export default class RevisionsDialog extends BasicWidget { | ||||
|  | ||||
|             this.$content.html($table); | ||||
|         } else if (revisionItem.type === 'canvas') { | ||||
|             /** | ||||
|              * FIXME: We load a font called Virgil.wof2, which originates from excalidraw.com | ||||
|              *        REMOVE external dependency!!!! This is defined in the svg in defs.style | ||||
|              */ | ||||
|             const content = fullRevision.content; | ||||
|             const sanitizedTitle = revisionItem.title.replace(/[^a-z0-9-.]/gi, ""); | ||||
|  | ||||
|             try { | ||||
|                 const data = JSON.parse(content) | ||||
|                 const svg = data.svg || "no svg present." | ||||
|  | ||||
|                 /** | ||||
|                  * maxWidth: 100% use full width of container but do not enlarge! | ||||
|                  * height:auto to ensure that height scales with width | ||||
|                  */ | ||||
|                 const $svgHtml = $(svg).css({maxWidth: "100%", height: "auto"}); | ||||
|                 this.$content.html($('<div>').append($svgHtml)); | ||||
|             } catch (err) { | ||||
|                 console.error("error parsing fullRevision.content as JSON", fullRevision.content, err); | ||||
|                 this.$content.html($("<div>").text("Error parsing content. Please check console.error() for more details.")); | ||||
|             } | ||||
|             this.$content.html($("<img>") | ||||
|                 .attr("src", `api/revisions/${revisionItem.revisionId}/image/${sanitizedTitle}?${Math.random()}`) | ||||
|                 .css("max-width", "100%")); | ||||
|         } else { | ||||
|             this.$content.text("Preview isn't available for this note type."); | ||||
|         } | ||||
|   | ||||
| @@ -14,7 +14,8 @@ const TPL = ` | ||||
|             <option value="dateCreated">Date created</option> | ||||
|             <option value="dateModified">Date of last modification</option> | ||||
|             <option value="contentSize">Note content size</option> | ||||
|             <option value="noteSize">Note content size including revisions</option> | ||||
|             <option value="contentAndAttachmentsSize">Note content size including attachments</option> | ||||
|             <option value="contentAndAttachmentsAndRevisionsSize">Note content size including attachments and revisions</option> | ||||
|             <option value="revisionCount">Number of revisions</option> | ||||
|             <option value="childrenCount">Number of children notes</option> | ||||
|             <option value="parentCount">Number of clones</option> | ||||
|   | ||||
| @@ -209,7 +209,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget { | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             const {elements, files, appState} = content; | ||||
|             const {elements, files, appState = {}} = content; | ||||
|  | ||||
|             appState.theme = this.themeStyle; | ||||
|  | ||||
|   | ||||
| @@ -5,14 +5,27 @@ const becca = require('../../becca/becca'); | ||||
| const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; | ||||
| const fs = require('fs'); | ||||
|  | ||||
| function returnImage(req, res) { | ||||
| function returnImageFromNote(req, res) { | ||||
|     const image = becca.getNote(req.params.noteId); | ||||
|  | ||||
|     return returnImageInt(image, res); | ||||
| } | ||||
|  | ||||
| function returnImageFromRevision(req, res) { | ||||
|     const image = becca.getRevision(req.params.revisionId); | ||||
|  | ||||
|     return returnImageInt(image, res); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {BNote|BRevision} image | ||||
|  * @param res | ||||
|  */ | ||||
| function returnImageInt(image, res) { | ||||
|     if (!image) { | ||||
|         res.set('Content-Type', 'image/png'); | ||||
|         return res.send(fs.readFileSync(`${RESOURCE_DIR}/db/image-deleted.png`)); | ||||
|     } | ||||
|     else if (!["image", "canvas"].includes(image.type)){ | ||||
|     } else if (!["image", "canvas"].includes(image.type)) { | ||||
|         return res.sendStatus(400); | ||||
|     } | ||||
|  | ||||
| @@ -84,7 +97,8 @@ function updateImage(req) { | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     returnImage, | ||||
|     returnImageFromNote, | ||||
|     returnImageFromRevision, | ||||
|     returnAttachedImage, | ||||
|     updateImage | ||||
| }; | ||||
|   | ||||
| @@ -181,6 +181,8 @@ function register(app) { | ||||
|     apiRoute(GET, '/api/revisions/:revisionId/blob', revisionsApiRoute.getRevisionBlob); | ||||
|     apiRoute(DEL, '/api/revisions/:revisionId', revisionsApiRoute.eraseRevision); | ||||
|     apiRoute(PST, '/api/revisions/:revisionId/restore', revisionsApiRoute.restoreRevision); | ||||
|     route(GET, '/api/revisions/:revisionId/image/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImageFromRevision); | ||||
|  | ||||
|     route(GET, '/api/revisions/:revisionId/download', [auth.checkApiAuthOrElectron], revisionsApiRoute.downloadRevision); | ||||
|  | ||||
|  | ||||
| @@ -200,7 +202,7 @@ function register(app) { | ||||
|     apiRoute(GET, '/api/attribute-values/:attributeName', attributesRoute.getValuesForAttribute); | ||||
|  | ||||
|     // :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename | ||||
|     route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); | ||||
|     route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImageFromNote); | ||||
|     route(PUT, '/api/images/:noteId', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware], imageRoute.updateImage, apiResultHandler); | ||||
|  | ||||
|     apiRoute(GET, '/api/options', optionsApiRoute.getOptions); | ||||
|   | ||||
| @@ -7,8 +7,9 @@ const sql = require("./sql"); | ||||
|  | ||||
| function getFullAnonymizationScript() { | ||||
|     // we want to delete all non-builtin attributes because they can contain sensitive names and values | ||||
| // on the other hand builtin/system attrs should not contain any sensitive info | ||||
|     // on the other hand builtin/system attrs should not contain any sensitive info | ||||
|     const builtinAttrNames = BUILTIN_ATTRIBUTES | ||||
|         .filter(attr => !["shareCredentials", "shareAlias"].includes(attr.name)) | ||||
|         .map(attr => `'${attr.name}'`).join(', '); | ||||
|  | ||||
|     const anonymizeScript = ` | ||||
|   | ||||
| @@ -4,7 +4,7 @@ const build = require('./build'); | ||||
| const packageJson = require('../../package'); | ||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||
|  | ||||
| const APP_DB_VERSION = 225; | ||||
| const APP_DB_VERSION = 226; | ||||
| const SYNC_VERSION = 31; | ||||
| const CLIPPER_PROTOCOL_VERSION = "1.0"; | ||||
|  | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| module.exports = { buildDate:"2023-09-29T00:54:45+02:00", buildRevision: "e5555beea9a1638fefa218118e0596f4cfc1f4d0" }; | ||||
| module.exports = { buildDate:"2023-10-07T23:02:47+03:00", buildRevision: "3d15aeae58224ac8716dd58938458e89af9bf7a0" }; | ||||
|   | ||||
| @@ -7,7 +7,7 @@ const BBranch = require('../becca/entities/bbranch'); | ||||
| const becca = require("../becca/becca"); | ||||
| const log = require("./log"); | ||||
|  | ||||
| function cloneNoteToParentNote(noteId, parentNoteId, prefix) { | ||||
| function cloneNoteToParentNote(noteId, parentNoteId, prefix = null) { | ||||
|     if (!(noteId in becca.notes) || !(parentNoteId in becca.notes)) { | ||||
|         return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' }; | ||||
|     } | ||||
|   | ||||
| @@ -327,6 +327,11 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|         content = content.replace(/<\/body>.*<\/html>/gis, ""); | ||||
|  | ||||
|         content = content.replace(/src="([^"]*)"/g, (match, url) => { | ||||
|             if (url.startsWith("data:image")) { | ||||
|                 // inline images are parsed and saved into attachments in the note service | ||||
|                 return match; | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 url = decodeURIComponent(url).trim(); | ||||
|             } catch (e) { | ||||
|   | ||||
| @@ -56,9 +56,9 @@ class OrderByAndLimitExp extends Expression { | ||||
|                 if (!valA && !valB) { | ||||
|                     // the attribute value is empty/zero in both notes so continue to the next order definition | ||||
|                     continue; | ||||
|                 } else if (!valB || valA < valB) { | ||||
|                 } else if (valA < valB) { | ||||
|                     return smaller; | ||||
|                 } else if (!valA || valA > valB) { | ||||
|                 } else if (valA > valB) { | ||||
|                     return larger; | ||||
|                 } | ||||
|                 // else the values are equal and continue to next order definition | ||||
|   | ||||
| @@ -31,7 +31,8 @@ const PROP_MAPPING = { | ||||
|     "targetrelationcount": "targetRelationCount", | ||||
|     "targetrelationcountincludinglinks": "targetRelationCountIncludingLinks", | ||||
|     "contentsize": "contentSize", | ||||
|     "notesize": "noteSize", | ||||
|     "contentandattachmentssize": "contentAndAttachmentsSize", | ||||
|     "contentandattachmentsandrevisionssize": "contentAndAttachmentsAndRevisionsSize", | ||||
|     "revisioncount": "revisionCount" | ||||
| }; | ||||
|  | ||||
| @@ -48,7 +49,7 @@ class PropertyComparisonExp extends Expression { | ||||
|         this.comparedValue = comparedValue; // for DEBUG mode | ||||
|         this.comparator = buildComparator(operator, comparedValue); | ||||
|  | ||||
|         if (['contentsize', 'notesize', 'revisioncount'].includes(this.propertyName)) { | ||||
|         if (['contentsize', 'contentandattachmentssize', 'contentandattachmentsandrevisionssize', 'revisioncount'].includes(this.propertyName)) { | ||||
|             searchContext.dbLoadNeeded = true; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -92,48 +92,108 @@ function searchFromRelation(note, relationName) { | ||||
| function loadNeededInfoFromDatabase() { | ||||
|     const sql = require('../../sql'); | ||||
|  | ||||
|     for (const noteId in becca.notes) { | ||||
|         becca.notes[noteId].contentSize = 0; | ||||
|         becca.notes[noteId].noteSize = 0; | ||||
|         becca.notes[noteId].revisionCount = 0; | ||||
|     } | ||||
|     /** | ||||
|      * This complex structure is needed to calculate total occupied space by a note. Several object instances | ||||
|      * (note, revisions, attachments) can point to a single blobId, and thus the blob size should count towards the total | ||||
|      * only once. | ||||
|      * | ||||
|      * @var {Object.<string, Object.<string, int>>} - noteId => { blobId => blobSize } | ||||
|      */ | ||||
|     const noteBlobs = {}; | ||||
|  | ||||
|     const noteContentLengths = sql.getRows(` | ||||
|         SELECT  | ||||
|             noteId,  | ||||
|             blobId, | ||||
|             LENGTH(content) AS length  | ||||
|         FROM notes | ||||
|              JOIN blobs USING(blobId)  | ||||
|         WHERE notes.isDeleted = 0`); | ||||
|  | ||||
|     for (const {noteId, length} of noteContentLengths) { | ||||
|     for (const {noteId, blobId, length} of noteContentLengths) { | ||||
|         if (!(noteId in becca.notes)) { | ||||
|             log.error(`Note ${noteId} not found in becca.`); | ||||
|             log.error(`Note '${noteId}' not found in becca.`); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         becca.notes[noteId].contentSize = length; | ||||
|         becca.notes[noteId].noteSize = length; | ||||
|         becca.notes[noteId].revisionCount = 0; | ||||
|  | ||||
|         noteBlobs[noteId] = { [blobId]: length }; | ||||
|     } | ||||
|  | ||||
|     const attachmentContentLengths = sql.getRows(` | ||||
|         SELECT | ||||
|             ownerId AS noteId, | ||||
|             attachments.blobId, | ||||
|             LENGTH(content) AS length | ||||
|         FROM attachments | ||||
|             JOIN notes ON attachments.ownerId = notes.noteId | ||||
|             JOIN blobs ON attachments.blobId = blobs.blobId | ||||
|         WHERE attachments.isDeleted = 0  | ||||
|             AND notes.isDeleted = 0`); | ||||
|  | ||||
|     for (const {noteId, blobId, length} of attachmentContentLengths) { | ||||
|         if (!(noteId in becca.notes)) { | ||||
|             log.error(`Note '${noteId}' not found in becca.`); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         if (!(noteId in noteBlobs)) { | ||||
|             log.error(`Did not find a '${noteId}' in the noteBlobs.`); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         noteBlobs[noteId][blobId] = length; | ||||
|     } | ||||
|  | ||||
|     for (const noteId in noteBlobs) { | ||||
|         becca.notes[noteId].contentAndAttachmentsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0); | ||||
|     } | ||||
|  | ||||
|     const revisionContentLengths = sql.getRows(` | ||||
|             SELECT  | ||||
|                 noteId,  | ||||
|             LENGTH(content) AS length  | ||||
|                 revisions.blobId, | ||||
|                 LENGTH(content) AS length, | ||||
|                 1 AS isNoteRevision | ||||
|             FROM notes | ||||
|                 JOIN revisions USING(noteId)  | ||||
|              JOIN blobs USING(blobId)  | ||||
|                 JOIN blobs ON revisions.blobId = blobs.blobId | ||||
|             WHERE notes.isDeleted = 0 | ||||
|         UNION ALL | ||||
|             SELECT | ||||
|                 noteId, | ||||
|                 revisions.blobId, | ||||
|                 LENGTH(content) AS length, | ||||
|                 0 AS isNoteRevision -- it's attachment not counting towards revision count | ||||
|             FROM notes | ||||
|                 JOIN revisions USING(noteId) | ||||
|                 JOIN attachments ON attachments.ownerId = revisions.revisionId | ||||
|                 JOIN blobs ON attachments.blobId = blobs.blobId | ||||
|             WHERE notes.isDeleted = 0`); | ||||
|  | ||||
|     for (const {noteId, length} of revisionContentLengths) { | ||||
|     for (const {noteId, blobId, length, isNoteRevision} of revisionContentLengths) { | ||||
|         if (!(noteId in becca.notes)) { | ||||
|             log.error(`Note ${noteId} not found in becca.`); | ||||
|             log.error(`Note '${noteId}' not found in becca.`); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         becca.notes[noteId].noteSize += length; | ||||
|         if (!(noteId in noteBlobs)) { | ||||
|             log.error(`Did not find a '${noteId}' in the noteBlobs.`); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         noteBlobs[noteId][blobId] = length; | ||||
|  | ||||
|         if (isNoteRevision) { | ||||
|             becca.notes[noteId].revisionCount++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     for (const noteId in noteBlobs) { | ||||
|         becca.notes[noteId].contentAndAttachmentsAndRevisionsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -27,7 +27,8 @@ const PROP_MAPPING = { | ||||
|     "targetrelationcount": "targetRelationCount", | ||||
|     "targetrelationcountincludinglinks": "targetRelationCountIncludingLinks", | ||||
|     "contentsize": "contentSize", | ||||
|     "notesize": "noteSize", | ||||
|     "contentandattachmentssize": "contentAndAttachmentsSize", | ||||
|     "contentandattachmentsandrevisionssize": "contentAndAttachmentsAndRevisionsSize", | ||||
|     "revisioncount": "revisionCount" | ||||
| }; | ||||
|  | ||||
| @@ -42,7 +43,7 @@ class ValueExtractor { | ||||
|             this.propertyPath = ['note', 'relations', this.propertyPath[0].substr(1), ...this.propertyPath.slice(1, this.propertyPath.length)]; | ||||
|         } | ||||
|  | ||||
|         if (['contentsize', 'notesize', 'revisioncount'].includes(this.propertyPath[this.propertyPath.length - 1])) { | ||||
|         if (['contentsize', 'contentandattachmentssize', 'contentandattachmentsandrevisionssize', 'revisioncount'].includes(this.propertyPath[this.propertyPath.length - 1])) { | ||||
|             searchContext.dbLoadNeeded = true; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -151,10 +151,15 @@ async function pullChanges(syncContext) { | ||||
|         if (entityChanges.length === 0) { | ||||
|             break; | ||||
|         } else { | ||||
|             try { // https://github.com/zadam/trilium/issues/4310 | ||||
|                 const sizeInKb = Math.round(JSON.stringify(resp).length / 1024); | ||||
|  | ||||
|                 log.info(`Sync ${logMarkerId}: Pulled ${entityChanges.length} changes in ${sizeInKb} KB, starting at entityChangeId=${lastSyncedPull} in ${pulledDate - startDate}ms and applied them in ${Date.now() - pulledDate}ms, ${outstandingPullCount} outstanding pulls`); | ||||
|             } | ||||
|             catch (e) { | ||||
|                 log.error(`Error occurred ${e.message} ${e.stack}`); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     log.info("Finished pull"); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user