Compare commits

..

68 Commits

Author SHA1 Message Date
zadam d09d3f5a96 release 0.61.9-beta
Publish Docker image / Push Docker image to multiple registries (push) Failing after 42s
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
Publish Docker image / Push Docker image to multiple registries (push) Failing after 38s
2023-09-29 00:54:45 +02:00
zadam e5555beea9 logging reason for frontend reload 2023-09-28 23:47:19 +02:00
zadam 9767b6269a upgrade code mirror to 5.65.15 and fix modes requiring multiplex or overlay, fixes #4279 2023-09-28 01:02:27 +02:00
zadam 7e486fda06 electron update 2023-09-28 00:27:00 +02:00
zadam 9f726304aa sync fix, #4288 2023-09-28 00:24:53 +02:00
zadam be918628c3 global API docs 2023-09-25 23:04:03 +02:00
zadam 602b9ae64a API docs 2023-09-23 00:04:32 +02:00
zadam 602a166e36 added info, confirm, prompt dialogs 2023-09-23 00:04:16 +02:00
zadam aaad858395 save scroll and zoom in canvas 2023-09-22 23:44:03 +02:00
zadam 48248224f8 release 0.61.7-beta
Publish Docker image / Push Docker image to multiple registries (push) Failing after 39s
2023-09-21 23:38:18 +02:00
zadam 79e5e3b65f more logging for sync 2023-09-21 18:13:14 +02:00
zadam d0383f3044 remove debian packaging hack 2023-09-21 12:44:20 +02:00
zadam 62ecd1ad76 node 18.18.0 2023-09-21 12:29:11 +02:00
zadam 75b7706c2c mermaid 10.4.0 2023-09-21 12:24:44 +02:00
zadam 584b176643 hiding useless/misleading buttons from excalidraw 2023-09-21 12:03:40 +02:00
zadam a16555bbff don't save appState in canvas - app state should be reset after each load 2023-09-21 11:54:54 +02:00
zadam a749e24147 fix creating revisions for non-text notes #4176 2023-09-21 11:38:38 +02:00
zadam bb81f110dd improved error handling 2023-09-21 11:16:03 +02:00
zadam 5dd6f49104 chart js 0.16.0 2023-09-19 23:59:05 +02:00
zadam bc6be44b19 better error condition checks 2023-09-19 23:48:55 +02:00
zadam 8075265753 fix migration, closes #4262 2023-09-18 23:45:00 +02:00
zadam 4a67f63abd better error message in image attachment + upgrades 2023-09-14 00:18:56 +02:00
zadam d9666210f1 make sure that the hidden note is never selected when hoisted to root to avoid e.g. erroneous deletion 2023-09-13 16:57:24 +02:00
zadam 5f6d562bf8 add ability to excalidraw to follow links 2023-09-08 23:00:43 +02:00
zadam f37dc66074 add support for storing canvas libraries in note attachments plus storing exported SVG in attachment 2023-09-08 21:53:57 +02:00
zadam 0b84524807 fix refreshing note actions on note/tab switch, closes #4247 2023-09-08 00:43:18 +02:00
zadam 8062bb7e2a fix reloading unprotected note title to the document.title after entering protected session, fixes #4244 2023-09-08 00:28:00 +02:00
zadam 806062c8d1 fix undelete attachments 2023-09-08 00:22:48 +02:00
zadam 83f19c0537 fix protecting attachments 2023-09-08 00:19:30 +02:00
zadam 3a83d58b25 release 0.61.6-beta
Publish Docker image / Push Docker image to multiple registries (push) Failing after 29s
2023-09-06 23:57:29 +02:00
zadam 6fa9d996e8 ckeditor 39.0.2 2023-09-06 23:23:42 +02:00
siriusXT 1ea3d238e0 Fix right click bookmark bug
(cherry picked from commit 92e43bc051)
2023-09-06 23:11:51 +02:00
zadam eb273b7dbb lib upgrades 2023-09-06 23:11:02 +02:00
zadam d2263c68f8 provide note dates in the frontend API, fixes #4232 2023-09-06 22:54:31 +02:00
zadam 97d8b19868 add missing API docs 2023-09-06 09:23:13 +02:00
zadam 2bc7da91a6 add createLink() returns jsDoc, #4235 2023-09-06 09:20:32 +02:00
zadam 2b4cbb5f6b fix clipperInbox handling for new note creation, closes #4219 2023-09-05 23:24:01 +02:00
zadam 7b662b04ff fix orderby with multiple labels, closes #4220 2023-09-05 23:00:08 +02:00
zadam f8e4a665bd fixed search parser tests 2023-09-05 22:48:20 +02:00
zadam f9a27dd90c add imageStyle alignBlockLeft, alignBlockRight, fixes #4215 2023-09-05 22:16:45 +02:00
zadam 641985737f fix FNote.getContent() #4210 2023-09-05 22:02:26 +02:00
zadam 121e4ba2ea fix displaying 1 / 0 in find widget 2023-09-05 21:00:24 +02:00
zadam 01474ecd2d sync fixes 2023-09-05 00:30:09 +02:00
zadam 82e4e28e7b fix 2023-09-04 23:57:42 +02:00
zadam 886ee0dbcb fix sync exception 2023-08-31 00:14:35 +02:00
zadam 6f7fbacca1 add "api.runOnFrontend()" to the backend script API 2023-08-30 23:18:16 +02:00
vaifix 8da5b90aea Fix bug: Calendar display incorrect tooltips.
(cherry picked from commit 58fe3a62af)
2023-08-30 00:20:42 +02:00
zadam e7d57bc08f Merge remote-tracking branch 'origin/beta' into beta
# Conflicts:
#	package-lock.json
2023-08-30 00:11:52 +02:00
zadam 041758766a allow specifying date created in the ETAPI, #4199 2023-08-30 00:11:32 +02:00
zadam f2a510e4c5 cleanup of old migrations, since upgrading to 0.61 is possible only from 0.60. 2023-08-18 15:56:38 +02:00
zadam 4717242dc7 force migration to 0.60 first before 0.61 #4132 2023-08-18 15:55:59 +02:00
zadam c1865f8564 small refactor 2023-08-17 09:09:06 +02:00
163 changed files with 10155 additions and 2285 deletions
-1
View File
@@ -75,7 +75,6 @@ module.exports = {
glob: true,
log: true,
EditorWatchdog: true,
// \src\share\canvas_share.js
React: true,
appState: true,
ExcalidrawLib: true,
+1 -1
View File
@@ -2,7 +2,7 @@ image:
file: .gitpod.dockerfile
tasks:
- before: nvm install 18.16.1 && nvm use 18.16.1
- before: nvm install 18.18.0 && nvm use 18.18.0
init: npm install
command: npm run start-server
+1 -1
View File
@@ -1,5 +1,5 @@
# !!! Don't try to build this Dockerfile directly, run it through bin/build-docker.sh script !!!
FROM node:18.16.1-alpine
FROM node:18.18.0-alpine
# Create app directory
WORKDIR /usr/src/app
-15
View File
@@ -5,18 +5,3 @@ echo "Packaging debian x64 distribution..."
VERSION=`jq -r ".version" package.json`
./node_modules/.bin/electron-installer-debian --config bin/deb-options.json --options.version=${VERSION} --arch amd64
# hacky stop-gag measure to produce debian compatible XZ compressed debs until this is fixed: https://github.com/electron-userland/electron-installer-debian/issues/272
cd dist
ar x trilium_${VERSION}_amd64.deb
rm trilium_${VERSION}_amd64.deb
# recompress
< control.tar.zst zstd -d | xz > control.tar.xz
< data.tar.zst zstd -d | xz > data.tar.xz
# create deb archive (I really do not know, what argument "sdsd" is for but something is required for ar to create the archive as desired)
ar -m -c -a sdsd trilium_${VERSION}_amd64.deb debian-binary control.tar.xz data.tar.xz
rm control* data* debian-binary
echo "Converted to XZ deb"
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
PKG_DIR=dist/trilium-linux-x64-server
NODE_VERSION=18.16.1
NODE_VERSION=18.18.0
if [ "$1" != "DONTCOPY" ]
then
+2 -2
View File
@@ -5,7 +5,7 @@ if [[ $# -eq 0 ]] ; then
exit 1
fi
n exec 18.16.1 npm run webpack
n exec 18.18.0 npm run webpack
DIR=$1
@@ -27,7 +27,7 @@ cp -r electron.js $DIR/
cp webpack-* $DIR/
# run in subshell (so we return to original dir)
(cd $DIR && n exec 18.16.1 npm install --only=prod)
(cd $DIR && n exec 18.18.0 npm install --only=prod)
# cleanup of useless files in dependencies
rm -r $DIR/node_modules/image-q/demo
View File
+2 -1
View File
@@ -1,6 +1,7 @@
{
"src": "dist/trilium-linux-x64",
"dest": "dist/",
"compression": "xz",
"name": "trilium",
"productName": "Trilium Notes",
"genericName": "Note taker",
@@ -11,4 +12,4 @@
"bin": "trilium",
"icon": "dist/trilium-linux-x64/icon.png",
"categories": [ "Office" ]
}
}
+39 -157
View File
@@ -1,165 +1,47 @@
UPDATE etapi_tokens SET tokenHash = 'API token hash value';
UPDATE notes SET title = 'title' WHERE noteId != 'root' AND noteId NOT LIKE '\_%' ESCAPE '\';
UPDATE notes SET title = 'title' WHERE title NOT IN ('root', '_hidden', '_share');
UPDATE blobs SET content = 'text' WHERE content IS NOT NULL;
UPDATE revisions SET title = 'title';
UPDATE attributes SET name = 'name', value = 'value'
WHERE type = 'label'
AND name NOT IN ('inbox',
'disableVersioning',
'calendarRoot',
'archived',
'excludeFromExport',
'disableInclusion',
'appCss',
'appTheme',
'hidePromotedAttributes',
'readOnly',
'autoReadOnlyDisabled',
'cssClass',
'iconClass',
'keyboardShortcut',
'run',
'runOnInstance',
'runAtHour',
'customRequestHandler',
'customResourceProvider',
'widget',
'noteInfoWidgetDisabled',
'linkMapWidgetDisabled',
'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled',
'similarNotesWidgetDisabled',
'workspace',
'workspaceIconClass',
'workspaceTabBackgroundColor',
'searchHome',
'workspaceInbox',
'workspaceSearchHome',
'sqlConsoleHome',
'datePattern',
'pageSize',
'viewType',
'mapRootNoteId',
'bookmarkFolder',
'sorted',
'top',
'fullContentWidth',
'shareHiddenFromTree',
'shareAlias',
'shareOmitDefaultCss',
'shareRoot',
'internalLink',
'imageLink',
'relationMapLink',
'includeMapLink',
'runOnNoteCreation',
'runOnNoteTitleChange',
'runOnNoteContentChange',
'runOnNoteChange',
'runOnChildNoteCreation',
'runOnAttributeCreation',
'runOnAttributeChange',
'template',
'inherit',
'widget',
'renderNote',
'shareCss',
'shareJs',
'shareFavicon',
'executeButton',
'keepCurrentHoisting',
'color',
'toc',
'excludeFromNoteMap',
'docName',
'launcherType',
'builtinWidget',
'baseSize',
'growthFactor'
);
UPDATE attributes SET name = 'name'
AND name NOT IN ('inbox',
'disableVersioning',
'calendarRoot',
'archived',
'excludeFromExport',
'disableInclusion',
'appCss',
'appTheme',
'hidePromotedAttributes',
'readOnly',
'autoReadOnlyDisabled',
'cssClass',
'iconClass',
'keyboardShortcut',
'run',
'runOnInstance',
'runAtHour',
'customRequestHandler',
'customResourceProvider',
'widget',
'noteInfoWidgetDisabled',
'linkMapWidgetDisabled',
'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled',
'similarNotesWidgetDisabled',
'workspace',
'workspaceIconClass',
'workspaceTabBackgroundColor',
'searchHome',
'workspaceInbox',
'workspaceSearchHome',
'sqlConsoleHome',
'datePattern',
'pageSize',
'viewType',
'mapRootNoteId',
'bookmarkFolder',
'sorted',
'top',
'fullContentWidth',
'shareHiddenFromTree',
'shareAlias',
'shareOmitDefaultCss',
'shareRoot',
'internalLink',
'imageLink',
'relationMapLink',
'includeMapLink',
'runOnNoteCreation',
'runOnNoteTitleChange',
'runOnNoteContentChange',
'runOnNoteChange',
'runOnChildNoteCreation',
'runOnAttributeCreation',
'runOnAttributeChange',
'template',
'inherit',
'widget',
'renderNote',
'shareCss',
'shareJs',
'shareFavicon',
'executeButton',
'keepCurrentHoisting',
'color',
'toc',
'excludeFromNoteMap',
'docName',
'launcherType',
'builtinWidget',
'baseSize',
'growthFactor'
);
UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label'
AND name NOT IN
('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss',
'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass',
'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider',
'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass',
'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox',
'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId',
'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top',
'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription',
'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate',
'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop',
'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation',
'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation',
'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template',
'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
UPDATE attributes SET name = 'name' WHERE type = 'relation'
AND name NOT IN
('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss',
'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass',
'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider',
'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'revisionsWidgetDisabled',
'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass',
'workspaceTabBackgroundColor', 'workspaceCalendarRoot', 'workspaceTemplate', 'searchHome', 'workspaceInbox',
'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId',
'bookmarkFolder', 'sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale', 'top',
'fullContentWidth', 'shareHiddenFromTree', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription',
'shareRaw', 'shareDisallowRobotIndexing', 'shareIndex', 'displayRelations', 'hideRelations', 'titleTemplate',
'template', 'toc', 'color', 'keepCurrentHoisting', 'executeButton', 'executeDescription', 'newNotesOnTop',
'clipperInbox', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation',
'runOnNoteTitleChange', 'runOnNoteChange', 'runOnNoteContentChange', 'runOnNoteDeletion', 'runOnBranchCreation',
'runOnBranchDeletion', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template',
'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL AND prefix != 'recovered';
UPDATE options SET value = 'anonymized' WHERE name IN
('documentId', 'documentSecret', 'encryptedDataKey',
'passwordVerificationHash', 'passwordVerificationSalt',
'passwordDerivedKeySalt', 'username', 'syncServerHost', 'syncProxy')
AND value != '';
('documentId', 'documentSecret', 'encryptedDataKey',
'passwordVerificationHash', 'passwordVerificationSalt',
'passwordDerivedKeySalt', 'username', 'syncServerHost', 'syncProxy')
AND value != '';
VACUUM;
-1
View File
@@ -1 +0,0 @@
module.exports = () => console.log("NOOP, moved to migration 0189");
@@ -1,4 +0,0 @@
-- black theme has been removed, dark is closest replacement
UPDATE options SET value = 'dark' WHERE name = 'theme' AND value = 'black';
UPDATE options SET value = 'light' WHERE name = 'theme' AND value = 'white';
@@ -1,2 +0,0 @@
ALTER TABLE branches DROP COLUMN utcDateCreated;
ALTER TABLE options DROP COLUMN utcDateCreated;
@@ -1,33 +0,0 @@
CREATE TABLE IF NOT EXISTS "mig_entity_changes" (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`entityName` TEXT NOT NULL,
`entityId` TEXT NOT NULL,
`hash` TEXT NOT NULL,
`isErased` INT NOT NULL,
`changeId` TEXT NOT NULL,
`sourceId` TEXT NOT NULL,
`isSynced` INTEGER NOT NULL,
`utcDateChanged` TEXT NOT NULL
);
INSERT INTO mig_entity_changes (id, entityName, entityId, hash, isErased, changeId, sourceId, isSynced, utcDateChanged)
SELECT id, entityName, entityId, hash, isErased, '', sourceId, isSynced, utcDateChanged FROM entity_changes;
-- delete duplicates https://github.com/zadam/trilium/issues/2534
DELETE FROM mig_entity_changes WHERE isErased = 0 AND id IN (
SELECT id FROM mig_entity_changes ec
WHERE (
SELECT COUNT(*) FROM mig_entity_changes
WHERE ec.entityName = mig_entity_changes.entityName
AND ec.entityId = mig_entity_changes.entityId
) > 1
);
DROP TABLE entity_changes;
ALTER TABLE mig_entity_changes RENAME TO entity_changes;
CREATE UNIQUE INDEX `IDX_entityChanges_entityName_entityId` ON "entity_changes" (
`entityName`,
`entityId`
);
@@ -1,8 +0,0 @@
UPDATE branches SET branchId = 'hidden' where branchId = (
SELECT branchId FROM branches
WHERE parentNoteId = 'root'
AND noteId = 'hidden'
AND isDeleted = 0
ORDER BY utcDateModified
LIMIT 1
);
@@ -1 +0,0 @@
DELETE FROM options WHERE name = 'username';
@@ -1,15 +0,0 @@
CREATE TABLE IF NOT EXISTS "etapi_tokens"
(
etapiTokenId TEXT PRIMARY KEY NOT NULL,
name TEXT NOT NULL,
tokenHash TEXT NOT NULL,
utcDateCreated TEXT NOT NULL,
utcDateModified TEXT NOT NULL,
isDeleted INT NOT NULL DEFAULT 0);
INSERT INTO etapi_tokens (etapiTokenId, name, tokenHash, utcDateCreated, utcDateModified, isDeleted)
SELECT apiTokenId, 'Trilium Sender', token, utcDateCreated, utcDateCreated, isDeleted FROM api_tokens;
DROP TABLE api_tokens;
UPDATE entity_changes SET entityName = 'etapi_tokens' WHERE entityName = 'api_tokens';
-10
View File
@@ -1,10 +0,0 @@
module.exports = () => {
const sql = require('../../src/services/sql');
const crypto = require('crypto');
for (const {etapiTokenId, token} of sql.getRows("SELECT etapiTokenId, tokenHash AS token FROM etapi_tokens")) {
const tokenHash = crypto.createHash('sha256').update(token).digest('base64');
sql.execute(`UPDATE etapi_tokens SET tokenHash = ? WHERE etapiTokenId = ?`, [tokenHash, etapiTokenId]);
}
};
@@ -1,20 +0,0 @@
DROP TABLE entity_changes;
-- not preserving the data because of https://github.com/zadam/trilium/issues/3447
CREATE TABLE IF NOT EXISTS "entity_changes" (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`entityName` TEXT NOT NULL,
`entityId` TEXT NOT NULL,
`hash` TEXT NOT NULL,
`isErased` INT NOT NULL,
`changeId` TEXT NOT NULL,
`componentId` TEXT NOT NULL,
`instanceId` TEXT NOT NULL,
`isSynced` INTEGER NOT NULL,
`utcDateChanged` TEXT NOT NULL
);
CREATE UNIQUE INDEX `IDX_entityChanges_entityName_entityId` ON "entity_changes" (
`entityName`,
`entityId`
);
@@ -1 +0,0 @@
CREATE INDEX `IDX_entity_changes_changeId` ON `entity_changes` (`changeId`);
@@ -1,15 +0,0 @@
const becca = require('../../src/becca/becca');
const beccaLoader = require('../../src/becca/becca_loader');
const cls = require('../../src/services/cls');
module.exports = () => {
cls.init(() => {
beccaLoader.load();
for (const note of Object.values(becca.notes)) {
if (note.hasLabel('calendarRoot')) {
note.addLabel('excludeFromNoteMap', "", true);
}
}
});
};
@@ -1,2 +0,0 @@
-- removing potential remnants of recent notes in entity changes, see https://github.com/zadam/trilium/issues/2842
DELETE FROM entity_changes WHERE entityName = 'recent_notes';
@@ -1,2 +0,0 @@
UPDATE attributes SET value = replace(value, 'setLabelValue', 'updateLabelValue') WHERE name = 'action' AND type = 'label';
UPDATE attributes SET value = replace(value, 'setRelationTarget', 'updateRelationTarget') WHERE name = 'action' AND type = 'label';
-1
View File
@@ -1 +0,0 @@
module.exports = () => console.log("NOOP, increased because of protected notes IV change");
-6
View File
@@ -1,6 +0,0 @@
UPDATE branches SET branchId = '_hidden__search' WHERE parentNoteId = 'hidden' AND noteId = 'search' AND isDeleted = 0;
UPDATE branches SET branchId = 'root__globalNoteMap' WHERE parentNoteId = 'singles' AND noteId = 'globalnotemap' AND isDeleted = 0;
UPDATE branches SET branchId = '_hidden__sqlConsole' WHERE parentNoteId = 'hidden' AND noteId = 'sqlconsole' AND isDeleted = 0;
UPDATE branches SET branchId = 'root__hidden' WHERE parentNoteId = 'root' AND noteId = 'hidden' AND isDeleted = 0;
UPDATE branches SET branchId = '_hidden__bulkAction' WHERE parentNoteId = 'hidden' AND noteId = 'bulkaction' AND isDeleted = 0;
UPDATE branches SET branchId = '_hidden__share' WHERE parentNoteId = 'root' AND noteId = 'share' AND isDeleted = 0;
-53
View File
@@ -1,53 +0,0 @@
UPDATE notes SET noteId = '_globalNoteMap', title = 'Note Map' WHERE noteId = 'globalnotemap';
UPDATE note_contents SET noteId = '_globalNoteMap' WHERE noteId = 'globalnotemap';
UPDATE note_revisions SET noteId = '_globalNoteMap' WHERE noteId = 'globalnotemap';
UPDATE branches SET noteId = '_globalNoteMap' WHERE noteId = 'globalnotemap';
UPDATE branches SET parentNoteId = '_globalNoteMap' WHERE parentNoteId = 'globalnotemap';
UPDATE attributes SET noteId = '_globalNoteMap' WHERE noteId = 'globalnotemap';
UPDATE attributes SET value = '_globalNoteMap' WHERE type = 'relation' AND value = 'globalnotemap';
UPDATE entity_changes SET entityId = '_globalNoteMap' WHERE entityId = 'globalnotemap';
UPDATE notes SET noteId = '_bulkAction', title = 'Bulk Action' WHERE noteId = 'bulkaction';
UPDATE note_contents SET noteId = '_bulkAction' WHERE noteId = 'bulkaction';
UPDATE note_revisions SET noteId = '_bulkAction' WHERE noteId = 'bulkaction';
UPDATE branches SET parentNoteId = '_bulkAction' WHERE parentNoteId = 'bulkaction';
UPDATE branches SET noteId = '_bulkAction' WHERE noteId = 'bulkaction';
UPDATE attributes SET noteId = '_bulkAction' WHERE noteId = 'bulkaction';
UPDATE attributes SET value = '_bulkAction' WHERE type = 'relation' AND value = 'bulkaction';
UPDATE entity_changes SET entityId = '_bulkAction' WHERE entityId = 'bulkaction';
UPDATE notes SET noteId = '_sqlConsole', title = 'SQL Console History' WHERE noteId = 'sqlconsole';
UPDATE note_contents SET noteId = '_sqlConsole' WHERE noteId = 'sqlconsole';
UPDATE note_revisions SET noteId = '_sqlConsole' WHERE noteId = 'sqlconsole';
UPDATE branches SET noteId = '_sqlConsole' WHERE noteId = 'sqlconsole';
UPDATE branches SET parentNoteId = '_sqlConsole' WHERE parentNoteId = 'sqlconsole';
UPDATE attributes SET noteId = '_sqlConsole' WHERE noteId = 'sqlconsole';
UPDATE attributes SET value = '_sqlConsole' WHERE type = 'relation' AND value = 'sqlconsole';
UPDATE entity_changes SET entityId = '_sqlConsole' WHERE entityId = 'sqlconsole';
UPDATE notes SET noteId = '_hidden', title = 'Hidden Notes' WHERE noteId = 'hidden';
UPDATE note_contents SET noteId = '_hidden' WHERE noteId = 'hidden';
UPDATE note_revisions SET noteId = '_hidden' WHERE noteId = 'hidden';
UPDATE branches SET noteId = '_hidden', prefix = NULL WHERE noteId = 'hidden';
UPDATE branches SET parentNoteId = '_hidden' WHERE parentNoteId = 'hidden';
UPDATE attributes SET noteId = '_hidden' WHERE noteId = 'hidden';
UPDATE attributes SET value = '_hidden' WHERE type = 'relation' AND value = 'hidden';
UPDATE entity_changes SET entityId = '_hidden' WHERE entityId = 'hidden';
UPDATE notes SET noteId = '_search', title = 'Search History' WHERE noteId = 'search';
UPDATE note_contents SET noteId = '_search' WHERE noteId = 'search';
UPDATE note_revisions SET noteId = '_search' WHERE noteId = 'search';
UPDATE branches SET noteId = '_search' WHERE noteId = 'search';
UPDATE branches SET parentNoteId = '_search' WHERE parentNoteId = 'search';
UPDATE attributes SET noteId = '_search' WHERE noteId = 'search';
UPDATE attributes SET value = '_search' WHERE type = 'relation' AND value = 'search';
UPDATE entity_changes SET entityId = '_search' WHERE entityId = 'search';
UPDATE notes SET noteId = '_share', title = 'Shared Notes' WHERE noteId = 'share';
UPDATE note_contents SET noteId = '_share' WHERE noteId = 'share';
UPDATE note_revisions SET noteId = '_share' WHERE noteId = 'share';
UPDATE branches SET noteId = '_share' WHERE noteId = 'share';
UPDATE branches SET parentNoteId = '_share' WHERE parentNoteId = 'share';
UPDATE attributes SET noteId = '_share' WHERE noteId = 'share';
UPDATE attributes SET value = '_share' WHERE type = 'relation' AND value = 'share';
UPDATE entity_changes SET entityId = '_share' WHERE entityId = 'share';
@@ -1,12 +0,0 @@
module.exports = () => {
const hiddenSubtreeService = require('../../src/services/hidden_subtree');
const cls = require("../../src/services/cls");
const beccaLoader = require("../../src/becca/becca_loader");
cls.init(() => {
beccaLoader.load();
// make sure the hidden subtree exists since the subsequent migrations we will move some existing notes into it (share...)
// in previous releases hidden subtree was created lazily
hiddenSubtreeService.checkHiddenSubtree(true);
});
};
@@ -1,2 +0,0 @@
DELETE FROM branches WHERE noteId = '_share' AND parentNoteId != 'root' AND parentNoteId != '_hidden'; -- delete all other branches of _share if any
UPDATE branches SET parentNoteId = '_hidden' WHERE noteId = '_share';
@@ -1,2 +0,0 @@
DELETE FROM branches WHERE noteId = '_globalNoteMap' AND parentNoteId != 'singles' AND parentNoteId != '_hidden'; -- make sure there are no clones which would fail at the next line
UPDATE branches SET parentNoteId = '_hidden' WHERE noteId = '_globalNoteMap';
@@ -1,6 +0,0 @@
DELETE FROM branches WHERE noteId = 'singles';
DELETE FROM notes WHERE noteId = 'singles';
DELETE FROM note_contents WHERE noteId = 'singles';
DELETE FROM note_revisions WHERE noteId = 'singles';
DELETE FROM attributes WHERE noteId = 'singles';
DELETE FROM entity_changes WHERE entityId = 'singles';
@@ -1,21 +0,0 @@
module.exports = () => {
const cls = require("../../src/services/cls");
const cloningService = require("../../src/services/cloning");
const beccaLoader = require("../../src/becca/becca_loader");
const becca = require("../../src/becca/becca");
cls.init(() => {
beccaLoader.load();
for (const attr of becca.findAttributes('label','bookmarked')) {
cloningService.toggleNoteInParent(true, attr.noteId, '_lbBookmarks');
attr.markAsDeleted("0204__migrate_bookmarks_to_clones");
}
// bookmarkFolder used to work in 0.57 without the bookmarked label
for (const attr of becca.findAttributes('label','bookmarkFolder')) {
cloningService.toggleNoteInParent(true, attr.noteId, '_lbBookmarks');
}
});
};
@@ -1,3 +0,0 @@
UPDATE notes SET type = 'relationMap' WHERE type = 'relation-map';
UPDATE notes SET type = 'noteMap' WHERE type = 'note-map';
UPDATE notes SET type = 'webView' WHERE type = 'web-view';
@@ -1,33 +0,0 @@
// the history was previously not exposed and the fact they were not cleaned up is rather a side-effect than an intention
module.exports = () => {
const cls = require("../../src/services/cls");
const beccaLoader = require("../../src/becca/becca_loader");
const becca = require("../../src/becca/becca");
cls.init(() => {
beccaLoader.load();
// deleting just branches because they might be cloned (and therefore saved) also outside of the hidden subtree
const searchRoot = becca.getNote('_search');
for (const searchBranch of searchRoot.getChildBranches()) {
const searchNote = searchBranch.getNote();
if (searchNote.type === 'search') {
searchBranch.deleteBranch('0206__delete_search_and_sql_console_history');
}
}
const sqlConsoleRoot = becca.getNote('_sqlConsole');
for (const sqlConsoleBranch of sqlConsoleRoot.getChildBranches()) {
const sqlConsoleNote = sqlConsoleBranch.getNote();
if (sqlConsoleNote.type === 'code' && sqlConsoleNote.mime === 'text/x-sqlite;schema=trilium') {
sqlConsoleBranch.deleteBranch('0206__delete_search_and_sql_console_history');
}
}
});
};
@@ -1,2 +0,0 @@
UPDATE notes SET title = 'SQL Console History' WHERE noteId = '_sqlConsole';
UPDATE notes SET title = 'Search History' WHERE noteId = '_search';
@@ -1,13 +0,0 @@
module.exports = () => {
const cls = require("../../src/services/cls");
const beccaLoader = require("../../src/becca/becca_loader");
const becca = require("../../src/becca/becca");
cls.init(() => {
beccaLoader.load();
for (const label of becca.getNote('_hidden').getLabels('archived')) {
label.markAsDeleted('0208__remove_archived_from_hidden');
}
});
};
@@ -1,5 +0,0 @@
UPDATE attributes SET name = 'workspaceInbox' WHERE type = 'label' AND name = 'hoistedInbox';
UPDATE entity_changes SET entityId = 'workspaceInbox' WHERE entityName = 'attributes' AND entityId = 'hoistedInbox';
UPDATE attributes SET name = 'workspaceSearchHome' WHERE type = 'label' AND name = 'hoistedSearchHome';
UPDATE entity_changes SET entityId = 'workspaceSearchHome' WHERE entityName = 'attributes' AND entityId = 'hoistedSearchHome';
-24
View File
@@ -1,24 +0,0 @@
module.exports = async () => {
const cls = require("../../src/services/cls");
const beccaLoader = require("../../src/becca/becca_loader");
const log = require("../../src/services/log");
const consistencyChecks = require("../../src/services/consistency_checks");
const eraseService = require("../../src/services/erase");
await cls.init(async () => {
// precaution for the 0211 migration
eraseService.eraseDeletedNotesNow();
beccaLoader.load();
try {
// precaution before running 211 which might produce unique constraint problems if the DB was not consistent
consistencyChecks.runOnDemandChecksWithoutExclusiveLock(true);
}
catch (e) {
// consistency checks might start failing in the future if there's some incompatible migration down the road
// we can optimistically assume the DB is consistent and still continue
log.error(`Consistency checks failed in migration 0210: ${e.message} ${e.stack}`);
}
});
};
-12
View File
@@ -1,12 +0,0 @@
-- case based on isDeleted is needed, otherwise 2 branches (1 deleted, 1 not) might get the same ID
UPDATE entity_changes SET entityId = COALESCE((
SELECT
CASE isDeleted
WHEN 0 THEN parentNoteId || '_' || noteId
WHEN 1 THEN branchId
END
FROM branches WHERE branchId = entityId
), entityId)
WHERE entityName = 'branches' AND isErased = 0;
UPDATE branches SET branchId = parentNoteId || '_' || noteId WHERE isDeleted = 0;
@@ -1,27 +0,0 @@
module.exports = () => {
const cls = require("../../src/services/cls");
const beccaLoader = require("../../src/becca/becca_loader");
const becca = require("../../src/becca/becca");
const log = require("../../src/services/log");
cls.init(() => {
beccaLoader.load();
const hidden = becca.getNote("_hidden");
if (!hidden) {
log.info("MIGRATION 212: no _hidden note, skipping.");
return;
}
for (const noteId of hidden.getSubtreeNoteIds({includeHidden: true})) {
if (noteId.startsWith("_")) { // is "named" note
const note = becca.getNote(noteId);
for (const attr of note.getOwnedAttributes().slice()) {
attr.markAsDeleted("0212__delete_all_attributes_of_named_notes");
}
}
}
});
};
-48
View File
@@ -1,48 +0,0 @@
module.exports = () => {
const beccaLoader = require("../../src/becca/becca_loader");
const becca = require("../../src/becca/becca");
const cls = require("../../src/services/cls");
const log = require("../../src/services/log");
cls.init(() => {
beccaLoader.load();
for (const note of Object.values(becca.notes)) {
try {
if (!note.isJavaScript()) {
continue;
}
if (!note.mime?.endsWith('env=frontend') && !note.mime?.endsWith('env=backend')) {
continue;
}
const origContent = note.getContent().toString();
const fixedContent = origContent
.replaceAll("runOnServer", "runOnBackend")
.replaceAll("api.refreshTree()", "")
.replaceAll("addTextToActiveTabEditor", "addTextToActiveContextEditor")
.replaceAll("getActiveTabNote", "getActiveContextNote")
.replaceAll("getActiveTabTextEditor", "getActiveContextTextEditor")
.replaceAll("getActiveTabNotePath", "getActiveContextNotePath")
.replaceAll("getDateNote", "getDayNote")
.replaceAll("utils.unescapeHtml", "unescapeHtml")
.replaceAll("sortNotesByTitle", "sortNotes")
.replaceAll("CollapsibleWidget", "RightPanelWidget")
.replaceAll("TabAwareWidget", "NoteContextAwareWidget")
.replaceAll("TabCachingWidget", "NoteContextAwareWidget")
.replaceAll("NoteContextCachingWidget", "NoteContextAwareWidget");
if (origContent !== fixedContent) {
log.info(`Replacing legacy API calls for note '${note.noteId}'`);
note.saveNoteRevision();
note.setContent(fixedContent);
}
}
catch (e) {
log.error(`Error during migration to 213 for note '${note.noteId}': ${e.message} ${e.stack}`);
}
}
});
};
@@ -1 +0,0 @@
UPDATE branches SET notePosition = notePosition - 999899999 WHERE parentNoteId = 'root' AND notePosition > 999999999;
@@ -0,0 +1 @@
UPDATE attributes SET value = 'contentAndAttachmentsAndRevisionsSize' WHERE name = 'orderBy' AND value = 'noteSize';
+3 -1
View File
@@ -1,3 +1,5 @@
# Running `docker-compose up` will create/use the "trilium-data" directory in the user home
# Run `TRILIUM_DATA_DIR=/path/of/your/choice docker-compose up` to set a different directory
version: '2.1'
services:
trilium:
@@ -8,7 +10,7 @@ services:
ports:
- "8080:8080"
volumes:
- trilium:/home/node/trilium-data
- ${TRILIUM_DATA_DIR:-~/trilium-data}:/home/node/trilium-data
volumes:
trilium:
File diff suppressed because it is too large Load Diff
+300 -179
View File
@@ -1588,7 +1588,7 @@ See addLabel, addRelation for more specific methods.
<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#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>
@@ -1835,7 +1835,7 @@ See addLabel, addRelation for more specific methods.
<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#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>
@@ -2081,7 +2081,7 @@ returned.
<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#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>
@@ -2316,7 +2316,7 @@ returned.
<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#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>
@@ -2432,7 +2432,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -2653,7 +2653,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -2919,7 +2919,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -3025,7 +3025,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -3127,7 +3127,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -3229,7 +3229,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -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>
<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>
@@ -3370,7 +3370,7 @@ In the future, this functionality might get more generic and some of the require
</dt>
<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>
@@ -3436,7 +3436,109 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -3610,7 +3712,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -3789,7 +3891,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -3997,7 +4099,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -4176,7 +4278,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -4355,7 +4457,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -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>
@@ -4978,7 +4978,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -5068,7 +5068,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -5174,7 +5174,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -5281,7 +5281,121 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -5309,6 +5423,10 @@ In the future, this functionality might get more generic and some of the require
<h5>Returns:</h5>
<div class="param-desc">
valid object or null if the content cannot be parsed as JSON
</div>
<dl>
@@ -5318,6 +5436,9 @@ In the future, this functionality might get more generic and some of the require
<dd>
<span class="param-type">*</span>
|
<span class="param-type">null</span>
</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>
<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>
@@ -5590,7 +5711,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -5760,7 +5881,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -5927,7 +6048,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -6033,7 +6154,7 @@ In the future, this functionality might get more generic and some of the require
<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#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>
@@ -6213,7 +6334,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -6483,7 +6604,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -6638,7 +6759,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -6796,7 +6917,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -6966,7 +7087,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -7133,7 +7254,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -7288,7 +7409,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -7446,7 +7567,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -7616,7 +7737,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -8064,7 +8185,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -8222,7 +8343,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -8392,7 +8513,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -8498,7 +8619,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -8600,7 +8721,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -8709,7 +8830,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -8880,7 +9001,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -9088,7 +9209,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -9190,7 +9311,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -9296,7 +9417,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -9398,7 +9519,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -9589,7 +9710,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -9815,7 +9936,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -10111,7 +10232,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -10340,7 +10461,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -10538,7 +10659,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -10736,7 +10857,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -10934,7 +11055,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11040,7 +11161,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11190,7 +11311,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11296,7 +11417,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11390,7 +11511,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11496,7 +11617,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11602,7 +11723,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11708,7 +11829,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11863,7 +11984,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -11969,7 +12090,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -12077,7 +12198,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@@ -12536,7 +12657,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -12716,7 +12837,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -12896,7 +13017,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -13091,7 +13212,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -13193,7 +13314,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -13425,7 +13546,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -13704,7 +13825,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -13884,7 +14005,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -14044,7 +14165,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -14286,7 +14407,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -14497,7 +14618,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
@@ -14708,7 +14829,7 @@ This is a low-level method, for notes and branches use `note.deleteNote()` and '
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_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>
File diff suppressed because it is too large Load Diff
+186 -1
View File
@@ -240,7 +240,7 @@ available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line537">line 537</a>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line579">line 579</a>
</li></ul></dd>
@@ -6381,6 +6381,191 @@ if some action needs to happen on only one specific instance.
<h4 class="name" id="runOnFrontend"><span class="type-signature"></span>runOnFrontend<span class="signature">(script, params)</span><span class="type-signature"> &rarr; {undefined}</span></h4>
<div class="description">
Executes given anonymous function on the frontend(s).
Internally this serializes the anonymous function into string and sends it to frontend(s) via WebSocket.
Note that there can be multiple connected frontend instances (e.g. in different tabs). In such case, all
instances execute the given function.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>script</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="description last">script to be executed on the frontend</td>
</tr>
<tr>
<td class="name"><code>params</code></td>
<td class="type">
<span class="param-type">Array.&lt;?></span>
</td>
<td class="description last">list of parameters to the anonymous function to be sent to frontend</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line543">line 543</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
- no return value is provided.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">undefined</span>
</dd>
</dl>
<h4 class="name" id="searchForNote"><span class="type-signature"></span>searchForNote<span class="signature">(query, searchParams<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {<a href="BNote.html">BNote</a>|null}</span></h4>
@@ -0,0 +1,289 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: becca/entities/battachment.js</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">Source: becca/entities/battachment.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>"use strict";
const utils = require('../../services/utils');
const dateUtils = require('../../services/date_utils');
const AbstractBeccaEntity = require("./abstract_becca_entity");
const sql = require("../../services/sql");
const protectedSessionService = require("../../services/protected_session");
const log = require("../../services/log");
const attachmentRoleToNoteTypeMapping = {
'image': 'image'
};
/**
* Attachment represent data related/attached to the note. Conceptually similar to attributes, but intended for
* larger amounts of data and generally not accessible to the user.
*
* @extends AbstractBeccaEntity
*/
class BAttachment extends AbstractBeccaEntity {
static get entityName() { return "attachments"; }
static get primaryKeyName() { return "attachmentId"; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId",
"utcDateScheduledForErasureSince", "utcDateModified"]; }
constructor(row) {
super();
if (!row.ownerId?.trim()) {
throw new Error("'ownerId' must be given to initialize a Attachment entity");
} else if (!row.role?.trim()) {
throw new Error("'role' must be given to initialize a Attachment entity");
} else if (!row.mime?.trim()) {
throw new Error("'mime' must be given to initialize a Attachment entity");
} else if (!row.title?.trim()) {
throw new Error("'title' must be given to initialize a Attachment entity");
}
/** @type {string} */
this.attachmentId = row.attachmentId;
/** @type {string} either noteId or revisionId to which this attachment belongs */
this.ownerId = row.ownerId;
/** @type {string} */
this.role = row.role;
/** @type {string} */
this.mime = row.mime;
/** @type {string} */
this.title = row.title;
/** @type {int} */
this.position = row.position;
/** @type {string} */
this.blobId = row.blobId;
/** @type {boolean} */
this.isProtected = !!row.isProtected;
/** @type {string} */
this.dateModified = row.dateModified;
/** @type {string} */
this.utcDateModified = row.utcDateModified;
/** @type {string} */
this.utcDateScheduledForErasureSince = row.utcDateScheduledForErasureSince;
/** @type {int} optionally added to the entity */
this.contentLength = row.contentLength;
this.decrypt();
}
/** @returns {BAttachment} */
copy() {
return new BAttachment({
ownerId: this.ownerId,
role: this.role,
mime: this.mime,
title: this.title,
blobId: this.blobId,
isProtected: this.isProtected
});
}
/** @returns {BNote} */
getNote() {
return this.becca.notes[this.ownerId];
}
/** @returns {boolean} true if the note has string content (not binary) */
hasStringContent() {
return utils.isStringNote(this.type, this.mime);
}
isContentAvailable() {
return !this.attachmentId // new attachment which was not encrypted yet
|| !this.isProtected
|| protectedSessionService.isProtectedSessionAvailable()
}
getTitleOrProtected() {
return this.isContentAvailable() ? this.title : '[protected]';
}
decrypt() {
if (!this.isProtected || !this.attachmentId) {
this.isDecrypted = true;
return;
}
if (!this.isDecrypted &amp;&amp; protectedSessionService.isProtectedSessionAvailable()) {
try {
this.title = protectedSessionService.decryptString(this.title);
this.isDecrypted = true;
}
catch (e) {
log.error(`Could not decrypt attachment ${this.attachmentId}: ${e.message} ${e.stack}`);
}
}
}
/** @returns {string|Buffer} */
getContent() {
return this._getContent();
}
/**
* @param content
* @param {object} [opts]
* @param {object} [opts.forceSave=false] - will also save this BAttachment entity
* @param {object} [opts.forceFrontendReload=false] - override frontend heuristics on when to reload, instruct to reload
*/
setContent(content, opts) {
this._setContent(content, opts);
}
/** @returns {{note: BNote, branch: BBranch}} */
convertToNote() {
if (this.type === 'search') {
throw new Error(`Note of type search cannot have child notes`);
}
if (!this.getNote()) {
throw new Error("Cannot find note of this attachment. It is possible that this is note revision's attachment. " +
"Converting note revision's attachments to note is not (yet) supported.");
}
if (!(this.role in attachmentRoleToNoteTypeMapping)) {
throw new Error(`Mapping from attachment role '${this.role}' to note's type is not defined`);
}
if (!this.isContentAvailable()) { // isProtected is the same for attachment
throw new Error(`Cannot convert protected attachment outside of protected session`);
}
const noteService = require('../../services/notes');
const { note, branch } = noteService.createNewNote({
parentNoteId: this.ownerId,
title: this.title,
type: attachmentRoleToNoteTypeMapping[this.role],
mime: this.mime,
content: this.getContent(),
isProtected: this.isProtected
});
this.markAsDeleted();
const parentNote = this.getNote();
if (this.role === 'image' &amp;&amp; parentNote.type === 'text') {
const origContent = parentNote.getContent();
const oldAttachmentUrl = `api/attachments/${this.attachmentId}/image/`;
const newNoteUrl = `api/images/${note.noteId}/`;
const fixedContent = utils.replaceAll(origContent, oldAttachmentUrl, newNoteUrl);
if (fixedContent !== origContent) {
parentNote.setContent(fixedContent);
}
noteService.asyncPostProcessContent(note, fixedContent);
}
return { note, branch };
}
getFileName() {
const type = this.role === 'image' ? 'image' : 'file';
return utils.formatDownloadTitle(this.title, type, this.mime);
}
beforeSaving() {
super.beforeSaving();
if (this.position === undefined || this.position === null) {
this.position = 10 + sql.getValue(`SELECT COALESCE(MAX(position), 0)
FROM attachments
WHERE ownerId = ?`, [this.noteId]);
}
this.dateModified = dateUtils.localNowDateTime();
this.utcDateModified = dateUtils.utcNowDateTime();
}
getPojo() {
return {
attachmentId: this.attachmentId,
ownerId: this.ownerId,
role: this.role,
mime: this.mime,
title: this.title,
position: this.position,
blobId: this.blobId,
isProtected: !!this.isProtected,
isDeleted: false,
dateModified: this.dateModified,
utcDateModified: this.utcDateModified,
utcDateScheduledForErasureSince: this.utcDateScheduledForErasureSince,
contentLength: this.contentLength
};
}
getPojoToSave() {
const pojo = this.getPojo();
delete pojo.contentLength;
if (pojo.isProtected) {
if (this.isDecrypted) {
pojo.title = protectedSessionService.encrypt(pojo.title);
}
else {
// updating protected note outside of protected session means we will keep original ciphertexts
delete pojo.title;
}
}
return pojo;
}
}
module.exports = BAttachment;
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-sql.html">sql</a></li></ul><h3>Classes</h3><ul><li><a href="AbstractBeccaEntity.html">AbstractBeccaEntity</a></li><li><a href="BAttachment.html">BAttachment</a></li><li><a href="BAttribute.html">BAttribute</a></li><li><a href="BBranch.html">BBranch</a></li><li><a href="BEtapiToken.html">BEtapiToken</a></li><li><a href="BNote.html">BNote</a></li><li><a href="BOption.html">BOption</a></li><li><a href="BRecentNote.html">BRecentNote</a></li><li><a href="BRevision.html">BRevision</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</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>
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: becca/entities/bblob.js</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">Source: becca/entities/bblob.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>class BBlob {
static get entityName() { return "blobs"; }
static get primaryKeyName() { return "blobId"; }
static get hashedProperties() { return ["blobId", "content"]; }
constructor(row) {
/** @type {string} */
this.blobId = row.blobId;
/** @type {string|Buffer} */
this.content = row.content;
/** @type {int} */
this.contentLength = row.contentLength;
/** @type {string} */
this.dateModified = row.dateModified;
/** @type {string} */
this.utcDateModified = row.utcDateModified;
}
getPojo() {
return {
blobId: this.blobId,
content: this.content,
contentLength: this.contentLength,
dateModified: this.dateModified,
utcDateModified: this.utcDateModified
};
}
}
module.exports = BBlob;
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-sql.html">sql</a></li></ul><h3>Classes</h3><ul><li><a href="AbstractBeccaEntity.html">AbstractBeccaEntity</a></li><li><a href="BAttachment.html">BAttachment</a></li><li><a href="BAttribute.html">BAttribute</a></li><li><a href="BBranch.html">BBranch</a></li><li><a href="BEtapiToken.html">BEtapiToken</a></li><li><a href="BNote.html">BNote</a></li><li><a href="BOption.html">BOption</a></li><li><a href="BRecentNote.html">BRecentNote</a></li><li><a href="BRevision.html">BRevision</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</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>
+30 -16
View File
@@ -239,12 +239,9 @@ class BNote extends AbstractBeccaEntity {
return this._getContent();
}
/** @returns {{dateModified, utcDateModified}} */
getContentMetadata() {
return sql.getRow(`SELECT dateModified, utcDateModified FROM blobs WHERE blobId = ?`, [this.blobId]);
}
/** @returns {*} */
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent();
@@ -255,6 +252,16 @@ class BNote extends AbstractBeccaEntity {
return JSON.parse(content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
/**
* @param content
* @param {object} [opts]
@@ -1158,7 +1165,7 @@ class BNote extends AbstractBeccaEntity {
}
/** @returns {BAttachment[]} */
getAttachmentByRole(role) {
getAttachmentsByRole(role) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
@@ -1169,6 +1176,18 @@ class BNote extends AbstractBeccaEntity {
.map(row => new BAttachment(row));
}
/** @returns {BAttachment} */
getAttachmentByTitle(title) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND title = ?
AND isDeleted = 0
ORDER BY position`, [this.noteId, title])
.map(row => new BAttachment(row))[0];
}
/**
* Gives all possible note paths leading to this note. Paths containing search note are ignored (could form cycles)
*
@@ -1599,7 +1618,6 @@ class BNote extends AbstractBeccaEntity {
saveRevision() {
return sql.transactional(() => {
let noteContent = this.getContent();
const contentMetadata = this.getContentMetadata();
const revision = new BRevision({
noteId: this.noteId,
@@ -1608,14 +1626,10 @@ class BNote extends AbstractBeccaEntity {
type: this.type,
mime: this.mime,
isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified
? this.utcDateModified
: contentMetadata.utcDateModified,
utcDateLastEdited: this.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: this.dateModified > contentMetadata.dateModified
? this.dateModified
: contentMetadata.dateModified,
dateLastEdited: this.dateModified,
dateCreated: dateUtils.localNowDateTime()
}, true);
@@ -1638,10 +1652,10 @@ class BNote extends AbstractBeccaEntity {
noteContent = noteContent.replaceAll(new RegExp(`href="[^"]*attachmentId=${noteAttachment.attachmentId}[^"]*"`, 'gi'),
`href="api/attachments/${revisionAttachment.attachmentId}/download"`);
}
revision.setContent(noteContent, {forceSave: true});
}
revision.setContent(noteContent);
return revision;
});
}
@@ -0,0 +1,203 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: becca/entities/brevision.js</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">Source: becca/entities/brevision.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>"use strict";
const protectedSessionService = require('../../services/protected_session');
const utils = require('../../services/utils');
const dateUtils = require('../../services/date_utils');
const becca = require('../becca');
const AbstractBeccaEntity = require("./abstract_becca_entity");
const sql = require("../../services/sql");
const BAttachment = require("./battachment");
/**
* Revision represents a snapshot of note's title and content at some point in the past.
* It's used for seamless note versioning.
*
* @extends AbstractBeccaEntity
*/
class BRevision extends AbstractBeccaEntity {
static get entityName() { return "revisions"; }
static get primaryKeyName() { return "revisionId"; }
static get hashedProperties() { return ["revisionId", "noteId", "title", "isProtected", "dateLastEdited", "dateCreated",
"utcDateLastEdited", "utcDateCreated", "utcDateModified", "blobId"]; }
constructor(row, titleDecrypted = false) {
super();
/** @type {string} */
this.revisionId = row.revisionId;
/** @type {string} */
this.noteId = row.noteId;
/** @type {string} */
this.type = row.type;
/** @type {string} */
this.mime = row.mime;
/** @type {boolean} */
this.isProtected = !!row.isProtected;
/** @type {string} */
this.title = row.title;
/** @type {string} */
this.blobId = row.blobId;
/** @type {string} */
this.dateLastEdited = row.dateLastEdited;
/** @type {string} */
this.dateCreated = row.dateCreated;
/** @type {string} */
this.utcDateLastEdited = row.utcDateLastEdited;
/** @type {string} */
this.utcDateCreated = row.utcDateCreated;
/** @type {string} */
this.utcDateModified = row.utcDateModified;
/** @type {int} */
this.contentLength = row.contentLength;
if (this.isProtected &amp;&amp; !titleDecrypted) {
this.title = protectedSessionService.isProtectedSessionAvailable()
? protectedSessionService.decryptString(this.title)
: "[protected]";
}
}
getNote() {
return becca.notes[this.noteId];
}
/** @returns {boolean} true if the note has string content (not binary) */
hasStringContent() {
return utils.isStringNote(this.type, this.mime);
}
isContentAvailable() {
return !this.revisionId // new note which was not encrypted yet
|| !this.isProtected
|| protectedSessionService.isProtectedSessionAvailable()
}
/*
* Note revision content has quite special handling - it's not a separate entity, but a lazily loaded
* part of Revision entity with its own sync. The reason behind this hybrid design is that
* content can be quite large, and it's not necessary to load it / fill memory for any note access even
* if we don't need a content, especially for bulk operations like search.
*
* This is the same approach as is used for Note's content.
*/
/** @returns {string|Buffer} */
getContent() {
return this._getContent();
}
/**
* @param content
* @param {object} [opts]
* @param {object} [opts.forceSave=false] - will also save this BRevision entity
*/
setContent(content, opts) {
this._setContent(content, opts);
}
/** @returns {BAttachment[]} */
getAttachments() {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND isDeleted = 0`, [this.revisionId])
.map(row => new BAttachment(row));
}
beforeSaving() {
super.beforeSaving();
this.utcDateModified = dateUtils.utcNowDateTime();
}
getPojo() {
return {
revisionId: this.revisionId,
noteId: this.noteId,
type: this.type,
mime: this.mime,
isProtected: this.isProtected,
title: this.title,
blobId: this.blobId,
dateLastEdited: this.dateLastEdited,
dateCreated: this.dateCreated,
utcDateLastEdited: this.utcDateLastEdited,
utcDateCreated: this.utcDateCreated,
utcDateModified: this.utcDateModified,
content: this.content, // used when retrieving full note revision to frontend
contentLength: this.contentLength
};
}
getPojoToSave() {
const pojo = this.getPojo();
delete pojo.content; // not getting persisted
delete pojo.contentLength; // not getting persisted
if (pojo.isProtected) {
if (protectedSessionService.isProtectedSessionAvailable()) {
pojo.title = protectedSessionService.encrypt(this.title);
}
else {
// updating protected note outside of protected session means we will keep original ciphertexts
delete pojo.title;
}
}
return pojo;
}
}
module.exports = BRevision;
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-sql.html">sql</a></li></ul><h3>Classes</h3><ul><li><a href="AbstractBeccaEntity.html">AbstractBeccaEntity</a></li><li><a href="BAttachment.html">BAttachment</a></li><li><a href="BAttribute.html">BAttribute</a></li><li><a href="BBranch.html">BBranch</a></li><li><a href="BEtapiToken.html">BEtapiToken</a></li><li><a href="BNote.html">BNote</a></li><li><a href="BOption.html">BOption</a></li><li><a href="BRecentNote.html">BRecentNote</a></li><li><a href="BRevision.html">BRevision</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</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>
@@ -557,6 +557,48 @@ function BackendScriptApi(currentNote, apiParams) {
*/
this.exportSubtreeToZipFile = async (noteId, format, zipFilePath) => await exportService.exportToZipFile(noteId, format, zipFilePath);
/**
* Executes given anonymous function on the frontend(s).
* Internally this serializes the anonymous function into string and sends it to frontend(s) via WebSocket.
* Note that there can be multiple connected frontend instances (e.g. in different tabs). In such case, all
* instances execute the given function.
*
* @method
* @param {string} script - script to be executed on the frontend
* @param {Array.&lt;?>} params - list of parameters to the anonymous function to be sent to frontend
* @returns {undefined} - no return value is provided.
*/
this.runOnFrontend = async (script, params = []) => {
if (typeof script === "function") {
script = script.toString();
}
ws.sendMessageToAllClients({
type: 'execute-script',
script: script,
params: prepareParams(params),
startNoteId: this.startNote.noteId,
currentNoteId: this.currentNote.noteId,
originEntityName: "notes", // currently there's no other entity on the frontend which can trigger event
originEntityId: this.originEntity?.noteId || null
});
function prepareParams(params) {
if (!params) {
return params;
}
return params.map(p => {
if (typeof p === "function") {
return `!@#Function: ${p.toString()}`;
}
else {
return p;
}
});
}
};
/**
* This object contains "at your risk" and "no BC guarantees" objects for advanced use cases.
*
+2 -2
View File
@@ -54,7 +54,7 @@ const LOG_ALL_QUERIES = false;
});
function insert(tableName, rec, replace = false) {
const keys = Object.keys(rec);
const keys = Object.keys(rec || {});
if (keys.length === 0) {
log.error(`Can't insert empty object into table ${tableName}`);
return;
@@ -81,7 +81,7 @@ function replace(tableName, rec) {
}
function upsert(tableName, primaryKey, rec) {
const keys = Object.keys(rec);
const keys = Object.keys(rec || {});
if (keys.length === 0) {
log.error(`Can't upsert empty object into table ${tableName}`);
return;
+1 -1
View File
@@ -912,7 +912,7 @@ and relation (representing named relationship between source and target note)</d
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
+1 -1
View File
@@ -1124,7 +1124,7 @@ parents.</div>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
+156 -54
View File
@@ -1168,7 +1168,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line354">line 354</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line359">line 359</a>
</li></ul></dd>
@@ -1274,7 +1274,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line241">line 241</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line246">line 246</a>
</li></ul></dd>
@@ -1376,7 +1376,109 @@
<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#line232">line 232</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line231">line 231</a>
</li></ul></dd>
</dl>
<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>
@@ -1550,7 +1652,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line617">line 617</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line622">line 622</a>
</li></ul></dd>
@@ -1728,7 +1830,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line639">line 639</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line644">line 644</a>
</li></ul></dd>
@@ -1928,7 +2030,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line288">line 288</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line293">line 293</a>
</li></ul></dd>
@@ -2107,7 +2209,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line410">line 410</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line415">line 415</a>
</li></ul></dd>
@@ -2286,7 +2388,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line420">line 420</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line425">line 425</a>
</li></ul></dd>
@@ -2392,7 +2494,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line864">line 864</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line869">line 869</a>
</li></ul></dd>
@@ -2496,7 +2598,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line153">line 153</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line152">line 152</a>
</li></ul></dd>
@@ -2600,7 +2702,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line170">line 170</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line169">line 169</a>
</li></ul></dd>
@@ -2702,7 +2804,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line180">line 180</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line179">line 179</a>
</li></ul></dd>
@@ -2804,7 +2906,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line222">line 222</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line221">line 221</a>
</li></ul></dd>
@@ -2906,7 +3008,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line227">line 227</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line226">line 226</a>
</li></ul></dd>
@@ -3057,7 +3159,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line693">line 693</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line698">line 698</a>
</li></ul></dd>
@@ -3212,7 +3314,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line717">line 717</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line722">line 722</a>
</li></ul></dd>
@@ -3379,7 +3481,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line503">line 503</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line508">line 508</a>
</li></ul></dd>
@@ -3487,7 +3589,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line859">line 859</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line864">line 864</a>
</li></ul></dd>
@@ -3589,7 +3691,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line759">line 759</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line764">line 764</a>
</li></ul></dd>
@@ -3763,7 +3865,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line606">line 606</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line611">line 611</a>
</li></ul></dd>
@@ -3941,7 +4043,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line628">line 628</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line633">line 633</a>
</li></ul></dd>
@@ -4141,7 +4243,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line275">line 275</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line280">line 280</a>
</li></ul></dd>
@@ -4296,7 +4398,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line687">line 687</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line692">line 692</a>
</li></ul></dd>
@@ -4451,7 +4553,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line711">line 711</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line716">line 716</a>
</li></ul></dd>
@@ -4618,7 +4720,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line495">line 495</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line500">line 500</a>
</li></ul></dd>
@@ -4773,7 +4875,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line699">line 699</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line704">line 704</a>
</li></ul></dd>
@@ -4928,7 +5030,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line723">line 723</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line728">line 728</a>
</li></ul></dd>
@@ -5095,7 +5197,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line569">line 569</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line574">line 574</a>
</li></ul></dd>
@@ -5201,7 +5303,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line145">line 145</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line144">line 144</a>
</li></ul></dd>
@@ -5303,7 +5405,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line160">line 160</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line159">line 159</a>
</li></ul></dd>
@@ -5405,7 +5507,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line188">line 188</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line187">line 187</a>
</li></ul></dd>
@@ -5507,7 +5609,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line193">line 193</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line192">line 192</a>
</li></ul></dd>
@@ -5658,7 +5760,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line705">line 705</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line710">line 710</a>
</li></ul></dd>
@@ -5813,7 +5915,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line735">line 735</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line740">line 740</a>
</li></ul></dd>
@@ -5983,7 +6085,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line745">line 745</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line750">line 750</a>
</li></ul></dd>
@@ -6134,7 +6236,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line729">line 729</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line734">line 734</a>
</li></ul></dd>
@@ -6301,7 +6403,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line577">line 577</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line582">line 582</a>
</li></ul></dd>
@@ -6407,7 +6509,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line908">line 908</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line913">line 913</a>
</li></ul></dd>
@@ -6585,7 +6687,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line376">line 376</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line381">line 381</a>
</li></ul></dd>
@@ -6691,7 +6793,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line849">line 849</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line854">line 854</a>
</li></ul></dd>
@@ -6797,7 +6899,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line839">line 839</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line844">line 844</a>
</li></ul></dd>
@@ -6971,7 +7073,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line586">line 586</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line591">line 591</a>
</li></ul></dd>
@@ -7077,7 +7179,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line175">line 175</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line174">line 174</a>
</li></ul></dd>
@@ -7228,7 +7330,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line655">line 655</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line660">line 660</a>
</li></ul></dd>
@@ -7406,7 +7508,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line597">line 597</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line602">line 602</a>
</li></ul></dd>
@@ -7561,7 +7663,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line649">line 649</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line654">line 654</a>
</li></ul></dd>
@@ -7716,7 +7818,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line675">line 675</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line680">line 680</a>
</li></ul></dd>
@@ -7871,7 +7973,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line681">line 681</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line686">line 686</a>
</li></ul></dd>
@@ -7979,7 +8081,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line832">line 832</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line837">line 837</a>
</li></ul></dd>
@@ -8063,7 +8165,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line429">line 429</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line434">line 434</a>
</li></ul></dd>
@@ -8157,7 +8259,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line903">line 903</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line908">line 908</a>
</li></ul></dd>
@@ -8263,7 +8365,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line895">line 895</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line900">line 900</a>
</li></ul></dd>
@@ -8520,7 +8622,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line661">line 661</a>
<a href="entities_fnote.js.html">entities/fnote.js</a>, <a href="entities_fnote.js.html#line666">line 666</a>
</li></ul></dd>
@@ -8588,7 +8690,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: entities/fattachment.js</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">Source: entities/fattachment.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>class FAttachment {
constructor(froca, row) {
/** @type {Froca} */
this.froca = froca;
this.update(row);
}
update(row) {
/** @type {string} */
this.attachmentId = row.attachmentId;
/** @type {string} */
this.ownerId = row.ownerId;
/** @type {string} */
this.role = row.role;
/** @type {string} */
this.mime = row.mime;
/** @type {string} */
this.title = row.title;
/** @type {string} */
this.dateModified = row.dateModified;
/** @type {string} */
this.utcDateModified = row.utcDateModified;
/** @type {string} */
this.utcDateScheduledForErasureSince = row.utcDateScheduledForErasureSince;
/** @type {int} optionally added to the entity */
this.contentLength = row.contentLength;
this.froca.attachments[this.attachmentId] = this;
}
/** @returns {FNote} */
getNote() {
return this.froca.notes[this.ownerId];
}
/** @return {FBlob} */
async getBlob() {
return await this.froca.getBlob('attachments', this.attachmentId);
}
}
export default FAttachment;
</code></pre>
</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>
@@ -116,7 +116,7 @@ export default FAttribute;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
+90
View File
@@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: entities/fblob.js</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">Source: entities/fblob.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>export default class FBlob {
constructor(row) {
/** @type {string} */
this.blobId = row.blobId;
/**
* can either contain the whole content (in e.g. string notes), only part (large text notes) or nothing at all (binary notes, images)
* @type {string}
*/
this.content = row.content;
this.contentLength = row.contentLength;
/** @type {string} */
this.dateModified = row.dateModified;
/** @type {string} */
this.utcDateModified = row.utcDateModified;
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
if (!this.content || !this.content.trim()) {
return null;
}
return JSON.parse(this.content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
}
</code></pre>
</article>
</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>
+1 -1
View File
@@ -100,7 +100,7 @@ export default FBranch;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
+13 -4
View File
@@ -148,10 +148,9 @@ class FNote {
}
async getContent() {
// we're not caching content since these objects are in froca and as such pretty long-lived
const note = await server.get(`notes/${this.noteId}`);
const blob = await this.getBlob();
return note.content;
return blob?.content;
}
async getJsonContent() {
@@ -265,6 +264,12 @@ class FNote {
return this.attachments;
}
/** @returns {Promise&lt;FAttachment[]>} */
async getAttachmentsByRole(role) {
return (await this.getAttachments())
.filter(attachment => attachment.role === role);
}
/** @returns {Promise&lt;FAttachment>} */
async getAttachmentById(attachmentId) {
const attachments = await this.getAttachments();
@@ -999,6 +1004,10 @@ class FNote {
isOptions() {
return this.noteId.startsWith("_options");
}
async getMetadata() {
return await server.get(`notes/${this.noteId}/metadata`);
}
}
export default FNote;
@@ -1012,7 +1021,7 @@ export default FNote;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
+352
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>
+1 -1
View File
@@ -50,7 +50,7 @@
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
@@ -42,6 +42,7 @@ import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js";
import shortcutService from "./shortcuts.js";
import dialogService from "./dialog.js";
/**
* &lt;p>This is the main frontend API interface for scripts. All the properties and methods are published in the "api" object
@@ -286,7 +287,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.parseDate = utils.parseDate;
/**
* Show an info message to the user.
* Show an info toast message to the user.
*
* @method
* @param {string} message
@@ -294,13 +295,43 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.showMessage = toastService.showMessage;
/**
* Show an error message to the user.
* Show an error toast message to the user.
*
* @method
* @param {string} message
*/
this.showError = toastService.showError;
/**
* Show an info dialog to the user.
*
* @method
* @param {string} message
* @returns {Promise}
*/
this.showInfoDialog = dialogService.info;
/**
* Show confirm dialog to the user.
*
* @method
* @param {string} message
* @returns {Promise&lt;boolean>} promise resolving to true if the user confirmed
*/
this.showConfirmDialog = dialogService.confirm;
/**
* Show prompt dialog to the user.
*
* @method
* @param {object} props
* @param {string} props.title
* @param {string} props.message
* @param {string} props.defaultValue
* @returns {Promise&lt;string>} promise resolving to the answer provided by the user
*/
this.showPromptDialog = dialogService.prompt;
/**
* Trigger command. This is a very low-level API which should be avoided if possible.
*
@@ -329,6 +360,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @param {boolean} [params.showNotePath=false] - show also whole note's path as part of the link
* @param {boolean} [params.showNoteIcon=false] - show also note icon before the title
* @param {string} [params.title=] - custom link tile with note's title as default
* @returns {jQuery} - jQuery element with the link (wrapped in &lt;span>)
*/
this.createLink = linkService.createLink;
@@ -569,7 +601,7 @@ export default FrontendScriptApi;
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FAttribute.html">FAttribute</a></li><li><a href="FBranch.html">FBranch</a></li><li><a href="FNote.html">FNote</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getJsonContent">getJsonContent</a></li><li><a href="global.html#getJsonContentSafely">getJsonContentSafely</a></li></ul>
</nav>
<br class="clear">
+3
View File
@@ -13,6 +13,9 @@ appIconService.installLocalAppIcon();
require('electron-dl')({ saveAs: true });
// needed for excalidraw export https://github.com/zadam/trilium/issues/4271
app.commandLine.appendSwitch("enable-experimental-web-platform-features");
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
+42 -42
View File
@@ -5,8 +5,8 @@
}
/*
* CKEditor 5 (v39.0.1) content styles.
* Generated on Thu, 10 Aug 2023 09:21:07 GMT.
* CKEditor 5 (v39.0.2) content styles.
* Generated on Wed, 06 Sep 2023 07:32:15 GMT.
* For more information, check out https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html
*/
@@ -197,6 +197,20 @@
.ck-content .todo-list .todo-list__label .todo-list__label__description {
vertical-align: middle;
}
/* @ckeditor/ckeditor5-image/theme/imageresize.css */
.ck-content .image.image_resized {
max-width: 100%;
display: block;
box-sizing: border-box;
}
/* @ckeditor/ckeditor5-image/theme/imageresize.css */
.ck-content .image.image_resized img {
width: 100%;
}
/* @ckeditor/ckeditor5-image/theme/imageresize.css */
.ck-content .image.image_resized > figcaption {
display: block;
}
/* @ckeditor/ckeditor5-image/theme/image.css */
.ck-content .image {
display: table;
@@ -234,20 +248,6 @@
flex-shrink: 1;
max-width: 100%;
}
/* @ckeditor/ckeditor5-image/theme/imageresize.css */
.ck-content .image.image_resized {
max-width: 100%;
display: block;
box-sizing: border-box;
}
/* @ckeditor/ckeditor5-image/theme/imageresize.css */
.ck-content .image.image_resized img {
width: 100%;
}
/* @ckeditor/ckeditor5-image/theme/imageresize.css */
.ck-content .image.image_resized > figcaption {
display: block;
}
/* @ckeditor/ckeditor5-image/theme/imagecaption.css */
.ck-content .image > figcaption {
display: table-caption;
@@ -259,32 +259,6 @@
font-size: .75em;
outline-offset: -1px;
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-yellow {
background-color: var(--ck-highlight-marker-yellow);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-green {
background-color: var(--ck-highlight-marker-green);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-pink {
background-color: var(--ck-highlight-marker-pink);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-blue {
background-color: var(--ck-highlight-marker-blue);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-red {
color: var(--ck-highlight-pen-red);
background-color: transparent;
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-green {
color: var(--ck-highlight-pen-green);
background-color: transparent;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol {
list-style-type: decimal;
@@ -321,6 +295,32 @@
.ck-content ul ul ul ul {
list-style-type: square;
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-yellow {
background-color: var(--ck-highlight-marker-yellow);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-green {
background-color: var(--ck-highlight-marker-green);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-pink {
background-color: var(--ck-highlight-marker-pink);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-blue {
background-color: var(--ck-highlight-marker-blue);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-red {
color: var(--ck-highlight-pen-red);
background-color: transparent;
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-green {
color: var(--ck-highlight-pen-green);
background-color: transparent;
}
/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
.ck-content .image-style-block-align-left,
.ck-content .image-style-block-align-right {
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -46,7 +46,7 @@
const errors = new eslint().verify(text, {
root: true,
parserOptions: {
ecmaVersion: 2022
ecmaVersion: "latest"
},
extends: ['eslint:recommended', 'airbnb-base'],
env: {
+5 -8
View File
@@ -24,8 +24,10 @@
function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
tt.style.left = (e.clientX + 5) + "px";
var top = Math.max(0, e.clientY - tt.offsetHeight - 5);
var left = Math.max(0, Math.min(e.clientX + 5, tt.ownerDocument.defaultView.innerWidth - tt.offsetWidth));
tt.style.top = top + "px"
tt.style.left = left + "px";
}
CodeMirror.on(document, "mousemove", position);
position(e);
@@ -199,10 +201,6 @@
var anns = annotations[line];
if (!anns) continue;
// filter out duplicate messages
var message = [];
anns = anns.filter(function(item) { return message.indexOf(item.message) > -1 ? false : message.push(item.message) });
var maxSeverity = null;
var tipLabel = state.hasGutter && document.createDocumentFragment();
@@ -220,9 +218,8 @@
__annotation: ann
}));
}
// use original annotations[line] to show multiple messages
if (state.hasGutter)
cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, annotations[line].length > 1,
cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, anns.length > 1,
options.tooltips));
if (options.highlightLines)
+136
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};
}
};
};
});
+90
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);
}
};
};
});
+6 -4
View File
@@ -8259,8 +8259,8 @@
}
function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) {
field.setAttribute("autocorrect", autocorrect ? "" : "off");
field.setAttribute("autocapitalize", autocapitalize ? "" : "off");
field.setAttribute("autocorrect", autocorrect ? "on" : "off");
field.setAttribute("autocapitalize", autocapitalize ? "on" : "off");
field.setAttribute("spellcheck", !!spellcheck);
}
@@ -8275,7 +8275,6 @@
else { te.setAttribute("wrap", "off"); }
// If border: 0; -- iOS fails to open keyboard (issue #1287)
if (ios) { te.style.border = "1px solid black"; }
disableBrowserMagic(te);
return div
}
@@ -8897,6 +8896,7 @@
}
// Old-fashioned briefly-focus-a-textarea hack
var kludge = hiddenTextarea(), te = kludge.firstChild;
disableBrowserMagic(te);
cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
te.value = lastCopied.text.join("\n");
var hadFocus = activeElt(div.ownerDocument);
@@ -9461,6 +9461,8 @@
// The semihidden textarea that is focused when the editor is
// focused, and receives input.
this.textarea = this.wrapper.firstChild;
var opts = this.cm.options;
disableBrowserMagic(this.textarea, opts.spellcheck, opts.autocorrect, opts.autocapitalize);
};
TextareaInput.prototype.screenReaderLabelChanged = function (label) {
@@ -9865,7 +9867,7 @@
addLegacyProps(CodeMirror);
CodeMirror.version = "5.65.9";
CodeMirror.version = "5.65.15";
return CodeMirror;
+6 -4
View File
@@ -218,7 +218,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
},
indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine && isTopScope(state.context))
return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
var closing = firstChar == ctx.type;
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
@@ -512,8 +513,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
name: "clike",
keywords: words("abstract as async await base break case catch checked class const continue" +
" default delegate do else enum event explicit extern finally fixed for" +
" foreach goto if implicit in interface internal is lock namespace new" +
" operator out override params private protected public readonly ref return sealed" +
" foreach goto if implicit in init interface internal is lock namespace new" +
" operator out override params private protected public readonly record ref required return sealed" +
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
" global group into join let orderby partial remove select set value var yield"),
@@ -522,7 +523,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
" UInt64 bool byte char decimal double short int long object" +
" sbyte float string ushort uint ulong"),
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
defKeywords: words("class interface namespace struct var"),
defKeywords: words("class interface namespace record struct var"),
typeFirstDefinitions: true,
atoms: words("true false null"),
hooks: {
@@ -613,6 +614,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return state.tokenize(stream, state);
},
"'": function(stream) {
if (stream.match(/^(\\[^'\s]+|[^\\'])'/)) return "string-2"
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
return "atom";
},
+4 -4
View File
@@ -12,10 +12,10 @@
"use strict";
var keywords = ("this super static final const abstract class extends external factory " +
"implements mixin get native set typedef with enum throw rethrow " +
"assert break case continue default in return new deferred async await covariant " +
"try catch finally do else for if switch while import library export " +
"part of show hide is as extension on yield late required").split(" ");
"implements mixin get native set typedef with enum throw rethrow assert break case " +
"continue default in return new deferred async await covariant try catch finally " +
"do else for if switch while import library export part of show hide is as extension " +
"on yield late required sealed base interface when inline").split(" ");
var blockKeywords = "try catch finally do else for if switch while".split(" ");
var atoms = "true false null".split(" ");
var builtins = "void bool num int double dynamic var String Null Never".split(" ");
+1 -1
View File
@@ -779,7 +779,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "async" ||
(type == "variable" &&
(value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
cx.stream.match(/^\s+#?[\w$\xa1-\uffff]/, false))) {
cx.marked = "keyword";
return cont(classBody);
}
+1 -1
View File
@@ -24,7 +24,7 @@ CodeMirror.defineSimpleMode("nsis",{
{ regex: /`(?:[^\\`]|\\.)*`?/, token: "string" },
// Compile Time Commands
{regex: /^\s*(?:\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|error|execute|finalize|getdllversion|gettlbversion|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|uninstfinalize|verbose|warning))\b/i, token: "keyword"},
{regex: /^\s*(?:\!(addincludedir|addplugindir|appendfile|assert|cd|define|delfile|echo|error|execute|finalize|getdllversion|gettlbversion|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|uninstfinalize|verbose|warning))\b/i, token: "keyword"},
// Conditional Compilation
{regex: /^\s*(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/i, token: "keyword", indent: true},
-3
View File
@@ -31,8 +31,6 @@ CodeMirror.defineMode("pegjs", function (config) {
};
},
token: function (stream, state) {
if (stream)
//check for state changes
if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) {
state.stringType = stream.peek();
@@ -43,7 +41,6 @@ CodeMirror.defineMode("pegjs", function (config) {
state.inComment = true;
}
//return state
if (state.inString) {
while (state.inString && !stream.eol()) {
if (stream.peek() === state.stringType) {
+3 -3
View File
@@ -20,7 +20,7 @@
"def", "del", "elif", "else", "except", "finally",
"for", "from", "global", "if", "import",
"lambda", "pass", "raise", "return",
"try", "while", "with", "yield", "in"];
"try", "while", "with", "yield", "in", "False", "True"];
var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
"classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
"enumerate", "eval", "filter", "float", "format", "frozenset",
@@ -60,7 +60,7 @@
if (py3) {
// since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
myKeywords = myKeywords.concat(["nonlocal", "None", "aiter", "anext", "async", "await", "breakpoint", "match", "case"]);
myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
var stringPrefixes = new RegExp("^(([rbuf]|(br)|(rb)|(fr)|(rf))?('{3}|\"{3}|['\"]))", "i");
} else {
@@ -68,7 +68,7 @@
myKeywords = myKeywords.concat(["exec", "print"]);
myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
"file", "intern", "long", "raw_input", "reduce", "reload",
"unichr", "unicode", "xrange", "False", "True", "None"]);
"unichr", "unicode", "xrange", "None"]);
var stringPrefixes = new RegExp("^(([rubf]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
}
var keywords = wordRegexp(myKeywords);
+12 -11
View File
@@ -33,6 +33,9 @@ CodeMirror.defineMode("sparql", function(config) {
"true", "false", "with",
"data", "copy", "to", "move", "add", "create", "drop", "clear", "load", "into"]);
var operatorChars = /[*+\-<>=&|\^\/!\?]/;
var PN_CHARS = "[A-Za-z_\\-0-9]";
var PREFIX_START = new RegExp("[A-Za-z]");
var PREFIX_REMAINDER = new RegExp("((" + PN_CHARS + "|\\.)*(" + PN_CHARS + "))?:");
function tokenBase(stream, state) {
var ch = stream.next();
@@ -71,20 +74,18 @@ CodeMirror.defineMode("sparql", function(config) {
stream.eatWhile(/[a-z\d\-]/i);
return "meta";
}
else {
stream.eatWhile(/[_\w\d]/);
if (stream.eat(":")) {
else if (PREFIX_START.test(ch) && stream.match(PREFIX_REMAINDER)) {
eatPnLocal(stream);
return "atom";
}
var word = stream.current();
if (ops.test(word))
return "builtin";
else if (keywords.test(word))
return "keyword";
else
return "variable";
}
stream.eatWhile(/[_\w\d]/);
var word = stream.current();
if (ops.test(word))
return "builtin";
else if (keywords.test(word))
return "keyword";
else
return "variable";
}
function eatPnLocal(stream) {
+12 -14
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -85,7 +85,7 @@ CodeMirror.defineMode("yaml", function() {
}
/* pairs (associative arrays) -> key */
if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) {
if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^\s,\[\]{}#&*!|>'"%@`])[^#:]*(?=:($|\s))/)) {
state.pair = true;
state.keyCol = stream.indentation();
return "atom";
+147 -146
View File
File diff suppressed because one or more lines are too long
+497 -566
View File
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -2,7 +2,7 @@
"name": "trilium",
"productName": "Trilium Notes",
"description": "Trilium Notes",
"version": "0.61.5-beta",
"version": "0.61.9-beta",
"license": "AGPL-3.0-only",
"main": "electron.js",
"bin": {
@@ -32,18 +32,18 @@
},
"dependencies": {
"@braintree/sanitize-url": "6.0.4",
"@electron/remote": "2.0.10",
"@excalidraw/excalidraw": "0.15.3",
"@electron/remote": "2.0.11",
"@excalidraw/excalidraw": "0.16.1",
"archiver": "5.3.1",
"async-mutex": "0.4.0",
"axios": "1.4.0",
"axios": "1.5.1",
"better-sqlite3": "8.4.0",
"chokidar": "3.5.3",
"cls-hooked": "4.2.2",
"compression": "1.7.4",
"cookie-parser": "1.4.6",
"csurf": "1.11.0",
"dayjs": "1.11.9",
"dayjs": "1.11.10",
"dayjs-plugin-utc": "0.1.2",
"debounce": "1.2.1",
"ejs": "3.1.9",
@@ -53,14 +53,14 @@
"escape-html": "1.0.3",
"express": "4.18.2",
"express-partial-content": "1.0.2",
"express-rate-limit": "6.9.0",
"express-rate-limit": "6.11.0",
"express-session": "1.17.3",
"fs-extra": "11.1.1",
"helmet": "7.0.0",
"html": "1.0.0",
"html2plaintext": "2.1.4",
"http-proxy-agent": "7.0.0",
"https-proxy-agent": "7.0.1",
"https-proxy-agent": "7.0.2",
"image-type": "4.1.0",
"ini": "3.0.1",
"is-animated": "2.0.2",
@@ -68,21 +68,21 @@
"jimp": "0.22.10",
"joplin-turndown-plugin-gfm": "1.0.12",
"jsdom": "22.1.0",
"marked": "7.0.3",
"marked": "9.1.0",
"mime-types": "2.1.35",
"multer": "1.4.5-lts.1",
"node-abi": "3.46.0",
"node-abi": "3.47.0",
"normalize-strings": "1.1.1",
"open": "8.4.1",
"rand-token": "1.0.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"request": "2.88.2",
"rimraf": "5.0.1",
"rimraf": "5.0.5",
"safe-compare": "1.1.4",
"sanitize-filename": "1.6.3",
"sanitize-html": "2.11.0",
"sax": "1.2.4",
"sax": "1.3.0",
"semver": "7.5.4",
"serve-favicon": "2.5.0",
"session-file-store": "1.5.0",
@@ -91,20 +91,20 @@
"tmp": "0.2.1",
"turndown": "7.1.2",
"unescape": "1.0.1",
"ws": "8.13.0",
"ws": "8.14.2",
"xml2js": "0.6.2",
"yauzl": "2.10.0"
},
"devDependencies": {
"cross-env": "7.0.3",
"electron": "25.5.0",
"electron-builder": "24.6.3",
"electron-packager": "17.1.1",
"electron": "25.9.0",
"electron-builder": "24.6.4",
"electron-packager": "17.1.2",
"electron-rebuild": "3.2.9",
"eslint": "8.47.0",
"eslint": "8.50.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-import": "2.28.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-jsonc": "2.9.0",
"eslint-plugin-prettier": "5.0.0",
"esm": "3.2.25",
@@ -112,16 +112,16 @@
"jasmine": "5.1.0",
"jsdoc": "4.0.2",
"jsonc-eslint-parser": "2.3.0",
"lint-staged": "14.0.0",
"lint-staged": "14.0.1",
"lorem-ipsum": "2.0.8",
"nodemon": "3.0.1",
"prettier": "3.0.2",
"prettier": "3.0.3",
"rcedit": "3.1.0",
"webpack": "5.88.2",
"webpack-cli": "5.1.4"
},
"optionalDependencies": {
"electron-installer-debian": "3.1.0"
"electron-installer-debian": "3.2.0"
},
"lint-staged": {
"*.js": "eslint --cache --fix"
+8
View File
@@ -4,6 +4,9 @@ describe("Lexer fulltext", () => {
it("simple lexing", () => {
expect(lex("hello world").fulltextTokens.map(t => t.token))
.toEqual(["hello", "world"]);
expect(lex("hello, world").fulltextTokens.map(t => t.token))
.toEqual(["hello", "world"]);
});
it("use quotes to keep words together", () => {
@@ -147,6 +150,11 @@ describe("Lexer expression", () => {
expect(lex(`# not(#capital) and note.noteId != "root"`).expressionTokens.map(t => t.token))
.toEqual(["#", "not", "(", "#capital", ")", "and", "note", ".", "noteid", "!=", "root"]);
});
it("order by multiple labels", () => {
expect(lex(`# orderby #a,#b`).expressionTokens.map(t => t.token))
.toEqual(["#", "orderby", "#a", ",", "#b"]);
});
});
describe("Lexer invalid queries and edge cases", () => {
+38 -37
View File
@@ -36,9 +36,9 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
expect(rootExp.subExpressions[0].constructor.name).toEqual("PropertyComparisonExp");
expect(rootExp.subExpressions[1].constructor.name).toEqual("OrExp");
expect(rootExp.subExpressions[1].subExpressions[0].constructor.name).toEqual("NoteFlatTextExp");
expect(rootExp.subExpressions[1].subExpressions[0].tokens).toEqual(["hello", "hi"]);
expect(rootExp.subExpressions[2].constructor.name).toEqual("OrExp");
expect(rootExp.subExpressions[2].subExpressions[0].constructor.name).toEqual("NoteFlatTextExp");
expect(rootExp.subExpressions[2].subExpressions[0].tokens).toEqual(["hello", "hi"]);
});
it("fulltext parser with content", () => {
@@ -51,9 +51,9 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("OrExp");
expect(rootExp.subExpressions[2].constructor.name).toEqual("OrExp");
const subs = rootExp.subExpressions[1].subExpressions;
const subs = rootExp.subExpressions[2].subExpressions;
expect(subs[0].constructor.name).toEqual("NoteFlatTextExp");
expect(subs[0].tokens).toEqual(["hello", "hi"]);
@@ -71,10 +71,10 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("LabelComparisonExp");
expect(rootExp.subExpressions[1].attributeType).toEqual("label");
expect(rootExp.subExpressions[1].attributeName).toEqual("mylabel");
expect(rootExp.subExpressions[1].comparator).toBeTruthy();
expect(rootExp.subExpressions[2].constructor.name).toEqual("LabelComparisonExp");
expect(rootExp.subExpressions[2].attributeType).toEqual("label");
expect(rootExp.subExpressions[2].attributeName).toEqual("mylabel");
expect(rootExp.subExpressions[2].comparator).toBeTruthy();
});
it("simple attribute negation", () => {
@@ -86,10 +86,10 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("NotExp");
expect(rootExp.subExpressions[1].subExpression.constructor.name).toEqual("AttributeExistsExp");
expect(rootExp.subExpressions[1].subExpression.attributeType).toEqual("label");
expect(rootExp.subExpressions[1].subExpression.attributeName).toEqual("mylabel");
expect(rootExp.subExpressions[2].constructor.name).toEqual("NotExp");
expect(rootExp.subExpressions[2].subExpression.constructor.name).toEqual("AttributeExistsExp");
expect(rootExp.subExpressions[2].subExpression.attributeType).toEqual("label");
expect(rootExp.subExpressions[2].subExpression.attributeName).toEqual("mylabel");
rootExp = parse({
fulltextTokens: [],
@@ -99,10 +99,10 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("NotExp");
expect(rootExp.subExpressions[1].subExpression.constructor.name).toEqual("AttributeExistsExp");
expect(rootExp.subExpressions[1].subExpression.attributeType).toEqual("relation");
expect(rootExp.subExpressions[1].subExpression.attributeName).toEqual("myrelation");
expect(rootExp.subExpressions[2].constructor.name).toEqual("NotExp");
expect(rootExp.subExpressions[2].subExpression.constructor.name).toEqual("AttributeExistsExp");
expect(rootExp.subExpressions[2].subExpression.attributeType).toEqual("relation");
expect(rootExp.subExpressions[2].subExpression.attributeName).toEqual("myrelation");
});
it("simple label AND", () => {
@@ -115,8 +115,8 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("AndExp");
const [firstSub, secondSub] = rootExp.subExpressions[1].subExpressions;
expect(rootExp.subExpressions[2].constructor.name).toEqual("AndExp");
const [firstSub, secondSub] = rootExp.subExpressions[2].subExpressions;
expect(firstSub.constructor.name).toEqual("LabelComparisonExp");
expect(firstSub.attributeName).toEqual("first");
@@ -135,8 +135,8 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("AndExp");
const [firstSub, secondSub] = rootExp.subExpressions[1].subExpressions;
expect(rootExp.subExpressions[2].constructor.name).toEqual("AndExp");
const [firstSub, secondSub] = rootExp.subExpressions[2].subExpressions;
expect(firstSub.constructor.name).toEqual("LabelComparisonExp");
expect(firstSub.attributeName).toEqual("first");
@@ -155,8 +155,8 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("OrExp");
const [firstSub, secondSub] = rootExp.subExpressions[1].subExpressions;
expect(rootExp.subExpressions[2].constructor.name).toEqual("OrExp");
const [firstSub, secondSub] = rootExp.subExpressions[2].subExpressions;
expect(firstSub.constructor.name).toEqual("LabelComparisonExp");
expect(firstSub.attributeName).toEqual("first");
@@ -173,17 +173,17 @@ describe("Parser", () => {
});
expect(rootExp.constructor.name).toEqual("AndExp");
const [firstSub, secondSub, thirdSub] = rootExp.subExpressions;
const [firstSub, secondSub, thirdSub, fourth] = rootExp.subExpressions;
expect(firstSub.constructor.name).toEqual("PropertyComparisonExp");
expect(firstSub.propertyName).toEqual('isArchived');
expect(secondSub.constructor.name).toEqual("OrExp");
expect(secondSub.subExpressions[0].constructor.name).toEqual("NoteFlatTextExp");
expect(secondSub.subExpressions[0].tokens).toEqual(["hello"]);
expect(thirdSub.constructor.name).toEqual("OrExp");
expect(thirdSub.subExpressions[0].constructor.name).toEqual("NoteFlatTextExp");
expect(thirdSub.subExpressions[0].tokens).toEqual(["hello"]);
expect(thirdSub.constructor.name).toEqual("LabelComparisonExp");
expect(thirdSub.attributeName).toEqual("mylabel");
expect(fourth.constructor.name).toEqual("LabelComparisonExp");
expect(fourth.attributeName).toEqual("mylabel");
});
it("label sub-expression", () => {
@@ -196,8 +196,8 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("OrExp");
const [firstSub, secondSub] = rootExp.subExpressions[1].subExpressions;
expect(rootExp.subExpressions[2].constructor.name).toEqual("OrExp");
const [firstSub, secondSub] = rootExp.subExpressions[2].subExpressions;
expect(firstSub.constructor.name).toEqual("LabelComparisonExp");
expect(firstSub.attributeName).toEqual("first");
@@ -222,8 +222,8 @@ describe("Parser", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("AndExp");
const [firstSub, secondSub, thirdSub] = rootExp.subExpressions[1].subExpressions;
expect(rootExp.subExpressions[2].constructor.name).toEqual("AndExp");
const [firstSub, secondSub, thirdSub] = rootExp.subExpressions[2].subExpressions;
expect(firstSub.constructor.name).toEqual("AttributeExistsExp");
expect(firstSub.attributeName).toEqual("first");
@@ -290,10 +290,11 @@ describe("Invalid expressions", () => {
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("LabelComparisonExp");
expect(rootExp.subExpressions[1].attributeType).toEqual("label");
expect(rootExp.subExpressions[1].attributeName).toEqual("first");
expect(rootExp.subExpressions[1].comparator).toBeTruthy();
expect(rootExp.subExpressions[2].constructor.name).toEqual("LabelComparisonExp");
expect(rootExp.subExpressions[2].attributeType).toEqual("label");
expect(rootExp.subExpressions[2].attributeName).toEqual("first");
expect(rootExp.subExpressions[2].comparator).toBeTruthy();
});
it("searching by relation without note property", () => {
+1
View File
@@ -208,6 +208,7 @@ class Becca {
return this.etapiTokens[etapiTokenId];
}
/** @returns {AbstractBeccaEntity|null} */
getEntity(entityName, entityId) {
if (!entityName || !entityId) {
return null;
+2 -2
View File
@@ -63,10 +63,10 @@ function load() {
log.info(`Becca (note cache) load took ${Date.now() - start}ms`);
}
function reload() {
function reload(reason) {
load();
require('../services/ws').reloadFrontend();
require('../services/ws').reloadFrontend(reason || "becca reloaded");
}
eventService.subscribeBeccaLoader([eventService.ENTITY_CHANGE_SYNCED], ({entityName, entityRow}) => {
+29 -25
View File
@@ -18,31 +18,11 @@ let becca = null;
class AbstractBeccaEntity {
/** @protected */
beforeSaving() {
this.generateIdIfNecessary();
}
/** @protected */
generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId();
}
}
/** @protected */
generateHash(isDeleted = false) {
let contentToHash = "";
for (const propertyName of this.constructor.hashedProperties) {
contentToHash += `|${this[propertyName]}`;
}
if (isDeleted) {
contentToHash += "|deleted";
}
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated;
@@ -61,7 +41,7 @@ class AbstractBeccaEntity {
}
/** @protected */
putEntityChange(isDeleted = false) {
putEntityChange(isDeleted) {
entityChangesService.putEntityChange({
entityName: this.constructor.entityName,
entityId: this[this.constructor.primaryKeyName],
@@ -72,11 +52,37 @@ class AbstractBeccaEntity {
});
}
/**
* @protected
* @returns {string}
*/
generateHash(isDeleted) {
let contentToHash = "";
for (const propertyName of this.constructor.hashedProperties) {
contentToHash += `|${this[propertyName]}`;
}
if (isDeleted) {
contentToHash += "|deleted";
}
return utils.hash(contentToHash).substr(0, 10);
}
/** @protected */
getPojoToSave() {
return this.getPojo();
}
/**
* @protected
* @abstract
*/
getPojo() {
throw new Error(`Unimplemented getPojo() for entity '${this.constructor.name}'`)
}
/**
* Saves entity - executes SQL, but doesn't commit the transaction on its own
*
@@ -88,9 +94,7 @@ class AbstractBeccaEntity {
const isNewEntity = !this[primaryKeyName];
if (this.beforeSaving) {
this.beforeSaving(opts);
}
this.beforeSaving(opts);
const pojo = this.getPojoToSave();
@@ -101,7 +105,7 @@ class AbstractBeccaEntity {
return;
}
this.putEntityChange(false);
this.putEntityChange(!!this.isDeleted);
if (!cls.isEntityEventsDisabled()) {
const eventPayload = {
+7 -3
View File
@@ -20,8 +20,7 @@ const attachmentRoleToNoteTypeMapping = {
class BAttachment extends AbstractBeccaEntity {
static get entityName() { return "attachments"; }
static get primaryKeyName() { return "attachmentId"; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId",
"utcDateScheduledForErasureSince", "utcDateModified"]; }
static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId", "utcDateScheduledForErasureSince"]; }
constructor(row) {
super();
@@ -98,7 +97,12 @@ class BAttachment extends AbstractBeccaEntity {
}
decrypt() {
if (this.isProtected && !this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) {
if (!this.isProtected || !this.attachmentId) {
this.isDecrypted = true;
return;
}
if (!this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) {
try {
this.title = protectedSessionService.decryptString(this.title);
this.isDecrypted = true;
+43 -27
View File
@@ -132,11 +132,17 @@ class BNote extends AbstractBeccaEntity {
*/
this.contentSize = null;
/**
* size of the content and note revision contents in bytes
* size of the note content, attachment contents in bytes
* @type {int|null}
* @private
*/
this.noteSize = null;
this.contentAndAttachmentsSize = null;
/**
* size of the note content, attachment contents and revision contents in bytes
* @type {int|null}
* @private
*/
this.contentAndAttachmentsAndRevisionsSize = null;
/**
* number of note revisions for this note
* @type {int|null}
@@ -211,12 +217,9 @@ class BNote extends AbstractBeccaEntity {
return this._getContent();
}
/** @returns {{dateModified, utcDateModified}} */
getContentMetadata() {
return sql.getRow(`SELECT dateModified, utcDateModified FROM blobs WHERE blobId = ?`, [this.blobId]);
}
/** @returns {*} */
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent();
@@ -227,6 +230,16 @@ class BNote extends AbstractBeccaEntity {
return JSON.parse(content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
/**
* @param content
* @param {object} [opts]
@@ -1130,7 +1143,7 @@ class BNote extends AbstractBeccaEntity {
}
/** @returns {BAttachment[]} */
getAttachmentByRole(role) {
getAttachmentsByRole(role) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
@@ -1141,6 +1154,18 @@ class BNote extends AbstractBeccaEntity {
.map(row => new BAttachment(row));
}
/** @returns {BAttachment} */
getAttachmentByTitle(title) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND title = ?
AND isDeleted = 0
ORDER BY position`, [this.noteId, title])
.map(row => new BAttachment(row))[0];
}
/**
* Gives all possible note paths leading to this note. Paths containing search note are ignored (could form cycles)
*
@@ -1571,7 +1596,6 @@ class BNote extends AbstractBeccaEntity {
saveRevision() {
return sql.transactional(() => {
let noteContent = this.getContent();
const contentMetadata = this.getContentMetadata();
const revision = new BRevision({
noteId: this.noteId,
@@ -1580,29 +1604,21 @@ class BNote extends AbstractBeccaEntity {
type: this.type,
mime: this.mime,
isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified
? this.utcDateModified
: contentMetadata.utcDateModified,
utcDateLastEdited: this.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: this.dateModified > contentMetadata.dateModified
? this.dateModified
: contentMetadata.dateModified,
dateLastEdited: this.dateModified,
dateCreated: dateUtils.localNowDateTime()
}, true);
revision.save(); // to generate revisionId, which is then used to save attachments
if (this.type === 'text') {
for (const noteAttachment of this.getAttachments()) {
if (noteAttachment.utcDateScheduledForErasureSince) {
continue;
}
const revisionAttachment = noteAttachment.copy();
revisionAttachment.ownerId = revision.revisionId;
revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true});
for (const noteAttachment of this.getAttachments()) {
const revisionAttachment = noteAttachment.copy();
revisionAttachment.ownerId = revision.revisionId;
revisionAttachment.setContent(noteAttachment.getContent(), {forceSave: true});
if (this.type === 'text') {
// content is rewritten to point to the revision attachments
noteContent = noteContent.replaceAll(`attachments/${noteAttachment.attachmentId}`,
`attachments/${revisionAttachment.attachmentId}`);
@@ -1610,10 +1626,10 @@ class BNote extends AbstractBeccaEntity {
noteContent = noteContent.replaceAll(new RegExp(`href="[^"]*attachmentId=${noteAttachment.attachmentId}[^"]*"`, 'gi'),
`href="api/attachments/${revisionAttachment.attachmentId}/download"`);
}
revision.setContent(noteContent, {forceSave: true});
}
revision.setContent(noteContent);
return revision;
});
}
+62
View File
@@ -86,6 +86,29 @@ class BRevision extends AbstractBeccaEntity {
return this._getContent();
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent();
if (!content || !content.trim()) {
return null;
}
return JSON.parse(content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
/**
* @param content
* @param {object} [opts]
@@ -105,6 +128,45 @@ class BRevision extends AbstractBeccaEntity {
.map(row => new BAttachment(row));
}
/** @returns {BAttachment|null} */
getAttachmentById(attachmentId, opts = {}) {
opts.includeContentLength = !!opts.includeContentLength;
const query = opts.includeContentLength
? `SELECT attachments.*, LENGTH(blobs.content) AS contentLength
FROM attachments
JOIN blobs USING (blobId)
WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`
: `SELECT * FROM attachments WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`;
return sql.getRows(query, [this.revisionId, attachmentId])
.map(row => new BAttachment(row))[0];
}
/** @returns {BAttachment[]} */
getAttachmentsByRole(role) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND role = ?
AND isDeleted = 0
ORDER BY position`, [this.revisionId, role])
.map(row => new BAttachment(row));
}
/** @returns {BAttachment} */
getAttachmentByTitle(title) {
return sql.getRows(`
SELECT attachments.*
FROM attachments
WHERE ownerId = ?
AND title = ?
AND isDeleted = 0
ORDER BY position`, [this.revisionId, title])
.map(row => new BAttachment(row))[0];
}
beforeSaving() {
super.beforeSaving();
+10 -5
View File
@@ -127,7 +127,8 @@ paths:
- targetRelationCount
- targetRelationCountIncludingLinks
- contentSize
- noteSize
- contentAndAttachmentsSize
- contentAndAttachmentsAndRevisionsSize
- revisionCount
- name: orderDirection
in: query
@@ -802,6 +803,12 @@ components:
branchId:
$ref: '#/components/schemas/EntityId'
description: DON'T specify unless you want to force a specific branchId
dateCreated:
$ref: '#/components/schemas/LocalDateTime'
description: Local timestap of the note creation. Specify only if you want to override the default (current datetime in the current timezone/offset).
utcDateCreated:
$ref: '#/components/schemas/UtcDateTime'
description: UTC timestap of the note creation. Specify only if you want to override the default (current datetime).
Note:
type: object
properties:
@@ -838,13 +845,11 @@ components:
readOnly: true
dateCreated:
$ref: '#/components/schemas/LocalDateTime'
readOnly: true
dateModified:
$ref: '#/components/schemas/LocalDateTime'
readOnly: true
utcDateCreated:
$ref: '#/components/schemas/UtcDateTime'
readOnly: true
utcDateModified:
$ref: '#/components/schemas/UtcDateTime'
readOnly: true
@@ -937,11 +942,11 @@ components:
LocalDateTime:
type: string
pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}[\+\-][0-9]{4}'
example: 2021-12-31 20:18:11.939+0100
example: 2021-12-31 20:18:11.930+0100
UtcDateTime:
type: string
pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z'
example: 2021-12-31 19:18:11.939Z
example: 2021-12-31 19:18:11.930Z
AppInfo:
type: object
properties:
+6 -2
View File
@@ -50,7 +50,9 @@ function register(router) {
'notePosition': [v.notNull, v.isInteger],
'prefix': [v.notNull, v.isString],
'isExpanded': [v.notNull, v.isBoolean],
'noteId': [v.notNull, v.isValidEntityId]
'noteId': [v.notNull, v.isValidEntityId],
'dateCreated': [v.notNull, v.isString, v.isLocalDateTime],
'utcDateCreated': [v.notNull, v.isString, v.isUtcDateTime]
};
eu.route(router, 'post' ,'/etapi/create-note', (req, res, next) => {
@@ -74,7 +76,9 @@ function register(router) {
const ALLOWED_PROPERTIES_FOR_PATCH = {
'title': [v.notNull, v.isString],
'type': [v.notNull, v.isString],
'mime': [v.notNull, v.isString]
'mime': [v.notNull, v.isString],
'dateCreated': [v.notNull, v.isString, v.isLocalDateTime],
'utcDateCreated': [v.notNull, v.isString, v.isUtcDateTime]
};
eu.route(router, 'patch' ,'/etapi/notes/:noteId', (req, res, next) => {
+20 -1
View File
@@ -1,4 +1,5 @@
const noteTypeService = require("../services/note_types");
const dateUtils = require("../services/date_utils");
function mandatory(obj) {
if (obj === undefined ) {
@@ -22,6 +23,22 @@ function isString(obj) {
}
}
function isLocalDateTime(obj) {
if (obj === undefined || obj === null) {
return;
}
return dateUtils.validateLocalDateTime(obj);
}
function isUtcDateTime(obj) {
if (obj === undefined || obj === null) {
return;
}
return dateUtils.validateUtcDateTime(obj);
}
function isBoolean(obj) {
if (obj === undefined || obj === null) {
return;
@@ -99,5 +116,7 @@ module.exports = {
isNoteId,
isNoteType,
isAttributeType,
isValidEntityId
isValidEntityId,
isLocalDateTime,
isUtcDateTime
};
+8
View File
@@ -647,4 +647,12 @@ export default class TabManager extends Component {
await this.updateDocumentTitle(activeContext);
}
}
async frocaReloadedEvent() {
const activeContext = this.getActiveContext();
if (activeContext) {
await this.updateDocumentTitle(activeContext);
}
}
}
+21
View File
@@ -15,4 +15,25 @@ export default class FBlob {
/** @type {string} */
this.utcDateModified = row.utcDateModified;
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
if (!this.content || !this.content.trim()) {
return null;
}
return JSON.parse(this.content);
}
/** @returns {*|null} valid object or null if the content cannot be parsed as JSON */
getJsonContentSafely() {
try {
return this.getJsonContent();
}
catch (e) {
return null;
}
}
}
+12 -3
View File
@@ -120,10 +120,9 @@ class FNote {
}
async getContent() {
// we're not caching content since these objects are in froca and as such pretty long-lived
const note = await server.get(`notes/${this.noteId}`);
const blob = await this.getBlob();
return note.content;
return blob?.content;
}
async getJsonContent() {
@@ -237,6 +236,12 @@ class FNote {
return this.attachments;
}
/** @returns {Promise<FAttachment[]>} */
async getAttachmentsByRole(role) {
return (await this.getAttachments())
.filter(attachment => attachment.role === role);
}
/** @returns {Promise<FAttachment>} */
async getAttachmentById(attachmentId) {
const attachments = await this.getAttachments();
@@ -971,6 +976,10 @@ class FNote {
isOptions() {
return this.noteId.startsWith("_options");
}
async getMetadata() {
return await server.get(`notes/${this.noteId}/metadata`);
}
}
export default FNote;
@@ -32,8 +32,8 @@ export default class LauncherContextMenu {
const isVisibleItem = parentNoteId === '_lbVisibleLaunchers';
const isAvailableItem = parentNoteId === '_lbAvailableLaunchers';
const isItem = isVisibleItem || isAvailableItem;
const canBeDeleted = !note.isLaunchBarConfig();
const canBeReset = note.isLaunchBarConfig();
const canBeDeleted = !note.noteId.startsWith("_"); // fixed notes can't be deleted
const canBeReset = !canBeDeleted && note.isLaunchBarConfig();;
return [
(isVisibleRoot || isAvailableRoot) ? { title: 'Add a note launcher', command: 'addNoteLauncher', uiIcon: "bx bx-plus" } : null,

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