mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	Compare commits
	
		
			306 Commits
		
	
	
		
			v0.24.5
			...
			v0.30.1-be
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 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 | ||
|  | a0933c7f10 | ||
|  | 492adc2909 | ||
|  | 90a52f57b5 | ||
|  | a1469854e8 | ||
|  | e2c2993255 | ||
|  | 270d63b265 | ||
|  | 1d004be91d | ||
|  | b8a74c727e | ||
|  | c87b592277 | ||
|  | cfa926602a | ||
|  | 350cb52c07 | ||
|  | af195beb7e | ||
|  | cb00d42546 | ||
|  | ee0b0c3dfe | ||
|  | ddcb4a0e10 | ||
|  | 8cbb29ee25 | ||
|  | 9da11ac144 | ||
|  | ba7c8e77e5 | ||
|  | 4577b03fc9 | ||
|  | 72d83aa85e | ||
|  | 8ee80cb5f1 | ||
|  | 4cc08bff8b | ||
|  | 295cfb2d75 | ||
|  | 7775376b33 | ||
|  | 9f64e994dc | ||
|  | ee1e4fc710 | ||
|  | 5ea62c710d | ||
|  | aeca31d06a | ||
|  | 9cb9ea6ab5 | ||
|  | e37dd69827 | ||
|  | 6c51696d1a | ||
|  | 27787c8f37 | ||
|  | e910595545 | 
| @@ -1,4 +1,7 @@ | |||||||
| node_modules | .git | ||||||
| npm-debug.log |  | ||||||
| dist |  | ||||||
| .idea | .idea | ||||||
|  | /bin | ||||||
|  | /dist | ||||||
|  | /docs | ||||||
|  | /npm-debug.log | ||||||
|  | node_modules | ||||||
|   | |||||||
							
								
								
									
										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> | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,21 +1,28 @@ | |||||||
| FROM node:10.13.0 | FROM node:10.15.0-alpine | ||||||
|  |  | ||||||
| RUN apt-get update && apt-get install -y nasm |  | ||||||
|  |  | ||||||
| # Create app directory | # Create app directory | ||||||
| WORKDIR /usr/src/app | WORKDIR /usr/src/app | ||||||
|  |  | ||||||
| # Install app dependencies | # Copy both package.json and package-lock.json | ||||||
| # A wildcard is used to ensure both package.json AND package-lock.json are copied |  | ||||||
| # where available (npm@5+) | # where available (npm@5+) | ||||||
| COPY package*.json ./ | COPY package.json package-lock.json ./ | ||||||
|  |  | ||||||
| RUN npm install --production | # Install app dependencies | ||||||
| # If you are building your code for production | RUN set -x \ | ||||||
| # RUN npm install --only=production |     && apk add --no-cache --virtual .build-dependencies \ | ||||||
|  |         autoconf \ | ||||||
|  |         automake \ | ||||||
|  |         g++ \ | ||||||
|  |         gcc \ | ||||||
|  |         libtool \ | ||||||
|  |         make \ | ||||||
|  |         nasm \ | ||||||
|  |         libpng-dev \ | ||||||
|  |     && npm install --production \ | ||||||
|  |     && apk del .build-dependencies | ||||||
|  |  | ||||||
| # Bundle app source | # Bundle app source | ||||||
| COPY . . | COPY . . | ||||||
|  |  | ||||||
| EXPOSE 8080 | EXPOSE 8080 | ||||||
| CMD [ "node", "src/www" ] | CMD [ "node", "./src/www" ] | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,37 +1,49 @@ | |||||||
| # Trilium Notes | # Trilium Notes | ||||||
|  |  | ||||||
| [](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | [](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||||||
| Trilium Notes is a hierarchical note taking application. Picture tells a thousand words: | Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases. See [screenshots](https://github.com/zadam/trilium/wiki/Screenshot-tour) for quick overview: | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| See other pictures in [screenshot tour](https://github.com/zadam/trilium/wiki/Screenshot-tour). |  | ||||||
|  |  | ||||||
| ## Features | ## Features | ||||||
|  |  | ||||||
| * Notes can be arranged into arbitrarily deep hierarchy (tree) | * 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 have more than 1 parents - 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 | ||||||
| * Strong [note encryption](https://github.com/zadam/trilium/wiki/Protected-notes) | * Strong [note encryption](https://github.com/zadam/trilium/wiki/Protected-notes) with per-note granularity | ||||||
| * [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 ([Electron](https://electronjs.org)-based) or web application hosted on your server. | 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. | ||||||
|  |  | ||||||
| ## Documentation | ## Documentation | ||||||
|  |  | ||||||
| [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. | ||||||
|  |  | ||||||
|  | ## 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 | ||||||
| @@ -1,8 +1,5 @@ | |||||||
| #!/usr/bin/env bash | #!/usr/bin/env bash | ||||||
|  |  | ||||||
| if [[ $# -eq 0 ]] ; then | VERSION=`jq -r ".version" package.json` | ||||||
|     echo "Missing argument of new version" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| sudo docker build -t zadam/trilium:latest -t zadam/trilium:$1 . | sudo docker build -t zadam/trilium:latest -t zadam/trilium:$VERSION . | ||||||
							
								
								
									
										24
									
								
								bin/build-linux-x64.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								bin/build-linux-x64.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | BUILD_DIR=./dist/trilium-linux-x64 | ||||||
|  | rm -rf $BUILD_DIR | ||||||
|  |  | ||||||
|  | rm -r node_modules/sqlite3/lib/binding/* | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  |  | ||||||
|  | cp src/public/images/app-icons/png/128x128.png $BUILD_DIR/icon.png | ||||||
|  |  | ||||||
|  | # removing software WebGL binaries because they are pretty huge and not necessary | ||||||
|  | rm -r $BUILD_DIR/swiftshader | ||||||
|  |  | ||||||
|  | echo "Packaging linux x64 electron distribution..." | ||||||
|  | VERSION=`jq -r ".version" package.json` | ||||||
|  |  | ||||||
|  | cd dist | ||||||
|  |  | ||||||
|  | tar cJf trilium-linux-x64-${VERSION}.tar.xz trilium-linux-x64 | ||||||
							
								
								
									
										32
									
								
								bin/build-mac-x64.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								bin/build-mac-x64.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | BUILD_DIR=./dist/trilium-mac-x64 | ||||||
|  | rm -rf $BUILD_DIR | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | mv "./dist/Trilium Notes-darwin-x64" $BUILD_DIR | ||||||
|  |  | ||||||
|  | ./bin/reset-local.sh | ||||||
|  |  | ||||||
|  | echo "Zipping mac x64 electron distribution..." | ||||||
|  |  | ||||||
|  | VERSION=`jq -r ".version" package.json` | ||||||
|  |  | ||||||
|  | cd dist | ||||||
|  |  | ||||||
|  | rm trilium-mac-x64-${VERSION}.zip | ||||||
|  | zip -r9 --symlinks trilium-mac-x64-${VERSION}.zip trilium-mac-x64 | ||||||
| @@ -1,13 +1,7 @@ | |||||||
| #!/usr/bin/env bash | #!/usr/bin/env bash | ||||||
|  |  | ||||||
| if [[ $# -eq 0 ]] ; then |  | ||||||
|     echo "Missing argument of new version" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| VERSION=$1 |  | ||||||
| PKG_DIR=dist/trilium-linux-x64-server | PKG_DIR=dist/trilium-linux-x64-server | ||||||
| NODE_VERSION=10.13.0 | NODE_VERSION=10.15.0 | ||||||
|  |  | ||||||
| rm -r $PKG_DIR | rm -r $PKG_DIR | ||||||
| mkdir $PKG_DIR | mkdir $PKG_DIR | ||||||
| @@ -30,9 +24,15 @@ cp -r ../../config-sample.ini ./ | |||||||
|  |  | ||||||
| rm -r ./node_modules/electron* | rm -r ./node_modules/electron* | ||||||
|  |  | ||||||
|  | rm -r ./node_modules/sqlite3/lib/binding/* | ||||||
|  |  | ||||||
|  | cp -r ../../bin/deps/linux-x64/sqlite/node* ./node_modules/sqlite3/lib/binding/ | ||||||
|  |  | ||||||
| printf "#/bin/sh\n./node/bin/node src/www" > trilium.sh | printf "#/bin/sh\n./node/bin/node src/www" > trilium.sh | ||||||
| chmod 755 trilium.sh | chmod 755 trilium.sh | ||||||
|  |  | ||||||
| cd .. | cd .. | ||||||
|  |  | ||||||
| 7z a trilium-linux-x64-server-${VERSION}.7z trilium-linux-x64-server | VERSION=`jq -r ".version" ../package.json` | ||||||
|  |  | ||||||
|  | tar cJf trilium-linux-x64-server-${VERSION}.tar.xz trilium-linux-x64-server | ||||||
							
								
								
									
										32
									
								
								bin/build-win-x64.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								bin/build-win-x64.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | BUILD_DIR=./dist/trilium-windows-x64 | ||||||
|  | rm -rf $BUILD_DIR | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  |  | ||||||
|  | # removing software WebGL binaries because they are pretty huge and not necessary | ||||||
|  | rm -r $BUILD_DIR/swiftshader | ||||||
|  |  | ||||||
|  | ./bin/reset-local.sh | ||||||
|  |  | ||||||
|  | echo "Zipping windows x64 electron distribution..." | ||||||
|  | VERSION=`jq -r ".version" package.json` | ||||||
|  |  | ||||||
|  | cd dist | ||||||
|  |  | ||||||
|  | zip -r9 trilium-windows-x64-${VERSION}.zip trilium-windows-x64 | ||||||
							
								
								
									
										36
									
								
								bin/build.sh
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								bin/build.sh
									
									
									
									
									
								
							| @@ -8,36 +8,14 @@ echo "Deleting existing builds" | |||||||
|  |  | ||||||
| rm -r dist/* | rm -r dist/* | ||||||
|  |  | ||||||
| echo "Rebuilding binaries for linux-ia32" | bin/build-win-x64.sh | ||||||
| ./node_modules/.bin/electron-rebuild --arch=ia32 |  | ||||||
|  |  | ||||||
| ./node_modules/.bin/electron-packager . --out=dist --executable-name=trilium --platform=linux --arch=ia32 --overwrite | bin/build-mac-x64.sh | ||||||
|  |  | ||||||
| mv "./dist/Trilium Notes-linux-ia32" ./dist/trilium-linux-ia32 | # building X64 linux as the last so electron-rebuild will prepare X64 binaries for local development | ||||||
|  | bin/build-linux-x64.sh | ||||||
|  |  | ||||||
| ./node_modules/.bin/electron-packager . --out=dist --executable-name=trilium --platform=win32  --arch=x64 --overwrite --icon=src/public/images/app-icons/win/icon.ico | # this needs to be run after linux build | ||||||
|  | bin/build-debian.sh | ||||||
|  |  | ||||||
| mv "./dist/Trilium Notes-win32-x64" ./dist/trilium-win32-x64 | bin/build-server.sh | ||||||
|  |  | ||||||
| # we build x64 as second so that we keep X64 binaries in node_modules for local development and server build |  | ||||||
| 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 |  | ||||||
|  |  | ||||||
| mv "./dist/Trilium Notes-linux-x64" ./dist/trilium-linux-x64 |  | ||||||
|  |  | ||||||
| echo "Copying required windows binaries" |  | ||||||
|  |  | ||||||
| WIN_RES_DIR=./dist/trilium-win32-x64/resources/app |  | ||||||
|  |  | ||||||
| cp -r bin/deps/sqlite/* $WIN_RES_DIR/node_modules/sqlite3/lib/binding/ |  | ||||||
| cp bin/deps/image/cjpeg.exe $WIN_RES_DIR/node_modules/mozjpeg/vendor/ |  | ||||||
| cp bin/deps/image/pngquant.exe $WIN_RES_DIR/node_modules/pngquant-bin/vendor/ |  | ||||||
| cp bin/deps/image/gifsicle.exe $WIN_RES_DIR/node_modules/giflossy/vendor/ |  | ||||||
|  |  | ||||||
| echo "Cleaning up unnecessary binaries from all builds" |  | ||||||
|  |  | ||||||
| rm -r ./dist/trilium-linux-ia32/resources/app/bin/deps |  | ||||||
| rm -r ./dist/trilium-linux-x64/resources/app/bin/deps |  | ||||||
| rm -r ./dist/trilium-win32-x64/resources/app/bin/deps |  | ||||||
							
								
								
									
										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" ] | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								bin/deps/linux-x64/sqlite/electron-v4.0-linux-x64/node_sqlite3.node
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/deps/linux-x64/sqlite/electron-v4.0-linux-x64/node_sqlite3.node
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bin/deps/linux-x64/sqlite/node-v64-linux-x64/node_sqlite3.node
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/deps/linux-x64/sqlite/node-v64-linux-x64/node_sqlite3.node
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bin/deps/mac-x64/image/cjpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/deps/mac-x64/image/cjpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bin/deps/mac-x64/image/gifsicle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/deps/mac-x64/image/gifsicle
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bin/deps/mac-x64/image/pngquant
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/deps/mac-x64/image/pngquant
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										0
									
								
								bin/generate-cert.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								bin/generate-cert.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -1,14 +0,0 @@ | |||||||
| #!/usr/bin/env bash |  | ||||||
|  |  | ||||||
| VERSION=`jq -r ".version" package.json` |  | ||||||
|  |  | ||||||
| cd dist |  | ||||||
|  |  | ||||||
| echo "Packaging linux x64 electron distribution..." |  | ||||||
| 7z a trilium-linux-x64-${VERSION}.7z trilium-linux-x64 |  | ||||||
|  |  | ||||||
| echo "Packaging linux ia32 electron distribution..." |  | ||||||
| 7z a trilium-linux-ia32-${VERSION}.7z trilium-linux-ia32 |  | ||||||
|  |  | ||||||
| echo "Packaging windows x64 electron distribution..." |  | ||||||
| 7z a trilium-windows-x64-${VERSION}.7z trilium-win32-x64 |  | ||||||
| @@ -42,32 +42,37 @@ git push origin $TAG | |||||||
|  |  | ||||||
| bin/build.sh | bin/build.sh | ||||||
|  |  | ||||||
| bin/package.sh | LINUX_X64_BUILD=trilium-linux-x64-$VERSION.tar.xz | ||||||
|  | DEBIAN_X64_BUILD=trilium_$VERSION_amd64.deb | ||||||
| LINUX_X64_BUILD=trilium-linux-x64-$VERSION.7z | WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.zip | ||||||
| LINUX_IA32_BUILD=trilium-linux-ia32-$VERSION.7z | MAC_X64_BUILD=trilium-mac-x64-$VERSION.zip | ||||||
| WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.7z | SERVER_BUILD=trilium-linux-x64-server-$VERSION.tar.xz | ||||||
| SERVER_BUILD=trilium-linux-x64-server-$VERSION.7z |  | ||||||
|  |  | ||||||
| echo "Creating release in GitHub" | echo "Creating release in GitHub" | ||||||
|  |  | ||||||
|  | EXTRA= | ||||||
|  |  | ||||||
|  | if [[ $TAG == *"beta"* ]]; then | ||||||
|  |   EXTRA=--pre-release | ||||||
|  | fi | ||||||
|  |  | ||||||
| github-release release \ | github-release release \ | ||||||
|     --tag $TAG \ |     --tag $TAG \ | ||||||
|     --name "$TAG release" |     --name "$TAG release" $EXTRA | ||||||
|  |  | ||||||
| echo "Uploading linux x64 build" | echo "Uploading linux x64 build" | ||||||
|  |  | ||||||
| github-release upload \ | github-release upload \ | ||||||
|     --tag $TAG \ |     --tag $TAG \ | ||||||
|     --name "$LINUX_X64_BUILD" \ |     --name "$DEBIAN_X64_BUILD" \ | ||||||
|     --file "dist/$LINUX_X64_BUILD" |     --file "dist/$DEBIAN_X64_BUILD" | ||||||
|  |  | ||||||
| echo "Uploading linux ia32 build" | echo "Uploading debian x64 package" | ||||||
|  |  | ||||||
| github-release upload \ | github-release upload \ | ||||||
|     --tag $TAG \ |     --tag $TAG \ | ||||||
|     --name "$LINUX_IA32_BUILD" \ |     --name "$LINUX_X64_BUILD" \ | ||||||
|     --file "dist/$LINUX_IA32_BUILD" |     --file "dist/$LINUX_X64_BUILD" | ||||||
|  |  | ||||||
| echo "Uploading windows x64 build" | echo "Uploading windows x64 build" | ||||||
|  |  | ||||||
| @@ -76,9 +81,14 @@ github-release upload \ | |||||||
|     --name "$WINDOWS_X64_BUILD" \ |     --name "$WINDOWS_X64_BUILD" \ | ||||||
|     --file "dist/$WINDOWS_X64_BUILD" |     --file "dist/$WINDOWS_X64_BUILD" | ||||||
|  |  | ||||||
| echo "Packaging server version" | echo "Uploading mac x64 build" | ||||||
|  |  | ||||||
| bin/build-server.sh $VERSION | github-release upload \ | ||||||
|  |     --tag $TAG \ | ||||||
|  |     --name "$MAC_X64_BUILD" \ | ||||||
|  |     --file "dist/$MAC_X64_BUILD" | ||||||
|  |  | ||||||
|  | echo "Uploading linux x64 server build" | ||||||
|  |  | ||||||
| github-release upload \ | github-release upload \ | ||||||
|     --tag $TAG \ |     --tag $TAG \ | ||||||
|   | |||||||
							
								
								
									
										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 | ||||||
							
								
								
									
										3263
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3263
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										61
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								package.json
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | |||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "productName": "Trilium Notes", |   "productName": "Trilium Notes", | ||||||
|   "description": "Trilium Notes", |   "description": "Trilium Notes", | ||||||
|   "version": "0.24.5", |   "version": "0.30.1-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", | ||||||
|     "devtron": "1.4.0", |  | ||||||
|     "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.5.6", |     "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": { | ||||||
|     "electron": "4.0.0-beta.7", |     "devtron": "1.4.0", | ||||||
|     "electron-compile": "6.4.3", |     "electron": "4.0.3", | ||||||
|     "electron-packager": "12.2.0", |     "electron-builder": "20.38.5", | ||||||
|     "electron-rebuild": "1.8.2", |     "electron-compile": "6.4.4", | ||||||
|  |     "electron-installer-debian": "^1.1.0", | ||||||
|  |     "electron-packager": "13.0.1", | ||||||
|  |     "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); | ||||||
|   | |||||||
| @@ -105,6 +105,11 @@ class Attribute extends Entity { | |||||||
|             this.dateModified = dateUtils.nowDate(); |             this.dateModified = dateUtils.nowDate(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // cannot be static! | ||||||
|  |     updatePojo(pojo) { | ||||||
|  |         delete pojo.isOwned; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = Attribute; | module.exports = Attribute; | ||||||
| @@ -59,6 +59,11 @@ class Branch extends Entity { | |||||||
|             this.dateModified = dateUtils.nowDate(); |             this.dateModified = dateUtils.nowDate(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // cannot be static! | ||||||
|  |     updatePojo(pojo) { | ||||||
|  |         delete pojo.origParentNoteId; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = Branch; | module.exports = Branch; | ||||||
| @@ -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'); | ||||||
| @@ -19,7 +20,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 +30,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 +47,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 */ | ||||||
| @@ -75,7 +120,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 */ | ||||||
| @@ -83,6 +130,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'))) { | ||||||
| @@ -367,6 +419,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. | ||||||
|      * |      * | ||||||
| @@ -423,16 +485,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 | ||||||
|      */ |      */ | ||||||
| @@ -599,17 +651,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; | ||||||
|         } |         } | ||||||
| @@ -624,6 +665,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; | module.exports = Note; | ||||||
							
								
								
									
										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 | 
							
								
								
									
										
											BIN
										
									
								
								src/public/images/app-icons/mac/icon.icns
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/public/images/app-icons/mac/icon.icns
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										153
									
								
								src/public/javascripts/desktop.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/public/javascripts/desktop.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | |||||||
|  | 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 './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'); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | 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(); | ||||||
| @@ -67,7 +67,8 @@ function AttributesModel() { | |||||||
|             attr.labelDefinition = (attr.type === 'label-definition' && attr.value) ? attr.value : { |             attr.labelDefinition = (attr.type === 'label-definition' && attr.value) ? attr.value : { | ||||||
|                 labelType: "text", |                 labelType: "text", | ||||||
|                 multiplicityType: "singlevalue", |                 multiplicityType: "singlevalue", | ||||||
|                 isPromoted: true |                 isPromoted: true, | ||||||
|  |                 numberPrecision: 0 | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             attr.relationDefinition = (attr.type === 'relation-definition' && attr.value) ? attr.value : { |             attr.relationDefinition = (attr.type === 'relation-definition' && attr.value) ? attr.value : { | ||||||
| @@ -96,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) { | ||||||
| @@ -168,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() { | ||||||
| @@ -187,7 +190,8 @@ function AttributesModel() { | |||||||
|                 labelDefinition: { |                 labelDefinition: { | ||||||
|                     labelType: "text", |                     labelType: "text", | ||||||
|                     multiplicityType: "singlevalue", |                     multiplicityType: "singlevalue", | ||||||
|                     isPromoted: true |                     isPromoted: true, | ||||||
|  |                     numberPrecision: 0 | ||||||
|                 }, |                 }, | ||||||
|                 relationDefinition: { |                 relationDefinition: { | ||||||
|                     multiplicityType: "singlevalue", |                     multiplicityType: "singlevalue", | ||||||
|   | |||||||
| @@ -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 | ||||||
|  | } | ||||||
							
								
								
									
										112
									
								
								src/public/javascripts/dialogs/import.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/public/javascripts/dialogs/import.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  | 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 $safeImport = $("#safe-import"); | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  |     $safeImport.attr("checked", "checked"); | ||||||
|  |  | ||||||
|  |     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; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | function importIntoNote(importNoteId) { | ||||||
|  |     const formData = new FormData(); | ||||||
|  |     formData.append('upload', $fileUploadInput[0].files[0]); | ||||||
|  |  | ||||||
|  |     // 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 safeImport = $safeImport.is(":checked") ? 1 : 0; | ||||||
|  |  | ||||||
|  |     $.ajax({ | ||||||
|  |         url: baseApiUrl + 'notes/' + importNoteId + '/import/' + importId + '/safe/' + safeImport, | ||||||
|  |         headers: server.getHeaders(), | ||||||
|  |         data: formData, | ||||||
|  |         dataType: 'json', | ||||||
|  |         type: 'POST', | ||||||
|  |         contentType: false, // NEEDED, DON'T REMOVE THIS | ||||||
|  |         processData: false, // NEEDED, DON'T REMOVE THIS | ||||||
|  |     }) | ||||||
|  |         // we actually ignore the error since it can be caused by HTTP timeout and use WS messages instead. | ||||||
|  |         .fail((xhr, status, error) => {}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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); | ||||||
|  |     } | ||||||
|  |     else if (message.type === 'import-finished') { | ||||||
|  |         $dialog.modal('hide'); | ||||||
|  |  | ||||||
|  |         infoService.showMessage("Import finished successfully."); | ||||||
|  |  | ||||||
|  |         await treeService.reload(); | ||||||
|  |  | ||||||
|  |         if (message.noteId) { | ||||||
|  |             const node = await treeService.activateNote(message.noteId); | ||||||
|  |  | ||||||
|  |             node.setExpanded(true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | $fileUploadInput.change(() => { | ||||||
|  |     if ($fileUploadInput.val()) { | ||||||
|  |         $importButton.removeAttr("disabled"); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         $importButton.attr("disabled", "disabled"); | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |     showDialog | ||||||
|  | } | ||||||
| @@ -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(); | ||||||
| @@ -10,7 +10,6 @@ function initAttributeNameAutocomplete({ $el, attributeType, open }) { | |||||||
|         $el.autocomplete({ |         $el.autocomplete({ | ||||||
|             appendTo: document.querySelector('body'), |             appendTo: document.querySelector('body'), | ||||||
|             hint: false, |             hint: false, | ||||||
|             autoselect: true, |  | ||||||
|             openOnFocus: true, |             openOnFocus: true, | ||||||
|             minLength: 0, |             minLength: 0, | ||||||
|             tabAutocomplete: false |             tabAutocomplete: false | ||||||
| @@ -26,10 +25,6 @@ function initAttributeNameAutocomplete({ $el, attributeType, open }) { | |||||||
|                     return {name}; |                     return {name}; | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|                 if (result.length === 0) { |  | ||||||
|                     result.push({name: "No results"}); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 cb(result); |                 cb(result); | ||||||
|             } |             } | ||||||
|         }]); |         }]); | ||||||
| @@ -58,7 +53,6 @@ async function initLabelValueAutocomplete({ $el, open }) { | |||||||
|         $el.autocomplete({ |         $el.autocomplete({ | ||||||
|             appendTo: document.querySelector('body'), |             appendTo: document.querySelector('body'), | ||||||
|             hint: false, |             hint: false, | ||||||
|             autoselect: true, |  | ||||||
|             openOnFocus: true, |             openOnFocus: true, | ||||||
|             minLength: 0, |             minLength: 0, | ||||||
|             tabAutocomplete: false |             tabAutocomplete: false | ||||||
|   | |||||||
| @@ -3,24 +3,35 @@ import utils from "./utils.js"; | |||||||
| import messagingService from "./messaging.js"; | import messagingService from "./messaging.js"; | ||||||
| import treeUtils from "./tree_utils.js"; | import treeUtils from "./tree_utils.js"; | ||||||
| import noteAutocompleteService from "./note_autocomplete.js"; | import noteAutocompleteService from "./note_autocomplete.js"; | ||||||
| import treeService from "./tree.js"; |  | ||||||
| import linkService from "./link.js"; | import linkService from "./link.js"; | ||||||
| import infoService from "./info.js"; |  | ||||||
| import noteDetailService from "./note_detail.js"; | import noteDetailService from "./note_detail.js"; | ||||||
|  |  | ||||||
| const $attributeList = $("#attribute-list"); | const $attributeList = $("#attribute-list"); | ||||||
| const $attributeListInner = $("#attribute-list-inner"); | const $attributeListInner = $("#attribute-list-inner"); | ||||||
| const $promotedAttributesContainer = $("#note-detail-promoted-attributes"); | const $promotedAttributesContainer = $("#note-detail-promoted-attributes"); | ||||||
|  | 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; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -74,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) + " "); | ||||||
|                 } |                 } | ||||||
| @@ -121,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) | ||||||
| @@ -144,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 | ||||||
| @@ -162,6 +178,14 @@ async function createPromotedAttributeRow(definitionAttr, valueAttr) { | |||||||
|         } |         } | ||||||
|         else if (definition.labelType === 'number') { |         else if (definition.labelType === 'number') { | ||||||
|             $input.prop("type", "number"); |             $input.prop("type", "number"); | ||||||
|  |  | ||||||
|  |             let step = 1; | ||||||
|  |  | ||||||
|  |             for (let i = 0; i < (definition.numberPrecision || 0) && i < 10; i++) { | ||||||
|  |                 step /= 10; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             $input.prop("step", step); | ||||||
|         } |         } | ||||||
|         else if (definition.labelType === 'boolean') { |         else if (definition.labelType === 'boolean') { | ||||||
|             $input.prop("type", "checkbox"); |             $input.prop("type", "checkbox"); | ||||||
| @@ -268,11 +292,17 @@ async function promotedAttributeChanged(event) { | |||||||
|  |  | ||||||
|     $attr.prop("attribute-id", result.attributeId); |     $attr.prop("attribute-id", result.attributeId); | ||||||
|  |  | ||||||
|     infoService.showMessage("Attribute has been saved."); |     // animate only if it's not being animated already, this is important especially for e.g. number inputs | ||||||
|  |     // which can be changed many times in a second by clicking on higher/lower buttons. | ||||||
|  |     if ($savedIndicator.queue().length === 0) { | ||||||
|  |         $savedIndicator.fadeOut(); | ||||||
|  |         $savedIndicator.fadeIn(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     getAttributes, |     getAttributes, | ||||||
|     showAttributes, |     showAttributes, | ||||||
|     refreshAttributes |     refreshAttributes, | ||||||
|  |     invalidateAttributes | ||||||
| } | } | ||||||
							
								
								
									
										121
									
								
								src/public/javascripts/services/bootstrap.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										121
									
								
								src/public/javascripts/services/bootstrap.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,121 +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); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| $("#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 { | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user