Compare commits

..

276 Commits

Author SHA1 Message Date
zadam 67e69f1940 release 0.53.0-beta
Publish Docker image / Push Docker image to multiple registries (push) Failing after 40s
2022-06-19 14:49:48 +02:00
zadam 046db503d3 added excalidraw to the demo document 2022-06-19 14:27:25 +02:00
zadam 9827e30a61 simple dedicated health check endpoint for docker 2022-06-19 14:15:31 +02:00
zadam e21a1b56fa Merge pull request #2928 from bill88t/master
Add a very basic docker health check
2022-06-19 14:14:22 +02:00
zadam 08e12e7349 no need to create template relation if there is already one owned 2022-06-19 14:06:00 +02:00
zadam 5ed1631a35 resort attributes for display 2022-06-19 12:18:13 +02:00
Bill Sideris 8ac776f305 Slowly making it an oneliner, added line check 2022-06-19 12:39:20 +03:00
zadam 981fac8e50 #template label is not inherited through template since it's meant to mark the template note only 2022-06-19 11:36:29 +02:00
Bill Sideris 8bb8ab96f1 a bit better 2022-06-19 12:23:00 +03:00
Bill Sideris 0b0d1b59b9 update it to check for login 200 2022-06-18 17:21:41 +03:00
Bill Sideris 57609a5952 Add docker health check 2022-06-18 17:10:26 +03:00
zadam 4f86d769be web view fixes + disclaimer 2022-06-18 15:52:09 +02:00
zadam 6cb5144c09 add score to note title matches as opposed to note path, #2927 2022-06-18 14:45:41 +02:00
zadam aee350b07b small bulk action fixes 2022-06-17 23:12:52 +02:00
zadam 5ca7e39852 fix putting new attribute correctly into becca 2022-06-17 23:04:46 +02:00
zadam 540aba39db vertical navigation in options 2022-06-16 23:00:40 +02:00
zadam 9a8e677baf converted options dialog to new pattern 2022-06-16 22:53:11 +02:00
zadam c5bc23d511 fixed confirmDeleteNoteBoxWithNote 2022-06-16 21:30:05 +02:00
zadam 7ac8dc6785 converted prompt dialog to new pattern 2022-06-16 21:13:09 +02:00
zadam 049261a8ee scope dialog CSS 2022-06-16 20:20:56 +02:00
zadam 1d037d3f0f converted confirm dialog to new pattern 2022-06-16 20:19:26 +02:00
zadam b45df29937 prevent pasting notes into search parent note 2022-06-16 20:02:40 +02:00
zadam ec087ed328 converted info dialog to new pattern 2022-06-16 19:53:33 +02:00
zadam 9707094686 converted delete notes dialog to new pattern 2022-06-16 19:41:29 +02:00
zadam eb8e5eafb6 converted note revisions to new pattern 2022-06-16 19:29:18 +02:00
zadam e140daa952 converted protected session password dialog to new pattern 2022-06-16 15:28:51 +02:00
zadam 3255607b09 converted markdown import dialog to new pattern 2022-06-16 15:15:42 +02:00
zadam 36c210d0dd converted export dialog to new pattern 2022-06-16 15:04:57 +02:00
zadam 595e16cc6f converted import dialog to new pattern 2022-06-16 14:21:24 +02:00
zadam 40bbe380d3 converted move to dialog to new pattern 2022-06-16 14:08:33 +02:00
zadam 683b4ac73a converted clone to dialog to new pattern 2022-06-16 14:02:43 +02:00
zadam e0ad256194 fix add link + note type chooser combo 2022-06-16 13:21:27 +02:00
zadam 0468ca6814 converted add link dialog to new pattern 2022-06-16 11:03:04 +02:00
zadam 6ebf7ae94e converted jump to note dialog to new pattern 2022-06-16 10:42:49 +02:00
zadam 5ccaf8b3b9 fix multiple parents indication on note tree 2022-06-15 23:07:09 +02:00
zadam 0e01c19414 don't show hidden notes in search results 2022-06-15 22:50:22 +02:00
zadam 1347d3fcc2 converted note type chooser dialog to new pattern 2022-06-15 00:10:32 +02:00
zadam ebd715ca1b converted include note dialog to new pattern 2022-06-14 23:51:16 +02:00
zadam 73574ac890 converted password not set dialog to new pattern 2022-06-14 23:32:16 +02:00
zadam ca44edd48c converted sort by dialog to new pattern 2022-06-14 23:19:41 +02:00
zadam 312ffc110a converted branch prefix dialog to new pattern 2022-06-14 23:07:42 +02:00
zadam bc87bf12cf converted backend log dialog to new pattern 2022-06-14 23:00:24 +02:00
zadam 11412a258b converted recent changes dialog to new pattern 2022-06-14 22:55:07 +02:00
zadam bc35efd565 Merge branch 'stable' 2022-06-14 22:46:58 +02:00
zadam 416a723160 Merge remote-tracking branch 'origin/master' 2022-06-14 22:46:52 +02:00
zadam 10322c5d0f Merge pull request #2920 from st3iny/fix/2919/docker-image-clean-exit
Fix docker image not exiting cleanly
2022-06-14 22:24:18 +02:00
Richard Steinmetz 7775d90b9a Fix docker image not exiting cleanly
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2022-06-14 10:34:07 +02:00
zadam fac9fef652 release 0.52.3
Publish Docker image / Push Docker image to multiple registries (push) Failing after 43s
2022-06-13 23:41:52 +02:00
zadam f0ab1fb5a1 Merge pull request #2917 from bill88t/master
Added the USER_UID & USER_GID env variables
2022-06-13 23:23:30 +02:00
zadam f86fb129b6 Merge remote-tracking branch 'origin/master' 2022-06-13 23:18:57 +02:00
zadam 63cabb13b6 Merge pull request #2917 from bill88t/master
Added the USER_UID & USER_GID env variables
2022-06-13 23:17:59 +02:00
zadam d3ee0aa8a8 Merge branch 'stable'
# Conflicts:
#	src/routes/api/files.js
#	src/routes/api/note_revisions.js
#	src/routes/api/notes.js
#	src/services/image.js
2022-06-13 23:04:54 +02:00
zadam 6256bcde2d note revisions and file properties buttons respect protected session 2022-06-13 23:03:56 +02:00
zadam df3fdb59c5 fix saving note revisions, closes #2915 2022-06-13 22:54:08 +02:00
zadam 4cec856e21 simplified updating note content 2022-06-13 22:38:59 +02:00
Bill Sideris 8a43688a65 Added the USER_UID & USER_GID env variables 2022-06-13 12:43:10 +03:00
zadam 7edcd5d746 Merge remote-tracking branch 'origin/master' 2022-06-13 00:00:24 +02:00
zadam ec6d93b34f converted help dialog to new pattern 2022-06-13 00:00:15 +02:00
zadam 0c6efb0cb7 Merge pull request #2914 from st3iny/enh/noid/trilium-data-dir-docker-start
Fix TRILIUM_DATA_DIR permissions in start-docker.sh
2022-06-12 23:31:15 +02:00
zadam f8fd8e47a9 added rename note bulk action 2022-06-12 23:29:11 +02:00
Richard Steinmetz 566111ce82 Fix TRILIUM_DATA_DIR permissions in start-docker.sh
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2022-06-12 23:25:33 +02:00
zadam 7ba619c71d converted note source dialog to new pattern 2022-06-12 19:38:28 +02:00
zadam b678d87c80 converted about dialog to new pattern 2022-06-12 14:03:59 +02:00
zadam 4aaa0f8d8c change tree node icon for selected notes to quickly bring up bulk action dialog 2022-06-12 13:57:22 +02:00
zadam 1bfc5fb77f calculate affected counts and take into account includeDescendants when executing 2022-06-12 10:35:30 +02:00
zadam 63f0e441b9 trigger execute bulk actions 2022-06-12 00:05:46 +02:00
zadam 041b4ea442 Merge remote-tracking branch 'origin/master' 2022-06-11 23:29:59 +02:00
zadam 2115b76047 bulk action dialog converted to widget 2022-06-11 23:29:52 +02:00
zadam 117db9f1cc Merge pull request #2910 from sigaloid/master
Add toast messages prior to possibly long operations
2022-06-11 22:15:34 +02:00
sigaloid b530bc548f Add messages prior to possibly long operations 2022-06-11 13:27:41 -04:00
zadam 8e23c15763 Merge branch 'next53'
# Conflicts:
#	src/services/builtin_attributes.js
2022-06-10 23:02:51 +02:00
zadam 23e9bcfdc5 release 0.52.2
Publish Docker image / Push Docker image to multiple registries (push) Failing after 39s
2022-06-09 23:39:48 +02:00
zadam 96c4934c00 new default keyboard shortcuts alt+up/down/left/right for moving notes on Mac 2022-06-09 23:38:07 +02:00
zadam 31fb02f810 titleTemplate should be sanitized on import 2022-06-09 21:01:02 +02:00
zadam 5fdb462ed5 fix activating ribbon tabs after note switch 2022-06-08 23:44:43 +02:00
zadam 7d76fb8bf5 merge fix 2022-06-08 22:52:17 +02:00
zadam 0f7fa7a7b7 Merge branch 'master' into next53
# Conflicts:
#	package-lock.json
#	src/routes/api/search.js
2022-06-08 22:51:18 +02:00
zadam e206d9cc68 fix selected note text color 2022-06-08 22:27:36 +02:00
zadam 2d33f570f4 fix bulk/search action delete 2022-06-08 22:25:00 +02:00
zadam 15f8173add fix ugly hover close button 2022-06-07 20:11:43 +02:00
zadam 51bbc23270 Merge branch 'master' into next53 2022-06-06 22:27:21 +02:00
zadam 7609bc78ec allow ignoring DB version for skipping uncritical migrations in case of a downgrade 2022-06-06 22:27:06 +02:00
zadam b4ac41eff8 fix handlers import, closes #2900 2022-06-06 21:59:44 +02:00
zadam f9bee7cd4e introduced bulk action groups 2022-06-05 23:36:46 +02:00
zadam f272238dde fix backend implementation of bulk actions 2022-06-05 23:13:09 +02:00
zadam 433003cf38 fix migration 2022-06-05 22:50:02 +02:00
zadam 773cefe21d refactorings of search actions to bulk actions 2022-06-05 22:46:37 +02:00
zadam 88fa51a34e refactorings of search actions to bulk actions 2022-06-05 22:32:23 +02:00
zadam 4211d0feda Merge branch 'master' into next53 2022-06-05 22:25:14 +02:00
zadam de1c76ee3c typo 2022-06-05 21:24:52 +02:00
zadam ec4fac421b release 0.52.1-beta
Publish Docker image / Push Docker image to multiple registries (push) Failing after 33s
2022-06-05 15:00:25 +02:00
zadam f587e0dfd9 added new runOnNoteDeletion, runOnBranchCreation, runOnBranchDeletion, #2898 2022-06-05 14:58:19 +02:00
zadam b5214e6cea disabled button theme/CSS tweaks 2022-06-05 14:35:23 +02:00
zadam 5fbaed61c1 fix "cut to note", closes #2895, #1182 2022-06-03 22:05:18 +02:00
zadam 9ce3e7e7d2 bulk actions WIP 2022-06-03 17:29:08 +02:00
zadam e1cd09df36 implement shift-click to select notes in between clicked and active note, closes #2647 2022-06-03 09:42:35 +02:00
zadam 27b55eb3ee make openOnFocus=false explicit 2022-06-03 08:07:27 +02:00
zadam 8fcc76ad6d fix debounce webpack 2022-06-02 23:26:40 +02:00
zadam ab0f0c5ced fix debounce webpack 2022-06-02 23:25:59 +02:00
zadam 4837dd050b fix bug when giving focus again to autocomplete input when coming back from note type chooser 2022-06-02 23:21:17 +02:00
zadam c0c38a4b49 Merge branch 'master' into next53 2022-06-02 22:32:29 +02:00
zadam 15a9ff4450 when closing / clearing last tab, close all splits 2022-06-02 22:28:25 +02:00
zadam 0a4f419e5e fix when searching for "note.", closes #2889 2022-06-02 17:41:23 +02:00
zadam 7fa531b3d6 add openSplitWithNote() frontend api method, #2891 2022-06-02 17:36:30 +02:00
zadam 3cfca27b54 expose ability to create note revisions in backend API #2890 2022-06-02 17:25:58 +02:00
zadam 93f0596b16 select template when creating note, closes #2813 2022-06-02 14:16:49 +02:00
zadam b204014a11 create note from template WIP 2022-05-31 23:27:45 +02:00
zadam 98b579524c create note from template WIP 2022-05-31 22:45:57 +02:00
zadam 88586b0f25 Merge branch 'master' into next53 2022-05-31 22:21:29 +02:00
zadam 103aa95ccf removed duplicated search action 2022-05-31 14:22:52 +02:00
zadam 339a6d7817 don't check for null content in consistency checks because it's too slow for large databases #2887 2022-05-31 14:09:46 +02:00
zadam f252badba6 skeleton for bulk assign attributes 2022-05-30 22:43:20 +02:00
zadam fe27c80078 added enter/leave protected session into the mobile frontend 2022-05-30 22:32:15 +02:00
zadam 8052574950 rename iframe to web view 2022-05-30 20:59:54 +02:00
zadam f19adf3ee0 add the ability to sort notes by folders first, closes #2649 2022-05-30 20:50:53 +02:00
zadam dcf31f8f95 toc fixes 2022-05-30 17:45:59 +02:00
zadam 93dd9274e7 fix relative address of lodash debounce, closes #2882 2022-05-30 13:22:28 +02:00
zadam cce3f9a700 TOC widget WIP 2022-05-29 21:44:26 +02:00
zadam 01155ad535 use webview instead of iframe 2022-05-29 17:42:09 +02:00
zadam ee217d6306 added iframe note type 2022-05-28 22:19:29 +02:00
zadam ca35527aeb release 0.52.0-beta 2022-05-27 22:13:24 +02:00
zadam 388dcadef3 release 0.52.0-beta
Publish Docker image / Push Docker image to multiple registries (push) Failing after 40s
2022-05-27 22:06:07 +02:00
zadam 8905148dbc fix NPE in note map, closes #2877 2022-05-27 21:55:58 +02:00
zadam daa36192cc fix jumping of find dialog in read only code 2022-05-27 21:50:59 +02:00
zadam ade77e5fb8 find widget readonly notes 2022-05-26 16:29:54 +02:00
zadam f250b72563 findwidget in read only notes WIP 2022-05-25 23:38:06 +02:00
zadam 37cb5f5e9a added previous/next buttons to the find widget 2022-05-25 20:43:52 +02:00
zadam 82fcc97ed2 Merge branch 'custom-search-dialog' 2022-05-25 20:32:22 +02:00
zadam 53e9c8cdac upgrades 2022-05-24 21:34:32 +02:00
zadam 541d451168 tree css changes to make selection and active note more distinct 2022-05-24 21:33:07 +02:00
zadam 7c64dc9440 fix coloring of backlinks popup in dark theme 2022-05-22 23:29:07 +02:00
zadam 27570a7756 fix for canvas theme after opening help 2022-05-22 15:27:40 +02:00
zadam d6931f7441 fix setting theme on new canvas note 2022-05-22 14:27:16 +02:00
zadam 7d39d080f5 switching note type will reevalute max content width setting 2022-05-22 14:24:47 +02:00
zadam 13ccd2ba67 remove the canvas dependency (transitive dep of jsdom) in postinstall 2022-05-22 13:45:49 +02:00
zadam 81fd7397e4 added underline to more distinguish selected items in the tree, #2865 2022-05-22 13:45:15 +02:00
zadam 6f75f944a3 Merge pull request #2864 from dousha/master
Fix docker data permissions
2022-05-21 22:55:59 +02:00
Jiahao Lee 308b0f7464 Remove unneeded packages 2022-05-22 03:35:26 +08:00
zadam 678e883044 switch excalidraw theme (light/dark) based on trilium setting 2022-05-21 21:08:24 +02:00
zadam 819cf0907d add option to disable auto-download of images for offline storage, #2859 2022-05-21 14:00:53 +02:00
dousha 942f17b2f4 fix docker file permissions so 777 is no longer needed 2022-05-21 13:25:59 +08:00
zadam 2085dc5ed4 minor canvas note cleanup 2022-05-19 23:00:07 +02:00
zadam a1d1b4580a Merge remote-tracking branch 'origin/stable' 2022-05-18 23:00:49 +02:00
zadam 9e089cc7cd disable COEP, fixes #2858 2022-05-18 22:56:29 +02:00
zadam cd622cbdd7 find widget refactoring to use note context 2022-05-17 23:53:35 +02:00
zadam 4978a3ff1a find widget improvements 2022-05-17 23:22:28 +02:00
zadam fca0b82610 find widget fixes 2022-05-17 22:11:45 +02:00
zadam 6cef1082b2 Merge remote-tracking branch 'origin/stable' into custom-search-dialog 2022-05-17 22:07:11 +02:00
zadam 37eb16b2f3 moved protected session expiration scheduling #2855 2022-05-17 20:39:37 +02:00
zadam c24c807921 delay protected session expiration check after DB init, fixes #2855 2022-05-17 20:39:37 +02:00
zadam 5bc629d1c7 moved protected session expiration scheduling #2855 2022-05-17 20:39:21 +02:00
zadam 04379b4e1f delay protected session expiration check after DB init, fixes #2855 2022-05-17 20:22:33 +02:00
zadam c51e6107a1 findwidget cleanup 2022-05-16 23:56:43 +02:00
zadam bb7ad496bf findwidget cleanup 2022-05-15 22:51:26 +02:00
zadam c50d8e85dc findwidget cleanup 2022-05-15 21:03:51 +02:00
zadam 1d8664927d Merge branch 'master' into custom-search-dialog 2022-05-15 20:35:26 +02:00
zadam dbb5d02ecf log the time spent during optimization process 2022-05-15 20:34:47 +02:00
zadam 593a275795 added #titleTemplate, closes #2852 2022-05-15 15:21:35 +02:00
zadam 6778e1e60e findwidget cleanup 2022-05-15 12:09:30 +02:00
zadam 36308c307b findwidget cleanup 2022-05-14 22:33:45 +02:00
zadam 078fc420b0 findwidget merge from upstream 2022-05-14 21:06:14 +02:00
zadam 8ec814c29f Merge branch 'master' into custom-search-dialog
# Conflicts:
#	docs/frontend_api/FrontendScriptApi.html
#	package-lock.json
#	package.json
2022-05-14 20:50:43 +02:00
zadam e87e065100 protected session expiration timer moved to backend, closes #2847 2022-05-13 23:20:56 +02:00
zadam 8318ab7ac0 added triggerCommand and triggerEvent into frontend API 2022-05-13 22:33:57 +02:00
zadam 87b75a9a22 Merge pull request #2798 from thfrei/excalidraw
New note type `canvas-note` using excalidraw (hand drawn notes, sketching, pen)
2022-05-12 23:48:16 +02:00
zadam 8df3b0a5bd Merge branch 'master' into excalidraw 2022-05-12 23:46:52 +02:00
zadam 6906c82408 changed regex operator to %= 2022-05-11 23:19:32 +02:00
zadam 45edef2d71 new ~ operator in search for regex 2022-05-11 23:06:14 +02:00
zadam bf49648896 allow operators =, *= and =* on note content 2022-05-11 22:43:21 +02:00
zadam 91d23c540a refactored note_content_protected_fulltext.js and note_content_unprotected_fulltext.js into one class 2022-05-11 21:33:41 +02:00
Tom 1cbf918024 update comment and discussion about canvas note 2022-05-11 09:29:54 +02:00
Tom 26f3c1d453 rename canvas_note_share to canvas_share to align witih refactor 2022-05-11 09:06:30 +02:00
zadam c421ee79b0 increase DB version 2022-05-10 23:47:25 +02:00
zadam 77f8474d83 don't fill recent notes into entity_changes
(cherry picked from commit 963c18b8e4)
2022-05-10 23:45:28 +02:00
zadam 9a04a76672 remove recent notes from entity changes migration, #2842
(cherry picked from commit bbbad67764)
2022-05-10 23:45:28 +02:00
zadam 963c18b8e4 don't fill recent notes into entity_changes 2022-05-10 23:45:06 +02:00
zadam bbbad67764 remove recent notes from entity changes migration, #2842 2022-05-10 23:42:28 +02:00
Tom 3491e71084 handle note.type changing 2022-05-10 13:53:50 +02:00
Tom c85f70e197 remove obsolete errorSvg 2022-05-10 13:47:43 +02:00
Tom 3df712b64f refactor canvas-note to canvas 2022-05-10 13:43:05 +02:00
Tom 160bd0a790 remove commented logs to clean up code 2022-05-10 13:32:25 +02:00
Tom 81e0c6dcc2 simplify code 2022-05-10 13:29:24 +02:00
Tom 11bd48a1b5 rename ExcalidrawReactApp() to createExcalidrawReactApp() 2022-05-10 13:28:14 +02:00
Tom 61657087f5 move debounce to library, remove unnecessary binds, replaceassets only for canvas 2022-05-10 13:26:29 +02:00
zadam 87f436c6ea search dialog WIP from custom widget from antoniotejada 2022-05-09 23:13:34 +02:00
Tom 065e4f55c3 remove logs, add explanation to collab 2022-05-09 17:25:20 +02:00
Tom 92adcf82e4 remove debug helper with uniqueId 2022-05-09 17:05:49 +02:00
Tom 06e0f2418c remove magic constants for scene_version and give them a name 2022-05-09 17:00:24 +02:00
Tom 35c4c61d15 sync canvas icon of tree_context_menu 2022-05-09 16:57:23 +02:00
Tom a168edb168 move sleep to general utisl function 2022-05-09 16:54:43 +02:00
Tom d2975bbd21 remove obsolete comments 2022-05-09 16:47:40 +02:00
Tom 358e8c548c remove branch bugfix 2022-05-09 16:47:28 +02:00
Tom f85ed672cc moving canvas_note_share to src/share and add routes 2022-05-09 16:38:23 +02:00
Tom 83f1a68bfd fix errorSvg.js path 2022-05-09 16:26:30 +02:00
Tom 552e5d7d06 typo in note.type 2022-05-09 16:18:06 +02:00
Tom 9c7f8cf5d8 extract errorSvg 2022-05-09 16:17:37 +02:00
Tom f0f9274a3c remove route without filename 2022-05-09 16:17:14 +02:00
Tom 65c725c21e add jsdoc to indicate possibility to use getContent async 2022-05-09 16:14:03 +02:00
Tom dfa30358c5 ensure external assets in excalidraw are avoided 2022-05-09 16:08:56 +02:00
Tom 2394fe6ed9 reduce redundant package version to simplify upgrade 2022-05-09 15:16:12 +02:00
Tom 6cae68288d adhere to convention, prefixing jquery objects with $ and dom not 2022-05-09 15:15:07 +02:00
zadam 83afb89a16 lib upgrades 2022-05-03 23:53:46 +02:00
zadam 93cc6b12ec added new APIs to access note detail, #2806 2022-05-03 23:25:28 +02:00
Tom dc35df9f63 optimize canvas_note share to make it more clear about view mode and excalidraw 2022-05-03 22:44:52 +02:00
Tom 1a4bc0b989 clean up code 2022-05-03 22:06:24 +02:00
Tom a37d75a08f upd package-lock version 2022-05-03 22:01:53 +02:00
Tom 8d510a3fdd Merge remote-tracking branch 'upstream/master' into excalidraw
conflict in
- package-lock (accept incoming),
- routes (remove the option to have image without filename, since it is not really necessary for canvas_note)
- note_detail
2022-05-03 21:56:52 +02:00
Matt 7bcd1c3009 Add download button to shared canvases (#7)
thx @sigaloid 

* Add download button to shared canvases
* Update canvas_note_share.js
* Update canvas_note_share.js
* Update canvas_note_share.js
* Change to more accurate language
2022-05-03 21:43:26 +02:00
zadam 5dab189815 recovery for tree cycle errors, #2831 2022-05-03 00:30:09 +02:00
zadam a9dc62505d fix height of textarea of SQL console 2022-05-02 21:23:40 +02:00
zadam 26e1ff4e16 release 0.51.2
Publish Docker image / Push Docker image to multiple registries (push) Failing after 38s
2022-05-01 23:18:35 +02:00
zadam b3763eed61 make sure shaca is loaded before any request 2022-05-01 23:16:47 +02:00
zadam f9c01851ef fix missing closing div tag in word count demo widget, closes #2829 2022-05-01 22:47:26 +02:00
zadam 6b61b0604a improve hiding of edit button #2787 2022-05-01 22:44:23 +02:00
zadam f705c432fd allow combining tokens in text and title/attributes, fixes #2820 2022-04-29 22:59:00 +02:00
zadam 70edd9a210 allow searching within mermaid diagrams, closes #2821 2022-04-29 22:36:05 +02:00
zadam 0a45b58784 fix doubling of icon tooltips, closes #2811 2022-04-24 13:23:01 +02:00
zadam dbd312c88d addTextToEditor appends text to the end instead of the beginning 2022-04-23 23:07:08 +02:00
zadam 11578b1bc3 fix "isActive()" detection to work well with splits, #2806 2022-04-23 23:06:42 +02:00
Tom 4e4010e15e update styles, fix share view 2022-04-19 21:46:25 +02:00
Tom 6bdaf050c5 replace excalidraw.com asset in svg with EXCALIDRAW_ASSET_PATH, clean up code 2022-04-19 14:39:53 +02:00
Tom 05c8c6cfaa set express same as master 4.17.3 2022-04-19 00:24:41 +02:00
Tom 2441515666 set EXCALIDRAW_ASSET_PATH to avoid loading from unpkg.com 2022-04-19 00:21:29 +02:00
Tom c42bcd6c59 remove icon-set so long as not clear how to use (preferably use special trilium note!) 2022-04-19 00:21:29 +02:00
Tom fc95bb8f18 add onLinkHandler experimental 2022-04-19 00:21:29 +02:00
Tom cb88f316db basic share view render (css wrong) 2022-04-19 00:21:29 +02:00
Tom e19ddc10d3 make revision and renderer svg to shrink to box but not enlarge 2022-04-19 00:21:29 +02:00
Tom d3e86acfaa explain checkFullHeight() due to missleading name 2022-04-19 00:21:29 +02:00
Tom 536643ed3b add undefined check for branch
unclear why this happens
2022-04-19 00:21:29 +02:00
Tom 9771b441ad missing path2d support for freedawings, remove node-side rendering, allow async getContent()
* ## Excalidraw and SVG
 * 2022-04-16 - @thfrei
 *
 * Known issues:
 *  - excalidraw-to-svg (node.js) does not render any hand drawn (freedraw) paths. There is an issue with
 *    Path2D object not present in node-canvas library used by jsdom. (See Trilium PR for samples and other issues
 *    in respective library. Link will be added later). Related links:
 *     - https://github.com/Automattic/node-canvas/pull/2013
 *     - https://github.com/google/canvas-5-polyfill
 *     - https://github.com/Automattic/node-canvas/issues/1116
 *     - https://www.npmjs.com/package/path2d-polyfill
 *  - excalidraw-to-svg (node.js) takes quite some time to load an image (1-2s)
 *  - excalidraw-utils (browser) does render freedraw, however NOT freedraw with background
 *
 * Due to this issues, we opt to use **only excalidraw in the frontend**. Upon saving, we will also get the SVG
 * output from the live excalidraw instance. We will save this **SVG side by side the native excalidraw format
 * in the trilium note**.
 *
 * Pro: we will combat bit-rot. Showing the SVG will be very fast, since it is already rendered.
 * Con: The note will get bigger (maybe +30%?), we will generate more bandwith.
 *      (However, using trilium desktop instance, does not care too much about bandwidth. Size increase is probably
 *       acceptable, as a trade off.)
2022-04-19 00:21:20 +02:00
Tom c295fdb142 rename excalidraw icon libraries 2022-04-19 00:20:21 +02:00
Tom Free ee7aa3d3da remove manually added, static libraries for excalidraw, react, etc. 2022-04-19 00:20:21 +02:00
Tom Free e437a9d70f note about buggy excalidraw-utils for browser svg rendering 2022-04-19 00:20:21 +02:00
Tom Free a8655fcd27 add canvas-note-type at some missing places after rebase 2022-04-19 00:20:21 +02:00
Tom aefc9f1593 add excalidraw excalidraw/utils, react and react-dom as npm-dependencies 2022-04-19 00:20:13 +02:00
Tom Free 73671671d7 remove obsolete fabric/hammer/jquery from canvas-note early trials 2022-04-19 00:17:39 +02:00
Tom f53a93e828 make :filename for GETing an image optional 2022-04-19 00:17:39 +02:00
Tom e156c6292b improve status 500 for canvas-note api/image.js 2022-04-19 00:17:39 +02:00
Tom e365521d5e add support for sharing canvas-note 2022-04-19 00:17:39 +02:00
Tom f354821f25 basic support for using api/images with canvas-note
http://localhost:8080/api/images/<noteId>/some-rando-text
2022-04-19 00:17:16 +02:00
Tom 82e278a2a2 add comment about excalidraw-error message on insert 2022-04-19 00:13:27 +02:00
Thomas Frei b4d4606c73 add a selection of excalidraw-drawing-libraries 2022-04-19 00:13:27 +02:00
Thomas Frei b14b7b6ad1 add _meta to note, in case it got changed to type json 2022-04-19 00:13:27 +02:00
Thomas Frei 32aa7bb540 ensure that fresh note has empty scene, no bleeding 2022-04-19 00:13:27 +02:00
Thomas Frei 300f4ad357 remove obsolete comments / code 2022-04-19 00:13:27 +02:00
Tom cf6b5c3b6e ensure only active/referenced files are saved 2022-04-19 00:13:27 +02:00
Tom f1c9dda366 make sure nothing breaks on fresh empty note or note that has already content 2022-04-19 00:13:27 +02:00
Tom 7f01032b6d add support for render excalidraw in book view (copy of note_revision)
maybe one should think about extract a function there and make it reusable
2022-04-19 00:13:27 +02:00
Tom f08afd4723 remove empty line break 2022-04-19 00:13:27 +02:00
Tom afe2a03aef fix initial load and safe issue by storing noteId 2022-04-19 00:13:27 +02:00
Tom 272bb136d8 make canvas_note height 100% 2022-04-19 00:13:27 +02:00
Tom 27d0388d79 add some comments 2022-04-19 00:13:26 +02:00
Tom 025032de42 make note revisions work 2022-04-19 00:13:26 +02:00
Tom 15a3b42124 remove some debug/testing code 2022-04-19 00:13:26 +02:00
Tom 4266156cee fix curser mismatch by manually setting offset 2022-04-19 00:13:26 +02:00
Tom 45a66ab694 some notes about loading and container width 2022-04-19 00:13:26 +02:00
Tom 49f4ce7149 example for trilium image-link usage and svg export 2022-04-19 00:13:26 +02:00
Tom 220df662ad make pasted images in excalidraw work (save and load "files") 2022-04-19 00:13:26 +02:00
Tom 6e535bac05 ensure isNewSceneVersion() does not increment currentVersion 2022-04-19 00:13:26 +02:00
Tom 3b1dcc7199 compare sceneVersion to omit unnecessary save/reloads of content 2022-04-19 00:13:26 +02:00
Tom ae75ac424f add noteid to console to differentiate logs 2022-04-19 00:13:26 +02:00
Tom 5c46fe792d use widget element to render for multiple excalidraw instances 2022-04-19 00:13:26 +02:00
Tom a33b0f1e1c updated react unmounting 2022-04-19 00:13:26 +02:00
Tom bd28ed07d7 working canvas_note PoC save and load for one note 2022-04-19 00:13:26 +02:00
Tom 12185fbd32 optimized canvas placement in trilium 2022-04-19 00:13:26 +02:00
Tom 24911da8db use react production build 2022-04-19 00:13:26 +02:00
Tom da84d16421 excalidraw include works, removed infinitedrawingcanvas 2022-04-19 00:13:26 +02:00
thfrei 53666cbfe8 lint 2022-04-19 00:13:26 +02:00
thfrei 8897d98bd9 add note-detail height to make canvas visible
due to some upstream changes, this was necessary.
otherwise complete inside container was not visible.
2022-04-19 00:13:26 +02:00
thfrei 93e485cea9 remove console.image 2022-04-19 00:13:26 +02:00
thfrei 22363f5b74 working trilium canvas note 2022-04-19 00:13:26 +02:00
thfrei 2a2c82cd29 minor update for canvas 2022-04-19 00:13:26 +02:00
thfrei 5ebe717da8 basic infinite-drawing-canvas integration 2022-04-19 00:13:26 +02:00
thfrei 2f2d8327e4 update libraries 2022-04-19 00:13:26 +02:00
Tom Free a894c19c2b add missing canvas-note entries in helper functions
Conflicts:
	src/public/app/entities/note_short.js
	src/public/app/services/tree_context_menu.js
2022-04-19 00:13:26 +02:00
Tom Free 0469962c5e wip: canvas-note patch
Conflicts:
	src/public/app/services/library_loader.js
	src/public/app/services/tree_context_menu.js
	src/public/app/widgets/note_actions.js
	src/services/consistency_checks.js
	src/services/utils.js
2022-04-19 00:13:26 +02:00
267 changed files with 14814 additions and 6232 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ image:
file: .gitpod.dockerfile
tasks:
- before: nvm install 16.14.2 && nvm use 16.14.2
- before: nvm install 16.15.0 && nvm use 16.15.0
init: npm install
command: npm run start-server
+1 -6
View File
@@ -3,12 +3,7 @@
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="openjdk-18" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="SwUserDefinedSpecifications">
<option name="specTypeByUrl">
<map />
</option>
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
if wget --spider -S "127.0.0.1:8080/api/health-check" 2>&1 | awk 'NR==2' | grep -w "HTTP/1.1 200 OK" ; then
exit 0
else
exit 1
fi
+10 -3
View File
@@ -1,5 +1,5 @@
# !!! Don't try to build this Dockerfile directly, run it through bin/build-docker.sh script !!!
FROM node:16.14.2-alpine
FROM node:16.15.0-alpine
# Create app directory
WORKDIR /usr/src/app
@@ -21,10 +21,17 @@ RUN set -x \
&& npm install --production \
&& apk del .build-dependencies
# Some setup tools need to be kept
RUN apk add --no-cache su-exec shadow
# Bundle app source
COPY . .
USER node
# Add application user and setup proper volume permissions
RUN adduser -s /bin/false node; exit 0
# Start the application
EXPOSE 8080
CMD [ "node", "./src/www" ]
CMD [ "./start-docker.sh" ]
HEALTHCHECK CMD sh DockerHealthcheck.sh
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
PKG_DIR=dist/trilium-linux-x64-server
NODE_VERSION=16.14.2
NODE_VERSION=16.15.0
if [ "$1" != "DONTCOPY" ]
then
+2 -2
View File
@@ -5,7 +5,7 @@ if [[ $# -eq 0 ]] ; then
exit 1
fi
n exec 16.14.2 npm run webpack
n exec 16.15.0 npm run webpack
DIR=$1
@@ -30,7 +30,7 @@ cp -r electron.js $DIR/
cp webpack-* $DIR/
# run in subshell (so we return to original dir)
(cd $DIR && n exec 16.14.2 npm install --only=prod)
(cd $DIR && n exec 16.15.0 npm install --only=prod)
# cleanup of useless files in dependencies
rm -r $DIR/node_modules/image-q/demo
BIN
View File
Binary file not shown.
@@ -0,0 +1,2 @@
-- removing potential remnants of recent notes in entity changes, see https://github.com/zadam/trilium/issues/2842
DELETE FROM entity_changes WHERE entityName = 'recent_notes';
@@ -0,0 +1,2 @@
UPDATE attributes SET value = replace(value, 'setLabelValue', 'updateLabelValue') WHERE name = 'action' AND type = 'label';
UPDATE attributes SET value = replace(value, 'setRelationTarget', 'updateRelationTarget') WHERE name = 'action' AND type = 'label';
+568 -2
View File
@@ -139,10 +139,576 @@
<h3 class="subsection-title">Members</h3>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -267,7 +833,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd>
@@ -355,7 +921,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd>
+602 -5
View File
@@ -223,6 +223,69 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="isInheritable"><span class="type-signature"></span>isInheritable<span class="type-signature"> :boolean</span></h4>
@@ -703,6 +766,362 @@ and relation (representing named relationship between source and target note)</d
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
@@ -757,7 +1176,7 @@ and relation (representing named relationship between source and target note)</d
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line114">line 114</a>
<a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line115">line 115</a>
</li></ul></dd>
@@ -808,6 +1227,95 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
@@ -862,7 +1370,7 @@ and relation (representing named relationship between source and target note)</d
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line121">line 121</a>
<a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line122">line 122</a>
</li></ul></dd>
@@ -913,6 +1421,95 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -967,7 +1564,7 @@ and relation (representing named relationship between source and target note)</d
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line136">line 136</a>
<a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line137">line 137</a>
</li></ul></dd>
@@ -1144,7 +1741,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd>
@@ -1237,7 +1834,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd>
+72
View File
@@ -131,6 +131,78 @@
<h4 class="name" id="__private"><span class="type-signature"></span>__private<span class="type-signature"> :Object</span></h4>
<div class="description">
This object contains "at your risk" and "no BC guarantees" objects for advanced use cases.
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Object</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line435">line 435</a>
</li></ul></dd>
</dl>
<h4 class="name" id="axios"><span class="type-signature"></span>axios<span class="type-signature"></span></h4>
+599 -2
View File
@@ -155,6 +155,69 @@ parents.</div>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="branchId"><span class="type-signature"></span>branchId<span class="type-signature"> :string</span></h4>
@@ -751,6 +814,184 @@ parents.</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
@@ -955,6 +1196,362 @@ parents.</div>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -1084,7 +1681,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd>
@@ -1177,7 +1774,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd>
+599 -2
View File
@@ -160,6 +160,69 @@ from tokenHash and token.</div>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="etapiTokenId"><span class="type-signature"></span>etapiTokenId<span class="type-signature"> :string</span></h4>
@@ -572,6 +635,540 @@ from tokenHash and token.</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -701,7 +1298,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd>
@@ -794,7 +1391,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd>
+980 -689
View File
File diff suppressed because it is too large Load Diff
+599 -2
View File
@@ -155,6 +155,69 @@ It's used for seamless note versioning.</div>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="contentLength"><span class="type-signature"></span>contentLength<span class="type-signature"> :number</span></h4>
@@ -975,6 +1038,362 @@ It's used for seamless note versioning.</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
@@ -1179,6 +1598,184 @@ It's used for seamless note versioning.</div>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -1414,7 +2011,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd>
@@ -1507,7 +2104,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd>
+599 -2
View File
@@ -154,6 +154,69 @@
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="isSynced"><span class="type-signature"></span>isSynced<span class="type-signature"> :boolean</span></h4>
@@ -430,6 +493,540 @@
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -559,7 +1156,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd>
@@ -652,7 +1249,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd>
+599 -2
View File
@@ -154,6 +154,69 @@
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="noteId"><span class="type-signature"></span>noteId<span class="type-signature"> :string</span></h4>
@@ -362,6 +425,540 @@
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -491,7 +1088,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd>
@@ -584,7 +1181,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd>
@@ -42,16 +42,19 @@ let becca = null;
* Base class for all backend entities.
*/
class AbstractEntity {
/** @protected */
beforeSaving() {
this.generateIdIfNecessary();
}
/** @protected */
generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId();
}
}
/** @protected */
generateHash(isDeleted = false) {
let contentToHash = "";
@@ -66,10 +69,12 @@ class AbstractEntity {
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated;
}
/** @protected */
get becca() {
if (!becca) {
becca = require('../becca');
@@ -78,6 +83,7 @@ class AbstractEntity {
return becca;
}
/** @protected */
addEntityChange(isDeleted = false) {
entityChangesService.addEntityChange({
entityName: this.constructor.entityName,
@@ -89,6 +95,7 @@ class AbstractEntity {
});
}
/** @protected */
getPojoToSave() {
return this.getPojo();
}
@@ -90,6 +90,7 @@ class Attribute extends AbstractEntity {
return this;
}
init() {
if (this.attributeId) {
this.becca.attributes[this.attributeId] = this;
+15 -4
View File
@@ -33,9 +33,9 @@ const AbstractEntity = require("./abstract_entity");
const sql = require("../../services/sql");
const dateUtils = require("../../services/date_utils");
const utils = require("../../services/utils.js");
const TaskContext = require("../../services/task_context.js");
const cls = require("../../services/cls.js");
const log = require("../../services/log.js");
const TaskContext = require("../../services/task_context");
const cls = require("../../services/cls");
const log = require("../../services/log");
/**
* Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple
@@ -165,6 +165,18 @@ class Branch extends AbstractEntity {
taskContext.increaseProgressCount();
const note = this.getNote();
if (!taskContext.noteDeletionHandlerTriggered) {
const parentBranches = note.getParentBranches();
if (parentBranches.length === 1 &amp;&amp; parentBranches[0] === this) {
// needs to be run before branches and attributes are deleted and thus attached relations disappear
const handlers = require("../../services/handlers");
handlers.runAttachedRelations(note, 'runOnNoteDeletion', note);
}
}
if (this.branchId === 'root'
|| this.noteId === 'root'
|| this.noteId === cls.getHoistedNoteId()) {
@@ -174,7 +186,6 @@ class Branch extends AbstractEntity {
this.markAsDeleted(deleteId);
const note = this.getNote();
const notDeletedBranches = note.getParentBranches();
if (notDeletedBranches.length === 0) {
+114 -22
View File
@@ -36,7 +36,10 @@ const dateUtils = require('../../services/date_utils');
const entityChangesService = require('../../services/entity_changes');
const AbstractEntity = require("./abstract_entity");
const NoteRevision = require("./note_revision");
const TaskContext = require("../../services/task_context.js");
const TaskContext = require("../../services/task_context");
const dayjs = require("dayjs");
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
const LABEL = 'label';
const RELATION = 'relation';
@@ -112,13 +115,17 @@ class Note extends AbstractEntity {
}
init() {
/** @type {Branch[]} */
/** @type {Branch[]}
* @private */
this.parentBranches = [];
/** @type {Note[]} */
/** @type {Note[]}
* @private */
this.parents = [];
/** @type {Note[]} */
/** @type {Note[]}
* @private*/
this.children = [];
/** @type {Attribute[]} */
/** @type {Attribute[]}
* @private */
this.ownedAttributes = [];
/** @type {Attribute[]|null}
@@ -128,7 +135,8 @@ class Note extends AbstractEntity {
* @private*/
this.inheritableAttributeCache = null;
/** @type {Attribute[]} */
/** @type {Attribute[]}
* @private*/
this.targetRelations = [];
this.becca.addNote(this.noteId, this);
@@ -142,16 +150,19 @@ class Note extends AbstractEntity {
/**
* size of the content in bytes
* @type {int|null}
* @private
*/
this.contentSize = null;
/**
* size of the content and note revision contents in bytes
* @type {int|null}
* @private
*/
this.noteSize = null;
/**
* number of note revisions for this note
* @type {int|null}
* @private
*/
this.revisionCount = null;
}
@@ -253,6 +264,22 @@ class Note extends AbstractEntity {
WHERE noteId = ?`, [this.noteId]);
}
get dateCreatedObj() {
return this.dateCreated === null ? null : dayjs(this.dateCreated);
}
get utcDateCreatedObj() {
return this.utcDateCreated === null ? null : dayjs.utc(this.utcDateCreated);
}
get dateModifiedObj() {
return this.dateModified === null ? null : dayjs(this.dateModified);
}
get utcDateModifiedObj() {
return this.utcDateModified === null ? null : dayjs.utc(this.utcDateModified);
}
/** @returns {*} */
getJsonContent() {
const content = this.getContent();
@@ -266,7 +293,7 @@ class Note extends AbstractEntity {
setContent(content, ignoreMissingProtectedSession = false) {
if (content === null || content === undefined) {
throw new Error(`Cannot set null content to note ${this.noteId}`);
throw new Error(`Cannot set null content to note '${this.noteId}'`);
}
if (this.isStringNote()) {
@@ -288,7 +315,7 @@ class Note extends AbstractEntity {
pojo.content = protectedSessionService.encrypt(pojo.content);
}
else if (!ignoreMissingProtectedSession) {
throw new Error(`Cannot update content of noteId=${this.noteId} since we're out of protected session.`);
throw new Error(`Cannot update content of noteId '${this.noteId}' since we're out of protected session.`);
}
}
@@ -378,6 +405,7 @@ class Note extends AbstractEntity {
}
}
/** @private */
__getAttributes(path) {
if (path.includes(this.noteId)) {
return [];
@@ -400,7 +428,11 @@ class Note extends AbstractEntity {
const templateNote = this.becca.notes[ownedAttr.value];
if (templateNote) {
templateAttributes.push(...templateNote.__getAttributes(newPath));
templateAttributes.push(
...templateNote.__getAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' &amp;&amp; attr.name === 'template'))
);
}
}
}
@@ -429,7 +461,10 @@ class Note extends AbstractEntity {
return this.__attributeCache;
}
/** @returns {Attribute[]} */
/**
* @private
* @returns {Attribute[]}
*/
__getInheritableAttributes(path) {
if (path.includes(this.noteId)) {
return [];
@@ -442,8 +477,12 @@ class Note extends AbstractEntity {
return this.inheritableAttributeCache;
}
hasAttribute(type, name) {
return !!this.getAttributes().find(attr => attr.type === type &amp;&amp; attr.name === name);
hasAttribute(type, name, value) {
return !!this.getAttributes().find(attr =>
attr.type === type
&amp;&amp; attr.name === name
&amp;&amp; (value === undefined || value === null || attr.value === value)
);
}
getAttributeCaseInsensitive(type, name, value) {
@@ -464,27 +503,31 @@ class Note extends AbstractEntity {
/**
* @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (including inherited)
*/
hasLabel(name) { return this.hasAttribute(LABEL, name); }
hasLabel(name, value) { return this.hasAttribute(LABEL, name, value); }
/**
* @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (excluding inherited)
*/
hasOwnedLabel(name) { return this.hasOwnedAttribute(LABEL, name); }
hasOwnedLabel(name, value) { return this.hasOwnedAttribute(LABEL, name, value); }
/**
* @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (including inherited)
*/
hasRelation(name) { return this.hasAttribute(RELATION, name); }
hasRelation(name, value) { return this.hasAttribute(RELATION, name, value); }
/**
* @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (excluding inherited)
*/
hasOwnedRelation(name) { return this.hasOwnedAttribute(RELATION, name); }
hasOwnedRelation(name, value) { return this.hasOwnedAttribute(RELATION, name, value); }
/**
* @param {string} name - label name
@@ -537,10 +580,11 @@ class Note extends AbstractEntity {
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @param {string} [value] - attribute value
* @returns {boolean} true if note has an attribute with given type and name (excluding inherited)
*/
hasOwnedAttribute(type, name) {
return !!this.getOwnedAttribute(type, name);
hasOwnedAttribute(type, name, value) {
return !!this.getOwnedAttribute(type, name, value);
}
/**
@@ -627,15 +671,19 @@ class Note extends AbstractEntity {
/**
* @param {string} [type] - (optional) attribute type to filter
* @param {string} [name] - (optional) attribute name to filter
* @param {string} [value] - (optional) attribute value to filter
* @returns {Attribute[]} note's "owned" attributes - excluding inherited ones
*/
getOwnedAttributes(type, name) {
getOwnedAttributes(type, name, value) {
// it's a common mistake to include # or ~ into attribute name
if (name &amp;&amp; ["#", "~"].includes(name[0])) {
name = name.substr(1);
}
if (type &amp;&amp; name) {
if (type &amp;&amp; name &amp;&amp; value !== undefined &amp;&amp; value !== null) {
return this.ownedAttributes.filter(attr => attr.type === type &amp;&amp; attr.name === name &amp;&amp; attr.value === value);
}
else if (type &amp;&amp; name) {
return this.ownedAttributes.filter(attr => attr.type === type &amp;&amp; attr.name === name);
}
else if (type) {
@@ -654,8 +702,8 @@ class Note extends AbstractEntity {
*
* This method can be significantly faster than the getAttribute()
*/
getOwnedAttribute(type, name) {
const attrs = this.getOwnedAttributes(type, name);
getOwnedAttribute(type, name, value) {
const attrs = this.getOwnedAttributes(type, name, value);
return attrs.length > 0 ? attrs[0] : null;
}
@@ -1161,6 +1209,10 @@ class Note extends AbstractEntity {
* @param {TaskContext} [taskContext]
*/
deleteNote(deleteId, taskContext) {
if (this.isDeleted) {
return;
}
if (!deleteId) {
deleteId = utils.randomString(10);
}
@@ -1169,6 +1221,11 @@ class Note extends AbstractEntity {
taskContext = new TaskContext('no-progress-reporting');
}
// needs to be run before branches and attributes are deleted and thus attached relations disappear
const handlers = require("../../services/handlers");
handlers.runAttachedRelations(this, 'runOnNoteDeletion', this);
taskContext.noteDeletionHandlerTriggered = true;
for (const branch of this.getParentBranches()) {
branch.deleteBranch(deleteId, taskContext);
}
@@ -1192,6 +1249,41 @@ class Note extends AbstractEntity {
return !(this.noteId in this.becca.notes);
}
/**
* @return {NoteRevision|null}
*/
saveNoteRevision() {
const content = this.getContent();
if (!content || (Buffer.isBuffer(content) &amp;&amp; content.byteLength === 0)) {
return null;
}
const contentMetadata = this.getContentMetadata();
const noteRevision = new NoteRevision({
noteId: this.noteId,
// title and text should be decrypted now
title: this.title,
type: this.type,
mime: this.mime,
isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified
? this.utcDateModified
: contentMetadata.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: this.dateModified > contentMetadata.dateModified
? this.dateModified
: contentMetadata.dateModified,
dateCreated: dateUtils.localNowDateTime()
}).save();
noteRevision.setContent(content);
return noteRevision;
}
beforeSaving() {
super.beforeSaving();
+1 -1
View File
@@ -237,7 +237,7 @@
<td class="description last">text, code, file, image, search, book, relation-map - MANDATORY</td>
<td class="description last">text, code, file, image, search, book, relation-map, canvas - MANDATORY</td>
</tr>
@@ -238,7 +238,7 @@ function BackendScriptApi(currentNote, apiParams) {
* @property {string} parentNoteId - MANDATORY
* @property {string} title - MANDATORY
* @property {string|buffer} content - MANDATORY
* @property {string} type - text, code, file, image, search, book, relation-map - MANDATORY
* @property {string} type - text, code, file, image, search, book, relation-map, canvas - MANDATORY
* @property {string} mime - value is derived from default mimes for type
* @property {boolean} isProtected - default is false
* @property {boolean} isExpanded - default is false
@@ -454,6 +454,15 @@ function BackendScriptApi(currentNote, apiParams) {
* @return {{syncVersion, appVersion, buildRevision, dbVersion, dataDirectory, buildDate}|*} - object representing basic info about running Trilium version
*/
this.getAppInfo = () => appInfo
/**
* This object contains "at your risk" and "no BC guarantees" objects for advanced use cases.
*
* @type {{becca: Becca}}
*/
this.__private = {
becca
}
}
module.exports = BackendScriptApi;
+2 -2
View File
@@ -270,9 +270,9 @@ function transactional(func) {
return ret;
}
catch (e) {
const entityChanges = cls.getAndClearEntityChangeIds();
const entityChangeIds = cls.getAndClearEntityChangeIds();
if (entityChanges.length > 0) {
if (entityChangeIds.length > 0) {
log.info("Transaction rollback dirtied the becca, forcing reload.");
require('../becca/becca_loader').load();
+1 -1
View File
@@ -742,7 +742,7 @@ and relation (representing named relationship between source and target note)</d
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+1 -1
View File
@@ -1056,7 +1056,7 @@ parents.</div>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -775,7 +775,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+58 -58
View File
@@ -167,7 +167,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line27">line 27</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line29">line 29</a>
</li></ul></dd>
@@ -267,7 +267,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line36">line 36</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line38">line 38</a>
</li></ul></dd>
@@ -335,7 +335,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line44">line 44</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line46">line 46</a>
</li></ul></dd>
@@ -403,7 +403,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line50">line 50</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line52">line 52</a>
</li></ul></dd>
@@ -471,7 +471,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line61">line 61</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line63">line 63</a>
</li></ul></dd>
@@ -543,7 +543,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line71">line 71</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line73">line 73</a>
</li></ul></dd>
@@ -611,7 +611,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line57">line 57</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line59">line 59</a>
</li></ul></dd>
@@ -679,7 +679,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line42">line 42</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line44">line 44</a>
</li></ul></dd>
@@ -747,7 +747,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line47">line 47</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line49">line 49</a>
</li></ul></dd>
@@ -815,7 +815,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line39">line 39</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line41">line 41</a>
</li></ul></dd>
@@ -883,7 +883,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line59">line 59</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line61">line 61</a>
</li></ul></dd>
@@ -955,7 +955,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line66">line 66</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line68">line 68</a>
</li></ul></dd>
@@ -1103,7 +1103,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line498">line 498</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line504">line 504</a>
</li></ul></dd>
@@ -1303,7 +1303,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line236">line 236</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line238">line 238</a>
</li></ul></dd>
@@ -1481,7 +1481,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line520">line 520</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line526">line 526</a>
</li></ul></dd>
@@ -1589,7 +1589,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line161">line 161</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line163">line 163</a>
</li></ul></dd>
@@ -1693,7 +1693,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line144">line 144</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line146">line 146</a>
</li></ul></dd>
@@ -1795,7 +1795,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line171">line 171</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line173">line 173</a>
</li></ul></dd>
@@ -1897,7 +1897,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line209">line 209</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line211">line 211</a>
</li></ul></dd>
@@ -1999,7 +1999,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line214">line 214</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line216">line 216</a>
</li></ul></dd>
@@ -2150,7 +2150,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line560">line 560</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line566">line 566</a>
</li></ul></dd>
@@ -2317,7 +2317,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line384">line 384</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line390">line 390</a>
</li></ul></dd>
@@ -2472,7 +2472,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line584">line 584</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line590">line 590</a>
</li></ul></dd>
@@ -2582,7 +2582,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line706">line 706</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line717">line 717</a>
</li></ul></dd>
@@ -2756,7 +2756,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line487">line 487</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line493">line 493</a>
</li></ul></dd>
@@ -2956,7 +2956,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line223">line 223</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line225">line 225</a>
</li></ul></dd>
@@ -3134,7 +3134,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line509">line 509</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line515">line 515</a>
</li></ul></dd>
@@ -3289,7 +3289,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line554">line 554</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line560">line 560</a>
</li></ul></dd>
@@ -3456,7 +3456,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line376">line 376</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line382">line 382</a>
</li></ul></dd>
@@ -3611,7 +3611,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line578">line 578</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line584">line 584</a>
</li></ul></dd>
@@ -3766,7 +3766,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line566">line 566</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line572">line 572</a>
</li></ul></dd>
@@ -3933,7 +3933,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line452">line 452</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line458">line 458</a>
</li></ul></dd>
@@ -4088,7 +4088,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line590">line 590</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line596">line 596</a>
</li></ul></dd>
@@ -4194,7 +4194,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line151">line 151</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line153">line 153</a>
</li></ul></dd>
@@ -4296,7 +4296,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line136">line 136</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line138">line 138</a>
</li></ul></dd>
@@ -4398,7 +4398,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line179">line 179</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line181">line 181</a>
</li></ul></dd>
@@ -4500,7 +4500,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line184">line 184</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line186">line 186</a>
</li></ul></dd>
@@ -4651,7 +4651,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line572">line 572</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line578">line 578</a>
</li></ul></dd>
@@ -4818,7 +4818,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line460">line 460</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line466">line 466</a>
</li></ul></dd>
@@ -4973,7 +4973,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line602">line 602</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line608">line 608</a>
</li></ul></dd>
@@ -5143,7 +5143,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line612">line 612</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line618">line 618</a>
</li></ul></dd>
@@ -5294,7 +5294,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line596">line 596</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line602">line 602</a>
</li></ul></dd>
@@ -5400,7 +5400,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line750">line 750</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line761">line 761</a>
</li></ul></dd>
@@ -5513,7 +5513,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line685">line 685</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line696">line 696</a>
</li></ul></dd>
@@ -5619,7 +5619,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line695">line 695</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line706">line 706</a>
</li></ul></dd>
@@ -5721,7 +5721,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line626">line 626</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line632">line 632</a>
</li></ul></dd>
@@ -5895,7 +5895,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line469">line 469</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line475">line 475</a>
</li></ul></dd>
@@ -6001,7 +6001,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line166">line 166</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line168">line 168</a>
</li></ul></dd>
@@ -6152,7 +6152,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line536">line 536</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line542">line 542</a>
</li></ul></dd>
@@ -6330,7 +6330,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line478">line 478</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line484">line 484</a>
</li></ul></dd>
@@ -6485,7 +6485,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line530">line 530</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line536">line 536</a>
</li></ul></dd>
@@ -6640,7 +6640,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line542">line 542</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line548">line 548</a>
</li></ul></dd>
@@ -6795,7 +6795,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line548">line 548</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line554">line 554</a>
</li></ul></dd>
@@ -6903,7 +6903,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line678">line 678</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line689">line 689</a>
</li></ul></dd>
@@ -6987,7 +6987,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line745">line 745</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line756">line 756</a>
</li></ul></dd>
@@ -7093,7 +7093,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line737">line 737</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line748">line 748</a>
</li></ul></dd>
@@ -7199,7 +7199,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line109">line 109</a>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line111">line 111</a>
</li></ul></dd>
@@ -7263,7 +7263,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+1 -1
View File
@@ -104,7 +104,7 @@ export default Attribute;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+1 -1
View File
@@ -93,7 +93,7 @@ export default Branch;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
@@ -76,7 +76,7 @@ export default NoteComplement;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+16 -5
View File
@@ -44,7 +44,9 @@ const NOTE_TYPE_ICONS = {
"relation-map": "bx bx-map-alt",
"book": "bx bx-book",
"note-map": "bx bx-map-alt",
"mermaid": "bx bx-selection"
"mermaid": "bx bx-selection",
"canvas": "bx bx-pen",
"web-view": "bx bx-globe-alt"
};
/**
@@ -152,7 +154,7 @@ class NoteShort {
return JSON.parse(content);
}
catch (e) {
console.log(`Cannot parse content of note ${this.noteId}: `, e.message);
console.log(`Cannot parse content of note '${this.noteId}': `, e.message);
return null;
}
@@ -289,7 +291,11 @@ class NoteShort {
const templateNote = this.froca.notes[templateAttr.value];
if (templateNote &amp;&amp; templateNote.noteId !== this.noteId) {
attrArrs.push(templateNote.__getCachedAttributes(newPath));
attrArrs.push(
templateNote.__getCachedAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' &amp;&amp; attr.name === 'template'))
);
}
}
@@ -662,13 +668,18 @@ class NoteShort {
return [];
}
return this.getAttributes()
const promotedAttrs = this.getAttributes()
.filter(attr => attr.isDefinition())
.filter(attr => {
const def = attr.getDefinition();
return def &amp;&amp; def.isPromoted;
});
// attrs are not resorted if position changes after initial load
promotedAttrs.sort((a, b) => a.position &lt; b.position ? -1 : 1);
return promotedAttrs;
}
hasAncestor(ancestorNoteId, visitedNoteIds = null) {
@@ -842,7 +853,7 @@ export default NoteShort;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+3 -3
View File
@@ -156,7 +156,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line34">line 34</a>
<a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line37">line 37</a>
</li></ul></dd>
@@ -395,7 +395,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line104">line 104</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line124">line 124</a>
</li></ul></dd>
@@ -425,7 +425,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+1 -1
View File
@@ -50,7 +50,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
@@ -129,6 +129,26 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
}
};
/**
* Open a note in a new split.
*
* @param {string} notePath (or noteId)
* @param {boolean} activate - set to true to activate the new split, false to stay on the current split
* @return {Promise&lt;void>}
*/
this.openSplitWithNote = async (notePath, activate) => {
await ws.waitForMaxKnownEntityChangeId();
const subContexts = appContext.tabManager.getActiveContext().getSubContexts();
const {ntxId} = subContexts[subContexts.length - 1];
appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath});
if (activate) {
appContext.triggerEvent('focusAndSelectTitle');
}
};
/**
* @typedef {Object} ToolbarButtonOptions
* @property {string} title
@@ -327,6 +347,24 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*/
this.showError = toastService.showError;
/**
* Trigger command.
*
* @method
* @param {string} name
* @param {object} data
*/
this.triggerCommand = (name, data) => appContext.triggerCommand(name, data);
/**
* Trigger event.
*
* @method
* @param {string} name
* @param {object} data
*/
this.triggerEvent = (name, data) => appContext.triggerEvent(name, data);
/**
* @method
* @deprecated - this is now no-op since all the changes should be gracefully handled per widget
@@ -349,30 +387,104 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Adds given text to the editor cursor
*
* @deprecated use addTextToActiveContextEditor() instead
* @param {string} text - this must be clear text, HTML is not supported.
* @method
*/
this.addTextToActiveTabEditor = text => appContext.triggerCommand('addTextToActiveEditor', {text});
this.addTextToActiveTabEditor = text => {
console.warn("api.addTextToActiveTabEditor() is deprecated, use addTextToActiveContextEditor() instead.");
return appContext.triggerCommand('addTextToActiveEditor', {text});
};
/**
* Adds given text to the editor cursor
*
* @param {string} text - this must be clear text, HTML is not supported.
* @method
*/
this.addTextToActiveContextEditor = text => appContext.triggerCommand('addTextToActiveEditor', {text});
/**
* @method
* @deprecated use getActiveContextNote() instead
* @returns {NoteShort} active note (loaded into right pane)
*/
this.getActiveTabNote = () => {
console.warn("api.getActiveTabNote() is deprecated, use getActiveContextNote() instead.");
return appContext.tabManager.getActiveContextNote();
};
/**
* @method
* @returns {NoteShort} active note (loaded into right pane)
*/
this.getActiveTabNote = () => appContext.tabManager.getActiveContextNote();
this.getActiveContextNote = () => appContext.tabManager.getActiveContextNote();
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
*
* @deprecated use getActiveContextTextEditor()
* @method
* @param [callback] - callback receiving "textEditor" instance
*/
this.getActiveTabTextEditor = callback => {
console.warn("api.getActiveTabTextEditor() is deprecated, use getActiveContextTextEditor() instead.");
return appContext.tabManager.getActiveContext()?.getTextEditor(callback);
};
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
*
* @method
* @param callback - method receiving "textEditor" instance
* @returns {Promise&lt;CKEditor>} instance of CKEditor
*/
this.getActiveTabTextEditor = callback => appContext.triggerCommand('executeInActiveEditor', {callback});
this.getActiveContextTextEditor = () => appContext.tabManager.getActiveContext()?.getTextEditor();
/**
* See https://codemirror.net/doc/manual.html#api
*
* @method
* @returns {Promise&lt;CodeMirror>} instance of CodeMirror
*/
this.getActiveContextCodeEditor = () => appContext.tabManager.getActiveContext()?.getCodeEditor();
/**
* Get access to the widget handling note detail. Methods like `getWidgetType()` and `getTypeWidget()` to get to the
* implementation of actual widget type.
*
* @method
* @returns {Promise&lt;NoteDetailWidget>}
*/
this.getActiveNoteDetailWidget = () => new Promise(resolve => appContext.triggerCommand('executeInActiveNoteDetailWidget', {callback: resolve}));
/**
* @method
* @deprecated use getActiveContextNotePath() instead
* @returns {Promise&lt;string|null>} returns note path of active note or null if there isn't active note
*/
this.getActiveTabNotePath = () => {
console.warn("api.getActiveTabNotePath() is deprecated, use getActiveContextNotePath() instead.");
return appContext.tabManager.getActiveContextNotePath();
};
/**
* @method
* @returns {Promise&lt;string|null>} returns note path of active note or null if there isn't active note
*/
this.getActiveTabNotePath = () => appContext.tabManager.getActiveContextNotePath();
this.getActiveContextNotePath = () => appContext.tabManager.getActiveContextNotePath();
/**
* Returns component which owns given DOM element (the nearest parent component in DOM tree)
*
* @method
* @param {Element} el - DOM element
* @returns {Component}
*/
this.getComponentByEl = el => appContext.getComponentByEl(el);
/**
* @method
@@ -523,7 +635,7 @@ export default FrontendScriptApi;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
@@ -37,6 +37,9 @@ const WIDGET_TPL = `
&lt;/div>
&lt;/div>`;
/**
* TODO: rename, it's not collapsible anymore
*/
export default class CollapsibleWidget extends NoteContextAwareWidget {
get widgetTitle() { return "Untitled widget"; }
@@ -60,10 +63,6 @@ export default class CollapsibleWidget extends NoteContextAwareWidget {
/** for overriding */
async doRenderBody() {}
isExpanded() {
return this.$bodyWrapper.hasClass("show");
}
}
</code></pre>
</article>
@@ -75,7 +74,7 @@ export default class CollapsibleWidget extends NoteContextAwareWidget {
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav>
<br class="clear">
+1 -1
View File
@@ -6,7 +6,7 @@ It is meant as a last resort solution when the standard mean to access your data
## Installation
This tool requires node.js, testing has been done on 16.14.2, but it will probably work on other versions as well.
This tool requires node.js, testing has been done on 16.15.0, but it will probably work on other versions as well.
```
npm install
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1019 -1951
View File
File diff suppressed because it is too large Load Diff
+24 -20
View File
@@ -2,7 +2,7 @@
"name": "trilium",
"productName": "Trilium Notes",
"description": "Trilium Notes",
"version": "0.51.1-beta",
"version": "0.53.0-beta",
"license": "AGPL-3.0-only",
"main": "electron.js",
"bin": {
@@ -21,31 +21,33 @@
"webpack": "npx webpack -c webpack-desktop.config.js && npx webpack -c webpack-mobile.config.js && npx webpack -c webpack-setup.config.js",
"test": "jasmine",
"test-es6": "node -r esm spec-es6/attribute_parser.spec.js ",
"test-all": "npm run test && npm run test-es6"
"test-all": "npm run test && npm run test-es6",
"postinstall": "rimraf ./node_modules/canvas"
},
"dependencies": {
"@electron/remote": "2.0.8",
"@excalidraw/excalidraw": "0.11.0",
"archiver": "5.3.1",
"async-mutex": "0.3.2",
"axios": "0.26.1",
"axios": "0.27.2",
"better-sqlite3": "7.4.5",
"chokidar": "3.5.3",
"cls-hooked": "4.2.2",
"commonmark": "0.30.0",
"cookie-parser": "1.4.6",
"csurf": "1.11.0",
"dayjs": "1.11.1",
"ejs": "3.1.6",
"dayjs": "1.11.3",
"dayjs-plugin-utc": "^0.1.2",
"ejs": "3.1.8",
"electron-debug": "3.2.0",
"electron-dl": "3.3.1",
"electron-find": "1.0.7",
"electron-window-state": "5.0.3",
"@electron/remote": "2.0.8",
"express": "4.17.3",
"express": "4.18.1",
"express-partial-content": "1.0.2",
"express-rate-limit": "6.3.0",
"express-session": "1.17.2",
"express-rate-limit": "6.4.0",
"express-session": "1.17.3",
"fs-extra": "10.1.0",
"helmet": "5.0.2",
"helmet": "5.1.0",
"html": "1.0.0",
"html2plaintext": "2.1.4",
"http-proxy-agent": "5.0.0",
@@ -58,12 +60,14 @@
"joplin-turndown-plugin-gfm": "1.0.12",
"jsdom": "19.0.0",
"mime-types": "2.1.35",
"multer": "1.4.4",
"node-abi": "3.15.0",
"multer": "1.4.5-lts.1",
"node-abi": "3.22.0",
"normalize-strings": "1.1.1",
"open": "8.4.0",
"portscanner": "2.2.0",
"rand-token": "1.0.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"request": "2.88.2",
"rimraf": "3.0.2",
"sanitize-filename": "1.6.3",
@@ -77,22 +81,22 @@
"tmp": "0.2.1",
"turndown": "7.1.1",
"unescape": "1.0.1",
"ws": "8.5.0",
"ws": "8.8.0",
"yauzl": "2.10.0"
},
"devDependencies": {
"cross-env": "7.0.3",
"electron": "16.2.1",
"electron": "16.2.8",
"electron-builder": "23.0.3",
"electron-packager": "15.5.0",
"electron-packager": "15.5.1",
"electron-rebuild": "3.2.7",
"esm": "3.2.25",
"jasmine": "4.1.0",
"jasmine": "4.2.0",
"jsdoc": "3.6.10",
"lorem-ipsum": "2.0.4",
"lorem-ipsum": "2.0.8",
"rcedit": "3.0.1",
"webpack": "5.72.0",
"webpack-cli": "4.9.2"
"webpack": "5.73.0",
"webpack-cli": "4.10.0"
},
"optionalDependencies": {
"electron-installer-debian": "3.1.0"
+1 -4
View File
@@ -58,11 +58,8 @@ describe("Parser", () => {
expect(subs[0].constructor.name).toEqual("NoteFlatTextExp");
expect(subs[0].tokens).toEqual(["hello", "hi"]);
expect(subs[1].constructor.name).toEqual("NoteContentProtectedFulltextExp");
expect(subs[1].constructor.name).toEqual("NoteContentFulltextExp");
expect(subs[1].tokens).toEqual(["hello", "hi"]);
expect(subs[2].constructor.name).toEqual("NoteContentUnprotectedFulltextExp");
expect(subs[2].tokens).toEqual(["hello", "hi"]);
});
it("simple label comparison", () => {
+7 -1
View File
@@ -20,7 +20,8 @@ app.set('view engine', 'ejs');
app.use(helmet({
hidePoweredBy: false, // errors out in electron
contentSecurityPolicy: false
contentSecurityPolicy: false,
crossOriginEmbedderPolicy: false
}));
app.use(express.text({limit: '500mb'}));
@@ -30,6 +31,11 @@ app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/libraries', express.static(path.join(__dirname, '..', 'libraries')));
// excalidraw-view mode in shared notes
app.use('/node_modules/react/umd/react.production.min.js', express.static(path.join(__dirname, '..', 'node_modules/react/umd/react.production.min.js')));
app.use('/node_modules/react-dom/umd/react-dom.production.min.js', express.static(path.join(__dirname, '..', 'node_modules/react-dom/umd/react-dom.production.min.js')));
// expose whole dist folder since complete assets are needed in edit and share
app.use('/node_modules/@excalidraw/excalidraw/dist/', express.static(path.join(__dirname, '..', 'node_modules/@excalidraw/excalidraw/dist/')));
app.use('/images', express.static(path.join(__dirname, '..', 'images')));
const sessionParser = session({
secret: sessionSecret,
+7
View File
@@ -14,16 +14,19 @@ let becca = null;
* Base class for all backend entities.
*/
class AbstractEntity {
/** @protected */
beforeSaving() {
this.generateIdIfNecessary();
}
/** @protected */
generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId();
}
}
/** @protected */
generateHash(isDeleted = false) {
let contentToHash = "";
@@ -38,10 +41,12 @@ class AbstractEntity {
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated;
}
/** @protected */
get becca() {
if (!becca) {
becca = require('../becca');
@@ -50,6 +55,7 @@ class AbstractEntity {
return becca;
}
/** @protected */
addEntityChange(isDeleted = false) {
entityChangesService.addEntityChange({
entityName: this.constructor.entityName,
@@ -61,6 +67,7 @@ class AbstractEntity {
});
}
/** @protected */
getPojoToSave() {
return this.getPojo();
}
+1
View File
@@ -62,6 +62,7 @@ class Attribute extends AbstractEntity {
return this;
}
init() {
if (this.attributeId) {
this.becca.attributes[this.attributeId] = this;
+15 -4
View File
@@ -5,9 +5,9 @@ const AbstractEntity = require("./abstract_entity");
const sql = require("../../services/sql");
const dateUtils = require("../../services/date_utils");
const utils = require("../../services/utils.js");
const TaskContext = require("../../services/task_context.js");
const cls = require("../../services/cls.js");
const log = require("../../services/log.js");
const TaskContext = require("../../services/task_context");
const cls = require("../../services/cls");
const log = require("../../services/log");
/**
* Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple
@@ -137,6 +137,18 @@ class Branch extends AbstractEntity {
taskContext.increaseProgressCount();
const note = this.getNote();
if (!taskContext.noteDeletionHandlerTriggered) {
const parentBranches = note.getParentBranches();
if (parentBranches.length === 1 && parentBranches[0] === this) {
// needs to be run before branches and attributes are deleted and thus attached relations disappear
const handlers = require("../../services/handlers");
handlers.runAttachedRelations(note, 'runOnNoteDeletion', note);
}
}
if (this.branchId === 'root'
|| this.noteId === 'root'
|| this.noteId === cls.getHoistedNoteId()) {
@@ -146,7 +158,6 @@ class Branch extends AbstractEntity {
this.markAsDeleted(deleteId);
const note = this.getNote();
const notDeletedBranches = note.getParentBranches();
if (notDeletedBranches.length === 0) {
+118 -20
View File
@@ -8,7 +8,10 @@ const dateUtils = require('../../services/date_utils');
const entityChangesService = require('../../services/entity_changes');
const AbstractEntity = require("./abstract_entity");
const NoteRevision = require("./note_revision");
const TaskContext = require("../../services/task_context.js");
const TaskContext = require("../../services/task_context");
const dayjs = require("dayjs");
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
const LABEL = 'label';
const RELATION = 'relation';
@@ -84,13 +87,17 @@ class Note extends AbstractEntity {
}
init() {
/** @type {Branch[]} */
/** @type {Branch[]}
* @private */
this.parentBranches = [];
/** @type {Note[]} */
/** @type {Note[]}
* @private */
this.parents = [];
/** @type {Note[]} */
/** @type {Note[]}
* @private*/
this.children = [];
/** @type {Attribute[]} */
/** @type {Attribute[]}
* @private */
this.ownedAttributes = [];
/** @type {Attribute[]|null}
@@ -100,7 +107,8 @@ class Note extends AbstractEntity {
* @private*/
this.inheritableAttributeCache = null;
/** @type {Attribute[]} */
/** @type {Attribute[]}
* @private*/
this.targetRelations = [];
this.becca.addNote(this.noteId, this);
@@ -114,16 +122,19 @@ class Note extends AbstractEntity {
/**
* size of the content in bytes
* @type {int|null}
* @private
*/
this.contentSize = null;
/**
* size of the content and note revision contents in bytes
* @type {int|null}
* @private
*/
this.noteSize = null;
/**
* number of note revisions for this note
* @type {int|null}
* @private
*/
this.revisionCount = null;
}
@@ -225,6 +236,22 @@ class Note extends AbstractEntity {
WHERE noteId = ?`, [this.noteId]);
}
get dateCreatedObj() {
return this.dateCreated === null ? null : dayjs(this.dateCreated);
}
get utcDateCreatedObj() {
return this.utcDateCreated === null ? null : dayjs.utc(this.utcDateCreated);
}
get dateModifiedObj() {
return this.dateModified === null ? null : dayjs(this.dateModified);
}
get utcDateModifiedObj() {
return this.utcDateModified === null ? null : dayjs.utc(this.utcDateModified);
}
/** @returns {*} */
getJsonContent() {
const content = this.getContent();
@@ -350,6 +377,7 @@ class Note extends AbstractEntity {
}
}
/** @private */
__getAttributes(path) {
if (path.includes(this.noteId)) {
return [];
@@ -372,7 +400,11 @@ class Note extends AbstractEntity {
const templateNote = this.becca.notes[ownedAttr.value];
if (templateNote) {
templateAttributes.push(...templateNote.__getAttributes(newPath));
templateAttributes.push(
...templateNote.__getAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' && attr.name === 'template'))
);
}
}
}
@@ -401,7 +433,10 @@ class Note extends AbstractEntity {
return this.__attributeCache;
}
/** @returns {Attribute[]} */
/**
* @private
* @returns {Attribute[]}
*/
__getInheritableAttributes(path) {
if (path.includes(this.noteId)) {
return [];
@@ -414,8 +449,18 @@ class Note extends AbstractEntity {
return this.inheritableAttributeCache;
}
hasAttribute(type, name) {
return !!this.getAttributes().find(attr => attr.type === type && attr.name === name);
/**
* @param type
* @param name
* @param [value]
* @returns {boolean}
*/
hasAttribute(type, name, value) {
return !!this.getAttributes().find(attr =>
attr.type === type
&& attr.name === name
&& (value === undefined || value === null || attr.value === value)
);
}
getAttributeCaseInsensitive(type, name, value) {
@@ -436,27 +481,31 @@ class Note extends AbstractEntity {
/**
* @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (including inherited)
*/
hasLabel(name) { return this.hasAttribute(LABEL, name); }
hasLabel(name, value) { return this.hasAttribute(LABEL, name, value); }
/**
* @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (excluding inherited)
*/
hasOwnedLabel(name) { return this.hasOwnedAttribute(LABEL, name); }
hasOwnedLabel(name, value) { return this.hasOwnedAttribute(LABEL, name, value); }
/**
* @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (including inherited)
*/
hasRelation(name) { return this.hasAttribute(RELATION, name); }
hasRelation(name, value) { return this.hasAttribute(RELATION, name, value); }
/**
* @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (excluding inherited)
*/
hasOwnedRelation(name) { return this.hasOwnedAttribute(RELATION, name); }
hasOwnedRelation(name, value) { return this.hasOwnedAttribute(RELATION, name, value); }
/**
* @param {string} name - label name
@@ -509,10 +558,11 @@ class Note extends AbstractEntity {
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @param {string} [value] - attribute value
* @returns {boolean} true if note has an attribute with given type and name (excluding inherited)
*/
hasOwnedAttribute(type, name) {
return !!this.getOwnedAttribute(type, name);
hasOwnedAttribute(type, name, value) {
return !!this.getOwnedAttribute(type, name, value);
}
/**
@@ -599,15 +649,19 @@ class Note extends AbstractEntity {
/**
* @param {string} [type] - (optional) attribute type to filter
* @param {string} [name] - (optional) attribute name to filter
* @param {string} [value] - (optional) attribute value to filter
* @returns {Attribute[]} note's "owned" attributes - excluding inherited ones
*/
getOwnedAttributes(type, name) {
getOwnedAttributes(type, name, value) {
// it's a common mistake to include # or ~ into attribute name
if (name && ["#", "~"].includes(name[0])) {
name = name.substr(1);
}
if (type && name) {
if (type && name && value !== undefined && value !== null) {
return this.ownedAttributes.filter(attr => attr.type === type && attr.name === name && attr.value === value);
}
else if (type && name) {
return this.ownedAttributes.filter(attr => attr.type === type && attr.name === name);
}
else if (type) {
@@ -626,8 +680,8 @@ class Note extends AbstractEntity {
*
* This method can be significantly faster than the getAttribute()
*/
getOwnedAttribute(type, name) {
const attrs = this.getOwnedAttributes(type, name);
getOwnedAttribute(type, name, value) {
const attrs = this.getOwnedAttributes(type, name, value);
return attrs.length > 0 ? attrs[0] : null;
}
@@ -1133,6 +1187,10 @@ class Note extends AbstractEntity {
* @param {TaskContext} [taskContext]
*/
deleteNote(deleteId, taskContext) {
if (this.isDeleted) {
return;
}
if (!deleteId) {
deleteId = utils.randomString(10);
}
@@ -1141,6 +1199,11 @@ class Note extends AbstractEntity {
taskContext = new TaskContext('no-progress-reporting');
}
// needs to be run before branches and attributes are deleted and thus attached relations disappear
const handlers = require("../../services/handlers");
handlers.runAttachedRelations(this, 'runOnNoteDeletion', this);
taskContext.noteDeletionHandlerTriggered = true;
for (const branch of this.getParentBranches()) {
branch.deleteBranch(deleteId, taskContext);
}
@@ -1164,6 +1227,41 @@ class Note extends AbstractEntity {
return !(this.noteId in this.becca.notes);
}
/**
* @return {NoteRevision|null}
*/
saveNoteRevision() {
const content = this.getContent();
if (!content || (Buffer.isBuffer(content) && content.byteLength === 0)) {
return null;
}
const contentMetadata = this.getContentMetadata();
const noteRevision = new NoteRevision({
noteId: this.noteId,
// title and text should be decrypted now
title: this.title,
type: this.type,
mime: this.mime,
isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified
? this.utcDateModified
: contentMetadata.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: this.dateModified > contentMetadata.dateModified
? this.dateModified
: contentMetadata.dateModified,
dateCreated: dateUtils.localNowDateTime()
}).save();
noteRevision.setContent(content);
return noteRevision;
}
beforeSaving() {
super.beforeSaving();
+8 -8
View File
@@ -52,13 +52,13 @@ if (utils.isElectron()) {
title: suggestion,
command: "replaceMisspelling",
spellingSuggestion: suggestion,
uiIcon: "empty"
uiIcon: "bx bx-empty"
});
}
items.push({
title: `Add "${params.misspelledWord}" to dictionary`,
uiIcon: "plus",
uiIcon: "bx bx-plus",
handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
});
@@ -69,7 +69,7 @@ if (utils.isElectron()) {
items.push({
enabled: editFlags.canCut && hasText,
title: `Cut <kbd>${platformModifier}+X`,
uiIcon: "cut",
uiIcon: "bx bx-cut",
handler: () => webContents.cut()
});
}
@@ -78,7 +78,7 @@ if (utils.isElectron()) {
items.push({
enabled: editFlags.canCopy && hasText,
title: `Copy <kbd>${platformModifier}+C`,
uiIcon: "copy",
uiIcon: "bx bx-copy",
handler: () => webContents.copy()
});
}
@@ -86,7 +86,7 @@ if (utils.isElectron()) {
if (!["", "javascript:", "about:blank#blocked"].includes(params.linkURL) && params.mediaType === 'none') {
items.push({
title: `Copy link`,
uiIcon: "copy",
uiIcon: "bx bx-copy",
handler: () => {
electron.clipboard.write({
bookmark: params.linkText,
@@ -100,7 +100,7 @@ if (utils.isElectron()) {
items.push({
enabled: editFlags.canPaste,
title: `Paste <kbd>${platformModifier}+V`,
uiIcon: "paste",
uiIcon: "bx bx-paste",
handler: () => webContents.paste()
});
}
@@ -109,7 +109,7 @@ if (utils.isElectron()) {
items.push({
enabled: editFlags.canPaste,
title: `Paste as plain text <kbd>${platformModifier}+Shift+V`,
uiIcon: "paste",
uiIcon: "bx bx-paste",
handler: () => webContents.pasteAndMatchStyle()
});
}
@@ -122,7 +122,7 @@ if (utils.isElectron()) {
items.push({
enabled: editFlags.canPaste,
title: `Search for "${shortenedSelection}" with DuckDuckGo`,
uiIcon: "search-alt",
uiIcon: "bx bx-search-alt",
handler: () => electron.shell.openExternal(`https://duckduckgo.com/?q=${encodeURIComponent(params.selectionText)}`)
});
}
-24
View File
@@ -1,24 +0,0 @@
import server from "../services/server.js";
import utils from "../services/utils.js";
const $dialog = $("#about-dialog");
const $appVersion = $("#app-version");
const $dbVersion = $("#db-version");
const $syncVersion = $("#sync-version");
const $buildDate = $("#build-date");
const $buildRevision = $("#build-revision");
const $dataDirectory = $("#data-directory");
export async function showDialog() {
const appInfo = await server.get('app-info');
$appVersion.text(appInfo.appVersion);
$dbVersion.text(appInfo.dbVersion);
$syncVersion.text(appInfo.syncVersion);
$buildDate.text(appInfo.buildDate);
$buildRevision.text(appInfo.buildRevision);
$buildRevision.attr('href', 'https://github.com/zadam/trilium/commit/' + appInfo.buildRevision);
$dataDirectory.text(appInfo.dataDirectory);
utils.openDialog($dialog);
}
-131
View File
@@ -1,131 +0,0 @@
import treeService from '../services/tree.js';
import noteAutocompleteService from "../services/note_autocomplete.js";
import utils from "../services/utils.js";
const $dialog = $("#add-link-dialog");
const $form = $("#add-link-form");
const $autoComplete = $("#add-link-note-autocomplete");
const $linkTitle = $("#link-title");
const $addLinkTitleSettings = $("#add-link-title-settings");
const $addLinkTitleRadios = $(".add-link-title-radios");
const $addLinkTitleFormGroup = $("#add-link-title-form-group");
/** @var TextTypeWidget */
let textTypeWidget;
export async function showDialog(widget, text = '') {
textTypeWidget = widget;
$addLinkTitleSettings.toggle(!textTypeWidget.hasSelection());
$addLinkTitleSettings.find('input[type=radio]').on('change', updateTitleSettingsVisibility);
// with selection hyper link is implied
if (textTypeWidget.hasSelection()) {
$addLinkTitleSettings.find("input[value='hyper-link']").prop("checked", true);
}
else {
$addLinkTitleSettings.find("input[value='reference-link']").prop("checked", true);
}
updateTitleSettingsVisibility();
utils.openDialog($dialog);
$autoComplete.val('');
$linkTitle.val('');
async function setDefaultLinkTitle(noteId) {
const noteTitle = await treeService.getNoteTitle(noteId);
$linkTitle.val(noteTitle);
}
noteAutocompleteService.initNoteAutocomplete($autoComplete, {
allowExternalLinks: true,
allowCreatingNotes: true
});
$autoComplete.on('autocomplete:noteselected', (event, suggestion, dataset) => {
if (!suggestion.notePath) {
return false;
}
updateTitleSettingsVisibility();
const noteId = treeService.getNoteIdFromNotePath(suggestion.notePath);
if (noteId) {
setDefaultLinkTitle(noteId);
}
});
$autoComplete.on('autocomplete:externallinkselected', (event, suggestion, dataset) => {
if (!suggestion.externalLink) {
return false;
}
updateTitleSettingsVisibility();
$linkTitle.val(suggestion.externalLink);
});
$autoComplete.on('autocomplete:cursorchanged', function(event, suggestion, dataset) {
if (suggestion.externalLink) {
$linkTitle.val(suggestion.externalLink)
}
else {
const noteId = treeService.getNoteIdFromNotePath(suggestion.notePath);
if (noteId) {
setDefaultLinkTitle(noteId);
}
}
});
if (text && text.trim()) {
noteAutocompleteService.setText($autoComplete, text);
}
else {
noteAutocompleteService.showRecentNotes($autoComplete);
}
$autoComplete
.trigger('focus')
.trigger('select'); // to be able to quickly remove entered text
}
function getLinkType() {
if ($autoComplete.getSelectedExternalLink()) {
return 'external-link';
}
return $addLinkTitleSettings.find('input[type=radio]:checked').val();
}
function updateTitleSettingsVisibility() {
const linkType = getLinkType();
$addLinkTitleFormGroup.toggle(linkType !== 'reference-link');
$addLinkTitleRadios.toggle(linkType !== 'external-link')
}
$form.on('submit', () => {
if ($autoComplete.getSelectedNotePath()) {
$dialog.modal('hide');
const linkTitle = getLinkType() === 'reference-link' ? null : $linkTitle.val();
textTypeWidget.addLink($autoComplete.getSelectedNotePath(), linkTitle);
}
else if ($autoComplete.getSelectedExternalLink()) {
$dialog.modal('hide');
textTypeWidget.addLink($autoComplete.getSelectedExternalLink(), $linkTitle.val());
}
else {
logError("No link to add.");
}
return false;
});
-28
View File
@@ -1,28 +0,0 @@
import server from "../services/server.js";
import utils from "../services/utils.js";
const $dialog = $("#backend-log-dialog");
const $backendLogTextArea = $("#backend-log-textarea");
const $refreshBackendLog = $("#refresh-backend-log-button");
export async function showDialog() {
utils.openDialog($dialog);
load();
}
function scrollToBottom() {
$backendLogTextArea.scrollTop($backendLogTextArea[0].scrollHeight);
}
async function load() {
const backendLog = await server.get('backend-log');
$backendLogTextArea.text(backendLog);
scrollToBottom();
}
$refreshBackendLog.on('click', load);
$dialog.on('shown.bs.modal', scrollToBottom);
-59
View File
@@ -1,59 +0,0 @@
import treeService from '../services/tree.js';
import server from '../services/server.js';
import froca from "../services/froca.js";
import toastService from "../services/toast.js";
import utils from "../services/utils.js";
const $dialog = $("#branch-prefix-dialog");
const $form = $("#branch-prefix-form");
const $treePrefixInput = $("#branch-prefix-input");
const $noteTitle = $('#branch-prefix-note-title');
let branchId;
export async function showDialog(notePath) {
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
if (!noteId || !parentNoteId) {
return;
}
branchId = await froca.getBranchId(parentNoteId, noteId);
const branch = froca.getBranch(branchId);
if (!branch || branch.noteId === 'root') {
return;
}
const parentNote = await froca.getNote(branch.parentNoteId);
if (parentNote.type === 'search') {
return;
}
utils.openDialog($dialog);
$treePrefixInput.val(branch.prefix);
const noteTitle = await treeService.getNoteTitle(noteId);
$noteTitle.text(" - " + noteTitle);
}
async function savePrefix() {
const prefix = $treePrefixInput.val();
await server.put('branches/' + branchId + '/set-prefix', { prefix: prefix });
$dialog.modal('hide');
toastService.showMessage("Branch prefix has been saved.");
}
$form.on('submit', () => {
savePrefix();
return false;
});
$dialog.on('shown.bs.modal', () => $treePrefixInput.trigger('focus'));
-73
View File
@@ -1,73 +0,0 @@
import noteAutocompleteService from "../services/note_autocomplete.js";
import utils from "../services/utils.js";
import treeService from "../services/tree.js";
import toastService from "../services/toast.js";
import froca from "../services/froca.js";
import branchService from "../services/branches.js";
import appContext from "../services/app_context.js";
const $dialog = $("#clone-to-dialog");
const $form = $("#clone-to-form");
const $noteAutoComplete = $("#clone-to-note-autocomplete");
const $clonePrefix = $("#clone-prefix");
const $noteList = $("#clone-to-note-list");
let clonedNoteIds;
export async function showDialog(noteIds) {
if (!noteIds || noteIds.length === 0) {
noteIds = [ appContext.tabManager.getActiveContextNoteId() ];
}
clonedNoteIds = [];
for (const noteId of noteIds) {
if (!clonedNoteIds.includes(noteId)) {
clonedNoteIds.push(noteId);
}
}
utils.openDialog($dialog);
$noteAutoComplete.val('').trigger('focus');
$noteList.empty();
for (const noteId of clonedNoteIds) {
const note = await froca.getNote(noteId);
$noteList.append($("<li>").text(note.title));
}
noteAutocompleteService.initNoteAutocomplete($noteAutoComplete);
noteAutocompleteService.showRecentNotes($noteAutoComplete);
}
async function cloneNotesTo(notePath) {
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
const targetBranchId = await froca.getBranchId(parentNoteId, noteId);
for (const cloneNoteId of clonedNoteIds) {
await branchService.cloneNoteToBranch(cloneNoteId, targetBranchId, $clonePrefix.val());
const clonedNote = await froca.getNote(cloneNoteId);
const targetNote = await froca.getBranch(targetBranchId).getNote();
toastService.showMessage(`Note "${clonedNote.title}" has been cloned into ${targetNote.title}`);
}
}
$form.on('submit', () => {
const notePath = $noteAutoComplete.getSelectedNotePath();
if (notePath) {
$dialog.modal('hide');
cloneNotesTo(notePath);
}
else {
logError("No path to clone to.");
}
return false;
});
-80
View File
@@ -1,80 +0,0 @@
const $dialog = $("#confirm-dialog");
const $confirmContent = $("#confirm-dialog-content");
const $okButton = $("#confirm-dialog-ok-button");
const $cancelButton = $("#confirm-dialog-cancel-button");
const $custom = $("#confirm-dialog-custom");
const DELETE_NOTE_BUTTON_ID = "confirm-dialog-delete-note";
let resolve;
let $originallyFocused; // element focused before the dialog was opened so we can return to it afterwards
export function confirm(message) {
$originallyFocused = $(':focus');
$custom.hide();
glob.activeDialog = $dialog;
if (typeof message === 'string') {
message = $("<div>").text(message);
}
$confirmContent.empty().append(message);
$dialog.modal();
return new Promise((res, rej) => { resolve = res; });
}
export function confirmDeleteNoteBoxWithNote(title) {
glob.activeDialog = $dialog;
$confirmContent.text(`Are you sure you want to remove the note "${title}" from relation map?`);
$custom.empty()
.append("<br/>")
.append($("<div>").addClass("form-check")
.append($("<input>")
.attr("id", DELETE_NOTE_BUTTON_ID)
.attr("type", "checkbox")
.addClass("form-check-input"))
.append($("<label>")
.attr("for", DELETE_NOTE_BUTTON_ID)
.addClass("form-check-label")
.attr("style", "text-decoration: underline dotted black")
.attr("title", "If you don't check this, note will be only removed from relation map, but will stay as a note.")
.html("Also delete note")));
$custom.show();
$dialog.modal();
return new Promise((res, rej) => { resolve = res; });
}
export function isDeleteNoteChecked() {
return $("#" + DELETE_NOTE_BUTTON_ID + ":checked").length > 0;
}
$dialog.on('shown.bs.modal', () => $okButton.trigger("focus"));
$dialog.on("hidden.bs.modal", () => {
if (resolve) {
resolve(false);
}
if ($originallyFocused) {
$originallyFocused.trigger('focus');
$originallyFocused = null;
}
});
function doResolve(ret) {
resolve(ret);
resolve = null;
$dialog.modal("hide");
}
$cancelButton.on('click', () => doResolve(false));
$okButton.on('click', () => doResolve(true));
-99
View File
@@ -1,99 +0,0 @@
import server from "../services/server.js";
import froca from "../services/froca.js";
import linkService from "../services/link.js";
import utils from "../services/utils.js";
const $dialog = $("#delete-notes-dialog");
const $okButton = $("#delete-notes-dialog-ok-button");
const $cancelButton = $("#delete-notes-dialog-cancel-button");
const $deleteNotesList = $("#delete-notes-list");
const $brokenRelationsList = $("#broken-relations-list");
const $deletedNotesCount = $("#deleted-notes-count");
const $noNoteToDeleteWrapper = $("#no-note-to-delete-wrapper");
const $deleteNotesListWrapper = $("#delete-notes-list-wrapper");
const $brokenRelationsListWrapper = $("#broken-relations-wrapper");
const $brokenRelationsCount = $("#broke-relations-count");
const $deleteAllClones = $("#delete-all-clones");
const $eraseNotes = $("#erase-notes");
let branchIds = null;
let resolve = null;
async function renderDeletePreview() {
const response = await server.post('delete-notes-preview', {
branchIdsToDelete: branchIds,
deleteAllClones: isDeleteAllClonesChecked()
});
$deleteNotesList.empty();
$brokenRelationsList.empty();
$deleteNotesListWrapper.toggle(response.noteIdsToBeDeleted.length > 0);
$noNoteToDeleteWrapper.toggle(response.noteIdsToBeDeleted.length === 0);
for (const note of await froca.getNotes(response.noteIdsToBeDeleted)) {
$deleteNotesList.append(
$("<li>").append(
await linkService.createNoteLink(note.noteId, {showNotePath: true})
)
);
}
$deletedNotesCount.text(response.noteIdsToBeDeleted.length);
$brokenRelationsListWrapper.toggle(response.brokenRelations.length > 0);
$brokenRelationsCount.text(response.brokenRelations.length);
await froca.getNotes(response.brokenRelations.map(br => br.noteId));
for (const attr of response.brokenRelations) {
$brokenRelationsList.append(
$("<li>")
.append(`Note `)
.append(await linkService.createNoteLink(attr.value))
.append(` (to be deleted) is referenced by relation <code>${attr.name}</code> originating from `)
.append(await linkService.createNoteLink(attr.noteId))
);
}
}
export async function showDialog(branchIdsToDelete) {
branchIds = branchIdsToDelete;
await renderDeletePreview();
utils.openDialog($dialog);
$deleteAllClones.prop("checked", false);
$eraseNotes.prop("checked", false);
return new Promise((res, rej) => resolve = res);
}
export function isDeleteAllClonesChecked() {
return $deleteAllClones.is(":checked");
}
export function isEraseNotesChecked() {
return $eraseNotes.is(":checked");
}
$dialog.on('shown.bs.modal', () => $okButton.trigger("focus"));
$cancelButton.on('click', () => {
utils.closeActiveDialog();
resolve({proceed: false});
});
$okButton.on('click', () => {
utils.closeActiveDialog();
resolve({
proceed: true,
deleteAllClones: isDeleteAllClonesChecked(),
eraseNotes: isEraseNotesChecked()
});
});
$deleteAllClones.on('click', () => renderDeletePreview());
-137
View File
@@ -1,137 +0,0 @@
import treeService from "../services/tree.js";
import utils from "../services/utils.js";
import ws from "../services/ws.js";
import toastService from "../services/toast.js";
import froca from "../services/froca.js";
import openService from "../services/open.js";
const $dialog = $("#export-dialog");
const $form = $("#export-form");
const $noteTitle = $dialog.find(".export-note-title");
const $subtreeFormats = $("#export-subtree-formats");
const $singleFormats = $("#export-single-formats");
const $subtreeType = $("#export-type-subtree");
const $singleType = $("#export-type-single");
const $exportButton = $("#export-button");
const $opmlVersions = $("#opml-versions");
let taskId = '';
let branchId = null;
export async function showDialog(notePath, defaultType) {
// each opening of the dialog resets the taskId so we don't associate it with previous exports anymore
taskId = '';
$exportButton.removeAttr("disabled");
if (defaultType === 'subtree') {
$subtreeType.prop("checked", true).trigger('change');
// to show/hide OPML versions
$("input[name=export-subtree-format]:checked").trigger('change');
}
else if (defaultType === 'single') {
$singleType.prop("checked", true).trigger('change');
}
else {
throw new Error("Unrecognized type " + defaultType);
}
$("#opml-v2").prop("checked", true); // setting default
utils.openDialog($dialog);
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
branchId = await froca.getBranchId(parentNoteId, noteId);
const noteTitle = await treeService.getNoteTitle(noteId);
$noteTitle.html(noteTitle);
}
$form.on('submit', () => {
$dialog.modal('hide');
const exportType = $dialog.find("input[name='export-type']:checked").val();
if (!exportType) {
// this shouldn't happen as we always choose default export type
alert("Choose export type first please");
return;
}
const exportFormat = exportType === 'subtree'
? $("input[name=export-subtree-format]:checked").val()
: $("input[name=export-single-format]:checked").val();
const exportVersion = exportFormat === 'opml' ? $dialog.find("input[name='opml-version']:checked").val() : "1.0";
exportBranch(branchId, exportType, exportFormat, exportVersion);
return false;
});
function exportBranch(branchId, type, format, version) {
taskId = utils.randomString(10);
const url = openService.getUrlForDownload(`api/notes/${branchId}/export/${type}/${format}/${version}/${taskId}`);
openService.download(url);
}
$('input[name=export-type]').on('change', function () {
if (this.value === 'subtree') {
if ($("input[name=export-subtree-format]:checked").length === 0) {
$("input[name=export-subtree-format]:first").prop("checked", true);
}
$subtreeFormats.slideDown();
$singleFormats.slideUp();
}
else {
if ($("input[name=export-single-format]:checked").length === 0) {
$("input[name=export-single-format]:first").prop("checked", true);
}
$subtreeFormats.slideUp();
$singleFormats.slideDown();
}
});
$('input[name=export-subtree-format]').on('change', function () {
if (this.value === 'opml') {
$opmlVersions.slideDown();
}
else {
$opmlVersions.slideUp();
}
});
function makeToast(id, message) {
return {
id: id,
title: "Export status",
message: message,
icon: "arrow-square-up-right"
};
}
ws.subscribeToMessages(async message => {
if (message.taskType !== 'export') {
return;
}
if (message.type === 'taskError') {
toastService.closePersistent(message.taskId);
toastService.showError(message.message);
}
else if (message.type === 'taskProgressCount') {
toastService.showPersistent(makeToast(message.taskId, "Export in progress: " + message.progressCount));
}
else if (message.type === 'taskSucceeded') {
const toast = makeToast(message.taskId, "Export finished successfully.");
toast.closeAfter = 5000;
toastService.showPersistent(toast);
}
});
-7
View File
@@ -1,7 +0,0 @@
import utils from "../services/utils.js";
const $dialog = $("#help-dialog");
export async function showDialog() {
utils.openDialog($dialog);
}
-76
View File
@@ -1,76 +0,0 @@
import utils from '../services/utils.js';
import treeService from "../services/tree.js";
import importService from "../services/import.js";
import options from "../services/options.js";
const $dialog = $("#import-dialog");
const $form = $("#import-form");
const $noteTitle = $dialog.find(".import-note-title");
const $fileUploadInput = $("#import-file-upload-input");
const $importButton = $("#import-button");
const $safeImportCheckbox = $("#safe-import-checkbox");
const $shrinkImagesWrapper = $("shrink-images-wrapper");
const $shrinkImagesCheckbox = $("#shrink-images-checkbox");
const $textImportedAsTextCheckbox = $("#text-imported-as-text-checkbox");
const $codeImportedAsCodeCheckbox = $("#code-imported-as-code-checkbox");
const $explodeArchivesCheckbox = $("#explode-archives-checkbox");
const $replaceUnderscoresWithSpacesCheckbox = $("#replace-underscores-with-spaces-checkbox");
const $csrf = $("#import-csrf");
let parentNoteId = null;
export async function showDialog(noteId) {
$fileUploadInput.val('').trigger('change'); // to trigger Import button disabling listener below
$safeImportCheckbox.prop("checked", true);
$shrinkImagesCheckbox.prop("checked", options.is('compressImages'));
$textImportedAsTextCheckbox.prop("checked", true);
$codeImportedAsCodeCheckbox.prop("checked", true);
$explodeArchivesCheckbox.prop("checked", true);
$replaceUnderscoresWithSpacesCheckbox.prop("checked", true);
parentNoteId = noteId;
$noteTitle.text(await treeService.getNoteTitle(parentNoteId));
utils.openDialog($dialog);
}
$form.on('submit', () => {
// disabling so that import is not triggered again.
$importButton.attr("disabled", "disabled");
importIntoNote(parentNoteId);
return false;
});
async function importIntoNote(parentNoteId) {
const files = Array.from($fileUploadInput[0].files); // shallow copy since we're resetting the upload button below
const options = {
safeImport: boolToString($safeImportCheckbox),
shrinkImages: boolToString($shrinkImagesCheckbox),
textImportedAsText: boolToString($textImportedAsTextCheckbox),
codeImportedAsCode: boolToString($codeImportedAsCodeCheckbox),
explodeArchives: boolToString($explodeArchivesCheckbox),
replaceUnderscoresWithSpaces: boolToString($replaceUnderscoresWithSpacesCheckbox)
};
$dialog.modal('hide');
await importService.uploadFiles(parentNoteId, files, options);
}
function boolToString($el) {
return $el.is(":checked") ? "true" : "false";
}
$fileUploadInput.on('change', () => {
if ($fileUploadInput.val()) {
$importButton.removeAttr("disabled");
}
else {
$importButton.attr("disabled", "disabled");
}
});
-56
View File
@@ -1,56 +0,0 @@
import treeService from '../services/tree.js';
import noteAutocompleteService from '../services/note_autocomplete.js';
import utils from "../services/utils.js";
import froca from "../services/froca.js";
const $dialog = $("#include-note-dialog");
const $form = $("#include-note-form");
const $autoComplete = $("#include-note-autocomplete");
/** @var TextTypeWidget */
let textTypeWidget;
export async function showDialog(widget) {
textTypeWidget = widget;
$autoComplete.val('');
utils.openDialog($dialog);
noteAutocompleteService.initNoteAutocomplete($autoComplete, {
hideGoToSelectedNoteButton: true,
allowCreatingNotes: true
});
noteAutocompleteService.showRecentNotes($autoComplete);
}
async function includeNote(notePath) {
const noteId = treeService.getNoteIdFromNotePath(notePath);
const note = await froca.getNote(noteId);
const boxSize = $("input[name='include-note-box-size']:checked").val();
if (note.type === 'image') {
// there's no benefit to use insert note functionlity for images
// so we'll just add an IMG tag
textTypeWidget.addImage(noteId);
}
else {
textTypeWidget.addIncludeNote(noteId, boxSize);
}
}
$form.on('submit', () => {
const notePath = $autoComplete.getSelectedNotePath();
if (notePath) {
$dialog.modal('hide');
includeNote(notePath);
}
else {
logError("No noteId to include.");
}
return false;
});
-33
View File
@@ -1,33 +0,0 @@
import utils from "../services/utils.js";
const $dialog = $("#info-dialog");
const $infoContent = $("#info-dialog-content");
const $okButton = $("#info-dialog-ok-button");
let resolve;
let $originallyFocused; // element focused before the dialog was opened so we can return to it afterwards
export function info(message) {
$originallyFocused = $(':focus');
$infoContent.text(message);
utils.openDialog($dialog);
return new Promise((res, rej) => { resolve = res; });
}
$dialog.on('shown.bs.modal', () => $okButton.trigger("focus"));
$dialog.on("hidden.bs.modal", () => {
if (resolve) {
resolve();
}
if ($originallyFocused) {
$originallyFocused.trigger('focus');
$originallyFocused = null;
}
});
$okButton.on('click', () => $dialog.modal("hide"));
-60
View File
@@ -1,60 +0,0 @@
import noteAutocompleteService from '../services/note_autocomplete.js';
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
const $dialog = $("#jump-to-note-dialog");
const $autoComplete = $("#jump-to-note-autocomplete");
const $showInFullTextButton = $("#show-in-full-text-button");
let lastOpenedTs = 0;
const KEEP_LAST_SEARCH_FOR_X_SECONDS = 120;
export async function showDialog() {
utils.openDialog($dialog);
noteAutocompleteService.initNoteAutocomplete($autoComplete, { hideGoToSelectedNoteButton: true })
// clear any event listener added in previous invocation of this function
.off('autocomplete:noteselected')
.on('autocomplete:noteselected', function(event, suggestion, dataset) {
if (!suggestion.notePath) {
return false;
}
appContext.tabManager.getActiveContext().setNote(suggestion.notePath);
});
// if you open the Jump To dialog soon after using it previously it can often mean that you
// actually want to search for the same thing (e.g. you opened the wrong note at first try)
// so we'll keep the content.
// if it's outside of this time limit then we assume it's a completely new search and show recent notes instead.
if (Date.now() - lastOpenedTs > KEEP_LAST_SEARCH_FOR_X_SECONDS * 1000) {
noteAutocompleteService.showRecentNotes($autoComplete);
}
else {
$autoComplete
// hack, the actual search value is stored in <pre> element next to the search input
// this is important because the search input value is replaced with the suggestion note's title
.autocomplete("val", $autoComplete.next().text())
.trigger('focus')
.trigger('select');
}
lastOpenedTs = Date.now();
}
function showInFullText(e) {
// stop from propagating upwards (dangerous especially with ctrl+enter executable javascript notes)
e.preventDefault();
e.stopPropagation();
const searchString = $autoComplete.val();
appContext.triggerCommand('searchNotes', {searchString});
$dialog.modal('hide');
}
$showInFullTextButton.on('click', showInFullText);
utils.bindElShortcut($dialog, 'ctrl+return', showInFullText);
-61
View File
@@ -1,61 +0,0 @@
import libraryLoader from "../services/library_loader.js";
import toastService from "../services/toast.js";
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
const $dialog = $('#markdown-import-dialog');
const $importTextarea = $('#markdown-import-textarea');
const $importButton = $('#markdown-import-button');
async function convertMarkdownToHtml(text) {
await libraryLoader.requireLibrary(libraryLoader.COMMONMARK);
const reader = new commonmark.Parser();
const writer = new commonmark.HtmlRenderer();
const parsed = reader.parse(text);
const result = writer.render(parsed);
appContext.triggerCommand('executeInActiveEditor', {
callback: textEditor => {
const viewFragment = textEditor.data.processor.toView(result);
const modelFragment = textEditor.data.toModel(viewFragment);
textEditor.model.insertContent(modelFragment, textEditor.model.document.selection);
toastService.showMessage("Markdown content has been imported into the document.");
}
});
}
export async function importMarkdownInline() {
if (appContext.tabManager.getActiveContextNoteType() !== 'text') {
return;
}
if (utils.isElectron()) {
const {clipboard} = utils.dynamicRequire('electron');
const text = clipboard.readText();
convertMarkdownToHtml(text);
}
else {
utils.openDialog($dialog);
}
}
async function sendForm() {
const text = $importTextarea.val();
$dialog.modal('hide');
await convertMarkdownToHtml(text);
$importTextarea.val('');
}
$importButton.on('click', sendForm);
$dialog.on('shown.bs.modal', () => $importTextarea.trigger('focus'));
utils.bindElShortcut($dialog, 'ctrl+return', sendForm);
-58
View File
@@ -1,58 +0,0 @@
import noteAutocompleteService from "../services/note_autocomplete.js";
import utils from "../services/utils.js";
import toastService from "../services/toast.js";
import froca from "../services/froca.js";
import branchService from "../services/branches.js";
import treeService from "../services/tree.js";
const $dialog = $("#move-to-dialog");
const $form = $("#move-to-form");
const $noteAutoComplete = $("#move-to-note-autocomplete");
const $noteList = $("#move-to-note-list");
let movedBranchIds;
export async function showDialog(branchIds) {
movedBranchIds = branchIds;
utils.openDialog($dialog);
$noteAutoComplete.val('').trigger('focus');
$noteList.empty();
for (const branchId of movedBranchIds) {
const branch = froca.getBranch(branchId);
const note = await froca.getNote(branch.noteId);
$noteList.append($("<li>").text(note.title));
}
noteAutocompleteService.initNoteAutocomplete($noteAutoComplete);
noteAutocompleteService.showRecentNotes($noteAutoComplete);
}
async function moveNotesTo(parentBranchId) {
await branchService.moveToParentNote(movedBranchIds, parentBranchId);
const parentBranch = froca.getBranch(parentBranchId);
const parentNote = await parentBranch.getNote();
toastService.showMessage(`Selected notes have been moved into ${parentNote.title}`);
}
$form.on('submit', () => {
const notePath = $noteAutoComplete.getSelectedNotePath();
if (notePath) {
$dialog.modal('hide');
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
froca.getBranchId(parentNoteId, noteId).then(branchId => moveNotesTo(branchId));
}
else {
logError("No path to move to.");
}
return false;
});
-203
View File
@@ -1,203 +0,0 @@
import utils from '../services/utils.js';
import server from '../services/server.js';
import toastService from "../services/toast.js";
import appContext from "../services/app_context.js";
import libraryLoader from "../services/library_loader.js";
import openService from "../services/open.js";
const $dialog = $("#note-revisions-dialog");
const $list = $("#note-revision-list");
const $listDropdown = $("#note-revision-list-dropdown");
const $content = $("#note-revision-content");
const $title = $("#note-revision-title");
const $titleButtons = $("#note-revision-title-buttons");
const $eraseAllRevisionsButton = $("#note-revisions-erase-all-revisions-button");
$listDropdown.dropdown();
$listDropdown.parent().on('hide.bs.dropdown', e => {
// prevent closing dropdown by clicking outside
if (e.clickEvent) {
e.preventDefault();
}
});
let revisionItems = [];
let note;
let noteRevisionId;
export async function showCurrentNoteRevisions() {
await showNoteRevisionsDialog(appContext.tabManager.getActiveContextNoteId());
}
export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
utils.openDialog($dialog);
await loadNoteRevisions(noteId, noteRevisionId);
}
async function loadNoteRevisions(noteId, noteRevId) {
$list.empty();
$content.empty();
$titleButtons.empty();
note = appContext.tabManager.getActiveContextNote();
revisionItems = await server.get(`notes/${noteId}/revisions`);
for (const item of revisionItems) {
$list.append(
$('<a class="dropdown-item" tabindex="0">')
.text(item.dateLastEdited.substr(0, 16) + ` (${item.contentLength} bytes)`)
.attr('data-note-revision-id', item.noteRevisionId)
.attr('title', 'This revision was last edited on ' + item.dateLastEdited)
);
}
$listDropdown.dropdown('show');
noteRevisionId = noteRevId;
if (revisionItems.length > 0) {
if (!noteRevisionId) {
noteRevisionId = revisionItems[0].noteRevisionId;
}
} else {
$title.text("No revisions for this note yet...");
noteRevisionId = null;
}
$eraseAllRevisionsButton.toggle(revisionItems.length > 0);
}
$dialog.on('shown.bs.modal', () => {
$list.find(`[data-note-revision-id="${noteRevisionId}"]`)
.trigger('focus');
});
async function setContentPane() {
const noteRevisionId = $list.find(".active").attr('data-note-revision-id');
const revisionItem = revisionItems.find(r => r.noteRevisionId === noteRevisionId);
$titleButtons.empty();
$content.empty();
$title.html(revisionItem.title);
const $restoreRevisionButton = $('<button class="btn btn-sm" type="button">Restore this revision</button>');
$restoreRevisionButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to restore this revision? This will overwrite current title/content of the note with this revision.';
if (await confirmDialog.confirm(text)) {
await server.put(`notes/${revisionItem.noteId}/restore-revision/${revisionItem.noteRevisionId}`);
$dialog.modal('hide');
toastService.showMessage('Note revision has been restored.');
}
});
const $eraseRevisionButton = $('<button class="btn btn-sm" type="button">Delete this revision</button>');
$eraseRevisionButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to delete this revision? This action will delete revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
loadNoteRevisions(revisionItem.noteId);
toastService.showMessage('Note revision has been deleted.');
}
});
$titleButtons
.append($restoreRevisionButton)
.append(' &nbsp; ')
.append($eraseRevisionButton)
.append(' &nbsp; ');
const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>');
$downloadButton.on('click', () => openService.downloadNoteRevision(revisionItem.noteId, revisionItem.noteRevisionId));
$titleButtons.append($downloadButton);
const fullNoteRevision = await server.get(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
if (revisionItem.type === 'text') {
$content.html(fullNoteRevision.content);
if ($content.find('span.math-tex').length > 0) {
await libraryLoader.requireLibrary(libraryLoader.KATEX);
renderMathInElement($content[0], {trust: true});
}
}
else if (revisionItem.type === 'code') {
$content.html($("<pre>").text(fullNoteRevision.content));
}
else if (revisionItem.type === 'image') {
$content.html($("<img>")
// reason why we put this inline as base64 is that we do not want to let user to copy this
// as a URL to be used in a note. Instead if they copy and paste it into a note, it will be a uploaded as a new note
.attr("src", `data:${note.mime};base64,` + fullNoteRevision.content)
.css("max-width", "100%")
.css("max-height", "100%"));
}
else if (revisionItem.type === 'file') {
const $table = $("<table cellpadding='10'>")
.append($("<tr>").append(
$("<th>").text("MIME: "),
$("<td>").text(revisionItem.mime)
))
.append($("<tr>").append(
$("<th>").text("File size:"),
$("<td>").text(revisionItem.contentLength + " bytes")
));
if (fullNoteRevision.content) {
$table.append($("<tr>").append(
$('<td colspan="2">').append(
$('<div style="font-weight: bold;">').text("Preview:"),
$('<pre class="file-preview-content"></pre>')
.text(fullNoteRevision.content)
)
));
}
$content.html($table);
}
else {
$content.text("Preview isn't available for this note type.");
}
}
$eraseAllRevisionsButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to delete all revisions of this note? This action will erase revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${note.noteId}/revisions`);
$dialog.modal('hide');
toastService.showMessage('Note revisions has been deleted.');
}
});
$list.on('click', '.dropdown-item', e => {
e.preventDefault();
return false;
});
$list.on('focus', '.dropdown-item', e => {
$list.find('.dropdown-item').each((i, el) => {
$(el).toggleClass('active', el === e.target);
});
setContentPane();
});
-40
View File
@@ -1,40 +0,0 @@
import appContext from "../services/app_context.js";
import utils from "../services/utils.js";
const $dialog = $("#note-source-dialog");
const $noteSource = $("#note-source");
export async function showDialog() {
utils.openDialog($dialog);
const noteCompletement = await appContext.tabManager.getActiveContext().getNoteComplement();
$noteSource.text(formatHtml(noteCompletement.content));
}
function formatHtml(str) {
const div = document.createElement('div');
div.innerHTML = str.trim();
return formatNode(div, 0).innerHTML.trim();
}
function formatNode(node, level) {
const indentBefore = new Array(level++ + 1).join(' ');
const indentAfter = new Array(level - 1).join(' ');
let textNode;
for (let i = 0; i < node.children.length; i++) {
textNode = document.createTextNode('\n' + indentBefore);
node.insertBefore(textNode, node.children[i]);
formatNode(node.children[i], level);
if (node.lastElementChild === node.children[i]) {
textNode = document.createTextNode('\n' + indentAfter);
node.appendChild(textNode);
}
}
return node;
}
-34
View File
@@ -1,34 +0,0 @@
"use strict";
import server from '../services/server.js';
import utils from "../services/utils.js";
const $dialog = $("#options-dialog");
export async function showDialog(openTab) {
const options = await server.get('options');
utils.openDialog($dialog);
(await Promise.all([
import('./options/appearance.js'),
import('./options/shortcuts.js'),
import('./options/code_notes.js'),
import('./options/password.js'),
import('./options/etapi.js'),
import('./options/backup.js'),
import('./options/sync.js'),
import('./options/other.js'),
import('./options/advanced.js')
]))
.map(m => new m.default)
.forEach(tab => {
if (tab.optionsLoaded) {
tab.optionsLoaded(options)
}
});
if (openTab) {
$(`.nav-link[href='#options-${openTab}']`).trigger("click");
}
}
@@ -1,13 +0,0 @@
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
export function show() {
const $dialog = $("#password-not-set-dialog");
const $openPasswordOptionsButton = $("#open-password-options-button");
utils.openDialog($dialog);
$openPasswordOptionsButton.on("click", () => {
appContext.triggerCommand("showOptions", { openTab: 'password' });
});
}
-59
View File
@@ -1,59 +0,0 @@
import utils from "../services/utils.js";
const $dialog = $("#prompt-dialog");
const $dialogBody = $dialog.find(".modal-body");
let $question;
let $answer;
const $form = $("#prompt-dialog-form");
let resolve;
let shownCb;
export function ask({ title, message, defaultValue, shown }) {
shownCb = shown;
$("#prompt-title").text(title || "Prompt");
$question = $("<label>")
.prop("for", "prompt-dialog-answer")
.text(message);
$answer = $("<input>")
.prop("type", "text")
.prop("id", "prompt-dialog-answer")
.addClass("form-control")
.val(defaultValue || "");
$dialogBody.empty().append(
$("<div>")
.addClass("form-group")
.append($question)
.append($answer));
utils.openDialog($dialog, false);
return new Promise((res, rej) => { resolve = res; });
}
$dialog.on('shown.bs.modal', () => {
if (shownCb) {
shownCb({ $dialog, $question, $answer, $form });
}
$answer.trigger('focus').select();
});
$dialog.on("hidden.bs.modal", () => {
if (resolve) {
resolve(null);
}
});
$form.on('submit', e => {
e.preventDefault();
resolve($answer.val());
$dialog.modal('hide');
});
@@ -1,29 +0,0 @@
import protectedSessionService from "../services/protected_session.js";
import utils from "../services/utils.js";
const $dialog = $("#protected-session-password-dialog");
const $passwordForm = $dialog.find(".protected-session-password-form");
const $passwordInput = $dialog.find(".protected-session-password");
export function show() {
utils.openDialog($dialog);
$passwordInput.trigger('focus');
}
export function close() {
// this may fail if the dialog has not been previously opened (not sure if still true with Bootstrap modal)
try {
$dialog.modal('hide');
}
catch (e) {}
}
$passwordForm.on('submit', () => {
const password = $passwordInput.val();
$passwordInput.val("");
protectedSessionService.setupProtectedSession(password);
return false;
});
-112
View File
@@ -1,112 +0,0 @@
import linkService from '../services/link.js';
import utils from '../services/utils.js';
import server from '../services/server.js';
import treeService from "../services/tree.js";
import froca from "../services/froca.js";
import appContext from "../services/app_context.js";
import hoistedNoteService from "../services/hoisted_note.js";
const $dialog = $("#recent-changes-dialog");
const $content = $("#recent-changes-content");
export async function showDialog(ancestorNoteId) {
utils.openDialog($dialog);
if (!ancestorNoteId) {
ancestorNoteId = hoistedNoteService.getHoistedNoteId();
}
const recentChangesRows = await server.get('recent-changes/' + ancestorNoteId);
// preload all notes into cache
await froca.getNotes(recentChangesRows.map(r => r.noteId), true);
$content.empty();
if (recentChangesRows.length === 0) {
$content.append("No changes yet ...");
}
const groupedByDate = groupByDate(recentChangesRows);
for (const [dateDay, dayChanges] of groupedByDate) {
const $changesList = $('<ul>');
const dayEl = $('<div>').append($('<b>').text(dateDay)).append($changesList);
for (const change of dayChanges) {
const formattedTime = change.date.substr(11, 5);
let $noteLink;
if (change.current_isDeleted) {
$noteLink = $("<span>").text(change.current_title);
if (change.canBeUndeleted) {
const $undeleteLink = $(`<a href="javascript:">`)
.text("undelete")
.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to undelete this note and its sub-notes?';
if (await confirmDialog.confirm(text)) {
await server.put(`notes/${change.noteId}/undelete`);
$dialog.modal('hide');
await froca.reloadNotes([change.noteId]);
appContext.tabManager.getActiveContext().setNote(change.noteId);
}
});
$noteLink
.append(' (')
.append($undeleteLink)
.append(')');
}
}
else {
const note = await froca.getNote(change.noteId);
const notePath = treeService.getSomeNotePath(note);
if (notePath) {
$noteLink = await linkService.createNoteLink(notePath, {
title: change.title,
showNotePath: true
});
}
else {
$noteLink = $("<span>").text(note.title);
}
}
$changesList.append($('<li>')
.append(
$("<span>")
.text(formattedTime)
.attr("title", change.date)
)
.append(' - ')
.append($noteLink));
}
$content.append(dayEl);
}
}
function groupByDate(rows) {
const groupedByDate = new Map();
for (const row of rows) {
const dateDay = row.date.substr(0, 10);
if (!groupedByDate.has(dateDay)) {
groupedByDate.set(dateDay, []);
}
groupedByDate.get(dateDay).push(row);
}
return groupedByDate;
}
@@ -1,24 +0,0 @@
import server from "../services/server.js";
import utils from "../services/utils.js";
const $dialog = $("#sort-child-notes-dialog");
const $form = $("#sort-child-notes-form");
let parentNoteId = null;
$form.on('submit', async () => {
const sortBy = $form.find("input[name='sort-by']:checked").val();
const sortDirection = $form.find("input[name='sort-direction']:checked").val();
await server.put(`notes/${parentNoteId}/sort-children`, {sortBy, sortDirection});
utils.closeActiveDialog();
});
export async function showDialog(noteId) {
parentNoteId = noteId;
utils.openDialog($dialog);
$form.find('input:first').focus();
}
+14 -3
View File
@@ -16,7 +16,9 @@ const NOTE_TYPE_ICONS = {
"relation-map": "bx bx-map-alt",
"book": "bx bx-book",
"note-map": "bx bx-map-alt",
"mermaid": "bx bx-selection"
"mermaid": "bx bx-selection",
"canvas": "bx bx-pen",
"web-view": "bx bx-globe-alt"
};
/**
@@ -261,7 +263,11 @@ class NoteShort {
const templateNote = this.froca.notes[templateAttr.value];
if (templateNote && templateNote.noteId !== this.noteId) {
attrArrs.push(templateNote.__getCachedAttributes(newPath));
attrArrs.push(
templateNote.__getCachedAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' && attr.name === 'template'))
);
}
}
@@ -634,13 +640,18 @@ class NoteShort {
return [];
}
return this.getAttributes()
const promotedAttrs = this.getAttributes()
.filter(attr => attr.isDefinition())
.filter(attr => {
const def = attr.getDefinition();
return def && def.isPromoted;
});
// attrs are not resorted if position changes after initial load
promotedAttrs.sort((a, b) => a.position < b.position ? -1 : 1);
return promotedAttrs;
}
hasAncestor(ancestorNoteId, visitedNoteIds = null) {
+55 -1
View File
@@ -48,6 +48,33 @@ import BookmarkButtons from "../widgets/bookmark_buttons.js";
import NoteWrapperWidget from "../widgets/note_wrapper.js";
import BacklinksWidget from "../widgets/backlinks.js";
import SharedInfoWidget from "../widgets/shared_info.js";
import FindWidget from "../widgets/find.js";
import TocWidget from "../widgets/toc.js";
import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
import AboutDialog from "../widgets/dialogs/about.js";
import NoteSourceDialog from "../widgets/dialogs/note_source.js";
import HelpDialog from "../widgets/dialogs/help.js";
import RecentChangesDialog from "../widgets/dialogs/recent_changes.js";
import BackendLogDialog from "../widgets/dialogs/backend_log.js";
import BranchPrefixDialog from "../widgets/dialogs/branch_prefix.js";
import SortChildNotesDialog from "../widgets/dialogs/sort_child_notes.js";
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
import IncludeNoteDialog from "../widgets/dialogs/include_note.js";
import NoteTypeChooserDialog from "../widgets/dialogs/note_type_chooser.js";
import JumpToNoteDialog from "../widgets/dialogs/jump_to_note.js";
import AddLinkDialog from "../widgets/dialogs/add_link.js";
import CloneToDialog from "../widgets/dialogs/clone_to.js";
import MoveToDialog from "../widgets/dialogs/move_to.js";
import ImportDialog from "../widgets/dialogs/import.js";
import ExportDialog from "../widgets/dialogs/export.js";
import MarkdownImportDialog from "../widgets/dialogs/markdown_import.js";
import ProtectedSessionPasswordDialog from "../widgets/dialogs/protected_session_password.js";
import NoteRevisionsDialog from "../widgets/dialogs/note_revisions.js";
import DeleteNotesDialog from "../widgets/dialogs/delete_notes.js";
import InfoDialog from "../widgets/dialogs/info.js";
import ConfirmDialog from "../widgets/dialogs/confirm.js";
import PromptDialog from "../widgets/dialogs/prompt.js";
import OptionsDialog from "../widgets/dialogs/options.js";
export default class DesktopLayout {
constructor(customWidgets) {
@@ -161,15 +188,42 @@ export default class DesktopLayout {
.child(new SearchResultWidget())
.child(new SqlResultWidget())
)
.child(new FindWidget())
.child(...this.customWidgets.get('node-detail-pane'))
)
)
.child(...this.customWidgets.get('center-pane'))
)
.child(new RightPaneContainer()
.child(new TocWidget())
.child(...this.customWidgets.get('right-pane'))
)
)
);
)
.child(new BulkActionsDialog())
.child(new AboutDialog())
.child(new NoteSourceDialog())
.child(new HelpDialog())
.child(new RecentChangesDialog())
.child(new BackendLogDialog())
.child(new BranchPrefixDialog())
.child(new SortChildNotesDialog())
.child(new PasswordNoteSetDialog())
.child(new IncludeNoteDialog())
.child(new NoteTypeChooserDialog())
.child(new JumpToNoteDialog())
.child(new AddLinkDialog())
.child(new CloneToDialog())
.child(new MoveToDialog())
.child(new ImportDialog())
.child(new ExportDialog())
.child(new MarkdownImportDialog())
.child(new ProtectedSessionPasswordDialog())
.child(new NoteRevisionsDialog())
.child(new DeleteNotesDialog())
.child(new InfoDialog())
.child(new ConfirmDialog())
.child(new PromptDialog())
.child(new OptionsDialog());
}
}
+5 -1
View File
@@ -8,6 +8,8 @@ import CloseDetailButtonWidget from "../widgets/mobile_widgets/close_detail_butt
import MobileDetailMenuWidget from "../widgets/mobile_widgets/mobile_detail_menu.js";
import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import ProtectedSessionPasswordDialog from "../widgets/dialogs/protected_session_password.js";
import ConfirmDialog from "../widgets/dialogs/confirm.js";
const MOBILE_CSS = `
<style>
@@ -128,6 +130,8 @@ export default class MobileLayout {
.css('padding', '5px 20px 10px 0')
)
)
);
)
.child(new ProtectedSessionPasswordDialog())
.child(new ConfirmDialog());
}
}
-1
View File
@@ -11,7 +11,6 @@ import Component from "../widgets/component.js";
import keyboardActionsService from "./keyboard_actions.js";
import MobileScreenSwitcherExecutor from "../widgets/mobile_widgets/mobile_screen_switcher.js";
import MainTreeExecutors from "./main_tree_executors.js";
import protectedSessionHolder from "./protected_session_holder.js";
import toast from "./toast.js";
class AppContext extends Component {
+3 -2
View File
@@ -4,6 +4,7 @@ import toastService from "./toast.js";
import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
import ws from "./ws.js";
import appContext from "./app_context.js";
async function moveBeforeBranch(branchIdsToMove, beforeBranchId) {
branchIdsToMove = filterRootNote(branchIdsToMove);
@@ -81,8 +82,8 @@ async function deleteNotes(branchIdsToDelete) {
deleteAllClones = false;
}
else {
const deleteNotesDialog = await import("../dialogs/delete_notes.js");
({proceed, deleteAllClones, eraseNotes} = await deleteNotesDialog.showDialog(branchIdsToDelete));
({proceed, deleteAllClones, eraseNotes} = await new Promise(res =>
appContext.triggerCommand('showDeleteNotesDialog', {branchIdsToDelete, callback: res})));
}
if (!proceed) {
+94
View File
@@ -0,0 +1,94 @@
import server from "./server.js";
import ws from "./ws.js";
import MoveNoteBulkAction from "../widgets/bulk_actions/note/move_note.js";
import DeleteNoteBulkAction from "../widgets/bulk_actions/note/delete_note.js";
import DeleteNoteRevisionsBulkAction from "../widgets/bulk_actions/note/delete_note_revisions.js";
import DeleteLabelBulkAction from "../widgets/bulk_actions/label/delete_label.js";
import DeleteRelationBulkAction from "../widgets/bulk_actions/relation/delete_relation.js";
import RenameLabelBulkAction from "../widgets/bulk_actions/label/rename_label.js";
import RenameRelationBulkAction from "../widgets/bulk_actions/relation/rename_relation.js";
import UpdateLabelValueBulkAction from "../widgets/bulk_actions/label/update_label_value.js";
import UpdateRelationTargetBulkAction from "../widgets/bulk_actions/relation/update_relation_target.js";
import ExecuteScriptBulkAction from "../widgets/bulk_actions/execute_script.js";
import AddLabelBulkAction from "../widgets/bulk_actions/label/add_label.js";
import AddRelationBulkAction from "../widgets/bulk_actions/relation/add_relation.js";
import RenameNoteBulkAction from "../widgets/bulk_actions/note/rename_note.js";
const ACTION_GROUPS = [
{
title: 'Labels',
actions: [AddLabelBulkAction, UpdateLabelValueBulkAction, RenameLabelBulkAction, DeleteLabelBulkAction]
},
{
title: 'Relations',
actions: [AddRelationBulkAction, UpdateRelationTargetBulkAction, RenameRelationBulkAction, DeleteRelationBulkAction]
},
{
title: 'Notes',
actions: [RenameNoteBulkAction, MoveNoteBulkAction, DeleteNoteBulkAction, DeleteNoteRevisionsBulkAction],
},
{
title: 'Other',
actions: [ExecuteScriptBulkAction]
}
];
const ACTION_CLASSES = [
RenameNoteBulkAction,
MoveNoteBulkAction,
DeleteNoteBulkAction,
DeleteNoteRevisionsBulkAction,
DeleteLabelBulkAction,
DeleteRelationBulkAction,
RenameLabelBulkAction,
RenameRelationBulkAction,
AddLabelBulkAction,
AddRelationBulkAction,
UpdateLabelValueBulkAction,
UpdateRelationTargetBulkAction,
ExecuteScriptBulkAction
];
async function addAction(noteId, actionName) {
await server.post(`notes/${noteId}/attributes`, {
type: 'label',
name: 'action',
value: JSON.stringify({
name: actionName
})
});
await ws.waitForMaxKnownEntityChangeId();
}
function parseActions(note) {
const actionLabels = note.getLabels('action');
return actionLabels.map(actionAttr => {
let actionDef;
try {
actionDef = JSON.parse(actionAttr.value);
} catch (e) {
logError(`Parsing of attribute: '${actionAttr.value}' failed with error: ${e.message}`);
return null;
}
const ActionClass = ACTION_CLASSES.find(actionClass => actionClass.actionName === actionDef.name);
if (!ActionClass) {
logError(`No action class for '${actionDef.name}' found.`);
return null;
}
return new ActionClass(actionAttr, actionDef);
})
.filter(action => !!action);
}
export default {
addAction,
parseActions,
ACTION_CLASSES,
ACTION_GROUPS
};
+1 -1
View File
@@ -82,7 +82,7 @@ class ContextMenu {
const $icon = $("<span>");
if (item.uiIcon) {
$icon.addClass("bx bx-" + item.uiIcon);
$icon.addClass(item.uiIcon);
} else {
$icon.append("&nbsp;");
}
+70
View File
@@ -0,0 +1,70 @@
/**
* Returns a function, that, as long as it continues to be invoked, will not
* be triggered. The function will be called after it stops being called for
* N milliseconds. If `immediate` is passed, trigger the function on the
* leading edge, instead of the trailing. The function also has a property 'clear'
* that is a function which will clear the timer to prevent previously scheduled executions.
*
* @source underscore.js
* @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
* @param {Function} function to wrap
* @param {Number} timeout in ms (`100`)
* @param {Boolean} whether to execute at the beginning (`false`)
* @api public
*/
function debounce(func, wait_ms, immediate){
var timeout, args, context, timestamp, result;
if (null == wait_ms) wait_ms = 100;
function later() {
var last = Date.now() - timestamp;
if (last < wait_ms && last >= 0) {
timeout = setTimeout(later, wait_ms - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
context = args = null;
}
}
};
var debounced = function(){
context = this;
args = arguments;
timestamp = Date.now();
var callNow = immediate && !timeout;
if (!timeout) timeout = setTimeout(later, wait_ms);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
};
debounced.clear = function() {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
};
debounced.flush = function() {
if (timeout) {
result = func.apply(context, args);
context = args = null;
clearTimeout(timeout);
timeout = null;
}
};
return debounced;
};
// Adds compatibility for ES modules
debounce.debounce = debounce;
export default debounce;
-37
View File
@@ -5,7 +5,6 @@ import server from "./server.js";
import appContext from "./app_context.js";
import Component from "../widgets/component.js";
import toastService from "./toast.js";
import noteCreateService from "./note_create.js";
import ws from "./ws.js";
import bundleService from "./bundle.js";
@@ -19,18 +18,6 @@ export default class Entrypoints extends Component {
jQuery.hotkeys.options.filterContentEditable = false;
jQuery.hotkeys.options.filterTextInputs = false;
}
$(document).on('click', "a[data-action='note-revision']", async event => {
const linkEl = $(event.target);
const noteId = linkEl.attr('data-note-path');
const noteRevisionId = linkEl.attr('data-note-revision-id');
const attributesDialog = await import("../dialogs/note_revisions.js");
attributesDialog.showNoteRevisionsDialog(noteId, noteRevisionId);
return false;
});
}
openDevToolsCommand() {
@@ -39,34 +26,10 @@ export default class Entrypoints extends Component {
}
}
findInTextCommand() {
if (!utils.isElectron()) {
return;
}
const remote = utils.dynamicRequire('@electron/remote');
const {FindInPage} = utils.dynamicRequire('electron-find');
const findInPage = new FindInPage(remote.getCurrentWebContents(), {
offsetTop: 10,
offsetRight: 10,
boxBgColor: 'var(--main-background-color)',
boxShadowColor: '#000',
inputColor: 'var(--input-text-color)',
inputBgColor: 'var(--input-background-color)',
inputFocusColor: '#555',
textColor: 'var(--main-text-color)',
textHoverBgColor: '#555',
caseSelectedColor: 'var(--main-border-color)'
});
findInPage.openFindWindow();
}
async createNoteIntoInboxCommand() {
const inboxNote = await dateNoteService.getInboxNote();
const {note} = await server.post(`notes/${inboxNote.noteId}/children?target=into`, {
title: 'new note',
content: '',
type: 'text',
isProtected: inboxNote.isProtected && protectedSessionHolder.isProtectedSessionAvailable()
+117 -5
View File
@@ -101,6 +101,26 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
}
};
/**
* Open a note in a new split.
*
* @param {string} notePath (or noteId)
* @param {boolean} activate - set to true to activate the new split, false to stay on the current split
* @return {Promise<void>}
*/
this.openSplitWithNote = async (notePath, activate) => {
await ws.waitForMaxKnownEntityChangeId();
const subContexts = appContext.tabManager.getActiveContext().getSubContexts();
const {ntxId} = subContexts[subContexts.length - 1];
appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath});
if (activate) {
appContext.triggerEvent('focusAndSelectTitle');
}
};
/**
* @typedef {Object} ToolbarButtonOptions
* @property {string} title
@@ -299,6 +319,24 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*/
this.showError = toastService.showError;
/**
* Trigger command.
*
* @method
* @param {string} name
* @param {object} data
*/
this.triggerCommand = (name, data) => appContext.triggerCommand(name, data);
/**
* Trigger event.
*
* @method
* @param {string} name
* @param {object} data
*/
this.triggerEvent = (name, data) => appContext.triggerEvent(name, data);
/**
* @method
* @deprecated - this is now no-op since all the changes should be gracefully handled per widget
@@ -321,30 +359,104 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Adds given text to the editor cursor
*
* @deprecated use addTextToActiveContextEditor() instead
* @param {string} text - this must be clear text, HTML is not supported.
* @method
*/
this.addTextToActiveTabEditor = text => appContext.triggerCommand('addTextToActiveEditor', {text});
this.addTextToActiveTabEditor = text => {
console.warn("api.addTextToActiveTabEditor() is deprecated, use addTextToActiveContextEditor() instead.");
return appContext.triggerCommand('addTextToActiveEditor', {text});
};
/**
* Adds given text to the editor cursor
*
* @param {string} text - this must be clear text, HTML is not supported.
* @method
*/
this.addTextToActiveContextEditor = text => appContext.triggerCommand('addTextToActiveEditor', {text});
/**
* @method
* @deprecated use getActiveContextNote() instead
* @returns {NoteShort} active note (loaded into right pane)
*/
this.getActiveTabNote = () => {
console.warn("api.getActiveTabNote() is deprecated, use getActiveContextNote() instead.");
return appContext.tabManager.getActiveContextNote();
};
/**
* @method
* @returns {NoteShort} active note (loaded into right pane)
*/
this.getActiveTabNote = () => appContext.tabManager.getActiveContextNote();
this.getActiveContextNote = () => appContext.tabManager.getActiveContextNote();
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
*
* @deprecated use getActiveContextTextEditor()
* @method
* @param [callback] - callback receiving "textEditor" instance
*/
this.getActiveTabTextEditor = callback => {
console.warn("api.getActiveTabTextEditor() is deprecated, use getActiveContextTextEditor() instead.");
return appContext.tabManager.getActiveContext()?.getTextEditor(callback);
};
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
*
* @method
* @param callback - method receiving "textEditor" instance
* @returns {Promise<CKEditor>} instance of CKEditor
*/
this.getActiveTabTextEditor = callback => appContext.triggerCommand('executeInActiveEditor', {callback});
this.getActiveContextTextEditor = () => appContext.tabManager.getActiveContext()?.getTextEditor();
/**
* See https://codemirror.net/doc/manual.html#api
*
* @method
* @returns {Promise<CodeMirror>} instance of CodeMirror
*/
this.getActiveContextCodeEditor = () => appContext.tabManager.getActiveContext()?.getCodeEditor();
/**
* Get access to the widget handling note detail. Methods like `getWidgetType()` and `getTypeWidget()` to get to the
* implementation of actual widget type.
*
* @method
* @returns {Promise<NoteDetailWidget>}
*/
this.getActiveNoteDetailWidget = () => new Promise(resolve => appContext.triggerCommand('executeInActiveNoteDetailWidget', {callback: resolve}));
/**
* @method
* @deprecated use getActiveContextNotePath() instead
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
*/
this.getActiveTabNotePath = () => {
console.warn("api.getActiveTabNotePath() is deprecated, use getActiveContextNotePath() instead.");
return appContext.tabManager.getActiveContextNotePath();
};
/**
* @method
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
*/
this.getActiveTabNotePath = () => appContext.tabManager.getActiveContextNotePath();
this.getActiveContextNotePath = () => appContext.tabManager.getActiveContextNotePath();
/**
* Returns component which owns given DOM element (the nearest parent component in DOM tree)
*
* @method
* @param {Element} el - DOM element
* @returns {Component}
*/
this.getComponentByEl = el => appContext.getComponentByEl(el);
/**
* @method
+1 -5
View File
@@ -23,11 +23,7 @@ function setupGlobs() {
window.glob.treeCache = froca; // compatibility for CKEditor builds for a while
// for CKEditor integration (button on block toolbar)
window.glob.importMarkdownInline = async () => {
const dialog = await import("../dialogs/markdown_import.js");
dialog.importMarkdownInline();
};
window.glob.importMarkdownInline = async () => appContext.triggerCommand("importMarkdownInline");
window.glob.SEARCH_HELP_TEXT = `
<strong>Search tips</strong> - also see <button class="btn btn-sm" type="button" data-help-page="Search">complete help on search</button>
+2 -3
View File
@@ -1,5 +1,6 @@
import appContext from "./app_context.js";
import treeService from "./tree.js";
import dialogService from "../widgets/dialog.js";
function getHoistedNoteId() {
const activeNoteContext = appContext.tabManager.getActiveContext();
@@ -36,9 +37,7 @@ async function checkNoteAccess(notePath, noteContext) {
const hoistedNoteId = noteContext.hoistedNoteId;
if (!resolvedNotePath.includes(hoistedNoteId) && !resolvedNotePath.includes("hidden")) {
const confirmDialog = await import('../dialogs/confirm.js');
if (!await confirmDialog.confirm("Requested note is outside of hoisted note subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?")) {
if (!await dialogService.confirm("Requested note is outside of hoisted note subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?")) {
return false;
}
+17 -1
View File
@@ -56,6 +56,20 @@ const MERMAID = {
js: [ "libraries/mermaid.min.js" ]
}
const EXCALIDRAW = {
js: [
"node_modules/react/umd/react.production.min.js",
"node_modules/react-dom/umd/react-dom.production.min.js",
"node_modules/@excalidraw/excalidraw/dist/excalidraw.production.min.js",
]
};
const MARKJS = {
js: [
"libraries/jquery.mark.es6.min.js"
]
};
async function requireLibrary(library) {
if (library.css) {
library.css.map(cssUrl => requireCss(cssUrl));
@@ -106,5 +120,7 @@ export default {
KATEX,
WHEEL_ZOOM,
FORCE_GRAPH,
MERMAID
MERMAID,
EXCALIDRAW,
MARKJS
}
+3 -3
View File
@@ -6,9 +6,9 @@ function openContextMenu(notePath, e) {
x: e.pageX,
y: e.pageY,
items: [
{title: "Open note in a new tab", command: "openNoteInNewTab", uiIcon: "empty"},
{title: "Open note in a new split", command: "openNoteInNewSplit", uiIcon: "dock-right"},
{title: "Open note in a new window", command: "openNoteInNewWindow", uiIcon: "window-open"}
{title: "Open note in a new tab", command: "openNoteInNewTab", uiIcon: "bx bx-empty"},
{title: "Open note in a new split", command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right"},
{title: "Open note in a new window", command: "openNoteInNewWindow", uiIcon: "bx bx-window-open"}
],
selectMenuItemHandler: ({command}) => {
if (command === 'openNoteInNewTab') {
+12 -3
View File
@@ -140,7 +140,9 @@ function initNoteAutocomplete($el, options) {
appendTo: document.querySelector('body'),
hint: false,
autoselect: true,
openOnFocus: true,
// openOnFocus has to be false, otherwise re-focus (after return from note type chooser dialog) forces
// re-querying of the autocomplete source which then changes currently selected suggestion
openOnFocus: false,
minLength: 0,
tabAutocomplete: false
}, [
@@ -170,9 +172,17 @@ function initNoteAutocomplete($el, options) {
}
if (suggestion.action === 'create-note') {
const {success, noteType, templateNoteId} = await noteCreateService.chooseNoteType();
if (!success) {
return;
}
const {note} = await noteCreateService.createNote(suggestion.parentNoteId, {
title: suggestion.noteTitle,
activate: false
activate: false,
type: noteType,
templateNoteId: templateNoteId
});
suggestion.notePath = treeService.getSomeNotePath(note);
@@ -261,7 +271,6 @@ function init() {
}
export default {
autocompleteSource,
autocompleteSourceForCKEditor,
initNoteAutocomplete,
showRecentNotes,
@@ -141,6 +141,27 @@ async function getRenderedContent(note, options = {}) {
$renderedContent.append($content);
}
else if (type === 'canvas') {
// make sure surrounding container has size of what is visible. Then image is shrinked to its boundaries
$renderedContent.css({height: "100%", width:"100%"});
const noteComplement = await froca.getNoteComplement(note.noteId);
const content = noteComplement.content || "";
try {
const placeHolderSVG = "<svg />";
const data = JSON.parse(content)
const svg = data.svg || placeHolderSVG;
/**
* maxWidth: size down to 100% (full) width of container but do not enlarge!
* height:auto to ensure that height scales with width
*/
$renderedContent.append($(svg).css({maxWidth: "100%", maxHeight: "100%", height: "auto", width: "auto"}));
} catch(err) {
console.error("error parsing content as JSON", content, err);
$renderedContent.append($("<div>").text("Error parsing content. Please check console.error() for more details."));
}
}
else if (!options.tooltip && type === 'protected-session') {
const $button = $(`<button class="btn btn-sm"><span class="bx bx-log-in"></span> Enter protected session</button>`)
.on('click', protectedSessionService.enterProtectedSession);
+29
View File
@@ -226,6 +226,35 @@ class NoteContext extends Component {
&& this.note.mime !== 'text/x-sqlite;schema=trilium'
&& !this.note.hasLabel('hideChildrenOverview');
}
async getTextEditor(callback) {
return new Promise(resolve => appContext.triggerCommand('executeWithTextEditor', {
callback,
resolve,
ntxId: this.ntxId
}));
}
async getCodeEditor() {
return new Promise(resolve => appContext.triggerCommand('executeWithCodeEditor', {
resolve,
ntxId: this.ntxId
}));
}
async getContentElement() {
return new Promise(resolve => appContext.triggerCommand('executeWithContentElement', {
resolve,
ntxId: this.ntxId
}));
}
async getTypeWidget() {
return new Promise(resolve => appContext.triggerCommand('executeWithTypeWidget', {
resolve,
ntxId: this.ntxId
}));
}
}
export default NoteContext;
+29 -9
View File
@@ -24,12 +24,10 @@ async function createNote(parentNotePath, options = {}) {
options.saveSelection = false;
}
if (options.saveSelection && utils.isCKEditorInitialized()) {
[options.title, options.content] = parseSelectedHtml(window.cutToNote.getSelectedHtml());
if (options.saveSelection) {
[options.title, options.content] = parseSelectedHtml(options.textEditor.getSelectedHtml());
}
const newNoteName = options.title || "new note";
const parentNoteId = treeService.getNoteIdFromNotePath(parentNotePath);
if (options.type === 'mermaid' && !options.content) {
@@ -41,16 +39,17 @@ async function createNote(parentNotePath, options = {}) {
}
const {note, branch} = await server.post(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId || ""}`, {
title: newNoteName,
title: options.title,
content: options.content || "",
isProtected: options.isProtected,
type: options.type,
mime: options.mime
mime: options.mime,
templateNoteId: options.templateNoteId
});
if (options.saveSelection && utils.isCKEditorInitialized()) {
if (options.saveSelection) {
// we remove the selection only after it was saved to server to make sure we don't lose anything
window.cutToNote.removeSelection();
options.textEditor.removeSelection();
}
await ws.waitForMaxKnownEntityChangeId();
@@ -76,6 +75,25 @@ async function createNote(parentNotePath, options = {}) {
};
}
async function chooseNoteType() {
return new Promise(res => {
appContext.triggerCommand("chooseNoteType", {callback: res});
});
}
async function createNoteWithTypePrompt(parentNotePath, options = {}) {
const {success, noteType, templateNoteId} = await chooseNoteType();
if (!success) {
return;
}
options.type = noteType;
options.templateNoteId = templateNoteId;
return await createNote(parentNotePath, options);
}
/* If first element is heading, parse it out and use it as a new heading. */
function parseSelectedHtml(selectedHtml) {
const dom = $.parseHTML(selectedHtml);
@@ -107,5 +125,7 @@ async function duplicateSubtree(noteId, parentNotePath) {
export default {
createNote,
duplicateSubtree
createNoteWithTypePrompt,
duplicateSubtree,
chooseNoteType
};
@@ -99,13 +99,15 @@ const TPL = `
padding: 10px;
}
.note-book-content.type-image img {
.note-book-content.type-image img, .note-book-content.type-canvas svg {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.note-book-card.type-image .note-book-content img, .note-book-card.type-text .note-book-content img {
.note-book-card.type-image .note-book-content img,
.note-book-card.type-text .note-book-content img,
.note-book-card.type-canvas .note-book-content img {
max-width: 100%;
max-height: 100%;
}
+1 -2
View File
@@ -22,8 +22,7 @@ async function mouseEnterHandler() {
const $link = $(this);
if ($link.hasClass("no-tooltip-preview")
|| $link.hasClass("disabled")
|| $link.attr("data-action") === 'note-revision') {
|| $link.hasClass("disabled")) {
return;
}
+40
View File
@@ -0,0 +1,40 @@
import server from "./server.js";
import froca from "./froca.js";
async function getNoteTypeItems(command) {
const items = [
{ title: "Text", command: command, type: "text", uiIcon: "bx bx-note" },
{ title: "Code", command: command, type: "code", uiIcon: "bx bx-code" },
{ title: "Saved Search", command: command, type: "search", uiIcon: "bx bx-file-find" },
{ title: "Relation Map", command: command, type: "relation-map", uiIcon: "bx bx-map-alt" },
{ title: "Note Map", command: command, type: "note-map", uiIcon: "bx bx-map-alt" },
{ title: "Render Note", command: command, type: "render", uiIcon: "bx bx-extension" },
{ title: "Book", command: command, type: "book", uiIcon: "bx bx-book" },
{ title: "Mermaid Diagram", command: command, type: "mermaid", uiIcon: "bx bx-selection" },
{ title: "Canvas", command: command, type: "canvas", uiIcon: "bx bx-pen" },
{ title: "Web View", command: command, type: "web-view", uiIcon: "bx bx-globe-alt" },
];
const templateNoteIds = await server.get("search-templates");
const templateNotes = await froca.getNotes(templateNoteIds);
if (templateNotes.length > 0) {
items.push({ title: "----" });
for (const templateNote of templateNotes) {
items.push({
title: templateNote.title,
uiIcon: templateNote.getIcon(),
command: command,
type: templateNote.type,
templateNoteId: templateNote.noteId
});
}
}
return items;
}
export default {
getNoteTypeItems
}
+5 -5
View File
@@ -20,7 +20,7 @@ function enterProtectedSession() {
const dfd = $.Deferred();
if (!options.is("isPasswordSet")) {
import("../dialogs/password_not_set.js").then(dialog => dialog.show());
appContext.triggerCommand("showPasswordNotSet");
return dfd;
}
@@ -31,7 +31,7 @@ function enterProtectedSession() {
// using deferred instead of promise because it allows resolving from outside
protectedSessionDeferred = dfd;
import("../dialogs/protected_session.js").then(dialog => dialog.show());
appContext.triggerCommand("showProtectedSessionPasswordDialog");
}
return dfd.promise();
@@ -61,13 +61,13 @@ ws.subscribeToMessages(async message => {
if (message.type === 'protectedSessionLogin') {
await reloadData();
await appContext.triggerEvent('frocaReloaded');
await appContext.triggerEvent('frocaReloaded');
appContext.triggerEvent('protectedSessionStarted');
if (protectedSessionDeferred !== null) {
import("../dialogs/protected_session.js").then(dialog => dialog.close());
appContext.triggerCommand("closeProtectedSessionPasswordDialog");
if (protectedSessionDeferred !== null) {
protectedSessionDeferred.resolve(true);
protectedSessionDeferred = null;
}
@@ -1,17 +1,5 @@
import options from './options.js';
import server from "./server.js";
let lastProtectedSessionOperationDate = 0;
setInterval(() => {
const protectedSessionTimeout = options.getInt('protectedSessionTimeout');
if (lastProtectedSessionOperationDate
&& Date.now() - lastProtectedSessionOperationDate > protectedSessionTimeout * 1000) {
resetProtectedSession();
}
}, 10000);
function enableProtectedSession() {
glob.isProtectedSessionAvailable = true;
@@ -26,9 +14,9 @@ function isProtectedSessionAvailable() {
return glob.isProtectedSessionAvailable;
}
function touchProtectedSession() {
async function touchProtectedSession() {
if (isProtectedSessionAvailable()) {
lastProtectedSessionOperationDate = Date.now();
await server.post("login/protected/touch");
}
}
@@ -8,35 +8,6 @@ import options from "./options.js";
import froca from "./froca.js";
export default class RootCommandExecutor extends Component {
jumpToNoteCommand() {
import("../dialogs/jump_to_note.js").then(d => d.showDialog());
}
showRecentChangesCommand() {
import("../dialogs/recent_changes.js").then(d => d.showDialog());
}
showNoteRevisionsCommand() {
import("../dialogs/note_revisions.js").then(d => d.showCurrentNoteRevisions());
}
showNoteSourceCommand() {
import("../dialogs/note_source.js").then(d => d.showDialog());
}
pasteMarkdownIntoTextCommand() {
import("../dialogs/markdown_import.js").then(d => d.importMarkdownInline());
}
async editBranchPrefixCommand() {
const notePath = appContext.tabManager.getActiveContextNotePath();
if (notePath) {
const editBranchPrefixDialog = await import("../dialogs/branch_prefix.js");
editBranchPrefixDialog.showDialog(notePath);
}
}
editReadOnlyNoteCommand() {
const noteContext = appContext.tabManager.getActiveContext();
noteContext.readOnlyTemporarilyDisabled = true;
@@ -44,24 +15,6 @@ export default class RootCommandExecutor extends Component {
appContext.triggerEvent("readOnlyTemporarilyDisabled", { noteContext });
}
async cloneNoteIdsToCommand({noteIds}) {
const d = await import("../dialogs/clone_to.js");
d.showDialog(noteIds);
}
async moveBranchIdsToCommand({branchIds}) {
const d = await import("../dialogs/move_to.js");
d.showDialog(branchIds);
}
showOptionsCommand({openTab}) {
import("../dialogs/options.js").then(d => d.showDialog(openTab));
}
showHelpCommand() {
import("../dialogs/help.js").then(d => d.showDialog());
}
async showSQLConsoleCommand() {
const sqlConsoleNote = await dateNoteService.createSqlConsole();
@@ -90,10 +43,6 @@ export default class RootCommandExecutor extends Component {
this.searchNotesCommand({ancestorNoteId: noteId});
}
showBackendLogCommand() {
import("../dialogs/backend_log.js").then(d => d.showDialog());
}
openNoteExternallyCommand() {
const noteId = appContext.tabManager.getActiveContextNoteId();
+33 -9
View File
@@ -306,7 +306,8 @@ export default class TabManager extends Component {
const mainNoteContexts = this.getNoteContexts().filter(nc => nc.isMainContext());
if (mainNoteContexts.length === 1) {
mainNoteContexts[0].setEmpty();
await this.clearLastMainNoteContext(noteContextToRemove);
return;
}
}
@@ -317,7 +318,7 @@ export default class TabManager extends Component {
const noteContextsToRemove = noteContextToRemove.getSubContexts();
const ntxIdsToRemove = noteContextsToRemove.map(nc => nc.ntxId);
await this.triggerEvent('beforeTabRemove', { ntxIds: ntxIdsToRemove });
await this.triggerEvent('beforeNoteContextRemove', { ntxIds: ntxIdsToRemove });
if (!noteContextToRemove.isMainContext()) {
await this.activateNoteContext(noteContextToRemove.getMainContext().ntxId);
@@ -336,16 +337,39 @@ export default class TabManager extends Component {
}
}
this.children = this.children.filter(nc => !ntxIdsToRemove.includes(nc.ntxId));
this.recentlyClosedTabs.push(noteContextsToRemove);
this.triggerEvent('noteContextRemoved', {ntxIds: ntxIdsToRemove});
this.tabsUpdate.scheduleUpdate();
this.removeNoteContexts(noteContextsToRemove);
});
}
async clearLastMainNoteContext(noteContextToClear) {
noteContextToClear.setEmpty();
// activate main split
await this.activateNoteContext(noteContextToClear.ntxId);
// remove all other splits
const noteContextsToRemove = noteContextToClear.getSubContexts()
.filter(ntx => ntx.ntxId !== noteContextToClear.ntxId);
const ntxIdsToRemove = noteContextsToRemove.map(ntx => ntx.ntxId);
await this.triggerEvent('beforeNoteContextRemove', {ntxIds: ntxIdsToRemove});
this.removeNoteContexts(noteContextsToRemove);
}
removeNoteContexts(noteContextsToRemove) {
const ntxIdsToRemove = noteContextsToRemove.map(nc => nc.ntxId);
this.children = this.children.filter(nc => !ntxIdsToRemove.includes(nc.ntxId));
this.recentlyClosedTabs.push(noteContextsToRemove);
this.triggerEvent('noteContextRemoved', {ntxIds: ntxIdsToRemove});
this.tabsUpdate.scheduleUpdate();
}
tabReorderEvent({ntxIdsInOrder}) {
const order = {};
+43 -47
View File
@@ -4,6 +4,7 @@ import clipboard from './clipboard.js';
import noteCreateService from "./note_create.js";
import contextMenu from "./context_menu.js";
import appContext from "./app_context.js";
import noteTypesService from "./note_types.js";
class TreeContextMenu {
/**
@@ -24,19 +25,6 @@ class TreeContextMenu {
})
}
getNoteTypeItems(command) {
return [
{ title: "Text", command: command, type: "text", uiIcon: "note" },
{ title: "Code", command: command, type: "code", uiIcon: "code" },
{ title: "Saved search", command: command, type: "search", uiIcon: "file-find" },
{ title: "Relation Map", command: command, type: "relation-map", uiIcon: "map-alt" },
{ title: "Note Map", command: command, type: "note-map", uiIcon: "map-alt" },
{ title: "Render HTML note", command: command, type: "render", uiIcon: "extension" },
{ title: "Book", command: command, type: "book", uiIcon: "book" },
{ title: "Mermaid diagram", command: command, type: "mermaid", uiIcon: "selection" }
];
}
async getMenuItems() {
const note = await froca.getNote(this.node.data.noteId);
const branch = froca.getBranch(this.node.data.branchId);
@@ -56,58 +44,59 @@ class TreeContextMenu {
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
return [
{ title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "empty", enabled: noSelectedNotes },
{ title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "dock-right", enabled: noSelectedNotes },
{ title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "plus",
items: insertNoteAfterEnabled ? this.getNoteTypeItems("insertNoteAfter") : null,
{ title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes },
{ title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes },
{ title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "plus",
items: notSearch ? this.getNoteTypeItems("insertChildNote") : null,
{ title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes },
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "trash",
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash",
enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: "----" },
{ title: 'Search in subtree <kbd data-command="searchInSubtree"></kbd>', command: "searchInSubtree", uiIcon: "search",
{ title: 'Search in subtree <kbd data-command="searchInSubtree"></kbd>', command: "searchInSubtree", uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes },
isHoisted ? null : { title: 'Hoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "empty", enabled: noSelectedNotes && notSearch },
!isHoisted || !isNotRoot ? null : { title: 'Unhoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "door-open" },
{ title: 'Edit branch prefix <kbd data-command="editBranchPrefix"></kbd>', command: "editBranchPrefix", uiIcon: "empty",
isHoisted ? null : { title: 'Hoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
!isHoisted || !isNotRoot ? null : { title: 'Unhoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: 'Edit branch prefix <kbd data-command="editBranchPrefix"></kbd>', command: "editBranchPrefix", uiIcon: "bx bx-empty",
enabled: isNotRoot && parentNotSearch && noSelectedNotes},
{ title: "Advanced", uiIcon: "empty", enabled: true, items: [
{ title: 'Expand subtree <kbd data-command="expandSubtree"></kbd>', command: "expandSubtree", uiIcon: "expand", enabled: noSelectedNotes },
{ title: 'Collapse subtree <kbd data-command="collapseSubtree"></kbd>', command: "collapseSubtree", uiIcon: "collapse", enabled: noSelectedNotes },
{ title: "Force note sync", command: "forceNoteSync", uiIcon: "refresh", enabled: noSelectedNotes },
{ title: 'Sort by ... <kbd data-command="sortChildNotes"></kbd>', command: "sortChildNotes", uiIcon: "empty", enabled: noSelectedNotes && notSearch },
{ title: 'Recent changes in subtree', command: "recentChangesInSubtree", uiIcon: "history", enabled: noSelectedNotes }
{ title: "Advanced", uiIcon: "bx bx-empty", enabled: true, items: [
{ title: 'Expand subtree <kbd data-command="expandSubtree"></kbd>', command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: 'Collapse subtree <kbd data-command="collapseSubtree"></kbd>', command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: "Force note sync", command: "forceNoteSync", uiIcon: "bx bx-refresh", enabled: noSelectedNotes },
{ title: 'Sort by ... <kbd data-command="sortChildNotes"></kbd>', command: "sortChildNotes", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
{ title: 'Recent changes in subtree', command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes }
] },
{ title: "----" },
{ title: "Protect subtree", command: "protectSubtree", uiIcon: "check-shield", enabled: noSelectedNotes },
{ title: "Unprotect subtree", command: "unprotectSubtree", uiIcon: "shield", enabled: noSelectedNotes },
{ title: "Protect subtree", command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: "Unprotect subtree", command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ title: "----" },
{ title: 'Copy / clone <kbd data-command="copyNotesToClipboard"></kbd>', command: "copyNotesToClipboard", uiIcon: "copy",
{ title: 'Copy / clone <kbd data-command="copyNotesToClipboard"></kbd>', command: "copyNotesToClipboard", uiIcon: "bx bx-copy",
enabled: isNotRoot && !isHoisted },
{ title: 'Clone to ... <kbd data-command="cloneNotesTo"></kbd>', command: "cloneNotesTo", uiIcon: "empty",
{ title: 'Clone to ... <kbd data-command="cloneNotesTo"></kbd>', command: "cloneNotesTo", uiIcon: "bx bx-empty",
enabled: isNotRoot && !isHoisted },
{ title: 'Cut <kbd data-command="cutNotesToClipboard"></kbd>', command: "cutNotesToClipboard", uiIcon: "cut",
{ title: 'Cut <kbd data-command="cutNotesToClipboard"></kbd>', command: "cutNotesToClipboard", uiIcon: "bx bx-cut",
enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: 'Move to ... <kbd data-command="moveNotesTo"></kbd>', command: "moveNotesTo", uiIcon: "empty",
{ title: 'Move to ... <kbd data-command="moveNotesTo"></kbd>', command: "moveNotesTo", uiIcon: "bx bx-empty",
enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: 'Paste into <kbd data-command="pasteNotesFromClipboard"></kbd>', command: "pasteNotesFromClipboard", uiIcon: "paste",
{ title: 'Paste into <kbd data-command="pasteNotesFromClipboard"></kbd>', command: "pasteNotesFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes },
{ title: 'Paste after', command: "pasteNotesAfterFromClipboard", uiIcon: "paste",
{ title: 'Paste after', command: "pasteNotesAfterFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes },
{ title: `Duplicate subtree <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "empty",
{ title: `Duplicate subtree <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty",
enabled: parentNotSearch && isNotRoot && !isHoisted },
{ title: "----" },
{ title: "Export", command: "exportNote", uiIcon: "empty",
{ title: "Export", command: "exportNote", uiIcon: "bx bx-empty",
enabled: notSearch && noSelectedNotes },
{ title: "Import into note", command: "importIntoNote", uiIcon: "empty",
enabled: notSearch && noSelectedNotes }
{ title: "Import into note", command: "importIntoNote", uiIcon: "bx bx-empty",
enabled: notSearch && noSelectedNotes },
{ title: "Apply bulk actions", command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus",
enabled: true }
].filter(row => row !== null);
}
async selectMenuItemHandler({command, type}) {
const noteId = this.node.data.noteId;
async selectMenuItemHandler({command, type, templateNoteId}) {
const notePath = treeService.getNotePath(this.node);
if (command === 'openInTab') {
@@ -121,7 +110,8 @@ class TreeContextMenu {
target: 'after',
targetBranchId: this.node.data.branchId,
type: type,
isProtected: isProtected
isProtected: isProtected,
templateNoteId: templateNoteId
});
}
else if (command === "insertChildNote") {
@@ -129,7 +119,8 @@ class TreeContextMenu {
noteCreateService.createNote(parentNotePath, {
type: type,
isProtected: this.node.data.isProtected
isProtected: this.node.data.isProtected,
templateNoteId: templateNoteId
});
}
else if (command === 'openNoteInSplit') {
@@ -139,7 +130,12 @@ class TreeContextMenu {
this.treeWidget.triggerCommand("openNewNoteSplit", {ntxId, notePath});
}
else {
this.treeWidget.triggerCommand(command, {node: this.node, notePath: notePath});
this.treeWidget.triggerCommand(command, {
node: this.node,
notePath: notePath,
selectedOrActiveBranchIds: this.treeWidget.getSelectedOrActiveBranchIds(this.node),
selectedOrActiveNoteIds: this.treeWidget.getSelectedOrActiveNoteIds(this.node)
});
}
}
}

Some files were not shown because too many files have changed in this diff Show More