2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								<!DOCTYPE html>  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< html  lang = "en" >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< head >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < meta  charset = "utf-8" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < title > JSDoc: Source: becca/entities/note.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/note.js< / h1 > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < section > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        < article > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            < pre  class = "prettyprint source linenums" > < code > "use strict";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const protectedSessionService = require('../../services/protected_session');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const log = require('../../services/log');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const sql = require('../../services/sql');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const utils = require('../../services/utils');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const dateUtils = require('../../services/date_utils');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const entityChangesService = require('../../services/entity_changes');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const AbstractEntity = require("./abstract_entity.js");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const NoteRevision = require("./note_revision.js");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const LABEL = 'label';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const RELATION = 'relation';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * Trilium's main entity which can represent text note, image, code note, file attachment etc.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								class Note extends AbstractEntity {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static get entityName() { return "notes"; }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static get primaryKeyName() { return "noteId"; }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static get hashedProperties() { return ["noteId", "title", "isProtected", "type", "mime"]; }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    constructor(row) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!row) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.updateFromRow(row);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.init();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    updateFromRow(row) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.update([
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.noteId,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.title,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.type,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.mime,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.isProtected,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.dateCreated,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.dateModified,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.utcDateCreated,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            row.utcDateModified
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    update([noteId, title, type, mime, isProtected, dateCreated, dateModified, utcDateCreated, utcDateModified]) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // ------ Database persisted attributes ------
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.noteId = noteId;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.title = title;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {boolean} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.isProtected = !!isProtected;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.type = type;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.mime = mime;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.dateCreated = dateCreated || dateUtils.localNowDateTime();
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.dateModified = dateModified;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.utcDateCreated = utcDateCreated || dateUtils.utcNowDateTime();
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.utcDateModified = utcDateModified;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // ------ Derived attributes ------
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {boolean} */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.isDecrypted = !this.noteId || !this.isProtected;
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.decrypt();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {string|null} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.flatTextCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    init() {
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Branch[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.parentBranches = [];
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Note[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.parents = [];
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Note[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.children = [];
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Attribute[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.ownedAttributes = [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Attribute[]|null}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * @private */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.__attributeCache = null;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Attribute[]|null}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * @private*/
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.inheritableAttributeCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Attribute[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.targetRelations = [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        this.becca.addNote(this.noteId, this);
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /** @type {Note[]|null}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * @private */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.ancestorCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // following attributes are filled during searching from database
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * size of the content in bytes
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * @type {int|null}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.contentSize = null;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * size of the content and note revision contents in bytes
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * @type {int|null}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.noteSize = null;
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * number of note revisions for this note
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * @type {int|null}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.revisionCount = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isContentAvailable() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return !this.noteId // new note which was not encrypted yet
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            || !this.isProtected
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            || protectedSessionService.isProtectedSessionAvailable()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Branch[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getParentBranches() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.parentBranches;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Branch[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getBranches() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.parentBranches;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Note[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getParentNotes() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.parents;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Note[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getChildNotes() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.children;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {boolean} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    hasChildren() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.children & &  this.children.length > 0;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Branch[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getChildBranches() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.children.map(childNote => this.becca.getBranchFromChildAndParent(childNote.noteId, this.noteId));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /*
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Note content has quite special handling - it's not a separate entity, but a lazily loaded
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * part of Note entity with it's own sync. Reasons behind this hybrid design has been:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * - 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
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * - changes in the note metadata or title should not trigger note content sync (so we keep separate utcDateModified and entity changes records)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * - but to the user note content and title changes are one and the same - single dateModified (so all changes must go through Note and content is not a separate entity)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {*} */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getContent(silentNotFoundError = false) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const row = sql.getRow(`SELECT content FROM note_contents WHERE noteId = ?`, [this.noteId]);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!row) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (silentNotFoundError) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return undefined;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                throw new Error("Cannot find note content for noteId=" + this.noteId);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let content = row.content;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.isProtected) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (protectedSessionService.isProtectedSessionAvailable()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                content = content === null ? null : protectedSessionService.decrypt(content);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                content = "";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.isStringNote()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return content === null
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ? ""
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                : content.toString("UTF-8");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return content;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {{contentLength, dateModified, utcDateModified}} */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getContentMetadata() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return sql.getRow(`
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            SELECT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                LENGTH(content) AS contentLength, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                dateModified,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                utcDateModified 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            FROM note_contents 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WHERE noteId = ?`, [this.noteId]);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {*} */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getJsonContent() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const content = this.getContent();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!content || !content.trim()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return JSON.parse(content);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    setContent(content, ignoreMissingProtectedSession = false) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (content === null || content === undefined) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            throw new Error(`Cannot set null content to note ${this.noteId}`);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.isStringNote()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            content = content.toString();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            content = Buffer.isBuffer(content) ? content : Buffer.from(content);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const pojo = {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            noteId: this.noteId,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            content: content,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dateModified: dateUtils.localNowDateTime(),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            utcDateModified: dateUtils.utcNowDateTime()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.isProtected) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (protectedSessionService.isProtectedSessionAvailable()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                pojo.content = protectedSessionService.encrypt(pojo.content);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else if (!ignoreMissingProtectedSession) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                throw new Error(`Cannot update content of noteId=${this.noteId} since we're out of protected session.`);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sql.upsert("note_contents", "noteId", pojo);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const hash = utils.hash(this.noteId + "|" + pojo.content.toString());
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        entityChangesService.addEntityChange({
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            entityName: 'note_contents',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            entityId: this.noteId,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            hash: hash,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            isErased: false,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            utcDateChanged: pojo.utcDateModified,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            isSynced: true
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        });
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    setJsonContent(content) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.setContent(JSON.stringify(content, null, '\t'));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isRoot() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.noteId === 'root';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is of application/json content type */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isJson() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.mime === "application/json";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is JavaScript (code or attachment) */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isJavaScript() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return (this.type === "code" || this.type === "file")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            & &  (this.mime.startsWith("application/javascript")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                || this.mime === "application/x-javascript"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                || this.mime === "text/javascript");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is HTML */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isHtml() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ["code", "file", "render"].includes(this.type)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            & &  this.mime === "text/html";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {boolean} true if the note has string content (not binary) */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isStringNote() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return utils.isStringNote(this.type, this.mime);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {string|null} JS script environment - either "frontend" or "backend" */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getScriptEnv() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.isHtml() || (this.isJavaScript() & &  this.mime.endsWith('env=frontend'))) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return "frontend";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.type === 'render') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return "frontend";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.isJavaScript() & &  this.mime.endsWith('env=backend')) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return "backend";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [type] - (optional) attribute type to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - (optional) attribute name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute[]} all note's attributes, including inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getAttributes(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.__getAttributes([]);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (type & &  name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.__attributeCache.filter(attr => attr.type === type & &  attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else if (type) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.__attributeCache.filter(attr => attr.type === type);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else if (name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.__attributeCache.filter(attr => attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.__attributeCache.slice();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    __getAttributes(path) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (path.includes(this.noteId)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!this.__attributeCache) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const parentAttributes = this.ownedAttributes.slice();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const newPath = [...path, this.noteId];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (this.noteId !== 'root') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for (const parentNote of this.parents) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    parentAttributes.push(...parentNote.__getInheritableAttributes(newPath));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const templateAttributes = [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const ownedAttr of parentAttributes) { // parentAttributes so we process also inherited templates
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (ownedAttr.type === 'relation' & &  ownedAttr.name === 'template') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    const templateNote = this.becca.notes[ownedAttr.value];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if (templateNote) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        templateAttributes.push(...templateNote.__getAttributes(newPath));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.__attributeCache = [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const addedAttributeIds = new Set();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const attr of parentAttributes.concat(templateAttributes)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (!addedAttributeIds.has(attr.attributeId)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    addedAttributeIds.add(attr.attributeId);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    this.__attributeCache.push(attr);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.inheritableAttributeCache = [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const attr of this.__attributeCache) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (attr.isInheritable) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    this.inheritableAttributeCache.push(attr);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.__attributeCache;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Attribute[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    __getInheritableAttributes(path) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (path.includes(this.noteId)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!this.inheritableAttributeCache) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.__getAttributes(path); // will refresh also this.inheritableAttributeCache
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.inheritableAttributeCache;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasAttribute(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return !!this.getAttributes().find(attr => attr.type === type & &  attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getAttributeCaseInsensitive(type, name, value) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        name = name.toLowerCase();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        value = value ? value.toLowerCase() : null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes().find(
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            attr => attr.type === type
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            & &  attr.name.toLowerCase() === name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            & &  (!value || attr.value.toLowerCase() === value));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getRelationTarget(name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const relation = this.getAttributes().find(attr => attr.type === 'relation' & &  attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return relation ? relation.targetNote : null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {boolean} true if label exists (including inherited)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasLabel(name) { return this.hasAttribute(LABEL, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {boolean} true if label exists (excluding inherited)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasOwnedLabel(name) { return this.hasOwnedAttribute(LABEL, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {boolean} true if relation exists (including inherited)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasRelation(name) { return this.hasAttribute(RELATION, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {boolean} true if relation exists (excluding inherited)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasOwnedRelation(name) { return this.hasOwnedAttribute(RELATION, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute|null} label if it exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getLabel(name) { return this.getAttribute(LABEL, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute|null} label if it exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedLabel(name) { return this.getOwnedAttribute(LABEL, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute|null} relation if it exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getRelation(name) { return this.getAttribute(RELATION, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute|null} relation if it exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedRelation(name) { return this.getOwnedAttribute(RELATION, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string|null} label value if label exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getLabelValue(name) { return this.getAttributeValue(LABEL, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string|null} label value if label exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedLabelValue(name) { return this.getOwnedAttributeValue(LABEL, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string|null} relation value if relation exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getRelationValue(name) { return this.getAttributeValue(RELATION, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string|null} relation value if relation exists, null otherwise
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedRelationValue(name) { return this.getOwnedAttributeValue(RELATION, name); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} type - attribute type (label, relation, etc.)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {boolean} true if note has an attribute with given type and name (excluding inherited)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasOwnedAttribute(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return !!this.getOwnedAttribute(type, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} type - attribute type (label, relation, etc.)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute} attribute of given type and name. If there's more such attributes, first is  returned. Returns null if there's no such attribute belonging to this note.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getAttribute(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const attributes = this.getAttributes();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return attributes.find(attr => attr.type === type & &  attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} type - attribute type (label, relation, etc.)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string|null} attribute value of given type and name or null if no such attribute exists.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getAttributeValue(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const attr = this.getAttribute(type, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return attr ? attr.value : null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} type - attribute type (label, relation, etc.)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string|null} attribute value of given type and name or null if no such attribute exists.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedAttributeValue(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const attr = this.getOwnedAttribute(type, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return attr ? attr.value : null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - label name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute[]} all note's labels (attributes with type label), including inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getLabels(name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes(LABEL, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - label name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string[]} all note's label values, including inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getLabelValues(name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getLabels(name).map(l => l.value);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - label name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute[]} all note's labels (attributes with type label), excluding inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedLabels(name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getOwnedAttributes(LABEL, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - label name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {string[]} all note's label values, excluding inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedLabelValues(name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getOwnedAttributes(LABEL, name).map(l => l.value);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - relation name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute[]} all note's relations (attributes with type relation), including inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getRelations(name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes(RELATION, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - relation name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute[]} all note's relations (attributes with type relation), excluding inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedRelations(name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getOwnedAttributes(RELATION, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [type] - (optional) attribute type to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [name] - (optional) attribute name to filter
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute[]} note's "owned" attributes - excluding inherited ones
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedAttributes(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // it's a common mistake to include # or ~ into attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (name & &  ["#", "~"].includes(name[0])) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            name = name.substr(1);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (type & &  name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.ownedAttributes.filter(attr => attr.type === type & &  attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else if (type) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.ownedAttributes.filter(attr => attr.type === type);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else if (name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.ownedAttributes.filter(attr => attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return this.ownedAttributes.slice();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @returns {Attribute} attribute belonging to this specific note (excludes inherited attributes)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * This method can be significantly faster than the getAttribute()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getOwnedAttribute(type, name) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const attrs = this.getOwnedAttributes(type, name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return attrs.length > 0 ? attrs[0] : null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get isArchived() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.hasAttribute('label', 'archived');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasInheritableOwnedArchivedLabel() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return !!this.ownedAttributes.find(attr => attr.type === 'label' & &  attr.name === 'archived' & &  attr.isInheritable);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // will sort the parents so that non-search &  non-archived are first and archived at the end
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // this is done so that non-search &  non-archived paths are always explored as first when looking for note path
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    sortParents() {
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        this.parentBranches.sort((a, b) =>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            a.branchId.startsWith('virt-')
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            || a.parentNote.hasInheritableOwnedArchivedLabel() ? 1 : -1);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.parents = this.parentBranches.map(branch => branch.parentNote);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * This is used for:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * - fast searching
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * - note similarity evaluation
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @return {string} - returns flattened textual representation of note, prefixes and attributes
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getFlatText() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!this.flatTextCache) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.flatTextCache = this.noteId + ' ' + this.type + ' ' + this.mime + ' ';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const branch of this.parentBranches) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (branch.prefix) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    this.flatTextCache += branch.prefix + ' ';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.flatTextCache += this.title + ' ';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const attr of this.getAttributes()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                // it's best to use space as separator since spaces are filtered from the search string by the tokenization into words
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                this.flatTextCache += (attr.type === 'label' ? '#' : '~') + attr.name;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (attr.value) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    this.flatTextCache += '=' + attr.value;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                this.flatTextCache += ' ';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.flatTextCache = utils.normalize(this.flatTextCache);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.flatTextCache;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    invalidateThisCache() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.flatTextCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.__attributeCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.inheritableAttributeCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.ancestorCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    invalidateSubTree(path = []) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (path.includes(this.noteId)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.invalidateThisCache();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.children.length || this.targetRelations.length) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            path = [...path, this.noteId];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const childNote of this.children) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            childNote.invalidateSubTree(path);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const targetRelation of this.targetRelations) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (targetRelation.name === 'template') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                const note = targetRelation.note;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (note) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    note.invalidateSubTree(path);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    invalidateSubtreeFlatText() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.flatTextCache = null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const childNote of this.children) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            childNote.invalidateSubtreeFlatText();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const targetRelation of this.targetRelations) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (targetRelation.name === 'template') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                const note = targetRelation.note;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (note) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    note.invalidateSubtreeFlatText();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getRelationDefinitions() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getLabels()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            .filter(l => l.name.startsWith("relation:"));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getLabelDefinitions() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getLabels()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            .filter(l => l.name.startsWith("relation:"));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isTemplate() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return !!this.targetRelations.find(rel => rel.name === 'template');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Note[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getSubtreeNotesIncludingTemplated() {
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const set = new Set();
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        function inner(note) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (set.has(note)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            set.add(note);
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for (const childNote of note.children) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                inner(childNote);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const targetRelation of note.targetRelations) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (targetRelation.name === 'template') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    const targetNote = targetRelation.note;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if (targetNote) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        inner(targetNote);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    }
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        inner(this);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return Array.from(set);
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Note[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getSubtreeNotes(includeArchived = true) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const noteSet = new Set();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        function addSubtreeNotesInner(note) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (!includeArchived & &  note.isArchived) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            noteSet.add(note);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const childNote of note.children) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                addSubtreeNotesInner(childNote);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        addSubtreeNotesInner(this);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return Array.from(noteSet);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {String[]} */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getSubtreeNoteIds(includeArchived = true) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getSubtreeNotes(includeArchived).map(note => note.noteId);
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getDescendantNoteIds() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getSubtreeNoteIds();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get parentCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.parents.length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get childrenCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.children.length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get labelCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes().filter(attr => attr.type === 'label').length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get ownedLabelCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.ownedAttributes.filter(attr => attr.type === 'label').length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get relationCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes().filter(attr => attr.type === 'relation' & &  !attr.isAutoLink()).length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get relationCountIncludingLinks() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes().filter(attr => attr.type === 'relation').length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get ownedRelationCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.ownedAttributes.filter(attr => attr.type === 'relation' & &  !attr.isAutoLink()).length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get ownedRelationCountIncludingLinks() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.ownedAttributes.filter(attr => attr.type === 'relation').length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get targetRelationCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.targetRelations.filter(attr => !attr.isAutoLink()).length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get targetRelationCountIncludingLinks() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.targetRelations.length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get attributeCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes().length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get ownedAttributeCount() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.getAttributes().length;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Note[]} */
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getAncestors() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!this.ancestorCache) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const noteIds = new Set();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.ancestorCache = [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const parent of this.parents) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (!noteIds.has(parent.noteId)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    this.ancestorCache.push(parent);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    noteIds.add(parent.noteId);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for (const ancestorNote of parent.getAncestors()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if (!noteIds.has(ancestorNote.noteId)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        this.ancestorCache.push(ancestorNote);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        noteIds.add(ancestorNote.noteId);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.ancestorCache;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {boolean} */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hasAncestor(ancestorNoteId) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const ancestorNote of this.getAncestors()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (ancestorNote.noteId === ancestorNoteId) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return true;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return false;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    getTargetRelations() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.targetRelations;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Note[]} - returns only notes which are templated, does not include their subtrees
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								     *                     in effect returns notes which are influenced by note's non-inheritable attributes */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getTemplatedNotes() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const arr = [this];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const targetRelation of this.targetRelations) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (targetRelation.name === 'template') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                const note = targetRelation.note;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if (note) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    arr.push(note);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return arr;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getDistanceToAncestor(ancestorNoteId) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.noteId === ancestorNoteId) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return 0;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let minDistance = 999999;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const parent of this.parents) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            minDistance = Math.min(minDistance, parent.getDistanceToAncestor(ancestorNoteId) + 1);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return minDistance;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getNoteRevisions() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return sql.getRows("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            .map(row => new NoteRevision(row));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @return {string[][]} - array of notePaths (each represented by array of noteIds constituting the particular note path)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getAllNotePaths() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.noteId === 'root') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return [['root']];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const notePaths = [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const parentNote of this.getParentNotes()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for (const parentPath of parentNote.getAllNotePaths()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                parentPath.push(this.noteId);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                notePaths.push(parentPath);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return notePaths;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param ancestorNoteId
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @return {boolean} - true if ancestorNoteId occurs in at least one of the note's paths
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isDescendantOfNote(ancestorNoteId) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const notePaths = this.getAllNotePaths();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return notePaths.some(path => path.includes(ancestorNoteId));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Update's given attribute's value or creates it if it doesn't exist
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} type - attribute type (label, relation, etc.)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - attribute value (optional)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    setAttribute(type, name, value) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const attributes = this.getOwnedAttributes();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const attr = attributes.find(attr => attr.type === type & &  attr.name === name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        value = value !== null & &  value !== undefined ? value.toString() : "";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (attr) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (attr.value !== value) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                attr.value = value;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                attr.save();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const Attribute = require("./attribute.js");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new Attribute({
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                noteId: this.noteId,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                type: type,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                name: name,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                value: value
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }).save();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Removes given attribute name-value pair if it exists.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} type - attribute type (label, relation, etc.)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - attribute value (optional)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    removeAttribute(type, name, value) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const attributes = this.getOwnedAttributes();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for (const attribute of attributes) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if (attribute.type === type & &  attribute.name === name & &  (value === undefined || value === attribute.value)) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                attribute.markAsDeleted();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @return {Attribute}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    addAttribute(type, name, value = "", isInheritable = false, position = 1000) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const Attribute = require("./attribute.js");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return new Attribute({
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            noteId: this.noteId,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            type: type,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            name: name,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            value: value,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            isInheritable: isInheritable,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            position: position
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }).save();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    addLabel(name, value = "", isInheritable = false) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.addAttribute(LABEL, name, value, isInheritable);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    addRelation(name, targetNoteId, isInheritable = false) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.addAttribute(RELATION, name, targetNoteId, isInheritable);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Based on enabled, attribute is either set or removed.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} type - attribute type ('relation', 'label' etc.)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {boolean} enabled - toggle On or Off
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - attribute name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - attribute value (optional)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    toggleAttribute(type, enabled, name, value) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (enabled) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.setAttribute(type, name, value);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this.removeAttribute(type, name, value);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Based on enabled, label is either set or removed.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {boolean} enabled - toggle On or Off
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - label value (optional)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    toggleLabel(enabled, name, value) { return this.toggleAttribute(LABEL, enabled, name, value); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Based on enabled, relation is either set or removed.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {boolean} enabled - toggle On or Off
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - relation value (noteId)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    toggleRelation(enabled, name, value) { return this.toggleAttribute(RELATION, enabled, name, value); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Update's given label's value or creates it if it doesn't exist
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - label value
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    setLabel(name, value) { return this.setAttribute(LABEL, name, value); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Update's given relation's value or creates it if it doesn't exist
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} value - relation value (noteId)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    setRelation(name, value) { return this.setAttribute(RELATION, name, value); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Remove label name-value pair, if it exists.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - label name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - label value
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    removeLabel(name, value) { return this.removeAttribute(LABEL, name, value); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /**
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * Remove relation name-value pair, if it exists.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} name - relation name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * @param {string} [value] - relation value (noteId)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    removeRelation(name, value) { return this.removeAttribute(RELATION, name, value); }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    searchNotesInSubtree(searchString) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const searchService = require("../../services/search/services/search");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return searchService.searchNotes(searchString);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    searchNoteInSubtree(searchString) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return this.searchNotesInSubtree(searchString)[0];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloneTo(parentNoteId) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const cloningService = require("../../services/cloning");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const branch = this.becca.getNote(parentNoteId).getParentBranches()[0];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return cloningService.cloneNoteToParent(this.noteId, branch.branchId);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    decrypt() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (this.isProtected & &  !this.isDecrypted & &  protectedSessionService.isProtectedSessionAvailable()) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                this.title = protectedSessionService.decryptString(this.title);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                this.isDecrypted = true;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            catch (e) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                log.error(`Could not decrypt note ${this.noteId}: ${e.message} ${e.stack}`);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    get isDeleted() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return !(this.noteId in this.becca.notes);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    beforeSaving() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super.beforeSaving();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        this.becca.addNote(this.noteId, this);
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.dateModified = dateUtils.localNowDateTime();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this.utcDateModified = dateUtils.utcNowDateTime();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getPojo() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            noteId: this.noteId,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            title: this.title,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            isProtected: this.isProtected,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            type: this.type,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            mime: this.mime,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            isDeleted: false,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dateCreated: this.dateCreated,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dateModified: this.dateModified,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            utcDateCreated: this.utcDateCreated,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            utcDateModified: this.utcDateModified
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    getPojoToSave() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const pojo = this.getPojo();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        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 = Note;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        < / article > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < / section > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< / div >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< nav >  
						 
					
						
							
								
									
										
										
										
											2021-11-10 21:30:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    < 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 = "ApiToken.html" > ApiToken< / a > < / li > < li > < a  href = "Attribute.html" > Attribute< / a > < / li > < li > < a  href = "BackendScriptApi.html" > BackendScriptApi< / a > < / li > < li > < a  href = "Branch.html" > Branch< / a > < / li > < li > < a  href = "Note.html" > Note< / a > < / li > < li > < a  href = "NoteRevision.html" > NoteRevision< / a > < / li > < li > < a  href = "Option.html" > Option< / a > < / li > < li > < a  href = "RecentNote.html" > RecentNote< / a > < / li > < / ul > < h3 > < a  href = "global.html" > Global< / a > < / h3 > 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 12:26:13 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								< / nav >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< br  class = "clear" >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< footer >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Documentation generated by < a  href = "https://github.com/jsdoc/jsdoc" > JSDoc 3.6.7< / a > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< / footer >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< script >  prettyPrint ( ) ;  < / script >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< script  src = "scripts/linenumber.js" >  < / script >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< / body >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< / html >