Compare commits

...

61 Commits

Author SHA1 Message Date
zadam
5115b33446 release 0.61.10-beta 2023-10-19 09:33:51 +02:00
zadam
b01fe5ead9 add canvas properties with a button to copy reference to clipboard which allows inserting canvas as an image into text notes 2023-10-19 09:20:23 +02:00
zadam
b1d4a258a1 move FAB down in canvas 2023-10-19 09:03:49 +02:00
zadam
ca041bb658 fix expanded status when moving note trees 2023-10-19 08:58:04 +02:00
zadam
87a60e325f added ctime to backup list #4321 2023-10-19 00:51:38 +02:00
zadam
0a172d8bc1 add api.runOutsideOfSync() to backend script API, #4327 2023-10-19 00:29:03 +02:00
zadam
67a12d3c4d improve sync error logging 2023-10-19 00:13:11 +02:00
zadam
5b2ba3646d removed maxTouchPoints condition for detection of mobile browsers, #4316 2023-10-18 23:23:20 +02:00
zadam
148bff9f77 show existing backups and anonymized DBs, #4321 2023-10-18 23:16:47 +02:00
zadam
2132cf3bdc nodejs 18.18.2 2023-10-18 09:40:00 +02:00
zadam
d5271c17e3 fix sync bug 2023-10-18 09:37:36 +02:00
zadam
b764761e58 run local dev with TRILIUM_SAFE_MODE as a safety precaution 2023-10-18 09:36:49 +02:00
zadam
c666fc3b98 make sure exact noteId match comes on the top in search 2023-10-18 09:33:24 +02:00
zadam
ba34df2e15 typo 2023-10-18 09:24:13 +02:00
zadam
840ac2d63e updates 2023-10-14 21:15:06 +02:00
zadam
5dd4586ebe added webViewSrc to builtin attrs 2023-10-14 21:09:20 +02:00
zadam
d09d3f5a96 release 0.61.9-beta 2023-10-07 23:02:47 +03:00
zadam
3d15aeae58 def value 2023-10-07 23:02:33 +03:00
zadam
9765892d18 fix loading canvas notes created in 0.61.7-beta, closes #4313 2023-10-07 21:49:25 +03:00
zadam
78f8a37587 added total result count to the note list widget 2023-10-06 22:02:09 +03:00
zadam
86d62866f2 catch JSON stringify error, #4310 2023-10-05 21:54:59 +02:00
zadam
1dc3fafcbf improve anonymization 2023-10-03 23:17:15 +02:00
zadam
7f06952d9e improve anonymization 2023-10-03 23:14:02 +02:00
zadam
78b6614eea fix docker-compose.yml #2239 2023-10-03 11:21:14 +02:00
zadam
9665e872c2 fix importing inline images within markdown within zip, closes #4301 2023-10-03 09:40:31 +02:00
zadam
9db0a062ed fix calculating revision attachment size 2023-10-03 09:05:30 +02:00
zadam
055bb39e4d Merge remote-tracking branch 'origin/beta' into beta 2023-10-02 22:02:31 +02:00
zadam
1261a06a30 order by note size + attachments + revisions, closes #4295 2023-10-02 22:02:25 +02:00
zadam
91eb3c45d5 added "save revision" to note actions menu 2023-10-02 15:29:45 +02:00
zadam
3944235592 -console.log 2023-10-02 15:25:12 +02:00
zadam
5be61e6142 saving / viewing canvas revisions 2023-10-02 15:24:40 +02:00
zadam
62ccf798ee allow deleting custom launchers, fixes #4291 2023-09-30 22:38:06 +02:00
zadam
70d6bd0157 release 0.61.8-beta 2023-09-29 00:54:45 +02:00
zadam
e5555beea9 logging reason for frontend reload 2023-09-28 23:47:19 +02:00
zadam
9767b6269a upgrade code mirror to 5.65.15 and fix modes requiring multiplex or overlay, fixes #4279 2023-09-28 01:02:27 +02:00
zadam
7e486fda06 electron update 2023-09-28 00:27:00 +02:00
zadam
9f726304aa sync fix, #4288 2023-09-28 00:24:53 +02:00
zadam
be918628c3 global API docs 2023-09-25 23:04:03 +02:00
zadam
602b9ae64a API docs 2023-09-23 00:04:32 +02:00
zadam
602a166e36 added info, confirm, prompt dialogs 2023-09-23 00:04:16 +02:00
zadam
aaad858395 save scroll and zoom in canvas 2023-09-22 23:44:03 +02:00
zadam
48248224f8 release 0.61.7-beta 2023-09-21 23:38:18 +02:00
zadam
79e5e3b65f more logging for sync 2023-09-21 18:13:14 +02:00
zadam
d0383f3044 remove debian packaging hack 2023-09-21 12:44:20 +02:00
zadam
62ecd1ad76 node 18.18.0 2023-09-21 12:29:11 +02:00
zadam
75b7706c2c mermaid 10.4.0 2023-09-21 12:24:44 +02:00
zadam
584b176643 hiding useless/misleading buttons from excalidraw 2023-09-21 12:03:40 +02:00
zadam
a16555bbff don't save appState in canvas - app state should be reset after each load 2023-09-21 11:54:54 +02:00
zadam
a749e24147 fix creating revisions for non-text notes #4176 2023-09-21 11:38:38 +02:00
zadam
bb81f110dd improved error handling 2023-09-21 11:16:03 +02:00
zadam
5dd6f49104 chart js 0.16.0 2023-09-19 23:59:05 +02:00
zadam
bc6be44b19 better error condition checks 2023-09-19 23:48:55 +02:00
zadam
8075265753 fix migration, closes #4262 2023-09-18 23:45:00 +02:00
zadam
4a67f63abd better error message in image attachment + upgrades 2023-09-14 00:18:56 +02:00
zadam
d9666210f1 make sure that the hidden note is never selected when hoisted to root to avoid e.g. erroneous deletion 2023-09-13 16:57:24 +02:00
zadam
5f6d562bf8 add ability to excalidraw to follow links 2023-09-08 23:00:43 +02:00
zadam
f37dc66074 add support for storing canvas libraries in note attachments plus storing exported SVG in attachment 2023-09-08 21:53:57 +02:00
zadam
0b84524807 fix refreshing note actions on note/tab switch, closes #4247 2023-09-08 00:43:18 +02:00
zadam
8062bb7e2a fix reloading unprotected note title to the document.title after entering protected session, fixes #4244 2023-09-08 00:28:00 +02:00
zadam
806062c8d1 fix undelete attachments 2023-09-08 00:22:48 +02:00
zadam
83f19c0537 fix protecting attachments 2023-09-08 00:19:30 +02:00
126 changed files with 4832 additions and 1943 deletions

View File

@@ -75,7 +75,6 @@ module.exports = {
glob: true,
log: true,
EditorWatchdog: true,
// \src\share\canvas_share.js
React: true,
appState: true,
ExcalidrawLib: true,

View File

@@ -2,7 +2,7 @@ image:
file: .gitpod.dockerfile
tasks:
- before: nvm install 18.16.1 && nvm use 18.16.1
- before: nvm install 18.18.2 && nvm use 18.18.2
init: npm install
command: npm run start-server

View File

@@ -1,5 +1,5 @@
# !!! Don't try to build this Dockerfile directly, run it through bin/build-docker.sh script !!!
FROM node:18.16.1-alpine
FROM node:18.18.2-alpine
# Create app directory
WORKDIR /usr/src/app

View File

@@ -5,18 +5,3 @@ echo "Packaging debian x64 distribution..."
VERSION=`jq -r ".version" package.json`
./node_modules/.bin/electron-installer-debian --config bin/deb-options.json --options.version=${VERSION} --arch amd64
# hacky stop-gag measure to produce debian compatible XZ compressed debs until this is fixed: https://github.com/electron-userland/electron-installer-debian/issues/272
cd dist
ar x trilium_${VERSION}_amd64.deb
rm trilium_${VERSION}_amd64.deb
# recompress
< control.tar.zst zstd -d | xz > control.tar.xz
< data.tar.zst zstd -d | xz > data.tar.xz
# create deb archive (I really do not know, what argument "sdsd" is for but something is required for ar to create the archive as desired)
ar -m -c -a sdsd trilium_${VERSION}_amd64.deb debian-binary control.tar.xz data.tar.xz
rm control* data* debian-binary
echo "Converted to XZ deb"

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
PKG_DIR=dist/trilium-linux-x64-server
NODE_VERSION=18.16.1
NODE_VERSION=18.18.2
if [ "$1" != "DONTCOPY" ]
then

View File

@@ -5,7 +5,7 @@ if [[ $# -eq 0 ]] ; then
exit 1
fi
n exec 18.16.1 npm run webpack
n exec 18.18.2 npm run webpack
DIR=$1
@@ -27,7 +27,7 @@ cp -r electron.js $DIR/
cp webpack-* $DIR/
# run in subshell (so we return to original dir)
(cd $DIR && n exec 18.16.1 npm install --only=prod)
(cd $DIR && n exec 18.18.2 npm install --only=prod)
# cleanup of useless files in dependencies
rm -r $DIR/node_modules/image-q/demo

0
bin/create-anonymization-script.js Normal file → Executable file
View File

View File

@@ -1,6 +1,7 @@
{
"src": "dist/trilium-linux-x64",
"dest": "dist/",
"compression": "xz",
"name": "trilium",
"productName": "Trilium Notes",
"genericName": "Note taker",
@@ -11,4 +12,4 @@
"bin": "trilium",
"icon": "dist/trilium-linux-x64/icon.png",
"categories": [ "Office" ]
}
}

View File

@@ -1,165 +1,47 @@
UPDATE etapi_tokens SET tokenHash = 'API token hash value';
UPDATE notes SET title = 'title' WHERE noteId != 'root' AND noteId NOT LIKE '\_%' ESCAPE '\';
UPDATE notes SET title = 'title' WHERE title NOT IN ('root', '_hidden', '_share');
UPDATE blobs SET content = 'text' WHERE content IS NOT NULL;
UPDATE revisions SET title = 'title';
UPDATE attributes SET name = 'name', value = 'value'
WHERE type = 'label'
AND name NOT IN ('inbox',
'disableVersioning',
'calendarRoot',
'archived',
'excludeFromExport',
'disableInclusion',
'appCss',
'appTheme',
'hidePromotedAttributes',
'readOnly',
'autoReadOnlyDisabled',
'cssClass',
'iconClass',
'keyboardShortcut',
'run',
'runOnInstance',
'runAtHour',
'customRequestHandler',
'customResourceProvider',
'widget',
'noteInfoWidgetDisabled',
'linkMapWidgetDisabled',
'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled',
'similarNotesWidgetDisabled',
'workspace',
'workspaceIconClass',
'workspaceTabBackgroundColor',
'searchHome',
'workspaceInbox',
'workspaceSearchHome',
'sqlConsoleHome',
'datePattern',
'pageSize',
'viewType',
'mapRootNoteId',
'bookmarkFolder',
'sorted',
'top',
'fullContentWidth',
'shareHiddenFromTree',
'shareAlias',
'shareOmitDefaultCss',
'shareRoot',
'internalLink',
'imageLink',
'relationMapLink',
'includeMapLink',
'runOnNoteCreation',
'runOnNoteTitleChange',
'runOnNoteContentChange',
'runOnNoteChange',
'runOnChildNoteCreation',
'runOnAttributeCreation',
'runOnAttributeChange',
'template',
'inherit',
'widget',
'renderNote',
'shareCss',
'shareJs',
'shareFavicon',
'executeButton',
'keepCurrentHoisting',
'color',
'toc',
'excludeFromNoteMap',
'docName',
'launcherType',
'builtinWidget',
'baseSize',
'growthFactor'
);
UPDATE attributes SET name = 'name'
AND name NOT IN ('inbox',
'disableVersioning',
'calendarRoot',
'archived',
'excludeFromExport',
'disableInclusion',
'appCss',
'appTheme',
'hidePromotedAttributes',
'readOnly',
'autoReadOnlyDisabled',
'cssClass',
'iconClass',
'keyboardShortcut',
'run',
'runOnInstance',
'runAtHour',
'customRequestHandler',
'customResourceProvider',
'widget',
'noteInfoWidgetDisabled',
'linkMapWidgetDisabled',
'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled',
'similarNotesWidgetDisabled',
'workspace',
'workspaceIconClass',
'workspaceTabBackgroundColor',
'searchHome',
'workspaceInbox',
'workspaceSearchHome',
'sqlConsoleHome',
'datePattern',
'pageSize',
'viewType',
'mapRootNoteId',
'bookmarkFolder',
'sorted',
'top',
'fullContentWidth',
'shareHiddenFromTree',
'shareAlias',
'shareOmitDefaultCss',
'shareRoot',
'internalLink',
'imageLink',
'relationMapLink',
'includeMapLink',
'runOnNoteCreation',
'runOnNoteTitleChange',
'runOnNoteContentChange',
'runOnNoteChange',
'runOnChildNoteCreation',
'runOnAttributeCreation',
'runOnAttributeChange',
'template',
'inherit',
'widget',
'renderNote',
'shareCss',
'shareJs',
'shareFavicon',
'executeButton',
'keepCurrentHoisting',
'color',
'toc',
'excludeFromNoteMap',
'docName',
'launcherType',
'builtinWidget',
'baseSize',
'growthFactor'
);
UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label'
AND name NOT IN
('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss',
'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass',
'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider',
'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass',
'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox',
'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId',
'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top',
'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription',
'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate',
'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop',
'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation',
'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation',
'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template',
'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
UPDATE attributes SET name = 'name' WHERE type = 'relation'
AND name NOT IN
('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss',
'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass',
'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider',
'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass',
'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox',
'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId',
'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top',
'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription',
'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate',
'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop',
'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation',
'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation',
'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template',
'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL AND prefix != 'recovered';
UPDATE options SET value = 'anonymized' WHERE name IN
('documentId', 'documentSecret', 'encryptedDataKey',
'passwordVerificationHash', 'passwordVerificationSalt',
'passwordDerivedKeySalt', 'username', 'syncServerHost', 'syncProxy')
AND value != '';
('documentId', 'documentSecret', 'encryptedDataKey',
'passwordVerificationHash', 'passwordVerificationSalt',
'passwordDerivedKeySalt', 'username', 'syncServerHost', 'syncProxy')
AND value != '';
VACUUM;

View File

@@ -0,0 +1 @@
UPDATE attributes SET value = 'contentAndAttachmentsAndRevisionsSize' WHERE name = 'orderBy' AND value = 'noteSize';

View File

@@ -1,3 +1,5 @@
# Running `docker-compose up` will create/use the "trilium-data" directory in the user home
# Run `TRILIUM_DATA_DIR=/path/of/your/choice docker-compose up` to set a different directory
version: '2.1'
services:
trilium:
@@ -8,7 +10,7 @@ services:
ports:
- "8080:8080"
volumes:
- trilium:/home/node/trilium-data
- ${TRILIUM_DATA_DIR:-~/trilium-data}:/home/node/trilium-data
volumes:
trilium:

View File

@@ -183,7 +183,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -259,7 +259,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -364,7 +364,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -484,7 +484,7 @@
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -532,7 +532,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -557,6 +557,24 @@
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
@@ -568,7 +586,7 @@
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<span class="signature">()</span><span class="type-signature"></span></h4>
@@ -616,7 +634,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
@@ -700,7 +718,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -784,7 +802,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -938,7 +956,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -1022,7 +1040,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -1110,7 +1128,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>

View File

@@ -205,7 +205,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line40">line 40</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line39">line 39</a>
</li></ul></dd>
@@ -268,7 +268,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -336,7 +336,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line52">line 52</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line51">line 51</a>
</li></ul></dd>
@@ -408,7 +408,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line63">line 63</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line62">line 62</a>
</li></ul></dd>
@@ -476,7 +476,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line56">line 56</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line55">line 55</a>
</li></ul></dd>
@@ -544,7 +544,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line54">line 54</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line53">line 53</a>
</li></ul></dd>
@@ -612,7 +612,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line46">line 46</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line45">line 45</a>
</li></ul></dd>
@@ -684,7 +684,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line42">line 42</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line41">line 41</a>
</li></ul></dd>
@@ -752,7 +752,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line50">line 50</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line49">line 49</a>
</li></ul></dd>
@@ -820,7 +820,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line44">line 44</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line43">line 43</a>
</li></ul></dd>
@@ -888,7 +888,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line48">line 48</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line47">line 47</a>
</li></ul></dd>
@@ -956,7 +956,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line58">line 58</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line57">line 57</a>
</li></ul></dd>
@@ -1024,7 +1024,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line60">line 60</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line59">line 59</a>
</li></ul></dd>
@@ -1105,7 +1105,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -1215,7 +1215,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -1388,7 +1388,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line128">line 128</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line132">line 132</a>
</li></ul></dd>
@@ -1490,7 +1490,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line69">line 69</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line68">line 68</a>
</li></ul></dd>
@@ -1544,7 +1544,7 @@ larger amounts of data and generally not accessible to the user.</div>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -1597,7 +1597,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -1622,95 +1622,24 @@ larger amounts of data and generally not accessible to the user.</div>
<h5>Returns:</h5>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractBeccaEntity.html#generateIdIfNecessary">AbstractBeccaEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
</li></ul></dd>
</dd>
</dl>
@@ -1770,7 +1699,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line113">line 113</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line117">line 117</a>
</li></ul></dd>
@@ -1875,7 +1804,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line81">line 81</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line80">line 80</a>
</li></ul></dd>
@@ -1923,6 +1852,95 @@ larger amounts of data and generally not accessible to the user.</div>
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<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="AbstractBeccaEntity.html#getPojo">AbstractBeccaEntity#getPojo</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
</dl>
@@ -1982,7 +2000,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -2071,7 +2089,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -2155,7 +2173,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line86">line 86</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line85">line 85</a>
</li></ul></dd>
@@ -2336,7 +2354,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -2425,7 +2443,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -2518,7 +2536,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>
@@ -2815,7 +2833,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_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line123">line 123</a>
<a href="becca_entities_battachment.js.html">becca/entities/battachment.js</a>, <a href="becca_entities_battachment.js.html#line127">line 127</a>
</li></ul></dd>

View File

@@ -268,7 +268,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_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -825,7 +825,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_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -935,7 +935,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_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -1060,7 +1060,7 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -1113,7 +1113,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_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -1138,95 +1138,24 @@ and relation (representing named relationship between source and target note)</d
<h5>Returns:</h5>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractBeccaEntity.html#generateIdIfNecessary">AbstractBeccaEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
</li></ul></dd>
</dd>
</dl>
@@ -1337,6 +1266,95 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<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="AbstractBeccaEntity.html#getPojo">AbstractBeccaEntity#getPojo</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
</dl>
@@ -1396,7 +1414,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_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -1590,7 +1608,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_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -1851,7 +1869,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -1940,7 +1958,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -2033,7 +2051,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>

View File

@@ -203,7 +203,7 @@ Always check noteId instead.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -945,7 +945,7 @@ of deletion should not act as a clone.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -1055,7 +1055,7 @@ of deletion should not act as a clone.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -1384,7 +1384,7 @@ of deletion should not act as a clone.
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -1437,7 +1437,7 @@ of deletion should not act as a clone.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -1462,95 +1462,24 @@ of deletion should not act as a clone.
<h5>Returns:</h5>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractBeccaEntity.html#generateIdIfNecessary">AbstractBeccaEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
</li></ul></dd>
</dd>
</dl>
@@ -1658,6 +1587,95 @@ of deletion should not act as a clone.
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<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="AbstractBeccaEntity.html#getPojo">AbstractBeccaEntity#getPojo</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
</dl>
@@ -1717,7 +1735,7 @@ of deletion should not act as a clone.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -1806,7 +1824,7 @@ of deletion should not act as a clone.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -1965,7 +1983,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -2054,7 +2072,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -2147,7 +2165,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>

View File

@@ -205,7 +205,7 @@ from tokenHash and token.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -694,7 +694,7 @@ from tokenHash and token.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -804,7 +804,7 @@ from tokenHash and token.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -929,7 +929,7 @@ from tokenHash and token.</div>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -982,7 +982,7 @@ from tokenHash and token.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -1007,6 +1007,24 @@ from tokenHash and token.</div>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
@@ -1018,7 +1036,7 @@ from tokenHash and token.</div>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<span class="signature">()</span><span class="type-signature"></span></h4>
@@ -1048,7 +1066,7 @@ from tokenHash and token.</div>
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractBeccaEntity.html#generateIdIfNecessary">AbstractBeccaEntity#generateIdIfNecessary</a>
<a href="AbstractBeccaEntity.html#getPojo">AbstractBeccaEntity#getPojo</a>
</li></ul></dd>
@@ -1071,7 +1089,7 @@ from tokenHash and token.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
@@ -1160,7 +1178,7 @@ from tokenHash and token.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -1249,7 +1267,7 @@ from tokenHash and token.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -1408,7 +1426,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -1497,7 +1515,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -1590,7 +1608,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>

File diff suppressed because it is too large Load Diff

View File

@@ -199,7 +199,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -552,7 +552,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -662,7 +662,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -787,7 +787,7 @@
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -840,7 +840,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -865,6 +865,24 @@
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
@@ -876,7 +894,7 @@
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<span class="signature">()</span><span class="type-signature"></span></h4>
@@ -906,7 +924,7 @@
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractBeccaEntity.html#generateIdIfNecessary">AbstractBeccaEntity#generateIdIfNecessary</a>
<a href="AbstractBeccaEntity.html#getPojo">AbstractBeccaEntity#getPojo</a>
</li></ul></dd>
@@ -929,7 +947,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
@@ -1018,7 +1036,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -1107,7 +1125,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -1266,7 +1284,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -1355,7 +1373,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -1448,7 +1466,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>

View File

@@ -199,7 +199,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -484,7 +484,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -594,7 +594,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -719,7 +719,7 @@
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -772,7 +772,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -797,6 +797,24 @@
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
@@ -808,7 +826,7 @@
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<span class="signature">()</span><span class="type-signature"></span></h4>
@@ -838,7 +856,7 @@
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractBeccaEntity.html#generateIdIfNecessary">AbstractBeccaEntity#generateIdIfNecessary</a>
<a href="AbstractBeccaEntity.html#getPojo">AbstractBeccaEntity#getPojo</a>
</li></ul></dd>
@@ -861,7 +879,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
@@ -950,7 +968,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -1039,7 +1057,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -1198,7 +1216,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -1287,7 +1305,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -1380,7 +1398,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>

View File

@@ -200,7 +200,7 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line55">line 55</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line35">line 35</a>
</li></ul></dd>
@@ -1165,7 +1165,7 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line246">line 246</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line250">line 250</a>
</li></ul></dd>
@@ -1275,7 +1275,7 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line124">line 124</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line128">line 128</a>
</li></ul></dd>
@@ -1400,7 +1400,7 @@ It's used for seamless note versioning.</div>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
@@ -1453,7 +1453,7 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line32">line 32</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line59">line 59</a>
</li></ul></dd>
@@ -1478,6 +1478,24 @@ It's used for seamless note versioning.</div>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
@@ -1489,7 +1507,7 @@ It's used for seamless note versioning.</div>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<h4 class="name" id="getAttachmentById"><span class="type-signature"></span>getAttachmentById<span class="signature">()</span><span class="type-signature"> &rarr; {<a href="BAttachment.html">BAttachment</a>|null}</span></h4>
@@ -1517,11 +1535,6 @@ It's used for seamless note versioning.</div>
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractBeccaEntity.html#generateIdIfNecessary">AbstractBeccaEntity#generateIdIfNecessary</a>
</li></ul></dd>
@@ -1542,7 +1555,7 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line25">line 25</a>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line132">line 132</a>
</li></ul></dd>
@@ -1567,6 +1580,129 @@ It's used for seamless note versioning.</div>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="BAttachment.html">BAttachment</a></span>
|
<span class="param-type">null</span>
</dd>
</dl>
<h4 class="name" id="getAttachmentByTitle"><span class="type-signature"></span>getAttachmentByTitle<span class="signature">()</span><span class="type-signature"> &rarr; {<a href="BAttachment.html">BAttachment</a>}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line159">line 159</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="BAttachment.html">BAttachment</a></span>
</dd>
</dl>
@@ -1626,7 +1762,109 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line99">line 99</a>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line122">line 122</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Array.&lt;<a href="BAttachment.html">BAttachment</a>></span>
</dd>
</dl>
<h4 class="name" id="getAttachmentsByRole"><span class="type-signature"></span>getAttachmentsByRole<span class="signature">()</span><span class="type-signature"> &rarr; {Array.&lt;<a href="BAttachment.html">BAttachment</a>>}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line147">line 147</a>
</li></ul></dd>
@@ -1779,6 +2017,318 @@ It's used for seamless note versioning.</div>
<h4 class="name" id="getJsonContent"><span class="type-signature"></span>getJsonContent<span class="signature">()</span><span class="type-signature"> &rarr; {*}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line92">line 92</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<div class="param-desc">
Error in case of invalid JSON
</div>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">*</span>
</dd>
</dl>
<h4 class="name" id="getJsonContentSafely"><span class="type-signature"></span>getJsonContentSafely<span class="signature">()</span><span class="type-signature"> &rarr; {*|null}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line103">line 103</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
valid object or null if the content cannot be parsed as JSON
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">*</span>
|
<span class="param-type">null</span>
</dd>
</dl>
<h4 class="name" id="getPojo"><span class="type-signature">(abstract, protected) </span>getPojo<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="AbstractBeccaEntity.html#getPojo">AbstractBeccaEntity#getPojo</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line82">line 82</a>
</li></ul></dd>
</dl>
@@ -1838,7 +2388,7 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line76">line 76</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line74">line 74</a>
</li></ul></dd>
@@ -1927,7 +2477,7 @@ It's used for seamless note versioning.</div>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line47">line 47</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line27">line 27</a>
</li></ul></dd>
@@ -2192,7 +2742,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line263">line 263</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line267">line 267</a>
</li></ul></dd>
@@ -2281,7 +2831,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line64">line 64</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line44">line 44</a>
</li></ul></dd>
@@ -2374,7 +2924,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_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line85">line 85</a>
<a href="becca_entities_abstract_becca_entity.js.html">becca/entities/abstract_becca_entity.js</a>, <a href="becca_entities_abstract_becca_entity.js.html#line91">line 91</a>
</li></ul></dd>
@@ -2632,7 +3182,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_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line94">line 94</a>
<a href="becca_entities_brevision.js.html">becca/entities/brevision.js</a>, <a href="becca_entities_brevision.js.html#line117">line 117</a>
</li></ul></dd>

View File

@@ -94,7 +94,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line29">line 29</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line30">line 30</a>
</li></ul></dd>
@@ -240,7 +240,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line579">line 579</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line594">line 594</a>
</li></ul></dd>
@@ -352,7 +352,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line45">line 45</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line46">line 46</a>
</li></ul></dd>
@@ -462,7 +462,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line33">line 33</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line34">line 34</a>
</li></ul></dd>
@@ -572,7 +572,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line47">line 47</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line48">line 48</a>
</li></ul></dd>
@@ -682,7 +682,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line35">line 35</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line36">line 36</a>
</li></ul></dd>
@@ -792,7 +792,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line437">line 437</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line438">line 438</a>
</li></ul></dd>
@@ -902,7 +902,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line31">line 31</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line32">line 32</a>
</li></ul></dd>
@@ -1012,7 +1012,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<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#line49">line 49</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line50">line 50</a>
</li></ul></dd>
@@ -1188,7 +1188,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line198">line 198</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line199">line 199</a>
</li></ul></dd>
@@ -1691,7 +1691,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line221">line 221</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line222">line 222</a>
</li></ul></dd>
@@ -2311,7 +2311,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line241">line 241</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line242">line 242</a>
</li></ul></dd>
@@ -2817,7 +2817,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line464">line 464</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line465">line 465</a>
</li></ul></dd>
@@ -3018,7 +3018,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line181">line 181</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line182">line 182</a>
</li></ul></dd>
@@ -3200,7 +3200,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line158">line 158</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line159">line 159</a>
</li></ul></dd>
@@ -3401,7 +3401,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line148">line 148</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line149">line 149</a>
</li></ul></dd>
@@ -3552,7 +3552,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line425">line 425</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line426">line 426</a>
</li></ul></dd>
@@ -3753,7 +3753,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line530">line 530</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line531">line 531</a>
</li></ul></dd>
@@ -3855,7 +3855,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line443">line 443</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line444">line 444</a>
</li></ul></dd>
@@ -4013,7 +4013,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line78">line 78</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line79">line 79</a>
</li></ul></dd>
@@ -4167,7 +4167,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line71">line 71</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line72">line 72</a>
</li></ul></dd>
@@ -4368,7 +4368,7 @@ JSON MIME type. See also createNewNote() for more options.
<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#line324">line 324</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line325">line 325</a>
</li></ul></dd>
@@ -4478,7 +4478,7 @@ if some action needs to happen on only one specific instance.
<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#line57">line 57</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line58">line 58</a>
</li></ul></dd>
@@ -4679,7 +4679,7 @@ if some action needs to happen on only one specific instance.
<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#line355">line 355</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line356">line 356</a>
</li></ul></dd>
@@ -4833,7 +4833,7 @@ if some action needs to happen on only one specific instance.
<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#line64">line 64</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line65">line 65</a>
</li></ul></dd>
@@ -5034,7 +5034,7 @@ if some action needs to happen on only one specific instance.
<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#line137">line 137</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line138">line 138</a>
</li></ul></dd>
@@ -5235,7 +5235,7 @@ if some action needs to happen on only one specific instance.
<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#line127">line 127</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line128">line 128</a>
</li></ul></dd>
@@ -5341,7 +5341,7 @@ if some action needs to happen on only one specific instance.
<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#line314">line 314</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line315">line 315</a>
</li></ul></dd>
@@ -5511,7 +5511,7 @@ if some action needs to happen on only one specific instance.
<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#line333">line 333</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line334">line 334</a>
</li></ul></dd>
@@ -5814,7 +5814,7 @@ if some action needs to happen on only one specific instance.
<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#line345">line 345</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line346">line 346</a>
</li></ul></dd>
@@ -6015,7 +6015,7 @@ if some action needs to happen on only one specific instance.
<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#line365">line 365</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line366">line 366</a>
</li></ul></dd>
@@ -6168,7 +6168,7 @@ if some action needs to happen on only one specific instance.
<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#line287">line 287</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line288">line 288</a>
</li></ul></dd>
@@ -6323,7 +6323,7 @@ if some action needs to happen on only one specific instance.
<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#line418">line 418</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line419">line 419</a>
</li></ul></dd>
@@ -6508,7 +6508,7 @@ instances execute the given function.
<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#line543">line 543</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line544">line 544</a>
</li></ul></dd>
@@ -6566,6 +6566,170 @@ instances execute the given function.
<h4 class="name" id="runOutsideOfSync"><span class="type-signature"></span>runOutsideOfSync<span class="signature">(callback)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
<div class="description">
Sync process can make data intermittently inconsistent. Scripts which require strong data consistency
can use this function to wait for a possible sync process to finish and prevent new sync process from starting
while it is running.
Because this is an async process, the inner callback doesn't have automatic transaction handling, so in case
you need to make some DB changes, you need to surround your call with api.transactional(...)
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>callback</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">function to be executed while sync process is not running</td>
</tr>
</tbody>
</table>
<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#line587">line 587</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
- resolves once the callback is finished (callback is awaited)
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise</span>
</dd>
</dl>
<h4 class="name" id="searchForNote"><span class="type-signature"></span>searchForNote<span class="signature">(query, searchParams<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {<a href="BNote.html">BNote</a>|null}</span></h4>
@@ -6711,7 +6875,7 @@ instances execute the given function.
<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#line113">line 113</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line114">line 114</a>
</li></ul></dd>
@@ -6913,7 +7077,7 @@ instances execute the given function.
<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#line89">line 89</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line90">line 90</a>
</li></ul></dd>
@@ -7122,7 +7286,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
<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#line399">line 399</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line400">line 400</a>
</li></ul></dd>
@@ -7465,7 +7629,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
<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#line379">line 379</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line380">line 380</a>
</li></ul></dd>
@@ -7689,7 +7853,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
<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#line170">line 170</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line171">line 171</a>
</li></ul></dd>
@@ -7845,7 +8009,7 @@ exists, then we'll use that transaction.
<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#line409">line 409</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line410">line 410</a>
</li></ul></dd>
@@ -8000,7 +8164,7 @@ exists, then we'll use that transaction.
<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#line432">line 432</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line433">line 433</a>
</li></ul></dd>

View File

@@ -46,31 +46,11 @@ let becca = null;
class AbstractBeccaEntity {
/** @protected */
beforeSaving() {
this.generateIdIfNecessary();
}
/** @protected */
generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId();
}
}
/** @protected */
generateHash(isDeleted = false) {
let contentToHash = "";
for (const propertyName of this.constructor.hashedProperties) {
contentToHash += `|${this[propertyName]}`;
}
if (isDeleted) {
contentToHash += "|deleted";
}
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated;
@@ -89,7 +69,7 @@ class AbstractBeccaEntity {
}
/** @protected */
putEntityChange(isDeleted = false) {
putEntityChange(isDeleted) {
entityChangesService.putEntityChange({
entityName: this.constructor.entityName,
entityId: this[this.constructor.primaryKeyName],
@@ -100,11 +80,37 @@ class AbstractBeccaEntity {
});
}
/**
* @protected
* @returns {string}
*/
generateHash(isDeleted) {
let contentToHash = "";
for (const propertyName of this.constructor.hashedProperties) {
contentToHash += `|${this[propertyName]}`;
}
if (isDeleted) {
contentToHash += "|deleted";
}
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getPojoToSave() {
return this.getPojo();
}
/**
* @protected
* @abstract
*/
getPojo() {
throw new Error(`Unimplemented getPojo() for entity '${this.constructor.name}'`)
}
/**
* Saves entity - executes SQL, but doesn't commit the transaction on its own
*
@@ -116,9 +122,7 @@ class AbstractBeccaEntity {
const isNewEntity = !this[primaryKeyName];
if (this.beforeSaving) {
this.beforeSaving(opts);
}
this.beforeSaving(opts);
const pojo = this.getPojoToSave();
@@ -129,7 +133,7 @@ class AbstractBeccaEntity {
return;
}
this.putEntityChange(false);
this.putEntityChange(!!this.isDeleted);
if (!cls.isEntityEventsDisabled()) {
const eventPayload = {

View File

@@ -48,8 +48,7 @@ const attachmentRoleToNoteTypeMapping = {
class BAttachment extends AbstractBeccaEntity {
static get entityName() { return "attachments"; }
static get primaryKeyName() { return "attachmentId"; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId",
"utcDateScheduledForErasureSince", "utcDateModified"]; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId", "utcDateScheduledForErasureSince"]; }
constructor(row) {
super();
@@ -126,7 +125,12 @@ class BAttachment extends AbstractBeccaEntity {
}
decrypt() {
if (this.isProtected &amp;&amp; !this.isDecrypted &amp;&amp; protectedSessionService.isProtectedSessionAvailable()) {
if (!this.isProtected || !this.attachmentId) {
this.isDecrypted = true;
return;
}
if (!this.isDecrypted &amp;&amp; protectedSessionService.isProtectedSessionAvailable()) {
try {
this.title = protectedSessionService.decryptString(this.title);
this.isDecrypted = true;

View File

@@ -160,11 +160,17 @@ class BNote extends AbstractBeccaEntity {
*/
this.contentSize = null;
/**
* size of the content and note revision contents in bytes
* size of the note content, attachment contents in bytes
* @type {int|null}
* @private
*/
this.noteSize = null;
this.contentAndAttachmentsSize = null;
/**
* size of the note content, attachment contents and revision contents in bytes
* @type {int|null}
* @private
*/
this.contentAndAttachmentsAndRevisionsSize = null;
/**
* number of note revisions for this note
* @type {int|null}
@@ -239,12 +245,9 @@ class BNote extends AbstractBeccaEntity {
return this._getContent();
}
/** @returns {{dateModified, utcDateModified}} */
getContentMetadata() {
return sql.getRow(`SELECT dateModified, utcDateModified FROM blobs WHERE blobId = ?`, [this.blobId]);
}
/** @returns {*} */
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent();
@@ -255,6 +258,16 @@ class BNote extends AbstractBeccaEntity {
return JSON.parse(content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
/**
* @param content
* @param {object} [opts]
@@ -1158,7 +1171,7 @@ class BNote extends AbstractBeccaEntity {
}
/** @returns {BAttachment[]} */
getAttachmentByRole(role) {
getAttachmentsByRole(role) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
@@ -1169,6 +1182,18 @@ class BNote extends AbstractBeccaEntity {
.map(row => new BAttachment(row));
}
/** @returns {BAttachment} */
getAttachmentByTitle(title) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND title = ?
AND isDeleted = 0
ORDER BY position`, [this.noteId, title])
.map(row => new BAttachment(row))[0];
}
/**
* Gives all possible note paths leading to this note. Paths containing search note are ignored (could form cycles)
*
@@ -1599,7 +1624,6 @@ class BNote extends AbstractBeccaEntity {
saveRevision() {
return sql.transactional(() => {
let noteContent = this.getContent();
const contentMetadata = this.getContentMetadata();
const revision = new BRevision({
noteId: this.noteId,
@@ -1608,29 +1632,21 @@ class BNote extends AbstractBeccaEntity {
type: this.type,
mime: this.mime,
isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified
? this.utcDateModified
: contentMetadata.utcDateModified,
utcDateLastEdited: this.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: this.dateModified > contentMetadata.dateModified
? this.dateModified
: contentMetadata.dateModified,
dateLastEdited: this.dateModified,
dateCreated: dateUtils.localNowDateTime()
}, true);
revision.save(); // to generate revisionId, which is then used to save attachments
if (this.type === 'text') {
for (const noteAttachment of this.getAttachments()) {
if (noteAttachment.utcDateScheduledForErasureSince) {
continue;
}
const revisionAttachment = noteAttachment.copy();
revisionAttachment.ownerId = revision.revisionId;
revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true});
for (const noteAttachment of this.getAttachments()) {
const revisionAttachment = noteAttachment.copy();
revisionAttachment.ownerId = revision.revisionId;
revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true});
if (this.type === 'text') {
// content is rewritten to point to the revision attachments
noteContent = noteContent.replaceAll(`attachments/${noteAttachment.attachmentId}`,
`attachments/${revisionAttachment.attachmentId}`);
@@ -1638,10 +1654,10 @@ class BNote extends AbstractBeccaEntity {
noteContent = noteContent.replaceAll(new RegExp(`href="[^"]*attachmentId=${noteAttachment.attachmentId}[^"]*"`, 'gi'),
`href="api/attachments/${revisionAttachment.attachmentId}/download"`);
}
revision.setContent(noteContent, {forceSave: true});
}
revision.setContent(noteContent);
return revision;
});
}

View File

@@ -114,6 +114,29 @@ class BRevision extends AbstractBeccaEntity {
return this._getContent();
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent();
if (!content || !content.trim()) {
return null;
}
return JSON.parse(content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
/**
* @param content
* @param {object} [opts]
@@ -133,6 +156,45 @@ class BRevision extends AbstractBeccaEntity {
.map(row => new BAttachment(row));
}
/** @returns {BAttachment|null} */
getAttachmentById(attachmentId, opts = {}) {
opts.includeContentLength = !!opts.includeContentLength;
const query = opts.includeContentLength
? `SELECT attachments.*, LENGTH(blobs.content) AS contentLength
FROM attachments
JOIN blobs USING (blobId)
WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`
: `SELECT * FROM attachments WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`;
return sql.getRows(query, [this.revisionId, attachmentId])
.map(row => new BAttachment(row))[0];
}
/** @returns {BAttachment[]} */
getAttachmentsByRole(role) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND role = ?
AND isDeleted = 0
ORDER BY position`, [this.revisionId, role])
.map(row => new BAttachment(row));
}
/** @returns {BAttachment} */
getAttachmentByTitle(title) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND title = ?
AND isDeleted = 0
ORDER BY position`, [this.revisionId, title])
.map(row => new BAttachment(row))[0];
}
beforeSaving() {
super.beforeSaving();

View File

@@ -47,6 +47,7 @@ const SpacedUpdate = require("./spaced_update");
const specialNotesService = require("./special_notes");
const branchService = require("./branches");
const exportService = require("./export/zip");
const syncMutex = require("./sync_mutex.js");
/**
* &lt;p>This is the main backend API interface for scripts. All the properties and methods are published in the "api" object
@@ -599,6 +600,20 @@ function BackendScriptApi(currentNote, apiParams) {
}
};
/**
* Sync process can make data intermittently inconsistent. Scripts which require strong data consistency
* can use this function to wait for a possible sync process to finish and prevent new sync process from starting
* while it is running.
*
* Because this is an async process, the inner callback doesn't have automatic transaction handling, so in case
* you need to make some DB changes, you need to surround your call with api.transactional(...)
*
* @method
* @param {function} callback - function to be executed while sync process is not running
* @returns {Promise} - resolves once the callback is finished (callback is awaited)
*/
this.runOutsideOfSync = syncMutex.doExclusively;
/**
* This object contains "at your risk" and "no BC guarantees" objects for advanced use cases.
*

View File

@@ -54,7 +54,7 @@ const LOG_ALL_QUERIES = false;
});
function insert(tableName, rec, replace = false) {
const keys = Object.keys(rec);
const keys = Object.keys(rec || {});
if (keys.length === 0) {
log.error(`Can't insert empty object into table ${tableName}`);
return;
@@ -81,7 +81,7 @@ function replace(tableName, rec) {
}
function upsert(tableName, primaryKey, rec) {
const keys = Object.keys(rec);
const keys = Object.keys(rec || {});
if (keys.length === 0) {
log.error(`Can't upsert empty object into table ${tableName}`);
return;

View File

@@ -912,7 +912,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="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -1124,7 +1124,7 @@ parents.</div>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -1168,7 +1168,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line353">line 353</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line359">line 359</a>
</li></ul></dd>
@@ -1274,7 +1274,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line240">line 240</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line246">line 246</a>
</li></ul></dd>
@@ -1401,6 +1401,108 @@
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise.&lt;Array.&lt;<a href="FAttachment.html">FAttachment</a>>></span>
</dd>
</dl>
<h4 class="name" id="getAttachmentsByRole"><span class="type-signature">(async) </span>getAttachmentsByRole<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;Array.&lt;<a href="FAttachment.html">FAttachment</a>>>}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line240">line 240</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
@@ -1550,7 +1652,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line616">line 616</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line622">line 622</a>
</li></ul></dd>
@@ -1728,7 +1830,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line638">line 638</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line644">line 644</a>
</li></ul></dd>
@@ -1928,7 +2030,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line287">line 287</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line293">line 293</a>
</li></ul></dd>
@@ -2107,7 +2209,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line409">line 409</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line415">line 415</a>
</li></ul></dd>
@@ -2286,7 +2388,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line419">line 419</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line425">line 425</a>
</li></ul></dd>
@@ -2392,7 +2494,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line863">line 863</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line869">line 869</a>
</li></ul></dd>
@@ -3057,7 +3159,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line692">line 692</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line698">line 698</a>
</li></ul></dd>
@@ -3212,7 +3314,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line716">line 716</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line722">line 722</a>
</li></ul></dd>
@@ -3379,7 +3481,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line502">line 502</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line508">line 508</a>
</li></ul></dd>
@@ -3487,7 +3589,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line858">line 858</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line864">line 864</a>
</li></ul></dd>
@@ -3589,7 +3691,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line758">line 758</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line764">line 764</a>
</li></ul></dd>
@@ -3763,7 +3865,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line605">line 605</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line611">line 611</a>
</li></ul></dd>
@@ -3941,7 +4043,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line627">line 627</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line633">line 633</a>
</li></ul></dd>
@@ -4141,7 +4243,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line274">line 274</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line280">line 280</a>
</li></ul></dd>
@@ -4296,7 +4398,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line686">line 686</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line692">line 692</a>
</li></ul></dd>
@@ -4451,7 +4553,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line710">line 710</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line716">line 716</a>
</li></ul></dd>
@@ -4618,7 +4720,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line494">line 494</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line500">line 500</a>
</li></ul></dd>
@@ -4773,7 +4875,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line698">line 698</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line704">line 704</a>
</li></ul></dd>
@@ -4928,7 +5030,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line722">line 722</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line728">line 728</a>
</li></ul></dd>
@@ -5095,7 +5197,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line568">line 568</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line574">line 574</a>
</li></ul></dd>
@@ -5658,7 +5760,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line704">line 704</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line710">line 710</a>
</li></ul></dd>
@@ -5813,7 +5915,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line734">line 734</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line740">line 740</a>
</li></ul></dd>
@@ -5983,7 +6085,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line744">line 744</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line750">line 750</a>
</li></ul></dd>
@@ -6134,7 +6236,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line728">line 728</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line734">line 734</a>
</li></ul></dd>
@@ -6301,7 +6403,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line576">line 576</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line582">line 582</a>
</li></ul></dd>
@@ -6407,7 +6509,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line907">line 907</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line913">line 913</a>
</li></ul></dd>
@@ -6585,7 +6687,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line375">line 375</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line381">line 381</a>
</li></ul></dd>
@@ -6691,7 +6793,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line848">line 848</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line854">line 854</a>
</li></ul></dd>
@@ -6797,7 +6899,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line838">line 838</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line844">line 844</a>
</li></ul></dd>
@@ -6971,7 +7073,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line585">line 585</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line591">line 591</a>
</li></ul></dd>
@@ -7228,7 +7330,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line654">line 654</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line660">line 660</a>
</li></ul></dd>
@@ -7406,7 +7508,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line596">line 596</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line602">line 602</a>
</li></ul></dd>
@@ -7561,7 +7663,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line648">line 648</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line654">line 654</a>
</li></ul></dd>
@@ -7716,7 +7818,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line674">line 674</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line680">line 680</a>
</li></ul></dd>
@@ -7871,7 +7973,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line680">line 680</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line686">line 686</a>
</li></ul></dd>
@@ -7979,7 +8081,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line831">line 831</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line837">line 837</a>
</li></ul></dd>
@@ -8063,7 +8165,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line428">line 428</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line434">line 434</a>
</li></ul></dd>
@@ -8157,7 +8259,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line902">line 902</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line908">line 908</a>
</li></ul></dd>
@@ -8263,7 +8365,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line894">line 894</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line900">line 900</a>
</li></ul></dd>
@@ -8520,7 +8622,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line660">line 660</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line666">line 666</a>
</li></ul></dd>
@@ -8588,7 +8690,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

File diff suppressed because it is too large Load Diff

View File

@@ -80,7 +80,7 @@ export default FAttachment;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -116,7 +116,7 @@ export default FAttribute;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -43,6 +43,27 @@
/** @type {string} */
this.utcDateModified = row.utcDateModified;
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
if (!this.content || !this.content.trim()) {
return null;
}
return JSON.parse(this.content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
}
</code></pre>
</article>
@@ -54,7 +75,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -100,7 +100,7 @@ export default FBranch;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -264,6 +264,12 @@ class FNote {
return this.attachments;
}
/** @returns {Promise&lt;FAttachment[]>} */
async getAttachmentsByRole(role) {
return (await this.getAttachments())
.filter(attachment => attachment.role === role);
}
/** @returns {Promise&lt;FAttachment>} */
async getAttachmentById(attachmentId) {
const attachments = await this.getAttachments();
@@ -998,6 +1004,10 @@ class FNote {
isOptions() {
return this.noteId.startsWith("_options");
}
async getMetadata() {
return await server.get(`notes/${this.noteId}/metadata`);
}
}
export default FNote;
@@ -1011,7 +1021,7 @@ export default FNote;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -0,0 +1,352 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Global</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Global</h1>
<section>
<header>
<h2></h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="getJsonContent"><span class="type-signature"></span>getJsonContent<span class="signature">()</span><span class="type-signature"> &rarr; {*}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fblob.js.html">entities/fblob.js</a>, <a href="entities_fblob.js.html#line22">line 22</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<div class="param-desc">
Error in case of invalid JSON
</div>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">*</span>
</dd>
</dl>
<h4 class="name" id="getJsonContentSafely"><span class="type-signature"></span>getJsonContentSafely<span class="signature">()</span><span class="type-signature"> &rarr; {*|null}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fblob.js.html">entities/fblob.js</a>, <a href="entities_fblob.js.html#line31">line 31</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
valid object or null if the content cannot be parsed as JSON
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">*</span>
|
<span class="param-type">null</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.2</a>
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View File

@@ -50,7 +50,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -42,6 +42,7 @@ import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js";
import shortcutService from "./shortcuts.js";
import dialogService from "./dialog.js";
/**
* &lt;p>This is the main frontend API interface for scripts. All the properties and methods are published in the "api" object
@@ -286,7 +287,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.parseDate = utils.parseDate;
/**
* Show an info message to the user.
* Show an info toast message to the user.
*
* @method
* @param {string} message
@@ -294,13 +295,43 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.showMessage = toastService.showMessage;
/**
* Show an error message to the user.
* Show an error toast message to the user.
*
* @method
* @param {string} message
*/
this.showError = toastService.showError;
/**
* Show an info dialog to the user.
*
* @method
* @param {string} message
* @returns {Promise}
*/
this.showInfoDialog = dialogService.info;
/**
* Show confirm dialog to the user.
*
* @method
* @param {string} message
* @returns {Promise&lt;boolean>} promise resolving to true if the user confirmed
*/
this.showConfirmDialog = dialogService.confirm;
/**
* Show prompt dialog to the user.
*
* @method
* @param {object} props
* @param {string} props.title
* @param {string} props.message
* @param {string} props.defaultValue
* @returns {Promise&lt;string>} promise resolving to the answer provided by the user
*/
this.showPromptDialog = dialogService.prompt;
/**
* Trigger command. This is a very low-level API which should be avoided if possible.
*
@@ -570,7 +601,7 @@ export default FrontendScriptApi;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">

View File

@@ -13,6 +13,9 @@ appIconService.installLocalAppIcon();
require('electron-dl')({ saveAs: true });
// needed for excalidraw export https://github.com/zadam/trilium/issues/4271
app.commandLine.appendSwitch("enable-experimental-web-platform-features");
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.

View File

@@ -46,7 +46,7 @@
const errors = new eslint().verify(text, {
root: true,
parserOptions: {
ecmaVersion: 2022
ecmaVersion: "latest"
},
extends: ['eslint:recommended', 'airbnb-base'],
env: {

View File

@@ -24,8 +24,10 @@
function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
tt.style.left = (e.clientX + 5) + "px";
var top = Math.max(0, e.clientY - tt.offsetHeight - 5);
var left = Math.max(0, Math.min(e.clientX + 5, tt.ownerDocument.defaultView.innerWidth - tt.offsetWidth));
tt.style.top = top + "px"
tt.style.left = left + "px";
}
CodeMirror.on(document, "mousemove", position);
position(e);
@@ -199,10 +201,6 @@
var anns = annotations[line];
if (!anns) continue;
// filter out duplicate messages
var message = [];
anns = anns.filter(function(item) { return message.indexOf(item.message) > -1 ? false : message.push(item.message) });
var maxSeverity = null;
var tipLabel = state.hasGutter && document.createDocumentFragment();
@@ -220,9 +218,8 @@
__annotation: ann
}));
}
// use original annotations[line] to show multiple messages
if (state.hasGutter)
cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, annotations[line].length > 1,
cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, anns.length > 1,
options.tooltips));
if (options.highlightLines)

View File

@@ -0,0 +1,136 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.multiplexingMode = function(outer /*, others */) {
// Others should be {open, close, mode [, delimStyle] [, innerStyle] [, parseDelimiters]} objects
var others = Array.prototype.slice.call(arguments, 1);
function indexOf(string, pattern, from, returnEnd) {
if (typeof pattern == "string") {
var found = string.indexOf(pattern, from);
return returnEnd && found > -1 ? found + pattern.length : found;
}
var m = pattern.exec(from ? string.slice(from) : string);
return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
}
return {
startState: function() {
return {
outer: CodeMirror.startState(outer),
innerActive: null,
inner: null,
startingInner: false
};
},
copyState: function(state) {
return {
outer: CodeMirror.copyState(outer, state.outer),
innerActive: state.innerActive,
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner),
startingInner: state.startingInner
};
},
token: function(stream, state) {
if (!state.innerActive) {
var cutOff = Infinity, oldContent = stream.string;
for (var i = 0; i < others.length; ++i) {
var other = others[i];
var found = indexOf(oldContent, other.open, stream.pos);
if (found == stream.pos) {
if (!other.parseDelimiters) stream.match(other.open);
state.startingInner = !!other.parseDelimiters
state.innerActive = other;
// Get the outer indent, making sure to handle CodeMirror.Pass
var outerIndent = 0;
if (outer.indent) {
var possibleOuterIndent = outer.indent(state.outer, "", "");
if (possibleOuterIndent !== CodeMirror.Pass) outerIndent = possibleOuterIndent;
}
state.inner = CodeMirror.startState(other.mode, outerIndent);
return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
} else if (found != -1 && found < cutOff) {
cutOff = found;
}
}
if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
var outerToken = outer.token(stream, state.outer);
if (cutOff != Infinity) stream.string = oldContent;
return outerToken;
} else {
var curInner = state.innerActive, oldContent = stream.string;
if (!curInner.close && stream.sol()) {
state.innerActive = state.inner = null;
return this.token(stream, state);
}
var found = curInner.close && !state.startingInner ?
indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
if (found == stream.pos && !curInner.parseDelimiters) {
stream.match(curInner.close);
state.innerActive = state.inner = null;
return curInner.delimStyle && (curInner.delimStyle + " " + curInner.delimStyle + "-close");
}
if (found > -1) stream.string = oldContent.slice(0, found);
var innerToken = curInner.mode.token(stream, state.inner);
if (found > -1) stream.string = oldContent;
else if (stream.pos > stream.start) state.startingInner = false
if (found == stream.pos && curInner.parseDelimiters)
state.innerActive = state.inner = null;
if (curInner.innerStyle) {
if (innerToken) innerToken = innerToken + " " + curInner.innerStyle;
else innerToken = curInner.innerStyle;
}
return innerToken;
}
},
indent: function(state, textAfter, line) {
var mode = state.innerActive ? state.innerActive.mode : outer;
if (!mode.indent) return CodeMirror.Pass;
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter, line);
},
blankLine: function(state) {
var mode = state.innerActive ? state.innerActive.mode : outer;
if (mode.blankLine) {
mode.blankLine(state.innerActive ? state.inner : state.outer);
}
if (!state.innerActive) {
for (var i = 0; i < others.length; ++i) {
var other = others[i];
if (other.open === "\n") {
state.innerActive = other;
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "", "") : 0);
}
}
} else if (state.innerActive.close === "\n") {
state.innerActive = state.inner = null;
}
},
electricChars: outer.electricChars,
innerMode: function(state) {
return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
}
};
};
});

View File

@@ -0,0 +1,90 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
// Utility function that allows modes to be combined. The mode given
// as the base argument takes care of most of the normal mode
// functionality, but a second (typically simple) mode is used, which
// can override the style of text. Both modes get to parse all of the
// text, but when both assign a non-null style to a piece of code, the
// overlay wins, unless the combine argument was true and not overridden,
// or state.overlay.combineTokens was true, in which case the styles are
// combined.
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.overlayMode = function(base, overlay, combine) {
return {
startState: function() {
return {
base: CodeMirror.startState(base),
overlay: CodeMirror.startState(overlay),
basePos: 0, baseCur: null,
overlayPos: 0, overlayCur: null,
streamSeen: null
};
},
copyState: function(state) {
return {
base: CodeMirror.copyState(base, state.base),
overlay: CodeMirror.copyState(overlay, state.overlay),
basePos: state.basePos, baseCur: null,
overlayPos: state.overlayPos, overlayCur: null
};
},
token: function(stream, state) {
if (stream != state.streamSeen ||
Math.min(state.basePos, state.overlayPos) < stream.start) {
state.streamSeen = stream;
state.basePos = state.overlayPos = stream.start;
}
if (stream.start == state.basePos) {
state.baseCur = base.token(stream, state.base);
state.basePos = stream.pos;
}
if (stream.start == state.overlayPos) {
stream.pos = stream.start;
state.overlayCur = overlay.token(stream, state.overlay);
state.overlayPos = stream.pos;
}
stream.pos = Math.min(state.basePos, state.overlayPos);
// state.overlay.combineTokens always takes precedence over combine,
// unless set to null
if (state.overlayCur == null) return state.baseCur;
else if (state.baseCur != null &&
state.overlay.combineTokens ||
combine && state.overlay.combineTokens == null)
return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
indent: base.indent && function(state, textAfter, line) {
return base.indent(state.base, textAfter, line);
},
electricChars: base.electricChars,
innerMode: function(state) { return {state: state.base, mode: base}; },
blankLine: function(state) {
var baseToken, overlayToken;
if (base.blankLine) baseToken = base.blankLine(state.base);
if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay);
return overlayToken == null ?
baseToken :
(combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken);
}
};
};
});

View File

@@ -8259,8 +8259,8 @@
}
function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) {
field.setAttribute("autocorrect", autocorrect ? "" : "off");
field.setAttribute("autocapitalize", autocapitalize ? "" : "off");
field.setAttribute("autocorrect", autocorrect ? "on" : "off");
field.setAttribute("autocapitalize", autocapitalize ? "on" : "off");
field.setAttribute("spellcheck", !!spellcheck);
}
@@ -8275,7 +8275,6 @@
else { te.setAttribute("wrap", "off"); }
// If border: 0; -- iOS fails to open keyboard (issue #1287)
if (ios) { te.style.border = "1px solid black"; }
disableBrowserMagic(te);
return div
}
@@ -8897,6 +8896,7 @@
}
// Old-fashioned briefly-focus-a-textarea hack
var kludge = hiddenTextarea(), te = kludge.firstChild;
disableBrowserMagic(te);
cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
te.value = lastCopied.text.join("\n");
var hadFocus = activeElt(div.ownerDocument);
@@ -9461,6 +9461,8 @@
// The semihidden textarea that is focused when the editor is
// focused, and receives input.
this.textarea = this.wrapper.firstChild;
var opts = this.cm.options;
disableBrowserMagic(this.textarea, opts.spellcheck, opts.autocorrect, opts.autocapitalize);
};
TextareaInput.prototype.screenReaderLabelChanged = function (label) {
@@ -9865,7 +9867,7 @@
addLegacyProps(CodeMirror);
CodeMirror.version = "5.65.9";
CodeMirror.version = "5.65.15";
return CodeMirror;

View File

@@ -218,7 +218,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
},
indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine && isTopScope(state.context))
return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
var closing = firstChar == ctx.type;
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
@@ -512,8 +513,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
name: "clike",
keywords: words("abstract as async await base break case catch checked class const continue" +
" default delegate do else enum event explicit extern finally fixed for" +
" foreach goto if implicit in interface internal is lock namespace new" +
" operator out override params private protected public readonly ref return sealed" +
" foreach goto if implicit in init interface internal is lock namespace new" +
" operator out override params private protected public readonly record ref required return sealed" +
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
" global group into join let orderby partial remove select set value var yield"),
@@ -522,7 +523,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
" UInt64 bool byte char decimal double short int long object" +
" sbyte float string ushort uint ulong"),
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
defKeywords: words("class interface namespace struct var"),
defKeywords: words("class interface namespace record struct var"),
typeFirstDefinitions: true,
atoms: words("true false null"),
hooks: {
@@ -613,6 +614,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return state.tokenize(stream, state);
},
"'": function(stream) {
if (stream.match(/^(\\[^'\s]+|[^\\'])'/)) return "string-2"
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
return "atom";
},

View File

@@ -12,10 +12,10 @@
"use strict";
var keywords = ("this super static final const abstract class extends external factory " +
"implements mixin get native set typedef with enum throw rethrow " +
"assert break case continue default in return new deferred async await covariant " +
"try catch finally do else for if switch while import library export " +
"part of show hide is as extension on yield late required").split(" ");
"implements mixin get native set typedef with enum throw rethrow assert break case " +
"continue default in return new deferred async await covariant try catch finally " +
"do else for if switch while import library export part of show hide is as extension " +
"on yield late required sealed base interface when inline").split(" ");
var blockKeywords = "try catch finally do else for if switch while".split(" ");
var atoms = "true false null".split(" ");
var builtins = "void bool num int double dynamic var String Null Never".split(" ");

View File

@@ -779,7 +779,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "async" ||
(type == "variable" &&
(value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
cx.stream.match(/^\s+#?[\w$\xa1-\uffff]/, false))) {
cx.marked = "keyword";
return cont(classBody);
}

View File

@@ -24,7 +24,7 @@ CodeMirror.defineSimpleMode("nsis",{
{ regex: /`(?:[^\\`]|\\.)*`?/, token: "string" },
// Compile Time Commands
{regex: /^\s*(?:\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|error|execute|finalize|getdllversion|gettlbversion|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|uninstfinalize|verbose|warning))\b/i, token: "keyword"},
{regex: /^\s*(?:\!(addincludedir|addplugindir|appendfile|assert|cd|define|delfile|echo|error|execute|finalize|getdllversion|gettlbversion|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|uninstfinalize|verbose|warning))\b/i, token: "keyword"},
// Conditional Compilation
{regex: /^\s*(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/i, token: "keyword", indent: true},

View File

@@ -31,8 +31,6 @@ CodeMirror.defineMode("pegjs", function (config) {
};
},
token: function (stream, state) {
if (stream)
//check for state changes
if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) {
state.stringType = stream.peek();
@@ -43,7 +41,6 @@ CodeMirror.defineMode("pegjs", function (config) {
state.inComment = true;
}
//return state
if (state.inString) {
while (state.inString && !stream.eol()) {
if (stream.peek() === state.stringType) {

View File

@@ -20,7 +20,7 @@
"def", "del", "elif", "else", "except", "finally",
"for", "from", "global", "if", "import",
"lambda", "pass", "raise", "return",
"try", "while", "with", "yield", "in"];
"try", "while", "with", "yield", "in", "False", "True"];
var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
"classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
"enumerate", "eval", "filter", "float", "format", "frozenset",
@@ -60,7 +60,7 @@
if (py3) {
// since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
myKeywords = myKeywords.concat(["nonlocal", "None", "aiter", "anext", "async", "await", "breakpoint", "match", "case"]);
myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
var stringPrefixes = new RegExp("^(([rbuf]|(br)|(rb)|(fr)|(rf))?('{3}|\"{3}|['\"]))", "i");
} else {
@@ -68,7 +68,7 @@
myKeywords = myKeywords.concat(["exec", "print"]);
myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
"file", "intern", "long", "raw_input", "reduce", "reload",
"unichr", "unicode", "xrange", "False", "True", "None"]);
"unichr", "unicode", "xrange", "None"]);
var stringPrefixes = new RegExp("^(([rubf]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
}
var keywords = wordRegexp(myKeywords);

View File

@@ -33,6 +33,9 @@ CodeMirror.defineMode("sparql", function(config) {
"true", "false", "with",
"data", "copy", "to", "move", "add", "create", "drop", "clear", "load", "into"]);
var operatorChars = /[*+\-<>=&|\^\/!\?]/;
var PN_CHARS = "[A-Za-z_\\-0-9]";
var PREFIX_START = new RegExp("[A-Za-z]");
var PREFIX_REMAINDER = new RegExp("((" + PN_CHARS + "|\\.)*(" + PN_CHARS + "))?:");
function tokenBase(stream, state) {
var ch = stream.next();
@@ -71,20 +74,18 @@ CodeMirror.defineMode("sparql", function(config) {
stream.eatWhile(/[a-z\d\-]/i);
return "meta";
}
else {
stream.eatWhile(/[_\w\d]/);
if (stream.eat(":")) {
else if (PREFIX_START.test(ch) && stream.match(PREFIX_REMAINDER)) {
eatPnLocal(stream);
return "atom";
}
var word = stream.current();
if (ops.test(word))
return "builtin";
else if (keywords.test(word))
return "keyword";
else
return "variable";
}
stream.eatWhile(/[_\w\d]/);
var word = stream.current();
if (ops.test(word))
return "builtin";
else if (keywords.test(word))
return "keyword";
else
return "variable";
}
function eatPnLocal(stream) {

File diff suppressed because one or more lines are too long

View File

@@ -85,7 +85,7 @@ CodeMirror.defineMode("yaml", function() {
}
/* pairs (associative arrays) -> key */
if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) {
if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^\s,\[\]{}#&*!|>'"%@`])[^#:]*(?=:($|\s))/)) {
state.pair = true;
state.keyCol = stream.indentation();
return "atom";

File diff suppressed because one or more lines are too long

567
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "trilium",
"productName": "Trilium Notes",
"description": "Trilium Notes",
"version": "0.61.6-beta",
"version": "0.61.10-beta",
"license": "AGPL-3.0-only",
"main": "electron.js",
"bin": {
@@ -13,10 +13,10 @@
"url": "https://github.com/zadam/trilium.git"
},
"scripts": {
"start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon ./src/www",
"start-server-no-dir": "cross-env TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon ./src/www",
"start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
"start-electron-no-dir": "cross-env TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
"start-server": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon ./src/www",
"start-server-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon ./src/www",
"start-electron": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
"start-electron-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
"switch-server": "rm -rf ./node_modules/better-sqlite3 && npm install",
"switch-electron": "./node_modules/.bin/electron-rebuild",
"build-backend-docs": "rm -rf ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js",
@@ -32,23 +32,23 @@
},
"dependencies": {
"@braintree/sanitize-url": "6.0.4",
"@electron/remote": "2.0.11",
"@excalidraw/excalidraw": "0.15.3",
"@electron/remote": "2.0.12",
"@excalidraw/excalidraw": "0.16.1",
"archiver": "5.3.1",
"async-mutex": "0.4.0",
"axios": "1.5.0",
"axios": "1.5.1",
"better-sqlite3": "8.4.0",
"chokidar": "3.5.3",
"cls-hooked": "4.2.2",
"compression": "1.7.4",
"cookie-parser": "1.4.6",
"csurf": "1.11.0",
"dayjs": "1.11.9",
"dayjs": "1.11.10",
"dayjs-plugin-utc": "0.1.2",
"debounce": "1.2.1",
"ejs": "3.1.9",
"electron-debug": "3.2.0",
"electron-dl": "3.5.0",
"electron-dl": "3.5.1",
"electron-window-state": "5.0.3",
"escape-html": "1.0.3",
"express": "4.18.2",
@@ -68,21 +68,21 @@
"jimp": "0.22.10",
"joplin-turndown-plugin-gfm": "1.0.12",
"jsdom": "22.1.0",
"marked": "8.0.1",
"marked": "9.1.2",
"mime-types": "2.1.35",
"multer": "1.4.5-lts.1",
"node-abi": "3.47.0",
"node-abi": "3.50.0",
"normalize-strings": "1.1.1",
"open": "8.4.1",
"rand-token": "1.0.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"request": "2.88.2",
"rimraf": "5.0.1",
"rimraf": "5.0.5",
"safe-compare": "1.1.4",
"sanitize-filename": "1.6.3",
"sanitize-html": "2.11.0",
"sax": "1.2.4",
"sax": "1.3.0",
"semver": "7.5.4",
"serve-favicon": "2.5.0",
"session-file-store": "1.5.0",
@@ -91,33 +91,33 @@
"tmp": "0.2.1",
"turndown": "7.1.2",
"unescape": "1.0.1",
"ws": "8.14.0",
"ws": "8.14.2",
"xml2js": "0.6.2",
"yauzl": "2.10.0"
},
"devDependencies": {
"cross-env": "7.0.3",
"electron": "25.8.0",
"electron": "25.9.2",
"electron-builder": "24.6.4",
"electron-packager": "17.1.2",
"electron-rebuild": "3.2.9",
"eslint": "8.48.0",
"eslint": "8.51.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-jsonc": "2.9.0",
"eslint-plugin-prettier": "5.0.0",
"eslint-plugin-jsonc": "2.10.0",
"eslint-plugin-prettier": "5.0.1",
"esm": "3.2.25",
"husky": "8.0.3",
"jasmine": "5.1.0",
"jsdoc": "4.0.2",
"jsonc-eslint-parser": "2.3.0",
"lint-staged": "14.0.1",
"lint-staged": "15.0.0",
"lorem-ipsum": "2.0.8",
"nodemon": "3.0.1",
"prettier": "3.0.3",
"rcedit": "3.1.0",
"webpack": "5.88.2",
"webpack": "5.89.0",
"webpack-cli": "5.1.4"
},
"optionalDependencies": {

View File

@@ -208,6 +208,7 @@ class Becca {
return this.etapiTokens[etapiTokenId];
}
/** @returns {AbstractBeccaEntity|null} */
getEntity(entityName, entityId) {
if (!entityName || !entityId) {
return null;

View File

@@ -63,10 +63,10 @@ function load() {
log.info(`Becca (note cache) load took ${Date.now() - start}ms`);
}
function reload() {
function reload(reason) {
load();
require('../services/ws').reloadFrontend();
require('../services/ws').reloadFrontend(reason || "becca reloaded");
}
eventService.subscribeBeccaLoader([eventService.ENTITY_CHANGE_SYNCED], ({entityName, entityRow}) => {

View File

@@ -18,31 +18,11 @@ let becca = null;
class AbstractBeccaEntity {
/** @protected */
beforeSaving() {
this.generateIdIfNecessary();
}
/** @protected */
generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId();
}
}
/** @protected */
generateHash(isDeleted = false) {
let contentToHash = "";
for (const propertyName of this.constructor.hashedProperties) {
contentToHash += `|${this[propertyName]}`;
}
if (isDeleted) {
contentToHash += "|deleted";
}
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated;
@@ -61,7 +41,7 @@ class AbstractBeccaEntity {
}
/** @protected */
putEntityChange(isDeleted = false) {
putEntityChange(isDeleted) {
entityChangesService.putEntityChange({
entityName: this.constructor.entityName,
entityId: this[this.constructor.primaryKeyName],
@@ -72,11 +52,37 @@ class AbstractBeccaEntity {
});
}
/**
* @protected
* @returns {string}
*/
generateHash(isDeleted) {
let contentToHash = "";
for (const propertyName of this.constructor.hashedProperties) {
contentToHash += `|${this[propertyName]}`;
}
if (isDeleted) {
contentToHash += "|deleted";
}
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getPojoToSave() {
return this.getPojo();
}
/**
* @protected
* @abstract
*/
getPojo() {
throw new Error(`Unimplemented getPojo() for entity '${this.constructor.name}'`)
}
/**
* Saves entity - executes SQL, but doesn't commit the transaction on its own
*
@@ -88,9 +94,7 @@ class AbstractBeccaEntity {
const isNewEntity = !this[primaryKeyName];
if (this.beforeSaving) {
this.beforeSaving(opts);
}
this.beforeSaving(opts);
const pojo = this.getPojoToSave();
@@ -101,7 +105,7 @@ class AbstractBeccaEntity {
return;
}
this.putEntityChange(false);
this.putEntityChange(!!this.isDeleted);
if (!cls.isEntityEventsDisabled()) {
const eventPayload = {

View File

@@ -20,8 +20,7 @@ const attachmentRoleToNoteTypeMapping = {
class BAttachment extends AbstractBeccaEntity {
static get entityName() { return "attachments"; }
static get primaryKeyName() { return "attachmentId"; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId",
"utcDateScheduledForErasureSince", "utcDateModified"]; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId", "utcDateScheduledForErasureSince"]; }
constructor(row) {
super();
@@ -98,7 +97,12 @@ class BAttachment extends AbstractBeccaEntity {
}
decrypt() {
if (this.isProtected && !this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) {
if (!this.isProtected || !this.attachmentId) {
this.isDecrypted = true;
return;
}
if (!this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) {
try {
this.title = protectedSessionService.decryptString(this.title);
this.isDecrypted = true;

View File

@@ -132,11 +132,17 @@ class BNote extends AbstractBeccaEntity {
*/
this.contentSize = null;
/**
* size of the content and note revision contents in bytes
* size of the note content, attachment contents in bytes
* @type {int|null}
* @private
*/
this.noteSize = null;
this.contentAndAttachmentsSize = null;
/**
* size of the note content, attachment contents and revision contents in bytes
* @type {int|null}
* @private
*/
this.contentAndAttachmentsAndRevisionsSize = null;
/**
* number of note revisions for this note
* @type {int|null}
@@ -211,7 +217,9 @@ class BNote extends AbstractBeccaEntity {
return this._getContent();
}
/** @returns {*} */
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent();
@@ -222,6 +230,16 @@ class BNote extends AbstractBeccaEntity {
return JSON.parse(content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
/**
* @param content
* @param {object} [opts]
@@ -1125,7 +1143,7 @@ class BNote extends AbstractBeccaEntity {
}
/** @returns {BAttachment[]} */
getAttachmentByRole(role) {
getAttachmentsByRole(role) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
@@ -1136,6 +1154,18 @@ class BNote extends AbstractBeccaEntity {
.map(row => new BAttachment(row));
}
/** @returns {BAttachment} */
getAttachmentByTitle(title) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND title = ?
AND isDeleted = 0
ORDER BY position`, [this.noteId, title])
.map(row => new BAttachment(row))[0];
}
/**
* Gives all possible note paths leading to this note. Paths containing search note are ignored (could form cycles)
*
@@ -1583,16 +1613,12 @@ class BNote extends AbstractBeccaEntity {
revision.save(); // to generate revisionId, which is then used to save attachments
if (this.type === 'text') {
for (const noteAttachment of this.getAttachments()) {
if (noteAttachment.utcDateScheduledForErasureSince) {
continue;
}
const revisionAttachment = noteAttachment.copy();
revisionAttachment.ownerId = revision.revisionId;
revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true});
for (const noteAttachment of this.getAttachments()) {
const revisionAttachment = noteAttachment.copy();
revisionAttachment.ownerId = revision.revisionId;
revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true});
if (this.type === 'text') {
// content is rewritten to point to the revision attachments
noteContent = noteContent.replaceAll(`attachments/${noteAttachment.attachmentId}`,
`attachments/${revisionAttachment.attachmentId}`);
@@ -1600,10 +1626,10 @@ class BNote extends AbstractBeccaEntity {
noteContent = noteContent.replaceAll(new RegExp(`href="[^"]*attachmentId=${noteAttachment.attachmentId}[^"]*"`, 'gi'),
`href="api/attachments/${revisionAttachment.attachmentId}/download"`);
}
revision.setContent(noteContent, {forceSave: true});
}
revision.setContent(noteContent);
return revision;
});
}

View File

@@ -86,6 +86,29 @@ class BRevision extends AbstractBeccaEntity {
return this._getContent();
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent();
if (!content || !content.trim()) {
return null;
}
return JSON.parse(content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
/**
* @param content
* @param {object} [opts]
@@ -105,6 +128,45 @@ class BRevision extends AbstractBeccaEntity {
.map(row => new BAttachment(row));
}
/** @returns {BAttachment|null} */
getAttachmentById(attachmentId, opts = {}) {
opts.includeContentLength = !!opts.includeContentLength;
const query = opts.includeContentLength
? `SELECT attachments.*, LENGTH(blobs.content) AS contentLength
FROM attachments
JOIN blobs USING (blobId)
WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`
: `SELECT * FROM attachments WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`;
return sql.getRows(query, [this.revisionId, attachmentId])
.map(row => new BAttachment(row))[0];
}
/** @returns {BAttachment[]} */
getAttachmentsByRole(role) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND role = ?
AND isDeleted = 0
ORDER BY position`, [this.revisionId, role])
.map(row => new BAttachment(row));
}
/** @returns {BAttachment} */
getAttachmentByTitle(title) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND title = ?
AND isDeleted = 0
ORDER BY position`, [this.revisionId, title])
.map(row => new BAttachment(row))[0];
}
beforeSaving() {
super.beforeSaving();

View File

@@ -127,7 +127,8 @@ paths:
- targetRelationCount
- targetRelationCountIncludingLinks
- contentSize
- noteSize
- contentAndAttachmentsSize
- contentAndAttachmentsAndRevisionsSize
- revisionCount
- name: orderDirection
in: query

View File

@@ -647,4 +647,12 @@ export default class TabManager extends Component {
await this.updateDocumentTitle(activeContext);
}
}
async frocaReloadedEvent() {
const activeContext = this.getActiveContext();
if (activeContext) {
await this.updateDocumentTitle(activeContext);
}
}
}

View File

@@ -15,4 +15,25 @@ export default class FBlob {
/** @type {string} */
this.utcDateModified = row.utcDateModified;
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
if (!this.content || !this.content.trim()) {
return null;
}
return JSON.parse(this.content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
}

View File

@@ -236,6 +236,12 @@ class FNote {
return this.attachments;
}
/** @returns {Promise<FAttachment[]>} */
async getAttachmentsByRole(role) {
return (await this.getAttachments())
.filter(attachment => attachment.role === role);
}
/** @returns {Promise<FAttachment>} */
async getAttachmentById(attachmentId) {
const attachments = await this.getAttachments();

View File

@@ -78,6 +78,7 @@ import HideFloatingButtonsButton from "../widgets/floating_buttons/hide_floating
import ScriptExecutorWidget from "../widgets/ribbon_widgets/script_executor.js";
import MovePaneButton from "../widgets/buttons/move_pane_button.js";
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
import CanvasPropertiesWidget from "../widgets/ribbon_widgets/canvas_properties.js";
export default class DesktopLayout {
constructor(customWidgets) {
@@ -144,6 +145,7 @@ export default class DesktopLayout {
.ribbon(new NotePropertiesWidget())
.ribbon(new FilePropertiesWidget())
.ribbon(new ImagePropertiesWidget())
.ribbon(new CanvasPropertiesWidget())
.ribbon(new BasicPropertiesWidget())
.ribbon(new OwnedAttributeListWidget())
.ribbon(new InheritedAttributesWidget())

View File

@@ -32,8 +32,8 @@ export default class LauncherContextMenu {
const isVisibleItem = parentNoteId === '_lbVisibleLaunchers';
const isAvailableItem = parentNoteId === '_lbAvailableLaunchers';
const isItem = isVisibleItem || isAvailableItem;
const canBeDeleted = !note.isLaunchBarConfig();
const canBeReset = note.isLaunchBarConfig();
const canBeDeleted = !note.noteId.startsWith("_"); // fixed notes can't be deleted
const canBeReset = !canBeDeleted && note.isLaunchBarConfig();;
return [
(isVisibleRoot || isAvailableRoot) ? { title: 'Add a note launcher', command: 'addNoteLauncher', uiIcon: "bx bx-plus" } : null,

View File

@@ -69,7 +69,8 @@ export default class TreeContextMenu {
{ title: 'Collapse subtree <kbd data-command="collapseSubtree"></kbd>', command: "collapseSubtree", uiIcon: "bx bx-collapse", 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: 'Convert to attachment', command: "convertNoteToAttachment", uiIcon: "bx bx-empty", enabled: isNotRoot && !isHoisted }
{ title: 'Convert to attachment', command: "convertNoteToAttachment", uiIcon: "bx bx-empty", enabled: isNotRoot && !isHoisted },
{ title: 'Copy note path to clipboard', command: "copyNotePathToClipboard", uiIcon: "bx bx-empty", enabled: true }
] },
{ title: "----" },
{ title: "Protect subtree", command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
@@ -153,6 +154,9 @@ export default class TreeContextMenu {
toastService.showMessage(`${converted} notes have been converted to attachments.`);
}
else if (command === 'copyNotePathToClipboard') {
navigator.clipboard.writeText('#' + notePath);
}
else {
this.treeWidget.triggerCommand(command, {
node: this.node,

View File

@@ -33,7 +33,7 @@ async function getRenderedContent(entity, options = {}) {
else if (type === 'code') {
await renderCode(entity, $renderedContent);
}
else if (type === 'image') {
else if (type === 'image' || type === 'canvas') {
renderImage(entity, $renderedContent, options);
}
else if (!options.tooltip && ['file', 'pdf', 'audio', 'video'].includes(type)) {
@@ -49,9 +49,6 @@ async function getRenderedContent(entity, options = {}) {
$renderedContent.append($content);
}
else if (type === 'canvas') {
await renderCanvas(entity, $renderedContent);
}
else if (!options.tooltip && type === 'protectedSession') {
const $button = $(`<button class="btn btn-sm"><span class="bx bx-log-in"></span> Enter protected session</button>`)
.on('click', protectedSessionService.enterProtectedSession);
@@ -125,7 +122,7 @@ function renderImage(entity, $renderedContent, options = {}) {
let url;
if (entity instanceof FNote) {
url = `api/images/${entity.noteId}/${sanitizedTitle}?${entity.utcDateModified}`;
url = `api/images/${entity.noteId}/${sanitizedTitle}?${Math.random()}`;
} else if (entity instanceof FAttachment) {
url = `api/attachments/${entity.attachmentId}/image/${sanitizedTitle}?${entity.utcDateModified}">`;
}
@@ -236,28 +233,6 @@ async function renderMermaid(note, $renderedContent) {
}
}
async function renderCanvas(note, $renderedContent) {
// make sure surrounding container has size of what is visible. Then image is shrinked to its boundaries
$renderedContent.css({height: "100%", width: "100%"});
const blob = await note.getBlob();
const content = blob.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."));
}
}
/**
* @param {jQuery} $renderedContent
* @param {FNote} note

View File

@@ -14,6 +14,7 @@ import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js";
import shortcutService from "./shortcuts.js";
import dialogService from "./dialog.js";
/**
* <p>This is the main frontend API interface for scripts. All the properties and methods are published in the "api" object
@@ -258,7 +259,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.parseDate = utils.parseDate;
/**
* Show an info message to the user.
* Show an info toast message to the user.
*
* @method
* @param {string} message
@@ -266,13 +267,43 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.showMessage = toastService.showMessage;
/**
* Show an error message to the user.
* Show an error toast message to the user.
*
* @method
* @param {string} message
*/
this.showError = toastService.showError;
/**
* Show an info dialog to the user.
*
* @method
* @param {string} message
* @returns {Promise}
*/
this.showInfoDialog = dialogService.info;
/**
* Show confirm dialog to the user.
*
* @method
* @param {string} message
* @returns {Promise<boolean>} promise resolving to true if the user confirmed
*/
this.showConfirmDialog = dialogService.confirm;
/**
* Show prompt dialog to the user.
*
* @method
* @param {object} props
* @param {string} props.title
* @param {string} props.message
* @param {string} props.defaultValue
* @returns {Promise<string>} promise resolving to the answer provided by the user
*/
this.showPromptDialog = dialogService.prompt;
/**
* Trigger command. This is a very low-level API which should be avoided if possible.
*

View File

@@ -10,6 +10,8 @@ const CODE_MIRROR = {
"libraries/codemirror/addon/lint/lint.js",
"libraries/codemirror/addon/lint/eslint.js",
"libraries/codemirror/addon/mode/loadmode.js",
"libraries/codemirror/addon/mode/multiplex.js",
"libraries/codemirror/addon/mode/overlay.js",
"libraries/codemirror/addon/mode/simple.js",
"libraries/codemirror/addon/search/match-highlighter.js",
"libraries/codemirror/mode/meta.js",

View File

@@ -194,6 +194,10 @@ function goToLink(evt) {
const $link = $(evt.target).closest("a,.block-link");
const hrefLink = $link.attr('href') || $link.attr('data-href');
return goToLinkExt(evt, hrefLink, $link);
}
function goToLinkExt(evt, hrefLink, $link) {
if (hrefLink?.startsWith("data:")) {
return true;
}
@@ -201,7 +205,7 @@ function goToLink(evt) {
evt.preventDefault();
evt.stopPropagation();
const { notePath, viewScope } = parseNavigationStateFromUrl(hrefLink);
const {notePath, viewScope} = parseNavigationStateFromUrl(hrefLink);
const ctrlKey = utils.isCtrlKey(evt);
const isLeftClick = evt.which === 1;
@@ -213,25 +217,23 @@ function goToLink(evt) {
if (notePath) {
if (openInNewTab) {
appContext.tabManager.openTabWithNoteWithHoisting(notePath, { viewScope });
}
else if (isLeftClick) {
appContext.tabManager.openTabWithNoteWithHoisting(notePath, {viewScope});
} else if (isLeftClick) {
const ntxId = $(evt.target).closest("[data-ntx-id]").attr("data-ntx-id");
const noteContext = ntxId
? appContext.tabManager.getNoteContextById(ntxId)
: appContext.tabManager.getActiveContext();
noteContext.setNote(notePath, { viewScope }).then(() => {
noteContext.setNote(notePath, {viewScope}).then(() => {
if (noteContext !== appContext.tabManager.getActiveContext()) {
appContext.tabManager.activateNoteContext(noteContext.ntxId);
}
});
}
}
else if (hrefLink) {
const withinEditLink = $link.hasClass("ck-link-actions__preview");
const outsideOfCKEditor = $link.closest("[contenteditable]").length === 0;
} else if (hrefLink) {
const withinEditLink = $link?.hasClass("ck-link-actions__preview");
const outsideOfCKEditor = !$link || $link.closest("[contenteditable]").length === 0;
if (openInNewTab
|| (withinEditLink && (leftClick || middleClick))
@@ -239,8 +241,7 @@ function goToLink(evt) {
) {
if (hrefLink.toLowerCase().startsWith('http') || hrefLink.startsWith("api/")) {
window.open(hrefLink, '_blank');
}
else if (hrefLink.toLowerCase().startsWith('file:') && utils.isElectron()) {
} else if (hrefLink.toLowerCase().startsWith('file:') && utils.isElectron()) {
const electron = utils.dynamicRequire('electron');
electron.shell.openPath(hrefLink);
@@ -364,6 +365,7 @@ export default {
getNotePathFromUrl,
createLink,
goToLink,
goToLinkExt,
loadReferenceLinkTitle,
getReferenceLinkTitle,
getReferenceLinkTitleSync,

View File

@@ -252,11 +252,15 @@ class NoteListRenderer {
if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(this.page - i) <= 2) {
lastPrinted = true;
const startIndex = (i - 1) * this.pageSize + 1;
const endIndex = Math.min(this.noteIds.length, i * this.pageSize);
$pager.append(
i === this.page
? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold")
: $('<a href="javascript:">')
.text(i)
.attr("title", `Page of ${startIndex} - ${endIndex}`)
.on('click', () => {
this.page = i;
this.renderList();
@@ -270,6 +274,9 @@ class NoteListRenderer {
lastPrinted = false;
}
}
// no need to distinguish "note" vs "notes" since in case of one result, there's no paging at all
$pager.append(`<span class="note-list-pager-total-count">(${this.noteIds.length} notes)</span>`);
}
async renderNote(note, expand = false) {

View File

@@ -495,6 +495,14 @@ function copyHtmlToClipboard(content) {
navigator.clipboard.write([clipboardItem]);
}
/**
* @param {FNote} note
* @return {string}
*/
function createImageSrcUrl(note) {
return `api/images/${note.noteId}/${encodeURIComponent(note.title)}?timestamp=${Date.now()}`;
}
export default {
reloadFrontendApp,
parseDate,
@@ -533,5 +541,6 @@ export default {
sleep,
escapeRegExp,
areObjectsEqual,
copyHtmlToClipboard
copyHtmlToClipboard,
createImageSrcUrl
};

View File

@@ -45,6 +45,7 @@ const TPL = `
<a class="dropdown-item export-note-button">Export note</a>
<a class="dropdown-item delete-note-button">Delete note</a>
<a data-trigger-command="printActiveNote" class="dropdown-item print-active-note-button"><kbd data-command="printActiveNote"></kbd> Print note</a>
<a data-trigger-command="forceSaveRevision" class="dropdown-item save-revision-button"><kbd data-command="forceSaveRevision"></kbd> Save revision</a>
</div>
</div>`;
@@ -55,6 +56,7 @@ export default class NoteActionsWidget extends NoteContextAwareWidget {
doRender() {
this.$widget = $(TPL);
this.$widget.on('show.bs.dropdown', () => this.refreshVisibility(this.note));
this.$convertNoteIntoAttachmentButton = this.$widget.find("[data-trigger-command='convertNoteIntoAttachment']");
this.$findInTextButton = this.$widget.find('.find-in-text-button');
@@ -92,22 +94,22 @@ export default class NoteActionsWidget extends NoteContextAwareWidget {
});
}
async refreshWithNote(note) {
async refreshVisibility(note) {
this.$convertNoteIntoAttachmentButton.toggle(note.isEligibleForConversionToAttachment());
this.toggleDisabled(this.$findInTextButton, ['text', 'code', 'book'].includes(note.type));
this.toggleDisabled(this.$showSourceButton, ['text', 'relationMap', 'mermaid'].includes(note.type));
this.toggleDisabled(this.$showSourceButton, ['text', 'code', 'relationMap', 'mermaid', 'canvas'].includes(note.type));
this.toggleDisabled(this.$printActiveNoteButton, ['text', 'code'].includes(note.type));
this.$renderNoteButton.toggle(note.type === 'render');
this.toggleDisabled(this.$openNoteExternallyButton, utils.isElectron() && !['search'].includes(note.type));
this.toggleDisabled(this.$openNoteExternallyButton, utils.isElectron() && !['search', 'book'].includes(note.type));
this.toggleDisabled(this.$openNoteCustomButton,
utils.isElectron()
&& !utils.isMac() // no implementation for Mac yet
&& !['search'].includes(note.type)
&& !['search', 'book'].includes(note.type)
);
// I don't want to handle all special notes like this, but intuitively user might want to export content of backend log

View File

@@ -274,26 +274,11 @@ export default class RevisionsDialog extends BasicWidget {
this.$content.html($table);
} else if (revisionItem.type === 'canvas') {
/**
* FIXME: We load a font called Virgil.wof2, which originates from excalidraw.com
* REMOVE external dependency!!!! This is defined in the svg in defs.style
*/
const content = fullRevision.content;
const sanitizedTitle = revisionItem.title.replace(/[^a-z0-9-.]/gi, "");
try {
const data = JSON.parse(content)
const svg = data.svg || "no svg present."
/**
* maxWidth: 100% use full width of container but do not enlarge!
* height:auto to ensure that height scales with width
*/
const $svgHtml = $(svg).css({maxWidth: "100%", height: "auto"});
this.$content.html($('<div>').append($svgHtml));
} catch (err) {
console.error("error parsing fullRevision.content as JSON", fullRevision.content, err);
this.$content.html($("<div>").text("Error parsing content. Please check console.error() for more details."));
}
this.$content.html($("<img>")
.attr("src", `api/revisions/${revisionItem.revisionId}/image/${sanitizedTitle}?${Math.random()}`)
.css("max-width", "100%"));
} else {
this.$content.text("Preview isn't available for this note type.");
}

View File

@@ -16,6 +16,10 @@ const TPL = `
z-index: 100;
}
.type-canvas .floating-buttons-children {
top: 70px;
}
.floating-buttons-children > *:not(.hidden-int):not(.no-content-hidden) {
margin-left: 10px;
}

View File

@@ -86,6 +86,8 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
protectedSessionHolder.touchProtectedSessionIfNecessary(note);
await server.put(`notes/${noteId}/data`, data, this.componentId);
this.getTypeWidget().dataSaved?.();
});
appContext.addBeforeUnloadListener(this);
@@ -167,7 +169,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
let type = note.type;
const viewScope = this.noteContext.viewScope;
if (type === 'text' && viewScope.viewMode === 'source') {
if (viewScope.viewMode === 'source') {
type = 'readOnlyCode';
} else if (viewScope.viewMode === 'attachments') {
type = viewScope.attachmentId ? 'attachmentDetail' : 'attachmentList';

View File

@@ -14,7 +14,6 @@ import keyboardActionsService from "../services/keyboard_actions.js";
import clipboard from "../services/clipboard.js";
import protectedSessionService from "../services/protected_session.js";
import linkService from "../services/link.js";
import syncService from "../services/sync.js";
import options from "../services/options.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import dialogService from "../services/dialog.js";
@@ -586,6 +585,17 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
});
},
select: (event, {node}) => {
if (hoistedNoteService.getHoistedNoteId() === 'root'
&& node.data.noteId === '_hidden'
&& node.isSelected()) {
// hidden is hackily hidden from the tree via CSS when root is hoisted
// make sure it's not selected by mistake, it could be e.g. deleted by mistake otherwise
node.setSelected(false);
return;
}
$(node.span).find(".fancytree-custom-icon").attr("title",
node.isSelected() ? "Apply bulk actions on selected notes" : "");
}
@@ -799,7 +809,10 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
nodes.push(this.getActiveNode());
}
return nodes;
// hidden subtree is hackily hidden via CSS when hoisted to root
// make sure it's never selected for e.g. deletion in such a case
return nodes.filter(node => hoistedNoteService.getHoistedNoteId() !== 'root'
|| node.data.noteId !== '_hidden');
}
async setExpandedStatusForSubtree(node, isExpanded) {
@@ -1134,6 +1147,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
let parentsOfAddedNodes = [];
const allBranchRows = loadResults.getBranchRows();
// TODO: this flag is suspicious - why does it matter that all branches in a particular update are deleted?
const allBranchesDeleted = allBranchRows.every(branchRow => !!branchRow.isDeleted);
for (const branchRow of allBranchRows) {
@@ -1146,8 +1160,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
noteIdsToUpdate.add(branchRow.noteId);
}
for (const node of this.getNodesByBranch(branchRow)) {
if (branchRow.isDeleted) {
if (branchRow.isDeleted) {
for (const node of this.getNodesByBranch(branchRow)) {
if (node.isActive()) {
if (allBranchesDeleted) {
const newActiveNode = node.getNextSibling()
@@ -1168,9 +1182,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
noteIdsToUpdate.add(branchRow.parentNoteId);
}
}
if (!branchRow.isDeleted) {
} else {
for (const parentNode of this.getNodesByNoteId(branchRow.parentNoteId)) {
parentsOfAddedNodes.push(parentNode)
@@ -1181,12 +1193,16 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
const found = (parentNode.getChildren() || []).find(child => child.data.noteId === branchRow.noteId);
if (!found) {
// make sure it's loaded
await froca.getNote(branchRow.noteId);
const note = await froca.getNote(branchRow.noteId);
const frocaBranch = froca.getBranch(branchRow.branchId);
// we're forcing lazy since it's not clear if the whole required subtree is in froca
parentNode.addChildren([this.prepareNode(frocaBranch, true)]);
if (frocaBranch.isExpanded && note.hasChildren()) {
noteIdsToReload.add(frocaBranch.noteId);
}
this.sortChildren(parentNode);
// this might be a first child which would force an icon change

View File

@@ -0,0 +1,56 @@
import NoteContextAwareWidget from "../note_context_aware_widget.js";
import utils from "../../services/utils.js";
import imageService from "../../services/image.js";
const TPL = `
<div class="image-properties">
<div style="display: flex; justify-content: space-evenly; margin: 10px;">
<button class="canvas-copy-reference-to-clipboard btn btn-sm btn-primary"
title="Pasting this reference into a text note will insert the canvas note as image"
type="button">Copy reference to clipboard</button>
</div>
<div class="hidden-canvas-copy"></div>
</div>`;
export default class CanvasPropertiesWidget extends NoteContextAwareWidget {
get name() {
return "canvasProperties";
}
get toggleCommand() {
return "toggleRibbonTabCanvasProperties";
}
isEnabled() {
return this.note && this.note.type === 'canvas';
}
getTitle() {
return {
show: this.isEnabled(),
activate: false,
title: 'Canvas',
icon: 'bx bx-pen'
};
}
doRender() {
this.$widget = $(TPL);
this.contentSized();
this.$hiddenCanvasCopy = this.$widget.find('.hidden-canvas-copy');
this.$copyReferenceToClipboardButton = this.$widget.find(".canvas-copy-reference-to-clipboard");
this.$copyReferenceToClipboardButton.on('click', () => {
this.$hiddenCanvasCopy.empty().append(
$("<img>")
.attr("src", utils.createImageSrcUrl(this.note))
);
imageService.copyImageReferenceToClipboard(this.$hiddenCanvasCopy);
this.$hiddenCanvasCopy.empty();
});
}
}

View File

@@ -61,9 +61,13 @@ export default class ImagePropertiesWidget extends NoteContextAwareWidget {
doRender() {
this.$widget = $(TPL);
this.contentSized();
this.$copyReferenceToClipboardButton = this.$widget.find(".image-copy-reference-to-clipboard");
this.$copyReferenceToClipboardButton.on('click', () => this.triggerEvent(`copyImageReferenceToClipboard`, {ntxId: this.noteContext.ntxId}));
this.$uploadNewRevisionButton = this.$widget.find(".image-upload-new-revision");
this.$uploadNewRevisionInput = this.$widget.find(".image-upload-new-revision-input");
this.$fileName = this.$widget.find(".image-filename");
this.$fileType = this.$widget.find(".image-filetype");
this.$fileSize = this.$widget.find(".image-filesize");
@@ -74,8 +78,6 @@ export default class ImagePropertiesWidget extends NoteContextAwareWidget {
this.$imageDownloadButton = this.$widget.find(".image-download");
this.$imageDownloadButton.on('click', () => openService.downloadFileNote(this.noteId));
this.$copyReferenceToClipboardButton.on('click', () => this.triggerEvent(`copyImageReferenceToClipboard`, {ntxId: this.noteContext.ntxId}));
this.$uploadNewRevisionButton.on("click", () => {
this.$uploadNewRevisionInput.trigger("click");
});

View File

@@ -14,7 +14,8 @@ const TPL = `
<option value="dateCreated">Date created</option>
<option value="dateModified">Date of last modification</option>
<option value="contentSize">Note content size</option>
<option value="noteSize">Note content size including revisions</option>
<option value="contentAndAttachmentsSize">Note content size including attachments</option>
<option value="contentAndAttachmentsAndRevisionsSize">Note content size including attachments and revisions</option>
<option value="revisionCount">Number of revisions</option>
<option value="childrenCount">Number of children notes</option>
<option value="parentCount">Number of clones</option>

View File

@@ -42,10 +42,12 @@ export default class AttachmentListTypeWidget extends TypeWidget {
const $helpButton = $('<button class="attachment-help-button" type="button" data-help-page="attachments" title="Open help page on attachments"><span class="bx bx-help-circle"></span></button>');
utils.initHelpButtons($helpButton);
const noteLink = await linkService.createLink(this.noteId); // do separately to avoid race condition between empty() and .append()
this.$linksWrapper.empty().append(
$('<div>').append(
"Owning note: ",
await linkService.createLink(this.noteId),
noteLink,
),
$('<div>').append(
$('<button class="btn btn-sm">')

View File

@@ -1,6 +1,7 @@
import libraryLoader from "../../services/library_loader.js";
import TypeWidget from "./type_widget.js";
import utils from '../../services/utils.js';
import linkService from '../../services/link.js';
import debounce from "../../services/debounce.js";
const {sleep} = utils;
@@ -19,10 +20,13 @@ const TPL = `
display: block;
}
.excalidraw-wrapper {
height: 100%;
}
.excalidraw button[data-testid="json-export-button"] {
display: none !important;
}
:root[dir="ltr"]
.excalidraw
@@ -51,8 +55,8 @@ const TPL = `
* for sketching. Excalidraw has a vibrant and active community.
*
* Functionality:
* We store the excalidraw assets (elements, appState, files) in the note. In addition to that, we
* export the SVG from the canvas on every update. The SVG is also saved in the note. It is used when
* We store the excalidraw assets (elements and files) in the note. In addition to that, we
* export the SVG from the canvas on every update and store it in the note's attachment. It is used when
* calling api/images and makes referencing very easy.
*
* Paths not taken.
@@ -75,7 +79,7 @@ const TPL = `
* - the 3 excalidraw fonts should be included in the share and everywhere, so that it is shown
* when requiring svg.
*
* Discussion of storing svg in the note:
* Discussion of storing svg in the note attachment:
* - Pro: we will combat bit-rot. Showing the SVG will be very fast and easy, since it is already there.
* - Con: The note will get bigger (~40-50%?), we will generate more bandwidth. However, using trilium
* desktop instance mitigates that issue.
@@ -84,7 +88,6 @@ const TPL = `
* - Support image-notes as reference in excalidraw
* - Support canvas note as reference (svg) in other canvas notes.
* - Make it easy to include a canvas note inside a text note
* - Support for excalidraw libraries. Maybe special code notes with a tag.
*/
export default class ExcalidrawTypeWidget extends TypeWidget {
constructor() {
@@ -113,6 +116,8 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
this.createExcalidrawReactApp = this.createExcalidrawReactApp.bind(this);
this.onChangeHandler = this.onChangeHandler.bind(this);
this.isNewSceneVersion = this.isNewSceneVersion.bind(this);
this.libraryChanged = false;
}
static getType() {
@@ -129,7 +134,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
}
});
this.$widget.toggleClass("full-height", true); // only add
this.$widget.toggleClass("full-height", true);
this.$render = this.$widget.find('.canvas-render');
const documentStyle = window.getComputedStyle(document.documentElement);
this.themeStyle = documentStyle.getPropertyValue('--theme-style')?.trim();
@@ -166,7 +171,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
const blob = await note.getBlob();
// before we load content into excalidraw, make sure excalidraw has loaded
while (!this.excalidrawRef || !this.excalidrawRef.current) {
while (!this.excalidrawRef?.current) {
console.log("excalidrawRef not yet loaded, sleep 200ms...");
await sleep(200);
}
@@ -177,7 +182,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
* note into this fresh note. Probably due to that this note-instance does not get
* newly instantiated?
*/
if (this.excalidrawRef.current && blob.content?.trim() === "") {
if (!blob.content?.trim()) {
const sceneData = {
elements: [],
appState: {
@@ -188,32 +193,26 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
this.excalidrawRef.current.updateScene(sceneData);
}
else if (this.excalidrawRef.current && blob.content) {
else if (blob.content) {
// load saved content into excalidraw canvas
let content;
try {
content = JSON.parse(blob.content || "");
content = blob.getJsonContent();
} catch(err) {
console.error("Error parsing content. Probably note.type changed",
"Starting with empty canvas"
, note, blob, err);
console.error("Error parsing content. Probably note.type changed. Starting with empty canvas", note, blob, err);
content = {
elements: [],
appState: {},
files: [],
appState: {}
};
}
const {elements, appState, files} = content;
const {elements, files, appState = {}} = content;
appState.theme = this.themeStyle;
/**
* use widths and offsets of current view, since stored appState has the state from
* previous edit. using the stored state would lead to pointer mismatch.
*/
const boundingClientRect = this.excalidrawWrapperRef.current.getBoundingClientRect();
appState.width = boundingClientRect.width;
appState.height = boundingClientRect.height;
@@ -243,6 +242,19 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
this.excalidrawRef.current.addFiles(fileArray);
}
Promise.all(
(await note.getAttachmentsByRole('canvasLibraryItem'))
.map(attachment => attachment.getBlob())
).then(blobs => {
if (note.noteId !== this.currentNoteId) {
// current note changed in the course of the async operation
return;
}
const libraryItems = blobs.map(blob => blob.getJsonContentSafely()).filter(item => !!item);
this.excalidrawRef.current.updateLibrary({libraryItems, merge: false});
});
// set initial scene version
if (this.currentSceneVersion === this.SCENE_VERSION_INITIAL) {
this.currentSceneVersion = this.getSceneVersion();
@@ -263,10 +275,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
*/
const files = this.excalidrawRef.current.getFiles();
/**
* parallel svg export to combat bitrot and enable rendering image for note inclusion,
* preview, and share.
*/
// parallel svg export to combat bitrot and enable rendering image for note inclusion, preview, and share
const svg = await window.ExcalidrawLib.exportToSvg({
elements,
appState,
@@ -281,20 +290,48 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
if (element.fileId) {
activeFiles[element.fileId] = files[element.fileId];
}
})
});
const content = {
type: "excalidraw",
version: 2,
_meta: "This note has type `canvas`. It uses excalidraw and stores an exported svg alongside.",
elements, // excalidraw
appState, // excalidraw
files: activeFiles, // excalidraw
svg: svgString, // not needed for excalidraw, used for note_short, content, and image api
elements,
files: activeFiles,
appState: {
scrollX: appState.scrollX,
scrollY: appState.scrollY,
zoom: appState.zoom
}
};
const attachments = [
{ role: 'image', title: 'canvas-export.svg', mime: 'image/svg+xml', content: svgString, position: 0 }
];
if (this.libraryChanged) {
// this.libraryChanged is unset in dataSaved()
// there's no separate method to get library items, so have to abuse this one
const libraryItems = await this.excalidrawRef.current.updateLibrary({merge: true});
let position = 10;
for (const libraryItem of libraryItems) {
attachments.push({
role: 'canvasLibraryItem',
title: libraryItem.id,
mime: 'application/json',
content: JSON.stringify(libraryItem),
position: position
});
position += 10;
}
}
return {
content: JSON.stringify(content)
content: JSON.stringify(content),
attachments
};
}
@@ -306,6 +343,10 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
this.spacedUpdate.scheduleUpdate();
}
dataSaved() {
this.libraryChanged = false;
}
onChangeHandler() {
// changeHandler is called upon any tiny change in excalidraw. button clicked, hover, etc.
// make sure only when a new element is added, we actually save something.
@@ -323,8 +364,6 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
if (shouldSave) {
this.updateSceneVersion();
this.saveData();
} else {
// do nothing
}
}
@@ -366,21 +405,17 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
}, [excalidrawWrapperRef]);
const onLinkOpen = React.useCallback((element, event) => {
const link = element.link;
const { nativeEvent } = event.detail;
const isNewTab = nativeEvent.ctrlKey || nativeEvent.metaKey;
const isNewWindow = nativeEvent.shiftKey;
const isInternalLink = link.startsWith("/")
|| link.includes(window.location.origin);
let link = element.link;
if (isInternalLink && !isNewTab && !isNewWindow) {
// signal that we're handling the redirect ourselves
event.preventDefault();
// do a custom redirect, such as passing to react-router
// ...
} else {
// open in the same tab
if (link.startsWith("root/")) {
link = "#" + link;
}
const { nativeEvent } = event.detail;
event.preventDefault();
return linkService.goToLinkExt(nativeEvent, link, null);
}, []);
return React.createElement(
@@ -401,6 +436,11 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
onPaste: (data, event) => {
console.log("Verbose: excalidraw internal paste. No trilium action implemented.", data, event);
},
onLibraryChange: () => {
this.libraryChanged = true;
this.saveData();
},
onChange: debounce(this.onChangeHandler, this.DEBOUNCE_TIME_ONCHANGEHANDLER),
viewModeEnabled: false,
zenModeEnabled: false,
@@ -408,15 +448,19 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
isCollaborating: false,
detectScroll: false,
handleKeyboardGlobally: false,
autoFocus: true,
autoFocus: false,
onLinkOpen,
UIOptions: {
saveToActiveFile: false,
saveAsImage: false
}
})
)
);
}
/**
* needed to ensure, that multipleOnChangeHandler calls do not trigger a safe.
* needed to ensure, that multipleOnChangeHandler calls do not trigger a save.
* we compare the scene version as suggested in:
* https://github.com/excalidraw/excalidraw/issues/3014#issuecomment-778115329
*
@@ -426,8 +470,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
const sceneVersion = this.getSceneVersion();
return this.currentSceneVersion === this.SCENE_VERSION_INITIAL // initial scene version update
|| this.currentSceneVersion !== sceneVersion // ensure scene changed
;
|| this.currentSceneVersion !== sceneVersion; // ensure scene changed
}
getSceneVersion() {

View File

@@ -90,7 +90,7 @@ class ImageTypeWidget extends TypeWidget {
}
async doRefresh(note) {
this.$imageView.prop("src", `api/images/${note.noteId}/${encodeURIComponent(note.title)}?timestamp=${Date.now()}`);
this.$imageView.prop("src", utils.createImageSrcUrl(note));
}
copyImageReferenceToClipboardEvent({ntxId}) {

View File

@@ -20,6 +20,10 @@ const TPL = `
<p>You can decide yourself if you want to provide a fully or lightly anonymized database. Even fully anonymized DB is very useful, however in some cases lightly anonymized database can speed up the process of bug identification and fixing.</p>
<button class="anonymize-light-button btn">Save lightly anonymized database</button>
<h5>Existing anonymized databases</h5>
<ul class="existing-anonymized-databases"></ul>
</div>`;
export default class DatabaseAnonymizationOptions extends OptionsWidget {
@@ -38,6 +42,8 @@ export default class DatabaseAnonymizationOptions extends OptionsWidget {
else {
toastService.showMessage(`Created fully anonymized database in ${resp.anonymizedFilePath}`, 10000);
}
this.refresh();
});
this.$anonymizeLightButton.on('click', async () => {
@@ -51,6 +57,24 @@ export default class DatabaseAnonymizationOptions extends OptionsWidget {
else {
toastService.showMessage(`Created lightly anonymized database in ${resp.anonymizedFilePath}`, 10000);
}
this.refresh();
});
this.$existingAnonymizedDatabases = this.$widget.find(".existing-anonymized-databases");
}
optionsLoaded(options) {
server.get("database/anonymized-databases").then(anonymizedDatabases => {
this.$existingAnonymizedDatabases.empty();
if (!anonymizedDatabases.length) {
anonymizedDatabases = [{filePath: "no anonymized database yet"}];
}
for (const {filePath} of anonymizedDatabases) {
this.$existingAnonymizedDatabases.append($("<li>").text(filePath));
}
});
}
}

View File

@@ -37,6 +37,12 @@ const TPL = `
<button class="backup-database-button btn">Backup database now</button>
</div>
<div class="options-section">
<h4>Existing backups</h4>
<ul class="existing-backup-list"></ul>
</div>
`;
export default class BackupOptions extends OptionsWidget {
@@ -49,6 +55,8 @@ export default class BackupOptions extends OptionsWidget {
const {backupFile} = await server.post('database/backup-database');
toastService.showMessage(`Database has been backed up to ${backupFile}`, 10000);
this.refresh();
});
this.$dailyBackupEnabled = this.$widget.find(".daily-backup-enabled");
@@ -63,11 +71,25 @@ export default class BackupOptions extends OptionsWidget {
this.$monthlyBackupEnabled.on('change', () =>
this.updateCheckboxOption('monthlyBackupEnabled', this.$monthlyBackupEnabled));
this.$existingBackupList = this.$widget.find(".existing-backup-list");
}
optionsLoaded(options) {
this.setCheckboxState(this.$dailyBackupEnabled, options.dailyBackupEnabled);
this.setCheckboxState(this.$weeklyBackupEnabled, options.weeklyBackupEnabled);
this.setCheckboxState(this.$monthlyBackupEnabled, options.monthlyBackupEnabled);
server.get("database/backups").then(backupFiles => {
this.$existingBackupList.empty();
if (!backupFiles.length) {
backupFiles = [{filePath: "no backup yet", ctime: ''}];
}
for (const {filePath, ctime} of backupFiles) {
this.$existingBackupList.append($("<li>").text(`${filePath} ${ctime ? ` - ${ctime}` : ''}`));
}
});
}
}

View File

@@ -6,8 +6,8 @@ const backupService = require('../../services/backup');
const anonymizationService = require('../../services/anonymization');
const consistencyChecksService = require('../../services/consistency_checks');
async function anonymize(req) {
return await anonymizationService.createAnonymizedCopy(req.params.type);
function getExistingBackups() {
return backupService.getExistingBackups();
}
async function backupDatabase() {
@@ -22,6 +22,18 @@ function vacuumDatabase() {
log.info("Database has been vacuumed.");
}
function findAndFixConsistencyIssues() {
consistencyChecksService.runOnDemandChecks(true);
}
function getExistingAnonymizedDatabases() {
return anonymizationService.getExistingAnonymizedDatabases();
}
async function anonymize(req) {
return await anonymizationService.createAnonymizedCopy(req.params.type);
}
function checkIntegrity() {
const results = sql.getRows("PRAGMA integrity_check");
@@ -32,14 +44,12 @@ function checkIntegrity() {
};
}
function findAndFixConsistencyIssues() {
consistencyChecksService.runOnDemandChecks(true);
}
module.exports = {
getExistingBackups,
backupDatabase,
vacuumDatabase,
findAndFixConsistencyIssues,
getExistingAnonymizedDatabases,
anonymize,
checkIntegrity
};

View File

@@ -5,14 +5,27 @@ const becca = require('../../becca/becca');
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
const fs = require('fs');
function returnImage(req, res) {
function returnImageFromNote(req, res) {
const image = becca.getNote(req.params.noteId);
return returnImageInt(image, res);
}
function returnImageFromRevision(req, res) {
const image = becca.getRevision(req.params.revisionId);
return returnImageInt(image, res);
}
/**
* @param {BNote|BRevision} image
* @param res
*/
function returnImageInt(image, res) {
if (!image) {
res.set('Content-Type', 'image/png');
return res.send(fs.readFileSync(`${RESOURCE_DIR}/db/image-deleted.png`));
}
else if (!["image", "canvas"].includes(image.type)){
} else if (!["image", "canvas"].includes(image.type)) {
return res.sendStatus(400);
}
@@ -21,19 +34,24 @@ function returnImage(req, res) {
* to avoid bitrot and enable usage as referenced image the svg is included.
*/
if (image.type === 'canvas') {
const content = image.getContent();
try {
const data = JSON.parse(content);
let svgString = '<svg/>'
const attachment = image.getAttachmentByTitle('canvas-export.svg');
const svg = data.svg || '<svg />'
res.set('Content-Type', "image/svg+xml");
res.set("Cache-Control", "no-cache, no-store, must-revalidate");
res.send(svg);
} catch(err) {
res.setHeader("Content-Type", "text/plain")
.status(500)
.send("there was an error parsing excalidraw to svg");
if (attachment) {
svgString = attachment.getContent();
} else {
// backwards compatibility, before attachments, the SVG was stored in the main note content as a separate key
const contentSvg = image.getJsonContentSafely()?.svg;
if (contentSvg) {
svgString = contentSvg;
}
}
const svg = svgString
res.set('Content-Type', "image/svg+xml");
res.set("Cache-Control", "no-cache, no-store, must-revalidate");
res.send(svg);
} else {
res.set('Content-Type', image.mime);
res.set("Cache-Control", "no-cache, no-store, must-revalidate");
@@ -50,7 +68,9 @@ function returnAttachedImage(req, res) {
}
if (!["image"].includes(attachment.role)) {
return res.sendStatus(400);
return res.setHeader("Content-Type", "text/plain")
.status(400)
.send(`Attachment '${attachment.attachmentId}' has role '${attachment.role}', but 'image' was expected.`);
}
res.set('Content-Type', attachment.mime);
@@ -77,7 +97,8 @@ function updateImage(req) {
}
module.exports = {
returnImage,
returnImageFromNote,
returnImageFromRevision,
returnAttachedImage,
updateImage
};

View File

@@ -45,10 +45,10 @@ function createNote(req) {
}
function updateNoteData(req) {
const {content} = req.body;
const {content, attachments} = req.body;
const {noteId} = req.params;
return noteService.updateNoteData(noteId, content);
return noteService.updateNoteData(noteId, content, attachments);
}
function deleteNote(req) {

View File

@@ -166,11 +166,7 @@ function update(req) {
const {entities, instanceId} = body;
sql.transactional(() => {
for (const {entityChange, entity} of entities) {
syncUpdateService.updateEntity(entityChange, entity, instanceId);
}
});
sql.transactional(() => syncUpdateService.updateEntities(entities, instanceId));
}
setInterval(() => {

View File

@@ -181,6 +181,8 @@ function register(app) {
apiRoute(GET, '/api/revisions/:revisionId/blob', revisionsApiRoute.getRevisionBlob);
apiRoute(DEL, '/api/revisions/:revisionId', revisionsApiRoute.eraseRevision);
apiRoute(PST, '/api/revisions/:revisionId/restore', revisionsApiRoute.restoreRevision);
route(GET, '/api/revisions/:revisionId/image/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImageFromRevision);
route(GET, '/api/revisions/:revisionId/download', [auth.checkApiAuthOrElectron], revisionsApiRoute.downloadRevision);
@@ -200,7 +202,7 @@ function register(app) {
apiRoute(GET, '/api/attribute-values/:attributeName', attributesRoute.getValuesForAttribute);
// :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImageFromNote);
route(PUT, '/api/images/:noteId', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware], imageRoute.updateImage, apiResultHandler);
apiRoute(GET, '/api/options', optionsApiRoute.getOptions);
@@ -287,9 +289,11 @@ function register(app) {
apiRoute(GET, '/api/sql/schema', sqlRoute.getSchema);
apiRoute(PST, '/api/sql/execute/:noteId', sqlRoute.execute);
route(PST, '/api/database/anonymize/:type', [auth.checkApiAuthOrElectron, csrfMiddleware], databaseRoute.anonymize, apiResultHandler, false);
apiRoute(GET, '/api/database/anonymized-databases', databaseRoute.getExistingAnonymizedDatabases);
// backup requires execution outside of transaction
route(PST, '/api/database/backup-database', [auth.checkApiAuthOrElectron, csrfMiddleware], databaseRoute.backupDatabase, apiResultHandler, false);
apiRoute(GET, '/api/database/backups', databaseRoute.getExistingBackups);
// VACUUM requires execution outside of transaction
route(PST, '/api/database/vacuum-database', [auth.checkApiAuthOrElectron, csrfMiddleware], databaseRoute.vacuumDatabase, apiResultHandler, false);

View File

@@ -4,11 +4,13 @@ const dataDir = require("./data_dir");
const dateUtils = require("./date_utils");
const Database = require("better-sqlite3");
const sql = require("./sql");
const path = require("path");
function getFullAnonymizationScript() {
// we want to delete all non-builtin attributes because they can contain sensitive names and values
// on the other hand builtin/system attrs should not contain any sensitive info
// on the other hand builtin/system attrs should not contain any sensitive info
const builtinAttrNames = BUILTIN_ATTRIBUTES
.filter(attr => !["shareCredentials", "shareAlias"].includes(attr.name))
.map(attr => `'${attr.name}'`).join(', ');
const anonymizeScript = `
@@ -69,7 +71,21 @@ async function createAnonymizedCopy(type) {
};
}
function getExistingAnonymizedDatabases() {
if (!fs.existsSync(dataDir.ANONYMIZED_DB_DIR)) {
return [];
}
return fs.readdirSync(dataDir.ANONYMIZED_DB_DIR)
.filter(fileName => fileName.includes("anonymized"))
.map(fileName => ({
fileName: fileName,
filePath: path.resolve(dataDir.ANONYMIZED_DB_DIR, fileName)
}));
}
module.exports = {
getFullAnonymizationScript,
createAnonymizedCopy
createAnonymizedCopy,
getExistingAnonymizedDatabases
}

View File

@@ -4,7 +4,7 @@ const build = require('./build');
const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir');
const APP_DB_VERSION = 225;
const APP_DB_VERSION = 226;
const SYNC_VERSION = 31;
const CLIPPER_PROTOCOL_VERSION = "1.0";

View File

@@ -19,6 +19,7 @@ const SpacedUpdate = require("./spaced_update");
const specialNotesService = require("./special_notes");
const branchService = require("./branches");
const exportService = require("./export/zip");
const syncMutex = require("./sync_mutex.js");
/**
* <p>This is the main backend API interface for scripts. All the properties and methods are published in the "api" object
@@ -571,6 +572,20 @@ function BackendScriptApi(currentNote, apiParams) {
}
};
/**
* Sync process can make data intermittently inconsistent. Scripts which require strong data consistency
* can use this function to wait for a possible sync process to finish and prevent new sync process from starting
* while it is running.
*
* Because this is an async process, the inner callback doesn't have automatic transaction handling, so in case
* you need to make some DB changes, you need to surround your call with api.transactional(...)
*
* @method
* @param {function} callback - function to be executed while sync process is not running
* @returns {Promise} - resolves once the callback is finished (callback is awaited)
*/
this.runOutsideOfSync = syncMutex.doExclusively;
/**
* This object contains "at your risk" and "no BC guarantees" objects for advanced use cases.
*

View File

@@ -8,6 +8,22 @@ const log = require('./log');
const syncMutexService = require('./sync_mutex');
const cls = require('./cls');
const sql = require('./sql');
const path = require('path');
function getExistingBackups() {
if (!fs.existsSync(dataDir.BACKUP_DIR)) {
return [];
}
return fs.readdirSync(dataDir.BACKUP_DIR)
.filter(fileName => fileName.includes("backup"))
.map(fileName => {
const filePath = path.resolve(dataDir.BACKUP_DIR, fileName);
const stat = fs.statSync(filePath)
return {fileName, filePath, ctime: stat.ctime};
});
}
function regularBackup() {
cls.init(() => {
@@ -58,6 +74,7 @@ if (!fs.existsSync(dataDir.BACKUP_DIR)) {
}
module.exports = {
getExistingBackups,
backupNow,
regularBackup
};

View File

@@ -1 +1 @@
module.exports = { buildDate:"2023-09-06T23:57:29+02:00", buildRevision: "6fa9d996e84f87fcb73c3388a5170affd2c2f7cc" };
module.exports = { buildDate:"2023-10-19T09:33:51+02:00", buildRevision: "b01fe5ead9268784fb133a8cfa53670927ba0e3b" };

View File

@@ -66,6 +66,7 @@ module.exports = [
{ type: 'label', name: 'executeDescription'},
{ type: 'label', name: 'newNotesOnTop'},
{ type: 'label', name: 'clipperInbox'},
{ type: 'label', name: 'webViewSrc', isDangerous: true },
// relation names
{ type: 'relation', name: 'internalLink' },

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