Compare commits

...

25 Commits

Author SHA1 Message Date
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
69 changed files with 2271 additions and 747 deletions

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

View File

@@ -1,160 +1,42 @@
UPDATE etapi_tokens SET tokenHash = 'API token hash value'; 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 blobs SET content = 'text' WHERE content IS NOT NULL;
UPDATE revisions SET title = 'title'; UPDATE revisions SET title = 'title';
UPDATE attributes SET name = 'name', value = 'value' UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label'
WHERE type = 'label' AND name NOT IN
AND name NOT IN ('inbox', ('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss',
'disableVersioning', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass',
'calendarRoot', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider',
'archived', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled',
'excludeFromExport', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass',
'disableInclusion', 'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox',
'appCss', 'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId',
'appTheme', 'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top',
'hidePromotedAttributes', 'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription',
'readOnly', 'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate',
'autoReadOnlyDisabled', 'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop',
'cssClass', 'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation',
'iconClass', 'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation',
'keyboardShortcut', 'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template',
'run', 'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
'runOnInstance', UPDATE attributes SET name = 'name' WHERE type = 'relation'
'runAtHour', AND name NOT IN
'customRequestHandler', ('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss',
'customResourceProvider', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass',
'widget', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider',
'noteInfoWidgetDisabled', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled',
'linkMapWidgetDisabled', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass',
'revisionsWidgetDisabled', 'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox',
'whatLinksHereWidgetDisabled', 'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId',
'similarNotesWidgetDisabled', 'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top',
'workspace', 'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription',
'workspaceIconClass', 'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate',
'workspaceTabBackgroundColor', 'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop',
'searchHome', 'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation',
'workspaceInbox', 'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation',
'workspaceSearchHome', 'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template',
'sqlConsoleHome', 'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
'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 branches SET prefix = 'prefix' WHERE prefix IS NOT NULL AND prefix != 'recovered'; UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL AND prefix != 'recovered';
UPDATE options SET value = 'anonymized' WHERE name IN UPDATE options SET value = 'anonymized' WHERE name IN
('documentId', 'documentSecret', 'encryptedDataKey', ('documentId', 'documentSecret', 'encryptedDataKey',

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' version: '2.1'
services: services:
trilium: trilium:
@@ -8,7 +10,7 @@ services:
ports: ports:
- "8080:8080" - "8080:8080"
volumes: volumes:
- trilium:/home/node/trilium-data - ${TRILIUM_DATA_DIR:-~/trilium-data}:/home/node/trilium-data
volumes: volumes:
trilium: trilium:

View File

@@ -1388,7 +1388,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line133">line 133</a>
</li></ul></dd> </li></ul></dd>
@@ -1770,7 +1770,7 @@ larger amounts of data and generally not accessible to the user.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line118">line 118</a>
</li></ul></dd> </li></ul></dd>
@@ -2815,7 +2815,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line128">line 128</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -1588,7 +1588,7 @@ See addLabel, addRelation for more specific methods.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1308">line 1308</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1327">line 1327</a>
</li></ul></dd> </li></ul></dd>
@@ -1835,7 +1835,7 @@ See addLabel, addRelation for more specific methods.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1329">line 1329</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1348">line 1348</a>
</li></ul></dd> </li></ul></dd>
@@ -2081,7 +2081,7 @@ returned.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1342">line 1342</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1361">line 1361</a>
</li></ul></dd> </li></ul></dd>
@@ -2316,7 +2316,7 @@ returned.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1427">line 1427</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1446">line 1446</a>
</li></ul></dd> </li></ul></dd>
@@ -2432,7 +2432,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1479">line 1479</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1498">line 1498</a>
</li></ul></dd> </li></ul></dd>
@@ -2653,7 +2653,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1517">line 1517</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1536">line 1536</a>
</li></ul></dd> </li></ul></dd>
@@ -2919,7 +2919,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1149">line 1149</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1168">line 1168</a>
</li></ul></dd> </li></ul></dd>
@@ -3025,7 +3025,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1037">line 1037</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1044">line 1044</a>
</li></ul></dd> </li></ul></dd>
@@ -3127,7 +3127,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1011">line 1011</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1018">line 1018</a>
</li></ul></dd> </li></ul></dd>
@@ -3229,7 +3229,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1118">line 1118</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1125">line 1125</a>
</li></ul></dd> </li></ul></dd>
@@ -3286,7 +3286,7 @@ In the future, this functionality might get more generic and some of the require
<h4 class="name" id="getAttachmentByRole"><span class="type-signature"></span>getAttachmentByRole<span class="signature">()</span><span class="type-signature"> &rarr; {Array.&lt;<a href="BAttachment.html">BAttachment</a>>}</span></h4> <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>
@@ -3334,7 +3334,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1133">line 1133</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1152">line 1152</a>
</li></ul></dd> </li></ul></dd>
@@ -3370,7 +3370,7 @@ In the future, this functionality might get more generic and some of the require
</dt> </dt>
<dd> <dd>
<span class="param-type">Array.&lt;<a href="BAttachment.html">BAttachment</a>></span> <span class="param-type"><a href="BAttachment.html">BAttachment</a></span>
</dd> </dd>
@@ -3436,7 +3436,109 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1100">line 1100</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1107">line 1107</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_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1140">line 1140</a>
</li></ul></dd> </li></ul></dd>
@@ -3610,7 +3712,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line574">line 574</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line581">line 581</a>
</li></ul></dd> </li></ul></dd>
@@ -3789,7 +3891,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line585">line 585</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line592">line 592</a>
</li></ul></dd> </li></ul></dd>
@@ -3997,7 +4099,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line327">line 327</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line334">line 334</a>
</li></ul></dd> </li></ul></dd>
@@ -4176,7 +4278,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1202">line 1202</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1221">line 1221</a>
</li></ul></dd> </li></ul></dd>
@@ -4355,7 +4457,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1212">line 1212</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1231">line 1231</a>
</li></ul></dd> </li></ul></dd>
@@ -4826,108 +4928,6 @@ In the future, this functionality might get more generic and some of the require
<h4 class="name" id="getContentMetadata"><span class="type-signature"></span>getContentMetadata<span class="signature">()</span><span class="type-signature"> &rarr; {Object}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line215">line 215</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Object</span>
</dd>
</dl>
<h4 class="name" id="getDescendantNoteIds"><span class="type-signature"></span>getDescendantNoteIds<span class="signature">()</span><span class="type-signature"></span></h4> <h4 class="name" id="getDescendantNoteIds"><span class="type-signature"></span>getDescendantNoteIds<span class="signature">()</span><span class="type-signature"></span></h4>
@@ -4978,7 +4978,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line958">line 958</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line965">line 965</a>
</li></ul></dd> </li></ul></dd>
@@ -5068,7 +5068,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line759">line 759</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line766">line 766</a>
</li></ul></dd> </li></ul></dd>
@@ -5174,7 +5174,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1063">line 1063</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1070">line 1070</a>
</li></ul></dd> </li></ul></dd>
@@ -5281,7 +5281,121 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line220">line 220</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line217">line 217</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_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line228">line 228</a>
</li></ul></dd> </li></ul></dd>
@@ -5309,6 +5423,10 @@ In the future, this functionality might get more generic and some of the require
<h5>Returns:</h5> <h5>Returns:</h5>
<div class="param-desc">
valid object or null if the content cannot be parsed as JSON
</div>
<dl> <dl>
@@ -5318,6 +5436,9 @@ In the future, this functionality might get more generic and some of the require
<dd> <dd>
<span class="param-type">*</span> <span class="param-type">*</span>
|
<span class="param-type">null</span>
</dd> </dd>
@@ -5432,7 +5553,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line514">line 514</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line521">line 521</a>
</li></ul></dd> </li></ul></dd>
@@ -5590,7 +5711,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line538">line 538</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line545">line 545</a>
</li></ul></dd> </li></ul></dd>
@@ -5760,7 +5881,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line614">line 614</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line621">line 621</a>
</li></ul></dd> </li></ul></dd>
@@ -5927,7 +6048,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line606">line 606</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line613">line 613</a>
</li></ul></dd> </li></ul></dd>
@@ -6033,7 +6154,7 @@ In the future, this functionality might get more generic and some of the require
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line684">line 684</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line691">line 691</a>
</li></ul></dd> </li></ul></dd>
@@ -6213,7 +6334,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line596">line 596</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line603">line 603</a>
</li></ul></dd> </li></ul></dd>
@@ -6483,7 +6604,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line659">line 659</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line666">line 666</a>
</li></ul></dd> </li></ul></dd>
@@ -6638,7 +6759,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line520">line 520</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line527">line 527</a>
</li></ul></dd> </li></ul></dd>
@@ -6796,7 +6917,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line544">line 544</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line551">line 551</a>
</li></ul></dd> </li></ul></dd>
@@ -6966,7 +7087,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line630">line 630</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line637">line 637</a>
</li></ul></dd> </li></ul></dd>
@@ -7133,7 +7254,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line622">line 622</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line629">line 629</a>
</li></ul></dd> </li></ul></dd>
@@ -7288,7 +7409,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line532">line 532</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line539">line 539</a>
</li></ul></dd> </li></ul></dd>
@@ -7446,7 +7567,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line556">line 556</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line563">line 563</a>
</li></ul></dd> </li></ul></dd>
@@ -7616,7 +7737,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line646">line 646</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line653">line 653</a>
</li></ul></dd> </li></ul></dd>
@@ -8064,7 +8185,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line526">line 526</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line533">line 533</a>
</li></ul></dd> </li></ul></dd>
@@ -8222,7 +8343,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line550">line 550</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line557">line 557</a>
</li></ul></dd> </li></ul></dd>
@@ -8392,7 +8513,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line638">line 638</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line645">line 645</a>
</li></ul></dd> </li></ul></dd>
@@ -8498,7 +8619,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1094">line 1094</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1101">line 1101</a>
</li></ul></dd> </li></ul></dd>
@@ -8600,7 +8721,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line303">line 303</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line310">line 310</a>
</li></ul></dd> </li></ul></dd>
@@ -8709,7 +8830,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line869">line 869</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line876">line 876</a>
</li></ul></dd> </li></ul></dd>
@@ -8880,7 +9001,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1171">line 1171</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1190">line 1190</a>
</li></ul></dd> </li></ul></dd>
@@ -9088,7 +9209,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line892">line 892</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line899">line 899</a>
</li></ul></dd> </li></ul></dd>
@@ -9190,7 +9311,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line951">line 951</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line958">line 958</a>
</li></ul></dd> </li></ul></dd>
@@ -9296,7 +9417,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line837">line 837</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line844">line 844</a>
</li></ul></dd> </li></ul></dd>
@@ -9398,7 +9519,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1057">line 1057</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1064">line 1064</a>
</li></ul></dd> </li></ul></dd>
@@ -9589,7 +9710,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1042">line 1042</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1049">line 1049</a>
</li></ul></dd> </li></ul></dd>
@@ -9815,7 +9936,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line444">line 444</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line451">line 451</a>
</li></ul></dd> </li></ul></dd>
@@ -10111,7 +10232,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line473">line 473</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line480">line 480</a>
</li></ul></dd> </li></ul></dd>
@@ -10340,7 +10461,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line564">line 564</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line571">line 571</a>
</li></ul></dd> </li></ul></dd>
@@ -10538,7 +10659,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line494">line 494</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line501">line 501</a>
</li></ul></dd> </li></ul></dd>
@@ -10736,7 +10857,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line508">line 508</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line515">line 515</a>
</li></ul></dd> </li></ul></dd>
@@ -10934,7 +11055,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line501">line 501</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line508">line 508</a>
</li></ul></dd> </li></ul></dd>
@@ -11040,7 +11161,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line298">line 298</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line305">line 305</a>
</li></ul></dd> </li></ul></dd>
@@ -11190,7 +11311,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1243">line 1243</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1262">line 1262</a>
</li></ul></dd> </li></ul></dd>
@@ -11296,7 +11417,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1221">line 1221</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1240">line 1240</a>
</li></ul></dd> </li></ul></dd>
@@ -11390,7 +11511,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line281">line 281</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line288">line 288</a>
</li></ul></dd> </li></ul></dd>
@@ -11496,7 +11617,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line287">line 287</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line294">line 294</a>
</li></ul></dd> </li></ul></dd>
@@ -11602,7 +11723,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line273">line 273</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line280">line 280</a>
</li></ul></dd> </li></ul></dd>
@@ -11708,7 +11829,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line268">line 268</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line275">line 275</a>
</li></ul></dd> </li></ul></dd>
@@ -11863,7 +11984,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line479">line 479</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line486">line 486</a>
</li></ul></dd> </li></ul></dd>
@@ -11969,7 +12090,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line263">line 263</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line270">line 270</a>
</li></ul></dd> </li></ul></dd>
@@ -12077,7 +12198,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line293">line 293</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line300">line 300</a>
</li></ul></dd> </li></ul></dd>
@@ -12536,7 +12657,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1287">line 1287</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1306">line 1306</a>
</li></ul></dd> </li></ul></dd>
@@ -12716,7 +12837,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1403">line 1403</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1422">line 1422</a>
</li></ul></dd> </li></ul></dd>
@@ -12896,7 +13017,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1411">line 1411</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1430">line 1430</a>
</li></ul></dd> </li></ul></dd>
@@ -13091,7 +13212,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1624">line 1624</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1638">line 1638</a>
</li></ul></dd> </li></ul></dd>
@@ -13193,7 +13314,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1571">line 1571</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1590">line 1590</a>
</li></ul></dd> </li></ul></dd>
@@ -13425,7 +13546,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1256">line 1256</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1275">line 1275</a>
</li></ul></dd> </li></ul></dd>
@@ -13704,7 +13825,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line236">line 236</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line243">line 243</a>
</li></ul></dd> </li></ul></dd>
@@ -13884,7 +14005,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1387">line 1387</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1406">line 1406</a>
</li></ul></dd> </li></ul></dd>
@@ -14044,7 +14165,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1395">line 1395</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1414">line 1414</a>
</li></ul></dd> </li></ul></dd>
@@ -14286,7 +14407,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1354">line 1354</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1373">line 1373</a>
</li></ul></dd> </li></ul></dd>
@@ -14497,7 +14618,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1370">line 1370</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1389">line 1389</a>
</li></ul></dd> </li></ul></dd>
@@ -14708,7 +14829,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1379">line 1379</a> <a href="becca_entities_bnote.js.html">becca/entities/bnote.js</a>, <a href="becca_entities_bnote.js.html#line1398">line 1398</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -126,7 +126,12 @@ class BAttachment extends AbstractBeccaEntity {
} }
decrypt() { 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 { try {
this.title = protectedSessionService.decryptString(this.title); this.title = protectedSessionService.decryptString(this.title);
this.isDecrypted = true; this.isDecrypted = true;

View File

@@ -239,12 +239,9 @@ class BNote extends AbstractBeccaEntity {
return this._getContent(); return this._getContent();
} }
/** @returns {{dateModified, utcDateModified}} */ /**
getContentMetadata() { * @returns {*}
return sql.getRow(`SELECT dateModified, utcDateModified FROM blobs WHERE blobId = ?`, [this.blobId]); * @throws Error in case of invalid JSON */
}
/** @returns {*} */
getJsonContent() { getJsonContent() {
const content = this.getContent(); const content = this.getContent();
@@ -255,6 +252,16 @@ class BNote extends AbstractBeccaEntity {
return JSON.parse(content); 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 content
* @param {object} [opts] * @param {object} [opts]
@@ -1158,7 +1165,7 @@ class BNote extends AbstractBeccaEntity {
} }
/** @returns {BAttachment[]} */ /** @returns {BAttachment[]} */
getAttachmentByRole(role) { getAttachmentsByRole(role) {
return sql.getRows(` return sql.getRows(`
SELECT attachments.* SELECT attachments.*
FROM attachments FROM attachments
@@ -1169,6 +1176,18 @@ class BNote extends AbstractBeccaEntity {
.map(row => new BAttachment(row)); .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) * Gives all possible note paths leading to this note. Paths containing search note are ignored (could form cycles)
* *
@@ -1599,7 +1618,6 @@ class BNote extends AbstractBeccaEntity {
saveRevision() { saveRevision() {
return sql.transactional(() => { return sql.transactional(() => {
let noteContent = this.getContent(); let noteContent = this.getContent();
const contentMetadata = this.getContentMetadata();
const revision = new BRevision({ const revision = new BRevision({
noteId: this.noteId, noteId: this.noteId,
@@ -1608,14 +1626,10 @@ class BNote extends AbstractBeccaEntity {
type: this.type, type: this.type,
mime: this.mime, mime: this.mime,
isProtected: this.isProtected, isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified utcDateLastEdited: this.utcDateModified,
? this.utcDateModified
: contentMetadata.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(), utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(), utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: this.dateModified > contentMetadata.dateModified dateLastEdited: this.dateModified,
? this.dateModified
: contentMetadata.dateModified,
dateCreated: dateUtils.localNowDateTime() dateCreated: dateUtils.localNowDateTime()
}, true); }, true);
@@ -1638,10 +1652,10 @@ class BNote extends AbstractBeccaEntity {
noteContent = noteContent.replaceAll(new RegExp(`href="[^"]*attachmentId=${noteAttachment.attachmentId}[^"]*"`, 'gi'), noteContent = noteContent.replaceAll(new RegExp(`href="[^"]*attachmentId=${noteAttachment.attachmentId}[^"]*"`, 'gi'),
`href="api/attachments/${revisionAttachment.attachmentId}/download"`); `href="api/attachments/${revisionAttachment.attachmentId}/download"`);
} }
revision.setContent(noteContent, {forceSave: true});
} }
revision.setContent(noteContent);
return revision; return revision;
}); });
} }

View File

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

View File

@@ -912,7 +912,7 @@ and relation (representing named relationship between source and target note)</d
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

View File

@@ -1124,7 +1124,7 @@ parents.</div>
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

View File

@@ -1168,7 +1168,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -1274,7 +1274,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </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> <h5>Returns:</h5>
@@ -1550,7 +1652,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -1728,7 +1830,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -1928,7 +2030,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -2107,7 +2209,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -2286,7 +2388,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -2392,7 +2494,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -3057,7 +3159,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -3212,7 +3314,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -3379,7 +3481,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -3487,7 +3589,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -3589,7 +3691,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -3763,7 +3865,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -3941,7 +4043,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -4141,7 +4243,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -4296,7 +4398,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -4451,7 +4553,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -4618,7 +4720,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -4773,7 +4875,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -4928,7 +5030,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -5095,7 +5197,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -5658,7 +5760,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -5813,7 +5915,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -5983,7 +6085,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -6134,7 +6236,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -6301,7 +6403,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -6407,7 +6509,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -6585,7 +6687,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -6691,7 +6793,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -6797,7 +6899,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -6971,7 +7073,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -7228,7 +7330,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -7406,7 +7508,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -7561,7 +7663,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -7716,7 +7818,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -7871,7 +7973,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -7979,7 +8081,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -8063,7 +8165,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -8157,7 +8259,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -8263,7 +8365,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -8520,7 +8622,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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> </li></ul></dd>
@@ -8588,7 +8690,7 @@
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

File diff suppressed because it is too large Load Diff

View File

@@ -80,7 +80,7 @@ export default FAttachment;
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

View File

@@ -116,7 +116,7 @@ export default FAttribute;
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

View File

@@ -43,6 +43,27 @@
/** @type {string} */ /** @type {string} */
this.utcDateModified = row.utcDateModified; 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> </code></pre>
</article> </article>
@@ -54,7 +75,7 @@
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

View File

@@ -100,7 +100,7 @@ export default FBranch;
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

View File

@@ -264,6 +264,12 @@ class FNote {
return this.attachments; return this.attachments;
} }
/** @returns {Promise&lt;FAttachment[]>} */
async getAttachmentsByRole(role) {
return (await this.getAttachments())
.filter(attachment => attachment.role === role);
}
/** @returns {Promise&lt;FAttachment>} */ /** @returns {Promise&lt;FAttachment>} */
async getAttachmentById(attachmentId) { async getAttachmentById(attachmentId) {
const attachments = await this.getAttachments(); const attachments = await this.getAttachments();
@@ -998,6 +1004,10 @@ class FNote {
isOptions() { isOptions() {
return this.noteId.startsWith("_options"); return this.noteId.startsWith("_options");
} }
async getMetadata() {
return await server.get(`notes/${this.noteId}/metadata`);
}
} }
export default FNote; export default FNote;
@@ -1011,7 +1021,7 @@ export default FNote;
</div> </div>
<nav> <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> </nav>
<br class="clear"> <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> </div>
<nav> <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> </nav>
<br class="clear"> <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 BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js"; import SpacedUpdate from "./spaced_update.js";
import shortcutService from "./shortcuts.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 * &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; this.parseDate = utils.parseDate;
/** /**
* Show an info message to the user. * Show an info toast message to the user.
* *
* @method * @method
* @param {string} message * @param {string} message
@@ -294,13 +295,43 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.showMessage = toastService.showMessage; this.showMessage = toastService.showMessage;
/** /**
* Show an error message to the user. * Show an error toast message to the user.
* *
* @method * @method
* @param {string} message * @param {string} message
*/ */
this.showError = toastService.showError; 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. * Trigger command. This is a very low-level API which should be avoided if possible.
* *
@@ -570,7 +601,7 @@ export default FrontendScriptApi;
</div> </div>
<nav> <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> </nav>
<br class="clear"> <br class="clear">

View File

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

View File

@@ -24,8 +24,10 @@
function position(e) { function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position); if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px"; var top = Math.max(0, e.clientY - tt.offsetHeight - 5);
tt.style.left = (e.clientX + 5) + "px"; 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); CodeMirror.on(document, "mousemove", position);
position(e); position(e);
@@ -199,10 +201,6 @@
var anns = annotations[line]; var anns = annotations[line];
if (!anns) continue; 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 maxSeverity = null;
var tipLabel = state.hasGutter && document.createDocumentFragment(); var tipLabel = state.hasGutter && document.createDocumentFragment();
@@ -220,9 +218,8 @@
__annotation: ann __annotation: ann
})); }));
} }
// use original annotations[line] to show multiple messages
if (state.hasGutter) 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)); options.tooltips));
if (options.highlightLines) 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) { function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) {
field.setAttribute("autocorrect", autocorrect ? "" : "off"); field.setAttribute("autocorrect", autocorrect ? "on" : "off");
field.setAttribute("autocapitalize", autocapitalize ? "" : "off"); field.setAttribute("autocapitalize", autocapitalize ? "on" : "off");
field.setAttribute("spellcheck", !!spellcheck); field.setAttribute("spellcheck", !!spellcheck);
} }
@@ -8275,7 +8275,6 @@
else { te.setAttribute("wrap", "off"); } else { te.setAttribute("wrap", "off"); }
// If border: 0; -- iOS fails to open keyboard (issue #1287) // If border: 0; -- iOS fails to open keyboard (issue #1287)
if (ios) { te.style.border = "1px solid black"; } if (ios) { te.style.border = "1px solid black"; }
disableBrowserMagic(te);
return div return div
} }
@@ -8897,6 +8896,7 @@
} }
// Old-fashioned briefly-focus-a-textarea hack // Old-fashioned briefly-focus-a-textarea hack
var kludge = hiddenTextarea(), te = kludge.firstChild; var kludge = hiddenTextarea(), te = kludge.firstChild;
disableBrowserMagic(te);
cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
te.value = lastCopied.text.join("\n"); te.value = lastCopied.text.join("\n");
var hadFocus = activeElt(div.ownerDocument); var hadFocus = activeElt(div.ownerDocument);
@@ -9461,6 +9461,8 @@
// The semihidden textarea that is focused when the editor is // The semihidden textarea that is focused when the editor is
// focused, and receives input. // focused, and receives input.
this.textarea = this.wrapper.firstChild; this.textarea = this.wrapper.firstChild;
var opts = this.cm.options;
disableBrowserMagic(this.textarea, opts.spellcheck, opts.autocorrect, opts.autocapitalize);
}; };
TextareaInput.prototype.screenReaderLabelChanged = function (label) { TextareaInput.prototype.screenReaderLabelChanged = function (label) {
@@ -9865,7 +9867,7 @@
addLegacyProps(CodeMirror); addLegacyProps(CodeMirror);
CodeMirror.version = "5.65.9"; CodeMirror.version = "5.65.15";
return CodeMirror; return CodeMirror;

View File

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

View File

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

View File

@@ -24,7 +24,7 @@ CodeMirror.defineSimpleMode("nsis",{
{ regex: /`(?:[^\\`]|\\.)*`?/, token: "string" }, { regex: /`(?:[^\\`]|\\.)*`?/, token: "string" },
// Compile Time Commands // 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 // Conditional Compilation
{regex: /^\s*(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/i, token: "keyword", indent: true}, {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) { token: function (stream, state) {
if (stream)
//check for state changes //check for state changes
if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) { if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) {
state.stringType = stream.peek(); state.stringType = stream.peek();
@@ -43,7 +41,6 @@ CodeMirror.defineMode("pegjs", function (config) {
state.inComment = true; state.inComment = true;
} }
//return state
if (state.inString) { if (state.inString) {
while (state.inString && !stream.eol()) { while (state.inString && !stream.eol()) {
if (stream.peek() === state.stringType) { if (stream.peek() === state.stringType) {

View File

@@ -20,7 +20,7 @@
"def", "del", "elif", "else", "except", "finally", "def", "del", "elif", "else", "except", "finally",
"for", "from", "global", "if", "import", "for", "from", "global", "if", "import",
"lambda", "pass", "raise", "return", "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", var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
"classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod", "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
"enumerate", "eval", "filter", "float", "format", "frozenset", "enumerate", "eval", "filter", "float", "format", "frozenset",
@@ -60,7 +60,7 @@
if (py3) { if (py3) {
// since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator // 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]*/; 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"]); myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
var stringPrefixes = new RegExp("^(([rbuf]|(br)|(rb)|(fr)|(rf))?('{3}|\"{3}|['\"]))", "i"); var stringPrefixes = new RegExp("^(([rbuf]|(br)|(rb)|(fr)|(rf))?('{3}|\"{3}|['\"]))", "i");
} else { } else {
@@ -68,7 +68,7 @@
myKeywords = myKeywords.concat(["exec", "print"]); myKeywords = myKeywords.concat(["exec", "print"]);
myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile", myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
"file", "intern", "long", "raw_input", "reduce", "reload", "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 stringPrefixes = new RegExp("^(([rubf]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
} }
var keywords = wordRegexp(myKeywords); var keywords = wordRegexp(myKeywords);

View File

@@ -33,6 +33,9 @@ CodeMirror.defineMode("sparql", function(config) {
"true", "false", "with", "true", "false", "with",
"data", "copy", "to", "move", "add", "create", "drop", "clear", "load", "into"]); "data", "copy", "to", "move", "add", "create", "drop", "clear", "load", "into"]);
var operatorChars = /[*+\-<>=&|\^\/!\?]/; 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) { function tokenBase(stream, state) {
var ch = stream.next(); var ch = stream.next();
@@ -71,12 +74,11 @@ CodeMirror.defineMode("sparql", function(config) {
stream.eatWhile(/[a-z\d\-]/i); stream.eatWhile(/[a-z\d\-]/i);
return "meta"; return "meta";
} }
else { else if (PREFIX_START.test(ch) && stream.match(PREFIX_REMAINDER)) {
stream.eatWhile(/[_\w\d]/);
if (stream.eat(":")) {
eatPnLocal(stream); eatPnLocal(stream);
return "atom"; return "atom";
} }
stream.eatWhile(/[_\w\d]/);
var word = stream.current(); var word = stream.current();
if (ops.test(word)) if (ops.test(word))
return "builtin"; return "builtin";
@@ -85,7 +87,6 @@ CodeMirror.defineMode("sparql", function(config) {
else else
return "variable"; return "variable";
} }
}
function eatPnLocal(stream) { function eatPnLocal(stream) {
stream.match(/(\.(?=[\w_\-\\%])|[:\w_-]|\\[-\\_~.!$&'()*+,;=/?#@%]|%[a-f\d][a-f\d])+/i); stream.match(/(\.(?=[\w_\-\\%])|[:\w_-]|\\[-\\_~.!$&'()*+,;=/?#@%]|%[a-f\d][a-f\d])+/i);

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 */ /* 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.pair = true;
state.keyCol = stream.indentation(); state.keyCol = stream.indentation();
return "atom"; return "atom";

192
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "trilium", "name": "trilium",
"version": "0.61.6-beta", "version": "0.61.8-beta",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "trilium", "name": "trilium",
"version": "0.61.6-beta", "version": "0.61.8-beta",
"hasInstallScript": true, "hasInstallScript": true,
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"dependencies": { "dependencies": {
@@ -15,7 +15,7 @@
"@excalidraw/excalidraw": "0.16.1", "@excalidraw/excalidraw": "0.16.1",
"archiver": "5.3.1", "archiver": "5.3.1",
"async-mutex": "0.4.0", "async-mutex": "0.4.0",
"axios": "1.5.0", "axios": "1.5.1",
"better-sqlite3": "8.4.0", "better-sqlite3": "8.4.0",
"chokidar": "3.5.3", "chokidar": "3.5.3",
"cls-hooked": "4.2.2", "cls-hooked": "4.2.2",
@@ -47,7 +47,7 @@
"jimp": "0.22.10", "jimp": "0.22.10",
"joplin-turndown-plugin-gfm": "1.0.12", "joplin-turndown-plugin-gfm": "1.0.12",
"jsdom": "22.1.0", "jsdom": "22.1.0",
"marked": "9.0.3", "marked": "9.1.0",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
"node-abi": "3.47.0", "node-abi": "3.47.0",
@@ -57,11 +57,11 @@
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"request": "2.88.2", "request": "2.88.2",
"rimraf": "5.0.1", "rimraf": "5.0.5",
"safe-compare": "1.1.4", "safe-compare": "1.1.4",
"sanitize-filename": "1.6.3", "sanitize-filename": "1.6.3",
"sanitize-html": "2.11.0", "sanitize-html": "2.11.0",
"sax": "1.2.4", "sax": "1.3.0",
"semver": "7.5.4", "semver": "7.5.4",
"serve-favicon": "2.5.0", "serve-favicon": "2.5.0",
"session-file-store": "1.5.0", "session-file-store": "1.5.0",
@@ -79,11 +79,11 @@
}, },
"devDependencies": { "devDependencies": {
"cross-env": "7.0.3", "cross-env": "7.0.3",
"electron": "25.8.1", "electron": "25.9.0",
"electron-builder": "24.6.4", "electron-builder": "24.6.4",
"electron-packager": "17.1.2", "electron-packager": "17.1.2",
"electron-rebuild": "3.2.9", "electron-rebuild": "3.2.9",
"eslint": "8.49.0", "eslint": "8.50.0",
"eslint-config-airbnb-base": "15.0.0", "eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.0.0", "eslint-config-prettier": "9.0.0",
"eslint-plugin-import": "2.28.1", "eslint-plugin-import": "2.28.1",
@@ -447,9 +447,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "8.49.0", "version": "8.50.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz",
"integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2417,9 +2417,9 @@
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.5.0", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz",
"integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
@@ -4276,9 +4276,9 @@
} }
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "25.8.1", "version": "25.9.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-25.8.1.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-25.9.0.tgz",
"integrity": "sha512-GtcP1nMrROZfFg0+mhyj1hamrHvukfF6of2B/pcWxmWkd5FVY1NJib0tlhiorFZRzQN5Z+APLPr7aMolt7i2AQ==", "integrity": "sha512-wgscxf2ORHL/8mAQfy7l9rVDG//wrG9RUQndG508kCCMHRq9deFyZ4psOMzySheBRSfGMcFoRFYSlkAeZr8cFg==",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@electron/get": "^2.0.0", "@electron/get": "^2.0.0",
@@ -5001,15 +5001,15 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.49.0", "version": "8.50.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz",
"integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2", "@eslint/eslintrc": "^2.1.2",
"@eslint/js": "8.49.0", "@eslint/js": "8.50.0",
"@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/config-array": "^0.11.11",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
@@ -7697,9 +7697,9 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
}, },
"node_modules/jackspeak": { "node_modules/jackspeak": {
"version": "2.2.1", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
"dependencies": { "dependencies": {
"@isaacs/cliui": "^8.0.2" "@isaacs/cliui": "^8.0.2"
}, },
@@ -8946,9 +8946,9 @@
} }
}, },
"node_modules/marked": { "node_modules/marked": {
"version": "9.0.3", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz",
"integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==", "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==",
"bin": { "bin": {
"marked": "bin/marked.js" "marked": "bin/marked.js"
}, },
@@ -10106,12 +10106,12 @@
"dev": true "dev": true
}, },
"node_modules/path-scurry": { "node_modules/path-scurry": {
"version": "1.9.2", "version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
"dependencies": { "dependencies": {
"lru-cache": "^9.1.1", "lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2" "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
}, },
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
@@ -10947,14 +10947,14 @@
"dev": true "dev": true
}, },
"node_modules/rimraf": { "node_modules/rimraf": {
"version": "5.0.1", "version": "5.0.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
"integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
"dependencies": { "dependencies": {
"glob": "^10.2.5" "glob": "^10.3.7"
}, },
"bin": { "bin": {
"rimraf": "dist/cjs/src/bin.js" "rimraf": "dist/esm/bin.mjs"
}, },
"engines": { "engines": {
"node": ">=14" "node": ">=14"
@@ -10972,18 +10972,18 @@
} }
}, },
"node_modules/rimraf/node_modules/glob": { "node_modules/rimraf/node_modules/glob": {
"version": "10.2.6", "version": "10.3.10",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
"integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
"jackspeak": "^2.0.3", "jackspeak": "^2.3.5",
"minimatch": "^9.0.1", "minimatch": "^9.0.1",
"minipass": "^5.0.0 || ^6.0.2", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"path-scurry": "^1.7.0" "path-scurry": "^1.10.1"
}, },
"bin": { "bin": {
"glob": "dist/cjs/src/bin.js" "glob": "dist/esm/bin.mjs"
}, },
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
@@ -10993,9 +10993,9 @@
} }
}, },
"node_modules/rimraf/node_modules/minimatch": { "node_modules/rimraf/node_modules/minimatch": {
"version": "9.0.1", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
}, },
@@ -11007,9 +11007,9 @@
} }
}, },
"node_modules/rimraf/node_modules/minipass": { "node_modules/rimraf/node_modules/minipass": {
"version": "6.0.2", "version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
@@ -11290,9 +11290,9 @@
} }
}, },
"node_modules/sax": { "node_modules/sax": {
"version": "1.2.4", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA=="
}, },
"node_modules/saxes": { "node_modules/saxes": {
"version": "6.0.0", "version": "6.0.0",
@@ -13572,9 +13572,9 @@
} }
}, },
"@eslint/js": { "@eslint/js": {
"version": "8.49.0", "version": "8.50.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz",
"integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==",
"dev": true "dev": true
}, },
"@excalidraw/excalidraw": { "@excalidraw/excalidraw": {
@@ -15125,9 +15125,9 @@
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
}, },
"axios": { "axios": {
"version": "1.5.0", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz",
"integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==",
"requires": { "requires": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
@@ -16542,9 +16542,9 @@
} }
}, },
"electron": { "electron": {
"version": "25.8.1", "version": "25.9.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-25.8.1.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-25.9.0.tgz",
"integrity": "sha512-GtcP1nMrROZfFg0+mhyj1hamrHvukfF6of2B/pcWxmWkd5FVY1NJib0tlhiorFZRzQN5Z+APLPr7aMolt7i2AQ==", "integrity": "sha512-wgscxf2ORHL/8mAQfy7l9rVDG//wrG9RUQndG508kCCMHRq9deFyZ4psOMzySheBRSfGMcFoRFYSlkAeZr8cFg==",
"requires": { "requires": {
"@electron/get": "^2.0.0", "@electron/get": "^2.0.0",
"@types/node": "^18.11.18", "@types/node": "^18.11.18",
@@ -17103,15 +17103,15 @@
"dev": true "dev": true
}, },
"eslint": { "eslint": {
"version": "8.49.0", "version": "8.50.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz",
"integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2", "@eslint/eslintrc": "^2.1.2",
"@eslint/js": "8.49.0", "@eslint/js": "8.50.0",
"@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/config-array": "^0.11.11",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
@@ -19062,9 +19062,9 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
}, },
"jackspeak": { "jackspeak": {
"version": "2.2.1", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
"requires": { "requires": {
"@isaacs/cliui": "^8.0.2", "@isaacs/cliui": "^8.0.2",
"@pkgjs/parseargs": "^0.11.0" "@pkgjs/parseargs": "^0.11.0"
@@ -19990,9 +19990,9 @@
"requires": {} "requires": {}
}, },
"marked": { "marked": {
"version": "9.0.3", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz",
"integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==" "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA=="
}, },
"matcher": { "matcher": {
"version": "3.0.0", "version": "3.0.0",
@@ -20873,12 +20873,12 @@
"dev": true "dev": true
}, },
"path-scurry": { "path-scurry": {
"version": "1.9.2", "version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
"requires": { "requires": {
"lru-cache": "^9.1.1", "lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2" "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
}, },
"dependencies": { "dependencies": {
"lru-cache": { "lru-cache": {
@@ -21498,11 +21498,11 @@
"dev": true "dev": true
}, },
"rimraf": { "rimraf": {
"version": "5.0.1", "version": "5.0.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
"integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
"requires": { "requires": {
"glob": "^10.2.5" "glob": "^10.3.7"
}, },
"dependencies": { "dependencies": {
"brace-expansion": { "brace-expansion": {
@@ -21514,29 +21514,29 @@
} }
}, },
"glob": { "glob": {
"version": "10.2.6", "version": "10.3.10",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
"integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"requires": { "requires": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
"jackspeak": "^2.0.3", "jackspeak": "^2.3.5",
"minimatch": "^9.0.1", "minimatch": "^9.0.1",
"minipass": "^5.0.0 || ^6.0.2", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"path-scurry": "^1.7.0" "path-scurry": "^1.10.1"
} }
}, },
"minimatch": { "minimatch": {
"version": "9.0.1", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"requires": { "requires": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
} }
}, },
"minipass": { "minipass": {
"version": "6.0.2", "version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==" "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ=="
} }
} }
}, },
@@ -21736,9 +21736,9 @@
} }
}, },
"sax": { "sax": {
"version": "1.2.4", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA=="
}, },
"saxes": { "saxes": {
"version": "6.0.0", "version": "6.0.0",

View File

@@ -2,7 +2,7 @@
"name": "trilium", "name": "trilium",
"productName": "Trilium Notes", "productName": "Trilium Notes",
"description": "Trilium Notes", "description": "Trilium Notes",
"version": "0.61.7-beta", "version": "0.61.9-beta",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"main": "electron.js", "main": "electron.js",
"bin": { "bin": {
@@ -36,7 +36,7 @@
"@excalidraw/excalidraw": "0.16.1", "@excalidraw/excalidraw": "0.16.1",
"archiver": "5.3.1", "archiver": "5.3.1",
"async-mutex": "0.4.0", "async-mutex": "0.4.0",
"axios": "1.5.0", "axios": "1.5.1",
"better-sqlite3": "8.4.0", "better-sqlite3": "8.4.0",
"chokidar": "3.5.3", "chokidar": "3.5.3",
"cls-hooked": "4.2.2", "cls-hooked": "4.2.2",
@@ -68,7 +68,7 @@
"jimp": "0.22.10", "jimp": "0.22.10",
"joplin-turndown-plugin-gfm": "1.0.12", "joplin-turndown-plugin-gfm": "1.0.12",
"jsdom": "22.1.0", "jsdom": "22.1.0",
"marked": "9.0.3", "marked": "9.1.0",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
"node-abi": "3.47.0", "node-abi": "3.47.0",
@@ -78,11 +78,11 @@
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"request": "2.88.2", "request": "2.88.2",
"rimraf": "5.0.1", "rimraf": "5.0.5",
"safe-compare": "1.1.4", "safe-compare": "1.1.4",
"sanitize-filename": "1.6.3", "sanitize-filename": "1.6.3",
"sanitize-html": "2.11.0", "sanitize-html": "2.11.0",
"sax": "1.2.4", "sax": "1.3.0",
"semver": "7.5.4", "semver": "7.5.4",
"serve-favicon": "2.5.0", "serve-favicon": "2.5.0",
"session-file-store": "1.5.0", "session-file-store": "1.5.0",
@@ -97,11 +97,11 @@
}, },
"devDependencies": { "devDependencies": {
"cross-env": "7.0.3", "cross-env": "7.0.3",
"electron": "25.8.1", "electron": "25.9.0",
"electron-builder": "24.6.4", "electron-builder": "24.6.4",
"electron-packager": "17.1.2", "electron-packager": "17.1.2",
"electron-rebuild": "3.2.9", "electron-rebuild": "3.2.9",
"eslint": "8.49.0", "eslint": "8.50.0",
"eslint-config-airbnb-base": "15.0.0", "eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.0.0", "eslint-config-prettier": "9.0.0",
"eslint-plugin-import": "2.28.1", "eslint-plugin-import": "2.28.1",

View File

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

View File

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

View File

@@ -18,31 +18,11 @@ let becca = null;
class AbstractBeccaEntity { class AbstractBeccaEntity {
/** @protected */ /** @protected */
beforeSaving() { beforeSaving() {
this.generateIdIfNecessary();
}
/** @protected */
generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) { if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId(); 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 */ /** @protected */
getUtcDateChanged() { getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated; return this.utcDateModified || this.utcDateCreated;
@@ -61,7 +41,7 @@ class AbstractBeccaEntity {
} }
/** @protected */ /** @protected */
putEntityChange(isDeleted = false) { putEntityChange(isDeleted) {
entityChangesService.putEntityChange({ entityChangesService.putEntityChange({
entityName: this.constructor.entityName, entityName: this.constructor.entityName,
entityId: this[this.constructor.primaryKeyName], 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 */ /** @protected */
getPojoToSave() { getPojoToSave() {
return this.getPojo(); 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 * Saves entity - executes SQL, but doesn't commit the transaction on its own
* *
@@ -88,9 +94,7 @@ class AbstractBeccaEntity {
const isNewEntity = !this[primaryKeyName]; const isNewEntity = !this[primaryKeyName];
if (this.beforeSaving) {
this.beforeSaving(opts); this.beforeSaving(opts);
}
const pojo = this.getPojoToSave(); const pojo = this.getPojoToSave();
@@ -101,7 +105,7 @@ class AbstractBeccaEntity {
return; return;
} }
this.putEntityChange(false); this.putEntityChange(!!this.isDeleted);
if (!cls.isEntityEventsDisabled()) { if (!cls.isEntityEventsDisabled()) {
const eventPayload = { const eventPayload = {

View File

@@ -20,8 +20,7 @@ const attachmentRoleToNoteTypeMapping = {
class BAttachment extends AbstractBeccaEntity { class BAttachment extends AbstractBeccaEntity {
static get entityName() { return "attachments"; } static get entityName() { return "attachments"; }
static get primaryKeyName() { return "attachmentId"; } static get primaryKeyName() { return "attachmentId"; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId", static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId", "utcDateScheduledForErasureSince"]; }
"utcDateScheduledForErasureSince", "utcDateModified"]; }
constructor(row) { constructor(row) {
super(); super();

View File

@@ -132,11 +132,17 @@ class BNote extends AbstractBeccaEntity {
*/ */
this.contentSize = null; 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} * @type {int|null}
* @private * @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 * number of note revisions for this note
* @type {int|null} * @type {int|null}
@@ -1607,16 +1613,12 @@ class BNote extends AbstractBeccaEntity {
revision.save(); // to generate revisionId, which is then used to save attachments revision.save(); // to generate revisionId, which is then used to save attachments
if (this.type === 'text') {
for (const noteAttachment of this.getAttachments()) { for (const noteAttachment of this.getAttachments()) {
if (noteAttachment.utcDateScheduledForErasureSince) {
continue;
}
const revisionAttachment = noteAttachment.copy(); const revisionAttachment = noteAttachment.copy();
revisionAttachment.ownerId = revision.revisionId; revisionAttachment.ownerId = revision.revisionId;
revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true}); revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true});
if (this.type === 'text') {
// content is rewritten to point to the revision attachments // content is rewritten to point to the revision attachments
noteContent = noteContent.replaceAll(`attachments/${noteAttachment.attachmentId}`, noteContent = noteContent.replaceAll(`attachments/${noteAttachment.attachmentId}`,
`attachments/${revisionAttachment.attachmentId}`); `attachments/${revisionAttachment.attachmentId}`);

View File

@@ -86,6 +86,29 @@ class BRevision extends AbstractBeccaEntity {
return this._getContent(); 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 content
* @param {object} [opts] * @param {object} [opts]
@@ -105,6 +128,45 @@ class BRevision extends AbstractBeccaEntity {
.map(row => new BAttachment(row)); .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() { beforeSaving() {
super.beforeSaving(); super.beforeSaving();

View File

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

View File

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

View File

@@ -14,6 +14,7 @@ import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import BasicWidget from "../widgets/basic_widget.js"; import BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js"; import SpacedUpdate from "./spaced_update.js";
import shortcutService from "./shortcuts.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 * <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; this.parseDate = utils.parseDate;
/** /**
* Show an info message to the user. * Show an info toast message to the user.
* *
* @method * @method
* @param {string} message * @param {string} message
@@ -266,13 +267,43 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.showMessage = toastService.showMessage; this.showMessage = toastService.showMessage;
/** /**
* Show an error message to the user. * Show an error toast message to the user.
* *
* @method * @method
* @param {string} message * @param {string} message
*/ */
this.showError = toastService.showError; 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. * 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/lint.js",
"libraries/codemirror/addon/lint/eslint.js", "libraries/codemirror/addon/lint/eslint.js",
"libraries/codemirror/addon/mode/loadmode.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/mode/simple.js",
"libraries/codemirror/addon/search/match-highlighter.js", "libraries/codemirror/addon/search/match-highlighter.js",
"libraries/codemirror/mode/meta.js", "libraries/codemirror/mode/meta.js",

View File

@@ -252,11 +252,15 @@ class NoteListRenderer {
if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(this.page - i) <= 2) { if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(this.page - i) <= 2) {
lastPrinted = true; lastPrinted = true;
const startIndex = (i - 1) * this.pageSize + 1;
const endIndex = Math.min(this.noteIds.length, i * this.pageSize);
$pager.append( $pager.append(
i === this.page i === this.page
? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold") ? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold")
: $('<a href="javascript:">') : $('<a href="javascript:">')
.text(i) .text(i)
.attr("title", `Page of ${startIndex} - ${endIndex}`)
.on('click', () => { .on('click', () => {
this.page = i; this.page = i;
this.renderList(); this.renderList();
@@ -270,6 +274,9 @@ class NoteListRenderer {
lastPrinted = false; 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) { async renderNote(note, expand = false) {

View File

@@ -45,6 +45,7 @@ const TPL = `
<a class="dropdown-item export-note-button">Export note</a> <a class="dropdown-item export-note-button">Export note</a>
<a class="dropdown-item delete-note-button">Delete 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="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>
</div>`; </div>`;

View File

@@ -274,26 +274,11 @@ export default class RevisionsDialog extends BasicWidget {
this.$content.html($table); this.$content.html($table);
} else if (revisionItem.type === 'canvas') { } else if (revisionItem.type === 'canvas') {
/** const sanitizedTitle = revisionItem.title.replace(/[^a-z0-9-.]/gi, "");
* 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;
try { this.$content.html($("<img>")
const data = JSON.parse(content) .attr("src", `api/revisions/${revisionItem.revisionId}/image/${sanitizedTitle}?${Math.random()}`)
const svg = data.svg || "no svg present." .css("max-width", "100%"));
/**
* 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."));
}
} else { } else {
this.$content.text("Preview isn't available for this note type."); this.$content.text("Preview isn't available for this note type.");
} }

View File

@@ -14,7 +14,8 @@ const TPL = `
<option value="dateCreated">Date created</option> <option value="dateCreated">Date created</option>
<option value="dateModified">Date of last modification</option> <option value="dateModified">Date of last modification</option>
<option value="contentSize">Note content size</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="revisionCount">Number of revisions</option>
<option value="childrenCount">Number of children notes</option> <option value="childrenCount">Number of children notes</option>
<option value="parentCount">Number of clones</option> <option value="parentCount">Number of clones</option>

View File

@@ -176,10 +176,6 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
await sleep(200); await sleep(200);
} }
const appState = {
theme: this.themeStyle
};
/** /**
* new and empty note - make sure that canvas is empty. * new and empty note - make sure that canvas is empty.
* If we do not set it manually, we occasionally get some "bleeding" from another * If we do not set it manually, we occasionally get some "bleeding" from another
@@ -189,7 +185,9 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
if (!blob.content?.trim()) { if (!blob.content?.trim()) {
const sceneData = { const sceneData = {
elements: [], elements: [],
appState, appState: {
theme: this.themeStyle
},
collaborators: [] collaborators: []
}; };
@@ -207,10 +205,13 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
content = { content = {
elements: [], elements: [],
files: [], files: [],
appState: {}
}; };
} }
const {elements, files} = content; const {elements, files, appState = {}} = content;
appState.theme = this.themeStyle;
const boundingClientRect = this.excalidrawWrapperRef.current.getBoundingClientRect(); const boundingClientRect = this.excalidrawWrapperRef.current.getBoundingClientRect();
appState.width = boundingClientRect.width; appState.width = boundingClientRect.width;
@@ -289,13 +290,18 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
if (element.fileId) { if (element.fileId) {
activeFiles[element.fileId] = files[element.fileId]; activeFiles[element.fileId] = files[element.fileId];
} }
}) });
const content = { const content = {
type: "excalidraw", type: "excalidraw",
version: 2, version: 2,
elements, elements,
files: activeFiles files: activeFiles,
appState: {
scrollX: appState.scrollX,
scrollY: appState.scrollY,
zoom: appState.zoom
}
}; };
const attachments = [ const attachments = [
@@ -325,7 +331,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
return { return {
content: JSON.stringify(content), content: JSON.stringify(content),
attachments: attachments attachments
}; };
} }

View File

@@ -5,14 +5,27 @@ const becca = require('../../becca/becca');
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
const fs = require('fs'); const fs = require('fs');
function returnImage(req, res) { function returnImageFromNote(req, res) {
const image = becca.getNote(req.params.noteId); 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) { if (!image) {
res.set('Content-Type', 'image/png'); res.set('Content-Type', 'image/png');
return res.send(fs.readFileSync(`${RESOURCE_DIR}/db/image-deleted.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); return res.sendStatus(400);
} }
@@ -84,7 +97,8 @@ function updateImage(req) {
} }
module.exports = { module.exports = {
returnImage, returnImageFromNote,
returnImageFromRevision,
returnAttachedImage, returnAttachedImage,
updateImage updateImage
}; };

View File

@@ -181,6 +181,8 @@ function register(app) {
apiRoute(GET, '/api/revisions/:revisionId/blob', revisionsApiRoute.getRevisionBlob); apiRoute(GET, '/api/revisions/:revisionId/blob', revisionsApiRoute.getRevisionBlob);
apiRoute(DEL, '/api/revisions/:revisionId', revisionsApiRoute.eraseRevision); apiRoute(DEL, '/api/revisions/:revisionId', revisionsApiRoute.eraseRevision);
apiRoute(PST, '/api/revisions/:revisionId/restore', revisionsApiRoute.restoreRevision); 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); 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); 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 // :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); route(PUT, '/api/images/:noteId', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware], imageRoute.updateImage, apiResultHandler);
apiRoute(GET, '/api/options', optionsApiRoute.getOptions); apiRoute(GET, '/api/options', optionsApiRoute.getOptions);

View File

@@ -7,8 +7,9 @@ const sql = require("./sql");
function getFullAnonymizationScript() { function getFullAnonymizationScript() {
// we want to delete all non-builtin attributes because they can contain sensitive names and values // 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 const builtinAttrNames = BUILTIN_ATTRIBUTES
.filter(attr => !["shareCredentials", "shareAlias"].includes(attr.name))
.map(attr => `'${attr.name}'`).join(', '); .map(attr => `'${attr.name}'`).join(', ');
const anonymizeScript = ` const anonymizeScript = `

View File

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

View File

@@ -1 +1 @@
module.exports = { buildDate:"2023-09-21T23:38:18+02:00", buildRevision: "79e5e3b65ff613cdb81e2afaa832037ccf06d7b8" }; module.exports = { buildDate:"2023-10-07T23:02:47+03:00", buildRevision: "3d15aeae58224ac8716dd58938458e89af9bf7a0" };

View File

@@ -7,7 +7,7 @@ const BBranch = require('../becca/entities/bbranch');
const becca = require("../becca/becca"); const becca = require("../becca/becca");
const log = require("./log"); const log = require("./log");
function cloneNoteToParentNote(noteId, parentNoteId, prefix) { function cloneNoteToParentNote(noteId, parentNoteId, prefix = null) {
if (!(noteId in becca.notes) || !(parentNoteId in becca.notes)) { if (!(noteId in becca.notes) || !(parentNoteId in becca.notes)) {
return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' }; return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' };
} }

View File

@@ -763,7 +763,7 @@ class ConsistencyChecks {
} }
if (this.reloadNeeded) { if (this.reloadNeeded) {
require("../becca/becca_loader").reload(); require("../becca/becca_loader").reload("consistency checks need becca reload");
} }
return !this.unrecoveredConsistencyErrors; return !this.unrecoveredConsistencyErrors;

View File

@@ -148,12 +148,13 @@ function fillEntityChanges(entityName, entityPrimaryKey, condition = '') {
const entity = becca.getEntity(entityName, entityId); const entity = becca.getEntity(entityName, entityId);
if (entity) { if (entity) {
ec.hash = entity.generateHash() || "|deleted"; ec.hash = entity.generateHash();
ec.utcDateChanged = entity.getUtcDateChanged() || dateUtils.utcNowDateTime(); ec.utcDateChanged = entity.getUtcDateChanged() || dateUtils.utcNowDateTime();
ec.isSynced = entityName !== 'options' || !!entity.isSynced; ec.isSynced = entityName !== 'options' || !!entity.isSynced;
} else { } else {
// entity might be null (not present in becca) when it's deleted // entity might be null (not present in becca) when it's deleted
// FIXME: hacky, not sure if it might cause some problems // this will produce different hash value than when entity is being deleted since then
// all normal hashed attributes are being used. Sync should recover from that, though.
ec.hash = "deleted"; ec.hash = "deleted";
ec.utcDateChanged = dateUtils.utcNowDateTime(); ec.utcDateChanged = dateUtils.utcNowDateTime();
ec.isSynced = true; // deletable (the ones with isDeleted) entities are synced ec.isSynced = true; // deletable (the ones with isDeleted) entities are synced

View File

@@ -327,6 +327,11 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
content = content.replace(/<\/body>.*<\/html>/gis, ""); content = content.replace(/<\/body>.*<\/html>/gis, "");
content = content.replace(/src="([^"]*)"/g, (match, url) => { content = content.replace(/src="([^"]*)"/g, (match, url) => {
if (url.startsWith("data:image")) {
// inline images are parsed and saved into attachments in the note service
return match;
}
try { try {
url = decodeURIComponent(url).trim(); url = decodeURIComponent(url).trim();
} catch (e) { } catch (e) {
@@ -456,7 +461,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
position: attachmentMeta.position position: attachmentMeta.position
}); });
attachment.setContent(content); attachment.setContent(content, { forceSave: true });
return; return;
} }

View File

@@ -60,7 +60,7 @@ function checkProtectedSessionExpiration() {
log.info("Expiring protected session"); log.info("Expiring protected session");
require('./ws').reloadFrontend(); require('./ws').reloadFrontend("leaving protected session");
} }
} }

View File

@@ -56,9 +56,9 @@ class OrderByAndLimitExp extends Expression {
if (!valA && !valB) { if (!valA && !valB) {
// the attribute value is empty/zero in both notes so continue to the next order definition // the attribute value is empty/zero in both notes so continue to the next order definition
continue; continue;
} else if (!valB || valA < valB) { } else if (valA < valB) {
return smaller; return smaller;
} else if (!valA || valA > valB) { } else if (valA > valB) {
return larger; return larger;
} }
// else the values are equal and continue to next order definition // else the values are equal and continue to next order definition

View File

@@ -31,7 +31,8 @@ const PROP_MAPPING = {
"targetrelationcount": "targetRelationCount", "targetrelationcount": "targetRelationCount",
"targetrelationcountincludinglinks": "targetRelationCountIncludingLinks", "targetrelationcountincludinglinks": "targetRelationCountIncludingLinks",
"contentsize": "contentSize", "contentsize": "contentSize",
"notesize": "noteSize", "contentandattachmentssize": "contentAndAttachmentsSize",
"contentandattachmentsandrevisionssize": "contentAndAttachmentsAndRevisionsSize",
"revisioncount": "revisionCount" "revisioncount": "revisionCount"
}; };
@@ -48,7 +49,7 @@ class PropertyComparisonExp extends Expression {
this.comparedValue = comparedValue; // for DEBUG mode this.comparedValue = comparedValue; // for DEBUG mode
this.comparator = buildComparator(operator, comparedValue); this.comparator = buildComparator(operator, comparedValue);
if (['contentsize', 'notesize', 'revisioncount'].includes(this.propertyName)) { if (['contentsize', 'contentandattachmentssize', 'contentandattachmentsandrevisionssize', 'revisioncount'].includes(this.propertyName)) {
searchContext.dbLoadNeeded = true; searchContext.dbLoadNeeded = true;
} }
} }

View File

@@ -92,48 +92,108 @@ function searchFromRelation(note, relationName) {
function loadNeededInfoFromDatabase() { function loadNeededInfoFromDatabase() {
const sql = require('../../sql'); const sql = require('../../sql');
for (const noteId in becca.notes) { /**
becca.notes[noteId].contentSize = 0; * This complex structure is needed to calculate total occupied space by a note. Several object instances
becca.notes[noteId].noteSize = 0; * (note, revisions, attachments) can point to a single blobId, and thus the blob size should count towards the total
becca.notes[noteId].revisionCount = 0; * only once.
} *
* @var {Object.<string, Object.<string, int>>} - noteId => { blobId => blobSize }
*/
const noteBlobs = {};
const noteContentLengths = sql.getRows(` const noteContentLengths = sql.getRows(`
SELECT SELECT
noteId, noteId,
blobId,
LENGTH(content) AS length LENGTH(content) AS length
FROM notes FROM notes
JOIN blobs USING(blobId) JOIN blobs USING(blobId)
WHERE notes.isDeleted = 0`); WHERE notes.isDeleted = 0`);
for (const {noteId, length} of noteContentLengths) { for (const {noteId, blobId, length} of noteContentLengths) {
if (!(noteId in becca.notes)) { if (!(noteId in becca.notes)) {
log.error(`Note ${noteId} not found in becca.`); log.error(`Note '${noteId}' not found in becca.`);
continue; continue;
} }
becca.notes[noteId].contentSize = length; becca.notes[noteId].contentSize = length;
becca.notes[noteId].noteSize = length; becca.notes[noteId].revisionCount = 0;
noteBlobs[noteId] = { [blobId]: length };
}
const attachmentContentLengths = sql.getRows(`
SELECT
ownerId AS noteId,
attachments.blobId,
LENGTH(content) AS length
FROM attachments
JOIN notes ON attachments.ownerId = notes.noteId
JOIN blobs ON attachments.blobId = blobs.blobId
WHERE attachments.isDeleted = 0
AND notes.isDeleted = 0`);
for (const {noteId, blobId, length} of attachmentContentLengths) {
if (!(noteId in becca.notes)) {
log.error(`Note '${noteId}' not found in becca.`);
continue;
}
if (!(noteId in noteBlobs)) {
log.error(`Did not find a '${noteId}' in the noteBlobs.`);
continue;
}
noteBlobs[noteId][blobId] = length;
}
for (const noteId in noteBlobs) {
becca.notes[noteId].contentAndAttachmentsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0);
} }
const revisionContentLengths = sql.getRows(` const revisionContentLengths = sql.getRows(`
SELECT SELECT
noteId, noteId,
LENGTH(content) AS length revisions.blobId,
LENGTH(content) AS length,
1 AS isNoteRevision
FROM notes FROM notes
JOIN revisions USING(noteId) JOIN revisions USING(noteId)
JOIN blobs USING(blobId) JOIN blobs ON revisions.blobId = blobs.blobId
WHERE notes.isDeleted = 0
UNION ALL
SELECT
noteId,
revisions.blobId,
LENGTH(content) AS length,
0 AS isNoteRevision -- it's attachment not counting towards revision count
FROM notes
JOIN revisions USING(noteId)
JOIN attachments ON attachments.ownerId = revisions.revisionId
JOIN blobs ON attachments.blobId = blobs.blobId
WHERE notes.isDeleted = 0`); WHERE notes.isDeleted = 0`);
for (const {noteId, length} of revisionContentLengths) { for (const {noteId, blobId, length, isNoteRevision} of revisionContentLengths) {
if (!(noteId in becca.notes)) { if (!(noteId in becca.notes)) {
log.error(`Note ${noteId} not found in becca.`); log.error(`Note '${noteId}' not found in becca.`);
continue; continue;
} }
becca.notes[noteId].noteSize += length; if (!(noteId in noteBlobs)) {
log.error(`Did not find a '${noteId}' in the noteBlobs.`);
continue;
}
noteBlobs[noteId][blobId] = length;
if (isNoteRevision) {
becca.notes[noteId].revisionCount++; becca.notes[noteId].revisionCount++;
} }
}
for (const noteId in noteBlobs) {
becca.notes[noteId].contentAndAttachmentsAndRevisionsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0);
}
} }
/** /**

View File

@@ -27,7 +27,8 @@ const PROP_MAPPING = {
"targetrelationcount": "targetRelationCount", "targetrelationcount": "targetRelationCount",
"targetrelationcountincludinglinks": "targetRelationCountIncludingLinks", "targetrelationcountincludinglinks": "targetRelationCountIncludingLinks",
"contentsize": "contentSize", "contentsize": "contentSize",
"notesize": "noteSize", "contentandattachmentssize": "contentAndAttachmentsSize",
"contentandattachmentsandrevisionssize": "contentAndAttachmentsAndRevisionsSize",
"revisioncount": "revisionCount" "revisioncount": "revisionCount"
}; };
@@ -42,7 +43,7 @@ class ValueExtractor {
this.propertyPath = ['note', 'relations', this.propertyPath[0].substr(1), ...this.propertyPath.slice(1, this.propertyPath.length)]; this.propertyPath = ['note', 'relations', this.propertyPath[0].substr(1), ...this.propertyPath.slice(1, this.propertyPath.length)];
} }
if (['contentsize', 'notesize', 'revisioncount'].includes(this.propertyPath[this.propertyPath.length - 1])) { if (['contentsize', 'contentandattachmentssize', 'contentandattachmentsandrevisionssize', 'revisioncount'].includes(this.propertyPath[this.propertyPath.length - 1])) {
searchContext.dbLoadNeeded = true; searchContext.dbLoadNeeded = true;
} }
} }

View File

@@ -151,10 +151,15 @@ async function pullChanges(syncContext) {
if (entityChanges.length === 0) { if (entityChanges.length === 0) {
break; break;
} else { } else {
try { // https://github.com/zadam/trilium/issues/4310
const sizeInKb = Math.round(JSON.stringify(resp).length / 1024); const sizeInKb = Math.round(JSON.stringify(resp).length / 1024);
log.info(`Sync ${logMarkerId}: Pulled ${entityChanges.length} changes in ${sizeInKb} KB, starting at entityChangeId=${lastSyncedPull} in ${pulledDate - startDate}ms and applied them in ${Date.now() - pulledDate}ms, ${outstandingPullCount} outstanding pulls`); log.info(`Sync ${logMarkerId}: Pulled ${entityChanges.length} changes in ${sizeInKb} KB, starting at entityChangeId=${lastSyncedPull} in ${pulledDate - startDate}ms and applied them in ${Date.now() - pulledDate}ms, ${outstandingPullCount} outstanding pulls`);
} }
catch (e) {
log.error(`Error occurred ${e.message} ${e.stack}`);
}
}
} }
log.info("Finished pull"); log.info("Finished pull");

View File

@@ -106,7 +106,7 @@ function updateNormalEntity(remoteEC, remoteEntityRow, instanceId, updateContext
updateContext.updated[remoteEC.entityName] = updateContext.updated[remoteEC.entityName] || []; updateContext.updated[remoteEC.entityName] = updateContext.updated[remoteEC.entityName] || [];
updateContext.updated[remoteEC.entityName].push(remoteEC.entityId); updateContext.updated[remoteEC.entityName].push(remoteEC.entityId);
if (!localEC || localEC.utcDateChanged < remoteEC.utcDateChanged) { if (!localEC || localEC.utcDateChanged < remoteEC.utcDateChanged || localEC.hash !== remoteEC.hash) {
entityChangesService.putEntityChangeWithInstanceId(remoteEC, instanceId); entityChangesService.putEntityChangeWithInstanceId(remoteEC, instanceId);
} }

View File

@@ -13,7 +13,7 @@ const env = require('./env');
if (env.isDev()) { if (env.isDev()) {
const chokidar = require('chokidar'); const chokidar = require('chokidar');
const debounce = require('debounce'); const debounce = require('debounce');
const debouncedReloadFrontend = debounce(reloadFrontend, 200); const debouncedReloadFrontend = debounce(() => reloadFrontend("source code change"), 200);
chokidar chokidar
.watch('src/public') .watch('src/public')
.on('add', debouncedReloadFrontend) .on('add', debouncedReloadFrontend)
@@ -230,8 +230,8 @@ function syncFailed() {
sendMessageToAllClients({ type: 'sync-failed', lastSyncedPush }); sendMessageToAllClients({ type: 'sync-failed', lastSyncedPush });
} }
function reloadFrontend() { function reloadFrontend(reason) {
sendMessageToAllClients({ type: 'reload-frontend' }); sendMessageToAllClients({ type: 'reload-frontend', reason });
} }
function setLastSyncedPush(entityChangeId) { function setLastSyncedPush(entityChangeId) {