mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	Compare commits
	
		
			45 Commits
		
	
	
		
			v0.30.1-be
			...
			v0.30.6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | efac7701eb | ||
|  | 27cee1cf33 | ||
|  | b4c6d9f800 | ||
|  | 24c8b39d8e | ||
|  | 0144dc12df | ||
|  | 65684550a8 | ||
|  | 6d09931a39 | ||
|  | 37d2a7939c | ||
|  | a432ad7483 | ||
|  | ae17e4dc60 | ||
|  | 02eddc347a | ||
|  | ee58bf3d5c | ||
|  | ecbaffa5f3 | ||
|  | fe86c09f22 | ||
|  | c8e01d6cce | ||
|  | 7c404f03db | ||
|  | ed1cf6aad5 | ||
|  | 9703fd61e2 | ||
|  | 16790e388b | ||
|  | b48474998b | ||
|  | 95d8f07458 | ||
|  | e628c30c89 | ||
|  | 52a8aae74f | ||
|  | 54b5898582 | ||
|  | 64974d75d5 | ||
|  | bd118027fb | ||
|  | 36de217835 | ||
|  | b5283d58bb | ||
|  | 8414d97ffa | ||
|  | 9f30d4e673 | ||
|  | 8e0d1fa0df | ||
|  | 5b251b9977 | ||
|  | 8b3e721028 | ||
|  | 7e2a2baa5d | ||
|  | 003eed368b | ||
|  | 4b1cf05c0e | ||
|  | d9429c4f4b | ||
|  | b7bd94b6b0 | ||
|  | 51bbc10744 | ||
|  | fb5df33ee7 | ||
|  | d8ba0ccd7d | ||
|  | 886ea6c68c | ||
|  | 936f85c09e | ||
|  | b25deea21d | ||
|  | cf5ec44303 | 
							
								
								
									
										0
									
								
								bin/deps/mac-x64/image/cjpeg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								bin/deps/mac-x64/image/cjpeg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								bin/deps/win-x64/image/cjpeg.exe
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								bin/deps/win-x64/image/cjpeg.exe
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -43,7 +43,7 @@ git push origin $TAG | ||||
| bin/build.sh | ||||
|  | ||||
| LINUX_X64_BUILD=trilium-linux-x64-$VERSION.tar.xz | ||||
| DEBIAN_X64_BUILD=trilium_$VERSION_amd64.deb | ||||
| DEBIAN_X64_BUILD=trilium_${VERSION}_amd64.deb | ||||
| WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.zip | ||||
| MAC_X64_BUILD=trilium-mac-x64-$VERSION.zip | ||||
| SERVER_BUILD=trilium-linux-x64-server-$VERSION.tar.xz | ||||
| @@ -60,14 +60,14 @@ github-release release \ | ||||
|     --tag $TAG \ | ||||
|     --name "$TAG release" $EXTRA | ||||
|  | ||||
| echo "Uploading linux x64 build" | ||||
| echo "Uploading debian x64 package" | ||||
|  | ||||
| github-release upload \ | ||||
|     --tag $TAG \ | ||||
|     --name "$DEBIAN_X64_BUILD" \ | ||||
|     --file "dist/$DEBIAN_X64_BUILD" | ||||
|  | ||||
| echo "Uploading debian x64 package" | ||||
| echo "Uploading linux x64 build" | ||||
|  | ||||
| github-release upload \ | ||||
|     --tag $TAG \ | ||||
|   | ||||
							
								
								
									
										2
									
								
								db/migrations/0126__fill_sync_for_note_contents.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								db/migrations/0126__fill_sync_for_note_contents.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| INSERT OR REPLACE INTO sync (entityName, entityId, sourceId, syncDate) | ||||
| SELECT 'note_contents', noteContentId, '', '2019-03-02T18:07:29.182Z' FROM note_contents; | ||||
| @@ -350,7 +350,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line30">line 30</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line32">line 32</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -535,7 +535,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line304">line 304</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line308">line 308</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -700,7 +700,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line173">line 173</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line177">line 177</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -876,7 +876,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line315">line 315</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line319">line 319</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -980,7 +980,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line602">line 602</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line606">line 606</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1080,7 +1080,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line630">line 630</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line634">line 634</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1184,7 +1184,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line616">line 616</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line620">line 620</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1288,7 +1288,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line80">line 80</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line82">line 82</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1388,7 +1388,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line491">line 491</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line495">line 495</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1619,7 +1619,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line514">line 514</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line518">line 518</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1815,7 +1815,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line552">line 552</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line556">line 556</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2011,7 +2011,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line561">line 561</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line565">line 565</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2111,7 +2111,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line87">line 87</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line89">line 89</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2260,7 +2260,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line402">line 402</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line406">line 406</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2425,7 +2425,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line198">line 198</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line202">line 202</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2590,7 +2590,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line190">line 190</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line194">line 194</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2743,7 +2743,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line414">line 414</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line418">line 418</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2851,7 +2851,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line577">line 577</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line581">line 581</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2955,7 +2955,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line595">line 595</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line599">line 599</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3055,7 +3055,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line63">line 63</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line65">line 65</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3155,7 +3155,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line158">line 158</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line162">line 162</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3259,7 +3259,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line642">line 642</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line646">line 646</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3412,7 +3412,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line408">line 408</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line412">line 412</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3577,7 +3577,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line214">line 214</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line218">line 218</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3742,7 +3742,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line206">line 206</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line210">line 210</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3895,7 +3895,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line426">line 426</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line430">line 430</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4051,7 +4051,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line420">line 420</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line424">line 424</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4159,7 +4159,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line568">line 568</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line572">line 572</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4259,7 +4259,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line139">line 139</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line143">line 143</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4367,7 +4367,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line586">line 586</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line590">line 590</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4467,7 +4467,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line165">line 165</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line169">line 169</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4643,7 +4643,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line295">line 295</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line299">line 299</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4747,7 +4747,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line609">line 609</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line613">line 613</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4900,7 +4900,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line390">line 390</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line394">line 394</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5053,7 +5053,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line396">line 396</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line400">line 400</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5162,7 +5162,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line222">line 222</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line226">line 226</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5244,7 +5244,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line129">line 129</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line131">line 131</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5348,7 +5348,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line121">line 121</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line123">line 123</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5452,7 +5452,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line116">line 116</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line118">line 118</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5556,7 +5556,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line111">line 111</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line113">line 113</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5660,7 +5660,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line134">line 134</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line136">line 136</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5764,7 +5764,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line227">line 227</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line231">line 231</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5991,7 +5991,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line373">line 373</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line377">line 377</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6187,7 +6187,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line477">line 477</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line481">line 481</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6383,7 +6383,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line486">line 486</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line490">line 490</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6610,7 +6610,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line347">line 347</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line351">line 351</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6710,7 +6710,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line94">line 94</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line96">line 96</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6810,7 +6810,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line106">line 106</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line108">line 108</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7006,7 +7006,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line459">line 459</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line463">line 463</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7202,7 +7202,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line468">line 468</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line472">line 472</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7460,7 +7460,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line330">line 330</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line334">line 334</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7687,7 +7687,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line440">line 440</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line444">line 444</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7914,7 +7914,7 @@ Cache is note instance scoped. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line450">line 450</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line454">line 454</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -41,6 +41,8 @@ const LABEL_DEFINITION = 'label-definition'; | ||||
| const RELATION = 'relation'; | ||||
| const RELATION_DEFINITION = 'relation-definition'; | ||||
|  | ||||
| const STRING_MIME_TYPES = ["application/x-javascript"]; | ||||
|  | ||||
| /** | ||||
|  * This represents a Note which is a central object in the Trilium Notes project. | ||||
|  * | ||||
| @@ -132,7 +134,7 @@ class Note extends Entity { | ||||
|  | ||||
|     /** @returns {Promise} */ | ||||
|     async setJsonContent(content) { | ||||
|         await this.setContent(JSON.stringify(content)); | ||||
|         await this.setContent(JSON.stringify(content, null, '\t')); | ||||
|     } | ||||
|  | ||||
|     /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */ | ||||
| @@ -160,7 +162,9 @@ class Note extends Entity { | ||||
|  | ||||
|     /** @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/'); | ||||
|         return ["text", "code", "relation-map", "search"].includes(this.type) | ||||
|             || this.mime.startsWith('text/') | ||||
|             || STRING_MIME_TYPES.includes(this.mime); | ||||
|     } | ||||
|  | ||||
|     /** @returns {string} JS script environment - either "frontend" or "backend" */ | ||||
| @@ -709,6 +713,7 @@ class Note extends Entity { | ||||
|         delete pojo.isContentAvailable; | ||||
|         delete pojo.__attributeCache; | ||||
|         delete pojo.titleCipherText; | ||||
|         delete pojo.noteContent; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1244,7 +1244,7 @@ | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="getCodeMimeTypes"><span class="type-signature"></span>getCodeMimeTypes<span class="signature">()</span><span class="type-signature"> → {array}</span></h4> | ||||
|     <h4 class="name" id="getActiveNote"><span class="type-signature"></span>getActiveNote<span class="signature">()</span><span class="type-signature"> → {<a href="NoteFull.html">NoteFull</a>}</span></h4> | ||||
|      | ||||
|  | ||||
|      | ||||
| @@ -1292,7 +1292,7 @@ | ||||
|      | ||||
|     <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#line236">line 236</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line211">line 211</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1319,7 +1319,7 @@ | ||||
|  | ||||
|          | ||||
| <div class="param-desc"> | ||||
|     list of currently used code mime types | ||||
|     active note (loaded into right pane) | ||||
| </div> | ||||
|  | ||||
|  | ||||
| @@ -1330,7 +1330,7 @@ | ||||
|     </dt> | ||||
|     <dd> | ||||
|          | ||||
| <span class="param-type">array</span> | ||||
| <span class="param-type"><a href="NoteFull.html">NoteFull</a></span> | ||||
|  | ||||
|  | ||||
|     </dd> | ||||
| @@ -1348,7 +1348,7 @@ | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="getCurrentNoteContent"><span class="type-signature"></span>getCurrentNoteContent<span class="signature">()</span><span class="type-signature"> → {string}</span></h4> | ||||
|     <h4 class="name" id="getActiveNoteContent"><span class="type-signature"></span>getActiveNoteContent<span class="signature">()</span><span class="type-signature"> → {string}</span></h4> | ||||
|      | ||||
|  | ||||
|      | ||||
| @@ -1423,7 +1423,7 @@ | ||||
|  | ||||
|          | ||||
| <div class="param-desc"> | ||||
|     content of currently loaded note in the editor (HTML, code etc.) | ||||
|     content of active note (loaded into right pane) | ||||
| </div> | ||||
|  | ||||
|  | ||||
| @@ -1452,6 +1452,110 @@ | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="getCodeMimeTypes"><span class="type-signature"></span>getCodeMimeTypes<span class="signature">()</span><span class="type-signature"> → {array}</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#line242">line 242</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
| </dl> | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| <h5>Returns:</h5> | ||||
|  | ||||
|          | ||||
| <div class="param-desc"> | ||||
|     list of currently used code mime types | ||||
| </div> | ||||
|  | ||||
|  | ||||
|  | ||||
| <dl> | ||||
|     <dt> | ||||
|         Type | ||||
|     </dt> | ||||
|     <dd> | ||||
|          | ||||
| <span class="param-type">array</span> | ||||
|  | ||||
|  | ||||
|     </dd> | ||||
| </dl> | ||||
|  | ||||
|      | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|          | ||||
|              | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="getDefaultCodeMimeTypes"><span class="type-signature"></span>getDefaultCodeMimeTypes<span class="signature">()</span><span class="type-signature"> → {array}</span></h4> | ||||
|      | ||||
|  | ||||
| @@ -1500,7 +1604,7 @@ | ||||
|      | ||||
|     <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#line230">line 230</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> | ||||
|      | ||||
|  | ||||
| @@ -1860,7 +1964,7 @@ 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> | ||||
|     <h4 class="name" id="isNoteStillActive"><span class="type-signature"></span>isNoteStillActive<span class="signature">()</span><span class="type-signature"> → {boolean}</span></h4> | ||||
|      | ||||
|  | ||||
|      | ||||
| @@ -1915,7 +2019,7 @@ note. | ||||
|      | ||||
|     <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> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line222">line 222</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2068,7 +2172,7 @@ note. | ||||
|      | ||||
|     <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#line224">line 224</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> | ||||
|      | ||||
|  | ||||
| @@ -2255,7 +2359,7 @@ note. | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="protectCurrentNote"><span class="type-signature"></span>protectCurrentNote<span class="signature">()</span><span class="type-signature"></span></h4> | ||||
|     <h4 class="name" id="protectActiveNote"><span class="type-signature"></span>protectActiveNote<span class="signature">()</span><span class="type-signature"></span></h4> | ||||
|      | ||||
|  | ||||
|      | ||||
| @@ -2303,7 +2407,7 @@ note. | ||||
|      | ||||
|     <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> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line259">line 259</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2719,7 +2823,7 @@ Internally this serializes the anonymous function into string and sends it to ba | ||||
|      | ||||
|     <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#line242">line 242</a> | ||||
|         <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> | ||||
|      | ||||
|  | ||||
| @@ -2850,7 +2954,7 @@ Internally this serializes the anonymous function into string and sends it to ba | ||||
|      | ||||
|     <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> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line254">line 254</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -228,9 +228,15 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | ||||
|  | ||||
|     /** | ||||
|      * @method | ||||
|      * @returns {string} content of currently loaded note in the editor (HTML, code etc.) | ||||
|      * @returns {string} content of active note (loaded into right pane) | ||||
|      */ | ||||
|     this.getCurrentNoteContent = noteDetailService.getCurrentNoteContent; | ||||
|     this.getActiveNoteContent = noteDetailService.getCurrentNoteContent; | ||||
|  | ||||
|     /** | ||||
|      * @method | ||||
|      * @returns {NoteFull} active note (loaded into right pane) | ||||
|      */ | ||||
|     this.getActiveNote = noteDetailService.getCurrentNote; | ||||
|  | ||||
|     /** | ||||
|      * This method checks whether user navigated away from the note from which the scripts has been started. | ||||
| @@ -241,7 +247,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | ||||
|      * @method | ||||
|      * @return {boolean} returns true if the original note is still loaded, false if user switched to another | ||||
|      */ | ||||
|     this.isNoteStillLoaded = () => { | ||||
|     this.isNoteStillActive = () => { | ||||
|         return this.originEntity.noteId === noteDetailService.getCurrentNoteId(); | ||||
|     }; | ||||
|  | ||||
| @@ -278,7 +284,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | ||||
|     /** | ||||
|      * @method | ||||
|      */ | ||||
|     this.protectCurrentNote = protectedSessionService.protectNoteAndSendToServer; | ||||
|     this.protectActiveNote = protectedSessionService.protectNoteAndSendToServer; | ||||
| } | ||||
|  | ||||
| export default FrontendScriptApi;</code></pre> | ||||
|   | ||||
							
								
								
									
										309
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										309
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "trilium", | ||||
|   "version": "0.30.0-beta", | ||||
|   "version": "0.30.5", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
| @@ -774,19 +774,19 @@ | ||||
|       "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" | ||||
|     }, | ||||
|     "asar": { | ||||
|       "version": "0.14.6", | ||||
|       "resolved": "https://registry.npmjs.org/asar/-/asar-0.14.6.tgz", | ||||
|       "integrity": "sha512-ZqybKcdO5At6y3ge2RHxVImc6Eltb2t3sxT7lk4T4zjZBSFUuIGCIZY6f41dCjlvJSizN5QPRr8YTgMhpgBjLg==", | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/asar/-/asar-1.0.0.tgz", | ||||
|       "integrity": "sha512-MBiDU5cDr9UWuY2F0zq2fZlnyRq1aOPmJGMas22Qa14K1odpRXL3xkMHPN3uw2hAK5mD89Q+/KidOUtpi4V0Cg==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "chromium-pickle-js": "^0.2.0", | ||||
|         "commander": "^2.9.0", | ||||
|         "cuint": "^0.2.1", | ||||
|         "glob": "^6.0.4", | ||||
|         "minimatch": "^3.0.3", | ||||
|         "mkdirp": "^0.5.0", | ||||
|         "mksnapshot": "^0.3.4", | ||||
|         "tmp": "0.0.28" | ||||
|         "commander": "^2.19.0", | ||||
|         "cuint": "^0.2.2", | ||||
|         "glob": "^7.1.3", | ||||
|         "minimatch": "^3.0.4", | ||||
|         "mkdirp": "^0.5.1", | ||||
|         "pify": "^4.0.1", | ||||
|         "tmp-promise": "^1.0.5" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "commander": { | ||||
| @@ -795,18 +795,11 @@ | ||||
|           "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", | ||||
|           "dev": true | ||||
|         }, | ||||
|         "glob": { | ||||
|           "version": "6.0.4", | ||||
|           "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", | ||||
|           "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "inflight": "^1.0.4", | ||||
|             "inherits": "2", | ||||
|             "minimatch": "2 || 3", | ||||
|             "once": "^1.3.0", | ||||
|             "path-is-absolute": "^1.0.0" | ||||
|           } | ||||
|         "pify": { | ||||
|           "version": "4.0.1", | ||||
|           "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", | ||||
|           "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", | ||||
|           "dev": true | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
| @@ -1053,16 +1046,6 @@ | ||||
|         "os-filter-obj": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "binary": { | ||||
|       "version": "0.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", | ||||
|       "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "buffers": "~0.1.1", | ||||
|         "chainsaw": "~0.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "bl": { | ||||
|       "version": "1.2.2", | ||||
|       "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", | ||||
| @@ -1331,12 +1314,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "buffers": { | ||||
|       "version": "0.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", | ||||
|       "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "builder-util": { | ||||
|       "version": "9.6.2", | ||||
|       "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-9.6.2.tgz", | ||||
| @@ -1568,15 +1545,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "chainsaw": { | ||||
|       "version": "0.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", | ||||
|       "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "traverse": ">=0.3.0 <0.4" | ||||
|       } | ||||
|     }, | ||||
|     "chalk": { | ||||
|       "version": "1.1.3", | ||||
|       "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", | ||||
| @@ -2307,56 +2275,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "decompress-zip": { | ||||
|       "version": "0.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.0.tgz", | ||||
|       "integrity": "sha1-rjvLfjTGWHmt/nfhnDD4ZgK0vbA=", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "binary": "^0.3.0", | ||||
|         "graceful-fs": "^4.1.3", | ||||
|         "mkpath": "^0.1.0", | ||||
|         "nopt": "^3.0.1", | ||||
|         "q": "^1.1.2", | ||||
|         "readable-stream": "^1.1.8", | ||||
|         "touch": "0.0.3" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "isarray": { | ||||
|           "version": "0.0.1", | ||||
|           "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", | ||||
|           "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", | ||||
|           "dev": true | ||||
|         }, | ||||
|         "nopt": { | ||||
|           "version": "3.0.6", | ||||
|           "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", | ||||
|           "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "abbrev": "1" | ||||
|           } | ||||
|         }, | ||||
|         "readable-stream": { | ||||
|           "version": "1.1.14", | ||||
|           "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", | ||||
|           "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "core-util-is": "~1.0.0", | ||||
|             "inherits": "~2.0.1", | ||||
|             "isarray": "0.0.1", | ||||
|             "string_decoder": "~0.10.x" | ||||
|           } | ||||
|         }, | ||||
|         "string_decoder": { | ||||
|           "version": "0.10.31", | ||||
|           "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", | ||||
|           "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", | ||||
|           "dev": true | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "deep-equal": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", | ||||
| @@ -2939,13 +2857,14 @@ | ||||
|       "integrity": "sha512-gHZtUV3t5g3UXndAOUC+QM0ZzvB43mtKvba4zig65SsOnYqu1G5SMeRq41OIKnDftZN8iXD0NgTzuK3fWh4F8g==" | ||||
|     }, | ||||
|     "electron-installer-common": { | ||||
|       "version": "0.5.0", | ||||
|       "resolved": "https://registry.npmjs.org/electron-installer-common/-/electron-installer-common-0.5.0.tgz", | ||||
|       "integrity": "sha512-BNIPjCI4LB+I0f5gK+1+NVxM9Hez8xLck48yKr6yosyze5S2p0K87QvNGZu8KBY8+X32RcHeI5Dfdyt+NK+fnw==", | ||||
|       "version": "0.6.1", | ||||
|       "resolved": "https://registry.npmjs.org/electron-installer-common/-/electron-installer-common-0.6.1.tgz", | ||||
|       "integrity": "sha512-C5lj5NJ9IlY/GtV1aegC0Tn7K0IeNFShVzlQ+jkHG7SEdiFnt+PlGx7aRBLEWOC4wc9hVgx/lvu6kM6oB4Dl9w==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "asar": "^0.14.6", | ||||
|         "asar": "^1.0.0", | ||||
|         "cross-spawn-promise": "^0.10.1", | ||||
|         "debug": "^4.1.1", | ||||
|         "fs-extra": "^7.0.1", | ||||
|         "glob": "^7.1.3", | ||||
|         "glob-promise": "^3.4.0", | ||||
| @@ -2956,20 +2875,20 @@ | ||||
|       } | ||||
|     }, | ||||
|     "electron-installer-debian": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/electron-installer-debian/-/electron-installer-debian-1.1.0.tgz", | ||||
|       "integrity": "sha512-PqWNjVBsfjHiyCYxWBB4W22wSS1DpDfwmAhRsCA2W/0NtOE2yQrnnOrIOC77TcmxY2HmsNlv+n0Aabp8O6b0SA==", | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/electron-installer-debian/-/electron-installer-debian-1.1.1.tgz", | ||||
|       "integrity": "sha512-2r27a1AhB6iCy3dmdm6aoS9Mn42UW0Y9KhCWUgf2Xd8zIB58Ew1ALTaB8xevVU0nOW5s+quq6McPS633PPHQIA==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "debug": "^4.0.1", | ||||
|         "electron-installer-common": "^0.5.0", | ||||
|         "fs-extra": "^7.0.0", | ||||
|         "get-folder-size": "^2.0.0", | ||||
|         "debug": "^4.1.1", | ||||
|         "electron-installer-common": "^0.6.1", | ||||
|         "fs-extra": "^7.0.1", | ||||
|         "get-folder-size": "^2.0.1", | ||||
|         "lodash": "^4.17.4", | ||||
|         "pify": "^4.0.0", | ||||
|         "semver": "^5.4.1", | ||||
|         "pify": "^4.0.1", | ||||
|         "semver": "^5.6.0", | ||||
|         "word-wrap": "^1.2.3", | ||||
|         "yargs": "^12.0.2" | ||||
|         "yargs": "^12.0.5" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "pify": { | ||||
| @@ -3047,12 +2966,12 @@ | ||||
|       } | ||||
|     }, | ||||
|     "electron-packager": { | ||||
|       "version": "13.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-13.0.1.tgz", | ||||
|       "integrity": "sha512-fXfldaZ1wihpPaMTSGMxvCeETJwVArlnMmKafVXLJbbZwS+WTjY4iL7ju9WMQ0LNGuiiIwSMCQFxt5iA087mqg==", | ||||
|       "version": "13.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-13.1.0.tgz", | ||||
|       "integrity": "sha512-XHoDqgG90NGBfgUJ3NcOmELAuvHucOIYzi7AhZKIC8FivRR45PDs0pXSf53OqTXXOkdL/1xSveogvJLjKJwkAQ==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "asar": "^0.14.0", | ||||
|         "asar": "^1.0.0", | ||||
|         "debug": "^4.0.1", | ||||
|         "electron-download": "^4.1.1", | ||||
|         "electron-notarize": "^0.0.5", | ||||
| @@ -3068,7 +2987,7 @@ | ||||
|         "resolve": "^1.1.6", | ||||
|         "sanitize-filename": "^1.6.0", | ||||
|         "semver": "^5.3.0", | ||||
|         "yargs-parser": "^11.0.0" | ||||
|         "yargs-parser": "^13.0.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "camelcase": { | ||||
| @@ -3084,9 +3003,9 @@ | ||||
|           "dev": true | ||||
|         }, | ||||
|         "yargs-parser": { | ||||
|           "version": "11.1.1", | ||||
|           "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", | ||||
|           "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", | ||||
|           "version": "13.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", | ||||
|           "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "camelcase": "^5.0.0", | ||||
| @@ -4961,7 +4880,7 @@ | ||||
|         }, | ||||
|         "load-json-file": { | ||||
|           "version": "2.0.0", | ||||
|           "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", | ||||
|           "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", | ||||
|           "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
| @@ -4982,7 +4901,7 @@ | ||||
|         }, | ||||
|         "pify": { | ||||
|           "version": "2.3.0", | ||||
|           "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", | ||||
|           "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", | ||||
|           "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", | ||||
|           "dev": true | ||||
|         }, | ||||
| @@ -5016,9 +4935,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "get-port": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.1.0.tgz", | ||||
|       "integrity": "sha512-4/fqAYrzrzOiqDrdeZRKXGdTGgbkfTEumGlNQPeP6Jy8w0PzN9mzeNQ3XgHaTNie8pQ3hOUkrwlZt2Fzk5H9mA==" | ||||
|       "version": "4.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", | ||||
|       "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==" | ||||
|     }, | ||||
|     "get-proxy": { | ||||
|       "version": "1.1.0", | ||||
| @@ -6656,15 +6575,6 @@ | ||||
|       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", | ||||
|       "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" | ||||
|     }, | ||||
|     "klaw": { | ||||
|       "version": "1.3.1", | ||||
|       "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", | ||||
|       "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "graceful-fs": "^4.1.9" | ||||
|       } | ||||
|     }, | ||||
|     "latest-version": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", | ||||
| @@ -7290,47 +7200,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "mkpath": { | ||||
|       "version": "0.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", | ||||
|       "integrity": "sha1-dVSm+Nhxg0zJe1RisSLEwSTW3pE=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "mksnapshot": { | ||||
|       "version": "0.3.4", | ||||
|       "resolved": "https://registry.npmjs.org/mksnapshot/-/mksnapshot-0.3.4.tgz", | ||||
|       "integrity": "sha512-FgUTiWiY+35LgL95P/MDYrBuQO5o0s3MmaWKX6ZJWoX4vMOY9vPsAv763l1OSSelL9jPsBQ/wf4bzfqTLNPSFg==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "decompress-zip": "0.3.0", | ||||
|         "fs-extra": "0.26.7", | ||||
|         "request": "2.x" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "fs-extra": { | ||||
|           "version": "0.26.7", | ||||
|           "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", | ||||
|           "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "graceful-fs": "^4.1.2", | ||||
|             "jsonfile": "^2.1.0", | ||||
|             "klaw": "^1.0.0", | ||||
|             "path-is-absolute": "^1.0.0", | ||||
|             "rimraf": "^2.2.8" | ||||
|           } | ||||
|         }, | ||||
|         "jsonfile": { | ||||
|           "version": "2.4.0", | ||||
|           "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", | ||||
|           "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "graceful-fs": "^4.1.6" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "modify-filename": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", | ||||
| @@ -9651,12 +9520,6 @@ | ||||
|       "resolved": "https://registry.npmjs.org/pupa/-/pupa-1.0.0.tgz", | ||||
|       "integrity": "sha1-mpVopa9+ZXuEYqbp1TKHQ1YM7/Y=" | ||||
|     }, | ||||
|     "q": { | ||||
|       "version": "1.5.1", | ||||
|       "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", | ||||
|       "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "qs": { | ||||
|       "version": "6.5.2", | ||||
|       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", | ||||
| @@ -11184,11 +11047,11 @@ | ||||
|       } | ||||
|     }, | ||||
|     "tar-stream": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.0.0.tgz", | ||||
|       "integrity": "sha512-n2vtsWshZOVr/SY4KtslPoUlyNh06I2SGgAOCZmquCEjlbV/LjY2CY80rDtdQRHFOYXNlgBDo6Fr3ww2CWPOtA==", | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.0.1.tgz", | ||||
|       "integrity": "sha512-I6OJF7wE62BC6zNPdHDtseK0D0187PBjbKSLYY4ffvVkBM6tyBn2O9plDvVM2229/mozfEL/X3++qSvYYQE2xw==", | ||||
|       "requires": { | ||||
|         "bl": "^2.2.0", | ||||
|         "bl": "^3.0.0", | ||||
|         "end-of-stream": "^1.4.1", | ||||
|         "fs-constants": "^1.0.0", | ||||
|         "inherits": "^2.0.3", | ||||
| @@ -11196,34 +11059,17 @@ | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "bl": { | ||||
|           "version": "2.2.0", | ||||
|           "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", | ||||
|           "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", | ||||
|           "version": "3.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", | ||||
|           "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", | ||||
|           "requires": { | ||||
|             "readable-stream": "^2.3.5", | ||||
|             "safe-buffer": "^5.1.1" | ||||
|           }, | ||||
|           "dependencies": { | ||||
|             "readable-stream": { | ||||
|               "version": "2.3.6", | ||||
|               "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", | ||||
|               "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", | ||||
|               "requires": { | ||||
|                 "core-util-is": "~1.0.0", | ||||
|                 "inherits": "~2.0.3", | ||||
|                 "isarray": "~1.0.0", | ||||
|                 "process-nextick-args": "~2.0.0", | ||||
|                 "safe-buffer": "~5.1.1", | ||||
|                 "string_decoder": "~1.1.1", | ||||
|                 "util-deprecate": "~1.0.1" | ||||
|               } | ||||
|             } | ||||
|             "readable-stream": "^3.0.1" | ||||
|           } | ||||
|         }, | ||||
|         "readable-stream": { | ||||
|           "version": "3.1.1", | ||||
|           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", | ||||
|           "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", | ||||
|           "version": "3.2.0", | ||||
|           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", | ||||
|           "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", | ||||
|           "requires": { | ||||
|             "inherits": "^2.0.3", | ||||
|             "string_decoder": "^1.1.1", | ||||
| @@ -11368,12 +11214,12 @@ | ||||
|       "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" | ||||
|     }, | ||||
|     "tmp": { | ||||
|       "version": "0.0.28", | ||||
|       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", | ||||
|       "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", | ||||
|       "version": "0.0.33", | ||||
|       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", | ||||
|       "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "os-tmpdir": "~1.0.1" | ||||
|         "os-tmpdir": "~1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "tmp-promise": { | ||||
| @@ -11384,17 +11230,6 @@ | ||||
|       "requires": { | ||||
|         "bluebird": "^3.5.0", | ||||
|         "tmp": "0.0.33" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "tmp": { | ||||
|           "version": "0.0.33", | ||||
|           "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", | ||||
|           "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "os-tmpdir": "~1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "to-absolute-glob": { | ||||
| @@ -11458,26 +11293,6 @@ | ||||
|         "repeat-string": "^1.6.1" | ||||
|       } | ||||
|     }, | ||||
|     "touch": { | ||||
|       "version": "0.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", | ||||
|       "integrity": "sha1-Ua7z1ElXHU8oel2Hyci0kYGg2x0=", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "nopt": "~1.0.10" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "nopt": { | ||||
|           "version": "1.0.10", | ||||
|           "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", | ||||
|           "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "abbrev": "1" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "tough-cookie": { | ||||
|       "version": "2.4.3", | ||||
|       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", | ||||
| @@ -11502,12 +11317,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "traverse": { | ||||
|       "version": "0.3.9", | ||||
|       "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", | ||||
|       "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "trim": { | ||||
|       "version": "0.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", | ||||
|   | ||||
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
|   "name": "trilium", | ||||
|   "productName": "Trilium Notes", | ||||
|   "description": "Trilium Notes", | ||||
|   "version": "0.30.1-beta", | ||||
|   "version": "0.30.5", | ||||
|   "license": "AGPL-3.0-only", | ||||
|   "main": "electron.js", | ||||
|   "bin": { | ||||
| @@ -37,7 +37,7 @@ | ||||
|     "express-session": "1.15.6", | ||||
|     "file-type": "10.8.0", | ||||
|     "fs-extra": "7.0.1", | ||||
|     "get-port": "4.1.0", | ||||
|     "get-port": "4.2.0", | ||||
|     "helmet": "3.15.1", | ||||
|     "html": "1.0.0", | ||||
|     "image-type": "3.0.0", | ||||
| @@ -62,7 +62,7 @@ | ||||
|     "session-file-store": "1.2.0", | ||||
|     "simple-node-logger": "18.12.22", | ||||
|     "sqlite": "3.0.2", | ||||
|     "tar-stream": "2.0.0", | ||||
|     "tar-stream": "2.0.1", | ||||
|     "turndown": "5.0.3", | ||||
|     "unescape": "1.0.1", | ||||
|     "ws": "6.1.4", | ||||
| @@ -73,8 +73,8 @@ | ||||
|     "electron": "4.0.3", | ||||
|     "electron-builder": "20.38.5", | ||||
|     "electron-compile": "6.4.4", | ||||
|     "electron-installer-debian": "^1.1.0", | ||||
|     "electron-packager": "13.0.1", | ||||
|     "electron-installer-debian": "^1.1.1", | ||||
|     "electron-packager": "13.1.0", | ||||
|     "electron-rebuild": "1.8.4", | ||||
|     "lorem-ipsum": "1.0.6", | ||||
|     "tape": "4.10.1", | ||||
|   | ||||
| @@ -13,6 +13,8 @@ const LABEL_DEFINITION = 'label-definition'; | ||||
| const RELATION = 'relation'; | ||||
| const RELATION_DEFINITION = 'relation-definition'; | ||||
|  | ||||
| const STRING_MIME_TYPES = ["application/x-javascript"]; | ||||
|  | ||||
| /** | ||||
|  * This represents a Note which is a central object in the Trilium Notes project. | ||||
|  * | ||||
| @@ -104,7 +106,7 @@ class Note extends Entity { | ||||
|  | ||||
|     /** @returns {Promise} */ | ||||
|     async setJsonContent(content) { | ||||
|         await this.setContent(JSON.stringify(content)); | ||||
|         await this.setContent(JSON.stringify(content, null, '\t')); | ||||
|     } | ||||
|  | ||||
|     /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */ | ||||
| @@ -132,7 +134,9 @@ class Note extends Entity { | ||||
|  | ||||
|     /** @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/'); | ||||
|         return ["text", "code", "relation-map", "search"].includes(this.type) | ||||
|             || this.mime.startsWith('text/') | ||||
|             || STRING_MIME_TYPES.includes(this.mime); | ||||
|     } | ||||
|  | ||||
|     /** @returns {string} JS script environment - either "frontend" or "backend" */ | ||||
| @@ -681,6 +685,7 @@ class Note extends Entity { | ||||
|         delete pojo.isContentAvailable; | ||||
|         delete pojo.__attributeCache; | ||||
|         delete pojo.titleCipherText; | ||||
|         delete pojo.noteContent; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fafafa" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shield"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg> | ||||
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-opacity="0.03" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shield"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg> | ||||
| Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 296 B | 
| @@ -8,6 +8,7 @@ import optionsDialog from './dialogs/options.js'; | ||||
| import sqlConsoleDialog from './dialogs/sql_console.js'; | ||||
| import markdownImportDialog from './dialogs/markdown_import.js'; | ||||
| import exportDialog from './dialogs/export.js'; | ||||
| import importDialog from './dialogs/import.js'; | ||||
|  | ||||
| import cloning from './services/cloning.js'; | ||||
| import contextMenu from './services/tree_context_menu.js'; | ||||
| @@ -16,7 +17,8 @@ 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 protectedSessionService from './services/protected_session.js'; | ||||
| import protectedSessionHolder from './services/protected_session_holder.js'; | ||||
| import searchNotesService from './services/search_notes.js'; | ||||
| import FrontendScriptApi from './services/frontend_script_api.js'; | ||||
| import ScriptContext from './services/script_context.js'; | ||||
| @@ -51,6 +53,8 @@ window.glob.getCurrentNote = noteDetailService.getCurrentNote; | ||||
| window.glob.requireLibrary = libraryLoader.requireLibrary; | ||||
| window.glob.ESLINT = libraryLoader.ESLINT; | ||||
|  | ||||
| protectedSessionHolder.setProtectedSessionId(null); | ||||
|  | ||||
| window.onerror = function (msg, url, lineNo, columnNo, error) { | ||||
|     const string = msg.toLowerCase(); | ||||
|  | ||||
| @@ -134,6 +138,12 @@ $("#export-note-button").click(function () { | ||||
|     exportDialog.showDialog('single'); | ||||
| }); | ||||
|  | ||||
| $('[data-toggle="tooltip"]').tooltip({ | ||||
|     html: true | ||||
| }); | ||||
|  | ||||
| $("#import-files-button").click(importDialog.showDialog); | ||||
|  | ||||
| macInit.init(); | ||||
|  | ||||
| searchNotesService.init(); // should be in front of treeService since that one manipulates address bar hash | ||||
|   | ||||
| @@ -137,6 +137,10 @@ function linkTypeChanged() { | ||||
|  | ||||
| $linkTypes.change(linkTypeChanged); | ||||
|  | ||||
| // return back focus to note text detail after quitting add link | ||||
| // the problem is that cursor position is reset | ||||
| $dialog.on("hidden.bs.modal", () => noteDetailText.focus()); | ||||
|  | ||||
| export default { | ||||
|     showDialog | ||||
| }; | ||||
| @@ -79,7 +79,7 @@ $form.submit(() => { | ||||
| 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()); | ||||
|     const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}/${version}/${exportId}`; | ||||
|  | ||||
|     utils.download(url); | ||||
| } | ||||
|   | ||||
| @@ -12,7 +12,11 @@ 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"); | ||||
| const $safeImportCheckbox = $("#safe-import-checkbox"); | ||||
| const $shrinkImagesCheckbox = $("#shrink-images-checkbox"); | ||||
| const $textImportedAsTextCheckbox = $("#text-imported-as-text-checkbox"); | ||||
| const $codeImportedAsCodeCheckbox = $("#code-imported-as-code-checkbox"); | ||||
| const $explodeArchivesCheckbox = $("#explode-archives-checkbox"); | ||||
|  | ||||
| let importId; | ||||
|  | ||||
| @@ -22,7 +26,12 @@ async function showDialog() { | ||||
|     $importProgressCountWrapper.hide(); | ||||
|     $importProgressCount.text('0'); | ||||
|     $fileUploadInput.val('').change(); // to trigger Import button disabling listener below | ||||
|     $safeImport.attr("checked", "checked"); | ||||
|  | ||||
|     $safeImportCheckbox.prop("checked", true); | ||||
|     $shrinkImagesCheckbox.prop("checked", true); | ||||
|     $textImportedAsTextCheckbox.prop("checked", true); | ||||
|     $codeImportedAsCodeCheckbox.prop("checked", true); | ||||
|     $explodeArchivesCheckbox.prop("checked", true); | ||||
|  | ||||
|     glob.activeDialog = $dialog; | ||||
|  | ||||
| @@ -43,27 +52,63 @@ $form.submit(() => { | ||||
|     return false; | ||||
| }); | ||||
|  | ||||
| function importIntoNote(importNoteId) { | ||||
|     const formData = new FormData(); | ||||
|     formData.append('upload', $fileUploadInput[0].files[0]); | ||||
| async function importIntoNote(importNoteId) { | ||||
|     const files = Array.from($fileUploadInput[0].files); // shallow copy since we're resetting the upload button below | ||||
|  | ||||
|     // we generate it here (and not on opening) for the case when you try to import multiple times from the same | ||||
|     // dialog (which shouldn't happen, but still ...) | ||||
|     importId = utils.randomString(10); | ||||
|  | ||||
|     const safeImport = $safeImport.is(":checked") ? 1 : 0; | ||||
|     const options = { | ||||
|         safeImport: boolToString($safeImportCheckbox), | ||||
|         shrinkImages: boolToString($shrinkImagesCheckbox), | ||||
|         textImportedAsText: boolToString($textImportedAsTextCheckbox), | ||||
|         codeImportedAsCode: boolToString($codeImportedAsCodeCheckbox), | ||||
|         explodeArchives: boolToString($explodeArchivesCheckbox) | ||||
|     }; | ||||
|  | ||||
|     $.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) => {}); | ||||
|     await uploadFiles(importNoteId, files, options); | ||||
|  | ||||
|     $dialog.modal('hide'); | ||||
| } | ||||
|  | ||||
| async function uploadFiles(importNoteId, files, options) { | ||||
|     let noteId; | ||||
|  | ||||
|     for (const file of files) { | ||||
|         const formData = new FormData(); | ||||
|         formData.append('upload', file); | ||||
|         formData.append('importId', importId); | ||||
|  | ||||
|         for (const key in options) { | ||||
|             formData.append(key, options[key]); | ||||
|         } | ||||
|  | ||||
|         ({noteId} = await $.ajax({ | ||||
|             url: baseApiUrl + 'notes/' + importNoteId + '/import', | ||||
|             headers: server.getHeaders(), | ||||
|             data: formData, | ||||
|             dataType: 'json', | ||||
|             type: 'POST', | ||||
|             timeout: 60 * 60 * 1000, | ||||
|             contentType: false, // NEEDED, DON'T REMOVE THIS | ||||
|             processData: false, // NEEDED, DON'T REMOVE THIS | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     infoService.showMessage("Import finished successfully."); | ||||
|  | ||||
|     await treeService.reload(); | ||||
|  | ||||
|     if (noteId) { | ||||
|         const node = await treeService.activateNote(noteId); | ||||
|  | ||||
|         node.setExpanded(true); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function boolToString($el) { | ||||
|     return $el.is(":checked") ? "true" : "false"; | ||||
| } | ||||
|  | ||||
| messagingService.subscribeToMessages(async message => { | ||||
| @@ -83,19 +128,6 @@ messagingService.subscribeToMessages(async message => { | ||||
|  | ||||
|         $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(() => { | ||||
| @@ -108,5 +140,6 @@ $fileUploadInput.change(() => { | ||||
| }); | ||||
|  | ||||
| export default { | ||||
|     showDialog | ||||
|     showDialog, | ||||
|     uploadFiles | ||||
| } | ||||
| @@ -17,7 +17,7 @@ async function executeBundle(bundle, originEntity) { | ||||
|         }.call(apiContext)); | ||||
|     } | ||||
|     catch (e) { | ||||
|         infoService.showAndLogError(`Execution of script "${bundle.note.title}" (${bundle.note.noteId}) failed with error: ${e.message}`); | ||||
|         infoService.showAndLogError(`Execution of ${bundle.noteId} failed with error: ${e.message}`); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| const $contextMenuContainer = $("#context-menu-container"); | ||||
|  | ||||
| let dateContextMenuOpenedMs = 0; | ||||
|  | ||||
| function initContextMenu(event, itemContainer, selectContextMenuItem) { | ||||
|     event.stopPropagation(); | ||||
|  | ||||
| @@ -55,6 +57,8 @@ function initContextMenu(event, itemContainer, selectContextMenuItem) { | ||||
|         top = event.pageY - 10; | ||||
|     } | ||||
|  | ||||
|     dateContextMenuOpenedMs = Date.now(); | ||||
|  | ||||
|     $contextMenuContainer.css({ | ||||
|         display: "block", | ||||
|         top: top, | ||||
| @@ -62,8 +66,18 @@ function initContextMenu(event, itemContainer, selectContextMenuItem) { | ||||
|     }).addClass("show"); | ||||
| } | ||||
|  | ||||
| $(document).click(() => $contextMenuContainer.hide()); | ||||
| $(document).click(() => hideContextMenu()); | ||||
|  | ||||
| function hideContextMenu() { | ||||
|     // this date checking comes from change in FF66 - https://github.com/zadam/trilium/issues/468 | ||||
|     // "contextmenu" event also triggers "click" event which depending on the timing can close just opened context menu | ||||
|     // we might filter out right clicks, but then it's better if even right clicks close the context menu | ||||
|     if (Date.now() - dateContextMenuOpenedMs > 300) { | ||||
|         $contextMenuContainer.hide(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     initContextMenu | ||||
|     initContextMenu, | ||||
|     hideContextMenu | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| import treeService from './tree.js'; | ||||
| import treeChangesService from './branches.js'; | ||||
| import importDialog from '../dialogs/import.js'; | ||||
|  | ||||
| const dragAndDropSetup = { | ||||
|     autoExpandMS: 600, | ||||
| @@ -32,23 +33,34 @@ const dragAndDropSetup = { | ||||
|         return true; | ||||
|     }, | ||||
|     dragEnter: (node, data) => true, // allow drop on any node | ||||
|     dragOver: (node, data) => true, | ||||
|     dragDrop: (node, data) => { | ||||
|         // This function MUST be defined to enable dropping of items on the tree. | ||||
|         // data.hitMode is 'before', 'after', or 'over'. | ||||
|         const dataTransfer = data.dataTransfer; | ||||
|  | ||||
|         const selectedNodes = treeService.getSelectedNodes(); | ||||
|  | ||||
|         if (data.hitMode === "before") { | ||||
|             treeChangesService.moveBeforeNode(selectedNodes, node); | ||||
|         } | ||||
|         else if (data.hitMode === "after") { | ||||
|             treeChangesService.moveAfterNode(selectedNodes, node); | ||||
|         } | ||||
|         else if (data.hitMode === "over") { | ||||
|             treeChangesService.moveToNode(selectedNodes, node); | ||||
|         if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { | ||||
|             importDialog.uploadFiles(node.data.noteId, dataTransfer.files, { | ||||
|                 safeImport: true, | ||||
|                 shrinkImages: true, | ||||
|                 textImportedAsText: true, | ||||
|                 codeImportedAsCode: true, | ||||
|                 explodeArchives: true | ||||
|             }); | ||||
|         } | ||||
|         else { | ||||
|             throw new Error("Unknown hitMode=" + data.hitMode); | ||||
|             // This function MUST be defined to enable dropping of items on the tree. | ||||
|             // data.hitMode is 'before', 'after', or 'over'. | ||||
|  | ||||
|             const selectedNodes = treeService.getSelectedNodes(); | ||||
|  | ||||
|             if (data.hitMode === "before") { | ||||
|                 treeChangesService.moveBeforeNode(selectedNodes, node); | ||||
|             } else if (data.hitMode === "after") { | ||||
|                 treeChangesService.moveAfterNode(selectedNodes, node); | ||||
|             } else if (data.hitMode === "over") { | ||||
|                 treeChangesService.moveToNode(selectedNodes, node); | ||||
|             } else { | ||||
|                 throw new Error("Unknown hitMode=" + data.hitMode); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import utils from "./utils.js"; | ||||
| import treeService from "./tree.js"; | ||||
| import linkService from "./link.js"; | ||||
| import fileService from "./file.js"; | ||||
| import zoomService from "./zoom.js"; | ||||
| import noteRevisionsDialog from "../dialogs/note_revisions.js"; | ||||
| import optionsDialog from "../dialogs/options.js"; | ||||
| @@ -160,8 +159,6 @@ function registerEntrypoints() { | ||||
|     } | ||||
|  | ||||
|     $("#note-title").bind('keydown', 'return', () => $("#note-detail-text").focus()); | ||||
|  | ||||
|     $("#upload-file-button").click(fileService.uploadFile); | ||||
| } | ||||
|  | ||||
| export default { | ||||
|   | ||||
| @@ -1,33 +0,0 @@ | ||||
| import noteDetailService from "./note_detail.js"; | ||||
| import treeService from "./tree.js"; | ||||
| import server from "./server.js"; | ||||
|  | ||||
| function uploadFile() { | ||||
|     $("#file-upload").trigger('click'); | ||||
| } | ||||
|  | ||||
| $("#file-upload").change(async function() { | ||||
|     const formData = new FormData(); | ||||
|     formData.append('upload', this.files[0]); | ||||
|  | ||||
|     // this is done to reset the field otherwise triggering import same file again would not work | ||||
|     // https://github.com/zadam/trilium/issues/388 | ||||
|     $("#file-upload").val(''); | ||||
|  | ||||
|     const resp = await $.ajax({ | ||||
|         url: baseApiUrl + 'notes/' + noteDetailService.getCurrentNoteId() + '/upload', | ||||
|         headers: server.getHeaders(), | ||||
|         data: formData, | ||||
|         type: 'POST', | ||||
|         contentType: false, // NEEDED, DON'T OMIT THIS | ||||
|         processData: false, // NEEDED, DON'T OMIT THIS | ||||
|     }); | ||||
|  | ||||
|     await treeService.reload(); | ||||
|  | ||||
|     await treeService.activateNote(resp.noteId); | ||||
| }); | ||||
|  | ||||
| export default { | ||||
|     uploadFile | ||||
| } | ||||
| @@ -200,9 +200,15 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | ||||
|  | ||||
|     /** | ||||
|      * @method | ||||
|      * @returns {string} content of currently loaded note in the editor (HTML, code etc.) | ||||
|      * @returns {string} content of active note (loaded into right pane) | ||||
|      */ | ||||
|     this.getCurrentNoteContent = noteDetailService.getCurrentNoteContent; | ||||
|     this.getActiveNoteContent = noteDetailService.getCurrentNoteContent; | ||||
|  | ||||
|     /** | ||||
|      * @method | ||||
|      * @returns {NoteFull} active note (loaded into right pane) | ||||
|      */ | ||||
|     this.getActiveNote = noteDetailService.getCurrentNote; | ||||
|  | ||||
|     /** | ||||
|      * This method checks whether user navigated away from the note from which the scripts has been started. | ||||
| @@ -213,7 +219,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | ||||
|      * @method | ||||
|      * @return {boolean} returns true if the original note is still loaded, false if user switched to another | ||||
|      */ | ||||
|     this.isNoteStillLoaded = () => { | ||||
|     this.isNoteStillActive = () => { | ||||
|         return this.originEntity.noteId === noteDetailService.getCurrentNoteId(); | ||||
|     }; | ||||
|  | ||||
| @@ -250,7 +256,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | ||||
|     /** | ||||
|      * @method | ||||
|      */ | ||||
|     this.protectCurrentNote = protectedSessionService.protectNoteAndSendToServer; | ||||
|     this.protectActiveNote = protectedSessionService.protectNoteAndSendToServer; | ||||
| } | ||||
|  | ||||
| export default FrontendScriptApi; | ||||
| @@ -18,6 +18,7 @@ import noteDetailRelationMap from './note_detail_relation_map.js'; | ||||
| import bundleService from "./bundle.js"; | ||||
| import attributeService from "./attributes.js"; | ||||
| import utils from "./utils.js"; | ||||
| import importDialog from "../dialogs/import.js"; | ||||
|  | ||||
| const $noteTitle = $("#note-title"); | ||||
|  | ||||
| @@ -116,7 +117,10 @@ async function saveNote() { | ||||
|     } | ||||
|  | ||||
|     note.title = $noteTitle.val(); | ||||
|     note.noteContent.content = getCurrentNoteContent(note); | ||||
|  | ||||
|     if (note.noteContent != null) { // might be null for file/image | ||||
|         note.noteContent.content = getCurrentNoteContent(note); | ||||
|     } | ||||
|  | ||||
|     // it's important to set the flag back to false immediatelly after retrieving title and content | ||||
|     // otherwise we might overwrite another change (especially async code) | ||||
| @@ -330,6 +334,20 @@ messagingService.subscribeToSyncMessages(syncData => { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| $noteDetailWrapper.on("dragover", e => e.preventDefault()); | ||||
|  | ||||
| $noteDetailWrapper.on("dragleave", e => e.preventDefault()); | ||||
|  | ||||
| $noteDetailWrapper.on("drop", e => { | ||||
|     importDialog.uploadFiles(getCurrentNoteId(), e.originalEvent.dataTransfer.files, { | ||||
|         safeImport: true, | ||||
|         shrinkImages: true, | ||||
|         textImportedAsText: true, | ||||
|         codeImportedAsCode: true, | ||||
|         explodeArchives: true | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| $(document).ready(() => { | ||||
|     $noteTitle.on('input', () => { | ||||
|         noteChanged(); | ||||
|   | ||||
| @@ -27,8 +27,13 @@ async function show() { | ||||
|     $fileSize.text((attributeMap.fileSize || "?") + " bytes"); | ||||
|     $fileType.text(currentNote.mime); | ||||
|  | ||||
|     $previewRow.toggle(!!currentNote.noteContent.content); | ||||
|     $previewContent.text(currentNote.noteContent.content); | ||||
|     if (currentNote.noteContent && currentNote.noteContent.content) { | ||||
|         $previewRow.show(); | ||||
|         $previewContent.text(currentNote.noteContent.content); | ||||
|     } | ||||
|     else { | ||||
|         $previewRow.hide(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| $downloadButton.click(() => utils.download(getFileUrl())); | ||||
| @@ -46,8 +51,7 @@ $openButton.click(() => { | ||||
|  | ||||
| function getFileUrl() { | ||||
|     // electron needs absolute URL so we extract current host, port, protocol | ||||
|     return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId() | ||||
|         + "/download?protectedSessionId=" + encodeURIComponent(protectedSessionHolder.getProtectedSessionId()); | ||||
|     return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId(); | ||||
| } | ||||
|  | ||||
| export default { | ||||
|   | ||||
| @@ -26,7 +26,7 @@ async function show() { | ||||
|     $fileSize.text((attributeMap.fileSize || "?") + " bytes"); | ||||
|     $fileType.text(currentNote.mime); | ||||
|  | ||||
|     $imageView.prop("src", `/api/images/${currentNote.noteId}/${currentNote.title}`); | ||||
|     $imageView.prop("src", `api/images/${currentNote.noteId}/${currentNote.title}`); | ||||
| } | ||||
|  | ||||
| $imageDownloadButton.click(() => utils.download(getFileUrl())); | ||||
| @@ -62,8 +62,7 @@ $copyToClipboardButton.click(() => { | ||||
|  | ||||
| function getFileUrl() { | ||||
|     // electron needs absolute URL so we extract current host, port, protocol | ||||
|     return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId() | ||||
|         + "/download?protectedSessionId=" + encodeURIComponent(protectedSessionHolder.getProtectedSessionId()); | ||||
|     return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId() + "/download"; | ||||
| } | ||||
|  | ||||
| export default { | ||||
|   | ||||
| @@ -122,7 +122,7 @@ async function renderTooltip(note, attributes) { | ||||
|     } | ||||
|     else if (note.type === 'image') { | ||||
|         content += $("<img>") | ||||
|             .prop("src", `/api/images/${note.noteId}/${note.title}`) | ||||
|             .prop("src", `api/images/${note.noteId}/${note.title}`) | ||||
|             .prop('outerHTML'); | ||||
|     } | ||||
|     // other types of notes don't have tooltip preview | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| import utils from "./utils.js"; | ||||
| import optionsInitService from './options_init.js'; | ||||
|  | ||||
| const PROTECTED_SESSION_ID_KEY = 'protectedSessionId'; | ||||
|  | ||||
| let lastProtectedSessionOperationDate = null; | ||||
| let protectedSessionTimeout = null; | ||||
| let protectedSessionId = null; | ||||
|  | ||||
| optionsInitService.optionsReady.then(options => protectedSessionTimeout = options.protectedSessionTimeout); | ||||
|  | ||||
| @@ -17,16 +18,13 @@ function setProtectedSessionTimeout(encSessTimeout) { | ||||
|     protectedSessionTimeout = encSessTimeout; | ||||
| } | ||||
|  | ||||
| function getProtectedSessionId() { | ||||
|     return protectedSessionId; | ||||
| } | ||||
|  | ||||
| function setProtectedSessionId(id) { | ||||
|     protectedSessionId = id; | ||||
|     // using session cookie so that it disappears after browser/tab is closed | ||||
|     utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, id); | ||||
| } | ||||
|  | ||||
| function resetProtectedSession() { | ||||
|     protectedSessionId = null; | ||||
|     utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, null); | ||||
|  | ||||
|     // most secure solution - guarantees nothing remained in memory | ||||
|     // since this expires because user doesn't use the app, it shouldn't be disruptive | ||||
| @@ -34,17 +32,16 @@ function resetProtectedSession() { | ||||
| } | ||||
|  | ||||
| function isProtectedSessionAvailable() { | ||||
|     return protectedSessionId !== null; | ||||
|     return !!utils.getCookie(PROTECTED_SESSION_ID_KEY); | ||||
| } | ||||
|  | ||||
| function touchProtectedSession() { | ||||
|     if (isProtectedSessionAvailable()) { | ||||
|         lastProtectedSessionOperationDate = new Date(); | ||||
|         setProtectedSessionId(utils.getCookie(PROTECTED_SESSION_ID_KEY)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     getProtectedSessionId, | ||||
|     setProtectedSessionId, | ||||
|     resetProtectedSession, | ||||
|     isProtectedSessionAvailable, | ||||
|   | ||||
| @@ -3,18 +3,10 @@ import utils from './utils.js'; | ||||
| import infoService from "./info.js"; | ||||
|  | ||||
| function getHeaders() { | ||||
|     let protectedSessionId = null; | ||||
|  | ||||
|     try { // this is because protected session might not be declared in some cases | ||||
|         protectedSessionId = protectedSessionHolder.getProtectedSessionId(); | ||||
|     } | ||||
|     catch(e) {} | ||||
|  | ||||
|     // headers need to be lowercase because node.js automatically converts them to lower case | ||||
|     // so hypothetical protectedSessionId becomes protectedsessionid on the backend | ||||
|     // also avoiding using underscores instead of dashes since nginx filters them out by default | ||||
|     return { | ||||
|         'trilium-protected-session-id': protectedSessionId, | ||||
|         'trilium-source-id': glob.sourceId | ||||
|     }; | ||||
| } | ||||
|   | ||||
| @@ -417,6 +417,9 @@ function initFancyTree(tree) { | ||||
|             const node = data.node; | ||||
|             const noteId = node.data.noteId; | ||||
|  | ||||
|             // click event won't propagate so let's close context menu manually | ||||
|             contextMenuWidget.hideContextMenu(); | ||||
|  | ||||
|             setCurrentNotePathToHash(node); | ||||
|  | ||||
|             noteDetailService.switchToNote(noteId); | ||||
|   | ||||
| @@ -164,11 +164,23 @@ function isDesktop() { | ||||
|         || (!window.device && !/Mobi/.test(navigator.userAgent)); | ||||
| } | ||||
|  | ||||
| // cookie code below works for simple use cases only - ASCII only | ||||
| // not setting path so that cookies do not leak into other websites if multiplexed with reverse proxy | ||||
|  | ||||
| function setCookie(name, value) { | ||||
|     const date = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000); | ||||
|     const expires = "; expires=" + date.toUTCString(); | ||||
|  | ||||
|     document.cookie = name + "=" + (value || "")  + expires + "; path=/"; | ||||
|     document.cookie = name + "=" + (value || "")  + expires + ";"; | ||||
| } | ||||
|  | ||||
| function setSessionCookie(name, value) { | ||||
|     document.cookie = name + "=" + (value || "") + ";"; | ||||
| } | ||||
|  | ||||
| function getCookie(name) { | ||||
|     const valueMatch = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)'); | ||||
|     return valueMatch ? valueMatch[2] : null; | ||||
| } | ||||
|  | ||||
| function getNoteTypeClass(type) { | ||||
| @@ -213,6 +225,8 @@ export default { | ||||
|     isMobile, | ||||
|     isDesktop, | ||||
|     setCookie, | ||||
|     setSessionCookie, | ||||
|     getCookie, | ||||
|     getNoteTypeClass, | ||||
|     getMimeTypeClass | ||||
| }; | ||||
| @@ -91,7 +91,7 @@ function SetupModel() { | ||||
|             } | ||||
|  | ||||
|             // not using server.js because it loads too many dependencies | ||||
|             const resp = await $.post('/api/setup/sync-from-server', { | ||||
|             const resp = await $.post('api/setup/sync-from-server', { | ||||
|                 syncServerHost: syncServerHost, | ||||
|                 syncProxy: syncProxy, | ||||
|                 username: username, | ||||
|   | ||||
							
								
								
									
										2
									
								
								src/public/libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/public/libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -108,4 +108,9 @@ body { | ||||
|  | ||||
| #note-info-table td, #note-info-table th { | ||||
|     padding: 15px; | ||||
| } | ||||
|  | ||||
| [data-toggle="tooltip"] span { | ||||
|     padding-bottom: 0; | ||||
|     border-bottom: 1px dotted; | ||||
| } | ||||
| @@ -53,6 +53,10 @@ body.theme-black { | ||||
|     --menu-background-color: #222; | ||||
| } | ||||
|  | ||||
| body.theme-black a, body.theme-black a:visited { | ||||
|     color: lightskyblue; | ||||
| } | ||||
|  | ||||
| body.theme-black .CodeMirror { | ||||
|     filter: invert(100%) hue-rotate(180deg); | ||||
| } | ||||
| @@ -80,6 +84,10 @@ body.theme-dark { | ||||
|     --menu-background-color: #222; | ||||
| } | ||||
|  | ||||
| body.theme-dark a, body.theme-dark a:visited { | ||||
|     color: lightskyblue; | ||||
| } | ||||
|  | ||||
| body.theme-dark .CodeMirror { | ||||
|     filter: invert(90%) hue-rotate(180deg); | ||||
| } | ||||
| @@ -109,6 +117,10 @@ input, select, textarea { | ||||
|     color: var(--muted-text-color) !important; | ||||
| } | ||||
|  | ||||
| table td, table th { | ||||
|     color: var(--main-text-color); | ||||
| } | ||||
|  | ||||
| button.close { | ||||
|     color: var(--main-text-color); | ||||
| } | ||||
| @@ -118,7 +130,7 @@ button.close { | ||||
| } | ||||
|  | ||||
| .nav-link.active { | ||||
|     background-color: inherit; | ||||
|     background-color: inherit !important; | ||||
|     color: var(--main-text-color) !important; | ||||
| } | ||||
|  | ||||
| @@ -679,6 +691,7 @@ table.promoted-attributes-in-tooltip td, table.promoted-attributes-in-tooltip th | ||||
|     /* height needs to stay small because tooltip has problem when it can't fit to either top or bottom of the cursor */ | ||||
|     max-height: 300px; | ||||
|     overflow: hidden; | ||||
|     font-size: var(--main-font-size); | ||||
|     color: var(--main-text-color); | ||||
|     border: 1px solid var(--main-border-color); | ||||
|     border-radius: 5px; | ||||
| @@ -867,8 +880,8 @@ div[data-notify="container"] { | ||||
| } | ||||
|  | ||||
| .ck-content .image > figcaption { | ||||
|     color: var(--main-text-color); | ||||
|     background-color: var(--accented-background-color); | ||||
|     color: var(--main-text-color) !important; | ||||
|     background-color: var(--accented-background-color) !important; | ||||
| } | ||||
|  | ||||
| #options-dialog input[type=number] { | ||||
| @@ -897,4 +910,9 @@ a.external:after, a[href^="http://"]:after, a[href^="https://"]:after { | ||||
|     font-size: smaller; | ||||
|     content: "\2197"; | ||||
|     vertical-align: top; | ||||
| } | ||||
|  | ||||
| .card { | ||||
|     background-color: inherit !important; | ||||
|     border-color: var(--main-border-color) !important; | ||||
| } | ||||
| @@ -38,7 +38,7 @@ async function uploadImage(req) { | ||||
|         return [400, "Unknown image type: " + file.mimetype]; | ||||
|     } | ||||
|  | ||||
|     const {url} = await imageService.saveImage(file.buffer, file.originalname, noteId); | ||||
|     const {url} = await imageService.saveImage(file.buffer, file.originalname, noteId, true); | ||||
|  | ||||
|     return { | ||||
|         uploaded: true, | ||||
|   | ||||
| @@ -12,9 +12,16 @@ const log = require('../../services/log'); | ||||
| const ImportContext = require('../../services/import_context'); | ||||
|  | ||||
| async function importToBranch(req) { | ||||
|     let {parentNoteId, importId, safeImport} = req.params; | ||||
|     const {parentNoteId} = req.params; | ||||
|     const {importId} = req.body; | ||||
|  | ||||
|     safeImport = safeImport !== '0'; | ||||
|     const options = { | ||||
|         safeImport: req.body.safeImport !== 'false', | ||||
|         shrinkImages: req.body.shrinkImages !== 'false', | ||||
|         textImportedAsText: req.body.textImportedAsText !== 'false', | ||||
|         codeImportedAsCode: req.body.codeImportedAsCode !== 'false', | ||||
|         explodeArchives: req.body.explodeArchives !== 'false' | ||||
|     }; | ||||
|  | ||||
|     const file = req.file; | ||||
|  | ||||
| @@ -36,21 +43,17 @@ async function importToBranch(req) { | ||||
|  | ||||
|     let note; // typically root of the import - client can show it after finishing the import | ||||
|  | ||||
|     const importContext = new ImportContext(importId, safeImport); | ||||
|     const importContext = ImportContext.getInstance(importId, options); | ||||
|  | ||||
|     try { | ||||
|         if (extension === '.tar') { | ||||
|         if (extension === '.tar' && options.explodeArchives) { | ||||
|             note = await tarImportService.importTar(importContext, file.buffer, parentNote); | ||||
|         } else if (extension === '.opml') { | ||||
|         } else if (extension === '.opml' && options.explodeArchives) { | ||||
|             note = await opmlImportService.importOpml(importContext, file.buffer, parentNote); | ||||
|         } else if (extension === '.md') { | ||||
|             note = await singleImportService.importMarkdown(importContext, file, parentNote); | ||||
|         } else if (extension === '.html' || extension === '.htm') { | ||||
|             note = await singleImportService.importHtml(importContext, file, parentNote); | ||||
|         } else if (extension === '.enex') { | ||||
|         } else if (extension === '.enex' && options.explodeArchives) { | ||||
|             note = await enexImportService.importEnex(importContext, file, parentNote); | ||||
|         } else { | ||||
|             return [400, `Unrecognized extension ${extension}, must be .tar or .opml`]; | ||||
|             note = await singleImportService.importSingleFile(importContext, file, parentNote); | ||||
|         } | ||||
|     } | ||||
|     catch (e) { | ||||
|   | ||||
| @@ -17,9 +17,13 @@ async function getRecentChanges() { | ||||
|             dateModifiedTo DESC  | ||||
|         LIMIT 1000`); | ||||
|  | ||||
|     if (!protectedSessionService.isProtectedSessionAvailable()) { | ||||
|         for (const change of recentChanges) { | ||||
|             if (change.current_isProtected) { | ||||
|     for (const change of recentChanges) { | ||||
|         if (change.current_isProtected) { | ||||
|             if (protectedSessionService.isProtectedSessionAvailable()) { | ||||
|                 change.title = protectedSessionService.decryptNoteTitle(change.noteId, change.title); | ||||
|                 change.current_title = protectedSessionService.decryptNoteTitle(change.noteId, change.current_title); | ||||
|             } | ||||
|             else { | ||||
|                 change.title = change.current_title = "[Protected]"; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -38,7 +38,7 @@ async function uploadImage(req) { | ||||
|  | ||||
|     const parentNote = await dateNoteService.getDateNote(req.headers['x-local-date']); | ||||
|  | ||||
|     const {noteId} = await imageService.saveImage(file.buffer, "Sender image", parentNote.noteId); | ||||
|     const {noteId} = await imageService.saveImage(file.buffer, "Sender image", parentNote.noteId, true); | ||||
|  | ||||
|     return { | ||||
|         noteId: noteId | ||||
|   | ||||
| @@ -129,7 +129,7 @@ function register(app) { | ||||
|     apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter); | ||||
|  | ||||
|     route(GET, '/api/notes/:branchId/export/:type/:format/:version/:exportId', [auth.checkApiAuthOrElectron], exportRoute.exportBranch); | ||||
|     route(POST, '/api/notes/:parentNoteId/import/:importId/safe/:safeImport', [auth.checkApiAuthOrElectron, uploadMiddleware], importRoute.importToBranch, apiResultHandler); | ||||
|     route(POST, '/api/notes/:parentNoteId/import', [auth.checkApiAuthOrElectron, uploadMiddleware], importRoute.importToBranch, apiResultHandler); | ||||
|  | ||||
|     route(POST, '/api/notes/:parentNoteId/upload', [auth.checkApiAuthOrElectron, uploadMiddleware], | ||||
|         filesRoute.uploadFile, apiResultHandler); | ||||
|   | ||||
| @@ -4,8 +4,8 @@ const build = require('./build'); | ||||
| const packageJson = require('../../package'); | ||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||
|  | ||||
| const APP_DB_VERSION = 125; | ||||
| const SYNC_VERSION = 5; | ||||
| const APP_DB_VERSION = 126; | ||||
| const SYNC_VERSION = 6; | ||||
|  | ||||
| module.exports = { | ||||
|     appVersion: packageJson.version, | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| module.exports = { buildDate:"2019-02-20T23:08:36+01:00", buildRevision: "3533160bef78e00cf906a436ff7b366bdec271be" }; | ||||
| module.exports = { buildDate:"2019-03-28T22:31:59+01:00", buildRevision: "27cee1cf3361d9004bc474d6118ba60a668b9b8a" }; | ||||
|   | ||||
| @@ -357,6 +357,13 @@ async function findLogicIssues() { | ||||
|  | ||||
|             logFix(`Removed link ${linkId} because target note ${targetNoteId} is also deleted.`); | ||||
|         }); | ||||
|  | ||||
|     await findIssues(` | ||||
|           SELECT noteId | ||||
|           FROM notes | ||||
|           JOIN note_contents USING(noteId) | ||||
|           WHERE notes.isDeleted = 0 AND notes.isProtected != note_contents.isProtected`, | ||||
|         ({noteId}) => `Note ${noteId} has inconsistent isProtected in notes and note_contents tables`); | ||||
| } | ||||
|  | ||||
| async function runSyncRowChecks(entityName, key) { | ||||
|   | ||||
| @@ -8,6 +8,7 @@ const messagingService = require('./messaging'); | ||||
| const ApiToken = require('../entities/api_token'); | ||||
| const Branch = require('../entities/branch'); | ||||
| const Note = require('../entities/note'); | ||||
| const NoteContent = require('../entities/note_content'); | ||||
| const Attribute = require('../entities/attribute'); | ||||
| const NoteRevision = require('../entities/note_revision'); | ||||
| const RecentNote = require('../entities/recent_note'); | ||||
| @@ -33,6 +34,7 @@ async function getHashes() { | ||||
|  | ||||
|     const hashes = { | ||||
|         notes: await getHash(Note), | ||||
|         note_contents: await getHash(NoteContent), | ||||
|         branches: await getHash(Branch), | ||||
|         note_revisions: await getHash(NoteRevision), | ||||
|         recent_notes: await getHash(RecentNote), | ||||
|   | ||||
| @@ -116,7 +116,7 @@ async function getDateNote(dateStr) { | ||||
|             dateNote = await createNote(monthNote.noteId, noteTitle); | ||||
|         } | ||||
|  | ||||
|         await attributeService.createLabel(dateNote.noteId, DATE_LABEL, dateStr); | ||||
|         await attributeService.createLabel(dateNote.noteId, DATE_LABEL, dateStr.substr(0, 10)); | ||||
|     } | ||||
|  | ||||
|     return dateNote; | ||||
|   | ||||
| @@ -54,7 +54,7 @@ async function exportToOpml(exportContext, branch, version, res) { | ||||
|     res.setHeader('Content-Type', 'text/x-opml'); | ||||
|  | ||||
|     res.write(`<?xml version="1.0" encoding="UTF-8"?> | ||||
| <opml version="1.0"> | ||||
| <opml version="${version}"> | ||||
| <head> | ||||
| <title>Trilium export</title> | ||||
| </head> | ||||
|   | ||||
| @@ -34,7 +34,7 @@ async function exportSingleNote(exportContext, branch, format, res) { | ||||
|             const turndownService = new TurndownService(); | ||||
|             payload = turndownService.turndown(noteContent.content); | ||||
|             extension = 'md'; | ||||
|             mime = 'text/markdown' | ||||
|             mime = 'text/x-markdown' | ||||
|         } | ||||
|     } | ||||
|     else if (note.type === 'code') { | ||||
|   | ||||
| @@ -12,41 +12,48 @@ const jimp = require('jimp'); | ||||
| const imageType = require('image-type'); | ||||
| const sanitizeFilename = require('sanitize-filename'); | ||||
|  | ||||
| async function saveImage(buffer, originalName, parentNoteId) { | ||||
|     const resizedImage = await resize(buffer); | ||||
|     let optimizedImage; | ||||
|     try { | ||||
|       optimizedImage = await optimize(resizedImage); | ||||
|     } catch (e) { | ||||
|       log.error(e); | ||||
|       optimizedImage = resizedImage; | ||||
|     } | ||||
| async function saveImage(buffer, originalName, parentNoteId, shrinkImageSwitch) { | ||||
|     const finalImageBuffer = shrinkImageSwitch ? await shrinkImage(buffer, originalName) : buffer; | ||||
|  | ||||
|     const imageFormat = imageType(optimizedImage); | ||||
|     const imageFormat = imageType(finalImageBuffer); | ||||
|  | ||||
|     const parentNote = await repository.getNote(parentNoteId); | ||||
|  | ||||
|     const fileNameWithoutExtension = originalName.replace(/\.[^/.]+$/, ""); | ||||
|     const fileName = sanitizeFilename(fileNameWithoutExtension + "." + imageFormat.ext); | ||||
|  | ||||
|     const {note} = await noteService.createNote(parentNoteId, fileName, optimizedImage, { | ||||
|     const {note} = await noteService.createNote(parentNoteId, fileName, finalImageBuffer, { | ||||
|         target: 'into', | ||||
|         type: 'image', | ||||
|         isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|         mime: 'image/' + imageFormat.ext.toLowerCase(), | ||||
|         attributes: [ | ||||
|             { type: 'label', name: 'originalFileName', value: originalName }, | ||||
|             { type: 'label', name: 'fileSize', value: optimizedImage.byteLength } | ||||
|             { type: 'label', name: 'fileSize', value: finalImageBuffer.byteLength } | ||||
|         ] | ||||
|     }); | ||||
|  | ||||
|     return { | ||||
|         fileName, | ||||
|         note, | ||||
|         noteId: note.noteId, | ||||
|         url: `/api/images/${note.noteId}/${fileName}` | ||||
|         url: `api/images/${note.noteId}/${fileName}` | ||||
|     }; | ||||
| } | ||||
|  | ||||
| async function shrinkImage(buffer, originalName) { | ||||
|     const resizedImage = await resize(buffer); | ||||
|     let finalImageBuffer; | ||||
|  | ||||
|     try { | ||||
|         finalImageBuffer = await optimize(resizedImage); | ||||
|     } catch (e) { | ||||
|         log.error("Failed to optimize image '" + originalName + "\nStack: " + e.stack); | ||||
|         finalImageBuffer = resizedImage; | ||||
|     } | ||||
|     return finalImageBuffer; | ||||
| } | ||||
|  | ||||
| const MAX_SIZE = 1000; | ||||
| const MAX_BYTE_SIZE = 200000; // images should have under 100 KBs | ||||
|  | ||||
| @@ -69,15 +76,7 @@ async function resize(buffer) { | ||||
|     // when converting PNG to JPG we lose alpha channel, this is replaced by white to match Trilium white background | ||||
|     image.background(0xFFFFFFFF); | ||||
|  | ||||
|     // getBuffer doesn't support promises so this workaround | ||||
|     return await new Promise((resolve, reject) => image.getBuffer(jimp.MIME_JPEG, (err, data) => { | ||||
|         if (err) { | ||||
|             reject(err); | ||||
|         } | ||||
|         else { | ||||
|             resolve(data); | ||||
|         } | ||||
|     })); | ||||
|     return image.getBufferAsync(jimp.MIME_JPEG); | ||||
| } | ||||
|  | ||||
| async function optimize(buffer) { | ||||
|   | ||||
| @@ -6,6 +6,7 @@ const log = require("../log"); | ||||
| const utils = require("../utils"); | ||||
| const noteService = require("../notes"); | ||||
| const imageService = require("../image"); | ||||
| const protectedSessionService = require('../protected_session'); | ||||
|  | ||||
| // date format is e.g. 20181121T193703Z | ||||
| function parseDate(text) { | ||||
| @@ -31,7 +32,8 @@ async function importEnex(importContext, file, parentNote) { | ||||
|     // root note is new note into all ENEX/notebook's notes will be imported | ||||
|     const rootNote = (await noteService.createNote(parentNote.noteId, rootNoteTitle, "", { | ||||
|         type: 'text', | ||||
|         mime: 'text/html' | ||||
|         mime: 'text/html', | ||||
|         isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|     })).note; | ||||
|  | ||||
|     // we're persisting notes as we parse the document, but these are run asynchronously and may not be finished | ||||
| @@ -215,7 +217,8 @@ async function importEnex(importContext, file, parentNote) { | ||||
|             attributes, | ||||
|             dateCreated, | ||||
|             type: 'text', | ||||
|             mime: 'text/html' | ||||
|             mime: 'text/html', | ||||
|             isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|         })).note; | ||||
|  | ||||
|         importContext.increaseProgressCount(); | ||||
| @@ -233,11 +236,12 @@ async function importEnex(importContext, file, parentNote) { | ||||
|               resource.mime = fileTypeFromBuffer.mime; | ||||
|             } | ||||
|  | ||||
|             const createResourceNote = async () => { | ||||
|             const createFileNote = async () => { | ||||
|                 const resourceNote = (await noteService.createNote(noteEntity.noteId, resource.title, resource.content, { | ||||
|                     attributes: resource.attributes, | ||||
|                     type: 'file', | ||||
|                     mime: resource.mime | ||||
|                     mime: resource.mime, | ||||
|                     isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|                 })).note; | ||||
|  | ||||
|                 importContext.increaseProgressCount(); | ||||
| @@ -251,7 +255,7 @@ async function importEnex(importContext, file, parentNote) { | ||||
|                 try { | ||||
|                     const originalName = "image." + resource.mime.substr(6); | ||||
|  | ||||
|                     const {url} = await imageService.saveImage(resource.content, originalName, noteEntity.noteId); | ||||
|                     const {url} = await imageService.saveImage(resource.content, originalName, noteEntity.noteId, importContext.shrinkImages); | ||||
|  | ||||
|                     const imageLink = `<img src="${url}">`; | ||||
|  | ||||
| @@ -264,10 +268,10 @@ async function importEnex(importContext, file, parentNote) { | ||||
|                     } | ||||
|                 } catch (e) { | ||||
|                     log.error("error when saving image from ENEX file: " + e); | ||||
|                     await createResourceNote(); | ||||
|                     await createFileNote(); | ||||
|                 } | ||||
|             } else { | ||||
|                 await createResourceNote(); | ||||
|                 await createFileNote(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -298,12 +302,7 @@ async function importEnex(importContext, file, parentNote) { | ||||
|     return new Promise((resolve, reject) => | ||||
|     { | ||||
|         // resolve only when we parse the whole document AND saving of all notes have been finished | ||||
|         saxStream.on("end", () => { Promise.all(saveNotePromises).then(() => { | ||||
|                 importContext.importFinished(rootNote.noteId); | ||||
|  | ||||
|                 resolve(rootNote); | ||||
|             }); | ||||
|         }); | ||||
|         saxStream.on("end", () => { Promise.all(saveNotePromises).then(() => resolve(rootNote)) }); | ||||
|  | ||||
|         const bufferStream = new stream.PassThrough(); | ||||
|         bufferStream.end(file.buffer); | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| const noteService = require('../../services/notes'); | ||||
| const parseString = require('xml2js').parseString; | ||||
| const protectedSessionService = require('../protected_session'); | ||||
|  | ||||
| /** | ||||
|  * @param {ImportContext} importContext | ||||
| @@ -43,7 +44,9 @@ async function importOpml(importContext, fileBuffer, parentNote) { | ||||
|             throw new Error("Unrecognized OPML version " + opmlVersion); | ||||
|         } | ||||
|  | ||||
|         const {note} = await noteService.createNote(parentNoteId, title, content); | ||||
|         const {note} = await noteService.createNote(parentNoteId, title, content, { | ||||
|             isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|         }); | ||||
|  | ||||
|         importContext.increaseProgressCount(); | ||||
|  | ||||
| @@ -64,8 +67,6 @@ async function importOpml(importContext, fileBuffer, parentNote) { | ||||
|         returnNote = returnNote || note; | ||||
|     } | ||||
|  | ||||
|     importContext.importFinished(returnNote.noteId); | ||||
|  | ||||
|     return returnNote; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,154 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const noteService = require('../../services/notes'); | ||||
| const imageService = require('../../services/image'); | ||||
| const protectedSessionService = require('../protected_session'); | ||||
| const commonmark = require('commonmark'); | ||||
| const path = require('path'); | ||||
| const mimeTypes = require('mime-types'); | ||||
|  | ||||
| const CODE_MIME_TYPES = { | ||||
|     'text/plain': true, | ||||
|     'text/x-csrc': true, | ||||
|     'text/x-c++src': true, | ||||
|     'text/x-csharp': true, | ||||
|     'text/x-clojure': true, | ||||
|     'text/css': true, | ||||
|     'text/x-dockerfile': true, | ||||
|     'text/x-erlang': true, | ||||
|     'text/x-feature': true, | ||||
|     'text/x-go': true, | ||||
|     'text/x-groovy': true, | ||||
|     'text/x-haskell': true, | ||||
|     'text/html': true, | ||||
|     'message/http': true, | ||||
|     'text/x-java': true, | ||||
|     'application/javascript': 'application/javascript;env=frontend', | ||||
|     'application/x-javascript': 'application/javascript;env=frontend', | ||||
|     'application/json': true, | ||||
|     'text/x-kotlin': true, | ||||
|     'text/x-stex': true, | ||||
|     'text/x-lua': true, | ||||
|     // possibly later migrate to text/markdown as primary MIME | ||||
|     'text/markdown': 'text/x-markdown', | ||||
|     'text/x-markdown': true, | ||||
|     'text/x-objectivec': true, | ||||
|     'text/x-pascal': true, | ||||
|     'text/x-perl': true, | ||||
|     'text/x-php': true, | ||||
|     'text/x-python': true, | ||||
|     'text/x-ruby': true, | ||||
|     'text/x-rustsrc': true, | ||||
|     'text/x-scala': true, | ||||
|     'text/x-sh': true, | ||||
|     'text/x-sql': true, | ||||
|     'text/x-swift': true, | ||||
|     'text/xml': true, | ||||
|     'text/x-yaml': true | ||||
| }; | ||||
|  | ||||
| async function importSingleFile(importContext, file, parentNote) { | ||||
|     const mime = mimeTypes.lookup(file.originalname); | ||||
|  | ||||
|     if (importContext.textImportedAsText) { | ||||
|         if (mime === 'text/html') { | ||||
|             return await importHtml(importContext, file, parentNote); | ||||
|         } else if (['text/markdown', 'text/x-markdown'].includes(mime)) { | ||||
|             return await importMarkdown(importContext, file, parentNote); | ||||
|         } else if (mime === 'text/plain') { | ||||
|             return await importPlainText(importContext, file, parentNote); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (importContext.codeImportedAsCode && mime in CODE_MIME_TYPES) { | ||||
|         return await importCodeNote(importContext, file, parentNote); | ||||
|     } | ||||
|  | ||||
|     if (["image/jpeg", "image/gif", "image/png"].includes(mime)) { | ||||
|         return await importImage(file, parentNote, importContext); | ||||
|     } | ||||
|  | ||||
|     return await importFile(importContext, file, parentNote); | ||||
| } | ||||
|  | ||||
| async function importImage(file, parentNote, importContext) { | ||||
|     const {note} = await imageService.saveImage(file.buffer, getFileNameWithoutExtension(file.originalname), parentNote.noteId, importContext.shrinkImages); | ||||
|  | ||||
|     importContext.increaseProgressCount(); | ||||
|  | ||||
|     return note; | ||||
| } | ||||
|  | ||||
| async function importFile(importContext, file, parentNote) { | ||||
|     const originalName = file.originalname; | ||||
|     const size = file.size; | ||||
|  | ||||
|     const {note} = await noteService.createNote(parentNote.noteId, originalName, file.buffer, { | ||||
|         target: 'into', | ||||
|         isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|         type: 'file', | ||||
|         mime: mimeTypes.lookup(originalName), | ||||
|         attributes: [ | ||||
|             { type: "label", name: "originalFileName", value: originalName }, | ||||
|             { type: "label", name: "fileSize", value: size } | ||||
|         ] | ||||
|     }); | ||||
|  | ||||
|     importContext.increaseProgressCount(); | ||||
|  | ||||
|     return note; | ||||
| } | ||||
|  | ||||
| async function importCodeNote(importContext, file, parentNote) { | ||||
|     const title = getFileNameWithoutExtension(file.originalname); | ||||
|     const content = file.buffer.toString("UTF-8"); | ||||
|     const detectedMime = mimeTypes.lookup(file.originalname); | ||||
|     const mime = CODE_MIME_TYPES[detectedMime] === true ? detectedMime : CODE_MIME_TYPES[detectedMime]; | ||||
|  | ||||
|     const {note} = await noteService.createNote(parentNote.noteId, title, content, { | ||||
|         type: 'code', | ||||
|         mime: mime, | ||||
|         isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable() | ||||
|     }); | ||||
|  | ||||
|     importContext.increaseProgressCount(); | ||||
|  | ||||
|     return note; | ||||
| } | ||||
|  | ||||
| async function importPlainText(importContext, file, parentNote) { | ||||
|     const title = getFileNameWithoutExtension(file.originalname); | ||||
|     const plainTextContent = file.buffer.toString("UTF-8"); | ||||
|     const htmlContent = convertTextToHtml(plainTextContent); | ||||
|  | ||||
|     const {note} = await noteService.createNote(parentNote.noteId, title, htmlContent, { | ||||
|         type: 'text', | ||||
|         mime: 'text/html', | ||||
|         isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|     }); | ||||
|  | ||||
|     importContext.increaseProgressCount(); | ||||
|  | ||||
|     return note; | ||||
| } | ||||
|  | ||||
| function convertTextToHtml(text) { | ||||
|     // 1: Plain Text Search | ||||
|     text = text.replace(/&/g, "&"). | ||||
|     replace(/</g, "<"). | ||||
|     replace(/>/g, ">"); | ||||
|  | ||||
|     // 2: Line Breaks | ||||
|     text = text.replace(/\r\n?|\n/g, "<br>"); | ||||
|  | ||||
|     // 3: Paragraphs | ||||
|     text = text.replace(/<br>\s*<br>/g, "</p><p>"); | ||||
|  | ||||
|     // 4: Wrap in Paragraph Tags | ||||
|     text = "<p>" + text + "</p>"; | ||||
|  | ||||
|     return text; | ||||
| } | ||||
|  | ||||
| async function importMarkdown(importContext, file, parentNote) { | ||||
|     const markdownContent = file.buffer.toString("UTF-8"); | ||||
| @@ -17,11 +163,11 @@ async function importMarkdown(importContext, file, parentNote) { | ||||
|  | ||||
|     const {note} = await noteService.createNote(parentNote.noteId, title, htmlContent, { | ||||
|         type: 'text', | ||||
|         mime: 'text/html' | ||||
|         mime: 'text/html', | ||||
|         isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|     }); | ||||
|  | ||||
|     importContext.increaseProgressCount(); | ||||
|     importContext.importFinished(note.noteId); | ||||
|  | ||||
|     return note; | ||||
| } | ||||
| @@ -32,11 +178,11 @@ async function importHtml(importContext, file, parentNote) { | ||||
|  | ||||
|     const {note} = await noteService.createNote(parentNote.noteId, title, content, { | ||||
|         type: 'text', | ||||
|         mime: 'text/html' | ||||
|         mime: 'text/html', | ||||
|         isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|     }); | ||||
|  | ||||
|     importContext.increaseProgressCount(); | ||||
|     importContext.importFinished(note.noteId); | ||||
|  | ||||
|     return note; | ||||
| } | ||||
| @@ -48,6 +194,5 @@ function getFileNameWithoutExtension(filePath) { | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     importMarkdown, | ||||
|     importHtml | ||||
|     importSingleFile | ||||
| }; | ||||
| @@ -14,6 +14,7 @@ const path = require('path'); | ||||
| const commonmark = require('commonmark'); | ||||
| const mimeTypes = require('mime-types'); | ||||
| const ImportContext = require('../import_context'); | ||||
| const protectedSessionService = require('../protected_session'); | ||||
|  | ||||
| /** | ||||
|  * @param {ImportContext} importContext | ||||
| @@ -22,8 +23,6 @@ const ImportContext = require('../import_context'); | ||||
|  * @return {Promise<*>} | ||||
|  */ | ||||
| async function importTar(importContext, fileBuffer, importRootNote) { | ||||
|     importContext = importContext || new ImportContext("1", false); | ||||
|  | ||||
|     // maps from original noteId (in tar file) to newly generated noteId | ||||
|     const noteIdMap = {}; | ||||
|     const attributes = []; | ||||
| @@ -134,7 +133,7 @@ async function importTar(importContext, fileBuffer, importRootNote) { | ||||
|         let type = 'file'; | ||||
|  | ||||
|         if (mime) { | ||||
|             if (mime === 'text/html' || mime === 'text/markdown') { | ||||
|             if (mime === 'text/html' || ['text/markdown', 'text/x-markdown'].includes(mime)) { | ||||
|                 type = 'text'; | ||||
|             } | ||||
|             else if (mime.startsWith('image/')) { | ||||
| @@ -195,7 +194,8 @@ async function importTar(importContext, fileBuffer, importRootNote) { | ||||
|             type: noteMeta ? noteMeta.type : 'text', | ||||
|             mime: noteMeta ? noteMeta.mime : 'text/html', | ||||
|             prefix: noteMeta ? noteMeta.prefix : '', | ||||
|             isExpanded: noteMeta ? noteMeta.isExpanded : false | ||||
|             isExpanded: noteMeta ? noteMeta.isExpanded : false, | ||||
|             isProtected: importRootNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|         })); | ||||
|  | ||||
|         await saveAttributesAndLinks(note, noteMeta); | ||||
| @@ -251,7 +251,7 @@ async function importTar(importContext, fileBuffer, importRootNote) { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ((noteMeta && noteMeta.format === 'markdown') || (!noteMeta && mime === 'text/markdown')) { | ||||
|         if ((noteMeta && noteMeta.format === 'markdown') || (!noteMeta && ['text/markdown', 'text/x-markdown'].includes(mime))) { | ||||
|             const parsed = mdReader.parse(content); | ||||
|             content = mdWriter.render(parsed); | ||||
|         } | ||||
| @@ -273,7 +273,8 @@ async function importTar(importContext, fileBuffer, importRootNote) { | ||||
|                 mime, | ||||
|                 prefix: noteMeta ? noteMeta.prefix : '', | ||||
|                 isExpanded: noteMeta ? noteMeta.isExpanded : false, | ||||
|                 notePosition: noteMeta ? noteMeta.notePosition : false | ||||
|                 notePosition: noteMeta ? noteMeta.notePosition : false, | ||||
|                 isProtected: importRootNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|             })); | ||||
|  | ||||
|             await saveAttributesAndLinks(note, noteMeta); | ||||
| @@ -386,8 +387,6 @@ async function importTar(importContext, fileBuffer, importRootNote) { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             importContext.importFinished(); | ||||
|  | ||||
|             resolve(firstNote); | ||||
|         }); | ||||
|  | ||||
|   | ||||
| @@ -2,19 +2,34 @@ | ||||
|  | ||||
| const messagingService = require('./messaging'); | ||||
|  | ||||
| // importId => ImportContext | ||||
| const importContexts = {}; | ||||
|  | ||||
| class ImportContext { | ||||
|     constructor(importId, safeImport) { | ||||
|     constructor(importId, options) { | ||||
|         // importId is to distinguish between different import events - it is possible (though not recommended) | ||||
|         // to have multiple imports going at the same time | ||||
|         this.importId = importId; | ||||
|  | ||||
|         this.safeImport = safeImport; | ||||
|         this.safeImport = options.safeImport; | ||||
|         this.shrinkImages = options.shrinkImages; | ||||
|         this.codeImportedAsCode = options.codeImportedAsCode; | ||||
|         this.textImportedAsText = options.textImportedAsText; | ||||
|  | ||||
|         // // count is mean to represent count of exported notes where practical, otherwise it's just some measure of progress | ||||
|         this.progressCount = 0; | ||||
|         this.lastSentCountTs = Date.now(); | ||||
|     } | ||||
|  | ||||
|     /** @return {ImportContext} */ | ||||
|     static getInstance(importId, options) { | ||||
|         if (!importContexts[importId]) { | ||||
|             importContexts[importId] = new ImportContext(importId, options); | ||||
|         } | ||||
|  | ||||
|         return importContexts[importId]; | ||||
|     } | ||||
|  | ||||
|     async increaseProgressCount() { | ||||
|         this.progressCount++; | ||||
|  | ||||
| @@ -29,14 +44,6 @@ class ImportContext { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async importFinished(noteId) { | ||||
|         await messagingService.sendMessageToAllClients({ | ||||
|             importId: this.importId, | ||||
|             type: 'import-finished', | ||||
|             noteId: noteId | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // must remaing non-static | ||||
|     async reportError(message) { | ||||
|         await messagingService.sendMessageToAllClients({ | ||||
|   | ||||
| @@ -207,7 +207,8 @@ function findImageLinks(content, foundLinks) { | ||||
|     } | ||||
|  | ||||
|     // removing absolute references to server to keep it working between instances | ||||
|     return content.replace(/src="[^"]*\/api\/images\//g, 'src="/api/images/'); | ||||
|     // we also omit / at the beginning to keep the paths relative | ||||
|     return content.replace(/src="[^"]*\/api\/images\//g, 'src="api/images/'); | ||||
| } | ||||
|  | ||||
| function findHyperLinks(content, foundLinks) { | ||||
| @@ -291,7 +292,7 @@ async function saveLinks(note, content) { | ||||
| async function saveNoteRevision(note) { | ||||
|     // files and images are immutable, they can't be updated | ||||
|     // but we don't even version titles which is probably not correct | ||||
|     if (note.type !== 'file' || note.type !== 'image' || await note.hasLabel('disableVersioning')) { | ||||
|     if (note.type === 'file' || note.type === 'image' || await note.hasLabel('disableVersioning')) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
| @@ -310,7 +311,7 @@ async function saveNoteRevision(note) { | ||||
|             noteId: note.noteId, | ||||
|             // title and text should be decrypted now | ||||
|             title: note.title, | ||||
|             content: note.noteContent.content, | ||||
|             content: await note.getContent(), | ||||
|             type: note.type, | ||||
|             mime: note.mime, | ||||
|             isProtected: false, // will be fixed in the protectNoteRevisions() call | ||||
| @@ -331,19 +332,21 @@ async function updateNote(noteId, noteUpdates) { | ||||
|  | ||||
|     const noteTitleChanged = note.title !== noteUpdates.title; | ||||
|  | ||||
|     noteUpdates.noteContent.content = await saveLinks(note, noteUpdates.noteContent.content); | ||||
|  | ||||
|     note.title = noteUpdates.title; | ||||
|     note.isProtected = noteUpdates.isProtected; | ||||
|     await note.save(); | ||||
|  | ||||
|     if (note.type !== 'file' && note.type !== 'image') { | ||||
|         const noteContent = await note.getNoteContent(); | ||||
|     const noteContent = await note.getNoteContent(); | ||||
|  | ||||
|     if (!['file', 'image'].includes(note.type)) { | ||||
|         noteUpdates.noteContent.content = await saveLinks(note, noteUpdates.noteContent.content); | ||||
|  | ||||
|         noteContent.content = noteUpdates.noteContent.content; | ||||
|         noteContent.isProtected = noteUpdates.isProtected; | ||||
|         await noteContent.save(); | ||||
|     } | ||||
|  | ||||
|     noteContent.isProtected = noteUpdates.isProtected; | ||||
|     await noteContent.save(); | ||||
|  | ||||
|     if (noteTitleChanged) { | ||||
|         await triggerNoteTitleChanged(note); | ||||
|     } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ function setDataKey(decryptedDataKey) { | ||||
| } | ||||
|  | ||||
| function setProtectedSessionId(req) { | ||||
|     cls.namespace.set('protectedSessionId', req.headers['trilium-protected-session-id']); | ||||
|     cls.namespace.set('protectedSessionId', req.cookies.protectedSessionId); | ||||
| } | ||||
|  | ||||
| function getProtectedSessionId() { | ||||
| @@ -62,7 +62,9 @@ function decryptNoteContent(noteContent) { | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|         noteContent.content = dataEncryptionService.decrypt(getDataKey(), noteContent.content); | ||||
|         if (noteContent.content != null) { | ||||
|             noteContent.content = dataEncryptionService.decrypt(getDataKey(), noteContent.content.toString()); | ||||
|         } | ||||
|     } | ||||
|     catch (e) { | ||||
|         e.message = `Cannot decrypt note content for noteContentId=${noteContent.noteContentId}: ` + e.message; | ||||
|   | ||||
| @@ -65,10 +65,10 @@ async function executeScript(script, params, startNoteId, currentNoteId, originE | ||||
|  | ||||
|     const bundle = await getScriptBundle(currentNote); | ||||
|  | ||||
|     return await executeBundle(bundle, startNote, originEntity); | ||||
|     return await executeBundle(bundle, { startNote, originEntity }); | ||||
| } | ||||
|  | ||||
| async function execute(ctx, script, params = []) { | ||||
| async function execute(ctx, script) { | ||||
|     // scripts run as "server" sourceId so clients recognize the changes as "foreign" and update themselves | ||||
|     cls.namespace.set('sourceId', sourceIdService.getCurrentSourceId()); | ||||
|  | ||||
|   | ||||
| @@ -161,7 +161,7 @@ async function transactional(func) { | ||||
|     } | ||||
|  | ||||
|     let ret = null; | ||||
|     const error = new Error(); // to capture correct stack trace in case of exception | ||||
|     const thisError = new Error(); // to capture correct stack trace in case of exception | ||||
|  | ||||
|     transactionActive = true; | ||||
|     transactionPromise = new Promise(async (resolve, reject) => { | ||||
| @@ -179,7 +179,7 @@ async function transactional(func) { | ||||
|         } | ||||
|         catch (e) { | ||||
|             if (transactionActive) { | ||||
|                 log.error("Error executing transaction, executing rollback. Inner exception: " + e.stack + error.stack); | ||||
|                 log.error("Error executing transaction, executing rollback. Inner stack: " + e.stack + "\nOutside stack: " + thisError.stack); | ||||
|  | ||||
|                 await rollback(); | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ const sql = require('./sql'); | ||||
| const cls = require('./cls'); | ||||
| const optionService = require('./options'); | ||||
| const Option = require('../entities/option'); | ||||
| const ImportContext = require('../services/import_context'); | ||||
|  | ||||
| async function createConnection() { | ||||
|     return await sqlite.open(dataDir.DOCUMENT_PATH, {Promise}); | ||||
| @@ -100,8 +101,10 @@ async function createInitialDatabase(username, password) { | ||||
|             notePosition: 0 | ||||
|         }).save(); | ||||
|  | ||||
|         const dummyImportContext = new ImportContext("1", false); | ||||
|  | ||||
|         const tarImportService = require("./import/tar"); | ||||
|         await tarImportService.importTar(null, demoFile, rootNote); | ||||
|         await tarImportService.importTar(dummyImportContext, demoFile, rootNote); | ||||
|  | ||||
|         const startNoteId = await sql.getValue("SELECT noteId FROM branches WHERE parentNoteId = 'root' AND isDeleted = 0 ORDER BY notePosition"); | ||||
|  | ||||
|   | ||||
| @@ -1,7 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export2.dtd"> | ||||
| <en-export export-date="20181101T193909Z" application="Evernote/Windows" version="6.x"> | ||||
| <note><title>Note</title><content><![CDATA[<?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"> | ||||
|  | ||||
| <en-note><div>this is a note in a notebook in a stack</div></en-note>]]></content><created>20181101T193703Z</created><updated>20181101T193712Z</updated><note-attributes><author>Adam Zivner</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note></en-export> | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -195,7 +195,7 @@ | ||||
|                             <a class="dropdown-item" id="show-note-revisions-button" data-bind="css: { disabled: type() == 'file' || type() == 'image' }">Revisions</a> | ||||
|                             <a class="dropdown-item show-attributes-button"><kbd>Alt+A</kbd> Attributes</a> | ||||
|                             <a class="dropdown-item" id="show-source-button" data-bind="css: { disabled: type() != 'text' && type() != 'code' && type() != 'relation-map' && type() != 'search' }">Note source</a> | ||||
|                             <a class="dropdown-item" id="upload-file-button">Upload file</a> | ||||
|                             <a class="dropdown-item" id="import-files-button">Import files</a> | ||||
|                             <a class="dropdown-item" id="export-note-button" data-bind="css: { disabled: type() != 'text' }">Export note</a> | ||||
|                             <a class="dropdown-item" id="show-note-info-button">Note info</a> | ||||
|                         </div> | ||||
|   | ||||
| @@ -9,7 +9,6 @@ | ||||
|         <div id="note-detail-text" class="note-detail-component" tabindex="10000"></div> | ||||
|  | ||||
|         <div id="note-detail-code" class="note-detail-component"></div> | ||||
|         <input type="file" id="file-upload" style="display: none" /> | ||||
|  | ||||
|         <% include search.ejs %> | ||||
|  | ||||
|   | ||||
| @@ -16,19 +16,46 @@ | ||||
|                     <div class="form-group"> | ||||
|                         <label for="import-file-upload-input"><strong>Choose import file</strong></label> | ||||
|  | ||||
|                         <input type="file" id="import-file-upload-input" class="form-control-file" /> | ||||
|                         <input type="file" id="import-file-upload-input" class="form-control-file" multiple /> | ||||
|  | ||||
|                         <p>Content of the file will be imported as child note(s) into <strong class="note-title"></strong>. Import file must be of supported type and have correct extension - one of <code>.html</code>, <code>.md</code>, <code>.tar</code>, <code>.enex</code>.</p> | ||||
|                         <p>Content of the file will be imported as child note(s) into <strong class="note-title"></strong>. | ||||
|                     </div> | ||||
|  | ||||
|                     <div class="form-group"> | ||||
|                         <strong>Options:</strong> | ||||
|  | ||||
|                         <div class="checkbox"> | ||||
|                             <label data-toggle="tooltip" title="Trilium <code>.tar</code> export files can contain executable scripts which may contain harmful behavior. Safe import will deactivate automatic execution of all imported scripts. Uncheck "Safe import" only if the imported tar archive is supposed to contain executable scripts and you completely trust the contents of the import file."> | ||||
|                                 <input id="safe-import-checkbox" value="1" type="checkbox" checked> | ||||
|                                 <span>Safe import</span> | ||||
|                             </label> | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="checkbox"> | ||||
|                             <label data-toggle="tooltip" title="If this is checked then Trilium will read <code>.tar</code>, <code>.enex</code> and <code>.opml</code> files and create notes from files insides those archives. If unchecked, then Trilium will attach the archives themselves to the note."> | ||||
|                                 <input id="explode-archives-checkbox" value="1" type="checkbox" checked> | ||||
|                                 <span>Read contents of <code>.tar</code>, <code>.enex</code> and <code>.opml</code> archives.</span> | ||||
|                             </label> | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="checkbox"> | ||||
|                             <label data-toggle="tooltip" title="<p>If you check this option, Trilium will attempt to shrink the imported images by scaling and optimization which may affect the perceived image quality. If unchecked, images will be imported without changes.</p><p>This doesn't apply to <code>.tar</code> imports with metadata since it is assumed these files are already optimized.</p>"> | ||||
|                                 <input id="shrink-images-checkbox" value="1" type="checkbox" checked> <span>Shrink images</span> | ||||
|                             </label> | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="checkbox"> | ||||
|                             <label> | ||||
|                                 <input id="safe-import" value="1" type="checkbox" checked> <strong>Safe import</strong> | ||||
|                             </label> | ||||
|                                 <input id="text-imported-as-text-checkbox" value="1" type="checkbox" checked> | ||||
|  | ||||
|                             <br/> | ||||
|                             Trilium <code>.tar</code> export files can contain executable scripts which may contain harmful behavior. Safe import will deactivate automatic execution of all imported scripts. Uncheck "Safe import" only if the imported tar archive is supposed to contain executable scripts and you completely trust the contents of the import file. | ||||
|                                 Import HTML, Markdown and TXT as text notes if it's unclear from metadata | ||||
|                             </label> | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="checkbox"> | ||||
|                             <label> | ||||
|                                 <input id="code-imported-as-code-checkbox" value="1" type="checkbox" checked> Import recognized code files (e.g. <code>.json</code>) as code notes if it's unclear from metadata | ||||
|                             </label> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <div id="options-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog"> | ||||
|     <div class="modal-dialog modal-lg" style="min-width: 1000px;" role="document"> | ||||
|     <div class="modal-dialog modal-lg modal-dialog-scrollable" style="min-width: 1000px;" role="document"> | ||||
|         <div class="modal-content"> | ||||
|             <div class="modal-header"> | ||||
|                 <h5 class="modal-title">Options</h5> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user