mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 04:16:17 +01:00 
			
		
		
		
	Compare commits
	
		
			292 Commits
		
	
	
		
			v0.25.1-be
			...
			v0.30.2-be
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					36de217835 | ||
| 
						 | 
					b5283d58bb | ||
| 
						 | 
					8414d97ffa | ||
| 
						 | 
					9f30d4e673 | ||
| 
						 | 
					8e0d1fa0df | ||
| 
						 | 
					5b251b9977 | ||
| 
						 | 
					8b3e721028 | ||
| 
						 | 
					7e2a2baa5d | ||
| 
						 | 
					003eed368b | ||
| 
						 | 
					4b1cf05c0e | ||
| 
						 | 
					d9429c4f4b | ||
| 
						 | 
					b7bd94b6b0 | ||
| 
						 | 
					51bbc10744 | ||
| 
						 | 
					fb5df33ee7 | ||
| 
						 | 
					d8ba0ccd7d | ||
| 
						 | 
					886ea6c68c | ||
| 
						 | 
					936f85c09e | ||
| 
						 | 
					b25deea21d | ||
| 
						 | 
					cf5ec44303 | ||
| 
						 | 
					6f956c2415 | ||
| 
						 | 
					3533160bef | ||
| 
						 | 
					60cbfdcabd | ||
| 
						 | 
					604f036a54 | ||
| 
						 | 
					dd4f3ec264 | ||
| 
						 | 
					ff67b8a0ba | ||
| 
						 | 
					1d5fb0b646 | ||
| 
						 | 
					80931a318f | ||
| 
						 | 
					16f16cb36a | ||
| 
						 | 
					899f24cde5 | ||
| 
						 | 
					9f29521ab8 | ||
| 
						 | 
					c1ce0c6b22 | ||
| 
						 | 
					a7fce33750 | ||
| 
						 | 
					6fd8e73150 | ||
| 
						 | 
					1359dd86c2 | ||
| 
						 | 
					a1b610fc50 | ||
| 
						 | 
					c849d719e9 | ||
| 
						 | 
					96de2e7008 | ||
| 
						 | 
					f140b77e7c | ||
| 
						 | 
					22228de63b | ||
| 
						 | 
					b0596c9eb2 | ||
| 
						 | 
					2a2319d434 | ||
| 
						 | 
					dad47d115f | ||
| 
						 | 
					502026359c | ||
| 
						 | 
					47b0e4e4d3 | ||
| 
						 | 
					6c927d9159 | ||
| 
						 | 
					ddc79b2517 | ||
| 
						 | 
					4c2e12d2cb | ||
| 
						 | 
					14f7a8b7b9 | ||
| 
						 | 
					caa7dd9619 | ||
| 
						 | 
					8aa7e2d0a0 | ||
| 
						 | 
					6be8a3f343 | ||
| 
						 | 
					a097cefba7 | ||
| 
						 | 
					e4c78f3887 | ||
| 
						 | 
					5baa251944 | ||
| 
						 | 
					cde68abec9 | ||
| 
						 | 
					51175e3676 | ||
| 
						 | 
					45ddfef30a | ||
| 
						 | 
					1e1d78999e | ||
| 
						 | 
					92fcd7b345 | ||
| 
						 | 
					e04f1cd574 | ||
| 
						 | 
					176c3a5d51 | ||
| 
						 | 
					c09570cf39 | ||
| 
						 | 
					4a093000be | ||
| 
						 | 
					6952b643ae | ||
| 
						 | 
					c487a95bc7 | ||
| 
						 | 
					8884177d9f | ||
| 
						 | 
					8b250ed523 | ||
| 
						 | 
					d8b78d8025 | ||
| 
						 | 
					42112b8053 | ||
| 
						 | 
					6cc0dd5a80 | ||
| 
						 | 
					afd5f4823f | ||
| 
						 | 
					b0cf82c91b | ||
| 
						 | 
					6a67cdd5af | ||
| 
						 | 
					bad7b84993 | ||
| 
						 | 
					d3ca6b5ae6 | ||
| 
						 | 
					da5009f089 | ||
| 
						 | 
					c08524c977 | ||
| 
						 | 
					f89537037e | ||
| 
						 | 
					c153793766 | ||
| 
						 | 
					0aec5927d5 | ||
| 
						 | 
					8aea9a1801 | ||
| 
						 | 
					73247e3220 | ||
| 
						 | 
					89344a6eda | ||
| 
						 | 
					40d2e6ea83 | ||
| 
						 | 
					910cfe9a17 | ||
| 
						 | 
					e58a80fc00 | ||
| 
						 | 
					4a2319cb33 | ||
| 
						 | 
					5619088c41 | ||
| 
						 | 
					60271993eb | ||
| 
						 | 
					6695e8b011 | ||
| 
						 | 
					707df18b93 | ||
| 
						 | 
					90895f1288 | ||
| 
						 | 
					ba1ca506af | ||
| 
						 | 
					f90ed99a40 | ||
| 
						 | 
					67630b1a22 | ||
| 
						 | 
					2c1580ea65 | ||
| 
						 | 
					840a0b5f64 | ||
| 
						 | 
					b39f6ef7ad | ||
| 
						 | 
					fb27088fcd | ||
| 
						 | 
					76fbff68ba | ||
| 
						 | 
					54de4d236d | ||
| 
						 | 
					e211dd65ad | ||
| 
						 | 
					a87f4d8653 | ||
| 
						 | 
					b59c175c2e | ||
| 
						 | 
					580104c4c5 | ||
| 
						 | 
					0fc3053b0a | ||
| 
						 | 
					929e0f69c2 | ||
| 
						 | 
					e70af1300a | ||
| 
						 | 
					4d0e46021b | ||
| 
						 | 
					1a9a49b739 | ||
| 
						 | 
					2ac560c56e | ||
| 
						 | 
					c23387c0fb | ||
| 
						 | 
					0ff250fe15 | ||
| 
						 | 
					52b1e58b26 | ||
| 
						 | 
					484715e440 | ||
| 
						 | 
					9d42c3d802 | ||
| 
						 | 
					c654172d33 | ||
| 
						 | 
					e17b26c883 | ||
| 
						 | 
					24d02d9cf5 | ||
| 
						 | 
					7208a311ac | ||
| 
						 | 
					ad7355372b | ||
| 
						 | 
					f18b5babad | ||
| 
						 | 
					9831ec0ca9 | ||
| 
						 | 
					596544eca3 | ||
| 
						 | 
					1f853024ee | ||
| 
						 | 
					0308b13460 | ||
| 
						 | 
					06b8a82f70 | ||
| 
						 | 
					91ca07929d | ||
| 
						 | 
					afabaa5fdb | ||
| 
						 | 
					a6fd3fa77c | ||
| 
						 | 
					58a2c08dcd | ||
| 
						 | 
					299bbff2f4 | ||
| 
						 | 
					19d8947123 | ||
| 
						 | 
					35edce7523 | ||
| 
						 | 
					bc4cec69a5 | ||
| 
						 | 
					cce8c1b674 | ||
| 
						 | 
					aa58788769 | ||
| 
						 | 
					6c62ab7a52 | ||
| 
						 | 
					d6ab638b30 | ||
| 
						 | 
					bd4db406de | ||
| 
						 | 
					e50f9cd0a3 | ||
| 
						 | 
					2b64cbce2c | ||
| 
						 | 
					2797c942ab | ||
| 
						 | 
					f1c3278874 | ||
| 
						 | 
					424c22dcde | ||
| 
						 | 
					5c223dfd12 | ||
| 
						 | 
					6a3e7a5a8e | ||
| 
						 | 
					f88cdac000 | ||
| 
						 | 
					eeead90f32 | ||
| 
						 | 
					b607857409 | ||
| 
						 | 
					9268f88bc3 | ||
| 
						 | 
					f7f0560a9f | ||
| 
						 | 
					3d8905207e | ||
| 
						 | 
					dbc312010b | ||
| 
						 | 
					b115a7cf19 | ||
| 
						 | 
					348562352c | ||
| 
						 | 
					70fd917e7c | ||
| 
						 | 
					d2b60764cd | ||
| 
						 | 
					581b1fdaa5 | ||
| 
						 | 
					3c19a712c0 | ||
| 
						 | 
					cc27f16088 | ||
| 
						 | 
					dffdb82288 | ||
| 
						 | 
					2b32addade | ||
| 
						 | 
					0b251530fa | ||
| 
						 | 
					f5b933149a | ||
| 
						 | 
					48bbfb8bdb | ||
| 
						 | 
					889971c4d6 | ||
| 
						 | 
					0722494d41 | ||
| 
						 | 
					4b977a3306 | ||
| 
						 | 
					3ff3021acd | ||
| 
						 | 
					99e56a9c42 | ||
| 
						 | 
					77279dfe16 | ||
| 
						 | 
					93f8050454 | ||
| 
						 | 
					31cfede7a7 | ||
| 
						 | 
					c8ec86e537 | ||
| 
						 | 
					05aee884b6 | ||
| 
						 | 
					012ba9e060 | ||
| 
						 | 
					8e8fd88857 | ||
| 
						 | 
					523ccdad6b | ||
| 
						 | 
					ded3f605be | ||
| 
						 | 
					62b44e3549 | ||
| 
						 | 
					030d12a465 | ||
| 
						 | 
					4d15628840 | ||
| 
						 | 
					81b849898c | ||
| 
						 | 
					3824486b85 | ||
| 
						 | 
					081ab00a0a | ||
| 
						 | 
					04f6af5c9a | ||
| 
						 | 
					4dc1f1f6eb | ||
| 
						 | 
					3930a02123 | ||
| 
						 | 
					3112de105e | ||
| 
						 | 
					3b8d7b8fba | ||
| 
						 | 
					9fca7f09a5 | ||
| 
						 | 
					fd39d6b3a9 | ||
| 
						 | 
					a103886ea5 | ||
| 
						 | 
					373408e401 | ||
| 
						 | 
					db44c1d8e6 | ||
| 
						 | 
					95a34c9e2d | ||
| 
						 | 
					6ce401f260 | ||
| 
						 | 
					5d74dcd256 | ||
| 
						 | 
					5a9fc1697b | ||
| 
						 | 
					927415838c | ||
| 
						 | 
					d72fcefdc7 | ||
| 
						 | 
					0be173a8f7 | ||
| 
						 | 
					c3913a8735 | ||
| 
						 | 
					e2dfe1b6de | ||
| 
						 | 
					fec3e47eb8 | ||
| 
						 | 
					d72efd2450 | ||
| 
						 | 
					ef1c840aa7 | ||
| 
						 | 
					1581464d8c | ||
| 
						 | 
					9de29584a4 | ||
| 
						 | 
					9e2e6fb50c | ||
| 
						 | 
					c85979b66b | ||
| 
						 | 
					ecdc5865a6 | ||
| 
						 | 
					1771ddb787 | ||
| 
						 | 
					3ab657fe46 | ||
| 
						 | 
					8785dae753 | ||
| 
						 | 
					2f1c5b29d4 | ||
| 
						 | 
					7135349a10 | ||
| 
						 | 
					66c639d5e3 | ||
| 
						 | 
					6704b755d8 | ||
| 
						 | 
					cf96baad48 | ||
| 
						 | 
					32220476aa | ||
| 
						 | 
					86bc84a2ad | ||
| 
						 | 
					de9e0c7929 | ||
| 
						 | 
					6963e662ef | ||
| 
						 | 
					7127822e8f | ||
| 
						 | 
					0a35abf68f | ||
| 
						 | 
					3f8e8f8561 | ||
| 
						 | 
					e02eca87b0 | ||
| 
						 | 
					2f680c4326 | ||
| 
						 | 
					0b4a44a403 | ||
| 
						 | 
					89299f865c | ||
| 
						 | 
					f6db9a50ab | ||
| 
						 | 
					78d9fac1e6 | ||
| 
						 | 
					458ed1faff | ||
| 
						 | 
					0657815de5 | ||
| 
						 | 
					a608832681 | ||
| 
						 | 
					d2f72529b3 | ||
| 
						 | 
					28185af158 | ||
| 
						 | 
					7aacd01ad7 | ||
| 
						 | 
					74cc34696e | ||
| 
						 | 
					d4baac0bb5 | ||
| 
						 | 
					35bc1421f1 | ||
| 
						 | 
					d4db265fd9 | ||
| 
						 | 
					1dad919de9 | ||
| 
						 | 
					246dfbdcb4 | ||
| 
						 | 
					f8d32d64f5 | ||
| 
						 | 
					5dea271d6f | ||
| 
						 | 
					eeb62a6cf2 | ||
| 
						 | 
					35cf8026b0 | ||
| 
						 | 
					e0028ab6f1 | ||
| 
						 | 
					a32645cdeb | ||
| 
						 | 
					812f9f6fca | ||
| 
						 | 
					f7a670ec24 | ||
| 
						 | 
					d0d24f0f4a | ||
| 
						 | 
					042f9b7f2d | ||
| 
						 | 
					2d260cdbed | ||
| 
						 | 
					6a786cad83 | ||
| 
						 | 
					67019b3d6c | ||
| 
						 | 
					1db6e59077 | ||
| 
						 | 
					5e4770875e | ||
| 
						 | 
					e9a77f3f16 | ||
| 
						 | 
					cbec85f295 | ||
| 
						 | 
					14bd5d301d | ||
| 
						 | 
					321d0e8d64 | ||
| 
						 | 
					84e1512031 | ||
| 
						 | 
					b036852b2d | ||
| 
						 | 
					f693dc31e8 | ||
| 
						 | 
					af8f5b11b8 | ||
| 
						 | 
					8ca943f87b | ||
| 
						 | 
					35cc9da626 | ||
| 
						 | 
					44cc86a1a5 | ||
| 
						 | 
					7c3bbfd45e | ||
| 
						 | 
					a1f939e3a0 | ||
| 
						 | 
					4ca7886090 | ||
| 
						 | 
					b942163748 | ||
| 
						 | 
					5b6d15acb3 | ||
| 
						 | 
					841420360e | ||
| 
						 | 
					a680bb4612 | ||
| 
						 | 
					f763e13996 | ||
| 
						 | 
					e73e1262ae | ||
| 
						 | 
					b774d56cf7 | ||
| 
						 | 
					bae55f2e8b | ||
| 
						 | 
					6c16cdb011 | ||
| 
						 | 
					86fcbb0354 | ||
| 
						 | 
					17d030e800 | ||
| 
						 | 
					6fbf28b30d | ||
| 
						 | 
					8171b68b18 | ||
| 
						 | 
					d30e3a4052 | ||
| 
						 | 
					87aab7ac5b | ||
| 
						 | 
					c46f5805b1 | ||
| 
						 | 
					dd6a29dfc0 | 
							
								
								
									
										7
									
								
								.gitpod.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.gitpod.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					tasks:
 | 
				
			||||||
 | 
					    - before: nvm install 10 && nvm use 10
 | 
				
			||||||
 | 
					      init: npm install
 | 
				
			||||||
 | 
					      command: npm run start
 | 
				
			||||||
 | 
					ports:
 | 
				
			||||||
 | 
					    - port: 8080
 | 
				
			||||||
 | 
					      onOpen: open-preview
 | 
				
			||||||
@@ -16,586 +16,662 @@
 | 
				
			|||||||
    <table id="8" parent="2" name="branches"/>
 | 
					    <table id="8" parent="2" name="branches"/>
 | 
				
			||||||
    <table id="9" parent="2" name="event_log"/>
 | 
					    <table id="9" parent="2" name="event_log"/>
 | 
				
			||||||
    <table id="10" parent="2" name="links"/>
 | 
					    <table id="10" parent="2" name="links"/>
 | 
				
			||||||
    <table id="11" parent="2" name="note_revisions"/>
 | 
					    <table id="11" parent="2" name="note_contents"/>
 | 
				
			||||||
    <table id="12" parent="2" name="notes"/>
 | 
					    <table id="12" parent="2" name="note_revisions"/>
 | 
				
			||||||
    <table id="13" parent="2" name="options"/>
 | 
					    <table id="13" parent="2" name="notes"/>
 | 
				
			||||||
    <table id="14" parent="2" name="recent_notes"/>
 | 
					    <table id="14" parent="2" name="options"/>
 | 
				
			||||||
    <table id="15" parent="2" name="source_ids"/>
 | 
					    <table id="15" parent="2" name="recent_notes"/>
 | 
				
			||||||
    <table id="16" parent="2" name="sqlite_master">
 | 
					    <table id="16" parent="2" name="source_ids"/>
 | 
				
			||||||
 | 
					    <table id="17" parent="2" name="sqlite_master">
 | 
				
			||||||
      <System>1</System>
 | 
					      <System>1</System>
 | 
				
			||||||
    </table>
 | 
					    </table>
 | 
				
			||||||
    <table id="17" parent="2" name="sqlite_sequence">
 | 
					    <table id="18" parent="2" name="sqlite_sequence">
 | 
				
			||||||
      <System>1</System>
 | 
					      <System>1</System>
 | 
				
			||||||
    </table>
 | 
					    </table>
 | 
				
			||||||
    <table id="18" parent="2" name="sync"/>
 | 
					    <table id="19" parent="2" name="sync"/>
 | 
				
			||||||
    <column id="19" parent="6" name="apiTokenId">
 | 
					    <column id="20" parent="6" name="apiTokenId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="20" parent="6" name="token">
 | 
					    <column id="21" parent="6" name="token">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="21" parent="6" name="dateCreated">
 | 
					    <column id="22" parent="6" name="dateCreated">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="22" parent="6" name="isDeleted">
 | 
					    <column id="23" parent="6" name="isDeleted">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="23" parent="6" name="hash">
 | 
					    <column id="24" parent="6" name="hash">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="24" parent="6" name="sqlite_autoindex_api_tokens_1">
 | 
					    <index id="25" parent="6" name="sqlite_autoindex_api_tokens_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>apiTokenId</ColNames>
 | 
					      <ColNames>apiTokenId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="25" parent="6">
 | 
					    <key id="26" parent="6">
 | 
				
			||||||
      <ColNames>apiTokenId</ColNames>
 | 
					      <ColNames>apiTokenId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_api_tokens_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_api_tokens_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="26" parent="7" name="attributeId">
 | 
					    <column id="27" parent="7" name="attributeId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="27" parent="7" name="noteId">
 | 
					    <column id="28" parent="7" name="noteId">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="28" parent="7" name="type">
 | 
					    <column id="29" parent="7" name="type">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="29" parent="7" name="name">
 | 
					    <column id="30" parent="7" name="name">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="30" parent="7" name="value">
 | 
					    <column id="31" parent="7" name="value">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>''</DefaultExpression>
 | 
					      <DefaultExpression>''</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="31" parent="7" name="position">
 | 
					    <column id="32" parent="7" name="position">
 | 
				
			||||||
      <Position>6</Position>
 | 
					      <Position>6</Position>
 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="32" parent="7" name="dateCreated">
 | 
					    <column id="33" parent="7" name="dateCreated">
 | 
				
			||||||
      <Position>7</Position>
 | 
					      <Position>7</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="33" parent="7" name="dateModified">
 | 
					    <column id="34" parent="7" name="dateModified">
 | 
				
			||||||
      <Position>8</Position>
 | 
					      <Position>8</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="34" parent="7" name="isDeleted">
 | 
					    <column id="35" parent="7" name="isDeleted">
 | 
				
			||||||
      <Position>9</Position>
 | 
					      <Position>9</Position>
 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="35" parent="7" name="hash">
 | 
					    <column id="36" parent="7" name="hash">
 | 
				
			||||||
      <Position>10</Position>
 | 
					      <Position>10</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="36" parent="7" name="isInheritable">
 | 
					    <column id="37" parent="7" name="isInheritable">
 | 
				
			||||||
      <Position>11</Position>
 | 
					      <Position>11</Position>
 | 
				
			||||||
      <DataType>int|0s</DataType>
 | 
					      <DataType>int|0s</DataType>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="37" parent="7" name="sqlite_autoindex_attributes_1">
 | 
					    <index id="38" parent="7" name="sqlite_autoindex_attributes_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>attributeId</ColNames>
 | 
					      <ColNames>attributeId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="38" parent="7">
 | 
					    <index id="39" parent="7" name="IDX_attributes_noteId_index">
 | 
				
			||||||
 | 
					      <ColNames>noteId</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <index id="40" parent="7" name="IDX_attributes_name_value">
 | 
				
			||||||
 | 
					      <ColNames>name
 | 
				
			||||||
 | 
					value</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <index id="41" parent="7" name="IDX_attributes_name_index">
 | 
				
			||||||
 | 
					      <ColNames>name</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <index id="42" parent="7" name="IDX_attributes_value_index">
 | 
				
			||||||
 | 
					      <ColNames>value</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <key id="43" parent="7">
 | 
				
			||||||
      <ColNames>attributeId</ColNames>
 | 
					      <ColNames>attributeId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_attributes_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_attributes_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="39" parent="8" name="branchId">
 | 
					    <column id="44" parent="8" name="branchId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="40" parent="8" name="noteId">
 | 
					    <column id="45" parent="8" name="noteId">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="41" parent="8" name="parentNoteId">
 | 
					    <column id="46" parent="8" name="parentNoteId">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="42" parent="8" name="notePosition">
 | 
					    <column id="47" parent="8" name="notePosition">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>INTEGER|0s</DataType>
 | 
					      <DataType>INTEGER|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="43" parent="8" name="prefix">
 | 
					    <column id="48" parent="8" name="prefix">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="44" parent="8" name="isExpanded">
 | 
					    <column id="49" parent="8" name="isExpanded">
 | 
				
			||||||
      <Position>6</Position>
 | 
					      <Position>6</Position>
 | 
				
			||||||
      <DataType>BOOLEAN|0s</DataType>
 | 
					      <DataType>BOOLEAN|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="45" parent="8" name="isDeleted">
 | 
					    <column id="50" parent="8" name="isDeleted">
 | 
				
			||||||
      <Position>7</Position>
 | 
					      <Position>7</Position>
 | 
				
			||||||
      <DataType>INTEGER|0s</DataType>
 | 
					      <DataType>INTEGER|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="46" parent="8" name="dateModified">
 | 
					    <column id="51" parent="8" name="dateModified">
 | 
				
			||||||
      <Position>8</Position>
 | 
					      <Position>8</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="47" parent="8" name="hash">
 | 
					    <column id="52" parent="8" name="hash">
 | 
				
			||||||
      <Position>9</Position>
 | 
					      <Position>9</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="48" parent="8" name="dateCreated">
 | 
					    <column id="53" parent="8" name="dateCreated">
 | 
				
			||||||
      <Position>10</Position>
 | 
					      <Position>10</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
 | 
					      <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="49" parent="8" name="sqlite_autoindex_branches_1">
 | 
					    <index id="54" parent="8" name="sqlite_autoindex_branches_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>branchId</ColNames>
 | 
					      <ColNames>branchId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <index id="50" parent="8" name="IDX_branches_noteId_parentNoteId">
 | 
					    <index id="55" parent="8" name="IDX_branches_noteId_parentNoteId">
 | 
				
			||||||
      <ColNames>noteId
 | 
					      <ColNames>noteId
 | 
				
			||||||
parentNoteId</ColNames>
 | 
					parentNoteId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <index id="51" parent="8" name="IDX_branches_noteId">
 | 
					    <index id="56" parent="8" name="IDX_branches_noteId">
 | 
				
			||||||
      <ColNames>noteId</ColNames>
 | 
					      <ColNames>noteId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <index id="52" parent="8" name="IDX_branches_parentNoteId">
 | 
					    <index id="57" parent="8" name="IDX_branches_parentNoteId">
 | 
				
			||||||
      <ColNames>parentNoteId</ColNames>
 | 
					      <ColNames>parentNoteId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="53" parent="8">
 | 
					    <key id="58" parent="8">
 | 
				
			||||||
      <ColNames>branchId</ColNames>
 | 
					      <ColNames>branchId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="54" parent="9" name="eventId">
 | 
					    <column id="59" parent="9" name="eventId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="55" parent="9" name="noteId">
 | 
					    <column id="60" parent="9" name="noteId">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="56" parent="9" name="comment">
 | 
					    <column id="61" parent="9" name="comment">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="57" parent="9" name="dateCreated">
 | 
					    <column id="62" parent="9" name="dateCreated">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="58" parent="9" name="sqlite_autoindex_event_log_1">
 | 
					    <index id="63" parent="9" name="sqlite_autoindex_event_log_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>eventId</ColNames>
 | 
					      <ColNames>eventId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="59" parent="9">
 | 
					    <key id="64" parent="9">
 | 
				
			||||||
      <ColNames>eventId</ColNames>
 | 
					      <ColNames>eventId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_event_log_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_event_log_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="60" parent="10" name="linkId">
 | 
					    <column id="65" parent="10" name="linkId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="61" parent="10" name="noteId">
 | 
					    <column id="66" parent="10" name="noteId">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="62" parent="10" name="targetNoteId">
 | 
					    <column id="67" parent="10" name="targetNoteId">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="63" parent="10" name="type">
 | 
					    <column id="68" parent="10" name="type">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="64" parent="10" name="isDeleted">
 | 
					    <column id="69" parent="10" name="hash">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>INTEGER|0s</DataType>
 | 
					 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					 | 
				
			||||||
    </column>
 | 
					 | 
				
			||||||
    <column id="65" parent="10" name="dateCreated">
 | 
					 | 
				
			||||||
      <Position>6</Position>
 | 
					 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					 | 
				
			||||||
    </column>
 | 
					 | 
				
			||||||
    <column id="66" parent="10" name="dateModified">
 | 
					 | 
				
			||||||
      <Position>7</Position>
 | 
					 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					 | 
				
			||||||
    </column>
 | 
					 | 
				
			||||||
    <column id="67" parent="10" name="hash">
 | 
					 | 
				
			||||||
      <Position>8</Position>
 | 
					 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="68" parent="10" name="sqlite_autoindex_links_1">
 | 
					    <column id="70" parent="10" name="isDeleted">
 | 
				
			||||||
 | 
					      <Position>6</Position>
 | 
				
			||||||
 | 
					      <DataType>INTEGER|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="71" parent="10" name="dateCreated">
 | 
				
			||||||
 | 
					      <Position>7</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="72" parent="10" name="dateModified">
 | 
				
			||||||
 | 
					      <Position>8</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <index id="73" parent="10" name="sqlite_autoindex_links_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>linkId</ColNames>
 | 
					      <ColNames>linkId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="69" parent="10">
 | 
					    <index id="74" parent="10" name="IDX_links_noteId_index">
 | 
				
			||||||
 | 
					      <ColNames>noteId</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <index id="75" parent="10" name="IDX_links_targetNoteId_index">
 | 
				
			||||||
 | 
					      <ColNames>targetNoteId</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <key id="76" parent="10">
 | 
				
			||||||
      <ColNames>linkId</ColNames>
 | 
					      <ColNames>linkId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_links_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_links_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="70" parent="11" name="noteRevisionId">
 | 
					    <column id="77" parent="11" name="noteContentId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="71" parent="11" name="noteId">
 | 
					    <column id="78" parent="11" name="noteId">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="72" parent="11" name="title">
 | 
					    <column id="79" parent="11" name="isProtected">
 | 
				
			||||||
 | 
					      <Position>3</Position>
 | 
				
			||||||
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="80" parent="11" name="content">
 | 
				
			||||||
 | 
					      <Position>4</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <DefaultExpression>NULL</DefaultExpression>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="81" parent="11" name="hash">
 | 
				
			||||||
 | 
					      <Position>5</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="82" parent="11" name="dateCreated">
 | 
				
			||||||
 | 
					      <Position>6</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					      <DefaultExpression>'2018-05-08T23:41:15.225Z'</DefaultExpression>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="83" parent="11" name="dateModified">
 | 
				
			||||||
 | 
					      <Position>7</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					      <DefaultExpression>'2018-05-08T23:41:15.225Z'</DefaultExpression>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <index id="84" parent="11" name="sqlite_autoindex_note_contents_1">
 | 
				
			||||||
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
 | 
					      <ColNames>noteContentId</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <index id="85" parent="11" name="IDX_note_contents_noteId">
 | 
				
			||||||
 | 
					      <ColNames>noteId</ColNames>
 | 
				
			||||||
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
 | 
					    </index>
 | 
				
			||||||
 | 
					    <key id="86" parent="11">
 | 
				
			||||||
 | 
					      <ColNames>noteContentId</ColNames>
 | 
				
			||||||
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
 | 
					      <UnderlyingIndexName>sqlite_autoindex_note_contents_1</UnderlyingIndexName>
 | 
				
			||||||
 | 
					    </key>
 | 
				
			||||||
 | 
					    <column id="87" parent="12" name="noteRevisionId">
 | 
				
			||||||
 | 
					      <Position>1</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="88" parent="12" name="noteId">
 | 
				
			||||||
 | 
					      <Position>2</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="89" parent="12" name="title">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="73" parent="11" name="content">
 | 
					    <column id="90" parent="12" name="content">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="74" parent="11" name="isProtected">
 | 
					    <column id="91" parent="12" name="isProtected">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="75" parent="11" name="dateModifiedFrom">
 | 
					    <column id="92" parent="12" name="dateModifiedFrom">
 | 
				
			||||||
      <Position>6</Position>
 | 
					      <Position>6</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="76" parent="11" name="dateModifiedTo">
 | 
					    <column id="93" parent="12" name="dateModifiedTo">
 | 
				
			||||||
      <Position>7</Position>
 | 
					      <Position>7</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="77" parent="11" name="type">
 | 
					    <column id="94" parent="12" name="type">
 | 
				
			||||||
      <Position>8</Position>
 | 
					      <Position>8</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>''</DefaultExpression>
 | 
					      <DefaultExpression>''</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="78" parent="11" name="mime">
 | 
					    <column id="95" parent="12" name="mime">
 | 
				
			||||||
      <Position>9</Position>
 | 
					      <Position>9</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>''</DefaultExpression>
 | 
					      <DefaultExpression>''</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="79" parent="11" name="hash">
 | 
					    <column id="96" parent="12" name="hash">
 | 
				
			||||||
      <Position>10</Position>
 | 
					      <Position>10</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="80" parent="11" name="sqlite_autoindex_note_revisions_1">
 | 
					    <index id="97" parent="12" name="sqlite_autoindex_note_revisions_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>noteRevisionId</ColNames>
 | 
					      <ColNames>noteRevisionId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <index id="81" parent="11" name="IDX_note_revisions_noteId">
 | 
					    <index id="98" parent="12" name="IDX_note_revisions_noteId">
 | 
				
			||||||
      <ColNames>noteId</ColNames>
 | 
					      <ColNames>noteId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <index id="82" parent="11" name="IDX_note_revisions_dateModifiedFrom">
 | 
					    <index id="99" parent="12" name="IDX_note_revisions_dateModifiedFrom">
 | 
				
			||||||
      <ColNames>dateModifiedFrom</ColNames>
 | 
					      <ColNames>dateModifiedFrom</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <index id="83" parent="11" name="IDX_note_revisions_dateModifiedTo">
 | 
					    <index id="100" parent="12" name="IDX_note_revisions_dateModifiedTo">
 | 
				
			||||||
      <ColNames>dateModifiedTo</ColNames>
 | 
					      <ColNames>dateModifiedTo</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="84" parent="11">
 | 
					    <key id="101" parent="12">
 | 
				
			||||||
      <ColNames>noteRevisionId</ColNames>
 | 
					      <ColNames>noteRevisionId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="85" parent="12" name="noteId">
 | 
					    <column id="102" parent="13" name="noteId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="86" parent="12" name="title">
 | 
					    <column id="103" parent="13" name="title">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>"note"</DefaultExpression>
 | 
					      <DefaultExpression>"note"</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="87" parent="12" name="content">
 | 
					    <column id="104" parent="13" name="isProtected">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					 | 
				
			||||||
      <DefaultExpression>NULL</DefaultExpression>
 | 
					 | 
				
			||||||
    </column>
 | 
					 | 
				
			||||||
    <column id="88" parent="12" name="isProtected">
 | 
					 | 
				
			||||||
      <Position>4</Position>
 | 
					 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="89" parent="12" name="type">
 | 
					    <column id="105" parent="13" name="type">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>'text'</DefaultExpression>
 | 
					      <DefaultExpression>'text'</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="90" parent="12" name="mime">
 | 
					    <column id="106" parent="13" name="mime">
 | 
				
			||||||
      <Position>6</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>'text/html'</DefaultExpression>
 | 
					      <DefaultExpression>'text/html'</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="91" parent="12" name="hash">
 | 
					    <column id="107" parent="13" name="hash">
 | 
				
			||||||
      <Position>7</Position>
 | 
					      <Position>6</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="92" parent="12" name="isDeleted">
 | 
					    <column id="108" parent="13" name="isDeleted">
 | 
				
			||||||
      <Position>8</Position>
 | 
					      <Position>7</Position>
 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="93" parent="12" name="dateCreated">
 | 
					    <column id="109" parent="13" name="dateCreated">
 | 
				
			||||||
 | 
					      <Position>8</Position>
 | 
				
			||||||
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
 | 
					    </column>
 | 
				
			||||||
 | 
					    <column id="110" parent="13" name="dateModified">
 | 
				
			||||||
      <Position>9</Position>
 | 
					      <Position>9</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="94" parent="12" name="dateModified">
 | 
					    <index id="111" parent="13" name="sqlite_autoindex_notes_1">
 | 
				
			||||||
      <Position>10</Position>
 | 
					 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					 | 
				
			||||||
    </column>
 | 
					 | 
				
			||||||
    <index id="95" parent="12" name="sqlite_autoindex_notes_1">
 | 
					 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>noteId</ColNames>
 | 
					      <ColNames>noteId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="96" parent="12">
 | 
					    <key id="112" parent="13">
 | 
				
			||||||
      <ColNames>noteId</ColNames>
 | 
					      <ColNames>noteId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="97" parent="13" name="name">
 | 
					    <column id="113" parent="14" name="name">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="98" parent="13" name="value">
 | 
					    <column id="114" parent="14" name="value">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="99" parent="13" name="dateModified">
 | 
					    <column id="115" parent="14" name="dateModified">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="100" parent="13" name="isSynced">
 | 
					    <column id="116" parent="14" name="isSynced">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>INTEGER|0s</DataType>
 | 
					      <DataType>INTEGER|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>0</DefaultExpression>
 | 
					      <DefaultExpression>0</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="101" parent="13" name="hash">
 | 
					    <column id="117" parent="14" name="hash">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="102" parent="13" name="dateCreated">
 | 
					    <column id="118" parent="14" name="dateCreated">
 | 
				
			||||||
      <Position>6</Position>
 | 
					      <Position>6</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
 | 
					      <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="103" parent="13" name="sqlite_autoindex_options_1">
 | 
					    <index id="119" parent="14" name="sqlite_autoindex_options_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>name</ColNames>
 | 
					      <ColNames>name</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="104" parent="13">
 | 
					    <key id="120" parent="14">
 | 
				
			||||||
      <ColNames>name</ColNames>
 | 
					      <ColNames>name</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="105" parent="14" name="branchId">
 | 
					    <column id="121" parent="15" name="branchId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="106" parent="14" name="notePath">
 | 
					    <column id="122" parent="15" name="notePath">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="107" parent="14" name="hash">
 | 
					    <column id="123" parent="15" name="hash">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <DefaultExpression>""</DefaultExpression>
 | 
					      <DefaultExpression>""</DefaultExpression>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="108" parent="14" name="dateCreated">
 | 
					    <column id="124" parent="15" name="dateCreated">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="109" parent="14" name="isDeleted">
 | 
					    <column id="125" parent="15" name="isDeleted">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>INT|0s</DataType>
 | 
					      <DataType>INT|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="110" parent="14" name="sqlite_autoindex_recent_notes_1">
 | 
					    <index id="126" parent="15" name="sqlite_autoindex_recent_notes_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>branchId</ColNames>
 | 
					      <ColNames>branchId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="111" parent="14">
 | 
					    <key id="127" parent="15">
 | 
				
			||||||
      <ColNames>branchId</ColNames>
 | 
					      <ColNames>branchId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="112" parent="15" name="sourceId">
 | 
					    <column id="128" parent="16" name="sourceId">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="113" parent="15" name="dateCreated">
 | 
					    <column id="129" parent="16" name="dateCreated">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="114" parent="15" name="sqlite_autoindex_source_ids_1">
 | 
					    <index id="130" parent="16" name="sqlite_autoindex_source_ids_1">
 | 
				
			||||||
      <NameSurrogate>1</NameSurrogate>
 | 
					      <NameSurrogate>1</NameSurrogate>
 | 
				
			||||||
      <ColNames>sourceId</ColNames>
 | 
					      <ColNames>sourceId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="115" parent="15">
 | 
					    <key id="131" parent="16">
 | 
				
			||||||
      <ColNames>sourceId</ColNames>
 | 
					      <ColNames>sourceId</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
      <UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
 | 
					      <UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <column id="116" parent="16" name="type">
 | 
					    <column id="132" parent="17" name="type">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>text|0s</DataType>
 | 
					      <DataType>text|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="117" parent="16" name="name">
 | 
					    <column id="133" parent="17" name="name">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>text|0s</DataType>
 | 
					      <DataType>text|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="118" parent="16" name="tbl_name">
 | 
					    <column id="134" parent="17" name="tbl_name">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>text|0s</DataType>
 | 
					      <DataType>text|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="119" parent="16" name="rootpage">
 | 
					    <column id="135" parent="17" name="rootpage">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>integer|0s</DataType>
 | 
					      <DataType>integer|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="120" parent="16" name="sql">
 | 
					    <column id="136" parent="17" name="sql">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>text|0s</DataType>
 | 
					      <DataType>text|0s</DataType>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="121" parent="17" name="name">
 | 
					    <column id="137" parent="18" name="name">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="122" parent="17" name="seq">
 | 
					    <column id="138" parent="18" name="seq">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="123" parent="18" name="id">
 | 
					    <column id="139" parent="19" name="id">
 | 
				
			||||||
      <Position>1</Position>
 | 
					      <Position>1</Position>
 | 
				
			||||||
      <DataType>INTEGER|0s</DataType>
 | 
					      <DataType>INTEGER|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
      <SequenceIdentity>1</SequenceIdentity>
 | 
					      <SequenceIdentity>1</SequenceIdentity>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="124" parent="18" name="entityName">
 | 
					    <column id="140" parent="19" name="entityName">
 | 
				
			||||||
      <Position>2</Position>
 | 
					      <Position>2</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="125" parent="18" name="entityId">
 | 
					    <column id="141" parent="19" name="entityId">
 | 
				
			||||||
      <Position>3</Position>
 | 
					      <Position>3</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="126" parent="18" name="sourceId">
 | 
					    <column id="142" parent="19" name="sourceId">
 | 
				
			||||||
      <Position>4</Position>
 | 
					      <Position>4</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <column id="127" parent="18" name="syncDate">
 | 
					    <column id="143" parent="19" name="syncDate">
 | 
				
			||||||
      <Position>5</Position>
 | 
					      <Position>5</Position>
 | 
				
			||||||
      <DataType>TEXT|0s</DataType>
 | 
					      <DataType>TEXT|0s</DataType>
 | 
				
			||||||
      <NotNull>1</NotNull>
 | 
					      <NotNull>1</NotNull>
 | 
				
			||||||
    </column>
 | 
					    </column>
 | 
				
			||||||
    <index id="128" parent="18" name="IDX_sync_entityName_entityId">
 | 
					    <index id="144" parent="19" name="IDX_sync_entityName_entityId">
 | 
				
			||||||
      <ColNames>entityName
 | 
					      <ColNames>entityName
 | 
				
			||||||
entityId</ColNames>
 | 
					entityId</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
      <Unique>1</Unique>
 | 
					      <Unique>1</Unique>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <index id="129" parent="18" name="IDX_sync_syncDate">
 | 
					    <index id="145" parent="19" name="IDX_sync_syncDate">
 | 
				
			||||||
      <ColNames>syncDate</ColNames>
 | 
					      <ColNames>syncDate</ColNames>
 | 
				
			||||||
      <ColumnCollations></ColumnCollations>
 | 
					      <ColumnCollations></ColumnCollations>
 | 
				
			||||||
    </index>
 | 
					    </index>
 | 
				
			||||||
    <key id="130" parent="18">
 | 
					    <key id="146" parent="19">
 | 
				
			||||||
      <ColNames>id</ColNames>
 | 
					      <ColNames>id</ColNames>
 | 
				
			||||||
      <Primary>1</Primary>
 | 
					      <Primary>1</Primary>
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
FROM node:10.14.0-alpine
 | 
					FROM node:10.15.0-alpine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Create app directory
 | 
					# Create app directory
 | 
				
			||||||
WORKDIR /usr/src/app
 | 
					WORKDIR /usr/src/app
 | 
				
			||||||
@@ -17,6 +17,7 @@ RUN set -x \
 | 
				
			|||||||
        libtool \
 | 
					        libtool \
 | 
				
			||||||
        make \
 | 
					        make \
 | 
				
			||||||
        nasm \
 | 
					        nasm \
 | 
				
			||||||
 | 
					        libpng-dev \
 | 
				
			||||||
    && npm install --production \
 | 
					    && npm install --production \
 | 
				
			||||||
    && apk del .build-dependencies
 | 
					    && apk del .build-dependencies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.md
									
									
									
									
									
								
							@@ -10,7 +10,7 @@ Trilium Notes is a hierarchical note taking application with focus on building l
 | 
				
			|||||||
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://github.com/zadam/trilium/wiki/Cloning-notes))
 | 
					* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://github.com/zadam/trilium/wiki/Cloning-notes))
 | 
				
			||||||
* Rich WYSIWYG note editing including e.g. tables and images with markdown [autoformat](https://github.com/zadam/trilium/wiki/Text-editor#autoformat)
 | 
					* Rich WYSIWYG note editing including e.g. tables and images with markdown [autoformat](https://github.com/zadam/trilium/wiki/Text-editor#autoformat)
 | 
				
			||||||
* Support for editing [notes with source code](https://github.com/zadam/trilium/wiki/Code-notes), including syntax highlighting
 | 
					* Support for editing [notes with source code](https://github.com/zadam/trilium/wiki/Code-notes), including syntax highlighting
 | 
				
			||||||
* Fast and easy [navigation between notes](https://github.com/zadam/trilium/wiki/Note-navigation)
 | 
					* Fast and easy [navigation between notes](https://github.com/zadam/trilium/wiki/Note-navigation), full text search and [note hoisting](https://github.com/zadam/trilium/wiki/Note-hoisting)
 | 
				
			||||||
* Seamless [note versioning](https://github.com/zadam/trilium/wiki/Note-revisions)
 | 
					* Seamless [note versioning](https://github.com/zadam/trilium/wiki/Note-revisions)
 | 
				
			||||||
* Note [attributes](https://github.com/zadam/trilium/wiki/Attributes) can be used for note organization, querying and advanced [scripting](https://github.com/zadam/trilium/wiki/Scripts)
 | 
					* Note [attributes](https://github.com/zadam/trilium/wiki/Attributes) can be used for note organization, querying and advanced [scripting](https://github.com/zadam/trilium/wiki/Scripts)
 | 
				
			||||||
* [Synchronization](https://github.com/zadam/trilium/wiki/Synchronization) with self-hosted sync server
 | 
					* [Synchronization](https://github.com/zadam/trilium/wiki/Synchronization) with self-hosted sync server
 | 
				
			||||||
@@ -18,14 +18,15 @@ Trilium Notes is a hierarchical note taking application with focus on building l
 | 
				
			|||||||
* [Relation maps](https://github.com/zadam/trilium/wiki/Relation-map) for visualizing notes and their relations
 | 
					* [Relation maps](https://github.com/zadam/trilium/wiki/Relation-map) for visualizing notes and their relations
 | 
				
			||||||
* [Scripting](https://github.com/zadam/trilium/wiki/Scripts) - see [Advanced showcases](https://github.com/zadam/trilium/wiki/Advanced-showcases)
 | 
					* [Scripting](https://github.com/zadam/trilium/wiki/Scripts) - see [Advanced showcases](https://github.com/zadam/trilium/wiki/Advanced-showcases)
 | 
				
			||||||
* Scales well in both usability and performance upwards of 100 000 notes
 | 
					* Scales well in both usability and performance upwards of 100 000 notes
 | 
				
			||||||
 | 
					* Touch optimized [mobile frontend](https://github.com/zadam/trilium/wiki/Mobile-frontend) for smartphones and tablets
 | 
				
			||||||
* [Night theme](https://github.com/zadam/trilium/wiki/Themes)
 | 
					* [Night theme](https://github.com/zadam/trilium/wiki/Themes)
 | 
				
			||||||
* [Evernote](https://github.com/zadam/trilium/wiki/Evernote-import) and [Markdown import & export](https://github.com/zadam/trilium/wiki/Markdown)
 | 
					* [Evernote](https://github.com/zadam/trilium/wiki/Evernote-import) and [Markdown import & export](https://github.com/zadam/trilium/wiki/Markdown)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Builds
 | 
					## Builds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Trilium is provided as either desktop application (Linux, Windows) or web application hosted on your server (Linux). Mac is planned but not available at the moment.
 | 
					Trilium is provided as either desktop application (Linux, Windows, Mac) or web application hosted on your server (Linux).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* If you want to use Trilium on the desktop, download binary release for your platform (currently Linux and Windows are supported) from [latest release](https://github.com/zadam/trilium/releases/latest), unzip the package and run ```trilium``` executable.
 | 
					* If you want to use Trilium on the desktop, download binary release for your platform from [latest release](https://github.com/zadam/trilium/releases/latest), unzip the package and run ```trilium``` executable.
 | 
				
			||||||
* If you want to install Trilium on server, follow [this page](https://github.com/zadam/trilium/wiki/Server-installation).
 | 
					* If you want to install Trilium on server, follow [this page](https://github.com/zadam/trilium/wiki/Server-installation).
 | 
				
			||||||
  * Currently only recent Chrome and Firefox are supported (tested) browsers.
 | 
					  * Currently only recent Chrome and Firefox are supported (tested) browsers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,3 +35,15 @@ Trilium is provided as either desktop application (Linux, Windows) or web applic
 | 
				
			|||||||
[See wiki for complete list of documentation pages.](https://github.com/zadam/trilium/wiki/)
 | 
					[See wiki for complete list of documentation pages.](https://github.com/zadam/trilium/wiki/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can also read [Patterns of personal knowledge base](https://github.com/zadam/trilium/wiki/Patterns-of-personal-knowledge-base) to get some inspiration on how you might use Trilium.
 | 
					You can also read [Patterns of personal knowledge base](https://github.com/zadam/trilium/wiki/Patterns-of-personal-knowledge-base) to get some inspiration on how you might use Trilium.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Contribute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use a browser based dev environment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[](https://gitpod.io/#https://github.com/zadam/trilium)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Or clone locally and run
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					npm install
 | 
				
			||||||
 | 
					npm run start
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										7
									
								
								bin/build-debian.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										7
									
								
								bin/build-debian.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Packaging debian x64 distribution..."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VERSION=`jq -r ".version" package.json`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					./node_modules/.bin/electron-installer-debian --config bin/deb-options.json --options.version=${VERSION} --arch amd64
 | 
				
			||||||
@@ -3,22 +3,22 @@
 | 
				
			|||||||
BUILD_DIR=./dist/trilium-linux-x64
 | 
					BUILD_DIR=./dist/trilium-linux-x64
 | 
				
			||||||
rm -rf $BUILD_DIR
 | 
					rm -rf $BUILD_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# we build x64 as second so that we keep X64 binaries in node_modules for local development and server build
 | 
					rm -r node_modules/sqlite3/lib/binding/*
 | 
				
			||||||
echo "Rebuilding binaries for linux-x64"
 | 
					 | 
				
			||||||
./node_modules/.bin/electron-rebuild --arch=x64
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
./node_modules/.bin/electron-packager . --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
 | 
					cp -r bin/deps/linux-x64/sqlite/* node_modules/sqlite3/lib/binding/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					./node_modules/.bin/electron-packager . --asar --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mv "./dist/Trilium Notes-linux-x64" $BUILD_DIR
 | 
					mv "./dist/Trilium Notes-linux-x64" $BUILD_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rm -r "$BUILD_DIR/resources/app/node_modules/sqlite3/lib/binding/*"
 | 
					cp src/public/images/app-icons/png/128x128.png $BUILD_DIR/icon.png
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cp -r bin/deps/linux-x64/sqlite/electron* "$BUILD_DIR/resources/app/node_modules/sqlite3/lib/binding/"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
rm -r $BUILD_DIR/resources/app/bin/deps
 | 
					 | 
				
			||||||
# removing software WebGL binaries because they are pretty huge and not necessary
 | 
					# removing software WebGL binaries because they are pretty huge and not necessary
 | 
				
			||||||
rm -r $BUILD_DIR/swiftshader
 | 
					rm -r $BUILD_DIR/swiftshader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Packaging linux x64 electron distribution..."
 | 
					echo "Packaging linux x64 electron distribution..."
 | 
				
			||||||
VERSION=`jq -r ".version" package.json`
 | 
					VERSION=`jq -r ".version" package.json`
 | 
				
			||||||
7z a $BUILD_DIR-${VERSION}.7z $BUILD_DIR
 | 
					
 | 
				
			||||||
 | 
					cd dist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tar cJf trilium-linux-x64-${VERSION}.tar.xz trilium-linux-x64
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,25 +3,30 @@
 | 
				
			|||||||
BUILD_DIR=./dist/trilium-mac-x64
 | 
					BUILD_DIR=./dist/trilium-mac-x64
 | 
				
			||||||
rm -rf $BUILD_DIR
 | 
					rm -rf $BUILD_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
./node_modules/.bin/electron-packager . --out=dist --executable-name=trilium --platform=darwin  --arch=x64 --overwrite --icon=src/public/images/app-icons/mac/icon.icns
 | 
					echo "Copying required mac binaries"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rm -r node_modules/sqlite3/lib/binding/*
 | 
				
			||||||
 | 
					rm -r node_modules/mozjpeg/vendor/*
 | 
				
			||||||
 | 
					rm -r node_modules/pngquant-bin/vendor/*
 | 
				
			||||||
 | 
					rm -r node_modules/giflossy/vendor/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cp -r bin/deps/mac-x64/sqlite/* node_modules/sqlite3/lib/binding/
 | 
				
			||||||
 | 
					cp bin/deps/mac-x64/image/cjpeg node_modules/mozjpeg/vendor/
 | 
				
			||||||
 | 
					cp bin/deps/mac-x64/image/pngquant node_modules/pngquant-bin/vendor/
 | 
				
			||||||
 | 
					cp bin/deps/mac-x64/image/gifsicle node_modules/giflossy/vendor/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					./node_modules/.bin/electron-packager . --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=src/public/images/app-icons/mac/icon.icns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Mac build has by default useless directory level
 | 
					# Mac build has by default useless directory level
 | 
				
			||||||
mv "./dist/Trilium Notes-darwin-x64" $BUILD_DIR
 | 
					mv "./dist/Trilium Notes-darwin-x64" $BUILD_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Copying required mac binaries"
 | 
					./bin/reset-local.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MAC_RES_DIR=$BUILD_DIR/Trilium\ Notes.app/Contents/Resources/app
 | 
					echo "Zipping mac x64 electron distribution..."
 | 
				
			||||||
 | 
					 | 
				
			||||||
rm -r "$MAC_RES_DIR/node_modules/sqlite3/lib/binding/*"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cp -r bin/deps/mac-x64/sqlite/* "$MAC_RES_DIR/node_modules/sqlite3/lib/binding/"
 | 
					 | 
				
			||||||
cp bin/deps/mac-x64/image/cjpeg "$MAC_RES_DIR/node_modules/mozjpeg/vendor/"
 | 
					 | 
				
			||||||
cp bin/deps/mac-x64/image/pngquant "$MAC_RES_DIR/node_modules/pngquant-bin/vendor/"
 | 
					 | 
				
			||||||
cp bin/deps/mac-x64/image/gifsicle "$MAC_RES_DIR/node_modules/giflossy/vendor/"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
rm -r "$MAC_RES_DIR/bin/deps"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
echo "Packaging mac x64 electron distribution..."
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
VERSION=`jq -r ".version" package.json`
 | 
					VERSION=`jq -r ".version" package.json`
 | 
				
			||||||
7z a $BUILD_DIR-${VERSION}.7z $BUILD_DIR
 | 
					
 | 
				
			||||||
 | 
					cd dist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rm trilium-mac-x64-${VERSION}.zip
 | 
				
			||||||
 | 
					zip -r9 --symlinks trilium-mac-x64-${VERSION}.zip trilium-mac-x64
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
#!/usr/bin/env bash
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_DIR=dist/trilium-linux-x64-server
 | 
					PKG_DIR=dist/trilium-linux-x64-server
 | 
				
			||||||
NODE_VERSION=10.14.1
 | 
					NODE_VERSION=10.15.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rm -r $PKG_DIR
 | 
					rm -r $PKG_DIR
 | 
				
			||||||
mkdir $PKG_DIR
 | 
					mkdir $PKG_DIR
 | 
				
			||||||
@@ -33,5 +33,6 @@ chmod 755 trilium.sh
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
cd ..
 | 
					cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VERSION=`jq -r ".version" ../../package.json`
 | 
					VERSION=`jq -r ".version" ../package.json`
 | 
				
			||||||
7z a trilium-linux-x64-server-${VERSION}.7z trilium-linux-x64-server
 | 
					
 | 
				
			||||||
 | 
					tar cJf trilium-linux-x64-server-${VERSION}.tar.xz trilium-linux-x64-server
 | 
				
			||||||
@@ -3,23 +3,30 @@
 | 
				
			|||||||
BUILD_DIR=./dist/trilium-windows-x64
 | 
					BUILD_DIR=./dist/trilium-windows-x64
 | 
				
			||||||
rm -rf $BUILD_DIR
 | 
					rm -rf $BUILD_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
./node_modules/.bin/electron-packager . --out=dist --executable-name=trilium --platform=win32  --arch=x64 --overwrite --icon=src/public/images/app-icons/win/icon.ico
 | 
					echo "Copying required windows binaries"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rm -r node_modules/sqlite3/lib/binding/*
 | 
				
			||||||
 | 
					rm -r node_modules/mozjpeg/vendor/*
 | 
				
			||||||
 | 
					rm -r node_modules/pngquant-bin/vendor/*
 | 
				
			||||||
 | 
					rm -r node_modules/giflossy/vendor/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cp -r bin/deps/win-x64/sqlite/* node_modules/sqlite3/lib/binding/
 | 
				
			||||||
 | 
					cp bin/deps/win-x64/image/cjpeg.exe node_modules/mozjpeg/vendor/
 | 
				
			||||||
 | 
					cp bin/deps/win-x64/image/pngquant.exe node_modules/pngquant-bin/vendor/
 | 
				
			||||||
 | 
					cp bin/deps/win-x64/image/gifsicle.exe node_modules/giflossy/vendor/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					./node_modules/.bin/electron-packager . --asar --out=dist --executable-name=trilium --platform=win32  --arch=x64 --overwrite --icon=src/public/images/app-icons/win/icon.ico
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mv "./dist/Trilium Notes-win32-x64" $BUILD_DIR
 | 
					mv "./dist/Trilium Notes-win32-x64" $BUILD_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Copying required windows binaries"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WIN_RES_DIR=$BUILD_DIR/resources/app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cp -r bin/deps/win-x64/sqlite/* $WIN_RES_DIR/node_modules/sqlite3/lib/binding/
 | 
					 | 
				
			||||||
cp bin/deps/win-x64/image/cjpeg.exe $WIN_RES_DIR/node_modules/mozjpeg/vendor/
 | 
					 | 
				
			||||||
cp bin/deps/win-x64/image/pngquant.exe $WIN_RES_DIR/node_modules/pngquant-bin/vendor/
 | 
					 | 
				
			||||||
cp bin/deps/win-x64/image/gifsicle.exe $WIN_RES_DIR/node_modules/giflossy/vendor/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
rm -r $WIN_RES_DIR/bin/deps
 | 
					 | 
				
			||||||
# removing software WebGL binaries because they are pretty huge and not necessary
 | 
					# removing software WebGL binaries because they are pretty huge and not necessary
 | 
				
			||||||
rm -r $BUILD_DIR/swiftshader
 | 
					rm -r $BUILD_DIR/swiftshader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Packaging windows x64 electron distribution..."
 | 
					./bin/reset-local.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Zipping windows x64 electron distribution..."
 | 
				
			||||||
VERSION=`jq -r ".version" package.json`
 | 
					VERSION=`jq -r ".version" package.json`
 | 
				
			||||||
7z a $BUILD_DIR-${VERSION}.7z $BUILD_DIR
 | 
					
 | 
				
			||||||
 | 
					cd dist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					zip -r9 trilium-windows-x64-${VERSION}.zip trilium-windows-x64
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,4 +15,7 @@ bin/build-mac-x64.sh
 | 
				
			|||||||
# building X64 linux as the last so electron-rebuild will prepare X64 binaries for local development
 | 
					# building X64 linux as the last so electron-rebuild will prepare X64 binaries for local development
 | 
				
			||||||
bin/build-linux-x64.sh
 | 
					bin/build-linux-x64.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# this needs to be run after linux build
 | 
				
			||||||
 | 
					bin/build-debian.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bin/build-server.sh
 | 
					bin/build-server.sh
 | 
				
			||||||
							
								
								
									
										14
									
								
								bin/deb-options.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								bin/deb-options.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "src": "dist/trilium-linux-x64",
 | 
				
			||||||
 | 
					  "dest": "dist/",
 | 
				
			||||||
 | 
					  "name": "trilium",
 | 
				
			||||||
 | 
					  "productName": "Trilium Notes",
 | 
				
			||||||
 | 
					  "genericName": "Note taker",
 | 
				
			||||||
 | 
					  "description": "Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases.",
 | 
				
			||||||
 | 
					  "sections": "misc",
 | 
				
			||||||
 | 
					  "maintainer": "zadam.apps@gmail.com",
 | 
				
			||||||
 | 
					  "homepage": "https://github.com/zadam/trilium",
 | 
				
			||||||
 | 
					  "bin": "trilium",
 | 
				
			||||||
 | 
					  "icon": "dist/trilium-linux-x64/icon.png",
 | 
				
			||||||
 | 
					  "categories": [ "Office" ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										0
									
								
								bin/deps/mac-x64/image/cjpeg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								bin/deps/mac-x64/image/cjpeg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								bin/deps/win-x64/image/cjpeg.exe
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								bin/deps/win-x64/image/cjpeg.exe
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -42,11 +42,11 @@ git push origin $TAG
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bin/build.sh
 | 
					bin/build.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LINUX_X64_BUILD=trilium-linux-x64-$VERSION.7z
 | 
					LINUX_X64_BUILD=trilium-linux-x64-$VERSION.tar.xz
 | 
				
			||||||
LINUX_IA32_BUILD=trilium-linux-ia32-$VERSION.7z
 | 
					DEBIAN_X64_BUILD=trilium_${VERSION}_amd64.deb
 | 
				
			||||||
WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.7z
 | 
					WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.zip
 | 
				
			||||||
MAC_X64_BUILD=trilium-mac-x64-$VERSION.7z
 | 
					MAC_X64_BUILD=trilium-mac-x64-$VERSION.zip
 | 
				
			||||||
SERVER_BUILD=trilium-linux-x64-server-$VERSION.7z
 | 
					SERVER_BUILD=trilium-linux-x64-server-$VERSION.tar.xz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Creating release in GitHub"
 | 
					echo "Creating release in GitHub"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -60,6 +60,13 @@ github-release release \
 | 
				
			|||||||
    --tag $TAG \
 | 
					    --tag $TAG \
 | 
				
			||||||
    --name "$TAG release" $EXTRA
 | 
					    --name "$TAG release" $EXTRA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Uploading debian x64 package"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					github-release upload \
 | 
				
			||||||
 | 
					    --tag $TAG \
 | 
				
			||||||
 | 
					    --name "$DEBIAN_X64_BUILD" \
 | 
				
			||||||
 | 
					    --file "dist/$DEBIAN_X64_BUILD"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Uploading linux x64 build"
 | 
					echo "Uploading linux x64 build"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
github-release upload \
 | 
					github-release upload \
 | 
				
			||||||
@@ -67,13 +74,6 @@ github-release upload \
 | 
				
			|||||||
    --name "$LINUX_X64_BUILD" \
 | 
					    --name "$LINUX_X64_BUILD" \
 | 
				
			||||||
    --file "dist/$LINUX_X64_BUILD"
 | 
					    --file "dist/$LINUX_X64_BUILD"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Uploading linux ia32 build"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
github-release upload \
 | 
					 | 
				
			||||||
    --tag $TAG \
 | 
					 | 
				
			||||||
    --name "$LINUX_IA32_BUILD" \
 | 
					 | 
				
			||||||
    --file "dist/$LINUX_IA32_BUILD"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
echo "Uploading windows x64 build"
 | 
					echo "Uploading windows x64 build"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
github-release upload \
 | 
					github-release upload \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								bin/reset-local.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								bin/reset-local.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					./node_modules/.bin/electron-rebuild --arch=x64
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								db/demo.tar
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								db/demo.tar
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								db/migrations/0121__add_hoisting_option.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								db/migrations/0121__add_hoisting_option.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
 | 
				
			||||||
 | 
					VALUES ('hoistedNoteId', 'root', '2018-12-11T18:31:00.874Z', '2018-12-11T18:31:00.874Z', 0);
 | 
				
			||||||
							
								
								
									
										62
									
								
								db/migrations/0122__add_iv_to_columns.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								db/migrations/0122__add_iv_to_columns.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					const sql = require('../../src/services/sql');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function prependIv(cipherText, ivText) {
 | 
				
			||||||
 | 
					    const arr = ivText.split("").map(c => parseInt(c) || 0);
 | 
				
			||||||
 | 
					    const iv = Buffer.from(arr);
 | 
				
			||||||
 | 
					    const payload = Buffer.from(cipherText, 'base64');
 | 
				
			||||||
 | 
					    const complete = Buffer.concat([iv, payload]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return complete.toString('base64');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function updateEncryptedDataKey() {
 | 
				
			||||||
 | 
					    const encryptedDataKey = await sql.getValue("SELECT value FROM options WHERE name = 'encryptedDataKey'");
 | 
				
			||||||
 | 
					    const encryptedDataKeyIv = await sql.getValue("SELECT value FROM options WHERE name = 'encryptedDataKeyIv'");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const newEncryptedDataKey = prependIv(encryptedDataKey, encryptedDataKeyIv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await sql.execute("UPDATE options SET value = ? WHERE name = 'encryptedDataKey'", [newEncryptedDataKey]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await sql.execute("DELETE FROM options WHERE name = 'encryptedDataKeyIv'");
 | 
				
			||||||
 | 
					    await sql.execute("DELETE FROM sync WHERE entityName = 'options' AND entityId = 'encryptedDataKeyIv'");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function updateNotes() {
 | 
				
			||||||
 | 
					    const protectedNotes = await sql.getRows("SELECT noteId, title, content FROM notes WHERE isProtected = 1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const note of protectedNotes) {
 | 
				
			||||||
 | 
					        if (note.title !== null) {
 | 
				
			||||||
 | 
					            note.title = prependIv(note.title, "0" + note.noteId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (note.content !== null) {
 | 
				
			||||||
 | 
					            note.content = prependIv(note.content, "1" + note.noteId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await sql.execute("UPDATE notes SET title = ?, content = ? WHERE noteId = ?", [note.title, note.content, note.noteId]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function updateNoteRevisions() {
 | 
				
			||||||
 | 
					    const protectedNoteRevisions = await sql.getRows("SELECT noteRevisionId, title, content FROM note_revisions WHERE isProtected = 1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const noteRevision of protectedNoteRevisions) {
 | 
				
			||||||
 | 
					        if (noteRevision.title !== null) {
 | 
				
			||||||
 | 
					            noteRevision.title = prependIv(noteRevision.title, "0" + noteRevision.noteRevisionId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (noteRevision.content !== null) {
 | 
				
			||||||
 | 
					            noteRevision.content = prependIv(noteRevision.content, "1" + noteRevision.noteRevisionId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await sql.execute("UPDATE note_revisions SET title = ?, content = ? WHERE noteRevisionId = ?", [noteRevision.title, noteRevision.content, noteRevision.noteRevisionId]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = async () => {
 | 
				
			||||||
 | 
					    await updateEncryptedDataKey();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await updateNotes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await updateNoteRevisions();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										8
									
								
								db/migrations/0123__add_options_for_font_sizes.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								db/migrations/0123__add_options_for_font_sizes.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
 | 
				
			||||||
 | 
					VALUES ('mainFontSize', '100', '2019-01-13T18:31:00.874Z', '2019-01-13T18:31:00.874Z', 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
 | 
				
			||||||
 | 
					VALUES ('treeFontSize', '100', '2019-01-13T18:31:00.874Z', '2019-01-13T18:31:00.874Z', 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
 | 
				
			||||||
 | 
					VALUES ('detailFontSize', '110', '2019-01-13T18:31:00.874Z', '2019-01-13T18:31:00.874Z', 0);
 | 
				
			||||||
							
								
								
									
										11
									
								
								db/migrations/0124__readd_font_sizes.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								db/migrations/0124__readd_font_sizes.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
 | 
				
			||||||
 | 
					  SELECT 'mainFontSize', '100', '2019-01-13T18:31:00.874Z', '2019-01-13T18:31:00.874Z', 0
 | 
				
			||||||
 | 
					    WHERE NOT EXISTS (SELECT 1 FROM options WHERE name = 'mainFontSize');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
 | 
				
			||||||
 | 
					  SELECT 'treeFontSize', '100', '2019-01-13T18:31:00.874Z', '2019-01-13T18:31:00.874Z', 0
 | 
				
			||||||
 | 
					    WHERE NOT EXISTS (SELECT 1 FROM options WHERE name = 'treeFontSize');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
 | 
				
			||||||
 | 
					  SELECT 'detailFontSize', '110', '2019-01-13T18:31:00.874Z', '2019-01-13T18:31:00.874Z', 0
 | 
				
			||||||
 | 
					    WHERE NOT EXISTS (SELECT 1 FROM options WHERE name = 'detailFontSize');
 | 
				
			||||||
							
								
								
									
										35
									
								
								db/migrations/0125__create_note_content_table.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								db/migrations/0125__create_note_content_table.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					CREATE TABLE IF NOT EXISTS "note_contents" (
 | 
				
			||||||
 | 
					  `noteContentId`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `noteId`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `isProtected`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
					  `content`	TEXT NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `hash` TEXT DEFAULT "" NOT NULL,
 | 
				
			||||||
 | 
					  `dateCreated`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `dateModified` TEXT NOT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY(`noteContentId`)
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE UNIQUE INDEX `IDX_note_contents_noteId` ON `note_contents` (`noteId`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO note_contents (noteContentId, noteId, isProtected, content, dateCreated, dateModified)
 | 
				
			||||||
 | 
					  SELECT 'C' || SUBSTR(noteId, 2), noteId, isProtected, content, dateCreated, dateModified FROM notes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE IF NOT EXISTS "notes_mig" (
 | 
				
			||||||
 | 
					  `noteId`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `title`	TEXT NOT NULL DEFAULT "note",
 | 
				
			||||||
 | 
					  `isProtected`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
					  `type` TEXT NOT NULL DEFAULT 'text',
 | 
				
			||||||
 | 
					  `mime` TEXT NOT NULL DEFAULT 'text/html',
 | 
				
			||||||
 | 
					  `hash` TEXT DEFAULT "" NOT NULL,
 | 
				
			||||||
 | 
					  `isDeleted`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
					  `dateCreated`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `dateModified`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY(`noteId`)
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO notes_mig (noteId, title, isProtected, isDeleted, dateCreated, dateModified, type, mime, hash)
 | 
				
			||||||
 | 
					SELECT noteId, title, isProtected, isDeleted, dateCreated, dateModified, type, mime, hash FROM notes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE notes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ALTER TABLE notes_mig RENAME TO notes;
 | 
				
			||||||
@@ -96,19 +96,6 @@ CREATE TABLE attributes
 | 
				
			|||||||
  hash         TEXT default "" not null, isInheritable int DEFAULT 0 NULL);
 | 
					  hash         TEXT default "" not null, isInheritable int DEFAULT 0 NULL);
 | 
				
			||||||
CREATE INDEX IDX_attributes_name_value
 | 
					CREATE INDEX IDX_attributes_name_value
 | 
				
			||||||
  on attributes (name, value);
 | 
					  on attributes (name, value);
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS "notes" (
 | 
					 | 
				
			||||||
  `noteId`	TEXT NOT NULL,
 | 
					 | 
				
			||||||
  `title`	TEXT NOT NULL DEFAULT "note",
 | 
					 | 
				
			||||||
  `content`	TEXT NULL DEFAULT NULL,
 | 
					 | 
				
			||||||
  `isProtected`	INT NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
  `type` TEXT NOT NULL DEFAULT 'text',
 | 
					 | 
				
			||||||
  `mime` TEXT NOT NULL DEFAULT 'text/html',
 | 
					 | 
				
			||||||
  `hash` TEXT DEFAULT "" NOT NULL,
 | 
					 | 
				
			||||||
  `isDeleted`	INT NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
  `dateCreated`	TEXT NOT NULL,
 | 
					 | 
				
			||||||
  `dateModified`	TEXT NOT NULL,
 | 
					 | 
				
			||||||
  PRIMARY KEY(`noteId`)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS "links" (
 | 
					CREATE TABLE IF NOT EXISTS "links" (
 | 
				
			||||||
  `linkId`	TEXT NOT NULL,
 | 
					  `linkId`	TEXT NOT NULL,
 | 
				
			||||||
  `noteId`	TEXT NOT NULL,
 | 
					  `noteId`	TEXT NOT NULL,
 | 
				
			||||||
@@ -130,3 +117,26 @@ CREATE INDEX IDX_attributes_noteId_index
 | 
				
			|||||||
  on attributes (noteId);
 | 
					  on attributes (noteId);
 | 
				
			||||||
CREATE INDEX IDX_attributes_value_index
 | 
					CREATE INDEX IDX_attributes_value_index
 | 
				
			||||||
  on attributes (value);
 | 
					  on attributes (value);
 | 
				
			||||||
 | 
					CREATE TABLE IF NOT EXISTS "note_contents" (
 | 
				
			||||||
 | 
					  `noteContentId`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `noteId`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `isProtected`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
					  `content`	TEXT NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `hash` TEXT DEFAULT "" NOT NULL,
 | 
				
			||||||
 | 
					  `dateCreated`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `dateModified` TEXT NOT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY(`noteContentId`)
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					CREATE UNIQUE INDEX `IDX_note_contents_noteId` ON `note_contents` (`noteId`);
 | 
				
			||||||
 | 
					CREATE TABLE IF NOT EXISTS "notes" (
 | 
				
			||||||
 | 
					  `noteId`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `title`	TEXT NOT NULL DEFAULT "note",
 | 
				
			||||||
 | 
					  `isProtected`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
					  `type` TEXT NOT NULL DEFAULT 'text',
 | 
				
			||||||
 | 
					  `mime` TEXT NOT NULL DEFAULT 'text/html',
 | 
				
			||||||
 | 
					  `hash` TEXT DEFAULT "" NOT NULL,
 | 
				
			||||||
 | 
					  `isDeleted`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
					  `dateCreated`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  `dateModified`	TEXT NOT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY(`noteId`)
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,7 +282,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -724,7 +724,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -505,7 +505,7 @@ Each note can have multiple (at least one) branches, meaning it can be placed in
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -210,7 +210,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -352,7 +352,7 @@ this is different concept than attribute/relation.</div>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										494
									
								
								docs/backend_api/NoteContent.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										494
									
								
								docs/backend_api/NoteContent.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,494 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="utf-8">
 | 
				
			||||||
 | 
					    <title>JSDoc: Class: NoteContent</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">Class: NoteContent</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<header>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        <h2><span class="attribs"><span class="type-signature"></span></span>NoteContent<span class="signature">(row)</span><span class="type-signature"></span></h2>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            <div class="class-description">This represents a Note which is a central object in the Trilium Notes project.</div>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</header>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<article>
 | 
				
			||||||
 | 
					    <div class="container-overview">
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <h2>Constructor</h2>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <h4 class="name" id="NoteContent"><span class="type-signature"></span>new NoteContent<span class="signature">(row)</span><span class="type-signature"></span></h4>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h5>Parameters:</h5>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<table class="params">
 | 
				
			||||||
 | 
					    <thead>
 | 
				
			||||||
 | 
					    <tr>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        <th>Name</th>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <th>Type</th>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <th class="last">Description</th>
 | 
				
			||||||
 | 
					    </tr>
 | 
				
			||||||
 | 
					    </thead>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>row</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last">object containing database row from "note_contents" table</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h5 class="subsection-title">Properties:</h5>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<table class="props">
 | 
				
			||||||
 | 
					    <thead>
 | 
				
			||||||
 | 
					    <tr>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        <th>Name</th>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <th>Type</th>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <th class="last">Description</th>
 | 
				
			||||||
 | 
					    </tr>
 | 
				
			||||||
 | 
					    </thead>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>noteContentId</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					<span class="param-type">string</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last">primary key</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>noteId</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					<span class="param-type">string</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last">reference to owning note</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>isProtected</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					<span class="param-type">boolean</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last">true if note content is protected</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>content</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					<span class="param-type">blob</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last">note content - e.g. HTML text for text notes, file payload for files</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>dateCreated</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					<span class="param-type">string</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last"></td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>dateModified</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					<span class="param-type">string</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last"></td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl class="details">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
 | 
					        <a href="entities_note_content.js.html">entities/note_content.js</a>, <a href="entities_note_content.js.html#line20">line 20</a>
 | 
				
			||||||
 | 
					    </li></ul></dd>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        <h3 class="subsection-title">Extends</h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <ul>
 | 
				
			||||||
 | 
					        <li><a href="Entity.html">Entity</a></li>
 | 
				
			||||||
 | 
					    </ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        <h3 class="subsection-title">Methods</h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <h4 class="name" id="getNote"><span class="type-signature">(async) </span>getNote<span class="signature">()</span><span class="type-signature"> → {Promise.<<a href="Note.html">Note</a>>}</span></h4>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl class="details">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
 | 
					        <a href="entities_note_content.js.html">entities/note_content.js</a>, <a href="entities_note_content.js.html#line63">line 63</a>
 | 
				
			||||||
 | 
					    </li></ul></dd>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h5>Returns:</h5>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl>
 | 
				
			||||||
 | 
					    <dt>
 | 
				
			||||||
 | 
					        Type
 | 
				
			||||||
 | 
					    </dt>
 | 
				
			||||||
 | 
					    <dd>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					<span class="param-type">Promise.<<a href="Note.html">Note</a>></span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </dd>
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</article>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<nav>
 | 
				
			||||||
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<br class="clear">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<footer>
 | 
				
			||||||
 | 
					    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
 | 
				
			||||||
 | 
					</footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script> prettyPrint(); </script>
 | 
				
			||||||
 | 
					<script src="scripts/linenumber.js"> </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@@ -397,7 +397,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -305,7 +305,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,7 +282,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,7 +69,7 @@ module.exports = ApiToken;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,6 +133,11 @@ class Attribute extends Entity {
 | 
				
			|||||||
            this.dateModified = dateUtils.nowDate();
 | 
					            this.dateModified = dateUtils.nowDate();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cannot be static!
 | 
				
			||||||
 | 
					    updatePojo(pojo) {
 | 
				
			||||||
 | 
					        delete pojo.isOwned;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = Attribute;</code></pre>
 | 
					module.exports = Attribute;</code></pre>
 | 
				
			||||||
@@ -145,7 +150,7 @@ module.exports = Attribute;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,11 @@ class Branch extends Entity {
 | 
				
			|||||||
            this.dateModified = dateUtils.nowDate();
 | 
					            this.dateModified = dateUtils.nowDate();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cannot be static!
 | 
				
			||||||
 | 
					    updatePojo(pojo) {
 | 
				
			||||||
 | 
					        delete pojo.origParentNoteId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = Branch;</code></pre>
 | 
					module.exports = Branch;</code></pre>
 | 
				
			||||||
@@ -99,7 +104,7 @@ module.exports = Branch;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,8 +36,11 @@ class Entity {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    constructor(row = {}) {
 | 
					    constructor(row = {}) {
 | 
				
			||||||
        for (const key in row) {
 | 
					        for (const key in row) {
 | 
				
			||||||
 | 
					            // ! is used when joint-fetching notes and note_contents objects for performance
 | 
				
			||||||
 | 
					            if (!key.startsWith('!')) {
 | 
				
			||||||
                this[key] = row[key];
 | 
					                this[key] = row[key];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ('isDeleted' in this) {
 | 
					        if ('isDeleted' in this) {
 | 
				
			||||||
            this.isDeleted = !!this.isDeleted;
 | 
					            this.isDeleted = !!this.isDeleted;
 | 
				
			||||||
@@ -87,7 +90,7 @@ module.exports = Entity;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,7 @@ module.exports = Link;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,8 +30,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Entity = require('./entity');
 | 
					const Entity = require('./entity');
 | 
				
			||||||
const Attribute = require('./attribute');
 | 
					const Attribute = require('./attribute');
 | 
				
			||||||
 | 
					const NoteContent = require('./note_content');
 | 
				
			||||||
const protectedSessionService = require('../services/protected_session');
 | 
					const protectedSessionService = require('../services/protected_session');
 | 
				
			||||||
const repository = require('../services/repository');
 | 
					const repository = require('../services/repository');
 | 
				
			||||||
 | 
					const sql = require('../services/sql');
 | 
				
			||||||
const dateUtils = require('../services/date_utils');
 | 
					const dateUtils = require('../services/date_utils');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const LABEL = 'label';
 | 
					const LABEL = 'label';
 | 
				
			||||||
@@ -46,7 +48,6 @@ const RELATION_DEFINITION = 'relation-definition';
 | 
				
			|||||||
 * @property {string} type - one of "text", "code", "file" or "render"
 | 
					 * @property {string} type - one of "text", "code", "file" or "render"
 | 
				
			||||||
 * @property {string} mime - MIME type, e.g. "text/html"
 | 
					 * @property {string} mime - MIME type, e.g. "text/html"
 | 
				
			||||||
 * @property {string} title - note title
 | 
					 * @property {string} title - note title
 | 
				
			||||||
 * @property {string} content - note content - e.g. HTML text for text notes, file payload for files
 | 
					 | 
				
			||||||
 * @property {boolean} isProtected - true if note is protected
 | 
					 * @property {boolean} isProtected - true if note is protected
 | 
				
			||||||
 * @property {boolean} isDeleted - true if note is deleted
 | 
					 * @property {boolean} isDeleted - true if note is deleted
 | 
				
			||||||
 * @property {string} dateCreated
 | 
					 * @property {string} dateCreated
 | 
				
			||||||
@@ -57,7 +58,7 @@ const RELATION_DEFINITION = 'relation-definition';
 | 
				
			|||||||
class Note extends Entity {
 | 
					class Note extends Entity {
 | 
				
			||||||
    static get entityName() { return "notes"; }
 | 
					    static get entityName() { return "notes"; }
 | 
				
			||||||
    static get primaryKeyName() { return "noteId"; }
 | 
					    static get primaryKeyName() { return "noteId"; }
 | 
				
			||||||
    static get hashedProperties() { return ["noteId", "title", "content", "type", "isProtected", "isDeleted"]; }
 | 
					    static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted"]; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param row - object containing database row from "notes" table
 | 
					     * @param row - object containing database row from "notes" table
 | 
				
			||||||
@@ -74,19 +75,64 @@ class Note extends Entity {
 | 
				
			|||||||
        if (this.isProtected && this.noteId) {
 | 
					        if (this.isProtected && this.noteId) {
 | 
				
			||||||
            this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
 | 
					            this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
                protectedSessionService.decryptNote(this);
 | 
					                protectedSessionService.decryptNote(this);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
        this.setContent(this.content);
 | 
					                // saving ciphertexts in case we do want to update protected note outside of protected session
 | 
				
			||||||
 | 
					                // (which is allowed)
 | 
				
			||||||
 | 
					                this.titleCipherText = this.title;
 | 
				
			||||||
 | 
					                this.title = "[protected]";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setContent(content) {
 | 
					    /** @returns {Promise<NoteContent>} */
 | 
				
			||||||
        this.content = content;
 | 
					    async getNoteContent() {
 | 
				
			||||||
 | 
					        if (!this.noteContent) {
 | 
				
			||||||
 | 
					            this.noteContent = await repository.getEntity(`SELECT * FROM note_contents WHERE noteId = ?`, [this.noteId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					            if (!this.noteContent) {
 | 
				
			||||||
            this.jsonContent = JSON.parse(this.content);
 | 
					                throw new Error("Note content not found for noteId=" + this.noteId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        catch(e) {}
 | 
					
 | 
				
			||||||
 | 
					            if (this.isStringNote()) {
 | 
				
			||||||
 | 
					                this.noteContent.content = this.noteContent.content.toString("UTF-8");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return this.noteContent;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise<*>} */
 | 
				
			||||||
 | 
					    async getContent() {
 | 
				
			||||||
 | 
					        const noteContent = await this.getNoteContent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return noteContent.content;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise<*>} */
 | 
				
			||||||
 | 
					    async getJsonContent() {
 | 
				
			||||||
 | 
					        const content = await this.getContent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return JSON.parse(content);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise} */
 | 
				
			||||||
 | 
					    async setContent(content) {
 | 
				
			||||||
 | 
					        if (!this.noteContent) {
 | 
				
			||||||
 | 
					            // make sure it is loaded
 | 
				
			||||||
 | 
					            await this.getNoteContent();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.noteContent.content = content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await this.noteContent.save();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise} */
 | 
				
			||||||
 | 
					    async setJsonContent(content) {
 | 
				
			||||||
 | 
					        await this.setContent(JSON.stringify(content));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */
 | 
					    /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */
 | 
				
			||||||
@@ -102,7 +148,9 @@ class Note extends Entity {
 | 
				
			|||||||
    /** @returns {boolean} true if this note is JavaScript (code or attachment) */
 | 
					    /** @returns {boolean} true if this note is JavaScript (code or attachment) */
 | 
				
			||||||
    isJavaScript() {
 | 
					    isJavaScript() {
 | 
				
			||||||
        return (this.type === "code" || this.type === "file")
 | 
					        return (this.type === "code" || this.type === "file")
 | 
				
			||||||
            && (this.mime.startsWith("application/javascript") || this.mime === "application/x-javascript");
 | 
					            && (this.mime.startsWith("application/javascript")
 | 
				
			||||||
 | 
					                || this.mime === "application/x-javascript"
 | 
				
			||||||
 | 
					                || this.mime === "text/javascript");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @returns {boolean} true if this note is HTML */
 | 
					    /** @returns {boolean} true if this note is HTML */
 | 
				
			||||||
@@ -110,6 +158,11 @@ class Note extends Entity {
 | 
				
			|||||||
        return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html";
 | 
					        return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {boolean} true if the note has string content (not binary) */
 | 
				
			||||||
 | 
					    isStringNote() {
 | 
				
			||||||
 | 
					        return ["text", "code", "relation-map", "search"].includes(this.type) || this.mime.startsWith('text/');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @returns {string} JS script environment - either "frontend" or "backend" */
 | 
					    /** @returns {string} JS script environment - either "frontend" or "backend" */
 | 
				
			||||||
    getScriptEnv() {
 | 
					    getScriptEnv() {
 | 
				
			||||||
        if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith('env=frontend'))) {
 | 
					        if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith('env=frontend'))) {
 | 
				
			||||||
@@ -394,6 +447,16 @@ class Note extends Entity {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); }
 | 
					    async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name
 | 
				
			||||||
 | 
					     * @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationTarget(name) {
 | 
				
			||||||
 | 
					        const relation = await this.getRelation(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return relation ? await repository.getNote(relation.value) : null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Based on enabled, label is either set or removed.
 | 
					     * Based on enabled, label is either set or removed.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -451,24 +514,32 @@ class Note extends Entity {
 | 
				
			|||||||
    async removeRelation(name, value) { return await this.removeAttribute(RELATION, name, value); }
 | 
					    async removeRelation(name, value) { return await this.removeAttribute(RELATION, name, value); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param {string} name
 | 
					     * @return {Promise<string[]>} return list of all descendant noteIds of this note. Returning just noteIds because number of notes can be huge. Includes also this note's noteId
 | 
				
			||||||
     * @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found)
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async getRelationTarget(name) {
 | 
					    async getDescendantNoteIds() {
 | 
				
			||||||
        const relation = await this.getRelation(name);
 | 
					        return await sql.getColumn(`
 | 
				
			||||||
 | 
					            WITH RECURSIVE
 | 
				
			||||||
        return relation ? await repository.getNote(relation.value) : null;
 | 
					            tree(noteId) AS (
 | 
				
			||||||
 | 
					                SELECT ?
 | 
				
			||||||
 | 
					                UNION
 | 
				
			||||||
 | 
					                SELECT branches.noteId FROM branches
 | 
				
			||||||
 | 
					                    JOIN tree ON branches.parentNoteId = tree.noteId
 | 
				
			||||||
 | 
					                    JOIN notes ON notes.noteId = branches.noteId
 | 
				
			||||||
 | 
					                WHERE notes.isDeleted = 0
 | 
				
			||||||
 | 
					                  AND branches.isDeleted = 0
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            SELECT noteId FROM tree`, [this.noteId]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Finds child notes with given attribute name and value. Only own attributes are considered, not inherited ones
 | 
					     * Finds descendant notes with given attribute name and value. Only own attributes are considered, not inherited ones
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {string} type - attribute type (label, relation, etc.)
 | 
					     * @param {string} type - attribute type (label, relation, etc.)
 | 
				
			||||||
     * @param {string} name - attribute name
 | 
					     * @param {string} name - attribute name
 | 
				
			||||||
     * @param {string} [value] - attribute value
 | 
					     * @param {string} [value] - attribute value
 | 
				
			||||||
     * @returns {Promise<Note[]>}
 | 
					     * @returns {Promise<Note[]>}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async findChildNotesWithAttribute(type, name, value) {
 | 
					    async getDescendantNotesWithAttribute(type, name, value) {
 | 
				
			||||||
        const params = [this.noteId, name];
 | 
					        const params = [this.noteId, name];
 | 
				
			||||||
        let valueCondition = "";
 | 
					        let valueCondition = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -500,22 +571,22 @@ class Note extends Entity {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Finds notes with given label name and value. Only own labels are considered, not inherited ones
 | 
					     * Finds descendant notes with given label name and value. Only own labels are considered, not inherited ones
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {string} name - label name
 | 
					     * @param {string} name - label name
 | 
				
			||||||
     * @param {string} [value] - label value
 | 
					     * @param {string} [value] - label value
 | 
				
			||||||
     * @returns {Promise<Note[]>}
 | 
					     * @returns {Promise<Note[]>}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async findChildNotesWithLabel(name, value) { return await this.findChildNotesWithAttribute(LABEL, name, value); }
 | 
					    async getDescendantNotesWithLabel(name, value) { return await this.getDescendantNotesWithAttribute(LABEL, name, value); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Finds notes with given relation name and value. Only own relations are considered, not inherited ones
 | 
					     * Finds descendant notes with given relation name and value. Only own relations are considered, not inherited ones
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {string} name - relation name
 | 
					     * @param {string} name - relation name
 | 
				
			||||||
     * @param {string} [value] - relation value
 | 
					     * @param {string} [value] - relation value
 | 
				
			||||||
     * @returns {Promise<Note[]>}
 | 
					     * @returns {Promise<Note[]>}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async findChildNotesWithRelation(name, value) { return await this.findChildNotesWithAttribute(RELATION, name, value); }
 | 
					    async getDescendantNotesWithRelation(name, value) { return await this.getDescendantNotesWithAttribute(RELATION, name, value); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns note revisions of this note.
 | 
					     * Returns note revisions of this note.
 | 
				
			||||||
@@ -608,17 +679,6 @@ class Note extends Entity {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    beforeSaving() {
 | 
					    beforeSaving() {
 | 
				
			||||||
        if (this.isJson() && this.jsonContent) {
 | 
					 | 
				
			||||||
            this.content = JSON.stringify(this.jsonContent, null, '\t');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // we do this here because encryption needs the note ID for the IV
 | 
					 | 
				
			||||||
        this.generateIdIfNecessary();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (this.isProtected) {
 | 
					 | 
				
			||||||
            protectedSessionService.encryptNote(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!this.isDeleted) {
 | 
					        if (!this.isDeleted) {
 | 
				
			||||||
            this.isDeleted = false;
 | 
					            this.isDeleted = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -633,6 +693,23 @@ class Note extends Entity {
 | 
				
			|||||||
            this.dateModified = dateUtils.nowDate();
 | 
					            this.dateModified = dateUtils.nowDate();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cannot be static!
 | 
				
			||||||
 | 
					    updatePojo(pojo) {
 | 
				
			||||||
 | 
					        if (pojo.isProtected) {
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
 | 
					                protectedSessionService.encryptNote(pojo);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // updating protected note outside of protected session means we will keep original ciphertexts
 | 
				
			||||||
 | 
					                pojo.title = pojo.titleCipherText;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delete pojo.isContentAvailable;
 | 
				
			||||||
 | 
					        delete pojo.__attributeCache;
 | 
				
			||||||
 | 
					        delete pojo.titleCipherText;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = Note;</code></pre>
 | 
					module.exports = Note;</code></pre>
 | 
				
			||||||
@@ -645,7 +722,7 @@ module.exports = Note;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										146
									
								
								docs/backend_api/entities_note_content.js.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								docs/backend_api/entities_note_content.js.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="utf-8">
 | 
				
			||||||
 | 
					    <title>JSDoc: Source: entities/note_content.js</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script src="scripts/prettify/prettify.js"> </script>
 | 
				
			||||||
 | 
					    <script src="scripts/prettify/lang-css.js"> </script>
 | 
				
			||||||
 | 
					    <!--[if lt IE 9]>
 | 
				
			||||||
 | 
					      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 | 
				
			||||||
 | 
					    <![endif]-->
 | 
				
			||||||
 | 
					    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 | 
				
			||||||
 | 
					    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="main">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h1 class="page-title">Source: entities/note_content.js</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <section>
 | 
				
			||||||
 | 
					        <article>
 | 
				
			||||||
 | 
					            <pre class="prettyprint source linenums"><code>"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Entity = require('./entity');
 | 
				
			||||||
 | 
					const protectedSessionService = require('../services/protected_session');
 | 
				
			||||||
 | 
					const repository = require('../services/repository');
 | 
				
			||||||
 | 
					const dateUtils = require('../services/date_utils');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This represents a Note which is a central object in the Trilium Notes project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @property {string} noteContentId - primary key
 | 
				
			||||||
 | 
					 * @property {string} noteId - reference to owning note
 | 
				
			||||||
 | 
					 * @property {boolean} isProtected - true if note content is protected
 | 
				
			||||||
 | 
					 * @property {blob} content - note content - e.g. HTML text for text notes, file payload for files
 | 
				
			||||||
 | 
					 * @property {string} dateCreated
 | 
				
			||||||
 | 
					 * @property {string} dateModified
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @extends Entity
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class NoteContent extends Entity {
 | 
				
			||||||
 | 
					    static get entityName() {
 | 
				
			||||||
 | 
					        return "note_contents";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get primaryKeyName() {
 | 
				
			||||||
 | 
					        return "noteContentId";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get hashedProperties() {
 | 
				
			||||||
 | 
					        return ["noteContentId", "noteId", "isProtected", "content"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param row - object containing database row from "note_contents" table
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor(row) {
 | 
				
			||||||
 | 
					        super(row);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.isProtected = !!this.isProtected;
 | 
				
			||||||
 | 
					        /* true if content (meaning any kind of potentially encrypted content) is either not encrypted
 | 
				
			||||||
 | 
					         * or encrypted, but with available protected session (so effectively decrypted) */
 | 
				
			||||||
 | 
					        this.isContentAvailable = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // check if there's noteContentId, otherwise this is a new entity which wasn't encrypted yet
 | 
				
			||||||
 | 
					        if (this.isProtected && this.noteContentId) {
 | 
				
			||||||
 | 
					            this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
 | 
					                protectedSessionService.decryptNoteContent(this);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // saving ciphertexts in case we do want to update protected note outside of protected session
 | 
				
			||||||
 | 
					                // (which is allowed)
 | 
				
			||||||
 | 
					                this.contentCipherText = this.content;
 | 
				
			||||||
 | 
					                this.content = "";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @returns {Promise<Note>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getNote() {
 | 
				
			||||||
 | 
					        return await repository.getNote(this.noteId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    beforeSaving() {
 | 
				
			||||||
 | 
					        if (!this.dateCreated) {
 | 
				
			||||||
 | 
					            this.dateCreated = dateUtils.nowDate();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super.beforeSaving();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.isChanged) {
 | 
				
			||||||
 | 
					            this.dateModified = dateUtils.nowDate();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cannot be static!
 | 
				
			||||||
 | 
					    updatePojo(pojo) {
 | 
				
			||||||
 | 
					        if (pojo.isProtected) {
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
 | 
					                protectedSessionService.encryptNoteContent(pojo);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // updating protected note outside of protected session means we will keep original ciphertext
 | 
				
			||||||
 | 
					                pojo.content = pojo.contentCipherText;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delete pojo.isContentAvailable;
 | 
				
			||||||
 | 
					        delete pojo.contentCipherText;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = NoteContent;</code></pre>
 | 
				
			||||||
 | 
					        </article>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<nav>
 | 
				
			||||||
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<br class="clear">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<footer>
 | 
				
			||||||
 | 
					    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
 | 
				
			||||||
 | 
					</footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script> prettyPrint(); </script>
 | 
				
			||||||
 | 
					<script src="scripts/linenumber.js"> </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@@ -85,7 +85,7 @@ module.exports = NoteRevision;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,7 +72,7 @@ module.exports = Option;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,7 +69,7 @@ module.exports = RecentNote;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -272,7 +272,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line144">line 144</a>
 | 
					        <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line149">line 149</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -558,7 +558,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line151">line 151</a>
 | 
					        <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line156">line 156</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -588,7 +588,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,7 @@ const repository = require('./repository');
 | 
				
			|||||||
const axios = require('axios');
 | 
					const axios = require('axios');
 | 
				
			||||||
const cloningService = require('./cloning');
 | 
					const cloningService = require('./cloning');
 | 
				
			||||||
const messagingService = require('./messaging');
 | 
					const messagingService = require('./messaging');
 | 
				
			||||||
 | 
					const appInfo = require('./app_info');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This is the main backend API interface for scripts. It's published in the local "api" object.
 | 
					 * This is the main backend API interface for scripts. It's published in the local "api" object.
 | 
				
			||||||
@@ -46,13 +47,17 @@ const messagingService = require('./messaging');
 | 
				
			|||||||
 * @constructor
 | 
					 * @constructor
 | 
				
			||||||
 * @hideconstructor
 | 
					 * @hideconstructor
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function BackendScriptApi(startNote, currentNote, originEntity) {
 | 
					function BackendScriptApi(currentNote, apiParams) {
 | 
				
			||||||
    /** @property {Note} note where script started executing */
 | 
					    /** @property {Note} note where script started executing */
 | 
				
			||||||
    this.startNote = startNote;
 | 
					    this.startNote = apiParams.startNote;
 | 
				
			||||||
    /** @property {Note} note where script is currently executing */
 | 
					    /** @property {Note} note where script is currently executing */
 | 
				
			||||||
    this.currentNote = currentNote;
 | 
					    this.currentNote = currentNote;
 | 
				
			||||||
    /** @property {Entity} entity whose event triggered this executions */
 | 
					    /** @property {Entity} entity whose event triggered this executions */
 | 
				
			||||||
    this.originEntity = originEntity;
 | 
					    this.originEntity = apiParams.originEntity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const key in apiParams) {
 | 
				
			||||||
 | 
					        this[key] = apiParams[key];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.axios = axios;
 | 
					    this.axios = axios;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -196,6 +201,23 @@ function BackendScriptApi(startNote, currentNote, originEntity) {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    this.createNote = noteService.createNote;
 | 
					    this.createNote = noteService.createNote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates new note according to given params and force all connected clients to refresh their tree.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {string} parentNoteId - create new note under this parent
 | 
				
			||||||
 | 
					     * @param {string} title
 | 
				
			||||||
 | 
					     * @param {string} [content=""]
 | 
				
			||||||
 | 
					     * @param {CreateNoteExtraOptions} [extraOptions={}]
 | 
				
			||||||
 | 
					     * @returns {Promise<{note: Note, branch: Branch}>} object contains newly created entities note and branch
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.createNoteAndRefresh = async function(parentNoteId, title, content, extraOptions) {
 | 
				
			||||||
 | 
					        await noteService.createNote(parentNoteId, title, content, extraOptions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        messagingService.refreshTree();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Log given message to trilium logs.
 | 
					     * Log given message to trilium logs.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -212,14 +234,42 @@ function BackendScriptApi(startNote, currentNote, originEntity) {
 | 
				
			|||||||
    this.getRootCalendarNote = dateNoteService.getRootCalendarNote;
 | 
					    this.getRootCalendarNote = dateNoteService.getRootCalendarNote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns day note for given date (YYYY-MM-DD format). If such note doesn't exist, it is created.
 | 
					     * Returns day note for given date. If such note doesn't exist, it is created.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @method
 | 
					     * @method
 | 
				
			||||||
     * @param {string} date
 | 
					     * @param {string} date in YYYY-MM-DD format
 | 
				
			||||||
     * @returns {Promise<Note|null>}
 | 
					     * @returns {Promise<Note|null>}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    this.getDateNote = dateNoteService.getDateNote;
 | 
					    this.getDateNote = dateNoteService.getDateNote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns note for the first date of the week of the given date.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     * @param {string} date in YYYY-MM-DD format
 | 
				
			||||||
 | 
					     * @param {object} options - "startOfTheWeek" - either "monday" (default) or "sunday"
 | 
				
			||||||
 | 
					     * @returns {Promise<Note|null>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.getWeekNote = dateNoteService.getWeekNote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns month note for given date. If such note doesn't exist, it is created.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     * @param {string} date in YYYY-MM format
 | 
				
			||||||
 | 
					     * @returns {Promise<Note|null>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.getMonthNote = dateNoteService.getMonthNote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns year note for given year. If such note doesn't exist, it is created.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     * @param {string} year in YYYY format
 | 
				
			||||||
 | 
					     * @returns {Promise<Note|null>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.getYearNote = dateNoteService.getYearNote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @method
 | 
					     * @method
 | 
				
			||||||
     * @param {string} parentNoteId - this note's child notes will be sorted
 | 
					     * @param {string} parentNoteId - this note's child notes will be sorted
 | 
				
			||||||
@@ -253,13 +303,20 @@ function BackendScriptApi(startNote, currentNote, originEntity) {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    this.transactional = sql.transactional;
 | 
					    this.transactional = sql.transactional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.sql = sql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Trigger tree refresh in all connected clients. This is required when some tree change happens in
 | 
					     * Trigger tree refresh in all connected clients. This is required when some tree change happens in
 | 
				
			||||||
     * the backend.
 | 
					     * the backend.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @returns {Promise<void>}
 | 
					     * @returns {Promise<void>}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    this.refreshTree = () => messagingService.sendMessageToAllClients({ type: 'refresh-tree' });
 | 
					    this.refreshTree = messagingService.refreshTree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return {{syncVersion, appVersion, buildRevision, dbVersion, dataDirectory, buildDate}|*} - object representing basic info about running Trilium version
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.getAppInfo = () => appInfo
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = BackendScriptApi;</code></pre>
 | 
					module.exports = BackendScriptApi;</code></pre>
 | 
				
			||||||
@@ -272,7 +329,7 @@ module.exports = BackendScriptApi;</code></pre>
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav>
 | 
					<nav>
 | 
				
			||||||
    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</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>
 | 
					    <h2><a href="index.html">Home</a></h2><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="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</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>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<br class="clear">
 | 
					<br class="clear">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,7 +81,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line16">line 16</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line18">line 18</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -221,7 +221,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line22">line 22</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line24">line 24</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -334,7 +334,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line24">line 24</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line26">line 26</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -444,7 +444,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line20">line 20</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line22">line 22</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -573,7 +573,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line41">line 41</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line43">line 43</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -726,7 +726,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line33">line 33</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line35">line 35</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -879,7 +879,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line60">line 60</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line62">line 62</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1057,7 +1057,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line197">line 197</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line199">line 199</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1188,7 +1188,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line157">line 157</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line159">line 159</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1292,7 +1292,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line221">line 221</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line236">line 236</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1396,7 +1396,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line203">line 203</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line205">line 205</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1500,7 +1500,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line215">line 215</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line230">line 230</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1609,7 +1609,7 @@ if some action needs to happen on only one specific instance.
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line150">line 150</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line152">line 152</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1808,7 +1808,7 @@ otherwise (by e.g. createNoteLink())
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line142">line 142</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line144">line 144</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1860,6 +1860,117 @@ otherwise (by e.g. createNoteLink())
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    <h4 class="name" id="isNoteStillLoaded"><span class="type-signature"></span>isNoteStillLoaded<span class="signature">()</span><span class="type-signature"> → {boolean}</span></h4>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="description">
 | 
				
			||||||
 | 
					    This method checks whether user navigated away from the note from which the scripts has been started.
 | 
				
			||||||
 | 
					This is necessary because script execution is async and by the time it is finished, the user might have
 | 
				
			||||||
 | 
					already navigated away from this page - the end result would be that script might return data for the wrong
 | 
				
			||||||
 | 
					note.
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl class="details">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line216">line 216</a>
 | 
				
			||||||
 | 
					    </li></ul></dd>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h5>Returns:</h5>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					<div class="param-desc">
 | 
				
			||||||
 | 
					    returns true if the original note is still loaded, false if user switched to another
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl>
 | 
				
			||||||
 | 
					    <dt>
 | 
				
			||||||
 | 
					        Type
 | 
				
			||||||
 | 
					    </dt>
 | 
				
			||||||
 | 
					    <dd>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					<span class="param-type">boolean</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </dd>
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    <h4 class="name" id="onNoteChange"><span class="type-signature"></span>onNoteChange<span class="signature">(func)</span><span class="type-signature"></span></h4>
 | 
					    <h4 class="name" id="onNoteChange"><span class="type-signature"></span>onNoteChange<span class="signature">(func)</span><span class="type-signature"></span></h4>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1957,7 +2068,7 @@ otherwise (by e.g. createNoteLink())
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line209">line 209</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line224">line 224</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2088,7 +2199,7 @@ otherwise (by e.g. createNoteLink())
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line164">line 164</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line166">line 166</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2140,6 +2251,88 @@ otherwise (by e.g. createNoteLink())
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <h4 class="name" id="protectCurrentNote"><span class="type-signature"></span>protectCurrentNote<span class="signature">()</span><span class="type-signature"></span></h4>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl class="details">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line253">line 253</a>
 | 
				
			||||||
 | 
					    </li></ul></dd>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2196,7 +2389,7 @@ otherwise (by e.g. createNoteLink())
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line188">line 188</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line190">line 190</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2373,7 +2566,7 @@ Internally this serializes the anonymous function into string and sends it to ba
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line110">line 110</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line112">line 112</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2526,7 +2719,138 @@ Internally this serializes the anonymous function into string and sends it to ba
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line227">line 227</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line242">line 242</a>
 | 
				
			||||||
 | 
					    </li></ul></dd>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <h4 class="name" id="setupElementTooltip"><span class="type-signature"></span>setupElementTooltip<span class="signature">($el)</span><span class="type-signature"></span></h4>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h5>Parameters:</h5>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<table class="params">
 | 
				
			||||||
 | 
					    <thead>
 | 
				
			||||||
 | 
					    <tr>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        <th>Name</th>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <th>Type</th>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <th class="last">Description</th>
 | 
				
			||||||
 | 
					    </tr>
 | 
				
			||||||
 | 
					    </thead>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                <td class="name"><code>$el</code></td>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="type">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					<span class="param-type">object</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <td class="description last">jquery object on which to setup the tooltip</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl class="details">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line248">line 248</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2661,7 +2985,7 @@ Internally this serializes the anonymous function into string and sends it to ba
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line180">line 180</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line182">line 182</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2796,7 +3120,7 @@ Internally this serializes the anonymous function into string and sends it to ba
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line172">line 172</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line174">line 174</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -141,7 +141,123 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
<h4 class="name" id="content"><span class="type-signature"></span>content<span class="type-signature"></span></h4>
 | 
					<h4 class="name" id="dateCreated"><span class="type-signature"></span>dateCreated<span class="type-signature"></span></h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl class="details">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
 | 
					        <a href="entities_note_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line14">line 14</a>
 | 
				
			||||||
 | 
					    </li></ul></dd>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					<h4 class="name" id="dateModified"><span class="type-signature"></span>dateModified<span class="type-signature"></span></h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<dl class="details">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
 | 
					        <a href="entities_note_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line17">line 17</a>
 | 
				
			||||||
 | 
					    </li></ul></dd>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					<h4 class="name" id="noteContent"><span class="type-signature"></span>noteContent<span class="type-signature"></span></h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -199,64 +315,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
<h4 class="name" id="jsonContent"><span class="type-signature"></span>jsonContent<span class="type-signature"></span></h4>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<dl class="details">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					 | 
				
			||||||
        <a href="entities_note_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line16">line 16</a>
 | 
					 | 
				
			||||||
    </li></ul></dd>
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
</dl>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										86
									
								
								docs/frontend_api/entities_attribute.js.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								docs/frontend_api/entities_attribute.js.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="utf-8">
 | 
				
			||||||
 | 
					    <title>JSDoc: Source: entities/attribute.js</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script src="scripts/prettify/prettify.js"> </script>
 | 
				
			||||||
 | 
					    <script src="scripts/prettify/lang-css.js"> </script>
 | 
				
			||||||
 | 
					    <!--[if lt IE 9]>
 | 
				
			||||||
 | 
					      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 | 
				
			||||||
 | 
					    <![endif]-->
 | 
				
			||||||
 | 
					    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 | 
				
			||||||
 | 
					    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="main">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h1 class="page-title">Source: entities/attribute.js</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <section>
 | 
				
			||||||
 | 
					        <article>
 | 
				
			||||||
 | 
					            <pre class="prettyprint source linenums"><code>class Attribute {
 | 
				
			||||||
 | 
					    constructor(treeCache, row) {
 | 
				
			||||||
 | 
					        this.treeCache = treeCache;
 | 
				
			||||||
 | 
					        /** @param {string} attributeId */
 | 
				
			||||||
 | 
					        this.attributeId = row.attributeId;
 | 
				
			||||||
 | 
					        /** @param {string} noteId */
 | 
				
			||||||
 | 
					        this.noteId = row.noteId;
 | 
				
			||||||
 | 
					        /** @param {string} type */
 | 
				
			||||||
 | 
					        this.type = row.type;
 | 
				
			||||||
 | 
					        /** @param {string} name */
 | 
				
			||||||
 | 
					        this.name = row.name;
 | 
				
			||||||
 | 
					        /** @param {string} value */
 | 
				
			||||||
 | 
					        this.value = row.value;
 | 
				
			||||||
 | 
					        /** @param {int} position */
 | 
				
			||||||
 | 
					        this.position = row.position;
 | 
				
			||||||
 | 
					        /** @param {boolean} isInheritable */
 | 
				
			||||||
 | 
					        this.isInheritable = row.isInheritable;
 | 
				
			||||||
 | 
					        /** @param {boolean} isDeleted */
 | 
				
			||||||
 | 
					        this.isDeleted = row.isDeleted;
 | 
				
			||||||
 | 
					        /** @param {string} dateCreated */
 | 
				
			||||||
 | 
					        this.dateCreated = row.dateCreated;
 | 
				
			||||||
 | 
					        /** @param {string} dateModified */
 | 
				
			||||||
 | 
					        this.dateModified = row.dateModified;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {NoteShort} */
 | 
				
			||||||
 | 
					    async getNote() {
 | 
				
			||||||
 | 
					        return await this.treeCache.getNote(this.noteId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get toString() {
 | 
				
			||||||
 | 
					        return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name})`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Attribute;</code></pre>
 | 
				
			||||||
 | 
					        </article>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<nav>
 | 
				
			||||||
 | 
					    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteFull.html">NoteFull</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3><a href="global.html">Global</a></h3>
 | 
				
			||||||
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<br class="clear">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<footer>
 | 
				
			||||||
 | 
					    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
 | 
				
			||||||
 | 
					</footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script> prettyPrint(); </script>
 | 
				
			||||||
 | 
					<script src="scripts/linenumber.js"> </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@@ -42,7 +42,7 @@ class Branch {
 | 
				
			|||||||
        /** @param {string} */
 | 
					        /** @param {string} */
 | 
				
			||||||
        this.prefix = row.prefix;
 | 
					        this.prefix = row.prefix;
 | 
				
			||||||
        /** @param {boolean} */
 | 
					        /** @param {boolean} */
 | 
				
			||||||
        this.isExpanded = row.isExpanded;
 | 
					        this.isExpanded = !!row.isExpanded;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @returns {NoteShort} */
 | 
					    /** @returns {NoteShort} */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,15 +36,13 @@ class NoteFull extends NoteShort {
 | 
				
			|||||||
        super(treeCache, row);
 | 
					        super(treeCache, row);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /** @param {string} */
 | 
					        /** @param {string} */
 | 
				
			||||||
        this.content = row.content;
 | 
					        this.noteContent = row.noteContent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.content !== "" && this.isJson()) {
 | 
					        /** @param {string} */
 | 
				
			||||||
            try {
 | 
					        this.dateCreated = row.dateCreated;
 | 
				
			||||||
                /** @param {object} */
 | 
					
 | 
				
			||||||
                this.jsonContent = JSON.parse(this.content);
 | 
					        /** @param {string} */
 | 
				
			||||||
            }
 | 
					        this.dateModified = row.dateModified;
 | 
				
			||||||
            catch(e) {}
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,14 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <section>
 | 
					    <section>
 | 
				
			||||||
        <article>
 | 
					        <article>
 | 
				
			||||||
            <pre class="prettyprint source linenums"><code>/**
 | 
					            <pre class="prettyprint source linenums"><code>import server from '../services/server.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const LABEL = 'label';
 | 
				
			||||||
 | 
					const LABEL_DEFINITION = 'label-definition';
 | 
				
			||||||
 | 
					const RELATION = 'relation';
 | 
				
			||||||
 | 
					const RELATION_DEFINITION = 'relation-definition';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 * This note's representation is used in note tree and is kept in TreeCache.
 | 
					 * This note's representation is used in note tree and is kept in TreeCache.
 | 
				
			||||||
 * Its notable omission is the note content.
 | 
					 * Its notable omission is the note content.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -99,6 +106,140 @@ class NoteShort {
 | 
				
			|||||||
        return await this.treeCache.getNotes(this.getChildNoteIds());
 | 
					        return await this.treeCache.getNotes(this.getChildNoteIds());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - attribute name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getAttributes(name) {
 | 
				
			||||||
 | 
					        if (!this.attributeCache) {
 | 
				
			||||||
 | 
					            this.attributeCache = await server.get('notes/' + this.noteId + '/attributes');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (name) {
 | 
				
			||||||
 | 
					            return this.attributeCache.filter(attr => attr.name === name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            return this.attributeCache;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - label name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's labels (attributes with type label), including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabels(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === LABEL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - label name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's label definitions, including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabelDefinitions(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === LABEL_DEFINITION);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - relation name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's relations (attributes with type relation), including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelations(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === RELATION);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - relation name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's relation definitions including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationDefinitions(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === RELATION_DEFINITION);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} type - attribute type (label, relation, etc.)
 | 
				
			||||||
 | 
					     * @param {string} name - attribute name
 | 
				
			||||||
 | 
					     * @returns {Promise<boolean>} true if note has an attribute with given type and name (including inherited)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async hasAttribute(type, name) {
 | 
				
			||||||
 | 
					        return !!await this.getAttribute(type, name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} type - attribute type (label, relation, etc.)
 | 
				
			||||||
 | 
					     * @param {string} name - attribute name
 | 
				
			||||||
 | 
					     * @returns {Promise<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.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getAttribute(type, name) {
 | 
				
			||||||
 | 
					        const attributes = await 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 {Promise<string>} attribute value of given type and name or null if no such attribute exists.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getAttributeValue(type, name) {
 | 
				
			||||||
 | 
					        const attr = await this.getAttribute(type, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return attr ? attr.value : null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - label name
 | 
				
			||||||
 | 
					     * @returns {Promise<boolean>} true if label exists (including inherited)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async hasLabel(name) { return await this.hasAttribute(LABEL, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - relation name
 | 
				
			||||||
 | 
					     * @returns {Promise<boolean>} true if relation exists (including inherited)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async hasRelation(name) { return await this.hasAttribute(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - label name
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute>} label if it exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabel(name) { return await this.getAttribute(LABEL, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - relation name
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute>} relation if it exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelation(name) { return await this.getAttribute(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - label name
 | 
				
			||||||
 | 
					     * @returns {Promise<string>} label value if label exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabelValue(name) { return await this.getAttributeValue(LABEL, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - relation name
 | 
				
			||||||
 | 
					     * @returns {Promise<string>} relation value if relation exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name
 | 
				
			||||||
 | 
					     * @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationTarget(name) {
 | 
				
			||||||
 | 
					        const relation = await this.getRelation(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return relation ? await repository.getNote(relation.value) : null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Clear note's attributes cache to force fresh reload for next attribute request.
 | 
				
			||||||
 | 
					     * Cache is note instance scoped.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    invalidateAttributeCache() {
 | 
				
			||||||
 | 
					        this.attributeCache = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get toString() {
 | 
					    get toString() {
 | 
				
			||||||
        return `Note(noteId=${this.noteId}, title=${this.title})`;
 | 
					        return `Note(noteId=${this.noteId}, title=${this.title})`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -107,6 +248,7 @@ class NoteShort {
 | 
				
			|||||||
        const dto = Object.assign({}, this);
 | 
					        const dto = Object.assign({}, this);
 | 
				
			||||||
        delete dto.treeCache;
 | 
					        delete dto.treeCache;
 | 
				
			||||||
        delete dto.archived;
 | 
					        delete dto.archived;
 | 
				
			||||||
 | 
					        delete dto.attributeCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return dto;
 | 
					        return dto;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -303,7 +303,7 @@
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    <dt class="tag-source">Source:</dt>
 | 
					    <dt class="tag-source">Source:</dt>
 | 
				
			||||||
    <dd class="tag-source"><ul class="dummy"><li>
 | 
					    <dd class="tag-source"><ul class="dummy"><li>
 | 
				
			||||||
        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line47">line 47</a>
 | 
					        <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line49">line 49</a>
 | 
				
			||||||
    </li></ul></dd>
 | 
					    </li></ul></dd>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,8 @@ import linkService from './link.js';
 | 
				
			|||||||
import treeCache from './tree_cache.js';
 | 
					import treeCache from './tree_cache.js';
 | 
				
			||||||
import noteDetailService from './note_detail.js';
 | 
					import noteDetailService from './note_detail.js';
 | 
				
			||||||
import noteTypeService from './note_type.js';
 | 
					import noteTypeService from './note_type.js';
 | 
				
			||||||
 | 
					import noteTooltipService from './note_tooltip.js';
 | 
				
			||||||
 | 
					import protectedSessionService from'./protected_session.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This is the main frontend API interface for scripts. It's published in the local "api" object.
 | 
					 * This is the main frontend API interface for scripts. It's published in the local "api" object.
 | 
				
			||||||
@@ -69,7 +71,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
 | 
				
			|||||||
    this.activateNewNote = async notePath => {
 | 
					    this.activateNewNote = async notePath => {
 | 
				
			||||||
        await treeService.reload();
 | 
					        await treeService.reload();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await treeService.activateNote(notePath, true);
 | 
					        await treeService.activateNote(notePath, noteDetailService.focusAndSelectTitle);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -230,6 +232,19 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    this.getCurrentNoteContent = noteDetailService.getCurrentNoteContent;
 | 
					    this.getCurrentNoteContent = noteDetailService.getCurrentNoteContent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * This method checks whether user navigated away from the note from which the scripts has been started.
 | 
				
			||||||
 | 
					     * This is necessary because script execution is async and by the time it is finished, the user might have
 | 
				
			||||||
 | 
					     * already navigated away from this page - the end result would be that script might return data for the wrong
 | 
				
			||||||
 | 
					     * note.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     * @return {boolean} returns true if the original note is still loaded, false if user switched to another
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.isNoteStillLoaded = () => {
 | 
				
			||||||
 | 
					        return this.originEntity.noteId === noteDetailService.getCurrentNoteId();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @method
 | 
					     * @method
 | 
				
			||||||
     * @param {function} func - callback called on note change as user is typing (not necessarily tied to save event)
 | 
					     * @param {function} func - callback called on note change as user is typing (not necessarily tied to save event)
 | 
				
			||||||
@@ -253,6 +268,17 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
 | 
				
			|||||||
     * @param {array} types - list of mime types to be used
 | 
					     * @param {array} types - list of mime types to be used
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    this.setCodeMimeTypes = noteTypeService.setCodeMimeTypes;
 | 
					    this.setCodeMimeTypes = noteTypeService.setCodeMimeTypes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     * @param {object} $el - jquery object on which to setup the tooltip
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.setupElementTooltip = noteTooltipService.setupElementTooltip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.protectCurrentNote = protectedSessionService.protectNoteAndSendToServer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default FrontendScriptApi;</code></pre>
 | 
					export default FrontendScriptApi;</code></pre>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								electron.js
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								electron.js
									
									
									
									
									
								
							@@ -7,6 +7,7 @@ const cls = require('./src/services/cls');
 | 
				
			|||||||
const url = require("url");
 | 
					const url = require("url");
 | 
				
			||||||
const port = require('./src/services/port');
 | 
					const port = require('./src/services/port');
 | 
				
			||||||
const appIconService = require('./src/services/app_icon');
 | 
					const appIconService = require('./src/services/app_icon');
 | 
				
			||||||
 | 
					const windowStateKeeper = require('electron-window-state');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const app = electron.app;
 | 
					const app = electron.app;
 | 
				
			||||||
const globalShortcut = electron.globalShortcut;
 | 
					const globalShortcut = electron.globalShortcut;
 | 
				
			||||||
@@ -28,14 +29,23 @@ function onClosed() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function createMainWindow() {
 | 
					async function createMainWindow() {
 | 
				
			||||||
 | 
					    let mainWindowState = windowStateKeeper({
 | 
				
			||||||
 | 
					        // default window width & height so it's usable on 1600 * 900 display (including some extra panels etc.)
 | 
				
			||||||
 | 
					        defaultWidth: 1200,
 | 
				
			||||||
 | 
					        defaultHeight: 800
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const win = new electron.BrowserWindow({
 | 
					    const win = new electron.BrowserWindow({
 | 
				
			||||||
        // initial window width & height so it's usable on 1600 * 900 display (including some extra panels etc.)
 | 
					        x: mainWindowState.x,
 | 
				
			||||||
        width: 1200,
 | 
					        y: mainWindowState.y,
 | 
				
			||||||
        height: 800,
 | 
					        width: mainWindowState.width,
 | 
				
			||||||
 | 
					        height: mainWindowState.height,
 | 
				
			||||||
        title: 'Trilium Notes',
 | 
					        title: 'Trilium Notes',
 | 
				
			||||||
        icon: path.join(__dirname, 'src/public/images/app-icons/png/256x256.png')
 | 
					        icon: path.join(__dirname, 'src/public/images/app-icons/png/256x256.png')
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mainWindowState.manage(win);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    win.setMenu(null);
 | 
					    win.setMenu(null);
 | 
				
			||||||
    win.loadURL('http://localhost:' + await port);
 | 
					    win.loadURL('http://localhost:' + await port);
 | 
				
			||||||
    win.on('closed', onClosed);
 | 
					    win.on('closed', onClosed);
 | 
				
			||||||
@@ -81,7 +91,7 @@ app.on('ready', async () => {
 | 
				
			|||||||
        const dateNoteService = require('./src/services/date_notes');
 | 
					        const dateNoteService = require('./src/services/date_notes');
 | 
				
			||||||
        const dateUtils = require('./src/services/date_utils');
 | 
					        const dateUtils = require('./src/services/date_utils');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const parentNote = await dateNoteService.getDateNote(dateUtils.nowDate());
 | 
					        const parentNote = await dateNoteService.getDateNote(dateUtils.nowLocalDate());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // window may be hidden / not in focus
 | 
					        // window may be hidden / not in focus
 | 
				
			||||||
        mainWindow.focus();
 | 
					        mainWindow.focus();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								issue_template.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								issue_template.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					For bug reports, please mention **version of the application** and include **log files** from following location:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `/home/[user]/.local/share/trilium-data/log` for Linux
 | 
				
			||||||
 | 
					* `C:\Users\[user]\AppData\Roaming\trilium-data\log` for Windows Vista and up
 | 
				
			||||||
 | 
					* `/Users/[user]/Library/Application Support/trilium-data/log` for Mac OS
 | 
				
			||||||
							
								
								
									
										3153
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3153
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										57
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								package.json
									
									
									
									
									
								
							@@ -2,7 +2,7 @@
 | 
				
			|||||||
  "name": "trilium",
 | 
					  "name": "trilium",
 | 
				
			||||||
  "productName": "Trilium Notes",
 | 
					  "productName": "Trilium Notes",
 | 
				
			||||||
  "description": "Trilium Notes",
 | 
					  "description": "Trilium Notes",
 | 
				
			||||||
  "version": "0.25.1-beta",
 | 
					  "version": "0.30.2-beta",
 | 
				
			||||||
  "license": "AGPL-3.0-only",
 | 
					  "license": "AGPL-3.0-only",
 | 
				
			||||||
  "main": "electron.js",
 | 
					  "main": "electron.js",
 | 
				
			||||||
  "bin": {
 | 
					  "bin": {
 | 
				
			||||||
@@ -17,7 +17,8 @@
 | 
				
			|||||||
    "start-electron": "electron . --disable-gpu",
 | 
					    "start-electron": "electron . --disable-gpu",
 | 
				
			||||||
    "build-backend-docs": "jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/entities/*.js src/services/backend_script_api.js",
 | 
					    "build-backend-docs": "jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/entities/*.js src/services/backend_script_api.js",
 | 
				
			||||||
    "build-frontend-docs": "jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/javascripts/entities/*.js src/public/javascripts/services/frontend_script_api.js",
 | 
					    "build-frontend-docs": "jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/javascripts/entities/*.js src/public/javascripts/services/frontend_script_api.js",
 | 
				
			||||||
    "build-docs": "npm run build-backend-docs && npm run build-frontend-docs"
 | 
					    "build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
 | 
				
			||||||
 | 
					    "postinstall": "electron-builder install-app-deps"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "async-mutex": "0.1.3",
 | 
					    "async-mutex": "0.1.3",
 | 
				
			||||||
@@ -25,55 +26,59 @@
 | 
				
			|||||||
    "body-parser": "1.18.3",
 | 
					    "body-parser": "1.18.3",
 | 
				
			||||||
    "cls-hooked": "4.2.2",
 | 
					    "cls-hooked": "4.2.2",
 | 
				
			||||||
    "commonmark": "0.28.1",
 | 
					    "commonmark": "0.28.1",
 | 
				
			||||||
    "cookie-parser": "1.4.3",
 | 
					    "cookie-parser": "1.4.4",
 | 
				
			||||||
    "debug": "4.1.0",
 | 
					    "debug": "4.1.1",
 | 
				
			||||||
    "ejs": "2.6.1",
 | 
					    "ejs": "2.6.1",
 | 
				
			||||||
    "electron-debug": "2.0.0",
 | 
					    "electron-debug": "2.1.0",
 | 
				
			||||||
    "electron-dl": "1.12.0",
 | 
					    "electron-dl": "1.13.0",
 | 
				
			||||||
    "electron-in-page-search": "1.3.2",
 | 
					    "electron-in-page-search": "1.3.2",
 | 
				
			||||||
 | 
					    "electron-window-state": "^5.0.3",
 | 
				
			||||||
    "express": "4.16.4",
 | 
					    "express": "4.16.4",
 | 
				
			||||||
    "express-session": "1.15.6",
 | 
					    "express-session": "1.15.6",
 | 
				
			||||||
 | 
					    "file-type": "10.8.0",
 | 
				
			||||||
    "fs-extra": "7.0.1",
 | 
					    "fs-extra": "7.0.1",
 | 
				
			||||||
    "get-port": "4.0.0",
 | 
					    "get-port": "4.1.0",
 | 
				
			||||||
    "helmet": "3.15.0",
 | 
					    "helmet": "3.15.1",
 | 
				
			||||||
    "html": "1.0.0",
 | 
					    "html": "1.0.0",
 | 
				
			||||||
    "image-type": "3.0.0",
 | 
					    "image-type": "3.0.0",
 | 
				
			||||||
    "imagemin": "6.0.0",
 | 
					    "imagemin": "6.1.0",
 | 
				
			||||||
    "imagemin-giflossy": "5.1.10",
 | 
					    "imagemin-giflossy": "5.1.10",
 | 
				
			||||||
    "imagemin-mozjpeg": "8.0.0",
 | 
					    "imagemin-mozjpeg": "8.0.0",
 | 
				
			||||||
    "imagemin-pngquant": "6.0.0",
 | 
					    "imagemin-pngquant": "7.0.0",
 | 
				
			||||||
    "ini": "1.3.5",
 | 
					    "ini": "1.3.5",
 | 
				
			||||||
    "jimp": "0.6.0",
 | 
					    "jimp": "0.6.0",
 | 
				
			||||||
    "mime-types": "^2.1.21",
 | 
					    "mime-types": "^2.1.22",
 | 
				
			||||||
    "moment": "2.22.2",
 | 
					    "moment": "2.24.0",
 | 
				
			||||||
    "multer": "1.4.1",
 | 
					    "multer": "1.4.1",
 | 
				
			||||||
 | 
					    "node-abi": "2.7.1",
 | 
				
			||||||
    "open": "0.0.5",
 | 
					    "open": "0.0.5",
 | 
				
			||||||
    "rand-token": "0.4.0",
 | 
					    "rand-token": "0.4.0",
 | 
				
			||||||
    "rcedit": "1.1.1",
 | 
					    "rcedit": "1.1.1",
 | 
				
			||||||
    "request": "2.88.0",
 | 
					    "rimraf": "2.6.3",
 | 
				
			||||||
    "request-promise": "4.2.2",
 | 
					 | 
				
			||||||
    "rimraf": "2.6.2",
 | 
					 | 
				
			||||||
    "sanitize-filename": "1.6.1",
 | 
					    "sanitize-filename": "1.6.1",
 | 
				
			||||||
    "sax": "^1.2.4",
 | 
					    "sax": "^1.2.4",
 | 
				
			||||||
 | 
					    "semver": "^5.6.0",
 | 
				
			||||||
    "serve-favicon": "2.5.0",
 | 
					    "serve-favicon": "2.5.0",
 | 
				
			||||||
    "session-file-store": "1.2.0",
 | 
					    "session-file-store": "1.2.0",
 | 
				
			||||||
    "simple-node-logger": "0.93.40",
 | 
					    "simple-node-logger": "18.12.22",
 | 
				
			||||||
    "sqlite": "3.0.0",
 | 
					    "sqlite": "3.0.2",
 | 
				
			||||||
    "tar-stream": "1.6.2",
 | 
					    "tar-stream": "2.0.0",
 | 
				
			||||||
    "turndown": "5.0.1",
 | 
					    "turndown": "5.0.3",
 | 
				
			||||||
    "unescape": "1.0.1",
 | 
					    "unescape": "1.0.1",
 | 
				
			||||||
    "ws": "6.1.2",
 | 
					    "ws": "6.1.4",
 | 
				
			||||||
    "xml2js": "0.4.19"
 | 
					    "xml2js": "0.4.19"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "devtron": "1.4.0",
 | 
					    "devtron": "1.4.0",
 | 
				
			||||||
    "electron": "4.0.0-beta.8",
 | 
					    "electron": "4.0.3",
 | 
				
			||||||
    "electron-compile": "6.4.3",
 | 
					    "electron-builder": "20.38.5",
 | 
				
			||||||
    "electron-packager": "12.2.0",
 | 
					    "electron-compile": "6.4.4",
 | 
				
			||||||
    "electron-rebuild": "1.8.2",
 | 
					    "electron-installer-debian": "^1.1.1",
 | 
				
			||||||
 | 
					    "electron-packager": "13.1.0",
 | 
				
			||||||
 | 
					    "electron-rebuild": "1.8.4",
 | 
				
			||||||
    "lorem-ipsum": "1.0.6",
 | 
					    "lorem-ipsum": "1.0.6",
 | 
				
			||||||
    "tape": "4.9.1",
 | 
					    "tape": "4.10.1",
 | 
				
			||||||
    "xo": "0.23.0"
 | 
					    "xo": "0.24.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "xo": {
 | 
					  "xo": {
 | 
				
			||||||
    "envs": [
 | 
					    "envs": [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@ app.use((req, res, next) => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.use(bodyParser.json({limit: '50mb'}));
 | 
					app.use(bodyParser.json({limit: '500mb'}));
 | 
				
			||||||
app.use(bodyParser.urlencoded({extended: false}));
 | 
					app.use(bodyParser.urlencoded({extended: false}));
 | 
				
			||||||
app.use(cookieParser());
 | 
					app.use(cookieParser());
 | 
				
			||||||
app.use(express.static(path.join(__dirname, 'public')));
 | 
					app.use(express.static(path.join(__dirname, 'public')));
 | 
				
			||||||
@@ -63,6 +63,8 @@ app.use(favicon(__dirname + '/public/images/app-icons/win/icon.ico'));
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
require('./routes/routes').register(app);
 | 
					require('./routes/routes').register(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require('./routes/custom').register(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// catch 404 and forward to error handler
 | 
					// catch 404 and forward to error handler
 | 
				
			||||||
app.use((req, res, next) => {
 | 
					app.use((req, res, next) => {
 | 
				
			||||||
    const err = new Error('Router not found for request ' + req.url);
 | 
					    const err = new Error('Router not found for request ' + req.url);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,8 +8,11 @@ class Entity {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    constructor(row = {}) {
 | 
					    constructor(row = {}) {
 | 
				
			||||||
        for (const key in row) {
 | 
					        for (const key in row) {
 | 
				
			||||||
 | 
					            // ! is used when joint-fetching notes and note_contents objects for performance
 | 
				
			||||||
 | 
					            if (!key.startsWith('!')) {
 | 
				
			||||||
                this[key] = row[key];
 | 
					                this[key] = row[key];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ('isDeleted' in this) {
 | 
					        if ('isDeleted' in this) {
 | 
				
			||||||
            this.isDeleted = !!this.isDeleted;
 | 
					            this.isDeleted = !!this.isDeleted;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
const Note = require('../entities/note');
 | 
					const Note = require('../entities/note');
 | 
				
			||||||
 | 
					const NoteContent = require('../entities/note_content');
 | 
				
			||||||
const NoteRevision = require('../entities/note_revision');
 | 
					const NoteRevision = require('../entities/note_revision');
 | 
				
			||||||
const Link = require('../entities/link');
 | 
					const Link = require('../entities/link');
 | 
				
			||||||
const Branch = require('../entities/branch');
 | 
					const Branch = require('../entities/branch');
 | 
				
			||||||
@@ -12,10 +13,12 @@ const ENTITY_NAME_TO_ENTITY = {
 | 
				
			|||||||
    "attributes": Attribute,
 | 
					    "attributes": Attribute,
 | 
				
			||||||
    "branches": Branch,
 | 
					    "branches": Branch,
 | 
				
			||||||
    "notes": Note,
 | 
					    "notes": Note,
 | 
				
			||||||
 | 
					    "note_contents": NoteContent,
 | 
				
			||||||
    "note_revisions": NoteRevision,
 | 
					    "note_revisions": NoteRevision,
 | 
				
			||||||
    "recent_notes": RecentNote,
 | 
					    "recent_notes": RecentNote,
 | 
				
			||||||
    "options": Option,
 | 
					    "options": Option,
 | 
				
			||||||
    "api_tokens": ApiToken
 | 
					    "api_tokens": ApiToken,
 | 
				
			||||||
 | 
					    "links": Link
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getEntityFromEntityName(entityName) {
 | 
					function getEntityFromEntityName(entityName) {
 | 
				
			||||||
@@ -47,6 +50,9 @@ function createEntityFromRow(row) {
 | 
				
			|||||||
    else if (row.branchId) {
 | 
					    else if (row.branchId) {
 | 
				
			||||||
        entity = new Branch(row);
 | 
					        entity = new Branch(row);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    else if (row.noteContentId) {
 | 
				
			||||||
 | 
					        entity = new NoteContent(row);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    else if (row.noteId) {
 | 
					    else if (row.noteId) {
 | 
				
			||||||
        entity = new Note(row);
 | 
					        entity = new Note(row);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Entity = require('./entity');
 | 
					const Entity = require('./entity');
 | 
				
			||||||
const Attribute = require('./attribute');
 | 
					const Attribute = require('./attribute');
 | 
				
			||||||
 | 
					const NoteContent = require('./note_content');
 | 
				
			||||||
const protectedSessionService = require('../services/protected_session');
 | 
					const protectedSessionService = require('../services/protected_session');
 | 
				
			||||||
const repository = require('../services/repository');
 | 
					const repository = require('../services/repository');
 | 
				
			||||||
const sql = require('../services/sql');
 | 
					const sql = require('../services/sql');
 | 
				
			||||||
@@ -12,6 +13,8 @@ const LABEL_DEFINITION = 'label-definition';
 | 
				
			|||||||
const RELATION = 'relation';
 | 
					const RELATION = 'relation';
 | 
				
			||||||
const RELATION_DEFINITION = 'relation-definition';
 | 
					const RELATION_DEFINITION = 'relation-definition';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const STRING_MIME_TYPES = ["application/x-javascript"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This represents a Note which is a central object in the Trilium Notes project.
 | 
					 * This represents a Note which is a central object in the Trilium Notes project.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -19,7 +22,6 @@ const RELATION_DEFINITION = 'relation-definition';
 | 
				
			|||||||
 * @property {string} type - one of "text", "code", "file" or "render"
 | 
					 * @property {string} type - one of "text", "code", "file" or "render"
 | 
				
			||||||
 * @property {string} mime - MIME type, e.g. "text/html"
 | 
					 * @property {string} mime - MIME type, e.g. "text/html"
 | 
				
			||||||
 * @property {string} title - note title
 | 
					 * @property {string} title - note title
 | 
				
			||||||
 * @property {string} content - note content - e.g. HTML text for text notes, file payload for files
 | 
					 | 
				
			||||||
 * @property {boolean} isProtected - true if note is protected
 | 
					 * @property {boolean} isProtected - true if note is protected
 | 
				
			||||||
 * @property {boolean} isDeleted - true if note is deleted
 | 
					 * @property {boolean} isDeleted - true if note is deleted
 | 
				
			||||||
 * @property {string} dateCreated
 | 
					 * @property {string} dateCreated
 | 
				
			||||||
@@ -30,7 +32,7 @@ const RELATION_DEFINITION = 'relation-definition';
 | 
				
			|||||||
class Note extends Entity {
 | 
					class Note extends Entity {
 | 
				
			||||||
    static get entityName() { return "notes"; }
 | 
					    static get entityName() { return "notes"; }
 | 
				
			||||||
    static get primaryKeyName() { return "noteId"; }
 | 
					    static get primaryKeyName() { return "noteId"; }
 | 
				
			||||||
    static get hashedProperties() { return ["noteId", "title", "content", "type", "isProtected", "isDeleted"]; }
 | 
					    static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted"]; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param row - object containing database row from "notes" table
 | 
					     * @param row - object containing database row from "notes" table
 | 
				
			||||||
@@ -47,19 +49,64 @@ class Note extends Entity {
 | 
				
			|||||||
        if (this.isProtected && this.noteId) {
 | 
					        if (this.isProtected && this.noteId) {
 | 
				
			||||||
            this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
 | 
					            this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
                protectedSessionService.decryptNote(this);
 | 
					                protectedSessionService.decryptNote(this);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
        this.setContent(this.content);
 | 
					                // saving ciphertexts in case we do want to update protected note outside of protected session
 | 
				
			||||||
 | 
					                // (which is allowed)
 | 
				
			||||||
 | 
					                this.titleCipherText = this.title;
 | 
				
			||||||
 | 
					                this.title = "[protected]";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setContent(content) {
 | 
					    /** @returns {Promise<NoteContent>} */
 | 
				
			||||||
        this.content = content;
 | 
					    async getNoteContent() {
 | 
				
			||||||
 | 
					        if (!this.noteContent) {
 | 
				
			||||||
 | 
					            this.noteContent = await repository.getEntity(`SELECT * FROM note_contents WHERE noteId = ?`, [this.noteId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					            if (!this.noteContent) {
 | 
				
			||||||
            this.jsonContent = JSON.parse(this.content);
 | 
					                throw new Error("Note content not found for noteId=" + this.noteId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        catch(e) {}
 | 
					
 | 
				
			||||||
 | 
					            if (this.isStringNote()) {
 | 
				
			||||||
 | 
					                this.noteContent.content = this.noteContent.content.toString("UTF-8");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return this.noteContent;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise<*>} */
 | 
				
			||||||
 | 
					    async getContent() {
 | 
				
			||||||
 | 
					        const noteContent = await this.getNoteContent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return noteContent.content;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise<*>} */
 | 
				
			||||||
 | 
					    async getJsonContent() {
 | 
				
			||||||
 | 
					        const content = await this.getContent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return JSON.parse(content);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise} */
 | 
				
			||||||
 | 
					    async setContent(content) {
 | 
				
			||||||
 | 
					        if (!this.noteContent) {
 | 
				
			||||||
 | 
					            // make sure it is loaded
 | 
				
			||||||
 | 
					            await this.getNoteContent();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.noteContent.content = content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await this.noteContent.save();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise} */
 | 
				
			||||||
 | 
					    async setJsonContent(content) {
 | 
				
			||||||
 | 
					        await this.setContent(JSON.stringify(content));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */
 | 
					    /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */
 | 
				
			||||||
@@ -85,6 +132,13 @@ class Note extends Entity {
 | 
				
			|||||||
        return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html";
 | 
					        return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {boolean} true if the note has string content (not binary) */
 | 
				
			||||||
 | 
					    isStringNote() {
 | 
				
			||||||
 | 
					        return ["text", "code", "relation-map", "search"].includes(this.type)
 | 
				
			||||||
 | 
					            || this.mime.startsWith('text/')
 | 
				
			||||||
 | 
					            || STRING_MIME_TYPES.includes(this.mime);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @returns {string} JS script environment - either "frontend" or "backend" */
 | 
					    /** @returns {string} JS script environment - either "frontend" or "backend" */
 | 
				
			||||||
    getScriptEnv() {
 | 
					    getScriptEnv() {
 | 
				
			||||||
        if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith('env=frontend'))) {
 | 
					        if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith('env=frontend'))) {
 | 
				
			||||||
@@ -369,6 +423,16 @@ class Note extends Entity {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); }
 | 
					    async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name
 | 
				
			||||||
 | 
					     * @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationTarget(name) {
 | 
				
			||||||
 | 
					        const relation = await this.getRelation(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return relation ? await repository.getNote(relation.value) : null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Based on enabled, label is either set or removed.
 | 
					     * Based on enabled, label is either set or removed.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -425,16 +489,6 @@ class Note extends Entity {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    async removeRelation(name, value) { return await this.removeAttribute(RELATION, name, value); }
 | 
					    async removeRelation(name, value) { return await this.removeAttribute(RELATION, name, value); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @param {string} name
 | 
					 | 
				
			||||||
     * @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found)
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    async getRelationTarget(name) {
 | 
					 | 
				
			||||||
        const relation = await this.getRelation(name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return relation ? await repository.getNote(relation.value) : null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return {Promise<string[]>} return list of all descendant noteIds of this note. Returning just noteIds because number of notes can be huge. Includes also this note's noteId
 | 
					     * @return {Promise<string[]>} return list of all descendant noteIds of this note. Returning just noteIds because number of notes can be huge. Includes also this note's noteId
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -601,13 +655,6 @@ class Note extends Entity {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    beforeSaving() {
 | 
					    beforeSaving() {
 | 
				
			||||||
        if (this.isJson() && this.jsonContent) {
 | 
					 | 
				
			||||||
            this.content = JSON.stringify(this.jsonContent, null, '\t');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // we do this here because encryption needs the note ID for the IV
 | 
					 | 
				
			||||||
        this.generateIdIfNecessary();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!this.isDeleted) {
 | 
					        if (!this.isDeleted) {
 | 
				
			||||||
            this.isDeleted = false;
 | 
					            this.isDeleted = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -626,12 +673,19 @@ class Note extends Entity {
 | 
				
			|||||||
    // cannot be static!
 | 
					    // cannot be static!
 | 
				
			||||||
    updatePojo(pojo) {
 | 
					    updatePojo(pojo) {
 | 
				
			||||||
        if (pojo.isProtected) {
 | 
					        if (pojo.isProtected) {
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
                protectedSessionService.encryptNote(pojo);
 | 
					                protectedSessionService.encryptNote(pojo);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // updating protected note outside of protected session means we will keep original ciphertexts
 | 
				
			||||||
 | 
					                pojo.title = pojo.titleCipherText;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        delete pojo.jsonContent;
 | 
					 | 
				
			||||||
        delete pojo.isContentAvailable;
 | 
					        delete pojo.isContentAvailable;
 | 
				
			||||||
        delete pojo.__attributeCache;
 | 
					        delete pojo.__attributeCache;
 | 
				
			||||||
 | 
					        delete pojo.titleCipherText;
 | 
				
			||||||
 | 
					        delete pojo.noteContent;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										96
									
								
								src/entities/note_content.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/entities/note_content.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Entity = require('./entity');
 | 
				
			||||||
 | 
					const protectedSessionService = require('../services/protected_session');
 | 
				
			||||||
 | 
					const repository = require('../services/repository');
 | 
				
			||||||
 | 
					const dateUtils = require('../services/date_utils');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This represents a Note which is a central object in the Trilium Notes project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @property {string} noteContentId - primary key
 | 
				
			||||||
 | 
					 * @property {string} noteId - reference to owning note
 | 
				
			||||||
 | 
					 * @property {boolean} isProtected - true if note content is protected
 | 
				
			||||||
 | 
					 * @property {blob} content - note content - e.g. HTML text for text notes, file payload for files
 | 
				
			||||||
 | 
					 * @property {string} dateCreated
 | 
				
			||||||
 | 
					 * @property {string} dateModified
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @extends Entity
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class NoteContent extends Entity {
 | 
				
			||||||
 | 
					    static get entityName() {
 | 
				
			||||||
 | 
					        return "note_contents";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get primaryKeyName() {
 | 
				
			||||||
 | 
					        return "noteContentId";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get hashedProperties() {
 | 
				
			||||||
 | 
					        return ["noteContentId", "noteId", "isProtected", "content"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param row - object containing database row from "note_contents" table
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor(row) {
 | 
				
			||||||
 | 
					        super(row);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.isProtected = !!this.isProtected;
 | 
				
			||||||
 | 
					        /* true if content (meaning any kind of potentially encrypted content) is either not encrypted
 | 
				
			||||||
 | 
					         * or encrypted, but with available protected session (so effectively decrypted) */
 | 
				
			||||||
 | 
					        this.isContentAvailable = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // check if there's noteContentId, otherwise this is a new entity which wasn't encrypted yet
 | 
				
			||||||
 | 
					        if (this.isProtected && this.noteContentId) {
 | 
				
			||||||
 | 
					            this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
 | 
					                protectedSessionService.decryptNoteContent(this);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // saving ciphertexts in case we do want to update protected note outside of protected session
 | 
				
			||||||
 | 
					                // (which is allowed)
 | 
				
			||||||
 | 
					                this.contentCipherText = this.content;
 | 
				
			||||||
 | 
					                this.content = "";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @returns {Promise<Note>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getNote() {
 | 
				
			||||||
 | 
					        return await repository.getNote(this.noteId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    beforeSaving() {
 | 
				
			||||||
 | 
					        if (!this.dateCreated) {
 | 
				
			||||||
 | 
					            this.dateCreated = dateUtils.nowDate();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super.beforeSaving();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.isChanged) {
 | 
				
			||||||
 | 
					            this.dateModified = dateUtils.nowDate();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cannot be static!
 | 
				
			||||||
 | 
					    updatePojo(pojo) {
 | 
				
			||||||
 | 
					        if (pojo.isProtected) {
 | 
				
			||||||
 | 
					            if (this.isContentAvailable) {
 | 
				
			||||||
 | 
					                protectedSessionService.encryptNoteContent(pojo);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // updating protected note outside of protected session means we will keep original ciphertext
 | 
				
			||||||
 | 
					                pojo.content = pojo.contentCipherText;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delete pojo.isContentAvailable;
 | 
				
			||||||
 | 
					        delete pojo.contentCipherText;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = NoteContent;
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								src/public/images/app-icons/ios/apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/public/images/app-icons/ios/apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.4 KiB  | 
							
								
								
									
										160
									
								
								src/public/javascripts/desktop.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								src/public/javascripts/desktop.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,160 @@
 | 
				
			|||||||
 | 
					import addLinkDialog from './dialogs/add_link.js';
 | 
				
			||||||
 | 
					import jumpToNoteDialog from './dialogs/jump_to_note.js';
 | 
				
			||||||
 | 
					import attributesDialog from './dialogs/attributes.js';
 | 
				
			||||||
 | 
					import noteRevisionsDialog from './dialogs/note_revisions.js';
 | 
				
			||||||
 | 
					import noteSourceDialog from './dialogs/note_source.js';
 | 
				
			||||||
 | 
					import recentChangesDialog from './dialogs/recent_changes.js';
 | 
				
			||||||
 | 
					import optionsDialog from './dialogs/options.js';
 | 
				
			||||||
 | 
					import sqlConsoleDialog from './dialogs/sql_console.js';
 | 
				
			||||||
 | 
					import markdownImportDialog from './dialogs/markdown_import.js';
 | 
				
			||||||
 | 
					import exportDialog from './dialogs/export.js';
 | 
				
			||||||
 | 
					import importDialog from './dialogs/import.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cloning from './services/cloning.js';
 | 
				
			||||||
 | 
					import contextMenu from './services/tree_context_menu.js';
 | 
				
			||||||
 | 
					import dragAndDropSetup from './services/drag_and_drop.js';
 | 
				
			||||||
 | 
					import link from './services/link.js';
 | 
				
			||||||
 | 
					import messagingService from './services/messaging.js';
 | 
				
			||||||
 | 
					import noteDetailService from './services/note_detail.js';
 | 
				
			||||||
 | 
					import noteType from './services/note_type.js';
 | 
				
			||||||
 | 
					import protected_session from './services/protected_session.js';
 | 
				
			||||||
 | 
					import searchNotesService from './services/search_notes.js';
 | 
				
			||||||
 | 
					import FrontendScriptApi from './services/frontend_script_api.js';
 | 
				
			||||||
 | 
					import ScriptContext from './services/script_context.js';
 | 
				
			||||||
 | 
					import sync from './services/sync.js';
 | 
				
			||||||
 | 
					import treeService from './services/tree.js';
 | 
				
			||||||
 | 
					import treeChanges from './services/branches.js';
 | 
				
			||||||
 | 
					import treeUtils from './services/tree_utils.js';
 | 
				
			||||||
 | 
					import utils from './services/utils.js';
 | 
				
			||||||
 | 
					import server from './services/server.js';
 | 
				
			||||||
 | 
					import entrypoints from './services/entrypoints.js';
 | 
				
			||||||
 | 
					import noteTooltipService from './services/note_tooltip.js';
 | 
				
			||||||
 | 
					import bundle from "./services/bundle.js";
 | 
				
			||||||
 | 
					import treeCache from "./services/tree_cache.js";
 | 
				
			||||||
 | 
					import libraryLoader from "./services/library_loader.js";
 | 
				
			||||||
 | 
					import hoistedNoteService from './services/hoisted_note.js';
 | 
				
			||||||
 | 
					import noteTypeService from './services/note_type.js';
 | 
				
			||||||
 | 
					import linkService from './services/link.js';
 | 
				
			||||||
 | 
					import noteAutocompleteService from './services/note_autocomplete.js';
 | 
				
			||||||
 | 
					import macInit from './services/mac_init.js';
 | 
				
			||||||
 | 
					import cssLoader from './services/css_loader.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// required for CKEditor image upload plugin
 | 
				
			||||||
 | 
					window.glob.getCurrentNode = treeService.getCurrentNode;
 | 
				
			||||||
 | 
					window.glob.getHeaders = server.getHeaders;
 | 
				
			||||||
 | 
					window.glob.showAddLinkDialog = addLinkDialog.showDialog;
 | 
				
			||||||
 | 
					// this is required by CKEditor when uploading images
 | 
				
			||||||
 | 
					window.glob.noteChanged = noteDetailService.noteChanged;
 | 
				
			||||||
 | 
					window.glob.refreshTree = treeService.reload;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// required for ESLint plugin
 | 
				
			||||||
 | 
					window.glob.getCurrentNote = noteDetailService.getCurrentNote;
 | 
				
			||||||
 | 
					window.glob.requireLibrary = libraryLoader.requireLibrary;
 | 
				
			||||||
 | 
					window.glob.ESLINT = libraryLoader.ESLINT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.onerror = function (msg, url, lineNo, columnNo, error) {
 | 
				
			||||||
 | 
					    const string = msg.toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let message = "Uncaught error: ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (string.includes("Cannot read property 'defaultView' of undefined")) {
 | 
				
			||||||
 | 
					        // ignore this specific error which is very common but we don't know where it comes from
 | 
				
			||||||
 | 
					        // and it seems to be harmless
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (string.includes("script error")) {
 | 
				
			||||||
 | 
					        message += 'No details available';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        message += [
 | 
				
			||||||
 | 
					            'Message: ' + msg,
 | 
				
			||||||
 | 
					            'URL: ' + url,
 | 
				
			||||||
 | 
					            'Line: ' + lineNo,
 | 
				
			||||||
 | 
					            'Column: ' + columnNo,
 | 
				
			||||||
 | 
					            'Error object: ' + JSON.stringify(error)
 | 
				
			||||||
 | 
					        ].join(' - ');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    messagingService.logError(message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for (const appCssNoteId of window.appCssNoteIds) {
 | 
				
			||||||
 | 
					    cssLoader.requireCss(`/api/notes/download/${appCssNoteId}`);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const wikiBaseUrl = "https://github.com/zadam/trilium/wiki/";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(document).on("click", "button[data-help-page]", e => {
 | 
				
			||||||
 | 
					    const $button = $(e.target);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    window.open(wikiBaseUrl + $button.attr("data-help-page"), '_blank');
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#logout-button").toggle(!utils.isElectron());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#logout-button").click(() => {
 | 
				
			||||||
 | 
					    const $logoutForm = $('<form action="logout" method="POST">');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $("body").append($logoutForm);
 | 
				
			||||||
 | 
					    $logoutForm.submit();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#tree").on("click", ".unhoist-button", hoistedNoteService.unhoist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("body").on("click", "a.external", function () {
 | 
				
			||||||
 | 
					    window.open($(this).attr("href"), '_blank');
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (utils.isElectron()) {
 | 
				
			||||||
 | 
					    require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
 | 
				
			||||||
 | 
					        // this might occur when day note had to be created
 | 
				
			||||||
 | 
					        if (!await treeCache.getNote(parentNoteId)) {
 | 
				
			||||||
 | 
					            await treeService.reload();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await treeService.activateNote(parentNoteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setTimeout(async () => {
 | 
				
			||||||
 | 
					            const parentNode = treeService.getCurrentNode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const {note} = await treeService.createNote(parentNode, parentNode.data.noteId, 'into', parentNode.data.isProtected);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await treeService.activateNote(note.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }, 500);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#export-note-button").click(function () {
 | 
				
			||||||
 | 
					    if ($(this).hasClass("disabled")) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    exportDialog.showDialog('single');
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$('[data-toggle="tooltip"]').tooltip({
 | 
				
			||||||
 | 
					    html: true
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#import-files-button").click(importDialog.showDialog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macInit.init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					searchNotesService.init(); // should be in front of treeService since that one manipulates address bar hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					treeService.showTree();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					entrypoints.registerEntrypoints();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					noteTooltipService.setupGlobalTooltip();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bundle.executeStartupBundles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					noteTypeService.init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					linkService.init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					noteAutocompleteService.init();
 | 
				
			||||||
@@ -97,7 +97,7 @@ function AttributesModel() {
 | 
				
			|||||||
        await showAttributes(attributes);
 | 
					        await showAttributes(attributes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // attribute might not be rendered immediatelly so could not focus
 | 
					        // attribute might not be rendered immediatelly so could not focus
 | 
				
			||||||
        setTimeout(() => $(".attribute-type-select:last").focus(), 100);
 | 
					        setTimeout(() => $(".attribute-type-select:last").focus(), 1000);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.deleteAttribute = function(data, event) {
 | 
					    this.deleteAttribute = function(data, event) {
 | 
				
			||||||
@@ -169,6 +169,8 @@ function AttributesModel() {
 | 
				
			|||||||
        infoService.showMessage("Attributes have been saved.");
 | 
					        infoService.showMessage("Attributes have been saved.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        attributeService.refreshAttributes();
 | 
					        attributeService.refreshAttributes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        noteDetailService.reload();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function addLastEmptyRow() {
 | 
					    function addLastEmptyRow() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import treeService from '../services/tree.js';
 | 
				
			|||||||
import server from '../services/server.js';
 | 
					import server from '../services/server.js';
 | 
				
			||||||
import treeCache from "../services/tree_cache.js";
 | 
					import treeCache from "../services/tree_cache.js";
 | 
				
			||||||
import treeUtils from "../services/tree_utils.js";
 | 
					import treeUtils from "../services/tree_utils.js";
 | 
				
			||||||
 | 
					import infoService from "../services/info.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const $dialog = $("#branch-prefix-dialog");
 | 
					const $dialog = $("#branch-prefix-dialog");
 | 
				
			||||||
const $form = $("#branch-prefix-form");
 | 
					const $form = $("#branch-prefix-form");
 | 
				
			||||||
@@ -24,7 +25,7 @@ async function showDialog() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const noteTitle = await treeUtils.getNoteTitle(currentNode.data.noteId);
 | 
					    const noteTitle = await treeUtils.getNoteTitle(currentNode.data.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $noteTitle.html(noteTitle);
 | 
					    $noteTitle.text(" - " + noteTitle);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function savePrefix() {
 | 
					async function savePrefix() {
 | 
				
			||||||
@@ -35,6 +36,8 @@ async function savePrefix() {
 | 
				
			|||||||
    await treeService.setPrefix(branchId, prefix);
 | 
					    await treeService.setPrefix(branchId, prefix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $dialog.modal('hide');
 | 
					    $dialog.modal('hide');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    infoService.showMessage("Branch prefix has been saved.");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$form.submit(() => {
 | 
					$form.submit(() => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,9 @@
 | 
				
			|||||||
import treeService from '../services/tree.js';
 | 
					import treeService from '../services/tree.js';
 | 
				
			||||||
import treeUtils from "../services/tree_utils.js";
 | 
					import treeUtils from "../services/tree_utils.js";
 | 
				
			||||||
import exportService from "../services/export.js";
 | 
					import utils from "../services/utils.js";
 | 
				
			||||||
 | 
					import protectedSessionHolder from "../services/protected_session_holder.js";
 | 
				
			||||||
 | 
					import messagingService from "../services/messaging.js";
 | 
				
			||||||
 | 
					import infoService from "../services/info.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const $dialog = $("#export-dialog");
 | 
					const $dialog = $("#export-dialog");
 | 
				
			||||||
const $form = $("#export-form");
 | 
					const $form = $("#export-form");
 | 
				
			||||||
@@ -9,10 +12,25 @@ const $subtreeFormats = $("#export-subtree-formats");
 | 
				
			|||||||
const $singleFormats = $("#export-single-formats");
 | 
					const $singleFormats = $("#export-single-formats");
 | 
				
			||||||
const $subtreeType = $("#export-type-subtree");
 | 
					const $subtreeType = $("#export-type-subtree");
 | 
				
			||||||
const $singleType = $("#export-type-single");
 | 
					const $singleType = $("#export-type-single");
 | 
				
			||||||
 | 
					const $exportProgressWrapper = $("#export-progress-count-wrapper");
 | 
				
			||||||
 | 
					const $exportProgressCount = $("#export-progress-count");
 | 
				
			||||||
 | 
					const $exportButton = $("#export-button");
 | 
				
			||||||
 | 
					const $opmlVersions = $("#opml-versions");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let exportId = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function showDialog(defaultType) {
 | 
					async function showDialog(defaultType) {
 | 
				
			||||||
 | 
					    // each opening of the dialog resets the exportId so we don't associate it with previous exports anymore
 | 
				
			||||||
 | 
					    exportId = '';
 | 
				
			||||||
 | 
					    $exportButton.removeAttr("disabled");
 | 
				
			||||||
 | 
					    $exportProgressWrapper.hide();
 | 
				
			||||||
 | 
					    $exportProgressCount.text('0');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (defaultType === 'subtree') {
 | 
					    if (defaultType === 'subtree') {
 | 
				
			||||||
        $subtreeType.prop("checked", true).change();
 | 
					        $subtreeType.prop("checked", true).change();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // to show/hide OPML versions
 | 
				
			||||||
 | 
					        $("input[name=export-subtree-format]:checked").change();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (defaultType === 'single') {
 | 
					    else if (defaultType === 'single') {
 | 
				
			||||||
        $singleType.prop("checked", true).change();
 | 
					        $singleType.prop("checked", true).change();
 | 
				
			||||||
@@ -21,6 +39,8 @@ async function showDialog(defaultType) {
 | 
				
			|||||||
        throw new Error("Unrecognized type " + defaultType);
 | 
					        throw new Error("Unrecognized type " + defaultType);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $("#opml-v2").prop("checked", true); // setting default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glob.activeDialog = $dialog;
 | 
					    glob.activeDialog = $dialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $dialog.modal();
 | 
					    $dialog.modal();
 | 
				
			||||||
@@ -32,6 +52,9 @@ async function showDialog(defaultType) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$form.submit(() => {
 | 
					$form.submit(() => {
 | 
				
			||||||
 | 
					    // disabling so export can't be triggered again
 | 
				
			||||||
 | 
					    $exportButton.attr("disabled", "disabled");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const exportType = $dialog.find("input[name='export-type']:checked").val();
 | 
					    const exportType = $dialog.find("input[name='export-type']:checked").val();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!exportType) {
 | 
					    if (!exportType) {
 | 
				
			||||||
@@ -44,15 +67,23 @@ $form.submit(() => {
 | 
				
			|||||||
        ? $("input[name=export-subtree-format]:checked").val()
 | 
					        ? $("input[name=export-subtree-format]:checked").val()
 | 
				
			||||||
        : $("input[name=export-single-format]:checked").val();
 | 
					        : $("input[name=export-single-format]:checked").val();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const exportVersion = exportFormat === 'opml' ? $dialog.find("input[name='opml-version']:checked").val() : "1.0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const currentNode = treeService.getCurrentNode();
 | 
					    const currentNode = treeService.getCurrentNode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    exportService.exportBranch(currentNode.data.branchId, exportType, exportFormat);
 | 
					    exportBranch(currentNode.data.branchId, exportType, exportFormat, exportVersion);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    $dialog.modal('hide');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function exportBranch(branchId, type, format, version) {
 | 
				
			||||||
 | 
					    exportId = utils.randomString(10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}/${version}/${exportId}?protectedSessionId=` + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    utils.download(url);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$('input[name=export-type]').change(function () {
 | 
					$('input[name=export-type]').change(function () {
 | 
				
			||||||
    if (this.value === 'subtree') {
 | 
					    if (this.value === 'subtree') {
 | 
				
			||||||
        if ($("input[name=export-subtree-format]:checked").length === 0) {
 | 
					        if ($("input[name=export-subtree-format]:checked").length === 0) {
 | 
				
			||||||
@@ -72,6 +103,39 @@ $('input[name=export-type]').change(function () {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$('input[name=export-subtree-format]').change(function () {
 | 
				
			||||||
 | 
					    if (this.value === 'opml') {
 | 
				
			||||||
 | 
					        $opmlVersions.slideDown();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        $opmlVersions.slideUp();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					messagingService.subscribeToMessages(async message => {
 | 
				
			||||||
 | 
					    if (message.type === 'export-error') {
 | 
				
			||||||
 | 
					        infoService.showError(message.message);
 | 
				
			||||||
 | 
					        $dialog.modal('hide');
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!message.exportId || message.exportId !== exportId) {
 | 
				
			||||||
 | 
					        // incoming messages must correspond to this export instance
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (message.type === 'export-progress-count') {
 | 
				
			||||||
 | 
					        $exportProgressWrapper.slideDown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $exportProgressCount.text(message.progressCount);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (message.type === 'export-finished') {
 | 
				
			||||||
 | 
					        $dialog.modal('hide');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        infoService.showMessage("Export finished successfully.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    showDialog
 | 
					    showDialog
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/public/javascripts/dialogs/help.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/public/javascripts/dialogs/help.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					const $dialog = $("#help-dialog");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function showDialog() {
 | 
				
			||||||
 | 
					    glob.activeDialog = $dialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $dialog.modal();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    showDialog
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										145
									
								
								src/public/javascripts/dialogs/import.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								src/public/javascripts/dialogs/import.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					import treeService from '../services/tree.js';
 | 
				
			||||||
 | 
					import utils from '../services/utils.js';
 | 
				
			||||||
 | 
					import treeUtils from "../services/tree_utils.js";
 | 
				
			||||||
 | 
					import server from "../services/server.js";
 | 
				
			||||||
 | 
					import infoService from "../services/info.js";
 | 
				
			||||||
 | 
					import messagingService from "../services/messaging.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const $dialog = $("#import-dialog");
 | 
				
			||||||
 | 
					const $form = $("#import-form");
 | 
				
			||||||
 | 
					const $noteTitle = $dialog.find(".note-title");
 | 
				
			||||||
 | 
					const $fileUploadInput = $("#import-file-upload-input");
 | 
				
			||||||
 | 
					const $importProgressCountWrapper = $("#import-progress-count-wrapper");
 | 
				
			||||||
 | 
					const $importProgressCount = $("#import-progress-count");
 | 
				
			||||||
 | 
					const $importButton = $("#import-button");
 | 
				
			||||||
 | 
					const $safeImportCheckbox = $("#safe-import-checkbox");
 | 
				
			||||||
 | 
					const $shrinkImagesCheckbox = $("#shrink-images-checkbox");
 | 
				
			||||||
 | 
					const $textImportedAsTextCheckbox = $("#text-imported-as-text-checkbox");
 | 
				
			||||||
 | 
					const $codeImportedAsCodeCheckbox = $("#code-imported-as-code-checkbox");
 | 
				
			||||||
 | 
					const $explodeArchivesCheckbox = $("#explode-archives-checkbox");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let importId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function showDialog() {
 | 
				
			||||||
 | 
					    // each opening of the dialog resets the importId so we don't associate it with previous imports anymore
 | 
				
			||||||
 | 
					    importId = '';
 | 
				
			||||||
 | 
					    $importProgressCountWrapper.hide();
 | 
				
			||||||
 | 
					    $importProgressCount.text('0');
 | 
				
			||||||
 | 
					    $fileUploadInput.val('').change(); // to trigger Import button disabling listener below
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $safeImportCheckbox.prop("checked", true);
 | 
				
			||||||
 | 
					    $shrinkImagesCheckbox.prop("checked", true);
 | 
				
			||||||
 | 
					    $textImportedAsTextCheckbox.prop("checked", true);
 | 
				
			||||||
 | 
					    $codeImportedAsCodeCheckbox.prop("checked", true);
 | 
				
			||||||
 | 
					    $explodeArchivesCheckbox.prop("checked", true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glob.activeDialog = $dialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const currentNode = treeService.getCurrentNode();
 | 
				
			||||||
 | 
					    $noteTitle.text(await treeUtils.getNoteTitle(currentNode.data.noteId));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $dialog.modal();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$form.submit(() => {
 | 
				
			||||||
 | 
					    const currentNode = treeService.getCurrentNode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // disabling so that import is not triggered again.
 | 
				
			||||||
 | 
					    $importButton.attr("disabled", "disabled");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    importIntoNote(currentNode.data.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function importIntoNote(importNoteId) {
 | 
				
			||||||
 | 
					    const files = Array.from($fileUploadInput[0].files); // shallow copy since we're resetting the upload button below
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // we generate it here (and not on opening) for the case when you try to import multiple times from the same
 | 
				
			||||||
 | 
					    // dialog (which shouldn't happen, but still ...)
 | 
				
			||||||
 | 
					    importId = utils.randomString(10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const options = {
 | 
				
			||||||
 | 
					        safeImport: boolToString($safeImportCheckbox),
 | 
				
			||||||
 | 
					        shrinkImages: boolToString($shrinkImagesCheckbox),
 | 
				
			||||||
 | 
					        textImportedAsText: boolToString($textImportedAsTextCheckbox),
 | 
				
			||||||
 | 
					        codeImportedAsCode: boolToString($codeImportedAsCodeCheckbox),
 | 
				
			||||||
 | 
					        explodeArchives: boolToString($explodeArchivesCheckbox)
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await uploadFiles(importNoteId, files, options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $dialog.modal('hide');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function uploadFiles(importNoteId, files, options) {
 | 
				
			||||||
 | 
					    let noteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const file of files) {
 | 
				
			||||||
 | 
					        const formData = new FormData();
 | 
				
			||||||
 | 
					        formData.append('upload', file);
 | 
				
			||||||
 | 
					        formData.append('importId', importId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const key in options) {
 | 
				
			||||||
 | 
					            formData.append(key, options[key]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ({noteId} = await $.ajax({
 | 
				
			||||||
 | 
					            url: baseApiUrl + 'notes/' + importNoteId + '/import',
 | 
				
			||||||
 | 
					            headers: server.getHeaders(),
 | 
				
			||||||
 | 
					            data: formData,
 | 
				
			||||||
 | 
					            dataType: 'json',
 | 
				
			||||||
 | 
					            type: 'POST',
 | 
				
			||||||
 | 
					            timeout: 60 * 60 * 1000,
 | 
				
			||||||
 | 
					            contentType: false, // NEEDED, DON'T REMOVE THIS
 | 
				
			||||||
 | 
					            processData: false, // NEEDED, DON'T REMOVE THIS
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    infoService.showMessage("Import finished successfully.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await treeService.reload();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (noteId) {
 | 
				
			||||||
 | 
					        const node = await treeService.activateNote(noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        node.setExpanded(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function boolToString($el) {
 | 
				
			||||||
 | 
					    return $el.is(":checked") ? "true" : "false";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					messagingService.subscribeToMessages(async message => {
 | 
				
			||||||
 | 
					    if (message.type === 'import-error') {
 | 
				
			||||||
 | 
					        infoService.showError(message.message);
 | 
				
			||||||
 | 
					        $dialog.modal('hide');
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!message.importId || message.importId !== importId) {
 | 
				
			||||||
 | 
					        // incoming messages must correspond to this import instance
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (message.type === 'import-progress-count') {
 | 
				
			||||||
 | 
					        $importProgressCountWrapper.slideDown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $importProgressCount.text(message.progressCount);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$fileUploadInput.change(() => {
 | 
				
			||||||
 | 
					    if ($fileUploadInput.val()) {
 | 
				
			||||||
 | 
					        $importButton.removeAttr("disabled");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        $importButton.attr("disabled", "disabled");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    showDialog,
 | 
				
			||||||
 | 
					    uploadFiles
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -6,8 +6,6 @@ const $dialog = $("#jump-to-note-dialog");
 | 
				
			|||||||
const $autoComplete = $("#jump-to-note-autocomplete");
 | 
					const $autoComplete = $("#jump-to-note-autocomplete");
 | 
				
			||||||
const $showInFullTextButton = $("#show-in-full-text-button");
 | 
					const $showInFullTextButton = $("#show-in-full-text-button");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$dialog.on("shown.bs.modal", e => $autoComplete.focus());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function showDialog() {
 | 
					async function showDialog() {
 | 
				
			||||||
    glob.activeDialog = $dialog;
 | 
					    glob.activeDialog = $dialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								src/public/javascripts/dialogs/note_info.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/public/javascripts/dialogs/note_info.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import noteDetailService from '../services/note_detail.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const $dialog = $("#note-info-dialog");
 | 
				
			||||||
 | 
					const $noteId = $("#note-info-note-id");
 | 
				
			||||||
 | 
					const $dateCreated = $("#note-info-date-created");
 | 
				
			||||||
 | 
					const $dateModified = $("#note-info-date-modified");
 | 
				
			||||||
 | 
					const $type = $("#note-info-type");
 | 
				
			||||||
 | 
					const $mime = $("#note-info-mime");
 | 
				
			||||||
 | 
					const $okButton = $("#note-info-ok-button");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function showDialog() {
 | 
				
			||||||
 | 
					    glob.activeDialog = $dialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $dialog.modal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const currentNote = noteDetailService.getCurrentNote();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $noteId.text(currentNote.noteId);
 | 
				
			||||||
 | 
					    $dateCreated.text(currentNote.dateCreated);
 | 
				
			||||||
 | 
					    $dateModified.text(currentNote.dateModified);
 | 
				
			||||||
 | 
					    $type.text(currentNote.type);
 | 
				
			||||||
 | 
					    $mime.text(currentNote.mime);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$okButton.click(() => $dialog.modal('hide'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    showDialog
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -8,7 +8,7 @@ function showDialog() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    $dialog.modal();
 | 
					    $dialog.modal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const noteText = noteDetailService.getCurrentNote().content;
 | 
					    const noteText = noteDetailService.getCurrentNote().noteContent.content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $noteSource.text(formatHtml(noteText));
 | 
					    $noteSource.text(formatHtml(noteText));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ import server from '../services/server.js';
 | 
				
			|||||||
import infoService from "../services/info.js";
 | 
					import infoService from "../services/info.js";
 | 
				
			||||||
import zoomService from "../services/zoom.js";
 | 
					import zoomService from "../services/zoom.js";
 | 
				
			||||||
import utils from "../services/utils.js";
 | 
					import utils from "../services/utils.js";
 | 
				
			||||||
 | 
					import cssLoader from "../services/css_loader.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const $dialog = $("#options-dialog");
 | 
					const $dialog = $("#options-dialog");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,10 +45,28 @@ addTabHandler((function() {
 | 
				
			|||||||
    const $zoomFactorSelect = $("#zoom-factor-select");
 | 
					    const $zoomFactorSelect = $("#zoom-factor-select");
 | 
				
			||||||
    const $leftPaneMinWidth = $("#left-pane-min-width");
 | 
					    const $leftPaneMinWidth = $("#left-pane-min-width");
 | 
				
			||||||
    const $leftPaneWidthPercent = $("#left-pane-width-percent");
 | 
					    const $leftPaneWidthPercent = $("#left-pane-width-percent");
 | 
				
			||||||
    const $html = $("html");
 | 
					    const $mainFontSize = $("#main-font-size");
 | 
				
			||||||
 | 
					    const $treeFontSize = $("#tree-font-size");
 | 
				
			||||||
 | 
					    const $detailFontSize = $("#detail-font-size");
 | 
				
			||||||
 | 
					    const $body = $("body");
 | 
				
			||||||
    const $container = $("#container");
 | 
					    const $container = $("#container");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function optionsLoaded(options) {
 | 
					    async function optionsLoaded(options) {
 | 
				
			||||||
 | 
					        const themes = [
 | 
				
			||||||
 | 
					            { val: 'white', title: 'White' },
 | 
				
			||||||
 | 
					            { val: 'dark', title: 'Dark' },
 | 
				
			||||||
 | 
					            { val: 'black', title: 'Black' }
 | 
				
			||||||
 | 
					        ].concat(await server.get('options/user-themes'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $themeSelect.empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const theme of themes) {
 | 
				
			||||||
 | 
					            $themeSelect.append($("<option>")
 | 
				
			||||||
 | 
					                .attr("value", theme.val)
 | 
				
			||||||
 | 
					                .attr("data-note-id", theme.noteId)
 | 
				
			||||||
 | 
					                .html(theme.title));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $themeSelect.val(options.theme);
 | 
					        $themeSelect.val(options.theme);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (utils.isElectron()) {
 | 
					        if (utils.isElectron()) {
 | 
				
			||||||
@@ -59,21 +78,35 @@ addTabHandler((function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $leftPaneMinWidth.val(options.leftPaneMinWidth);
 | 
					        $leftPaneMinWidth.val(options.leftPaneMinWidth);
 | 
				
			||||||
        $leftPaneWidthPercent.val(options.leftPaneWidthPercent);
 | 
					        $leftPaneWidthPercent.val(options.leftPaneWidthPercent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $mainFontSize.val(options.mainFontSize);
 | 
				
			||||||
 | 
					        $treeFontSize.val(options.treeFontSize);
 | 
				
			||||||
 | 
					        $detailFontSize.val(options.detailFontSize);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $themeSelect.change(function() {
 | 
					    $themeSelect.change(function() {
 | 
				
			||||||
        const newTheme = $(this).val();
 | 
					        const newTheme = $(this).val();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $html.attr("class", "theme-" + newTheme);
 | 
					        for (const clazz of Array.from($body[0].classList)) { // create copy to safely iterate over while removing classes
 | 
				
			||||||
 | 
					            if (clazz.startsWith("theme-")) {
 | 
				
			||||||
 | 
					                $body.removeClass(clazz);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const noteId = $(this).find(":selected").attr("data-note-id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (noteId) {
 | 
				
			||||||
 | 
					            // make sure the CSS is loaded
 | 
				
			||||||
 | 
					            // if the CSS has been loaded and then updated then the changes won't take effect though
 | 
				
			||||||
 | 
					            cssLoader.requireCss(`/api/notes/download/${noteId}`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $body.addClass("theme-" + newTheme);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        server.put('options/theme/' + newTheme);
 | 
					        server.put('options/theme/' + newTheme);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $zoomFactorSelect.change(function() {
 | 
					    $zoomFactorSelect.change(function() { zoomService.setZoomFactorAndSave($(this).val()); });
 | 
				
			||||||
        const newZoomFactor = $(this).val();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        zoomService.setZoomFactorAndSave(newZoomFactor);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function resizeLeftPanel() {
 | 
					    function resizeLeftPanel() {
 | 
				
			||||||
        const leftPanePercent = parseInt($leftPaneWidthPercent.val());
 | 
					        const leftPanePercent = parseInt($leftPaneWidthPercent.val());
 | 
				
			||||||
@@ -83,20 +116,42 @@ addTabHandler((function() {
 | 
				
			|||||||
        $container.css("grid-template-columns", `minmax(${leftPaneMinWidth}px, ${leftPanePercent}fr) ${rightPanePercent}fr`);
 | 
					        $container.css("grid-template-columns", `minmax(${leftPaneMinWidth}px, ${leftPanePercent}fr) ${rightPanePercent}fr`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $leftPaneMinWidth.change(function() {
 | 
					    $leftPaneMinWidth.change(async function() {
 | 
				
			||||||
        const newMinWidth = $(this).val();
 | 
					        await server.put('options/leftPaneMinWidth/' + $(this).val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        resizeLeftPanel();
 | 
					        resizeLeftPanel();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        server.put('options/leftPaneMinWidth/' + newMinWidth);
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $leftPaneWidthPercent.change(function() {
 | 
					    $leftPaneWidthPercent.change(async function() {
 | 
				
			||||||
        const newWidthPercent = $(this).val();
 | 
					        await server.put('options/leftPaneWidthPercent/' + $(this).val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        resizeLeftPanel();
 | 
					        resizeLeftPanel();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        server.put('options/leftPaneWidthPercent/' + newWidthPercent);
 | 
					    function applyFontSizes() {
 | 
				
			||||||
 | 
					        console.log($mainFontSize.val() + "% !important");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $body.get(0).style.setProperty("--main-font-size", $mainFontSize.val() + "%");
 | 
				
			||||||
 | 
					        $body.get(0).style.setProperty("--tree-font-size", $treeFontSize.val() + "%");
 | 
				
			||||||
 | 
					        $body.get(0).style.setProperty("--detail-font-size", $detailFontSize.val() + "%");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $mainFontSize.change(async function() {
 | 
				
			||||||
 | 
					        await server.put('options/mainFontSize/' + $(this).val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        applyFontSizes();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $treeFontSize.change(async function() {
 | 
				
			||||||
 | 
					        await server.put('options/treeFontSize/' + $(this).val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        applyFontSizes();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $detailFontSize.change(async function() {
 | 
				
			||||||
 | 
					        await server.put('options/detailFontSize/' + $(this).val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        applyFontSizes();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
@@ -198,15 +253,17 @@ addTabHandler((async function () {
 | 
				
			|||||||
    const $syncVersion = $("#sync-version");
 | 
					    const $syncVersion = $("#sync-version");
 | 
				
			||||||
    const $buildDate = $("#build-date");
 | 
					    const $buildDate = $("#build-date");
 | 
				
			||||||
    const $buildRevision = $("#build-revision");
 | 
					    const $buildRevision = $("#build-revision");
 | 
				
			||||||
 | 
					    const $dataDirectory = $("#data-directory");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const appInfo = await server.get('app-info');
 | 
					    const appInfo = await server.get('app-info');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $appVersion.html(appInfo.appVersion);
 | 
					    $appVersion.text(appInfo.appVersion);
 | 
				
			||||||
    $dbVersion.html(appInfo.dbVersion);
 | 
					    $dbVersion.text(appInfo.dbVersion);
 | 
				
			||||||
    $syncVersion.html(appInfo.syncVersion);
 | 
					    $syncVersion.text(appInfo.syncVersion);
 | 
				
			||||||
    $buildDate.html(appInfo.buildDate);
 | 
					    $buildDate.text(appInfo.buildDate);
 | 
				
			||||||
    $buildRevision.html(appInfo.buildRevision);
 | 
					    $buildRevision.text(appInfo.buildRevision);
 | 
				
			||||||
    $buildRevision.attr('href', 'https://github.com/zadam/trilium/commit/' + appInfo.buildRevision);
 | 
					    $buildRevision.attr('href', 'https://github.com/zadam/trilium/commit/' + appInfo.buildRevision);
 | 
				
			||||||
 | 
					    $dataDirectory.text(appInfo.dataDirectory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {};
 | 
					    return {};
 | 
				
			||||||
})());
 | 
					})());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,3 @@
 | 
				
			|||||||
import utils from '../services/utils.js';
 | 
					 | 
				
			||||||
import libraryLoader from '../services/library_loader.js';
 | 
					import libraryLoader from '../services/library_loader.js';
 | 
				
			||||||
import server from '../services/server.js';
 | 
					import server from '../services/server.js';
 | 
				
			||||||
import infoService from "../services/info.js";
 | 
					import infoService from "../services/info.js";
 | 
				
			||||||
@@ -8,14 +7,17 @@ const $query = $('#sql-console-query');
 | 
				
			|||||||
const $executeButton = $('#sql-console-execute');
 | 
					const $executeButton = $('#sql-console-execute');
 | 
				
			||||||
const $resultHead = $('#sql-console-results thead');
 | 
					const $resultHead = $('#sql-console-results thead');
 | 
				
			||||||
const $resultBody = $('#sql-console-results tbody');
 | 
					const $resultBody = $('#sql-console-results tbody');
 | 
				
			||||||
 | 
					const $tables = $("#sql-console-tables");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let codeEditor;
 | 
					let codeEditor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$dialog.on("shown.bs.modal", e => initEditor());
 | 
					$dialog.on("shown.bs.modal", e => initEditor());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function showDialog() {
 | 
					async function showDialog() {
 | 
				
			||||||
    glob.activeDialog = $dialog;
 | 
					    glob.activeDialog = $dialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await showTables();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $dialog.modal();
 | 
					    $dialog.modal();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,6 +98,32 @@ async function execute(e) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function showTables() {
 | 
				
			||||||
 | 
					    const tables = await server.get('sql/schema');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $tables.empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const table of tables) {
 | 
				
			||||||
 | 
					        const $tableLink = $('<button class="btn">').text(table.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const $columns = $("<table>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const column of table.columns) {
 | 
				
			||||||
 | 
					            $columns.append(
 | 
				
			||||||
 | 
					                $("<tr>")
 | 
				
			||||||
 | 
					                    .append($("<td>").text(column.name))
 | 
				
			||||||
 | 
					                    .append($("<td>").text(column.type))
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $tables.append($tableLink).append(" ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $tableLink
 | 
				
			||||||
 | 
					            .tooltip({html: true, title: $columns.html()})
 | 
				
			||||||
 | 
					            .click(() => codeEditor.setValue("SELECT * FROM " + table.name + " LIMIT 100"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$query.bind('keydown', 'ctrl+return', execute);
 | 
					$query.bind('keydown', 'ctrl+return', execute);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$executeButton.click(execute);
 | 
					$executeButton.click(execute);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								src/public/javascripts/entities/attribute.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/public/javascripts/entities/attribute.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					class Attribute {
 | 
				
			||||||
 | 
					    constructor(treeCache, row) {
 | 
				
			||||||
 | 
					        this.treeCache = treeCache;
 | 
				
			||||||
 | 
					        /** @param {string} attributeId */
 | 
				
			||||||
 | 
					        this.attributeId = row.attributeId;
 | 
				
			||||||
 | 
					        /** @param {string} noteId */
 | 
				
			||||||
 | 
					        this.noteId = row.noteId;
 | 
				
			||||||
 | 
					        /** @param {string} type */
 | 
				
			||||||
 | 
					        this.type = row.type;
 | 
				
			||||||
 | 
					        /** @param {string} name */
 | 
				
			||||||
 | 
					        this.name = row.name;
 | 
				
			||||||
 | 
					        /** @param {string} value */
 | 
				
			||||||
 | 
					        this.value = row.value;
 | 
				
			||||||
 | 
					        /** @param {int} position */
 | 
				
			||||||
 | 
					        this.position = row.position;
 | 
				
			||||||
 | 
					        /** @param {boolean} isInheritable */
 | 
				
			||||||
 | 
					        this.isInheritable = row.isInheritable;
 | 
				
			||||||
 | 
					        /** @param {boolean} isDeleted */
 | 
				
			||||||
 | 
					        this.isDeleted = row.isDeleted;
 | 
				
			||||||
 | 
					        /** @param {string} dateCreated */
 | 
				
			||||||
 | 
					        this.dateCreated = row.dateCreated;
 | 
				
			||||||
 | 
					        /** @param {string} dateModified */
 | 
				
			||||||
 | 
					        this.dateModified = row.dateModified;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {NoteShort} */
 | 
				
			||||||
 | 
					    async getNote() {
 | 
				
			||||||
 | 
					        return await this.treeCache.getNote(this.noteId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get toString() {
 | 
				
			||||||
 | 
					        return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name})`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Attribute;
 | 
				
			||||||
@@ -8,15 +8,13 @@ class NoteFull extends NoteShort {
 | 
				
			|||||||
        super(treeCache, row);
 | 
					        super(treeCache, row);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /** @param {string} */
 | 
					        /** @param {string} */
 | 
				
			||||||
        this.content = row.content;
 | 
					        this.noteContent = row.noteContent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.content !== "" && this.isJson()) {
 | 
					        /** @param {string} */
 | 
				
			||||||
            try {
 | 
					        this.dateCreated = row.dateCreated;
 | 
				
			||||||
                /** @param {object} */
 | 
					
 | 
				
			||||||
                this.jsonContent = JSON.parse(this.content);
 | 
					        /** @param {string} */
 | 
				
			||||||
            }
 | 
					        this.dateModified = row.dateModified;
 | 
				
			||||||
            catch(e) {}
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,10 @@
 | 
				
			|||||||
 | 
					import server from '../services/server.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const LABEL = 'label';
 | 
				
			||||||
 | 
					const LABEL_DEFINITION = 'label-definition';
 | 
				
			||||||
 | 
					const RELATION = 'relation';
 | 
				
			||||||
 | 
					const RELATION_DEFINITION = 'relation-definition';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This note's representation is used in note tree and is kept in TreeCache.
 | 
					 * This note's representation is used in note tree and is kept in TreeCache.
 | 
				
			||||||
 * Its notable omission is the note content.
 | 
					 * Its notable omission is the note content.
 | 
				
			||||||
@@ -71,6 +78,140 @@ class NoteShort {
 | 
				
			|||||||
        return await this.treeCache.getNotes(this.getChildNoteIds());
 | 
					        return await this.treeCache.getNotes(this.getChildNoteIds());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - attribute name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getAttributes(name) {
 | 
				
			||||||
 | 
					        if (!this.attributeCache) {
 | 
				
			||||||
 | 
					            this.attributeCache = await server.get('notes/' + this.noteId + '/attributes');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (name) {
 | 
				
			||||||
 | 
					            return this.attributeCache.filter(attr => attr.name === name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            return this.attributeCache;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - label name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's labels (attributes with type label), including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabels(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === LABEL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - label name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's label definitions, including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabelDefinitions(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === LABEL_DEFINITION);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - relation name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's relations (attributes with type relation), including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelations(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === RELATION);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} [name] - relation name to filter
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute[]>} all note's relation definitions including inherited ones
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationDefinitions(name) {
 | 
				
			||||||
 | 
					        return (await this.getAttributes(name)).filter(attr => attr.type === RELATION_DEFINITION);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} type - attribute type (label, relation, etc.)
 | 
				
			||||||
 | 
					     * @param {string} name - attribute name
 | 
				
			||||||
 | 
					     * @returns {Promise<boolean>} true if note has an attribute with given type and name (including inherited)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async hasAttribute(type, name) {
 | 
				
			||||||
 | 
					        return !!await this.getAttribute(type, name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} type - attribute type (label, relation, etc.)
 | 
				
			||||||
 | 
					     * @param {string} name - attribute name
 | 
				
			||||||
 | 
					     * @returns {Promise<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.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getAttribute(type, name) {
 | 
				
			||||||
 | 
					        const attributes = await 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 {Promise<string>} attribute value of given type and name or null if no such attribute exists.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getAttributeValue(type, name) {
 | 
				
			||||||
 | 
					        const attr = await this.getAttribute(type, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return attr ? attr.value : null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - label name
 | 
				
			||||||
 | 
					     * @returns {Promise<boolean>} true if label exists (including inherited)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async hasLabel(name) { return await this.hasAttribute(LABEL, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - relation name
 | 
				
			||||||
 | 
					     * @returns {Promise<boolean>} true if relation exists (including inherited)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async hasRelation(name) { return await this.hasAttribute(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - label name
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute>} label if it exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabel(name) { return await this.getAttribute(LABEL, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - relation name
 | 
				
			||||||
 | 
					     * @returns {Promise<Attribute>} relation if it exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelation(name) { return await this.getAttribute(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - label name
 | 
				
			||||||
 | 
					     * @returns {Promise<string>} label value if label exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getLabelValue(name) { return await this.getAttributeValue(LABEL, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name - relation name
 | 
				
			||||||
 | 
					     * @returns {Promise<string>} relation value if relation exists, null otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {string} name
 | 
				
			||||||
 | 
					     * @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async getRelationTarget(name) {
 | 
				
			||||||
 | 
					        const relation = await this.getRelation(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return relation ? await repository.getNote(relation.value) : null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Clear note's attributes cache to force fresh reload for next attribute request.
 | 
				
			||||||
 | 
					     * Cache is note instance scoped.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    invalidateAttributeCache() {
 | 
				
			||||||
 | 
					        this.attributeCache = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get toString() {
 | 
					    get toString() {
 | 
				
			||||||
        return `Note(noteId=${this.noteId}, title=${this.title})`;
 | 
					        return `Note(noteId=${this.noteId}, title=${this.title})`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -79,6 +220,7 @@ class NoteShort {
 | 
				
			|||||||
        const dto = Object.assign({}, this);
 | 
					        const dto = Object.assign({}, this);
 | 
				
			||||||
        delete dto.treeCache;
 | 
					        delete dto.treeCache;
 | 
				
			||||||
        delete dto.archived;
 | 
					        delete dto.archived;
 | 
				
			||||||
 | 
					        delete dto.attributeCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return dto;
 | 
					        return dto;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										128
									
								
								src/public/javascripts/mobile.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/public/javascripts/mobile.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					import treeService from "./services/tree.js";
 | 
				
			||||||
 | 
					import noteDetailService from "./services/note_detail.js";
 | 
				
			||||||
 | 
					import dragAndDropSetup from "./services/drag_and_drop.js";
 | 
				
			||||||
 | 
					import treeCache from "./services/tree_cache.js";
 | 
				
			||||||
 | 
					import treeBuilder from "./services/tree_builder.js";
 | 
				
			||||||
 | 
					import contextMenuWidget from "./services/context_menu.js";
 | 
				
			||||||
 | 
					import ContextMenuItemsContainer from "./services/context_menu_items_container.js";
 | 
				
			||||||
 | 
					import treeChangesService from "./services/branches.js";
 | 
				
			||||||
 | 
					import utils from "./services/utils.js";
 | 
				
			||||||
 | 
					import treeUtils from "./services/tree_utils.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const $leftPane = $("#left-pane");
 | 
				
			||||||
 | 
					const $tree = $("#tree");
 | 
				
			||||||
 | 
					const $detail = $("#detail");
 | 
				
			||||||
 | 
					const $closeDetailButton = $("#close-detail-button");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function togglePanes() {
 | 
				
			||||||
 | 
					    if (!$leftPane.is(":visible") || !$detail.is(":visible")) {
 | 
				
			||||||
 | 
					        $detail.toggleClass("d-none");
 | 
				
			||||||
 | 
					        $leftPane.toggleClass("d-none");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function showDetailPane() {
 | 
				
			||||||
 | 
					    if (!$detail.is(":visible")) {
 | 
				
			||||||
 | 
					        $detail.removeClass("d-none");
 | 
				
			||||||
 | 
					        $leftPane.addClass("d-none");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$closeDetailButton.click(() => {
 | 
				
			||||||
 | 
					    // no page is opened
 | 
				
			||||||
 | 
					    document.location.hash = '-';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    togglePanes();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function showTree() {
 | 
				
			||||||
 | 
					    const tree = await treeService.loadTree();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $tree.fancytree({
 | 
				
			||||||
 | 
					        autoScroll: true,
 | 
				
			||||||
 | 
					        extensions: ["dnd5", "clones"],
 | 
				
			||||||
 | 
					        source: tree,
 | 
				
			||||||
 | 
					        scrollParent: $tree,
 | 
				
			||||||
 | 
					        minExpandLevel: 2, // root can't be collapsed
 | 
				
			||||||
 | 
					        activate: (event, data) => {
 | 
				
			||||||
 | 
					            const node = data.node;
 | 
				
			||||||
 | 
					            const noteId = node.data.noteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            treeService.clearSelectedNodes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            treeService.setCurrentNotePathToHash(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            showDetailPane();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            noteDetailService.switchToNote(noteId, true);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true),
 | 
				
			||||||
 | 
					        collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false),
 | 
				
			||||||
 | 
					        init: (event, data) => treeService.treeInitialized(), // don't collapse to short form
 | 
				
			||||||
 | 
					        dnd5: dragAndDropSetup,
 | 
				
			||||||
 | 
					        lazyLoad: function(event, data) {
 | 
				
			||||||
 | 
					            const noteId = data.node.data.noteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            data.result = treeCache.getNote(noteId).then(note => treeBuilder.prepareBranch(note));
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        clones: {
 | 
				
			||||||
 | 
					            highlightActiveClones: true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#note-menu-button").click(async e => {
 | 
				
			||||||
 | 
					    const node = treeService.getCurrentNode();
 | 
				
			||||||
 | 
					    const branch = await treeCache.getBranch(node.data.branchId);
 | 
				
			||||||
 | 
					    const note = await treeCache.getNote(node.data.noteId);
 | 
				
			||||||
 | 
					    const parentNote = await treeCache.getNote(branch.parentNoteId);
 | 
				
			||||||
 | 
					    const isNotRoot = note.noteId !== 'root';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const itemsContainer = new ContextMenuItemsContainer([
 | 
				
			||||||
 | 
					        {title: "Insert note after", cmd: "insertNoteAfter", uiIcon: "plus"},
 | 
				
			||||||
 | 
					        {title: "Insert child note", cmd: "insertChildNote", uiIcon: "plus"},
 | 
				
			||||||
 | 
					        {title: "Delete this note", cmd: "delete", uiIcon: "trash"}
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    itemsContainer.enableItem("insertNoteAfter", isNotRoot && parentNote.type !== 'search');
 | 
				
			||||||
 | 
					    itemsContainer.enableItem("insertChildNote", note.type !== 'search');
 | 
				
			||||||
 | 
					    itemsContainer.enableItem("delete", isNotRoot && parentNote.type !== 'search');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    contextMenuWidget.initContextMenu(e, itemsContainer, (event, cmd) => {
 | 
				
			||||||
 | 
					        if (cmd === "insertNoteAfter") {
 | 
				
			||||||
 | 
					            const parentNoteId = node.data.parentNoteId;
 | 
				
			||||||
 | 
					            const isProtected = treeUtils.getParentProtectedStatus(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            treeService.createNote(node, parentNoteId, 'after', isProtected);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (cmd === "insertChildNote") {
 | 
				
			||||||
 | 
					            treeService.createNote(node, node.data.noteId, 'into');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (cmd === "delete") {
 | 
				
			||||||
 | 
					            treeChangesService.deleteNodes([node]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // move to the tree
 | 
				
			||||||
 | 
					            togglePanes();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            throw new Error("Unrecognized command " + cmd);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#switch-to-desktop-button").click(() => {
 | 
				
			||||||
 | 
					    utils.setCookie('trilium-device', 'desktop');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    utils.reloadApp();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("#log-out-button").click(() => {
 | 
				
			||||||
 | 
					    $("#logout-form").submit();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// this is done so that startNotePath is not used
 | 
				
			||||||
 | 
					if (!document.location.hash) {
 | 
				
			||||||
 | 
					    document.location.hash = '-';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					showTree();
 | 
				
			||||||
@@ -13,13 +13,25 @@ const $savedIndicator = $("#saved-indicator");
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let attributePromise;
 | 
					let attributePromise;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function refreshAttributes() {
 | 
					function invalidateAttributes() {
 | 
				
			||||||
 | 
					    attributePromise = null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function reloadAttributes() {
 | 
				
			||||||
    attributePromise = server.get('notes/' + noteDetailService.getCurrentNoteId() + '/attributes');
 | 
					    attributePromise = server.get('notes/' + noteDetailService.getCurrentNoteId() + '/attributes');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function refreshAttributes() {
 | 
				
			||||||
 | 
					    reloadAttributes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await showAttributes();
 | 
					    await showAttributes();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function getAttributes() {
 | 
					async function getAttributes() {
 | 
				
			||||||
 | 
					    if (!attributePromise) {
 | 
				
			||||||
 | 
					        reloadAttributes();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return await attributePromise;
 | 
					    return await attributePromise;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,8 +85,11 @@ async function showAttributes() {
 | 
				
			|||||||
        $promotedAttributesContainer.empty().append($tbody);
 | 
					        $promotedAttributesContainer.empty().append($tbody);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (note.type !== 'relation-map') {
 | 
					    else if (note.type !== 'relation-map') {
 | 
				
			||||||
        if (attributes.length > 0) {
 | 
					        // display only "own" notes
 | 
				
			||||||
            for (const attribute of attributes) {
 | 
					        const ownedAttributes = attributes.filter(attr => attr.noteId === note.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ownedAttributes.length > 0) {
 | 
				
			||||||
 | 
					            for (const attribute of ownedAttributes) {
 | 
				
			||||||
                if (attribute.type === 'label') {
 | 
					                if (attribute.type === 'label') {
 | 
				
			||||||
                    $attributeListInner.append(utils.formatLabel(attribute) + " ");
 | 
					                    $attributeListInner.append(utils.formatLabel(attribute) + " ");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -120,7 +135,9 @@ async function createPromotedAttributeRow(definitionAttr, valueAttr) {
 | 
				
			|||||||
    const $inputCell = $("<td>").append($("<div>").addClass("input-group").append($input));
 | 
					    const $inputCell = $("<td>").append($("<div>").addClass("input-group").append($input));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const $actionCell = $("<td>");
 | 
					    const $actionCell = $("<td>");
 | 
				
			||||||
    const $multiplicityCell = $("<td>").addClass("multiplicity");
 | 
					    const $multiplicityCell = $("<td>")
 | 
				
			||||||
 | 
					        .addClass("multiplicity")
 | 
				
			||||||
 | 
					        .attr("nowrap", true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $tr
 | 
					    $tr
 | 
				
			||||||
        .append($labelCell)
 | 
					        .append($labelCell)
 | 
				
			||||||
@@ -143,7 +160,7 @@ async function createPromotedAttributeRow(definitionAttr, valueAttr) {
 | 
				
			|||||||
                $input.autocomplete({
 | 
					                $input.autocomplete({
 | 
				
			||||||
                    appendTo: document.querySelector('body'),
 | 
					                    appendTo: document.querySelector('body'),
 | 
				
			||||||
                    hint: false,
 | 
					                    hint: false,
 | 
				
			||||||
                    autoselect: true,
 | 
					                    autoselect: false,
 | 
				
			||||||
                    openOnFocus: true,
 | 
					                    openOnFocus: true,
 | 
				
			||||||
                    minLength: 0,
 | 
					                    minLength: 0,
 | 
				
			||||||
                    tabAutocomplete: false
 | 
					                    tabAutocomplete: false
 | 
				
			||||||
@@ -286,5 +303,6 @@ async function promotedAttributeChanged(event) {
 | 
				
			|||||||
export default {
 | 
					export default {
 | 
				
			||||||
    getAttributes,
 | 
					    getAttributes,
 | 
				
			||||||
    showAttributes,
 | 
					    showAttributes,
 | 
				
			||||||
    refreshAttributes
 | 
					    refreshAttributes,
 | 
				
			||||||
 | 
					    invalidateAttributes
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										136
									
								
								src/public/javascripts/services/bootstrap.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										136
									
								
								src/public/javascripts/services/bootstrap.js
									
									
									
									
										vendored
									
									
								
							@@ -1,136 +0,0 @@
 | 
				
			|||||||
import addLinkDialog from '../dialogs/add_link.js';
 | 
					 | 
				
			||||||
import jumpToNoteDialog from '../dialogs/jump_to_note.js';
 | 
					 | 
				
			||||||
import attributesDialog from '../dialogs/attributes.js';
 | 
					 | 
				
			||||||
import noteRevisionsDialog from '../dialogs/note_revisions.js';
 | 
					 | 
				
			||||||
import noteSourceDialog from '../dialogs/note_source.js';
 | 
					 | 
				
			||||||
import recentChangesDialog from '../dialogs/recent_changes.js';
 | 
					 | 
				
			||||||
import optionsDialog from '../dialogs/options.js';
 | 
					 | 
				
			||||||
import sqlConsoleDialog from '../dialogs/sql_console.js';
 | 
					 | 
				
			||||||
import markdownImportDialog from '../dialogs/markdown_import.js';
 | 
					 | 
				
			||||||
import exportDialog from '../dialogs/export.js';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import cloning from './cloning.js';
 | 
					 | 
				
			||||||
import contextMenu from './tree_context_menu.js';
 | 
					 | 
				
			||||||
import dragAndDropSetup from './drag_and_drop.js';
 | 
					 | 
				
			||||||
import exportService from './export.js';
 | 
					 | 
				
			||||||
import link from './link.js';
 | 
					 | 
				
			||||||
import messagingService from './messaging.js';
 | 
					 | 
				
			||||||
import noteDetailService from './note_detail.js';
 | 
					 | 
				
			||||||
import noteType from './note_type.js';
 | 
					 | 
				
			||||||
import protected_session from './protected_session.js';
 | 
					 | 
				
			||||||
import searchNotesService from './search_notes.js';
 | 
					 | 
				
			||||||
import FrontendScriptApi from './frontend_script_api.js';
 | 
					 | 
				
			||||||
import ScriptContext from './script_context.js';
 | 
					 | 
				
			||||||
import sync from './sync.js';
 | 
					 | 
				
			||||||
import treeService from './tree.js';
 | 
					 | 
				
			||||||
import treeChanges from './branches.js';
 | 
					 | 
				
			||||||
import treeUtils from './tree_utils.js';
 | 
					 | 
				
			||||||
import utils from './utils.js';
 | 
					 | 
				
			||||||
import server from './server.js';
 | 
					 | 
				
			||||||
import entrypoints from './entrypoints.js';
 | 
					 | 
				
			||||||
import tooltip from './tooltip.js';
 | 
					 | 
				
			||||||
import bundle from "./bundle.js";
 | 
					 | 
				
			||||||
import treeCache from "./tree_cache.js";
 | 
					 | 
				
			||||||
import libraryLoader from "./library_loader.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// required for CKEditor image upload plugin
 | 
					 | 
				
			||||||
window.glob.getCurrentNode = treeService.getCurrentNode;
 | 
					 | 
				
			||||||
window.glob.getHeaders = server.getHeaders;
 | 
					 | 
				
			||||||
window.glob.showAddLinkDialog = addLinkDialog.showDialog;
 | 
					 | 
				
			||||||
// this is required by CKEditor when uploading images
 | 
					 | 
				
			||||||
window.glob.noteChanged = noteDetailService.noteChanged;
 | 
					 | 
				
			||||||
window.glob.refreshTree = treeService.reload;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// required for ESLint plugin
 | 
					 | 
				
			||||||
window.glob.getCurrentNote = noteDetailService.getCurrentNote;
 | 
					 | 
				
			||||||
window.glob.requireLibrary = libraryLoader.requireLibrary;
 | 
					 | 
				
			||||||
window.glob.ESLINT = libraryLoader.ESLINT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
 | 
					 | 
				
			||||||
    const string = msg.toLowerCase();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let message = "Uncaught error: ";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (string.includes("Cannot read property 'defaultView' of undefined")) {
 | 
					 | 
				
			||||||
        // ignore this specific error which is very common but we don't know where it comes from
 | 
					 | 
				
			||||||
        // and it seems to be harmless
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (string.includes("script error")) {
 | 
					 | 
				
			||||||
        message += 'No details available';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        message += [
 | 
					 | 
				
			||||||
            'Message: ' + msg,
 | 
					 | 
				
			||||||
            'URL: ' + url,
 | 
					 | 
				
			||||||
            'Line: ' + lineNo,
 | 
					 | 
				
			||||||
            'Column: ' + columnNo,
 | 
					 | 
				
			||||||
            'Error object: ' + JSON.stringify(error)
 | 
					 | 
				
			||||||
        ].join(' - ');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    messagingService.logError(message);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const wikiBaseUrl = "https://github.com/zadam/trilium/wiki/";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$(document).on("click", "button[data-help-page]", e => {
 | 
					 | 
				
			||||||
    const $button = $(e.target);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    window.open(wikiBaseUrl + $button.attr("data-help-page"), '_blank');
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$("#logout-button").toggle(!utils.isElectron());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (utils.isElectron()) {
 | 
					 | 
				
			||||||
    require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
 | 
					 | 
				
			||||||
        // this might occur when day note had to be created
 | 
					 | 
				
			||||||
        if (!await treeCache.getNote(parentNoteId)) {
 | 
					 | 
				
			||||||
            await treeService.reload();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        await treeService.activateNote(parentNoteId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        setTimeout(async () => {
 | 
					 | 
				
			||||||
            const parentNode = treeService.getCurrentNode();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const {note} = await treeService.createNote(parentNode, parentNode.data.noteId, 'into', parentNode.data.isProtected);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            await treeService.activateNote(note.noteId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }, 500);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function exec(cmd) {
 | 
					 | 
				
			||||||
    document.execCommand(cmd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (utils.isElectron() && utils.isMac()) {
 | 
					 | 
				
			||||||
    utils.bindShortcut('ctrl+c', () => exec("copy"));
 | 
					 | 
				
			||||||
    utils.bindShortcut('ctrl+v', () => exec('paste'));
 | 
					 | 
				
			||||||
    utils.bindShortcut('ctrl+x', () => exec('cut'));
 | 
					 | 
				
			||||||
    utils.bindShortcut('ctrl+a', () => exec('selectAll'));
 | 
					 | 
				
			||||||
    utils.bindShortcut('ctrl+z', () => exec('undo'));
 | 
					 | 
				
			||||||
    utils.bindShortcut('ctrl+y', () => exec('redo'));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$("#export-note-button").click(function () {
 | 
					 | 
				
			||||||
    if ($(this).hasClass("disabled")) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    exportDialog.showDialog('single');
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
treeService.showTree();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
entrypoints.registerEntrypoints();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tooltip.setupTooltip();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bundle.executeStartupBundles();
 | 
					 | 
				
			||||||
@@ -9,7 +9,7 @@ async function getAndExecuteBundle(noteId, originEntity = null) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function executeBundle(bundle, originEntity) {
 | 
					async function executeBundle(bundle, originEntity) {
 | 
				
			||||||
    const apiContext = ScriptContext(bundle.note, bundle.allNotes, originEntity);
 | 
					    const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        return await (function () {
 | 
					        return await (function () {
 | 
				
			||||||
@@ -30,9 +30,13 @@ async function executeStartupBundles() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function executeRelationBundles(note, relationName) {
 | 
					async function executeRelationBundles(note, relationName) {
 | 
				
			||||||
    const bundlesToRun = await server.get("script/relation/" + note.noteId + "/" + relationName);
 | 
					    note.bundleCache = note.bundleCache || {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const bundle of bundlesToRun) {
 | 
					    if (!note.bundleCache[relationName]) {
 | 
				
			||||||
 | 
					        note.bundleCache[relationName] = await server.get("script/relation/" + note.noteId + "/" + relationName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const bundle of note.bundleCache[relationName]) {
 | 
				
			||||||
        await executeBundle(bundle, note);
 | 
					        await executeBundle(bundle, note);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,11 @@
 | 
				
			|||||||
const $contextMenuContainer = $("#context-menu-container");
 | 
					const $contextMenuContainer = $("#context-menu-container");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function initContextMenu(event, contextMenuItems, selectContextMenuItem) {
 | 
					function initContextMenu(event, itemContainer, selectContextMenuItem) {
 | 
				
			||||||
 | 
					    event.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $contextMenuContainer.empty();
 | 
					    $contextMenuContainer.empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const item of contextMenuItems) {
 | 
					    for (const item of itemContainer.getItems()) {
 | 
				
			||||||
        if (item.title === '----') {
 | 
					        if (item.title === '----') {
 | 
				
			||||||
            $contextMenuContainer.append($("<div>").addClass("dropdown-divider"));
 | 
					            $contextMenuContainer.append($("<div>").addClass("dropdown-divider"));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					class ContextMenuItemsContainer {
 | 
				
			||||||
 | 
					    constructor(items) {
 | 
				
			||||||
 | 
					        // clone the item array and the items themselves
 | 
				
			||||||
 | 
					        this.items = items.map(item => Object.assign({}, item));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hideItem(cmd, hidden = true) {
 | 
				
			||||||
 | 
					        if (hidden) {
 | 
				
			||||||
 | 
					            this.items = this.items.filter(item => item.cmd !== cmd);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enableItem(cmd, enabled) {
 | 
				
			||||||
 | 
					        const item = this.items.find(item => item.cmd === cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!item) {
 | 
				
			||||||
 | 
					            throw new Error(`Command ${cmd} has not been found!`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        item.enabled = enabled;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getItems() {
 | 
				
			||||||
 | 
					        return this.items;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ContextMenuItemsContainer;
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/public/javascripts/services/css_loader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/public/javascripts/services/css_loader.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					async function requireCss(url) {
 | 
				
			||||||
 | 
					    const css = Array
 | 
				
			||||||
 | 
					        .from(document.querySelectorAll('link'))
 | 
				
			||||||
 | 
					        .map(scr => scr.href);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!css.includes(url)) {
 | 
				
			||||||
 | 
					        $('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    requireCss
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
import treeService from './tree.js';
 | 
					import treeService from './tree.js';
 | 
				
			||||||
import treeChangesService from './branches.js';
 | 
					import treeChangesService from './branches.js';
 | 
				
			||||||
 | 
					import importDialog from '../dialogs/import.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const dragAndDropSetup = {
 | 
					const dragAndDropSetup = {
 | 
				
			||||||
    autoExpandMS: 600,
 | 
					    autoExpandMS: 600,
 | 
				
			||||||
@@ -9,6 +10,14 @@ const dragAndDropSetup = {
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!data.originalEvent.ctrlKey) {
 | 
				
			||||||
 | 
					            // keep existing selection only if CTRL key is pressed
 | 
				
			||||||
 | 
					            for (const selectedNode of treeService.getSelectedNodes()) {
 | 
				
			||||||
 | 
					                selectedNode.setSelected(false);
 | 
				
			||||||
 | 
					                selectedNode.renderTitle();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        node.setSelected(true);
 | 
					        node.setSelected(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // this is for dragging notes into relation map
 | 
					        // this is for dragging notes into relation map
 | 
				
			||||||
@@ -24,7 +33,20 @@ const dragAndDropSetup = {
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    dragEnter: (node, data) => true, // allow drop on any node
 | 
					    dragEnter: (node, data) => true, // allow drop on any node
 | 
				
			||||||
 | 
					    dragOver: (node, data) => true,
 | 
				
			||||||
    dragDrop: (node, data) => {
 | 
					    dragDrop: (node, data) => {
 | 
				
			||||||
 | 
					        const dataTransfer = data.dataTransfer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
 | 
				
			||||||
 | 
					            importDialog.uploadFiles(node.data.noteId, dataTransfer.files, {
 | 
				
			||||||
 | 
					                safeImport: true,
 | 
				
			||||||
 | 
					                shrinkImages: true,
 | 
				
			||||||
 | 
					                textImportedAsText: true,
 | 
				
			||||||
 | 
					                codeImportedAsCode: true,
 | 
				
			||||||
 | 
					                explodeArchives: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
            // This function MUST be defined to enable dropping of items on the tree.
 | 
					            // This function MUST be defined to enable dropping of items on the tree.
 | 
				
			||||||
            // data.hitMode is 'before', 'after', or 'over'.
 | 
					            // data.hitMode is 'before', 'after', or 'over'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,17 +54,15 @@ const dragAndDropSetup = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (data.hitMode === "before") {
 | 
					            if (data.hitMode === "before") {
 | 
				
			||||||
                treeChangesService.moveBeforeNode(selectedNodes, node);
 | 
					                treeChangesService.moveBeforeNode(selectedNodes, node);
 | 
				
			||||||
        }
 | 
					            } else if (data.hitMode === "after") {
 | 
				
			||||||
        else if (data.hitMode === "after") {
 | 
					 | 
				
			||||||
                treeChangesService.moveAfterNode(selectedNodes, node);
 | 
					                treeChangesService.moveAfterNode(selectedNodes, node);
 | 
				
			||||||
        }
 | 
					            } else if (data.hitMode === "over") {
 | 
				
			||||||
        else if (data.hitMode === "over") {
 | 
					 | 
				
			||||||
                treeChangesService.moveToNode(selectedNodes, node);
 | 
					                treeChangesService.moveToNode(selectedNodes, node);
 | 
				
			||||||
        }
 | 
					            } else {
 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
                throw new Error("Unknown hitMode=" + data.hitMode);
 | 
					                throw new Error("Unknown hitMode=" + data.hitMode);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default dragAndDropSetup;
 | 
					export default dragAndDropSetup;
 | 
				
			||||||
@@ -1,7 +1,6 @@
 | 
				
			|||||||
import utils from "./utils.js";
 | 
					import utils from "./utils.js";
 | 
				
			||||||
import treeService from "./tree.js";
 | 
					import treeService from "./tree.js";
 | 
				
			||||||
import linkService from "./link.js";
 | 
					import linkService from "./link.js";
 | 
				
			||||||
import fileService from "./file.js";
 | 
					 | 
				
			||||||
import zoomService from "./zoom.js";
 | 
					import zoomService from "./zoom.js";
 | 
				
			||||||
import noteRevisionsDialog from "../dialogs/note_revisions.js";
 | 
					import noteRevisionsDialog from "../dialogs/note_revisions.js";
 | 
				
			||||||
import optionsDialog from "../dialogs/options.js";
 | 
					import optionsDialog from "../dialogs/options.js";
 | 
				
			||||||
@@ -12,6 +11,8 @@ import recentChangesDialog from "../dialogs/recent_changes.js";
 | 
				
			|||||||
import sqlConsoleDialog from "../dialogs/sql_console.js";
 | 
					import sqlConsoleDialog from "../dialogs/sql_console.js";
 | 
				
			||||||
import searchNotesService from "./search_notes.js";
 | 
					import searchNotesService from "./search_notes.js";
 | 
				
			||||||
import attributesDialog from "../dialogs/attributes.js";
 | 
					import attributesDialog from "../dialogs/attributes.js";
 | 
				
			||||||
 | 
					import helpDialog from "../dialogs/help.js";
 | 
				
			||||||
 | 
					import noteInfoDialog from "../dialogs/note_info.js";
 | 
				
			||||||
import protectedSessionService from "./protected_session.js";
 | 
					import protectedSessionService from "./protected_session.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function registerEntrypoints() {
 | 
					function registerEntrypoints() {
 | 
				
			||||||
@@ -54,16 +55,29 @@ function registerEntrypoints() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    $("#options-button").click(optionsDialog.showDialog);
 | 
					    $("#options-button").click(optionsDialog.showDialog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $("#show-help-button").click(helpDialog.showDialog);
 | 
				
			||||||
 | 
					    utils.bindShortcut('f1', helpDialog.showDialog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $("#open-sql-console-button").click(sqlConsoleDialog.showDialog);
 | 
				
			||||||
    utils.bindShortcut('alt+o', sqlConsoleDialog.showDialog);
 | 
					    utils.bindShortcut('alt+o', sqlConsoleDialog.showDialog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $("#show-note-info-button").click(noteInfoDialog.showDialog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (utils.isElectron()) {
 | 
					    if (utils.isElectron()) {
 | 
				
			||||||
        $("#history-navigation").show();
 | 
					        $("#history-navigation").show();
 | 
				
			||||||
        $("#history-back-button").click(window.history.back);
 | 
					        $("#history-back-button").click(window.history.back);
 | 
				
			||||||
        $("#history-forward-button").click(window.history.forward);
 | 
					        $("#history-forward-button").click(window.history.forward);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (utils.isMac()) {
 | 
				
			||||||
 | 
					            // Mac has a different history navigation shortcuts - https://github.com/zadam/trilium/issues/376
 | 
				
			||||||
 | 
					            utils.bindShortcut('meta+left', window.history.back);
 | 
				
			||||||
 | 
					            utils.bindShortcut('meta+right', window.history.forward);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
            utils.bindShortcut('alt+left', window.history.back);
 | 
					            utils.bindShortcut('alt+left', window.history.back);
 | 
				
			||||||
            utils.bindShortcut('alt+right', window.history.forward);
 | 
					            utils.bindShortcut('alt+right', window.history.forward);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    utils.bindShortcut('alt+m', e => {
 | 
					    utils.bindShortcut('alt+m', e => {
 | 
				
			||||||
        $(".hide-toggle").toggle();
 | 
					        $(".hide-toggle").toggle();
 | 
				
			||||||
@@ -87,15 +101,20 @@ function registerEntrypoints() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    utils.bindShortcut('ctrl+r', utils.reloadApp);
 | 
					    utils.bindShortcut('ctrl+r', utils.reloadApp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $(document).bind('keydown', 'ctrl+shift+i', () => {
 | 
					    $("#open-dev-tools-button").toggle(utils.isElectron());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (utils.isElectron()) {
 | 
					    if (utils.isElectron()) {
 | 
				
			||||||
 | 
					        const openDevTools = () => {
 | 
				
			||||||
            require('electron').remote.getCurrentWindow().toggleDevTools();
 | 
					            require('electron').remote.getCurrentWindow().toggleDevTools();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        };
 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $(document).bind('keydown', 'ctrl+f', () => {
 | 
					        utils.bindShortcut('ctrl+shift+i', openDevTools);
 | 
				
			||||||
 | 
					        $("#open-dev-tools-button").click(openDevTools);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function openInPageSearch() {
 | 
				
			||||||
        if (utils.isElectron()) {
 | 
					        if (utils.isElectron()) {
 | 
				
			||||||
            const $searchWindowWebview = $(".electron-in-page-search-window");
 | 
					            const $searchWindowWebview = $(".electron-in-page-search-window");
 | 
				
			||||||
            $searchWindowWebview.show();
 | 
					            $searchWindowWebview.show();
 | 
				
			||||||
@@ -113,7 +132,9 @@ function registerEntrypoints() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    utils.bindShortcut('ctrl+f', openInPageSearch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // FIXME: do we really need these at this point?
 | 
					    // FIXME: do we really need these at this point?
 | 
				
			||||||
    utils.bindShortcut("ctrl+shift+up", () => {
 | 
					    utils.bindShortcut("ctrl+shift+up", () => {
 | 
				
			||||||
@@ -133,13 +154,11 @@ function registerEntrypoints() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (utils.isElectron()) {
 | 
					    if (utils.isElectron()) {
 | 
				
			||||||
        $(document).bind('keydown', 'ctrl+-', zoomService.decreaseZoomFactor);
 | 
					        utils.bindShortcut('ctrl+-', zoomService.decreaseZoomFactor);
 | 
				
			||||||
        $(document).bind('keydown', 'ctrl+=', zoomService.increaseZoomFactor);
 | 
					        utils.bindShortcut('ctrl+=', zoomService.increaseZoomFactor);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $("#note-title").bind('keydown', 'return', () => $("#note-detail-text").focus());
 | 
					    $("#note-title").bind('keydown', 'return', () => $("#note-detail-text").focus());
 | 
				
			||||||
 | 
					 | 
				
			||||||
    $("#upload-file-button").click(fileService.uploadFile);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,50 +0,0 @@
 | 
				
			|||||||
import treeService from './tree.js';
 | 
					 | 
				
			||||||
import protectedSessionHolder from './protected_session_holder.js';
 | 
					 | 
				
			||||||
import utils from './utils.js';
 | 
					 | 
				
			||||||
import server from './server.js';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function exportBranch(branchId, type, format) {
 | 
					 | 
				
			||||||
    const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}?protectedSessionId=` + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    console.log(url);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    utils.download(url);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let importNoteId;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function importIntoNote(noteId) {
 | 
					 | 
				
			||||||
    importNoteId = noteId;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $("#import-upload").trigger('click');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$("#import-upload").change(async function() {
 | 
					 | 
				
			||||||
    const formData = new FormData();
 | 
					 | 
				
			||||||
    formData.append('upload', this.files[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await $.ajax({
 | 
					 | 
				
			||||||
        url: baseApiUrl + 'notes/' + importNoteId + '/import',
 | 
					 | 
				
			||||||
        headers: server.getHeaders(),
 | 
					 | 
				
			||||||
        data: formData,
 | 
					 | 
				
			||||||
        dataType: 'json',
 | 
					 | 
				
			||||||
        type: 'POST',
 | 
					 | 
				
			||||||
        contentType: false, // NEEDED, DON'T REMOVE THIS
 | 
					 | 
				
			||||||
        processData: false, // NEEDED, DON'T REMOVE THIS
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
        .fail((xhr, status, error) => alert('Import error: ' + xhr.responseText))
 | 
					 | 
				
			||||||
        .done(async note => {
 | 
					 | 
				
			||||||
            await treeService.reload();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (note) {
 | 
					 | 
				
			||||||
                const node = await treeService.activateNote(note.noteId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                node.setExpanded(true);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    exportBranch,
 | 
					 | 
				
			||||||
    importIntoNote
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@@ -1,29 +0,0 @@
 | 
				
			|||||||
import noteDetailService from "./note_detail.js";
 | 
					 | 
				
			||||||
import treeService from "./tree.js";
 | 
					 | 
				
			||||||
import server from "./server.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function uploadFile() {
 | 
					 | 
				
			||||||
    $("#file-upload").trigger('click');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$("#file-upload").change(async function() {
 | 
					 | 
				
			||||||
    const formData = new FormData();
 | 
					 | 
				
			||||||
    formData.append('upload', this.files[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const resp = await $.ajax({
 | 
					 | 
				
			||||||
        url: baseApiUrl + 'notes/' + noteDetailService.getCurrentNoteId() + '/upload',
 | 
					 | 
				
			||||||
        headers: server.getHeaders(),
 | 
					 | 
				
			||||||
        data: formData,
 | 
					 | 
				
			||||||
        type: 'POST',
 | 
					 | 
				
			||||||
        contentType: false, // NEEDED, DON'T OMIT THIS
 | 
					 | 
				
			||||||
        processData: false, // NEEDED, DON'T OMIT THIS
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await treeService.reload();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await treeService.activateNote(resp.noteId);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    uploadFile
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -6,6 +6,8 @@ import linkService from './link.js';
 | 
				
			|||||||
import treeCache from './tree_cache.js';
 | 
					import treeCache from './tree_cache.js';
 | 
				
			||||||
import noteDetailService from './note_detail.js';
 | 
					import noteDetailService from './note_detail.js';
 | 
				
			||||||
import noteTypeService from './note_type.js';
 | 
					import noteTypeService from './note_type.js';
 | 
				
			||||||
 | 
					import noteTooltipService from './note_tooltip.js';
 | 
				
			||||||
 | 
					import protectedSessionService from'./protected_session.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This is the main frontend API interface for scripts. It's published in the local "api" object.
 | 
					 * This is the main frontend API interface for scripts. It's published in the local "api" object.
 | 
				
			||||||
@@ -41,7 +43,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
 | 
				
			|||||||
    this.activateNewNote = async notePath => {
 | 
					    this.activateNewNote = async notePath => {
 | 
				
			||||||
        await treeService.reload();
 | 
					        await treeService.reload();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await treeService.activateNote(notePath, true);
 | 
					        await treeService.activateNote(notePath, noteDetailService.focusAndSelectTitle);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -202,6 +204,19 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    this.getCurrentNoteContent = noteDetailService.getCurrentNoteContent;
 | 
					    this.getCurrentNoteContent = noteDetailService.getCurrentNoteContent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * This method checks whether user navigated away from the note from which the scripts has been started.
 | 
				
			||||||
 | 
					     * This is necessary because script execution is async and by the time it is finished, the user might have
 | 
				
			||||||
 | 
					     * already navigated away from this page - the end result would be that script might return data for the wrong
 | 
				
			||||||
 | 
					     * note.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     * @return {boolean} returns true if the original note is still loaded, false if user switched to another
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.isNoteStillLoaded = () => {
 | 
				
			||||||
 | 
					        return this.originEntity.noteId === noteDetailService.getCurrentNoteId();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @method
 | 
					     * @method
 | 
				
			||||||
     * @param {function} func - callback called on note change as user is typing (not necessarily tied to save event)
 | 
					     * @param {function} func - callback called on note change as user is typing (not necessarily tied to save event)
 | 
				
			||||||
@@ -225,6 +240,17 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
 | 
				
			|||||||
     * @param {array} types - list of mime types to be used
 | 
					     * @param {array} types - list of mime types to be used
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    this.setCodeMimeTypes = noteTypeService.setCodeMimeTypes;
 | 
					    this.setCodeMimeTypes = noteTypeService.setCodeMimeTypes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     * @param {object} $el - jquery object on which to setup the tooltip
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.setupElementTooltip = noteTooltipService.setupElementTooltip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @method
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.protectCurrentNote = protectedSessionService.protectNoteAndSendToServer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default FrontendScriptApi;
 | 
					export default FrontendScriptApi;
 | 
				
			||||||
							
								
								
									
										33
									
								
								src/public/javascripts/services/hoisted_note.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/public/javascripts/services/hoisted_note.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					import optionsInit from './options_init.js';
 | 
				
			||||||
 | 
					import server from "./server.js";
 | 
				
			||||||
 | 
					import tree from "./tree.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let hoistedNoteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					optionsInit.optionsReady.then(options => {
 | 
				
			||||||
 | 
					    hoistedNoteId = options['hoistedNoteId'];
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function getHoistedNoteId() {
 | 
				
			||||||
 | 
					    await optionsInit.optionsReady;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return hoistedNoteId;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function setHoistedNoteId(noteId) {
 | 
				
			||||||
 | 
					    hoistedNoteId = noteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await server.put('options/hoistedNoteId/' + noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await tree.reload();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function unhoist() {
 | 
				
			||||||
 | 
					    await setHoistedNoteId('root');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    getHoistedNoteId,
 | 
				
			||||||
 | 
					    setHoistedNoteId,
 | 
				
			||||||
 | 
					    unhoist
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					import cssLoader from './css_loader.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const CKEDITOR = {"js": ["libraries/ckeditor/ckeditor.js"]};
 | 
					const CKEDITOR = {"js": ["libraries/ckeditor/ckeditor.js"]};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const CODE_MIRROR = {
 | 
					const CODE_MIRROR = {
 | 
				
			||||||
@@ -34,7 +36,7 @@ const RELATION_MAP = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
async function requireLibrary(library) {
 | 
					async function requireLibrary(library) {
 | 
				
			||||||
    if (library.css) {
 | 
					    if (library.css) {
 | 
				
			||||||
        library.css.map(cssUrl => requireCss(cssUrl));
 | 
					        library.css.map(cssUrl => cssLoader.requireCss(cssUrl));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (library.js) {
 | 
					    if (library.js) {
 | 
				
			||||||
@@ -59,16 +61,6 @@ async function requireScript(url) {
 | 
				
			|||||||
    await loadedScriptPromises[url];
 | 
					    await loadedScriptPromises[url];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function requireCss(url) {
 | 
					 | 
				
			||||||
    const css = Array
 | 
					 | 
				
			||||||
        .from(document.querySelectorAll('link'))
 | 
					 | 
				
			||||||
        .map(scr => scr.href);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!css.includes(url)) {
 | 
					 | 
				
			||||||
        $('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    requireLibrary,
 | 
					    requireLibrary,
 | 
				
			||||||
    CKEDITOR,
 | 
					    CKEDITOR,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,7 +88,8 @@ function addTextToEditor(text) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ko.bindingHandlers.noteLink = {
 | 
					function init() {
 | 
				
			||||||
 | 
					    ko.bindingHandlers.noteLink = {
 | 
				
			||||||
        init: async function(element, valueAccessor, allBindings, viewModel, bindingContext) {
 | 
					        init: async function(element, valueAccessor, allBindings, viewModel, bindingContext) {
 | 
				
			||||||
            const noteId = ko.unwrap(valueAccessor());
 | 
					            const noteId = ko.unwrap(valueAccessor());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,13 +99,15 @@ ko.bindingHandlers.noteLink = {
 | 
				
			|||||||
                $(element).append(link);
 | 
					                $(element).append(link);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
};
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// when click on link popup, in case of internal link, just go the the referenced note instead of default behavior
 | 
					// when click on link popup, in case of internal link, just go the the referenced note instead of default behavior
 | 
				
			||||||
// of opening the link in new window/tab
 | 
					// of opening the link in new window/tab
 | 
				
			||||||
$(document).on('click', "a[data-action='note']", goToLink);
 | 
					$(document).on('click', "a[data-action='note']", goToLink);
 | 
				
			||||||
$(document).on('click', 'div.popover-content a, div.ui-tooltip-content a', goToLink);
 | 
					$(document).on('click', 'div.popover-content a, div.ui-tooltip-content a', goToLink);
 | 
				
			||||||
$(document).on('dblclick', '#note-detail-text a', goToLink);
 | 
					$(document).on('dblclick', '#note-detail-text a', goToLink);
 | 
				
			||||||
 | 
					$(document).on('click', '#note-detail-text.ck-read-only a', goToLink);
 | 
				
			||||||
$(document).on('click', 'span.ck-button__label', e => {
 | 
					$(document).on('click', 'span.ck-button__label', e => {
 | 
				
			||||||
    // this is a link preview dialog from CKEditor link editing
 | 
					    // this is a link preview dialog from CKEditor link editing
 | 
				
			||||||
    // for some reason clicked element is span
 | 
					    // for some reason clicked element is span
 | 
				
			||||||
@@ -124,5 +127,6 @@ export default {
 | 
				
			|||||||
    getNotePathFromUrl,
 | 
					    getNotePathFromUrl,
 | 
				
			||||||
    createNoteLink,
 | 
					    createNoteLink,
 | 
				
			||||||
    addLinkToEditor,
 | 
					    addLinkToEditor,
 | 
				
			||||||
    addTextToEditor
 | 
					    addTextToEditor,
 | 
				
			||||||
 | 
					    init
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
							
								
								
									
										25
									
								
								src/public/javascripts/services/mac_init.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/public/javascripts/services/mac_init.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Mac specific initialization
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import utils from "./utils.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function init() {
 | 
				
			||||||
 | 
					    if (utils.isElectron() && utils.isMac()) {
 | 
				
			||||||
 | 
					        utils.bindShortcut('meta+c', () => exec("copy"));
 | 
				
			||||||
 | 
					        utils.bindShortcut('meta+v', () => exec('paste'));
 | 
				
			||||||
 | 
					        utils.bindShortcut('meta+x', () => exec('cut'));
 | 
				
			||||||
 | 
					        utils.bindShortcut('meta+a', () => exec('selectAll'));
 | 
				
			||||||
 | 
					        utils.bindShortcut('meta+z', () => exec('undo'));
 | 
				
			||||||
 | 
					        utils.bindShortcut('meta+y', () => exec('redo'));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function exec(cmd) {
 | 
				
			||||||
 | 
					    document.execCommand(cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    init
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -38,7 +38,7 @@ function handleMessage(event) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (message.type === 'sync') {
 | 
					    if (message.type === 'sync') {
 | 
				
			||||||
        lastPingTs = new Date().getTime();
 | 
					        lastPingTs = Date.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (message.data.length > 0) {
 | 
					        if (message.data.length > 0) {
 | 
				
			||||||
            console.debug(utils.now(), "Sync data: ", message.data);
 | 
					            console.debug(utils.now(), "Sync data: ", message.data);
 | 
				
			||||||
@@ -81,10 +81,10 @@ setTimeout(() => {
 | 
				
			|||||||
    ws = connectWebSocket();
 | 
					    ws = connectWebSocket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    lastSyncId = glob.maxSyncIdAtLoad;
 | 
					    lastSyncId = glob.maxSyncIdAtLoad;
 | 
				
			||||||
    lastPingTs = new Date().getTime();
 | 
					    lastPingTs = Date.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setInterval(async () => {
 | 
					    setInterval(async () => {
 | 
				
			||||||
        if (new Date().getTime() - lastPingTs > 30000) {
 | 
					        if (Date.now() - lastPingTs > 30000) {
 | 
				
			||||||
            console.log("Lost connection to server");
 | 
					            console.log("Lost connection to server");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ function clearText($el) {
 | 
				
			|||||||
function showRecentNotes($el) {
 | 
					function showRecentNotes($el) {
 | 
				
			||||||
    $el.setSelectedPath("");
 | 
					    $el.setSelectedPath("");
 | 
				
			||||||
    $el.autocomplete("val", "");
 | 
					    $el.autocomplete("val", "");
 | 
				
			||||||
    $el.autocomplete("open");
 | 
					    $el.focus();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function initNoteAutocomplete($el, options) {
 | 
					function initNoteAutocomplete($el, options) {
 | 
				
			||||||
@@ -61,7 +61,13 @@ function initNoteAutocomplete($el, options) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $clearTextButton.click(() => clearText($el));
 | 
					        $clearTextButton.click(() => clearText($el));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $showRecentNotesButton.click(() => showRecentNotes($el));
 | 
					        $showRecentNotesButton.click(e => {
 | 
				
			||||||
 | 
					            showRecentNotes($el);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // this will cause the click not give focus to the "show recent notes" button
 | 
				
			||||||
 | 
					            // this is important because otherwise input will lose focus immediatelly and not show the results
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $goToSelectedNoteButton.click(() => {
 | 
					        $goToSelectedNoteButton.click(() => {
 | 
				
			||||||
            if ($el.hasClass("disabled")) {
 | 
					            if ($el.hasClass("disabled")) {
 | 
				
			||||||
@@ -86,7 +92,9 @@ function initNoteAutocomplete($el, options) {
 | 
				
			|||||||
                    suggestion: function(suggestion) {
 | 
					                    suggestion: function(suggestion) {
 | 
				
			||||||
                        return suggestion.highlighted;
 | 
					                        return suggestion.highlighted;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                },
 | 
				
			||||||
 | 
					                // we can't cache identical searches because notes can be created / renamed, new recent notes can be added
 | 
				
			||||||
 | 
					                cache: false
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,16 +109,16 @@ function initNoteAutocomplete($el, options) {
 | 
				
			|||||||
    return $el;
 | 
					    return $el;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$.fn.getSelectedPath = function() {
 | 
					function init() {
 | 
				
			||||||
 | 
					    $.fn.getSelectedPath = function () {
 | 
				
			||||||
        if (!$(this).val().trim()) {
 | 
					        if (!$(this).val().trim()) {
 | 
				
			||||||
            return "";
 | 
					            return "";
 | 
				
			||||||
    }
 | 
					        } else {
 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
            return $(this).attr(SELECTED_PATH_KEY);
 | 
					            return $(this).attr(SELECTED_PATH_KEY);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
};
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$.fn.setSelectedPath = function(path) {
 | 
					    $.fn.setSelectedPath = function (path) {
 | 
				
			||||||
        path = path || "";
 | 
					        path = path || "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $(this).attr(SELECTED_PATH_KEY, path);
 | 
					        $(this).attr(SELECTED_PATH_KEY, path);
 | 
				
			||||||
@@ -120,21 +128,23 @@ $.fn.setSelectedPath = function(path) {
 | 
				
			|||||||
            .find(".go-to-selected-note-button")
 | 
					            .find(".go-to-selected-note-button")
 | 
				
			||||||
            .toggleClass("disabled", !path.trim())
 | 
					            .toggleClass("disabled", !path.trim())
 | 
				
			||||||
            .attr(SELECTED_PATH_KEY, path); // we also set attr here so tooltip can be displayed
 | 
					            .attr(SELECTED_PATH_KEY, path); // we also set attr here so tooltip can be displayed
 | 
				
			||||||
};
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ko.bindingHandlers.noteAutocomplete = {
 | 
					    ko.bindingHandlers.noteAutocomplete = {
 | 
				
			||||||
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
 | 
					        init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
 | 
				
			||||||
            initNoteAutocomplete($(element));
 | 
					            initNoteAutocomplete($(element));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $(element).setSelectedPath(bindingContext.$data.selectedPath);
 | 
					            $(element).setSelectedPath(bindingContext.$data.selectedPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $(element).on('autocomplete:selected', function(event, suggestion, dataset) {
 | 
					            $(element).on('autocomplete:selected', function (event, suggestion, dataset) {
 | 
				
			||||||
                bindingContext.$data.selectedPath = $(element).val().trim() ? suggestion.path : '';
 | 
					                bindingContext.$data.selectedPath = $(element).val().trim() ? suggestion.path : '';
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
};
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    initNoteAutocomplete,
 | 
					    initNoteAutocomplete,
 | 
				
			||||||
    showRecentNotes
 | 
					    showRecentNotes,
 | 
				
			||||||
 | 
					    init
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -17,6 +17,8 @@ import noteDetailRender from './note_detail_render.js';
 | 
				
			|||||||
import noteDetailRelationMap from './note_detail_relation_map.js';
 | 
					import noteDetailRelationMap from './note_detail_relation_map.js';
 | 
				
			||||||
import bundleService from "./bundle.js";
 | 
					import bundleService from "./bundle.js";
 | 
				
			||||||
import attributeService from "./attributes.js";
 | 
					import attributeService from "./attributes.js";
 | 
				
			||||||
 | 
					import utils from "./utils.js";
 | 
				
			||||||
 | 
					import importDialog from "../dialogs/import.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const $noteTitle = $("#note-title");
 | 
					const $noteTitle = $("#note-title");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,10 +27,10 @@ const $noteDetailComponents = $(".note-detail-component");
 | 
				
			|||||||
const $protectButton = $("#protect-button");
 | 
					const $protectButton = $("#protect-button");
 | 
				
			||||||
const $unprotectButton = $("#unprotect-button");
 | 
					const $unprotectButton = $("#unprotect-button");
 | 
				
			||||||
const $noteDetailWrapper = $("#note-detail-wrapper");
 | 
					const $noteDetailWrapper = $("#note-detail-wrapper");
 | 
				
			||||||
const $noteIdDisplay = $("#note-id-display");
 | 
					 | 
				
			||||||
const $childrenOverview = $("#children-overview");
 | 
					const $childrenOverview = $("#children-overview");
 | 
				
			||||||
const $scriptArea = $("#note-detail-script-area");
 | 
					const $scriptArea = $("#note-detail-script-area");
 | 
				
			||||||
const $savedIndicator = $("#saved-indicator");
 | 
					const $savedIndicator = $("#saved-indicator");
 | 
				
			||||||
 | 
					const $body = $("body");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let currentNote = null;
 | 
					let currentNote = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,6 +38,8 @@ let noteChangeDisabled = false;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let isNoteChanged = false;
 | 
					let isNoteChanged = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let detailLoadedListeners = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const components = {
 | 
					const components = {
 | 
				
			||||||
    'code': noteDetailCode,
 | 
					    'code': noteDetailCode,
 | 
				
			||||||
    'text': noteDetailText,
 | 
					    'text': noteDetailText,
 | 
				
			||||||
@@ -108,8 +112,12 @@ function onNoteChange(func) {
 | 
				
			|||||||
async function saveNote() {
 | 
					async function saveNote() {
 | 
				
			||||||
    const note = getCurrentNote();
 | 
					    const note = getCurrentNote();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    note.title = $noteTitle.val();
 | 
					    note.title = $noteTitle.val();
 | 
				
			||||||
    note.content = getCurrentNoteContent(note);
 | 
					    note.noteContent.content = getCurrentNoteContent(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // it's important to set the flag back to false immediatelly after retrieving title and content
 | 
					    // it's important to set the flag back to false immediatelly after retrieving title and content
 | 
				
			||||||
    // otherwise we might overwrite another change (especially async code)
 | 
					    // otherwise we might overwrite another change (especially async code)
 | 
				
			||||||
@@ -124,6 +132,9 @@ async function saveNote() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $savedIndicator.fadeIn();
 | 
					    $savedIndicator.fadeIn();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // run async
 | 
				
			||||||
 | 
					    bundleService.executeRelationBundles(getCurrentNote(), 'runOnNoteChange');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function saveNoteIfChanged() {
 | 
					async function saveNoteIfChanged() {
 | 
				
			||||||
@@ -135,17 +146,21 @@ async function saveNoteIfChanged() {
 | 
				
			|||||||
    $savedIndicator.fadeIn();
 | 
					    $savedIndicator.fadeIn();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setNoteBackgroundIfProtected(note) {
 | 
					function updateNoteView() {
 | 
				
			||||||
    $noteDetailWrapper.toggleClass("protected", note.isProtected);
 | 
					    $noteDetailWrapper.toggleClass("protected", currentNote.isProtected);
 | 
				
			||||||
    $protectButton.toggleClass("active", note.isProtected);
 | 
					    $protectButton.toggleClass("active", currentNote.isProtected);
 | 
				
			||||||
    $unprotectButton.toggleClass("active", !note.isProtected);
 | 
					    $protectButton.prop("disabled", currentNote.isProtected);
 | 
				
			||||||
    $unprotectButton.prop("disabled", !protectedSessionHolder.isProtectedSessionAvailable());
 | 
					    $unprotectButton.toggleClass("active", !currentNote.isProtected);
 | 
				
			||||||
}
 | 
					    $unprotectButton.prop("disabled", !currentNote.isProtected || !protectedSessionHolder.isProtectedSessionAvailable());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let isNewNoteCreated = false;
 | 
					    for (const clazz of Array.from($body[0].classList)) { // create copy to safely iterate over while removing classes
 | 
				
			||||||
 | 
					        if (clazz.startsWith("type-") || clazz.startsWith("mime-")) {
 | 
				
			||||||
 | 
					            $body.removeClass(clazz);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function newNoteCreated() {
 | 
					    $body.addClass(utils.getNoteTypeClass(currentNote.type));
 | 
				
			||||||
    isNewNoteCreated = true;
 | 
					    $body.addClass(utils.getMimeTypeClass(currentNote.mime));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function handleProtectedSession() {
 | 
					async function handleProtectedSession() {
 | 
				
			||||||
@@ -177,18 +192,16 @@ async function loadNoteDetail(noteId) {
 | 
				
			|||||||
    // only now that we're in sync with tree active node we will switch currentNote
 | 
					    // only now that we're in sync with tree active node we will switch currentNote
 | 
				
			||||||
    currentNote = loadedNote;
 | 
					    currentNote = loadedNote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // needs to happend after loading the note itself because it references current noteId
 | 
					    if (utils.isDesktop()) {
 | 
				
			||||||
 | 
					        // needs to happen after loading the note itself because it references current noteId
 | 
				
			||||||
        attributeService.refreshAttributes();
 | 
					        attributeService.refreshAttributes();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (isNewNoteCreated) {
 | 
					    else {
 | 
				
			||||||
        isNewNoteCreated = false;
 | 
					        // mobile usually doesn't need attributes so we just invalidate
 | 
				
			||||||
 | 
					        attributeService.invalidateAttributes();
 | 
				
			||||||
        $noteTitle.focus().select();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $noteIdDisplay.html(noteId);
 | 
					    updateNoteView();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    setNoteBackgroundIfProtected(currentNote);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $noteDetailWrapper.show();
 | 
					    $noteDetailWrapper.show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -197,8 +210,10 @@ async function loadNoteDetail(noteId) {
 | 
				
			|||||||
    try {
 | 
					    try {
 | 
				
			||||||
        $noteTitle.val(currentNote.title);
 | 
					        $noteTitle.val(currentNote.title);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (utils.isDesktop()) {
 | 
				
			||||||
            noteTypeService.setNoteType(currentNote.type);
 | 
					            noteTypeService.setNoteType(currentNote.type);
 | 
				
			||||||
            noteTypeService.setNoteMime(currentNote.mime);
 | 
					            noteTypeService.setNoteMime(currentNote.mime);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const componentType in components) {
 | 
					        for (const componentType in components) {
 | 
				
			||||||
            if (componentType !== currentNote.type) {
 | 
					            if (componentType !== currentNote.type) {
 | 
				
			||||||
@@ -214,6 +229,8 @@ async function loadNoteDetail(noteId) {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $noteTitle.removeAttr("readonly"); // this can be set by protected session service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await getComponent(currentNote.type).show();
 | 
					        await getComponent(currentNote.type).show();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    finally {
 | 
					    finally {
 | 
				
			||||||
@@ -223,15 +240,19 @@ async function loadNoteDetail(noteId) {
 | 
				
			|||||||
    treeService.setBranchBackgroundBasedOnProtectedStatus(noteId);
 | 
					    treeService.setBranchBackgroundBasedOnProtectedStatus(noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // after loading new note make sure editor is scrolled to the top
 | 
					    // after loading new note make sure editor is scrolled to the top
 | 
				
			||||||
    $noteDetailWrapper.scrollTop(0);
 | 
					    getComponent(currentNote.type).scrollToTop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fireDetailLoaded();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $scriptArea.empty();
 | 
					    $scriptArea.empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await bundleService.executeRelationBundles(getCurrentNote(), 'runOnNoteView');
 | 
					    await bundleService.executeRelationBundles(getCurrentNote(), 'runOnNoteView');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (utils.isDesktop()) {
 | 
				
			||||||
        await attributeService.showAttributes();
 | 
					        await attributeService.showAttributes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await showChildrenOverview();
 | 
					        await showChildrenOverview();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function showChildrenOverview() {
 | 
					async function showChildrenOverview() {
 | 
				
			||||||
@@ -257,7 +278,7 @@ async function showChildrenOverview() {
 | 
				
			|||||||
            text: await treeUtils.getNoteTitle(childBranch.noteId, childBranch.parentNoteId)
 | 
					            text: await treeUtils.getNoteTitle(childBranch.noteId, childBranch.parentNoteId)
 | 
				
			||||||
        }).attr('data-action', 'note').attr('data-note-path', notePath + '/' + childBranch.noteId);
 | 
					        }).attr('data-action', 'note').attr('data-note-path', notePath + '/' + childBranch.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const childEl = $('<div class="child-overview">').html(link);
 | 
					        const childEl = $('<div class="child-overview-item">').html(link);
 | 
				
			||||||
        $childrenOverview.append(childEl);
 | 
					        $childrenOverview.append(childEl);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -274,6 +295,34 @@ function focusOnTitle() {
 | 
				
			|||||||
    $noteTitle.focus();
 | 
					    $noteTitle.focus();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function focusAndSelectTitle() {
 | 
				
			||||||
 | 
					    $noteTitle.focus().select();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Since detail loading may take some time and user might just browse through the notes using UP-DOWN keys,
 | 
				
			||||||
 | 
					 * we intentionally decouple activation of the note in the tree and full load of the note so just avaiting on
 | 
				
			||||||
 | 
					 * fancytree's activate() won't wait for the full load.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This causes an issue where in some cases you want to do some action after detail is loaded. For this reason
 | 
				
			||||||
 | 
					 * we provide the listeners here which will be triggered after the detail is loaded and if the loaded note
 | 
				
			||||||
 | 
					 * is the one registered in the listener.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function addDetailLoadedListener(noteId, callback) {
 | 
				
			||||||
 | 
					    detailLoadedListeners.push({ noteId, callback });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function fireDetailLoaded() {
 | 
				
			||||||
 | 
					    for (const {noteId, callback} of detailLoadedListeners) {
 | 
				
			||||||
 | 
					        if (noteId === currentNote.noteId) {
 | 
				
			||||||
 | 
					            callback();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // all the listeners are one time only
 | 
				
			||||||
 | 
					    detailLoadedListeners = [];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
messagingService.subscribeToSyncMessages(syncData => {
 | 
					messagingService.subscribeToSyncMessages(syncData => {
 | 
				
			||||||
    if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === getCurrentNoteId())) {
 | 
					    if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === getCurrentNoteId())) {
 | 
				
			||||||
        infoService.showMessage('Reloading note because of background changes');
 | 
					        infoService.showMessage('Reloading note because of background changes');
 | 
				
			||||||
@@ -282,6 +331,20 @@ messagingService.subscribeToSyncMessages(syncData => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$noteDetailWrapper.on("dragover", e => e.preventDefault());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$noteDetailWrapper.on("dragleave", e => e.preventDefault());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$noteDetailWrapper.on("drop", e => {
 | 
				
			||||||
 | 
					    importDialog.uploadFiles(getCurrentNoteId(), e.originalEvent.dataTransfer.files, {
 | 
				
			||||||
 | 
					        safeImport: true,
 | 
				
			||||||
 | 
					        shrinkImages: true,
 | 
				
			||||||
 | 
					        textImportedAsText: true,
 | 
				
			||||||
 | 
					        codeImportedAsCode: true,
 | 
				
			||||||
 | 
					        explodeArchives: true
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(document).ready(() => {
 | 
					$(document).ready(() => {
 | 
				
			||||||
    $noteTitle.on('input', () => {
 | 
					    $noteTitle.on('input', () => {
 | 
				
			||||||
        noteChanged();
 | 
					        noteChanged();
 | 
				
			||||||
@@ -303,16 +366,17 @@ setInterval(saveNoteIfChanged, 3000);
 | 
				
			|||||||
export default {
 | 
					export default {
 | 
				
			||||||
    reload,
 | 
					    reload,
 | 
				
			||||||
    switchToNote,
 | 
					    switchToNote,
 | 
				
			||||||
    setNoteBackgroundIfProtected,
 | 
					    updateNoteView,
 | 
				
			||||||
    loadNote,
 | 
					    loadNote,
 | 
				
			||||||
    getCurrentNote,
 | 
					    getCurrentNote,
 | 
				
			||||||
 | 
					    getCurrentNoteContent,
 | 
				
			||||||
    getCurrentNoteType,
 | 
					    getCurrentNoteType,
 | 
				
			||||||
    getCurrentNoteId,
 | 
					    getCurrentNoteId,
 | 
				
			||||||
    newNoteCreated,
 | 
					 | 
				
			||||||
    focusOnTitle,
 | 
					    focusOnTitle,
 | 
				
			||||||
 | 
					    focusAndSelectTitle,
 | 
				
			||||||
    saveNote,
 | 
					    saveNote,
 | 
				
			||||||
    saveNoteIfChanged,
 | 
					    saveNoteIfChanged,
 | 
				
			||||||
    noteChanged,
 | 
					    noteChanged,
 | 
				
			||||||
    getCurrentNoteContent,
 | 
					    onNoteChange,
 | 
				
			||||||
    onNoteChange
 | 
					    addDetailLoadedListener
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -3,6 +3,7 @@ import bundleService from "./bundle.js";
 | 
				
			|||||||
import infoService from "./info.js";
 | 
					import infoService from "./info.js";
 | 
				
			||||||
import server from "./server.js";
 | 
					import server from "./server.js";
 | 
				
			||||||
import noteDetailService from "./note_detail.js";
 | 
					import noteDetailService from "./note_detail.js";
 | 
				
			||||||
 | 
					import utils from "./utils.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let codeEditor = null;
 | 
					let codeEditor = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,7 +49,7 @@ async function show() {
 | 
				
			|||||||
    // this needs to happen after the element is shown, otherwise the editor won't be refreshed
 | 
					    // this needs to happen after the element is shown, otherwise the editor won't be refreshed
 | 
				
			||||||
    // CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
 | 
					    // CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
 | 
				
			||||||
    // we provide fallback
 | 
					    // we provide fallback
 | 
				
			||||||
    codeEditor.setValue(currentNote.content || "");
 | 
					    codeEditor.setValue(currentNote.noteContent.content || "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const info = CodeMirror.findModeByMIME(currentNote.mime);
 | 
					    const info = CodeMirror.findModeByMIME(currentNote.mime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -94,7 +95,7 @@ function onNoteChange(func) {
 | 
				
			|||||||
    codeEditor.on('change', func);
 | 
					    codeEditor.on('change', func);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(document).bind('keydown', "ctrl+return", executeCurrentNote);
 | 
					utils.bindShortcut("ctrl+return", executeCurrentNote);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$executeScriptButton.click(executeCurrentNote);
 | 
					$executeScriptButton.click(executeCurrentNote);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -107,5 +108,6 @@ export default {
 | 
				
			|||||||
        if (codeEditor) {
 | 
					        if (codeEditor) {
 | 
				
			||||||
            codeEditor.setValue('');
 | 
					            codeEditor.setValue('');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    },
 | 
				
			||||||
 | 
					    scrollToTop: () => $component.scrollTop(0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ import noteDetailService from "./note_detail.js";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const $component = $('#note-detail-file');
 | 
					const $component = $('#note-detail-file');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const $fileNoteId = $("#file-note-id");
 | 
				
			||||||
const $fileName = $("#file-filename");
 | 
					const $fileName = $("#file-filename");
 | 
				
			||||||
const $fileType = $("#file-filetype");
 | 
					const $fileType = $("#file-filetype");
 | 
				
			||||||
const $fileSize = $("#file-filesize");
 | 
					const $fileSize = $("#file-filesize");
 | 
				
			||||||
@@ -21,12 +22,18 @@ async function show() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    $component.show();
 | 
					    $component.show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $fileNoteId.text(currentNote.noteId);
 | 
				
			||||||
    $fileName.text(attributeMap.originalFileName || "?");
 | 
					    $fileName.text(attributeMap.originalFileName || "?");
 | 
				
			||||||
    $fileSize.text((attributeMap.fileSize || "?") + " bytes");
 | 
					    $fileSize.text((attributeMap.fileSize || "?") + " bytes");
 | 
				
			||||||
    $fileType.text(currentNote.mime);
 | 
					    $fileType.text(currentNote.mime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $previewRow.toggle(!!currentNote.content);
 | 
					    if (currentNote.noteContent && currentNote.noteContent.content) {
 | 
				
			||||||
    $previewContent.text(currentNote.content);
 | 
					        $previewRow.show();
 | 
				
			||||||
 | 
					        $previewContent.text(currentNote.noteContent.content);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        $previewRow.hide();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$downloadButton.click(() => utils.download(getFileUrl()));
 | 
					$downloadButton.click(() => utils.download(getFileUrl()));
 | 
				
			||||||
@@ -53,5 +60,6 @@ export default {
 | 
				
			|||||||
    getContent: () => null,
 | 
					    getContent: () => null,
 | 
				
			||||||
    focus: () => null,
 | 
					    focus: () => null,
 | 
				
			||||||
    onNoteChange: () => null,
 | 
					    onNoteChange: () => null,
 | 
				
			||||||
    cleanup: () => null
 | 
					    cleanup: () => null,
 | 
				
			||||||
 | 
					    scrollToTop: () => null
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user