mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	Compare commits
	
		
			80 Commits
		
	
	
		
			kev/share-
			...
			feat/clean
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 64f191b83b | ||
|  | 31c8e96d70 | ||
|  | 1191421388 | ||
|  | 831a184c2a | ||
|  | c671f91bca | ||
|  | fa436c7ce6 | ||
|  | d1367286c9 | ||
|  | d10b0fa823 | ||
|  | 545c8648b7 | ||
|  | d6e9acc149 | ||
|  | 26e14aff7b | ||
|  | 280ec5b406 | ||
|  | 26081ffd36 | ||
|  | f106cbf6c0 | ||
|  | f3877a52ab | ||
|  | 5becf60a63 | ||
|  | 2ea96dc8f8 | ||
|  | e48724662e | ||
|  | 745ce7de76 | ||
|  | 997217861c | ||
|  | 44f8e8b833 | ||
|  | 99e2b63ff0 | ||
|  | 0139d90ac7 | ||
|  | 5b7484c27c | ||
|  | 71e64be44c | ||
|  | 639651329a | ||
|  | a7a0d3584a | ||
|  | f765441f1e | ||
|  | 10cd5bf130 | ||
|  | d93c5dfeea | ||
|  | b58aac1298 | ||
|  | d662718a4a | ||
|  | bebd3d430b | ||
|  | 2fca995725 | ||
|  | caa1ea12f1 | ||
|  | f25e4ea391 | ||
|  | 05b433edb5 | ||
|  | b8851565eb | ||
|  | 888d0d1084 | ||
|  | 0a25d4db0d | ||
|  | d483b6e840 | ||
|  | 979fbe2e76 | ||
|  | ea5564c6e6 | ||
|  | 6ab8750726 | ||
|  | 923eabd750 | ||
|  | c52d6a6384 | ||
|  | 519b9648c6 | ||
|  | b25fd6ca3a | ||
|  | 2bd8c215ff | ||
|  | 34e7901de9 | ||
|  | 30a191cedf | ||
|  | 128d8907c3 | ||
|  | 3b1d7d045e | ||
|  | 0ae9a29e0d | ||
|  | f4b5ed73ad | ||
|  | 43166dbeb5 | ||
|  | 00b5aef890 | ||
|  | 1b7266f083 | ||
|  | d1d4b47111 | ||
|  | c90364bd76 | ||
|  | 6dc687ef43 | ||
|  | 0e31aab1ab | ||
|  | b0030f89b7 | ||
|  | 9f0a0238cc | ||
|  | dabdfaddec | ||
|  | a8901e6dc8 | ||
|  | ab901a5d32 | ||
|  | 56fc2d9b30 | ||
|  | df45fa2e1e | ||
|  | 9a11fc13d7 | ||
|  | d72a0d3c69 | ||
|  | 0be508ed70 | ||
|  | 37f3a9b19d | ||
|  | 81d2fbc057 | ||
|  | 1aecf66cbe | ||
|  | fbe7d64e00 | ||
|  | c9d151289c | ||
|  | bba2f6db64 | ||
|  | 6725f81a00 | ||
|  | 8487c8cd03 | 
| @@ -35,7 +35,7 @@ | |||||||
|     "chore:generate-openapi": "tsx bin/generate-openapi.js" |     "chore:generate-openapi": "tsx bin/generate-openapi.js" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": {     |   "devDependencies": {     | ||||||
|     "@playwright/test": "1.55.1", |     "@playwright/test": "1.56.0", | ||||||
|     "@stylistic/eslint-plugin": "5.4.0",         |     "@stylistic/eslint-plugin": "5.4.0",         | ||||||
|     "@types/express": "5.0.3",     |     "@types/express": "5.0.3",     | ||||||
|     "@types/node": "22.18.8",     |     "@types/node": "22.18.8",     | ||||||
|   | |||||||
| @@ -3,16 +3,7 @@ import linkContextMenuService from "../menus/link_context_menu.js"; | |||||||
| import appContext, { type NoteCommandData } from "../components/app_context.js"; | import appContext, { type NoteCommandData } from "../components/app_context.js"; | ||||||
| import froca from "./froca.js"; | import froca from "./froca.js"; | ||||||
| import utils from "./utils.js"; | import utils from "./utils.js"; | ||||||
|  | import { ALLOWED_PROTOCOLS } from "@triliumnext/commons"; | ||||||
| // Be consistent with `allowedSchemes` in `src\services\html_sanitizer.ts` |  | ||||||
| // TODO: Deduplicate with server once we can. |  | ||||||
| export const ALLOWED_PROTOCOLS = [ |  | ||||||
|     'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git', |  | ||||||
|     'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message', |  | ||||||
|     'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp', |  | ||||||
|     'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo', |  | ||||||
|     'mid' |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| function getNotePathFromUrl(url: string) { | function getNotePathFromUrl(url: string) { | ||||||
|     const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url); |     const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url); | ||||||
|   | |||||||
| @@ -1743,9 +1743,17 @@ | |||||||
|     "show_login_link": "在共享主题中显示登录链接", |     "show_login_link": "在共享主题中显示登录链接", | ||||||
|     "show_login_link_description": "在共享页面底部添加登录链接", |     "show_login_link_description": "在共享页面底部添加登录链接", | ||||||
|     "check_share_root": "检查共享根状态", |     "check_share_root": "检查共享根状态", | ||||||
|  |     "check_share_root_error": "检查共享根状态时发生意外错误,请检查日志以获取更多信息。", | ||||||
|  |     "share_note_title": "'{{noteTitle}}'", | ||||||
|     "share_root_found": "共享根笔记 '{{noteTitle}}' 已准备好", |     "share_root_found": "共享根笔记 '{{noteTitle}}' 已准备好", | ||||||
|     "share_root_not_found": "未找到带有 #shareRoot 标签的笔记", |     "share_root_not_found": "未找到带有 #shareRoot 标签的笔记", | ||||||
|     "share_root_not_shared": "笔记 '{{noteTitle}}' 具有 #shareRoot 标签,但未共享" |     "share_root_not_shared": "笔记 '{{noteTitle}}' 具有 #shareRoot 标签,但未共享", | ||||||
|  |     "share_root_multiple_found": "找到多个具有 #shareRoot 标签的共享笔记:{{- foundNoteTitles}}。将使用笔记 {{- activeNoteTitle}} 作为共享根笔记。", | ||||||
|  |     "share_path": "共享路径", | ||||||
|  |     "share_path_description": "共享笔记的 URL 前缀(例如 '/share' --> '/share/noteId' 或 '/custom-path' --> '/custom-path/noteId')。支持多级嵌套(例如 '/custom-path/sub-path' --> '/custom-path/sub-path/noteId')。刷新页面以应用更改。", | ||||||
|  |     "share_path_placeholder": "/share 或 /custom-path", | ||||||
|  |     "share_subtree": "共享子树", | ||||||
|  |     "share_subtree_description": "共享整个子树,而不是仅共享笔记" | ||||||
|   }, |   }, | ||||||
|   "time_selector": { |   "time_selector": { | ||||||
|     "invalid_input": "输入的时间值不是有效数字。", |     "invalid_input": "输入的时间值不是有效数字。", | ||||||
|   | |||||||
| @@ -1907,9 +1907,17 @@ | |||||||
|     "show_login_link": "Show Login link in Share theme", |     "show_login_link": "Show Login link in Share theme", | ||||||
|     "show_login_link_description": "Add a login link to the Share page footer", |     "show_login_link_description": "Add a login link to the Share page footer", | ||||||
|     "check_share_root": "Check Share Root Status", |     "check_share_root": "Check Share Root Status", | ||||||
|  |     "check_share_root_error": "An unexpected error happened while checking the Share Root Status, please check the logs for more information.", | ||||||
|  |     "share_note_title": "'{{noteTitle}}'", | ||||||
|     "share_root_found": "Share root note '{{noteTitle}}' is ready", |     "share_root_found": "Share root note '{{noteTitle}}' is ready", | ||||||
|     "share_root_not_found": "No note with #shareRoot label found", |     "share_root_not_found": "No note with #shareRoot label found", | ||||||
|     "share_root_not_shared": "Note '{{noteTitle}}' has #shareRoot label but is not shared" |     "share_root_not_shared": "Note '{{noteTitle}}' has #shareRoot label but is not Shared", | ||||||
|  |     "share_root_multiple_found": "Found multiple shared notes with a #shareRoot label: {{- foundNoteTitles}}. The note {{- activeNoteTitle}} will be used as shared root note.", | ||||||
|  |     "share_path": "Share path", | ||||||
|  |     "share_path_description": "The url prefix for shared notes (e.g. '/share' --> '/share/noteId' or '/custom-path' --> '/custom-path/noteId'). Multiple levels of nesting are supported (e.g. '/custom-path/sub-path' --> '/custom-path/sub-path/noteId'). Refresh the page to apply the changes.", | ||||||
|  |     "share_path_placeholder": "/share or /custom-path", | ||||||
|  |     "share_subtree": "Share subtree", | ||||||
|  |     "share_subtree_description": "Share the entire subtree, not just the note" | ||||||
|   }, |   }, | ||||||
|   "time_selector": { |   "time_selector": { | ||||||
|     "invalid_input": "The entered time value is not a valid number.", |     "invalid_input": "The entered time value is not a valid number.", | ||||||
|   | |||||||
| @@ -251,12 +251,12 @@ | |||||||
|   "help": { |   "help": { | ||||||
|     "title": "チートシート", |     "title": "チートシート", | ||||||
|     "noteNavigation": "ノートナビゲーション", |     "noteNavigation": "ノートナビゲーション", | ||||||
|     "collapseExpand": "ノードの格納/展開", |     "collapseExpand": "ノードを折りたたむ / 展開", | ||||||
|     "goBackForwards": "履歴を戻る/進む", |     "goBackForwards": "履歴を戻る/進む", | ||||||
|     "scrollToActiveNote": "アクティブノートまでスクロール", |     "scrollToActiveNote": "アクティブノートまでスクロール", | ||||||
|     "jumpToParentNote": "親ノートへ移動", |     "jumpToParentNote": "親ノートへ移動", | ||||||
|     "collapseWholeTree": "すべてのノートツリーを格納", |     "collapseWholeTree": "すべてのノートツリーを折りたたむ", | ||||||
|     "collapseSubTree": "サブツリーを格納", |     "collapseSubTree": "サブツリーを折りたたむ", | ||||||
|     "tabShortcuts": "タブショートカット", |     "tabShortcuts": "タブショートカット", | ||||||
|     "newTabNoteLink": "ノートのリンクをクリックすると、新しいタブで開く", |     "newTabNoteLink": "ノートのリンクをクリックすると、新しいタブで開く", | ||||||
|     "newTabWithActivationNoteLink": "ノートのリンクをクリックすると、新しいタブで開き、アクティブにします", |     "newTabWithActivationNoteLink": "ノートのリンクをクリックすると、新しいタブで開き、アクティブにします", | ||||||
| @@ -515,9 +515,9 @@ | |||||||
|   "book_properties": { |   "book_properties": { | ||||||
|     "grid": "グリッド", |     "grid": "グリッド", | ||||||
|     "list": "リスト", |     "list": "リスト", | ||||||
|     "collapse_all_notes": "すべてのノートを格納", |     "collapse_all_notes": "すべてのノートを折りたたむ", | ||||||
|     "expand_all_children": "すべての子を展開", |     "expand_all_children": "すべての子を展開", | ||||||
|     "collapse": "格納", |     "collapse": "折りたたむ", | ||||||
|     "expand": "展開", |     "expand": "展開", | ||||||
|     "book_properties": "コレクションプロパティ", |     "book_properties": "コレクションプロパティ", | ||||||
|     "invalid_view_type": "無効なビュータイプ '{{type}}'", |     "invalid_view_type": "無効なビュータイプ '{{type}}'", | ||||||
|   | |||||||
| @@ -1 +1,6 @@ | |||||||
| {} | { | ||||||
|  |   "about": { | ||||||
|  |     "title": "Acerca de \"Trillium Notes\"", | ||||||
|  |     "app_version": "Versão da aplicação:" | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| import { ALLOWED_PROTOCOLS } from "../../../services/link.js"; | import { ALLOWED_PROTOCOLS, MIME_TYPE_AUTO } from "@triliumnext/commons"; | ||||||
| import { MIME_TYPE_AUTO } from "@triliumnext/commons"; |  | ||||||
| import { buildExtraCommands, type EditorConfig, PREMIUM_PLUGINS } from "@triliumnext/ckeditor5"; | import { buildExtraCommands, type EditorConfig, PREMIUM_PLUGINS } from "@triliumnext/ckeditor5"; | ||||||
| import { getHighlightJsNameForMime } from "../../../services/mime_types.js"; | import { getHighlightJsNameForMime } from "../../../services/mime_types.js"; | ||||||
| import options from "../../../services/options.js"; | import options from "../../../services/options.js"; | ||||||
|   | |||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | // Ensure sharePath always starts with a single slash and does not end with (one or multiple) trailing slashes | ||||||
|  | export function normalizeSharePathInput(sharePathInput: string) { | ||||||
|  |     const REGEXP_STARTING_SLASH = /^\/+/g; | ||||||
|  |     const REGEXP_TRAILING_SLASH = /\b\/+$/g; | ||||||
|  |  | ||||||
|  |     const normalizedSharePath = (!sharePathInput.startsWith("/") | ||||||
|  |         ? `/${sharePathInput}` | ||||||
|  |         : sharePathInput) | ||||||
|  |         .replaceAll(REGEXP_TRAILING_SLASH, "") | ||||||
|  |         .replaceAll(REGEXP_STARTING_SLASH, "/"); | ||||||
|  |  | ||||||
|  |     return normalizedSharePath; | ||||||
|  | } | ||||||
| @@ -0,0 +1,58 @@ | |||||||
|  | import { describe, it, expect } from "vitest"; | ||||||
|  | import { normalizeSharePathInput } from "./share_path_utils.js"; | ||||||
|  |  | ||||||
|  | type TestCase<T extends (...args: any) => any> = [ | ||||||
|  |     desc: string, | ||||||
|  |     fnParams: Parameters<T>, | ||||||
|  |     expected: ReturnType<T> | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | describe("ShareSettingsOptions", () => { | ||||||
|  |  | ||||||
|  |     describe("#normalizeSharePathInput", () => { | ||||||
|  |  | ||||||
|  |         const testCases: TestCase<typeof normalizeSharePathInput>[] = [ | ||||||
|  |             [ | ||||||
|  |                 "should handle multiple trailing '/' and remove them completely", | ||||||
|  |                 ["/trailingtest////"], | ||||||
|  |                 "/trailingtest" | ||||||
|  |             ], | ||||||
|  |             [ | ||||||
|  |                 "should handle multiple starting '/' and replace them by a single '/'", | ||||||
|  |                 ["////startingtest"], | ||||||
|  |                 "/startingtest" | ||||||
|  |             ], | ||||||
|  |             [ | ||||||
|  |                 "should handle multiple starting & trailing '/' and replace them by a single '/'", | ||||||
|  |                 ["////startingAndTrailingTest///"], | ||||||
|  |                 "/startingAndTrailingTest" | ||||||
|  |             ], | ||||||
|  |             [ | ||||||
|  |                 "should not remove any '/' other than at the end or start of the input", | ||||||
|  |                 ["/test/with/subpath"], | ||||||
|  |                 "/test/with/subpath" | ||||||
|  |             ], | ||||||
|  |             [ | ||||||
|  |                 "should prepend the string with a '/' if it does not start with one", | ||||||
|  |                 ["testpath"], | ||||||
|  |                 "/testpath" | ||||||
|  |             ], | ||||||
|  |             [ | ||||||
|  |                 "should not change anything, if the string is a single '/'", | ||||||
|  |                 ["/"], | ||||||
|  |                 "/" | ||||||
|  |             ], | ||||||
|  |         ]; | ||||||
|  |  | ||||||
|  |         testCases.forEach((testCase) => { | ||||||
|  |             const [desc, fnParams, expected] = testCase; | ||||||
|  |             it(desc, () => { | ||||||
|  |                 const actual = normalizeSharePathInput(...fnParams); | ||||||
|  |                 expect(actual).toStrictEqual(expected); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  | }) | ||||||
| @@ -90,6 +90,10 @@ const config: ForgeConfig = { | |||||||
|                     base: "org.electronjs.Electron2.BaseApp", |                     base: "org.electronjs.Electron2.BaseApp", | ||||||
|                     baseVersion: "24.08", |                     baseVersion: "24.08", | ||||||
|                     baseFlatpakref: "https://flathub.org/repo/flathub.flatpakrepo", |                     baseFlatpakref: "https://flathub.org/repo/flathub.flatpakrepo", | ||||||
|  |                     finishArgs: [ | ||||||
|  |                         "--socket=fallback-x11", | ||||||
|  |                         "--socket=wayland" | ||||||
|  |                     ], | ||||||
|                     modules: [ |                     modules: [ | ||||||
|                         { |                         { | ||||||
|                             name: "zypak", |                             name: "zypak", | ||||||
|   | |||||||
							
								
								
									
										73
									
								
								apps/edit-docs/demo/!!!meta.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								apps/edit-docs/demo/!!!meta.json
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
| 	"formatVersion": 2, | 	"formatVersion": 2, | ||||||
| 	"appVersion": "0.98.1", | 	"appVersion": "0.99.1", | ||||||
| 	"files": [ | 	"files": [ | ||||||
| 		{ | 		{ | ||||||
| 			"isClone": false, | 			"isClone": false, | ||||||
| @@ -60,6 +60,13 @@ | |||||||
| 							"value": "dayGridMonth", | 							"value": "dayGridMonth", | ||||||
| 							"isInheritable": false, | 							"isInheritable": false, | ||||||
| 							"position": 40 | 							"position": 40 | ||||||
|  | 						}, | ||||||
|  | 						{ | ||||||
|  | 							"type": "relation", | ||||||
|  | 							"name": "dateTemplate", | ||||||
|  | 							"value": "bRQvb9VCkc3t", | ||||||
|  | 							"isInheritable": false, | ||||||
|  | 							"position": 50 | ||||||
| 						} | 						} | ||||||
| 					], | 					], | ||||||
| 					"dataFileName": "Journal.dat", | 					"dataFileName": "Journal.dat", | ||||||
| @@ -75,7 +82,7 @@ | |||||||
| 					"title": "Trilium Demo", | 					"title": "Trilium Demo", | ||||||
| 					"notePosition": 20, | 					"notePosition": 20, | ||||||
| 					"prefix": null, | 					"prefix": null, | ||||||
| 					"isExpanded": true, | 					"isExpanded": false, | ||||||
| 					"type": "text", | 					"type": "text", | ||||||
| 					"mime": "text/html", | 					"mime": "text/html", | ||||||
| 					"attributes": [ | 					"attributes": [ | ||||||
| @@ -6033,6 +6040,68 @@ | |||||||
| 							] | 							] | ||||||
| 						} | 						} | ||||||
| 					] | 					] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"isClone": false, | ||||||
|  | 					"noteId": "fhNlr1V1o3d8", | ||||||
|  | 					"notePath": [ | ||||||
|  | 						"root", | ||||||
|  | 						"fhNlr1V1o3d8" | ||||||
|  | 					], | ||||||
|  | 					"title": "Miscellaneous", | ||||||
|  | 					"notePosition": 30, | ||||||
|  | 					"prefix": null, | ||||||
|  | 					"isExpanded": false, | ||||||
|  | 					"type": "text", | ||||||
|  | 					"mime": "text/html", | ||||||
|  | 					"attributes": [ | ||||||
|  | 						{ | ||||||
|  | 							"type": "label", | ||||||
|  | 							"name": "iconClass", | ||||||
|  | 							"value": "bx bx-dots-horizontal-rounded", | ||||||
|  | 							"isInheritable": false, | ||||||
|  | 							"position": 10 | ||||||
|  | 						} | ||||||
|  | 					], | ||||||
|  | 					"format": "html", | ||||||
|  | 					"attachments": [], | ||||||
|  | 					"dirFileName": "Miscellaneous", | ||||||
|  | 					"children": [ | ||||||
|  | 						{ | ||||||
|  | 							"isClone": false, | ||||||
|  | 							"noteId": "bRQvb9VCkc3t", | ||||||
|  | 							"notePath": [ | ||||||
|  | 								"root", | ||||||
|  | 								"fhNlr1V1o3d8", | ||||||
|  | 								"bRQvb9VCkc3t" | ||||||
|  | 							], | ||||||
|  | 							"title": "Day Note Template", | ||||||
|  | 							"notePosition": 10, | ||||||
|  | 							"prefix": null, | ||||||
|  | 							"isExpanded": false, | ||||||
|  | 							"type": "text", | ||||||
|  | 							"mime": "text/html", | ||||||
|  | 							"attributes": [ | ||||||
|  | 								{ | ||||||
|  | 									"type": "label", | ||||||
|  | 									"name": "iconClass", | ||||||
|  | 									"value": "bx bx-notepad", | ||||||
|  | 									"isInheritable": false, | ||||||
|  | 									"position": 10 | ||||||
|  | 								}, | ||||||
|  | 								{ | ||||||
|  | 									"type": "label", | ||||||
|  | 									"name": "excludeFromNoteMap", | ||||||
|  | 									"value": "", | ||||||
|  | 									"isInheritable": false, | ||||||
|  | 									"position": 20 | ||||||
|  | 								} | ||||||
|  | 							], | ||||||
|  | 							"format": "html", | ||||||
|  | 							"dataFileName": "Day Note Template.html", | ||||||
|  | 							"attachments": [] | ||||||
|  | 						} | ||||||
|  | 					] | ||||||
| 				} | 				} | ||||||
| 			] | 			] | ||||||
| 		}, | 		}, | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								apps/edit-docs/demo/navigation.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								apps/edit-docs/demo/navigation.html
									
									
									
									
										vendored
									
									
								
							| @@ -637,6 +637,12 @@ | |||||||
|               </li> |               </li> | ||||||
|             </ul> |             </ul> | ||||||
|           </li> |           </li> | ||||||
|  |           <li>Miscellaneous | ||||||
|  |             <ul> | ||||||
|  |               <li><a href="root/Miscellaneous/Day%20Note%20Template.html" target="detail">Day Note Template</a> | ||||||
|  |               </li> | ||||||
|  |             </ul> | ||||||
|  |           </li> | ||||||
|         </ul> |         </ul> | ||||||
|       </li> |       </li> | ||||||
|     </ul> |     </ul> | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								apps/edit-docs/demo/root/Miscellaneous/Day Note Template.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								apps/edit-docs/demo/root/Miscellaneous/Day Note Template.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | <html> | ||||||
|  |    | ||||||
|  |   <head> | ||||||
|  |     <meta charset="utf-8"> | ||||||
|  |     <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||||
|  |     <link rel="stylesheet" href="../../style.css"> | ||||||
|  |     <base target="_parent"> | ||||||
|  |     <title data-trilium-title>Day Note Template</title> | ||||||
|  |   </head> | ||||||
|  |    | ||||||
|  |   <body> | ||||||
|  |     <div class="content"> | ||||||
|  |        <h1 data-trilium-h1>Day Note Template</h1> | ||||||
|  |  | ||||||
|  |       <div class="ck-content"> | ||||||
|  |         <h2>☑️ Tasks</h2> | ||||||
|  |         <ul> | ||||||
|  |           <li data-list-item-id="e4b26220d6ce48997f1116dc1d1d83dc0">[…]</li> | ||||||
|  |         </ul> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </body> | ||||||
|  |  | ||||||
|  | </html> | ||||||
| @@ -23,10 +23,18 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	alert("Hello world"); | 	alert("Hello world"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| }</code></pre> | }</code></pre> | ||||||
|         <p>For larger pieces of code it is better to use a code note, which uses |         <p>For larger pieces of code it is better to use a code note, which uses | ||||||
|           a fully-fledged code editor (CodeMirror). For an example of a code note, |           a fully-fledged code editor (CodeMirror). For an example of a code note, | ||||||
|   | |||||||
| @@ -18,6 +18,10 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # This script opens 4 terminal windows. | # This script opens 4 terminal windows. | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -26,18 +30,38 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| i="0" | i="0" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| while [ $i -lt 4 ] | while [ $i -lt 4 ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| do | do | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     xterm & |     xterm & | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -46,10 +70,22 @@ do | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     i=$[$i+1] |     i=$[$i+1] | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| done</code></pre> | done</code></pre> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -110,7 +110,7 @@ | |||||||
|     "multer": "2.0.2", |     "multer": "2.0.2", | ||||||
|     "normalize-strings": "1.1.1", |     "normalize-strings": "1.1.1", | ||||||
|     "ollama": "0.6.0", |     "ollama": "0.6.0", | ||||||
|     "openai": "6.1.0", |     "openai": "6.2.0", | ||||||
|     "rand-token": "1.0.1", |     "rand-token": "1.0.1", | ||||||
|     "safe-compare": "1.1.4", |     "safe-compare": "1.1.4", | ||||||
|     "sanitize-filename": "1.6.3", |     "sanitize-filename": "1.6.3", | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							| @@ -116,6 +116,13 @@ class="admonition tip"> | |||||||
|         <td>JavaScript note which will be injected into the share page. JS note must |         <td>JavaScript note which will be injected into the share page. JS note must | ||||||
|           be in the shared sub-tree as well. Consider using <code>share_hidden_from_tree</code>.</td> |           be in the shared sub-tree as well. Consider using <code>share_hidden_from_tree</code>.</td> | ||||||
|       </tr> |       </tr> | ||||||
|  |       <tr> | ||||||
|  |         <td><code>shareHtml</code> | ||||||
|  |         </td> | ||||||
|  |         <td>HTML note which will be injected into the share page at locations specified | ||||||
|  |           by the <code>shareHtmlLocation</code> label. HTML note must be in the shared | ||||||
|  |           sub-tree as well. Consider using <code>share_hidden_from_tree</code>.</td> | ||||||
|  |       </tr> | ||||||
|       <tr> |       <tr> | ||||||
|         <td><code>shareTemplate</code> |         <td><code>shareTemplate</code> | ||||||
|         </td> |         </td> | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing.html
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing.html
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -6,8 +6,7 @@ class="image"> | |||||||
|   <img style="aspect-ratio:1144/660;" src="Sharing_image.png" width="1144" |   <img style="aspect-ratio:1144/660;" src="Sharing_image.png" width="1144" | ||||||
|   height="660"> |   height="660"> | ||||||
|   </figure> |   </figure> | ||||||
|    |   <h2>Features, interaction and limitations</h2> | ||||||
| <h2>Features, interaction and limitations</h2> |  | ||||||
|   <ul> |   <ul> | ||||||
|     <li>Searching by note title.</li> |     <li>Searching by note title.</li> | ||||||
|     <li>Automatic dark/light mode based on the user's browser settings.</li> |     <li>Automatic dark/light mode based on the user's browser settings.</li> | ||||||
| @@ -189,11 +188,9 @@ class="image"> | |||||||
|         <img src="Sharing_share-single-note.png" alt="Share Note"> |         <img src="Sharing_share-single-note.png" alt="Share Note"> | ||||||
|       </p> |       </p> | ||||||
|     </li> |     </li> | ||||||
|     <li> |     <li><strong>Access the Shared Note</strong>: The link provided will open the | ||||||
|       <p><strong>Access the Shared Note</strong>: The link provided will open the |       note in your browser. If your server is not configured with a public IP, | ||||||
|         note in your browser. If your server is not configured with a public IP, |       the URL will refer to <code>localhost (127.0.0.1)</code>.</li> | ||||||
|         the URL will refer to <code>localhost (127.0.0.1)</code>.</p> |  | ||||||
|     </li> |  | ||||||
|   </ol> |   </ol> | ||||||
|   <h2>Sharing a note subtree</h2> |   <h2>Sharing a note subtree</h2> | ||||||
|   <p>When you share a note, you actually share the entire subtree of notes |   <p>When you share a note, you actually share the entire subtree of notes | ||||||
| @@ -234,6 +231,34 @@ class="image"> | |||||||
|     This allows you to access note attributes or traverse the note tree using |     This allows you to access note attributes or traverse the note tree using | ||||||
|     the <code>fetchNote()</code> API, which retrieves note data based on its |     the <code>fetchNote()</code> API, which retrieves note data based on its | ||||||
|     ID.</p> |     ID.</p> | ||||||
|  |   <h3>Adding custom HTML</h3> | ||||||
|  |   <p>You can inject custom HTML snippets into specific locations of the shared | ||||||
|  |     page using the <code>~shareHtml</code> relation. The HTML note should contain | ||||||
|  |     the raw HTML content you want to inject, and you can control where it appears | ||||||
|  |     by adding the <code>#shareHtmlLocation</code> label to the HTML snippet note | ||||||
|  |     itself.</p> | ||||||
|  |   <p>The <code>#shareHtmlLocation</code> label accepts values in the format <code>location:position</code>:</p> | ||||||
|  |   <ul> | ||||||
|  |     <li><strong>Locations</strong>: <code>head</code>, <code>body</code>, <code>content</code> | ||||||
|  |     </li> | ||||||
|  |     <li><strong>Positions</strong>: <code>start</code>, <code>end</code> | ||||||
|  |     </li> | ||||||
|  |   </ul> | ||||||
|  |   <p>For example:</p> | ||||||
|  |   <ul> | ||||||
|  |     <li><code>#shareHtmlLocation=head:start</code> - Injects HTML at the beginning | ||||||
|  |       of the <code><head></code> section</li> | ||||||
|  |     <li><code>#shareHtmlLocation=head:end</code> - Injects HTML at the end of the <code><head></code> section | ||||||
|  |       (default)</li> | ||||||
|  |     <li><code>#shareHtmlLocation=body:start</code> - Injects HTML at the beginning | ||||||
|  |       of the <code><body></code> section</li> | ||||||
|  |     <li><code>#shareHtmlLocation=content:start</code> - Injects HTML at the beginning | ||||||
|  |       of the content area</li> | ||||||
|  |     <li><code>#shareHtmlLocation=content:end</code> - Injects HTML at the end of | ||||||
|  |       the content area</li> | ||||||
|  |   </ul> | ||||||
|  |   <p>If no location is specified, the HTML will be injected at <code>content:end</code> by | ||||||
|  |     default.</p> | ||||||
|   <p>Example:</p><pre><code class="language-application-javascript-env-backend">const currentNote = await fetchNote(); |   <p>Example:</p><pre><code class="language-application-javascript-env-backend">const currentNote = await fetchNote(); | ||||||
| const parentNote = await fetchNote(currentNote.parentNoteIds[0]); | const parentNote = await fetchNote(currentNote.parentNoteIds[0]); | ||||||
|  |  | ||||||
| @@ -344,6 +369,14 @@ for (const attr of parentNote.attributes) { | |||||||
|         </td> |         </td> | ||||||
|         <td>Note with this label will list all roots of shared notes.</td> |         <td>Note with this label will list all roots of shared notes.</td> | ||||||
|       </tr> |       </tr> | ||||||
|  |       <tr> | ||||||
|  |         <td><code>shareHtmlLocation</code> | ||||||
|  |         </td> | ||||||
|  |         <td>defines where custom HTML injected via <code>~shareHtml</code> relation | ||||||
|  |           should be placed. Applied to the HTML snippet note itself. Format: <code>location:position</code> where | ||||||
|  |           location is <code>head</code>, <code>body</code>, or <code>content</code> and | ||||||
|  |           position is <code>start</code> or <code>end</code>. Defaults to <code>content:end</code>.</td> | ||||||
|  |       </tr> | ||||||
|     </tbody> |     </tbody> | ||||||
|   </table> |   </table> | ||||||
|    |    | ||||||
|   | |||||||
| @@ -1,26 +1,26 @@ | |||||||
| { | { | ||||||
|   "keyboard_actions": { |   "keyboard_actions": { | ||||||
|     "back-in-note-history": "Navegar para a nota anterior no histórico", |     "back-in-note-history": "Navegar para a nota anterior no histórico", | ||||||
|     "forward-in-note-history": "Navegar para a próxima nota no histórico", |     "forward-in-note-history": "Navegar para a nota seguinte no histórico", | ||||||
|     "open-jump-to-note-dialog": "Abrir diálogo \"Ir para nota\"", |     "open-jump-to-note-dialog": "Abrir diálogo \"Ir para nota\"", | ||||||
|     "open-command-palette": "Abrir paleta de comandos", |     "open-command-palette": "Abrir paleta de comandos", | ||||||
|     "scroll-to-active-note": "Rolar a árvore de notas até a nota atual", |     "scroll-to-active-note": "Rolar a árvore de notas até a nota atual", | ||||||
|     "quick-search": "Ativar barra de pesquisa rápida", |     "quick-search": "Ativar barra de pesquisa rápida", | ||||||
|     "search-in-subtree": "Pesquisar notas na subárvore da nota atual", |     "search-in-subtree": "Pesquisar notas na sub-árvore da nota atual", | ||||||
|     "expand-subtree": "Expandir subárvore da nota atual", |     "expand-subtree": "Expandir sub-árvore da nota atual", | ||||||
|     "collapse-tree": "Colapsar a árvore completa de notas", |     "collapse-tree": "Colapsar a árvore de notas completa", | ||||||
|     "collapse-subtree": "Colapsar subárvore da nota atual", |     "collapse-subtree": "Colapsar sub-árvore da nota atual", | ||||||
|     "sort-child-notes": "Ordenar notas filhas", |     "sort-child-notes": "Ordenar notas filhas", | ||||||
|     "creating-and-moving-notes": "A criar e mover notas", |     "creating-and-moving-notes": "A criar e mover notas", | ||||||
|     "create-note-after": "Criar nota após nota atual", |     "create-note-after": "Criar nota após nota atual", | ||||||
|     "create-note-into": "Criar nota como subnota da nota atual", |     "create-note-into": "Criar nota como sub-nota da nota atual", | ||||||
|     "create-note-into-inbox": "Crie uma nota na caixa de entrada (se definida) ou na nota do dia", |     "create-note-into-inbox": "Criar uma nota na caixa de entrada (se definida) ou na nota do dia", | ||||||
|     "delete-note": "Apagar nota", |     "delete-note": "Apagar nota", | ||||||
|     "move-note-up": "Mover nota para cima", |     "move-note-up": "Mover nota para cima", | ||||||
|     "move-note-down": "Mover nota para baixo", |     "move-note-down": "Mover nota para baixo", | ||||||
|     "move-note-up-in-hierarchy": "Mover nota para cima na hierarquia", |     "move-note-up-in-hierarchy": "Mover nota para cima na hierarquia", | ||||||
|     "move-note-down-in-hierarchy": "Mover nota para baixo na hierarquia", |     "move-note-down-in-hierarchy": "Mover nota para baixo na hierarquia", | ||||||
|     "edit-note-title": "Pular da árvore para os pormenores da nota e editar o título", |     "edit-note-title": "Saltar da árvore para os pormenores da nota e editar o título", | ||||||
|     "edit-branch-prefix": "Exibir o diálogo \"Editar prefixo da ramificação\"", |     "edit-branch-prefix": "Exibir o diálogo \"Editar prefixo da ramificação\"", | ||||||
|     "clone-notes-to": "Clonar notas selecionadas", |     "clone-notes-to": "Clonar notas selecionadas", | ||||||
|     "move-notes-to": "Mover notas selecionadas", |     "move-notes-to": "Mover notas selecionadas", | ||||||
| @@ -31,36 +31,36 @@ | |||||||
|     "select-all-notes-in-parent": "Selecionar todas as notas do nível atual da nota", |     "select-all-notes-in-parent": "Selecionar todas as notas do nível atual da nota", | ||||||
|     "add-note-above-to-the-selection": "Adicionar nota acima à seleção", |     "add-note-above-to-the-selection": "Adicionar nota acima à seleção", | ||||||
|     "add-note-below-to-selection": "Adicionar nota abaixo à seleção", |     "add-note-below-to-selection": "Adicionar nota abaixo à seleção", | ||||||
|     "duplicate-subtree": "Duplicar subárvores", |     "duplicate-subtree": "Duplicar subárvore", | ||||||
|     "tabs-and-windows": "Guias & Janelas", |     "tabs-and-windows": "Separadores & Janelas", | ||||||
|     "open-new-tab": "Abre nova guia", |     "open-new-tab": "Abre novo separador", | ||||||
|     "close-active-tab": "Fecha guia ativa", |     "close-active-tab": "Fechar separador ativo", | ||||||
|     "reopen-last-tab": "Reabre a última guia fechada", |     "reopen-last-tab": "Reabre o último separador fechado", | ||||||
|     "activate-next-tab": "Ativa guia à direita", |     "activate-next-tab": "Ativa separador à direita", | ||||||
|     "activate-previous-tab": "Ativa guia à esquerda", |     "activate-previous-tab": "Ativa separador à esquerda", | ||||||
|     "open-new-window": "Abre nova janela vazia", |     "open-new-window": "Abre nova janela vazia", | ||||||
|     "toggle-tray": "Mostrar/ocultar a aplicação da bandeja do sistema", |     "toggle-tray": "Mostrar/ocultar a aplicação na bandeja do sistema", | ||||||
|     "first-tab": "Ativa a primeira guia na lista", |     "first-tab": "Ativar o primeiro separador na lista", | ||||||
|     "second-tab": "Ativa a segunda guia na lista", |     "second-tab": "Ativa o segundo separador na lista", | ||||||
|     "third-tab": "Ativa a terceira guia na lista", |     "third-tab": "Ativar o terceiro separador na lista", | ||||||
|     "fourth-tab": "Ativa a quarta guia na lista", |     "fourth-tab": "Ativar o quarto separador na lista", | ||||||
|     "fifth-tab": "Ativa a quinta guia na lista", |     "fifth-tab": "Ativar o quinto separador na lista", | ||||||
|     "sixth-tab": "Ativa a sexta guia na lista", |     "sixth-tab": "Ativar o sexto separador na lista", | ||||||
|     "seventh-tab": "Ativa a sétima guia na lista", |     "seventh-tab": "Ativar o sétimo separador na lista", | ||||||
|     "eight-tab": "Ativa a oitava guia na lista", |     "eight-tab": "Ativar o oitavo separador na lista", | ||||||
|     "ninth-tab": "Ativa a nona guia na lista", |     "ninth-tab": "Ativar o novo separador na lista", | ||||||
|     "last-tab": "Ativa a última guia na lista", |     "last-tab": "Ativar o último separador na lista", | ||||||
|     "dialogs": "Diálogos", |     "dialogs": "Diálogos", | ||||||
|     "show-note-source": "Exibe o diálogo de origem da nota", |     "show-note-source": "Exibe o diálogo \"origem da nota\"", | ||||||
|     "show-options": "Mostrar página de configurações", |     "show-options": "Abrir página de configurações", | ||||||
|     "show-revisions": "Exibe diálogo de revisões de nota", |     "show-revisions": "Exibe diálogo \"revisões de nota\"", | ||||||
|     "show-recent-changes": "Exibe o diálogo de alterações recentes", |     "show-recent-changes": "Exibe o diálogo \"alterações recentes\"", | ||||||
|     "show-sql-console": "Exibe a página do console SQL", |     "show-sql-console": "Exibe a página \"consola SQL\"", | ||||||
|     "show-backend-log": "Exibe a página do backend", |     "show-backend-log": "Exibe a página \"registo do backend\"", | ||||||
|     "show-help": "Exibir Ajuda integrada / colinha", |     "show-help": "Exibir o guia de utilizador integrado", | ||||||
|     "show-cheatsheet": "Exibir um modal com operações comuns de teclado", |     "show-cheatsheet": "Exibir um modal com atalhos de teclado", | ||||||
|     "text-note-operations": "Operações de nota de texto", |     "text-note-operations": "Operações de nota de texto", | ||||||
|     "add-link-to-text": "Abrir diálogo e adicionar ligação ao texto", |     "add-link-to-text": "Abrir diálogo para adicionar ligação ao texto", | ||||||
|     "follow-link-under-cursor": "Seguir a ligação sob o cursor", |     "follow-link-under-cursor": "Seguir a ligação sob o cursor", | ||||||
|     "insert-date-and-time-to-text": "Inserir data e hora atual no texto", |     "insert-date-and-time-to-text": "Inserir data e hora atual no texto", | ||||||
|     "paste-markdown-into-text": "Colar Markdown da área de transferência na nota de texto", |     "paste-markdown-into-text": "Colar Markdown da área de transferência na nota de texto", | ||||||
|   | |||||||
| @@ -16,7 +16,8 @@ vi.mock("../../services/ws.js", () => ({ | |||||||
|     default: { |     default: { | ||||||
|         sendMessageToAllClients: vi.fn(), |         sendMessageToAllClients: vi.fn(), | ||||||
|         sendTransactionEntityChangesToAllClients: vi.fn(), |         sendTransactionEntityChangesToAllClients: vi.fn(), | ||||||
|         setLastSyncedPush: vi.fn() |         setLastSyncedPush: vi.fn(), | ||||||
|  |         syncFailed() {} | ||||||
|     } |     } | ||||||
| })); | })); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -97,6 +97,8 @@ const ALLOWED_OPTIONS = new Set<OptionNames>([ | |||||||
|     "allowedHtmlTags", |     "allowedHtmlTags", | ||||||
|     "redirectBareDomain", |     "redirectBareDomain", | ||||||
|     "showLoginInShareTheme", |     "showLoginInShareTheme", | ||||||
|  |     "shareSubtree", | ||||||
|  |     "sharePath", | ||||||
|     "splitEditorOrientation", |     "splitEditorOrientation", | ||||||
|     "seenCallToActions", |     "seenCallToActions", | ||||||
|  |  | ||||||
|   | |||||||
| @@ -80,6 +80,7 @@ const GET = "get", | |||||||
|     DEL = "delete"; |     DEL = "delete"; | ||||||
|  |  | ||||||
| function register(app: express.Application) { | function register(app: express.Application) { | ||||||
|  |  | ||||||
|     route(GET, "/", [auth.checkAuth, csrfMiddleware], indexRoute.index); |     route(GET, "/", [auth.checkAuth, csrfMiddleware], indexRoute.index); | ||||||
|     route(GET, "/login", [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage); |     route(GET, "/login", [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage); | ||||||
|     route(GET, "/set-password", [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPasswordPage); |     route(GET, "/set-password", [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPasswordPage); | ||||||
|   | |||||||
| @@ -37,9 +37,26 @@ function checkAuth(req: Request, res: Response, next: NextFunction) { | |||||||
|             // Check if any note has the #shareRoot label |             // Check if any note has the #shareRoot label | ||||||
|             const shareRootNotes = attributes.getNotesWithLabel("shareRoot"); |             const shareRootNotes = attributes.getNotesWithLabel("shareRoot"); | ||||||
|             if (shareRootNotes.length === 0) { |             if (shareRootNotes.length === 0) { | ||||||
|  |                 // should this be a translation string? | ||||||
|                 res.status(404).json({ message: "Share root not found. Please set up a note with #shareRoot label first." }); |                 res.status(404).json({ message: "Share root not found. Please set up a note with #shareRoot label first." }); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             // Get the configured share path | ||||||
|  |             const sharePath = options.getOption("sharePath") || '/share'; | ||||||
|  |  | ||||||
|  |             // Check if we're already at the share path to prevent redirect loops | ||||||
|  |             if (req.path === sharePath || req.path.startsWith(`${sharePath}/`)) { | ||||||
|  |                 log.info(`checkAuth: Already at share path, skipping redirect. Path: ${req.path}, SharePath: ${sharePath}`); | ||||||
|  |                 next(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Redirect to the share path | ||||||
|  |             log.info(`checkAuth: Redirecting to share path. From: ${req.path}, To: ${sharePath}`); | ||||||
|  |             res.redirect(`${sharePath}/`); | ||||||
|  |         } else { | ||||||
|  |             res.redirect("login"); | ||||||
|         } |         } | ||||||
|         res.redirect(hasRedirectBareDomain ? "share" : "login"); |         res.redirect(hasRedirectBareDomain ? "share" : "login"); | ||||||
|     } else if (currentTotpStatus !== lastAuthState.totpEnabled || currentSsoStatus !== lastAuthState.ssoEnabled) { |     } else if (currentTotpStatus !== lastAuthState.totpEnabled || currentSsoStatus !== lastAuthState.ssoEnabled) { | ||||||
| @@ -81,15 +98,6 @@ function checkApiAuthOrElectron(req: Request, res: Response, next: NextFunction) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function checkApiAuth(req: Request, res: Response, next: NextFunction) { |  | ||||||
|     if (!req.session.loggedIn && !noAuthentication) { |  | ||||||
|         console.warn(`Missing session with ID '${req.sessionID}'.`); |  | ||||||
|         reject(req, res, "Logged in session not found"); |  | ||||||
|     } else { |  | ||||||
|         next(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function checkAppInitialized(req: Request, res: Response, next: NextFunction) { | function checkAppInitialized(req: Request, res: Response, next: NextFunction) { | ||||||
|     if (!sqlInit.isDbInitialized()) { |     if (!sqlInit.isDbInitialized()) { | ||||||
|         res.redirect("setup"); |         res.redirect("setup"); | ||||||
|   | |||||||
| @@ -66,6 +66,7 @@ export default [ | |||||||
|     { type: "label", name: "shareDisallowRobotIndexing" }, |     { type: "label", name: "shareDisallowRobotIndexing" }, | ||||||
|     { type: "label", name: "shareCredentials" }, |     { type: "label", name: "shareCredentials" }, | ||||||
|     { type: "label", name: "shareIndex" }, |     { type: "label", name: "shareIndex" }, | ||||||
|  |     { type: "label", name: "shareHtmlLocation" }, | ||||||
|     { type: "label", name: "displayRelations" }, |     { type: "label", name: "displayRelations" }, | ||||||
|     { type: "label", name: "hideRelations" }, |     { type: "label", name: "hideRelations" }, | ||||||
|     { type: "label", name: "titleTemplate", isDangerous: true }, |     { type: "label", name: "titleTemplate", isDangerous: true }, | ||||||
| @@ -105,6 +106,7 @@ export default [ | |||||||
|     { type: "relation", name: "renderNote", isDangerous: true }, |     { type: "relation", name: "renderNote", isDangerous: true }, | ||||||
|     { type: "relation", name: "shareCss" }, |     { type: "relation", name: "shareCss" }, | ||||||
|     { type: "relation", name: "shareJs" }, |     { type: "relation", name: "shareJs" }, | ||||||
|  |     { type: "relation", name: "shareHtml" }, | ||||||
|     { type: "relation", name: "shareTemplate" }, |     { type: "relation", name: "shareTemplate" }, | ||||||
|     { type: "relation", name: "shareFavicon" } |     { type: "relation", name: "shareFavicon" } | ||||||
| ]; | ]; | ||||||
|   | |||||||
| @@ -9,13 +9,13 @@ import { changeLanguage } from "./i18n.js"; | |||||||
| import { deferred } from "./utils.js"; | import { deferred } from "./utils.js"; | ||||||
|  |  | ||||||
| describe("Hidden Subtree", () => { | describe("Hidden Subtree", () => { | ||||||
|     describe("Launcher movement persistence", () => { |     beforeAll(async () => { | ||||||
|         beforeAll(async () => { |         sql_init.initializeDb(); | ||||||
|             sql_init.initializeDb(); |         await sql_init.dbReady; | ||||||
|             await sql_init.dbReady; |         cls.init(() => hiddenSubtreeService.checkHiddenSubtree()); | ||||||
|             cls.init(() => hiddenSubtreeService.checkHiddenSubtree()); |     }); | ||||||
|         }); |  | ||||||
|  |  | ||||||
|  |     describe("Launcher movement persistence", () => { | ||||||
|         it("should persist launcher movement between visible and available after integrity check", () => { |         it("should persist launcher movement between visible and available after integrity check", () => { | ||||||
|             // Move backend log to visible launchers. |             // Move backend log to visible launchers. | ||||||
|             const backendLogBranch = becca.getBranchFromChildAndParent("_lbBackendLog", "_lbAvailableLaunchers"); |             const backendLogBranch = becca.getBranchFromChildAndParent("_lbBackendLog", "_lbAvailableLaunchers"); | ||||||
| @@ -119,4 +119,14 @@ describe("Hidden Subtree", () => { | |||||||
|             await done; |             await done; | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     describe("Hidden subtree", () => { | ||||||
|  |         it("cleans up exclude from note map at the root", async () => { | ||||||
|  |             const hiddenSubtree = becca.getNoteOrThrow("_hidden"); | ||||||
|  |             cls.init(() => hiddenSubtree.addLabel("excludeFromNoteMap")); | ||||||
|  |             expect(hiddenSubtree.hasLabel("excludeFromNoteMap")).toBeTruthy(); | ||||||
|  |             cls.init(() => hiddenSubtreeService.checkHiddenSubtree()); | ||||||
|  |             expect(hiddenSubtree.hasLabel("excludeFromNoteMap")).toBeFalsy(); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -40,8 +40,8 @@ function buildHiddenSubtreeDefinition(helpSubtree: HiddenSubtreeItem[]): HiddenS | |||||||
|         // we want to keep the hidden subtree always last, otherwise there will be problems with e.g., keyboard navigation |         // we want to keep the hidden subtree always last, otherwise there will be problems with e.g., keyboard navigation | ||||||
|         // over tree when it's in the middle |         // over tree when it's in the middle | ||||||
|         notePosition: 999_999_999, |         notePosition: 999_999_999, | ||||||
|  |         enforceAttributes: true, | ||||||
|         attributes: [ |         attributes: [ | ||||||
|             { type: "label", name: "excludeFromNoteMap", isInheritable: true }, |  | ||||||
|             { type: "label", name: "docName", value: "hidden" } |             { type: "label", name: "docName", value: "hidden" } | ||||||
|         ], |         ], | ||||||
|         children: [ |         children: [ | ||||||
| @@ -441,6 +441,15 @@ function checkHiddenSubtreeRecursively(parentNoteId: string, item: HiddenSubtree | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Enforce attribute structure if needed. | ||||||
|  |     if (item.enforceAttributes) { | ||||||
|  |         for (const attribute of note.getAttributes()) { | ||||||
|  |             if (!attrs.some(a => a.name === attribute.name)) { | ||||||
|  |                 attribute.markAsDeleted(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     for (const attr of attrs) { |     for (const attr of attrs) { | ||||||
|         const attrId = note.noteId + "_" + attr.type.charAt(0) + attr.name; |         const attrId = note.noteId + "_" + attr.type.charAt(0) + attr.name; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,17 +1,7 @@ | |||||||
| import sanitizeHtml from "sanitize-html"; | import sanitizeHtml from "sanitize-html"; | ||||||
| import { sanitizeUrl } from "@braintree/sanitize-url"; | import { sanitizeUrl } from "@braintree/sanitize-url"; | ||||||
| import optionService from "./options.js"; | import optionService from "./options.js"; | ||||||
| import { SANITIZER_DEFAULT_ALLOWED_TAGS } from "@triliumnext/commons"; | import { ALLOWED_PROTOCOLS, SANITIZER_DEFAULT_ALLOWED_TAGS } from "@triliumnext/commons"; | ||||||
|  |  | ||||||
| // Be consistent with `ALLOWED_PROTOCOLS` in `src\public\app\services\link.js` |  | ||||||
| // TODO: Deduplicate with client once we can. |  | ||||||
| export const ALLOWED_PROTOCOLS = [ |  | ||||||
|     'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git', |  | ||||||
|     'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message', |  | ||||||
|     'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp', |  | ||||||
|     'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo', |  | ||||||
|     'mid' |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| // intended mainly as protection against XSS via import | // intended mainly as protection against XSS via import | ||||||
| // secondarily, it (partly) protects against "CSS takeover" | // secondarily, it (partly) protects against "CSS takeover" | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; | import { describe, it, expect, vi, beforeEach } from 'vitest'; | ||||||
| import { StreamProcessor, createStreamHandler, processProviderStream, extractStreamStats, performProviderHealthCheck } from './stream_handler.js'; | import { StreamProcessor, createStreamHandler, processProviderStream, extractStreamStats, performProviderHealthCheck } from './stream_handler.js'; | ||||||
| import type { StreamProcessingOptions, StreamChunk, ProviderStreamOptions } from './stream_handler.js'; | import type { StreamProcessingOptions, StreamChunk } from './stream_handler.js'; | ||||||
|  |  | ||||||
| // Mock the log module | // Mock the log module | ||||||
| vi.mock('../../log.js', () => ({ | vi.mock('../../log.js', () => ({ | ||||||
|   | |||||||
| @@ -196,8 +196,10 @@ const defaultOptions: DefaultOption[] = [ | |||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     // Share settings |     // Share settings | ||||||
|  |     { name: "sharePath", value: "/share", isSynced: true }, | ||||||
|     { name: "redirectBareDomain", value: "false", isSynced: true }, |     { name: "redirectBareDomain", value: "false", isSynced: true }, | ||||||
|     { name: "showLoginInShareTheme", value: "false", isSynced: true }, |     { name: "showLoginInShareTheme", value: "false", isSynced: true }, | ||||||
|  |     { name: "shareSubtree", value: "false", isSynced: true }, | ||||||
|  |  | ||||||
|     // AI Options |     // AI Options | ||||||
|     { name: "aiEnabled", value: "false", isSynced: true }, |     { name: "aiEnabled", value: "false", isSynced: true }, | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ export function getContent(note: SNote) { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     if (note.type === "text") { |     if (note.type === "text") { | ||||||
|         renderText(result, note); |         renderText(result, note, relativePath); | ||||||
|     } else if (note.type === "code") { |     } else if (note.type === "code") { | ||||||
|         renderCode(result); |         renderCode(result); | ||||||
|     } else if (note.type === "mermaid") { |     } else if (note.type === "mermaid") { | ||||||
| @@ -106,10 +106,10 @@ function renderText(result: Result, note: SNote) { | |||||||
|  |  | ||||||
|         if (result.content.includes(`<span class="math-tex">`)) { |         if (result.content.includes(`<span class="math-tex">`)) { | ||||||
|             result.header += ` |             result.header += ` | ||||||
| <script src="../${assetPath}/node_modules/katex/dist/katex.min.js"></script> | <script src="${relativePath}${assetPath}/node_modules/katex/dist/katex.min.js"></script> | ||||||
| <link rel="stylesheet" href="../${assetPath}/node_modules/katex/dist/katex.min.css"> | <link rel="stylesheet" href="${relativePath}${assetPath}/node_modules/katex/dist/katex.min.css"> | ||||||
| <script src="../${assetPath}/node_modules/katex/dist/contrib/auto-render.min.js"></script> | <script src="${relativePath}${assetPath}/node_modules/katex/dist/contrib/auto-render.min.js"></script> | ||||||
| <script src="../${assetPath}/node_modules/katex/dist/contrib/mhchem.min.js"></script> | <script src="${relativePath}${assetPath}/node_modules/katex/dist/contrib/mhchem.min.js"></script> | ||||||
| <script> | <script> | ||||||
| document.addEventListener("DOMContentLoaded", function() { | document.addEventListener("DOMContentLoaded", function() { | ||||||
|     renderMathInElement(document.getElementById('content')); |     renderMathInElement(document.getElementById('content')); | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ describe("Share API test", () => { | |||||||
|     let cannotSetHeadersCount = 0; |     let cannotSetHeadersCount = 0; | ||||||
|  |  | ||||||
|     beforeAll(async () => { |     beforeAll(async () => { | ||||||
|  |         vi.useFakeTimers(); | ||||||
|         const buildApp = (await import("../app.js")).default; |         const buildApp = (await import("../app.js")).default; | ||||||
|         app = await buildApp(); |         app = await buildApp(); | ||||||
|         app.use((err: unknown, req: Request, res: Response, next: NextFunction) => { |         app.use((err: unknown, req: Request, res: Response, next: NextFunction) => { | ||||||
| @@ -43,3 +44,39 @@ describe("Share API test", () => { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | describe("Share Routes - Asset Path Calculation", () => { | ||||||
|  |     it("should calculate correct relative path depth for different share paths", () => { | ||||||
|  |         // Helper function to simulate the path depth calculation | ||||||
|  |         const calculateRelativePath = (sharePath: string) => { | ||||||
|  |             const pathDepth = sharePath.split('/').filter(segment => segment.length > 0).length; | ||||||
|  |             return '../'.repeat(pathDepth); | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         // Test single level path | ||||||
|  |         expect(calculateRelativePath("/share")).toBe("../"); | ||||||
|  |  | ||||||
|  |         // Test double level path | ||||||
|  |         expect(calculateRelativePath("/sharePath/test")).toBe("../../"); | ||||||
|  |  | ||||||
|  |         // Test triple level path | ||||||
|  |         expect(calculateRelativePath("/my/custom/share")).toBe("../../../"); | ||||||
|  |  | ||||||
|  |         // Test root path | ||||||
|  |         expect(calculateRelativePath("/")).toBe(""); | ||||||
|  |  | ||||||
|  |         // Test path with trailing slash | ||||||
|  |         expect(calculateRelativePath("/share/")).toBe("../"); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it("should handle normalized share paths correctly", () => { | ||||||
|  |         const calculateRelativePath = (sharePath: string) => { | ||||||
|  |             const pathDepth = sharePath.split('/').filter(segment => segment.length > 0).length; | ||||||
|  |             return '../'.repeat(pathDepth); | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         // Test the examples from the original TODO comment | ||||||
|  |         expect(calculateRelativePath("/sharePath")).toBe("../"); | ||||||
|  |         expect(calculateRelativePath("/sharePath/test")).toBe("../../"); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import safeCompare from "safe-compare"; | import safeCompare from "safe-compare"; | ||||||
|  |  | ||||||
| import type { Request, Response, Router } from "express"; | import type { Request, Response, Router, NextFunction } from "express"; | ||||||
|  |  | ||||||
| import shaca from "./shaca/shaca.js"; | import shaca from "./shaca/shaca.js"; | ||||||
| import shacaLoader from "./shaca/shaca_loader.js"; | import shacaLoader from "./shaca/shaca_loader.js"; | ||||||
| @@ -139,17 +139,21 @@ function renderImageAttachment(image: SNote, res: Response, attachmentName: stri | |||||||
| } | } | ||||||
|  |  | ||||||
| function register(router: Router) { | function register(router: Router) { | ||||||
|     function renderNote(note: SNote, req: Request, res: Response) { |         function renderNote(note: SNote, req: Request, res: Response) { | ||||||
|  |         // Calculate the correct relative path depth based on the current request path | ||||||
|  |         // We need to go up one level for each path segment in the request URL | ||||||
|  |         const pathSegments = req.path.split('/').filter(segment => segment.length > 0); | ||||||
|  |         const relativePath = '../'.repeat(pathSegments.length); | ||||||
|  |  | ||||||
|         if (!note) { |         if (!note) { | ||||||
|             console.log("Unable to find note ", note); |             console.log("Unable to find note ", note); | ||||||
|             res.status(404); |             res.status(404); | ||||||
|             renderDefault(res, "404"); |             renderDefault(res, "404", { relativePath, t }); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!checkNoteAccess(note.noteId, req, res)) { |         if (!checkNoteAccess(note.noteId, req, res)) { | ||||||
|             requestCredentials(res); |             requestCredentials(res); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -161,18 +165,20 @@ function register(router: Router) { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const { header, content, isEmpty } = contentRenderer.getContent(note); |         const { header, content, isEmpty } = contentRenderer.getContent(note, relativePath); | ||||||
|         const subRoot = getSharedSubTreeRoot(note); |         const subRoot = getSharedSubTreeRoot(note); | ||||||
|         const showLoginInShareTheme = options.getOption("showLoginInShareTheme"); |         const showLoginInShareTheme = options.getOption("showLoginInShareTheme"); | ||||||
|  |  | ||||||
|         const opts = { |         const opts = { | ||||||
|             note, |             note, | ||||||
|             header, |             header, | ||||||
|             content, |             content, | ||||||
|             isEmpty, |             isEmpty, | ||||||
|             subRoot, |             subRoot, | ||||||
|             assetPath: isDev ? assetPath : `../${assetPath}`, |             assetPath: isDev ? assetPath : `${relativePath}${assetPath}`, | ||||||
|             assetUrlFragment, |             assetUrlFragment, | ||||||
|             appPath: isDev ? appPath : `../${appPath}`, |             appPath: isDev ? appPath : `${relativePath}${appPath}`, | ||||||
|  |             relativePath, | ||||||
|             showLoginInShareTheme, |             showLoginInShareTheme, | ||||||
|             t, |             t, | ||||||
|             isDev |             isDev | ||||||
| @@ -219,184 +225,165 @@ function register(router: Router) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     router.get("/share/", (req, res) => { |     // Dynamic dispatch middleware | ||||||
|         if (req.path.substr(-1) !== "/") { |     router.use((req: Request, res: Response, next: NextFunction) => { | ||||||
|             res.redirect("../share/"); |         const sharePath = options.getOptionOrNull("sharePath") || "/share"; | ||||||
|             return; |         // Only handle requests starting with sharePath | ||||||
|  |         if (req.path === sharePath || req.path.startsWith(sharePath + "/")) { | ||||||
|  |             // Remove sharePath prefix to get the remaining path | ||||||
|  |             const subPath = req.path.slice(sharePath.length); | ||||||
|  |             // Handle root path | ||||||
|  |             if (subPath === "" || subPath === "/") { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 if (!shaca.shareRootNote) { | ||||||
|  |                     res.status(404).json({ message: "Share root not found" }); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 renderNote(shaca.shareRootNote, req, res); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /:shareId | ||||||
|  |             const shareIdMatch = subPath.match(/^\/([^/]+)$/); | ||||||
|  |             if (shareIdMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const shareId = shareIdMatch[1]; | ||||||
|  |                 const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; | ||||||
|  |                 renderNote(note, req, res); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /api/notes/:noteId | ||||||
|  |             const apiNoteMatch = subPath.match(/^\/api\/notes\/([^/]+)$/); | ||||||
|  |             if (apiNoteMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const noteId = apiNoteMatch[1]; | ||||||
|  |                 let note: SNote | boolean; | ||||||
|  |                 if (!(note = checkNoteAccess(noteId, req, res))) return; | ||||||
|  |                 addNoIndexHeader(note, res); | ||||||
|  |                 res.json(note.getPojo()); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /api/notes/:noteId/download | ||||||
|  |             const apiNoteDownloadMatch = subPath.match(/^\/api\/notes\/([^/]+)\/download$/); | ||||||
|  |             if (apiNoteDownloadMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const noteId = apiNoteDownloadMatch[1]; | ||||||
|  |                 let note: SNote | boolean; | ||||||
|  |                 if (!(note = checkNoteAccess(noteId, req, res))) return; | ||||||
|  |                 addNoIndexHeader(note, res); | ||||||
|  |                 const filename = utils.formatDownloadTitle(note.title, note.type, note.mime); | ||||||
|  |                 res.setHeader("Content-Disposition", utils.getContentDisposition(filename)); | ||||||
|  |                 res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | ||||||
|  |                 res.setHeader("Content-Type", note.mime); | ||||||
|  |                 res.send(note.getContent()); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /api/images/:noteId/:filename | ||||||
|  |             const apiImageMatch = subPath.match(/^\/api\/images\/([^/]+)\/([^/]+)$/); | ||||||
|  |             if (apiImageMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const noteId = apiImageMatch[1]; | ||||||
|  |                 let image: SNote | boolean; | ||||||
|  |                 if (!(image = checkNoteAccess(noteId, req, res))) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 if (image.type === "image") { | ||||||
|  |                     // normal image | ||||||
|  |                     res.set("Content-Type", image.mime); | ||||||
|  |                     addNoIndexHeader(image, res); | ||||||
|  |                     res.send(image.getContent()); | ||||||
|  |                 } else if (image.type === "canvas") { | ||||||
|  |                     renderImageAttachment(image, res, "canvas-export.svg"); | ||||||
|  |                 } else if (image.type === "mermaid") { | ||||||
|  |                     renderImageAttachment(image, res, "mermaid-export.svg"); | ||||||
|  |                 } else if (image.type === "mindMap") { | ||||||
|  |                     renderImageAttachment(image, res, "mindmap-export.svg"); | ||||||
|  |                 } else { | ||||||
|  |                     res.status(400).json({ message: "Requested note is not a shareable image" }); | ||||||
|  |                 } | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /api/attachments/:attachmentId/image/:filename | ||||||
|  |             const apiAttachmentImageMatch = subPath.match(/^\/api\/attachments\/([^/]+)\/image\/([^/]+)$/); | ||||||
|  |             if (apiAttachmentImageMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const attachmentId = apiAttachmentImageMatch[1]; | ||||||
|  |                 let attachment: SAttachment | boolean; | ||||||
|  |                 if (!(attachment = checkAttachmentAccess(attachmentId, req, res))) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 if (attachment.role === "image") { | ||||||
|  |                     res.set("Content-Type", attachment.mime); | ||||||
|  |                     addNoIndexHeader(attachment.note, res); | ||||||
|  |                     res.send(attachment.getContent()); | ||||||
|  |                 } else { | ||||||
|  |                     res.status(400).json({ message: "Requested attachment is not a shareable image" }); | ||||||
|  |                 } | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /api/attachments/:attachmentId/download | ||||||
|  |             const apiAttachmentDownloadMatch = subPath.match(/^\/api\/attachments\/([^/]+)\/download$/); | ||||||
|  |             if (apiAttachmentDownloadMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const attachmentId = apiAttachmentDownloadMatch[1]; | ||||||
|  |                 let attachment: SAttachment | boolean; | ||||||
|  |                 if (!(attachment = checkAttachmentAccess(attachmentId, req, res))) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 addNoIndexHeader(attachment.note, res); | ||||||
|  |                 const filename = utils.formatDownloadTitle(attachment.title, null, attachment.mime); | ||||||
|  |                 res.setHeader("Content-Disposition", utils.getContentDisposition(filename)); | ||||||
|  |                 res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | ||||||
|  |                 res.setHeader("Content-Type", attachment.mime); | ||||||
|  |                 res.send(attachment.getContent()); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /api/notes/:noteId/view | ||||||
|  |             const apiNoteViewMatch = subPath.match(/^\/api\/notes\/([^/]+)\/view$/); | ||||||
|  |             if (apiNoteViewMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const noteId = apiNoteViewMatch[1]; | ||||||
|  |                 let note: SNote | boolean; | ||||||
|  |                 if (!(note = checkNoteAccess(noteId, req, res))) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 addNoIndexHeader(note, res); | ||||||
|  |                 res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | ||||||
|  |                 res.setHeader("Content-Type", note.mime); | ||||||
|  |                 res.send(note.getContent()); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // Handle /api/notes 搜索 | ||||||
|  |             const apiNotesSearchMatch = subPath.match(/^\/api\/notes$/); | ||||||
|  |             if (apiNotesSearchMatch) { | ||||||
|  |                 shacaLoader.ensureLoad(); | ||||||
|  |                 const ancestorNoteId = req.query.ancestorNoteId ?? "_share"; | ||||||
|  |                 if (typeof ancestorNoteId !== "string") { | ||||||
|  |                     res.status(400).json({ message: "'ancestorNoteId' parameter is mandatory." }); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 // This will automatically return if no ancestorNoteId is provided and there is no shareIndex | ||||||
|  |                 if (!checkNoteAccess(ancestorNoteId, req, res)) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 const { search } = req.query; | ||||||
|  |                 if (typeof search !== "string" || !search?.trim()) { | ||||||
|  |                     res.status(400).json({ message: "'search' parameter is mandatory." }); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 const searchContext = new SearchContext({ ancestorNoteId: ancestorNoteId }); | ||||||
|  |                 const searchResults = searchService.findResultsWithQuery(search, searchContext); | ||||||
|  |                 const filteredResults = searchResults.map((sr) => { | ||||||
|  |                     const fullNote = shaca.notes[sr.noteId]; | ||||||
|  |                     const startIndex = sr.notePathArray.indexOf(ancestorNoteId); | ||||||
|  |                     const localPathArray = sr.notePathArray.slice(startIndex + 1).filter((id) => shaca.notes[id]); | ||||||
|  |                     const pathTitle = localPathArray.map((id) => shaca.notes[id].title).join(" / "); | ||||||
|  |                     return { id: fullNote.shareId, title: fullNote.title, score: sr.score, path: pathTitle }; | ||||||
|  |                 }); | ||||||
|  |                 res.json({ results: filteredResults }); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |         next(); | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         if (!shaca.shareRootNote) { |  | ||||||
|             res.status(404).json({ message: "Share root note not found" }); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         renderNote(shaca.shareRootNote, req, res); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     router.get("/share/:shareId", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         const { shareId } = req.params; |  | ||||||
|  |  | ||||||
|         const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; |  | ||||||
|  |  | ||||||
|         renderNote(note, req, res); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     router.get("/share/api/notes/:noteId", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|         let note: SNote | boolean; |  | ||||||
|  |  | ||||||
|         if (!(note = checkNoteAccess(req.params.noteId, req, res))) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         addNoIndexHeader(note, res); |  | ||||||
|  |  | ||||||
|         res.json(note.getPojo()); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     router.get("/share/api/notes/:noteId/download", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         let note: SNote | boolean; |  | ||||||
|  |  | ||||||
|         if (!(note = checkNoteAccess(req.params.noteId, req, res))) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         addNoIndexHeader(note, res); |  | ||||||
|  |  | ||||||
|         const filename = utils.formatDownloadTitle(note.title, note.type, note.mime); |  | ||||||
|  |  | ||||||
|         res.setHeader("Content-Disposition", utils.getContentDisposition(filename)); |  | ||||||
|  |  | ||||||
|         res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); |  | ||||||
|         res.setHeader("Content-Type", note.mime); |  | ||||||
|  |  | ||||||
|         res.send(note.getContent()); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename |  | ||||||
|     router.get("/share/api/images/:noteId/:filename", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         let image: SNote | boolean; |  | ||||||
|  |  | ||||||
|         if (!(image = checkNoteAccess(req.params.noteId, req, res))) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (image.type === "image") { |  | ||||||
|             // normal image |  | ||||||
|             res.set("Content-Type", image.mime); |  | ||||||
|             addNoIndexHeader(image, res); |  | ||||||
|             res.send(image.getContent()); |  | ||||||
|         } else if (image.type === "canvas") { |  | ||||||
|             renderImageAttachment(image, res, "canvas-export.svg"); |  | ||||||
|         } else if (image.type === "mermaid") { |  | ||||||
|             renderImageAttachment(image, res, "mermaid-export.svg"); |  | ||||||
|         } else if (image.type === "mindMap") { |  | ||||||
|             renderImageAttachment(image, res, "mindmap-export.svg"); |  | ||||||
|         } else { |  | ||||||
|             res.status(400).json({ message: "Requested note is not a shareable image" }); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename |  | ||||||
|     router.get("/share/api/attachments/:attachmentId/image/:filename", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         let attachment: SAttachment | boolean; |  | ||||||
|  |  | ||||||
|         if (!(attachment = checkAttachmentAccess(req.params.attachmentId, req, res))) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (attachment.role === "image") { |  | ||||||
|             res.set("Content-Type", attachment.mime); |  | ||||||
|             addNoIndexHeader(attachment.note, res); |  | ||||||
|             res.send(attachment.getContent()); |  | ||||||
|         } else { |  | ||||||
|             res.status(400).json({ message: "Requested attachment is not a shareable image" }); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     router.get("/share/api/attachments/:attachmentId/download", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         let attachment: SAttachment | boolean; |  | ||||||
|  |  | ||||||
|         if (!(attachment = checkAttachmentAccess(req.params.attachmentId, req, res))) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         addNoIndexHeader(attachment.note, res); |  | ||||||
|  |  | ||||||
|         const filename = utils.formatDownloadTitle(attachment.title, null, attachment.mime); |  | ||||||
|  |  | ||||||
|         res.setHeader("Content-Disposition", utils.getContentDisposition(filename)); |  | ||||||
|  |  | ||||||
|         res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); |  | ||||||
|         res.setHeader("Content-Type", attachment.mime); |  | ||||||
|  |  | ||||||
|         res.send(attachment.getContent()); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // used for PDF viewing |  | ||||||
|     router.get("/share/api/notes/:noteId/view", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         let note: SNote | boolean; |  | ||||||
|  |  | ||||||
|         if (!(note = checkNoteAccess(req.params.noteId, req, res))) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         addNoIndexHeader(note, res); |  | ||||||
|  |  | ||||||
|         res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); |  | ||||||
|         res.setHeader("Content-Type", note.mime); |  | ||||||
|  |  | ||||||
|         res.send(note.getContent()); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // Used for searching, require noteId so we know the subTreeRoot |  | ||||||
|     router.get("/share/api/notes", (req, res) => { |  | ||||||
|         shacaLoader.ensureLoad(); |  | ||||||
|  |  | ||||||
|         const ancestorNoteId = req.query.ancestorNoteId ?? "_share"; |  | ||||||
|  |  | ||||||
|         if (typeof ancestorNoteId !== "string") { |  | ||||||
|             res.status(400).json({ message: "'ancestorNoteId' parameter is mandatory." }); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // This will automatically return if no ancestorNoteId is provided and there is no shareIndex |  | ||||||
|         if (!checkNoteAccess(ancestorNoteId, req, res)) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         const { search } = req.query; |  | ||||||
|  |  | ||||||
|         if (typeof search !== "string" || !search?.trim()) { |  | ||||||
|             res.status(400).json({ message: "'search' parameter is mandatory." }); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         const searchContext = new SearchContext({ ancestorNoteId: ancestorNoteId }); |  | ||||||
|         const searchResults = searchService.findResultsWithQuery(search, searchContext); |  | ||||||
|         const filteredResults = searchResults.map((sr) => { |  | ||||||
|             const fullNote = shaca.notes[sr.noteId]; |  | ||||||
|             const startIndex = sr.notePathArray.indexOf(ancestorNoteId); |  | ||||||
|             const localPathArray = sr.notePathArray.slice(startIndex + 1).filter((id) => shaca.notes[id]); |  | ||||||
|             const pathTitle = localPathArray.map((id) => shaca.notes[id].title).join(" / "); |  | ||||||
|             return { id: fullNote.shareId, title: fullNote.title, score: sr.score, path: pathTitle }; |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         res.json({ results: filteredResults }); |  | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import utils from "../services/utils.js"; | import utils from "../services/utils.js"; | ||||||
| import BNote from "../becca/entities/bnote.js"; | import BNote from "../becca/entities/bnote.js"; | ||||||
| import BAttribute from "../becca/entities/battribute.js"; | import BAttribute from "../becca/entities/battribute.js"; | ||||||
|  | import BBranch from "../becca/entities/bbranch.js"; | ||||||
|  |  | ||||||
| type AttributeDefinitions = { [key in `#${string}`]: string; }; | type AttributeDefinitions = { [key in `#${string}`]: string; }; | ||||||
| type RelationDefinitions = { [key in `~${string}`]: string; }; | type RelationDefinitions = { [key in `~${string}`]: string; }; | ||||||
| @@ -9,6 +10,7 @@ interface NoteDefinition extends AttributeDefinitions, RelationDefinitions { | |||||||
|     id?: string | undefined; |     id?: string | undefined; | ||||||
|     title?: string; |     title?: string; | ||||||
|     content?: string; |     content?: string; | ||||||
|  |     children?: NoteDefinition[]; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -51,6 +53,18 @@ export function buildNote(noteDef: NoteDefinition) { | |||||||
|         note.getContent = () => noteDef.content!; |         note.getContent = () => noteDef.content!; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Handle children | ||||||
|  |     if (noteDef.children) { | ||||||
|  |         for (const childDef of noteDef.children) { | ||||||
|  |             const childNote = buildNote(childDef); | ||||||
|  |             new BBranch({ | ||||||
|  |                 noteId: childNote.noteId, | ||||||
|  |                 parentNoteId: note.noteId, | ||||||
|  |                 branchId: `${note.noteId}_${childNote.noteId}` | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Handle labels and relations. |     // Handle labels and relations. | ||||||
|     let position = 0; |     let position = 0; | ||||||
|     for (const [ key, value ] of Object.entries(noteDef)) { |     for (const [ key, value ] of Object.entries(noteDef)) { | ||||||
|   | |||||||
| @@ -27,6 +27,6 @@ export default defineConfig(() => ({ | |||||||
|       provider: 'v8' as const, |       provider: 'v8' as const, | ||||||
|       reporter: [ "text", "html" ] |       reporter: [ "text", "html" ] | ||||||
|     }, |     }, | ||||||
|     pool: "threads" |     pool: "vmForks" | ||||||
|   }, |   }, | ||||||
| })); | })); | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								docs/README-ro.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								docs/README-ro.md
									
									
									
									
										vendored
									
									
								
							| @@ -153,7 +153,7 @@ sugestii sau probleme aveți! | |||||||
|  |  | ||||||
| ## 🏗 Procesul de instalare | ## 🏗 Procesul de instalare | ||||||
|  |  | ||||||
| ### Windows / MacOS | ### Windows / macOS | ||||||
|  |  | ||||||
| Descărcați release-ul binar pentru platforma dvs. de pe pagina [ultimului | Descărcați release-ul binar pentru platforma dvs. de pe pagina [ultimului | ||||||
| release](https://github.com/TriliumNext/Trilium/releases/latest), dezarhivați și | release](https://github.com/TriliumNext/Trilium/releases/latest), dezarhivați și | ||||||
|   | |||||||
							
								
								
									
										26563
									
								
								docs/User Guide/!!!meta.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26563
									
								
								docs/User Guide/!!!meta.json
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -50,5 +50,6 @@ These relations are supported and used internally by Trilium. | |||||||
| | `widget_relation` | target of this relation will be executed and rendered as a widget in the sidebar | | | `widget_relation` | target of this relation will be executed and rendered as a widget in the sidebar | | ||||||
| | `shareCss` | CSS note which will be injected into the share page. CSS note must be in the shared sub-tree as well. Consider using `share_hidden_from_tree` and `share_omit_default_css` as well. | | | `shareCss` | CSS note which will be injected into the share page. CSS note must be in the shared sub-tree as well. Consider using `share_hidden_from_tree` and `share_omit_default_css` as well. | | ||||||
| | `shareJs` | JavaScript note which will be injected into the share page. JS note must be in the shared sub-tree as well. Consider using `share_hidden_from_tree`. | | | `shareJs` | JavaScript note which will be injected into the share page. JS note must be in the shared sub-tree as well. Consider using `share_hidden_from_tree`. | | ||||||
|  | | `shareHtml` | HTML note which will be injected into the share page at locations specified by the `shareHtmlLocation` label. HTML note must be in the shared sub-tree as well. Consider using `share_hidden_from_tree`. | | ||||||
| | `shareTemplate` | Embedded JavaScript note that will be used as the template for displaying the shared note. Falls back to the default template. Consider using `share_hidden_from_tree`. | | | `shareTemplate` | Embedded JavaScript note that will be used as the template for displaying the shared note. Falls back to the default template. Consider using `share_hidden_from_tree`. | | ||||||
| | `shareFavicon` | Favicon note to be set in the shared page. Typically you want to set it to share root and make it inheritable. Favicon note must be in the shared sub-tree as well. Consider using `share_hidden_from_tree`. | | | `shareFavicon` | Favicon note to be set in the shared page. Typically you want to set it to share root and make it inheritable. Favicon note must be in the shared sub-tree as well. Consider using `share_hidden_from_tree`. | | ||||||
| @@ -67,6 +67,25 @@ The default design should be a good starting point, but you can customize it usi | |||||||
|  |  | ||||||
| You can inject custom JavaScript into the shared note using the `~shareJs` relation. This allows you to access note attributes or traverse the note tree using the `fetchNote()` API, which retrieves note data based on its ID. | You can inject custom JavaScript into the shared note using the `~shareJs` relation. This allows you to access note attributes or traverse the note tree using the `fetchNote()` API, which retrieves note data based on its ID. | ||||||
|  |  | ||||||
|  | ### Adding custom HTML | ||||||
|  |  | ||||||
|  | You can inject custom HTML snippets into specific locations of the shared page using the `~shareHtml` relation. The HTML note should contain the raw HTML content you want to inject, and you can control where it appears by adding the `#shareHtmlLocation` label to the HTML snippet note itself. | ||||||
|  |  | ||||||
|  | The `#shareHtmlLocation` label accepts values in the format `location:position`: | ||||||
|  |  | ||||||
|  | *   **Locations**: `head`, `body`, `content` | ||||||
|  | *   **Positions**: `start`, `end` | ||||||
|  |  | ||||||
|  | For example: | ||||||
|  |  | ||||||
|  | *   `#shareHtmlLocation=head:start` - Injects HTML at the beginning of the `<head>` section | ||||||
|  | *   `#shareHtmlLocation=head:end` - Injects HTML at the end of the `<head>` section (default) | ||||||
|  | *   `#shareHtmlLocation=body:start` - Injects HTML at the beginning of the `<body>` section | ||||||
|  | *   `#shareHtmlLocation=content:start` - Injects HTML at the beginning of the content area | ||||||
|  | *   `#shareHtmlLocation=content:end` - Injects HTML at the end of the content area | ||||||
|  |  | ||||||
|  | If no location is specified, the HTML will be injected at `content:end` by default. | ||||||
|  |  | ||||||
| Example: | Example: | ||||||
|  |  | ||||||
| ```javascript | ```javascript | ||||||
| @@ -104,9 +123,19 @@ When accessing a share, the sub-notes will be displayed in a tree on the left. B | |||||||
|  |  | ||||||
| To do so, create a shared text note and apply the `shareIndex` label. When viewed, the list of shared roots will be displayed at the bottom of the note. | To do so, create a shared text note and apply the `shareIndex` label. When viewed, the list of shared roots will be displayed at the bottom of the note. | ||||||
|  |  | ||||||
|  | ### Redirect Bare Domain to Share Page | ||||||
|  |  | ||||||
|  | This option can be enabled under `Option → Other → Share Settings`. When activated, anonymous users accessing the bare domain will be redirected to the Share page, preventing them from seeing the login option and thereby improving security.   | ||||||
|  | To ensure accessibility for legitimate users, you can also enable a login link on the Share page, allowing yourself to access the login screen if you're redirected there. | ||||||
|  |  | ||||||
|  | ### Setting a Custom Share Path | ||||||
|  |  | ||||||
|  | This option can be enabled under `Option → Other → Share Settings`. It allows you to customize the share URL prefix before the `noteId`. Nested paths are supported.   | ||||||
|  | If you're using a proxy service, make sure to update its configuration accordingly to reflect the new path structure. | ||||||
|  |  | ||||||
| ## Attribute reference | ## Attribute reference | ||||||
|  |  | ||||||
| <table><thead><tr><th>Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>shareHiddenFromTree</code></td><td>this note is hidden from left navigation tree, but still accessible with its URL</td></tr><tr><td><code>shareExternalLink</code></td><td>note will act as a link to an external website in the share tree</td></tr><tr><td><code>shareAlias</code></td><td>define an alias using which the note will be available under <code>https://your_trilium_host/share/[your_alias]</code></td></tr><tr><td><code>shareOmitDefaultCss</code></td><td>default share page CSS will be omitted. Use when you make extensive styling changes.</td></tr><tr><td><code>shareRoot</code></td><td>marks note which is served on /share root.</td></tr><tr><td><code>shareDescription</code></td><td>define text to be added to the HTML meta tag for description</td></tr><tr><td><code>shareRaw</code></td><td>Note will be served in its raw format, without HTML wrapper. See also <a class="reference-link" href="Sharing/Serving%20directly%20the%20content%20o.md">Serving directly the content of a note</a> for an alternative method without setting an attribute.</td></tr><tr><td><code>shareDisallowRobotIndexing</code></td><td><p>Indicates to web crawlers that the page should not be indexed of this note by:</p><ul><li data-list-item-id="e6baa9f60bf59d085fd31aa2cce07a0e7">Setting the <code>X-Robots-Tag: noindex</code> HTTP header.</li><li data-list-item-id="ec0d067db136ef9794e4f1033405880b7">Setting the <code>noindex, follow</code> meta tag.</li></ul></td></tr><tr><td><code>shareCredentials</code></td><td>require credentials to access this shared note. Value is expected to be in format <code>username:password</code>. Don't forget to make this inheritable to apply to child-notes/images.</td></tr><tr><td><code>shareIndex</code></td><td>Note with this label will list all roots of shared notes.</td></tr></tbody></table> | <table><thead><tr><th>Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>shareHiddenFromTree</code></td><td>this note is hidden from left navigation tree, but still accessible with its URL</td></tr><tr><td><code>shareExternalLink</code></td><td>note will act as a link to an external website in the share tree</td></tr><tr><td><code>shareAlias</code></td><td>define an alias using which the note will be available under <code>https://your_trilium_host/share/[your_alias]</code></td></tr><tr><td><code>shareOmitDefaultCss</code></td><td>default share page CSS will be omitted. Use when you make extensive styling changes.</td></tr><tr><td><code>shareRoot</code></td><td>marks note which is served on /share root.</td></tr><tr><td><code>shareDescription</code></td><td>define text to be added to the HTML meta tag for description</td></tr><tr><td><code>shareRaw</code></td><td>Note will be served in its raw format, without HTML wrapper. See also <a class="reference-link" href="Sharing/Serving%20directly%20the%20content%20o.md">Serving directly the content of a note</a> for an alternative method without setting an attribute.</td></tr><tr><td><code>shareDisallowRobotIndexing</code></td><td><p>Indicates to web crawlers that the page should not be indexed of this note by:</p><ul><li data-list-item-id="e6baa9f60bf59d085fd31aa2cce07a0e7">Setting the <code>X-Robots-Tag: noindex</code> HTTP header.</li><li data-list-item-id="ec0d067db136ef9794e4f1033405880b7">Setting the <code>noindex, follow</code> meta tag.</li></ul></td></tr><tr><td><code>shareCredentials</code></td><td>require credentials to access this shared note. Value is expected to be in format <code>username:password</code>. Don't forget to make this inheritable to apply to child-notes/images.</td></tr><tr><td><code>shareIndex</code></td><td>Note with this label will list all roots of shared notes.</td></tr><tr><td><code>shareHtmlLocation</code></td><td>defines where custom HTML injected via <code>~shareHtml</code> relation should be placed. Applied to the HTML snippet note itself. Format: <code>location:position</code> where location is <code>head</code>, <code>body</code>, or <code>content</code> and position is <code>start</code> or <code>end</code>. Defaults to <code>content:end</code>.</td></tr></tbody></table> | ||||||
|  |  | ||||||
| ## Credits | ## Credits | ||||||
|  |  | ||||||
|   | |||||||
| @@ -200,7 +200,7 @@ | |||||||
|           # '/build/source/apps/desktop/node_modules/better-sqlite3/build/node_gyp_bins' |           # '/build/source/apps/desktop/node_modules/better-sqlite3/build/node_gyp_bins' | ||||||
|           preBuildCommands = '' |           preBuildCommands = '' | ||||||
|             export npm_config_nodedir=${electron.headers} |             export npm_config_nodedir=${electron.headers} | ||||||
|             pnpm postinstall || true |             pnpm postinstall | ||||||
|           ''; |           ''; | ||||||
|           buildTask = "desktop:build"; |           buildTask = "desktop:build"; | ||||||
|           mainProgram = "trilium"; |           mainProgram = "trilium"; | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ | |||||||
|   "private": true, |   "private": true, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@electron/rebuild": "4.0.1", |     "@electron/rebuild": "4.0.1", | ||||||
|     "@playwright/test": "1.55.1", |     "@playwright/test": "1.56.0", | ||||||
|     "@triliumnext/server": "workspace:*", |     "@triliumnext/server": "workspace:*", | ||||||
|     "@types/express": "5.0.3", |     "@types/express": "5.0.3", | ||||||
|     "@types/node": "22.18.8", |     "@types/node": "22.18.8", | ||||||
| @@ -59,7 +59,7 @@ | |||||||
|     "tslib": "2.8.1", |     "tslib": "2.8.1", | ||||||
|     "tsx": "4.20.6", |     "tsx": "4.20.6", | ||||||
|     "typescript": "~5.9.0", |     "typescript": "~5.9.0", | ||||||
|     "typescript-eslint": "8.45.0", |     "typescript-eslint": "8.46.0", | ||||||
|     "upath": "2.0.1", |     "upath": "2.0.1", | ||||||
|     "vite": "7.1.9", |     "vite": "7.1.9", | ||||||
|     "vite-plugin-dts": "~4.5.0", |     "vite-plugin-dts": "~4.5.0", | ||||||
| @@ -79,7 +79,7 @@ | |||||||
|     "url": "https://github.com/TriliumNext/Trilium/issues" |     "url": "https://github.com/TriliumNext/Trilium/issues" | ||||||
|   }, |   }, | ||||||
|   "homepage": "https://triliumnotes.org", |   "homepage": "https://triliumnotes.org", | ||||||
|   "packageManager": "pnpm@10.18.0", |   "packageManager": "pnpm@10.18.1", | ||||||
|   "pnpm": { |   "pnpm": { | ||||||
|     "patchedDependencies": { |     "patchedDependencies": { | ||||||
|       "@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch", |       "@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch", | ||||||
| @@ -90,7 +90,7 @@ | |||||||
|       "mermaid": "11.12.0", |       "mermaid": "11.12.0", | ||||||
|       "preact": "10.27.2", |       "preact": "10.27.2", | ||||||
|       "roughjs": "4.6.6", |       "roughjs": "4.6.6", | ||||||
|       "@types/express-serve-static-core": "5.0.7", |       "@types/express-serve-static-core": "5.1.0", | ||||||
|       "flat@<5.0.1": ">=5.0.1", |       "flat@<5.0.1": ">=5.0.1", | ||||||
|       "debug@>=3.2.0 <3.2.7": ">=3.2.7", |       "debug@>=3.2.0 <3.2.7": ">=3.2.7", | ||||||
|       "nanoid@<3.3.8": ">=3.3.8", |       "nanoid@<3.3.8": ">=3.3.8", | ||||||
|   | |||||||
| @@ -24,8 +24,8 @@ | |||||||
|     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", |     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", | ||||||
|     "@ckeditor/ckeditor5-inspector": ">=4.1.0", |     "@ckeditor/ckeditor5-inspector": ">=4.1.0", | ||||||
|     "@ckeditor/ckeditor5-package-tools": "4.1.0", |     "@ckeditor/ckeditor5-package-tools": "4.1.0", | ||||||
|     "@typescript-eslint/eslint-plugin": "~8.45.0", |     "@typescript-eslint/eslint-plugin": "~8.46.0", | ||||||
|     "@typescript-eslint/parser": "8.45.0", |     "@typescript-eslint/parser": "8.46.0", | ||||||
|     "@vitest/browser": "3.2.4", |     "@vitest/browser": "3.2.4", | ||||||
|     "@vitest/coverage-istanbul": "3.2.4", |     "@vitest/coverage-istanbul": "3.2.4", | ||||||
|     "ckeditor5": "47.0.0", |     "ckeditor5": "47.0.0", | ||||||
|   | |||||||
| @@ -25,8 +25,8 @@ | |||||||
|     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", |     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", | ||||||
|     "@ckeditor/ckeditor5-inspector": ">=4.1.0", |     "@ckeditor/ckeditor5-inspector": ">=4.1.0", | ||||||
|     "@ckeditor/ckeditor5-package-tools": "4.1.0", |     "@ckeditor/ckeditor5-package-tools": "4.1.0", | ||||||
|     "@typescript-eslint/eslint-plugin": "~8.45.0", |     "@typescript-eslint/eslint-plugin": "~8.46.0", | ||||||
|     "@typescript-eslint/parser": "8.45.0", |     "@typescript-eslint/parser": "8.46.0", | ||||||
|     "@vitest/browser": "3.2.4", |     "@vitest/browser": "3.2.4", | ||||||
|     "@vitest/coverage-istanbul": "3.2.4", |     "@vitest/coverage-istanbul": "3.2.4", | ||||||
|     "ckeditor5": "47.0.0", |     "ckeditor5": "47.0.0", | ||||||
|   | |||||||
| @@ -27,8 +27,8 @@ | |||||||
|     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", |     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", | ||||||
|     "@ckeditor/ckeditor5-inspector": ">=4.1.0", |     "@ckeditor/ckeditor5-inspector": ">=4.1.0", | ||||||
|     "@ckeditor/ckeditor5-package-tools": "4.1.0", |     "@ckeditor/ckeditor5-package-tools": "4.1.0", | ||||||
|     "@typescript-eslint/eslint-plugin": "~8.45.0", |     "@typescript-eslint/eslint-plugin": "~8.46.0", | ||||||
|     "@typescript-eslint/parser": "8.45.0", |     "@typescript-eslint/parser": "8.46.0", | ||||||
|     "@vitest/browser": "3.2.4", |     "@vitest/browser": "3.2.4", | ||||||
|     "@vitest/coverage-istanbul": "3.2.4", |     "@vitest/coverage-istanbul": "3.2.4", | ||||||
|     "ckeditor5": "47.0.0", |     "ckeditor5": "47.0.0", | ||||||
|   | |||||||
| @@ -28,8 +28,8 @@ | |||||||
|     "@ckeditor/ckeditor5-dev-utils": "43.1.0", |     "@ckeditor/ckeditor5-dev-utils": "43.1.0", | ||||||
|     "@ckeditor/ckeditor5-inspector": ">=4.1.0", |     "@ckeditor/ckeditor5-inspector": ">=4.1.0", | ||||||
|     "@ckeditor/ckeditor5-package-tools": "4.1.0", |     "@ckeditor/ckeditor5-package-tools": "4.1.0", | ||||||
|     "@typescript-eslint/eslint-plugin": "~8.45.0", |     "@typescript-eslint/eslint-plugin": "~8.46.0", | ||||||
|     "@typescript-eslint/parser": "8.45.0", |     "@typescript-eslint/parser": "8.46.0", | ||||||
|     "@vitest/browser": "3.2.4", |     "@vitest/browser": "3.2.4", | ||||||
|     "@vitest/coverage-istanbul": "3.2.4", |     "@vitest/coverage-istanbul": "3.2.4", | ||||||
|     "ckeditor5": "47.0.0", |     "ckeditor5": "47.0.0", | ||||||
|   | |||||||
| @@ -30,7 +30,12 @@ export default class MathCommand extends Command { | |||||||
|  |  | ||||||
| 				mathtex = writer.createElement( | 				mathtex = writer.createElement( | ||||||
| 					display ? 'mathtex-display' : 'mathtex-inline', | 					display ? 'mathtex-display' : 'mathtex-inline', | ||||||
| 					{ equation, type, display } | 					{ | ||||||
|  | 						...Object.fromEntries(selection.getAttributes()), | ||||||
|  | 						equation, | ||||||
|  | 						type, | ||||||
|  | 						display | ||||||
|  | 					} | ||||||
| 				); | 				); | ||||||
| 			} else { | 			} else { | ||||||
| 				const selection = this.editor.model.document.selection; | 				const selection = this.editor.model.document.selection; | ||||||
| @@ -40,7 +45,7 @@ export default class MathCommand extends Command { | |||||||
| 					display ? 'mathtex-display' : 'mathtex-inline', | 					display ? 'mathtex-display' : 'mathtex-inline', | ||||||
| 					{ | 					{ | ||||||
| 						// Inherit all attributes from selection (e.g. color, background color, size). | 						// Inherit all attributes from selection (e.g. color, background color, size). | ||||||
| 						...Object.fromEntries( selection.getAttributes() ), | 						...Object.fromEntries(selection.getAttributes()), | ||||||
| 						equation, | 						equation, | ||||||
| 						type: outputType, | 						type: outputType, | ||||||
| 						display, | 						display, | ||||||
|   | |||||||
| @@ -27,8 +27,8 @@ | |||||||
|     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", |     "@ckeditor/ckeditor5-dev-build-tools": "43.1.0", | ||||||
|     "@ckeditor/ckeditor5-inspector": ">=4.1.0", |     "@ckeditor/ckeditor5-inspector": ">=4.1.0", | ||||||
|     "@ckeditor/ckeditor5-package-tools": "4.1.0", |     "@ckeditor/ckeditor5-package-tools": "4.1.0", | ||||||
|     "@typescript-eslint/eslint-plugin": "~8.45.0", |     "@typescript-eslint/eslint-plugin": "~8.46.0", | ||||||
|     "@typescript-eslint/parser": "8.45.0", |     "@typescript-eslint/parser": "8.46.0", | ||||||
|     "@vitest/browser": "3.2.4", |     "@vitest/browser": "3.2.4", | ||||||
|     "@vitest/coverage-istanbul": "3.2.4", |     "@vitest/coverage-istanbul": "3.2.4", | ||||||
|     "ckeditor5": "47.0.0", |     "ckeditor5": "47.0.0", | ||||||
|   | |||||||
| @@ -49,4 +49,9 @@ export interface HiddenSubtreeItem { | |||||||
|      * the user moves it around. |      * the user moves it around. | ||||||
|      */ |      */ | ||||||
|     enforceBranches?: boolean; |     enforceBranches?: boolean; | ||||||
|  |     /** | ||||||
|  |      * If set to true, then the attributes of this note will be checked. Any owned attribute that does not match the | ||||||
|  |      * definitions will be removed. | ||||||
|  |      */ | ||||||
|  |     enforceAttributes?: boolean; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -135,6 +135,8 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions<KeyboardActi | |||||||
|     // Share settings |     // Share settings | ||||||
|     redirectBareDomain: boolean; |     redirectBareDomain: boolean; | ||||||
|     showLoginInShareTheme: boolean; |     showLoginInShareTheme: boolean; | ||||||
|  |     shareSubtree: boolean; | ||||||
|  |     sharePath: string; | ||||||
|  |  | ||||||
|     // AI/LLM integration options |     // AI/LLM integration options | ||||||
|     aiEnabled: boolean; |     aiEnabled: boolean; | ||||||
|   | |||||||
| @@ -1,98 +1,22 @@ | |||||||
| // Default list of allowed HTML tags | // Default list of allowed HTML tags | ||||||
| export const SANITIZER_DEFAULT_ALLOWED_TAGS = [ | export const SANITIZER_DEFAULT_ALLOWED_TAGS = [ | ||||||
|     "h1", |     "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "p", "a", "ul", "ol", "li", "b", "i", "strong", "em", | ||||||
|     "h2", |     "strike", "s", "del", "abbr", "code", "hr", "br", "div", "table", "thead", "caption", "tbody", "tfoot", | ||||||
|     "h3", |     "tr", "th", "td", "pre", "section", "img", "figure", "figcaption", "span", "label", "input", "details", | ||||||
|     "h4", |     "summary", "address", "aside", "footer", "header", "hgroup", "main", "nav", "dl", "dt", "menu", "bdi", | ||||||
|     "h5", |     "bdo", "dfn", "kbd", "mark", "q", "time", "var", "wbr", "area", "map", "track", "video", "audio", "picture", | ||||||
|     "h6", |     "del", "ins", | ||||||
|     "blockquote", |     // for ENEX import | ||||||
|     "p", |     "en-media", | ||||||
|     "a", |  | ||||||
|     "ul", |  | ||||||
|     "ol", |  | ||||||
|     "li", |  | ||||||
|     "b", |  | ||||||
|     "i", |  | ||||||
|     "strong", |  | ||||||
|     "em", |  | ||||||
|     "strike", |  | ||||||
|     "s", |  | ||||||
|     "del", |  | ||||||
|     "abbr", |  | ||||||
|     "code", |  | ||||||
|     "hr", |  | ||||||
|     "br", |  | ||||||
|     "div", |  | ||||||
|     "table", |  | ||||||
|     "thead", |  | ||||||
|     "caption", |  | ||||||
|     "tbody", |  | ||||||
|     "tfoot", |  | ||||||
|     "tr", |  | ||||||
|     "th", |  | ||||||
|     "td", |  | ||||||
|     "pre", |  | ||||||
|     "section", |  | ||||||
|     "img", |  | ||||||
|     "figure", |  | ||||||
|     "figcaption", |  | ||||||
|     "span", |  | ||||||
|     "label", |  | ||||||
|     "input", |  | ||||||
|     "details", |  | ||||||
|     "summary", |  | ||||||
|     "address", |  | ||||||
|     "aside", |  | ||||||
|     "footer", |  | ||||||
|     "header", |  | ||||||
|     "hgroup", |  | ||||||
|     "main", |  | ||||||
|     "nav", |  | ||||||
|     "dl", |  | ||||||
|     "dt", |  | ||||||
|     "menu", |  | ||||||
|     "bdi", |  | ||||||
|     "bdo", |  | ||||||
|     "dfn", |  | ||||||
|     "kbd", |  | ||||||
|     "mark", |  | ||||||
|     "q", |  | ||||||
|     "time", |  | ||||||
|     "var", |  | ||||||
|     "wbr", |  | ||||||
|     "area", |  | ||||||
|     "map", |  | ||||||
|     "track", |  | ||||||
|     "video", |  | ||||||
|     "audio", |  | ||||||
|     "picture", |  | ||||||
|     "del", |  | ||||||
|     "ins", |  | ||||||
|     "en-media", // for ENEX import |  | ||||||
|     // Additional tags (https://github.com/TriliumNext/Trilium/issues/567) |     // Additional tags (https://github.com/TriliumNext/Trilium/issues/567) | ||||||
|     "acronym", |     "acronym", "article", "big", "button", "cite", "col", "colgroup", "data", "dd", "fieldset", "form", "legend", | ||||||
|     "article", |     "meter", "noscript", "option", "progress", "rp", "samp", "small", "sub", "sup", "template", "textarea", "tt" | ||||||
|     "big", |  | ||||||
|     "button", |  | ||||||
|     "cite", |  | ||||||
|     "col", |  | ||||||
|     "colgroup", |  | ||||||
|     "data", |  | ||||||
|     "dd", |  | ||||||
|     "fieldset", |  | ||||||
|     "form", |  | ||||||
|     "legend", |  | ||||||
|     "meter", |  | ||||||
|     "noscript", |  | ||||||
|     "option", |  | ||||||
|     "progress", |  | ||||||
|     "rp", |  | ||||||
|     "samp", |  | ||||||
|     "small", |  | ||||||
|     "sub", |  | ||||||
|     "sup", |  | ||||||
|     "template", |  | ||||||
|     "textarea", |  | ||||||
|     "tt" |  | ||||||
| ] as const; | ] as const; | ||||||
|  |  | ||||||
|  | export const ALLOWED_PROTOCOLS = [ | ||||||
|  |     'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git', | ||||||
|  |     'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message', | ||||||
|  |     'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp', | ||||||
|  |     'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo', | ||||||
|  |     'mid', 'obsidian' | ||||||
|  | ]; | ||||||
|   | |||||||
| @@ -24,8 +24,8 @@ | |||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@digitak/esrun": "3.2.26", |     "@digitak/esrun": "3.2.26", | ||||||
|     "@types/swagger-ui": "5.21.1", |     "@types/swagger-ui": "5.21.1", | ||||||
|     "@typescript-eslint/eslint-plugin": "8.45.0", |     "@typescript-eslint/eslint-plugin": "8.46.0", | ||||||
|     "@typescript-eslint/parser": "8.45.0", |     "@typescript-eslint/parser": "8.46.0", | ||||||
|     "dotenv": "17.2.3", |     "dotenv": "17.2.3", | ||||||
|     "esbuild": "0.25.10", |     "esbuild": "0.25.10", | ||||||
|     "eslint": "9.37.0", |     "eslint": "9.37.0", | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| <html lang="en"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
|     <meta charset="utf-8"> |     <meta charset="utf-8"> | ||||||
|     <link rel="shortcut icon" href="../favicon.ico"> |     <link rel="shortcut icon" href="<%= relativePath %>favicon.ico"> | ||||||
|     <title><%= t("share_404.title") %></title> |     <title><%= t("share_404.title") %></title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|   | |||||||
| @@ -1,7 +1,31 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
|     <% const hasTree = subRoot.note.hasVisibleChildren(); %> |     <% | ||||||
|  |     const hasTree = subRoot.note.hasVisibleChildren(); | ||||||
|  |  | ||||||
|  |     // Collect HTML snippets by location | ||||||
|  |     const htmlSnippetsByLocation = {}; | ||||||
|  |     for (const htmlRelation of note.getRelations("shareHtml")) { | ||||||
|  |         const htmlNote = htmlRelation.targetNote; | ||||||
|  |         if (htmlNote) { | ||||||
|  |             let location = htmlNote.getLabelValue("shareHtmlLocation") || "content:end"; | ||||||
|  |             // Default to :end if no position specified | ||||||
|  |             if (!location.includes(":")) { | ||||||
|  |                 location = location + ":end"; | ||||||
|  |             } | ||||||
|  |             if (!htmlSnippetsByLocation[location]) { | ||||||
|  |                 htmlSnippetsByLocation[location] = []; | ||||||
|  |             } | ||||||
|  |             htmlSnippetsByLocation[location].push(htmlNote.getContent()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     const renderSnippets = (location) => { | ||||||
|  |         const snippets = htmlSnippetsByLocation[location]; | ||||||
|  |         return snippets ? snippets.join("\n") : ""; | ||||||
|  |     }; | ||||||
|  |     %> | ||||||
|  |     <%- renderSnippets("head:start") %> | ||||||
|     <meta charset="utf-8"> |     <meta charset="utf-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"> |     <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||||
|  |  | ||||||
| @@ -53,10 +77,11 @@ | |||||||
|     <meta name="twitter:image" content="<%= openGraphImage %>"> |     <meta name="twitter:image" content="<%= openGraphImage %>"> | ||||||
|     <!-- Meta Tags Generated via https://opengraph.dev --> |     <!-- Meta Tags Generated via https://opengraph.dev --> | ||||||
|     <meta name="theme-color" content="<%= openGraphColor %>"> |     <meta name="theme-color" content="<%= openGraphColor %>"> | ||||||
|  |     <%- renderSnippets("head:end") %> | ||||||
| </head> | </head> | ||||||
| <% | <% | ||||||
| const customLogoId = subRoot.note.getRelation("shareLogo")?.value; | const customLogoId = subRoot.note.getRelation("shareLogo")?.value; | ||||||
| const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png` : `../${assetUrlFragment}/images/icon-color.svg`; | const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png` : `${relativePath}${assetUrlFragment}/images/icon-color.svg`; | ||||||
| const logoWidth = subRoot.note.getLabelValue("shareLogoWidth") ?? 53; | const logoWidth = subRoot.note.getLabelValue("shareLogoWidth") ?? 53; | ||||||
| const logoHeight = subRoot.note.getLabelValue("shareLogoHeight") ?? 40; | const logoHeight = subRoot.note.getLabelValue("shareLogoHeight") ?? 40; | ||||||
| const mobileLogoHeight = logoHeight && logoWidth ? 32 / (logoWidth / logoHeight) : ""; | const mobileLogoHeight = logoHeight && logoWidth ? 32 / (logoWidth / logoHeight) : ""; | ||||||
| @@ -72,6 +97,7 @@ content = content.replaceAll(headingRe, (...match) => { | |||||||
| }); | }); | ||||||
| %> | %> | ||||||
| <body data-note-id="<%= note.noteId %>" class="type-<%= note.type %><%= themeClass %>" data-ancestor-note-id="<%= subRoot.note.noteId %>"> | <body data-note-id="<%= note.noteId %>" class="type-<%= note.type %><%= themeClass %>" data-ancestor-note-id="<%= subRoot.note.noteId %>"> | ||||||
|  | <%- renderSnippets("body:start") %> | ||||||
| <div id="mobile-header"> | <div id="mobile-header"> | ||||||
|     <a href="<%= shareRootLink %>"> |     <a href="<%= shareRootLink %>"> | ||||||
|             <img src="<%= logoUrl %>" width="32" height="<%= mobileLogoHeight %>" alt="Logo" /> |             <img src="<%= logoUrl %>" width="32" height="<%= mobileLogoHeight %>" alt="Logo" /> | ||||||
| @@ -121,8 +147,8 @@ content = content.replaceAll(headingRe, (...match) => { | |||||||
|     </div> |     </div> | ||||||
|     <div id="right-pane"> |     <div id="right-pane"> | ||||||
|         <div id="main"> |         <div id="main"> | ||||||
|  |  | ||||||
|             <div id="content" class="type-<%= note.type %><% if (note.type === "text") { %> ck-content<% } %><% if (isEmpty) { %> no-content<% } %>"> |             <div id="content" class="type-<%= note.type %><% if (note.type === "text") { %> ck-content<% } %><% if (isEmpty) { %> no-content<% } %>"> | ||||||
|  |                 <%- renderSnippets("content:start") %> | ||||||
|                     <h1 id="title"><%= note.title %></h1> |                     <h1 id="title"><%= note.title %></h1> | ||||||
|                 <% if (isEmpty && (!note.hasVisibleChildren() && note.type !== "book")) { %> |                 <% if (isEmpty && (!note.hasVisibleChildren() && note.type !== "book")) { %> | ||||||
|                     <p>This note has no content.</p> |                     <p>This note has no content.</p> | ||||||
| @@ -132,6 +158,7 @@ content = content.replaceAll(headingRe, (...match) => { | |||||||
|                     %> |                     %> | ||||||
|                     <%- content %> |                     <%- content %> | ||||||
|                 <% } %> |                 <% } %> | ||||||
|  |                 <%- renderSnippets("content:end") %> | ||||||
|             </div> |             </div> | ||||||
|  |  | ||||||
|             <% if (note.hasVisibleChildren() || note.type === "book") { %> |             <% if (note.hasVisibleChildren() || note.type === "book") { %> | ||||||
| @@ -205,5 +232,6 @@ content = content.replaceAll(headingRe, (...match) => { | |||||||
|         <% } %> |         <% } %> | ||||||
|     </div> |     </div> | ||||||
| </div> | </div> | ||||||
|  | <%- renderSnippets("body:end") %> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
							
								
								
									
										260
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										260
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @@ -8,7 +8,7 @@ overrides: | |||||||
|   mermaid: 11.12.0 |   mermaid: 11.12.0 | ||||||
|   preact: 10.27.2 |   preact: 10.27.2 | ||||||
|   roughjs: 4.6.6 |   roughjs: 4.6.6 | ||||||
|   '@types/express-serve-static-core': 5.0.7 |   '@types/express-serve-static-core': 5.1.0 | ||||||
|   flat@<5.0.1: '>=5.0.1' |   flat@<5.0.1: '>=5.0.1' | ||||||
|   debug@>=3.2.0 <3.2.7: '>=3.2.7' |   debug@>=3.2.0 <3.2.7: '>=3.2.7' | ||||||
|   nanoid@<3.3.8: '>=3.3.8' |   nanoid@<3.3.8: '>=3.3.8' | ||||||
| @@ -41,8 +41,8 @@ importers: | |||||||
|         specifier: 4.0.1 |         specifier: 4.0.1 | ||||||
|         version: 4.0.1 |         version: 4.0.1 | ||||||
|       '@playwright/test': |       '@playwright/test': | ||||||
|         specifier: 1.55.1 |         specifier: 1.56.0 | ||||||
|         version: 1.55.1 |         version: 1.56.0 | ||||||
|       '@triliumnext/server': |       '@triliumnext/server': | ||||||
|         specifier: workspace:* |         specifier: workspace:* | ||||||
|         version: link:apps/server |         version: link:apps/server | ||||||
| @@ -107,8 +107,8 @@ importers: | |||||||
|         specifier: ~5.9.0 |         specifier: ~5.9.0 | ||||||
|         version: 5.9.3 |         version: 5.9.3 | ||||||
|       typescript-eslint: |       typescript-eslint: | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       upath: |       upath: | ||||||
|         specifier: 2.0.1 |         specifier: 2.0.1 | ||||||
|         version: 2.0.1 |         version: 2.0.1 | ||||||
| @@ -694,8 +694,8 @@ importers: | |||||||
|         specifier: 0.6.0 |         specifier: 0.6.0 | ||||||
|         version: 0.6.0 |         version: 0.6.0 | ||||||
|       openai: |       openai: | ||||||
|         specifier: 6.1.0 |         specifier: 6.2.0 | ||||||
|         version: 6.1.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))(zod@3.24.4) |         version: 6.2.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))(zod@3.24.4) | ||||||
|       rand-token: |       rand-token: | ||||||
|         specifier: 1.0.1 |         specifier: 1.0.1 | ||||||
|         version: 1.0.1 |         version: 1.0.1 | ||||||
| @@ -837,14 +837,14 @@ importers: | |||||||
|         specifier: 4.1.0 |         specifier: 4.1.0 | ||||||
|         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) |         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) | ||||||
|       '@typescript-eslint/eslint-plugin': |       '@typescript-eslint/eslint-plugin': | ||||||
|         specifier: ~8.45.0 |         specifier: ~8.46.0 | ||||||
|         version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/parser': |       '@typescript-eslint/parser': | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@vitest/browser': |       '@vitest/browser': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) |         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||||
|       '@vitest/coverage-istanbul': |       '@vitest/coverage-istanbul': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(vitest@3.2.4) |         version: 3.2.4(vitest@3.2.4) | ||||||
| @@ -897,14 +897,14 @@ importers: | |||||||
|         specifier: 4.1.0 |         specifier: 4.1.0 | ||||||
|         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) |         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) | ||||||
|       '@typescript-eslint/eslint-plugin': |       '@typescript-eslint/eslint-plugin': | ||||||
|         specifier: ~8.45.0 |         specifier: ~8.46.0 | ||||||
|         version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/parser': |       '@typescript-eslint/parser': | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@vitest/browser': |       '@vitest/browser': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) |         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||||
|       '@vitest/coverage-istanbul': |       '@vitest/coverage-istanbul': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(vitest@3.2.4) |         version: 3.2.4(vitest@3.2.4) | ||||||
| @@ -957,14 +957,14 @@ importers: | |||||||
|         specifier: 4.1.0 |         specifier: 4.1.0 | ||||||
|         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) |         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) | ||||||
|       '@typescript-eslint/eslint-plugin': |       '@typescript-eslint/eslint-plugin': | ||||||
|         specifier: ~8.45.0 |         specifier: ~8.46.0 | ||||||
|         version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/parser': |       '@typescript-eslint/parser': | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@vitest/browser': |       '@vitest/browser': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) |         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||||
|       '@vitest/coverage-istanbul': |       '@vitest/coverage-istanbul': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(vitest@3.2.4) |         version: 3.2.4(vitest@3.2.4) | ||||||
| @@ -1024,14 +1024,14 @@ importers: | |||||||
|         specifier: 4.1.0 |         specifier: 4.1.0 | ||||||
|         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) |         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) | ||||||
|       '@typescript-eslint/eslint-plugin': |       '@typescript-eslint/eslint-plugin': | ||||||
|         specifier: ~8.45.0 |         specifier: ~8.46.0 | ||||||
|         version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/parser': |       '@typescript-eslint/parser': | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@vitest/browser': |       '@vitest/browser': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) |         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||||
|       '@vitest/coverage-istanbul': |       '@vitest/coverage-istanbul': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(vitest@3.2.4) |         version: 3.2.4(vitest@3.2.4) | ||||||
| @@ -1091,14 +1091,14 @@ importers: | |||||||
|         specifier: 4.1.0 |         specifier: 4.1.0 | ||||||
|         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) |         version: 4.1.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.8)(bufferutil@4.0.9)(esbuild@0.25.10)(utf-8-validate@6.0.5) | ||||||
|       '@typescript-eslint/eslint-plugin': |       '@typescript-eslint/eslint-plugin': | ||||||
|         specifier: ~8.45.0 |         specifier: ~8.46.0 | ||||||
|         version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/parser': |       '@typescript-eslint/parser': | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@vitest/browser': |       '@vitest/browser': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) |         version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||||
|       '@vitest/coverage-istanbul': |       '@vitest/coverage-istanbul': | ||||||
|         specifier: 3.2.4 |         specifier: 3.2.4 | ||||||
|         version: 3.2.4(vitest@3.2.4) |         version: 3.2.4(vitest@3.2.4) | ||||||
| @@ -1315,11 +1315,11 @@ importers: | |||||||
|         specifier: 5.21.1 |         specifier: 5.21.1 | ||||||
|         version: 5.21.1 |         version: 5.21.1 | ||||||
|       '@typescript-eslint/eslint-plugin': |       '@typescript-eslint/eslint-plugin': | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/parser': |       '@typescript-eslint/parser': | ||||||
|         specifier: 8.45.0 |         specifier: 8.46.0 | ||||||
|         version: 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |         version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       dotenv: |       dotenv: | ||||||
|         specifier: 17.2.3 |         specifier: 17.2.3 | ||||||
|         version: 17.2.3 |         version: 17.2.3 | ||||||
| @@ -3372,8 +3372,8 @@ packages: | |||||||
|     resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} |     resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} | ||||||
|     engines: {node: '>=14'} |     engines: {node: '>=14'} | ||||||
|  |  | ||||||
|   '@playwright/test@1.55.1': |   '@playwright/test@1.56.0': | ||||||
|     resolution: {integrity: sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==} |     resolution: {integrity: sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==} | ||||||
|     engines: {node: '>=18'} |     engines: {node: '>=18'} | ||||||
|     hasBin: true |     hasBin: true | ||||||
|  |  | ||||||
| @@ -4715,8 +4715,8 @@ packages: | |||||||
|   '@types/express-http-proxy@1.6.7': |   '@types/express-http-proxy@1.6.7': | ||||||
|     resolution: {integrity: sha512-CEp9pbnwVI1RzN9PXc+KESMxwUW5r1O7tkWb5h7Wg/YAIf+KulD/zKev8fbbn+Ljt0Yvs8MXwV2W6Id+cKxe2Q==} |     resolution: {integrity: sha512-CEp9pbnwVI1RzN9PXc+KESMxwUW5r1O7tkWb5h7Wg/YAIf+KulD/zKev8fbbn+Ljt0Yvs8MXwV2W6Id+cKxe2Q==} | ||||||
|  |  | ||||||
|   '@types/express-serve-static-core@5.0.7': |   '@types/express-serve-static-core@5.1.0': | ||||||
|     resolution: {integrity: sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==} |     resolution: {integrity: sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==} | ||||||
|  |  | ||||||
|   '@types/express-session@1.18.2': |   '@types/express-session@1.18.2': | ||||||
|     resolution: {integrity: sha512-k+I0BxwVXsnEU2hV77cCobC08kIsn4y44C3gC0b46uxZVMaXA04lSPgRLR/bSL2w0t0ShJiG8o4jPzRG/nscFg==} |     resolution: {integrity: sha512-k+I0BxwVXsnEU2hV77cCobC08kIsn4y44C3gC0b46uxZVMaXA04lSPgRLR/bSL2w0t0ShJiG8o4jPzRG/nscFg==} | ||||||
| @@ -4989,11 +4989,11 @@ packages: | |||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   '@typescript-eslint/eslint-plugin@8.45.0': |   '@typescript-eslint/eslint-plugin@8.46.0': | ||||||
|     resolution: {integrity: sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==} |     resolution: {integrity: sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       '@typescript-eslint/parser': ^8.45.0 |       '@typescript-eslint/parser': ^8.46.0 | ||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
| @@ -5004,8 +5004,8 @@ packages: | |||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   '@typescript-eslint/parser@8.45.0': |   '@typescript-eslint/parser@8.46.0': | ||||||
|     resolution: {integrity: sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==} |     resolution: {integrity: sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
| @@ -5023,8 +5023,8 @@ packages: | |||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   '@typescript-eslint/project-service@8.45.0': |   '@typescript-eslint/project-service@8.46.0': | ||||||
|     resolution: {integrity: sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==} |     resolution: {integrity: sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
| @@ -5037,8 +5037,8 @@ packages: | |||||||
|     resolution: {integrity: sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==} |     resolution: {integrity: sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|  |  | ||||||
|   '@typescript-eslint/scope-manager@8.45.0': |   '@typescript-eslint/scope-manager@8.46.0': | ||||||
|     resolution: {integrity: sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==} |     resolution: {integrity: sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|  |  | ||||||
|   '@typescript-eslint/tsconfig-utils@8.40.0': |   '@typescript-eslint/tsconfig-utils@8.40.0': | ||||||
| @@ -5059,6 +5059,12 @@ packages: | |||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|  |   '@typescript-eslint/tsconfig-utils@8.46.0': | ||||||
|  |     resolution: {integrity: sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==} | ||||||
|  |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|  |     peerDependencies: | ||||||
|  |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   '@typescript-eslint/type-utils@8.40.0': |   '@typescript-eslint/type-utils@8.40.0': | ||||||
|     resolution: {integrity: sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==} |     resolution: {integrity: sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
| @@ -5066,8 +5072,8 @@ packages: | |||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   '@typescript-eslint/type-utils@8.45.0': |   '@typescript-eslint/type-utils@8.46.0': | ||||||
|     resolution: {integrity: sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==} |     resolution: {integrity: sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
| @@ -5085,6 +5091,10 @@ packages: | |||||||
|     resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==} |     resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|  |  | ||||||
|  |   '@typescript-eslint/types@8.46.0': | ||||||
|  |     resolution: {integrity: sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==} | ||||||
|  |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|  |  | ||||||
|   '@typescript-eslint/typescript-estree@8.40.0': |   '@typescript-eslint/typescript-estree@8.40.0': | ||||||
|     resolution: {integrity: sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==} |     resolution: {integrity: sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
| @@ -5097,8 +5107,8 @@ packages: | |||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   '@typescript-eslint/typescript-estree@8.45.0': |   '@typescript-eslint/typescript-estree@8.46.0': | ||||||
|     resolution: {integrity: sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==} |     resolution: {integrity: sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
| @@ -5117,8 +5127,8 @@ packages: | |||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   '@typescript-eslint/utils@8.45.0': |   '@typescript-eslint/utils@8.46.0': | ||||||
|     resolution: {integrity: sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==} |     resolution: {integrity: sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
| @@ -5132,8 +5142,8 @@ packages: | |||||||
|     resolution: {integrity: sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==} |     resolution: {integrity: sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|  |  | ||||||
|   '@typescript-eslint/visitor-keys@8.45.0': |   '@typescript-eslint/visitor-keys@8.46.0': | ||||||
|     resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==} |     resolution: {integrity: sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|  |  | ||||||
|   '@ungap/structured-clone@1.3.0': |   '@ungap/structured-clone@1.3.0': | ||||||
| @@ -10096,8 +10106,8 @@ packages: | |||||||
|     resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} |     resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} | ||||||
|     engines: {node: '>=18'} |     engines: {node: '>=18'} | ||||||
|  |  | ||||||
|   openai@6.1.0: |   openai@6.2.0: | ||||||
|     resolution: {integrity: sha512-5sqb1wK67HoVgGlsPwcH2bUbkg66nnoIYKoyV9zi5pZPqh7EWlmSrSDjAh4O5jaIg/0rIlcDKBtWvZBuacmGZg==} |     resolution: {integrity: sha512-qqjzHls7F5xkXNGy9P1Ei1rorI5LWupUUFWP66zPU8FlZbiITX8SFcHMKNZg/NATJ0LpIZcMUFxSwQmdeQPwSw==} | ||||||
|     hasBin: true |     hasBin: true | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       ws: ^8.18.0 |       ws: ^8.18.0 | ||||||
| @@ -10428,13 +10438,13 @@ packages: | |||||||
|   pkg-types@2.1.0: |   pkg-types@2.1.0: | ||||||
|     resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==} |     resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==} | ||||||
|  |  | ||||||
|   playwright-core@1.55.1: |   playwright-core@1.56.0: | ||||||
|     resolution: {integrity: sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==} |     resolution: {integrity: sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==} | ||||||
|     engines: {node: '>=18'} |     engines: {node: '>=18'} | ||||||
|     hasBin: true |     hasBin: true | ||||||
|  |  | ||||||
|   playwright@1.55.1: |   playwright@1.56.0: | ||||||
|     resolution: {integrity: sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==} |     resolution: {integrity: sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==} | ||||||
|     engines: {node: '>=18'} |     engines: {node: '>=18'} | ||||||
|     hasBin: true |     hasBin: true | ||||||
|  |  | ||||||
| @@ -13012,8 +13022,8 @@ packages: | |||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
|       typescript: '>=4.8.4 <6.0.0' |       typescript: '>=4.8.4 <6.0.0' | ||||||
|  |  | ||||||
|   typescript-eslint@8.45.0: |   typescript-eslint@8.46.0: | ||||||
|     resolution: {integrity: sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==} |     resolution: {integrity: sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw==} | ||||||
|     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} |     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       eslint: ^8.57.0 || ^9.0.0 |       eslint: ^8.57.0 || ^9.0.0 | ||||||
| @@ -14714,6 +14724,8 @@ snapshots: | |||||||
|       '@ckeditor/ckeditor5-utils': 47.0.0 |       '@ckeditor/ckeditor5-utils': 47.0.0 | ||||||
|       '@ckeditor/ckeditor5-watchdog': 47.0.0 |       '@ckeditor/ckeditor5-watchdog': 47.0.0 | ||||||
|       es-toolkit: 1.39.5 |       es-toolkit: 1.39.5 | ||||||
|  |     transitivePeerDependencies: | ||||||
|  |       - supports-color | ||||||
|  |  | ||||||
|   '@ckeditor/ckeditor5-dev-build-tools@43.1.0(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)': |   '@ckeditor/ckeditor5-dev-build-tools@43.1.0(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
| @@ -14905,6 +14917,8 @@ snapshots: | |||||||
|       '@ckeditor/ckeditor5-utils': 47.0.0 |       '@ckeditor/ckeditor5-utils': 47.0.0 | ||||||
|       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) |       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||||
|       es-toolkit: 1.39.5 |       es-toolkit: 1.39.5 | ||||||
|  |     transitivePeerDependencies: | ||||||
|  |       - supports-color | ||||||
|  |  | ||||||
|   '@ckeditor/ckeditor5-editor-multi-root@47.0.0': |   '@ckeditor/ckeditor5-editor-multi-root@47.0.0': | ||||||
|     dependencies: |     dependencies: | ||||||
| @@ -14927,6 +14941,8 @@ snapshots: | |||||||
|       '@ckeditor/ckeditor5-table': 47.0.0 |       '@ckeditor/ckeditor5-table': 47.0.0 | ||||||
|       '@ckeditor/ckeditor5-utils': 47.0.0 |       '@ckeditor/ckeditor5-utils': 47.0.0 | ||||||
|       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) |       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||||
|  |     transitivePeerDependencies: | ||||||
|  |       - supports-color | ||||||
|  |  | ||||||
|   '@ckeditor/ckeditor5-emoji@47.0.0': |   '@ckeditor/ckeditor5-emoji@47.0.0': | ||||||
|     dependencies: |     dependencies: | ||||||
| @@ -15098,6 +15114,8 @@ snapshots: | |||||||
|       '@ckeditor/ckeditor5-widget': 47.0.0 |       '@ckeditor/ckeditor5-widget': 47.0.0 | ||||||
|       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) |       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||||
|       es-toolkit: 1.39.5 |       es-toolkit: 1.39.5 | ||||||
|  |     transitivePeerDependencies: | ||||||
|  |       - supports-color | ||||||
|  |  | ||||||
|   '@ckeditor/ckeditor5-icons@47.0.0': {} |   '@ckeditor/ckeditor5-icons@47.0.0': {} | ||||||
|  |  | ||||||
| @@ -15484,8 +15502,6 @@ snapshots: | |||||||
|       '@ckeditor/ckeditor5-ui': 47.0.0 |       '@ckeditor/ckeditor5-ui': 47.0.0 | ||||||
|       '@ckeditor/ckeditor5-utils': 47.0.0 |       '@ckeditor/ckeditor5-utils': 47.0.0 | ||||||
|       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) |       ckeditor5: 47.0.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||||
|     transitivePeerDependencies: |  | ||||||
|       - supports-color |  | ||||||
|  |  | ||||||
|   '@ckeditor/ckeditor5-special-characters@47.0.0': |   '@ckeditor/ckeditor5-special-characters@47.0.0': | ||||||
|     dependencies: |     dependencies: | ||||||
| @@ -17551,9 +17567,9 @@ snapshots: | |||||||
|   '@pkgjs/parseargs@0.11.0': |   '@pkgjs/parseargs@0.11.0': | ||||||
|     optional: true |     optional: true | ||||||
|  |  | ||||||
|   '@playwright/test@1.55.1': |   '@playwright/test@1.56.0': | ||||||
|     dependencies: |     dependencies: | ||||||
|       playwright: 1.55.1 |       playwright: 1.56.0 | ||||||
|  |  | ||||||
|   '@polka/url@1.0.0-next.29': {} |   '@polka/url@1.0.0-next.29': {} | ||||||
|  |  | ||||||
| @@ -18777,7 +18793,7 @@ snapshots: | |||||||
|  |  | ||||||
|   '@types/connect-history-api-fallback@1.5.4': |   '@types/connect-history-api-fallback@1.5.4': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@types/express-serve-static-core': 5.0.7 |       '@types/express-serve-static-core': 5.1.0 | ||||||
|       '@types/node': 22.18.8 |       '@types/node': 22.18.8 | ||||||
|  |  | ||||||
|   '@types/connect@3.4.38': |   '@types/connect@3.4.38': | ||||||
| @@ -18948,7 +18964,7 @@ snapshots: | |||||||
|     dependencies: |     dependencies: | ||||||
|       '@types/express': 5.0.3 |       '@types/express': 5.0.3 | ||||||
|  |  | ||||||
|   '@types/express-serve-static-core@5.0.7': |   '@types/express-serve-static-core@5.1.0': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@types/node': 22.18.8 |       '@types/node': 22.18.8 | ||||||
|       '@types/qs': 6.14.0 |       '@types/qs': 6.14.0 | ||||||
| @@ -18962,14 +18978,14 @@ snapshots: | |||||||
|   '@types/express@4.17.23': |   '@types/express@4.17.23': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@types/body-parser': 1.19.6 |       '@types/body-parser': 1.19.6 | ||||||
|       '@types/express-serve-static-core': 5.0.7 |       '@types/express-serve-static-core': 5.1.0 | ||||||
|       '@types/qs': 6.14.0 |       '@types/qs': 6.14.0 | ||||||
|       '@types/serve-static': 1.15.9 |       '@types/serve-static': 1.15.9 | ||||||
|  |  | ||||||
|   '@types/express@5.0.3': |   '@types/express@5.0.3': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@types/body-parser': 1.19.6 |       '@types/body-parser': 1.19.6 | ||||||
|       '@types/express-serve-static-core': 5.0.7 |       '@types/express-serve-static-core': 5.1.0 | ||||||
|       '@types/serve-static': 1.15.9 |       '@types/serve-static': 1.15.9 | ||||||
|  |  | ||||||
|   '@types/fs-extra@11.0.4': |   '@types/fs-extra@11.0.4': | ||||||
| @@ -19270,14 +19286,14 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': |   '@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@eslint-community/regexpp': 4.12.1 |       '@eslint-community/regexpp': 4.12.1 | ||||||
|       '@typescript-eslint/parser': 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |       '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/scope-manager': 8.45.0 |       '@typescript-eslint/scope-manager': 8.46.0 | ||||||
|       '@typescript-eslint/type-utils': 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |       '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/utils': 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |       '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/visitor-keys': 8.45.0 |       '@typescript-eslint/visitor-keys': 8.46.0 | ||||||
|       eslint: 9.37.0(jiti@2.6.1) |       eslint: 9.37.0(jiti@2.6.1) | ||||||
|       graphemer: 1.4.0 |       graphemer: 1.4.0 | ||||||
|       ignore: 7.0.5 |       ignore: 7.0.5 | ||||||
| @@ -19299,12 +19315,12 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': |   '@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/scope-manager': 8.45.0 |       '@typescript-eslint/scope-manager': 8.46.0 | ||||||
|       '@typescript-eslint/types': 8.45.0 |       '@typescript-eslint/types': 8.46.0 | ||||||
|       '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) |       '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) | ||||||
|       '@typescript-eslint/visitor-keys': 8.45.0 |       '@typescript-eslint/visitor-keys': 8.46.0 | ||||||
|       debug: 4.4.3(supports-color@6.0.0) |       debug: 4.4.3(supports-color@6.0.0) | ||||||
|       eslint: 9.37.0(jiti@2.6.1) |       eslint: 9.37.0(jiti@2.6.1) | ||||||
|       typescript: 5.9.3 |       typescript: 5.9.3 | ||||||
| @@ -19329,10 +19345,10 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@typescript-eslint/project-service@8.45.0(typescript@5.9.3)': |   '@typescript-eslint/project-service@8.46.0(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) |       '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) | ||||||
|       '@typescript-eslint/types': 8.45.0 |       '@typescript-eslint/types': 8.46.0 | ||||||
|       debug: 4.4.3(supports-color@6.0.0) |       debug: 4.4.3(supports-color@6.0.0) | ||||||
|       typescript: 5.9.3 |       typescript: 5.9.3 | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
| @@ -19348,10 +19364,10 @@ snapshots: | |||||||
|       '@typescript-eslint/types': 8.44.1 |       '@typescript-eslint/types': 8.44.1 | ||||||
|       '@typescript-eslint/visitor-keys': 8.44.1 |       '@typescript-eslint/visitor-keys': 8.44.1 | ||||||
|  |  | ||||||
|   '@typescript-eslint/scope-manager@8.45.0': |   '@typescript-eslint/scope-manager@8.46.0': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/types': 8.45.0 |       '@typescript-eslint/types': 8.46.0 | ||||||
|       '@typescript-eslint/visitor-keys': 8.45.0 |       '@typescript-eslint/visitor-keys': 8.46.0 | ||||||
|  |  | ||||||
|   '@typescript-eslint/tsconfig-utils@8.40.0(typescript@5.9.3)': |   '@typescript-eslint/tsconfig-utils@8.40.0(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
| @@ -19365,6 +19381,10 @@ snapshots: | |||||||
|     dependencies: |     dependencies: | ||||||
|       typescript: 5.9.3 |       typescript: 5.9.3 | ||||||
|  |  | ||||||
|  |   '@typescript-eslint/tsconfig-utils@8.46.0(typescript@5.9.3)': | ||||||
|  |     dependencies: | ||||||
|  |       typescript: 5.9.3 | ||||||
|  |  | ||||||
|   '@typescript-eslint/type-utils@8.40.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': |   '@typescript-eslint/type-utils@8.40.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/types': 8.40.0 |       '@typescript-eslint/types': 8.40.0 | ||||||
| @@ -19377,11 +19397,11 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@typescript-eslint/type-utils@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': |   '@typescript-eslint/type-utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/types': 8.45.0 |       '@typescript-eslint/types': 8.46.0 | ||||||
|       '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) |       '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) | ||||||
|       '@typescript-eslint/utils': 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |       '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       debug: 4.4.3(supports-color@6.0.0) |       debug: 4.4.3(supports-color@6.0.0) | ||||||
|       eslint: 9.37.0(jiti@2.6.1) |       eslint: 9.37.0(jiti@2.6.1) | ||||||
|       ts-api-utils: 2.1.0(typescript@5.9.3) |       ts-api-utils: 2.1.0(typescript@5.9.3) | ||||||
| @@ -19395,6 +19415,8 @@ snapshots: | |||||||
|  |  | ||||||
|   '@typescript-eslint/types@8.45.0': {} |   '@typescript-eslint/types@8.45.0': {} | ||||||
|  |  | ||||||
|  |   '@typescript-eslint/types@8.46.0': {} | ||||||
|  |  | ||||||
|   '@typescript-eslint/typescript-estree@8.40.0(typescript@5.9.3)': |   '@typescript-eslint/typescript-estree@8.40.0(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/project-service': 8.40.0(typescript@5.9.3) |       '@typescript-eslint/project-service': 8.40.0(typescript@5.9.3) | ||||||
| @@ -19427,12 +19449,12 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@typescript-eslint/typescript-estree@8.45.0(typescript@5.9.3)': |   '@typescript-eslint/typescript-estree@8.46.0(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/project-service': 8.45.0(typescript@5.9.3) |       '@typescript-eslint/project-service': 8.46.0(typescript@5.9.3) | ||||||
|       '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) |       '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) | ||||||
|       '@typescript-eslint/types': 8.45.0 |       '@typescript-eslint/types': 8.46.0 | ||||||
|       '@typescript-eslint/visitor-keys': 8.45.0 |       '@typescript-eslint/visitor-keys': 8.46.0 | ||||||
|       debug: 4.4.3(supports-color@6.0.0) |       debug: 4.4.3(supports-color@6.0.0) | ||||||
|       fast-glob: 3.3.3 |       fast-glob: 3.3.3 | ||||||
|       is-glob: 4.0.3 |       is-glob: 4.0.3 | ||||||
| @@ -19465,12 +19487,12 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@typescript-eslint/utils@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': |   '@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) |       '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) | ||||||
|       '@typescript-eslint/scope-manager': 8.45.0 |       '@typescript-eslint/scope-manager': 8.46.0 | ||||||
|       '@typescript-eslint/types': 8.45.0 |       '@typescript-eslint/types': 8.46.0 | ||||||
|       '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) |       '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) | ||||||
|       eslint: 9.37.0(jiti@2.6.1) |       eslint: 9.37.0(jiti@2.6.1) | ||||||
|       typescript: 5.9.3 |       typescript: 5.9.3 | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
| @@ -19486,9 +19508,9 @@ snapshots: | |||||||
|       '@typescript-eslint/types': 8.44.1 |       '@typescript-eslint/types': 8.44.1 | ||||||
|       eslint-visitor-keys: 4.2.1 |       eslint-visitor-keys: 4.2.1 | ||||||
|  |  | ||||||
|   '@typescript-eslint/visitor-keys@8.45.0': |   '@typescript-eslint/visitor-keys@8.46.0': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/types': 8.45.0 |       '@typescript-eslint/types': 8.46.0 | ||||||
|       eslint-visitor-keys: 4.2.1 |       eslint-visitor-keys: 4.2.1 | ||||||
|  |  | ||||||
|   '@ungap/structured-clone@1.3.0': {} |   '@ungap/structured-clone@1.3.0': {} | ||||||
| @@ -19524,7 +19546,7 @@ snapshots: | |||||||
|       - bufferutil |       - bufferutil | ||||||
|       - utf-8-validate |       - utf-8-validate | ||||||
|  |  | ||||||
|   '@vitest/browser@3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))': |   '@vitest/browser@3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@testing-library/dom': 10.4.0 |       '@testing-library/dom': 10.4.0 | ||||||
|       '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) |       '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) | ||||||
| @@ -19536,7 +19558,7 @@ snapshots: | |||||||
|       vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.8)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@19.0.2)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) |       vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.8)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@19.0.2)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) | ||||||
|       ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5) |       ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5) | ||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       playwright: 1.55.1 |       playwright: 1.56.0 | ||||||
|       webdriverio: 9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) |       webdriverio: 9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - bufferutil |       - bufferutil | ||||||
| @@ -19577,7 +19599,7 @@ snapshots: | |||||||
|       tinyrainbow: 2.0.0 |       tinyrainbow: 2.0.0 | ||||||
|       vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.8)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@19.0.2)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) |       vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.8)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@19.0.2)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) | ||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) |       '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
| @@ -25917,7 +25939,7 @@ snapshots: | |||||||
|       is-inside-container: 1.0.0 |       is-inside-container: 1.0.0 | ||||||
|       wsl-utils: 0.1.0 |       wsl-utils: 0.1.0 | ||||||
|  |  | ||||||
|   openai@6.1.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))(zod@3.24.4): |   openai@6.2.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))(zod@3.24.4): | ||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5) |       ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5) | ||||||
|       zod: 3.24.4 |       zod: 3.24.4 | ||||||
| @@ -26251,11 +26273,11 @@ snapshots: | |||||||
|       exsolve: 1.0.5 |       exsolve: 1.0.5 | ||||||
|       pathe: 2.0.3 |       pathe: 2.0.3 | ||||||
|  |  | ||||||
|   playwright-core@1.55.1: {} |   playwright-core@1.56.0: {} | ||||||
|  |  | ||||||
|   playwright@1.55.1: |   playwright@1.56.0: | ||||||
|     dependencies: |     dependencies: | ||||||
|       playwright-core: 1.55.1 |       playwright-core: 1.56.0 | ||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       fsevents: 2.3.2 |       fsevents: 2.3.2 | ||||||
|  |  | ||||||
| @@ -29434,12 +29456,12 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   typescript-eslint@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3): |   typescript-eslint@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |       '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/parser': 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |       '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) |       '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) | ||||||
|       '@typescript-eslint/utils': 8.45.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) |       '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) | ||||||
|       eslint: 9.37.0(jiti@2.6.1) |       eslint: 9.37.0(jiti@2.6.1) | ||||||
|       typescript: 5.9.3 |       typescript: 5.9.3 | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
| @@ -29806,7 +29828,7 @@ snapshots: | |||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       '@types/debug': 4.1.12 |       '@types/debug': 4.1.12 | ||||||
|       '@types/node': 22.18.8 |       '@types/node': 22.18.8 | ||||||
|       '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.55.1)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) |       '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.8)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.5)(vite@7.1.9(@types/node@22.18.8)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||||
|       '@vitest/ui': 3.2.4(vitest@3.2.4) |       '@vitest/ui': 3.2.4(vitest@3.2.4) | ||||||
|       happy-dom: 19.0.2 |       happy-dom: 19.0.2 | ||||||
|       jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) |       jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) | ||||||
| @@ -29972,7 +29994,7 @@ snapshots: | |||||||
|       '@types/bonjour': 3.5.13 |       '@types/bonjour': 3.5.13 | ||||||
|       '@types/connect-history-api-fallback': 1.5.4 |       '@types/connect-history-api-fallback': 1.5.4 | ||||||
|       '@types/express': 4.17.23 |       '@types/express': 4.17.23 | ||||||
|       '@types/express-serve-static-core': 5.0.7 |       '@types/express-serve-static-core': 5.1.0 | ||||||
|       '@types/serve-index': 1.9.4 |       '@types/serve-index': 1.9.4 | ||||||
|       '@types/serve-static': 1.15.9 |       '@types/serve-static': 1.15.9 | ||||||
|       '@types/sockjs': 0.3.36 |       '@types/sockjs': 0.3.36 | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ function copyNativeDependencies(projectRoot: string) { | |||||||
|     cpSync(sourcePath, destPath, { recursive: true, dereference: true }); |     cpSync(sourcePath, destPath, { recursive: true, dereference: true }); | ||||||
| } | } | ||||||
|  |  | ||||||
| function rebuildNativeDependencies(projectRoot: string) { | async function rebuildNativeDependencies(projectRoot: string) { | ||||||
|     const electronVersion = determineElectronVersion(projectRoot); |     const electronVersion = determineElectronVersion(projectRoot); | ||||||
|  |  | ||||||
|     if (!electronVersion) { |     if (!electronVersion) { | ||||||
| @@ -35,7 +35,7 @@ function rebuildNativeDependencies(projectRoot: string) { | |||||||
|     console.log(`Rebuilding ${projectRoot} with ${electronVersion} for ${targetArch}...`); |     console.log(`Rebuilding ${projectRoot} with ${electronVersion} for ${targetArch}...`); | ||||||
|  |  | ||||||
|     const resolvedPath = resolve(projectRoot); |     const resolvedPath = resolve(projectRoot); | ||||||
|     rebuild({ |     await rebuild({ | ||||||
|         projectRootPath: resolvedPath, |         projectRootPath: resolvedPath, | ||||||
|         buildPath: resolvedPath, |         buildPath: resolvedPath, | ||||||
|         electronVersion, |         electronVersion, | ||||||
| @@ -64,5 +64,5 @@ function determineElectronVersion(projectRoot: string) { | |||||||
|  |  | ||||||
| for (const projectRoot of [ "apps/desktop", "apps/edit-docs" ]) { | for (const projectRoot of [ "apps/desktop", "apps/edit-docs" ]) { | ||||||
|     copyNativeDependencies(projectRoot); |     copyNativeDependencies(projectRoot); | ||||||
|     rebuildNativeDependencies(projectRoot); |     await rebuildNativeDependencies(projectRoot); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user