mirror of
https://github.com/zadam/trilium.git
synced 2025-10-27 16:26:31 +01:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a13edd490 | ||
|
|
0ec11d29ba | ||
|
|
a6cd25071e | ||
|
|
759e47bfcf | ||
|
|
67bdffb27b | ||
|
|
3386dace3b | ||
|
|
3cf3fc13b9 | ||
|
|
2b69abf8ab | ||
|
|
3e49a7dbfa | ||
|
|
f782d2bef9 | ||
|
|
ccaa9eae3a | ||
|
|
24c5388e0c |
3
.idea/.gitignore
generated
vendored
3
.idea/.gitignore
generated
vendored
@@ -2,4 +2,5 @@
|
|||||||
/workspace.xml
|
/workspace.xml
|
||||||
|
|
||||||
# Datasource local storage ignored files
|
# Datasource local storage ignored files
|
||||||
/dataSources.local.xml
|
/dataSources.local.xml
|
||||||
|
/dataSources/
|
||||||
|
|||||||
@@ -1240,6 +1240,143 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="addTextToActiveTabEditor"><span class="type-signature"></span>addTextToActiveTabEditor<span class="signature">(text)</span><span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Adds given text to the editor cursor
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Parameters:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<table class="params">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th>Name</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th>Type</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<th class="last">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>text</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line305">line 305</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1366,7 +1503,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line390">line 390</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line406">line 406</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -1785,7 +1922,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line303">line 303</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line311">line 311</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -1891,7 +2028,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line309">line 309</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line325">line 325</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -1949,6 +2086,119 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="getActiveTabTextEditor"><span class="type-signature"></span>getActiveTabTextEditor<span class="signature">()</span><span class="type-signature"> → {Editor|null}</span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line319">line 319</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Returns:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="param-desc">
|
||||||
|
CKEditor instance or null (e.g. if active note is not a text note)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
Type
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<span class="param-type">Editor</span>
|
||||||
|
|
|
||||||
|
|
||||||
|
<span class="param-type">null</span>
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4 class="name" id="getDateNote"><span class="type-signature"></span>getDateNote<span class="signature">(date)</span><span class="type-signature"> → {Promise.<<a href="NoteShort.html">NoteShort</a>>}</span></h4>
|
<h4 class="name" id="getDateNote"><span class="type-signature"></span>getDateNote<span class="signature">(date)</span><span class="type-signature"> → {Promise.<<a href="NoteShort.html">NoteShort</a>>}</span></h4>
|
||||||
|
|
||||||
|
|
||||||
@@ -2050,7 +2300,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line356">line 356</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line372">line 372</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -2312,7 +2562,7 @@ if some action needs to happen on only one specific instance.
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line365">line 365</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line381">line 381</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -2775,7 +3025,7 @@ otherwise (by e.g. createNoteLink())
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line347">line 347</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line363">line 363</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -2930,7 +3180,7 @@ otherwise (by e.g. createNoteLink())
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line374">line 374</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line390">line 390</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -3039,7 +3289,7 @@ note.
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line320">line 320</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line336">line 336</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -3194,7 +3444,7 @@ note.
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line328">line 328</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line344">line 344</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -3433,7 +3683,7 @@ note.
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line339">line 339</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line355">line 355</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -4606,7 +4856,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line383">line 383</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line399">line 399</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -4757,7 +5007,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line334">line 334</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line350">line 350</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@@ -5123,7 +5373,7 @@ Typical use case is when new note has been created, we should wait until it is s
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line401">line 401</a>
|
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line417">line 417</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -324,12 +324,28 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
|||||||
*/
|
*/
|
||||||
this.createNoteLink = linkService.createNoteLink;
|
this.createNoteLink = linkService.createNoteLink;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds given text to the editor cursor
|
||||||
|
*
|
||||||
|
* @param {string} text
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
|
this.addTextToActiveTabEditor = linkService.addTextToEditor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method
|
* @method
|
||||||
* @returns {NoteFull} active note (loaded into right pane)
|
* @returns {NoteFull} active note (loaded into right pane)
|
||||||
*/
|
*/
|
||||||
this.getActiveTabNote = noteDetailService.getActiveTabNote;
|
this.getActiveTabNote = noteDetailService.getActiveTabNote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @returns {Editor|null} CKEditor instance or null (e.g. if active note is not a text note)
|
||||||
|
*/
|
||||||
|
this.getActiveTabTextEditor = noteDetailService.getActiveEditor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method
|
* @method
|
||||||
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
|
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"version": "0.39.3",
|
"version": "0.39.5",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"productName": "Trilium Notes",
|
"productName": "Trilium Notes",
|
||||||
"description": "Trilium Notes",
|
"description": "Trilium Notes",
|
||||||
"version": "0.39.4",
|
"version": "0.39.6",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"main": "electron.js",
|
"main": "electron.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -805,7 +805,7 @@ class Note extends Entity {
|
|||||||
WHERE noteId = ? AND
|
WHERE noteId = ? AND
|
||||||
isDeleted = 0 AND
|
isDeleted = 0 AND
|
||||||
type = 'relation' AND
|
type = 'relation' AND
|
||||||
name IN ('internalLink', 'imageLink', 'relationMapLink')`, [this.noteId]);
|
name IN ('internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink')`, [this.noteId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const TPL = `
|
|||||||
<div>
|
<div>
|
||||||
<h4>Spell check</h4>
|
<h4>Spell check</h4>
|
||||||
|
|
||||||
<p>These options apply only for desktop builds, browsers will use their own native spell check.</p>
|
<p>These options apply only for desktop builds, browsers will use their own native spell check. App restart is required after change.</p>
|
||||||
|
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="custom-control custom-checkbox">
|
||||||
<input type="checkbox" class="custom-control-input" id="spell-check-enabled">
|
<input type="checkbox" class="custom-control-input" id="spell-check-enabled">
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ async function initContextMenu(event, contextMenu) {
|
|||||||
// in such case we'll position it above click coordinates so it will fit into client
|
// in such case we'll position it above click coordinates so it will fit into client
|
||||||
const clickPosition = event.pageY;
|
const clickPosition = event.pageY;
|
||||||
const clientHeight = document.documentElement.clientHeight;
|
const clientHeight = document.documentElement.clientHeight;
|
||||||
const contextMenuHeight = $contextMenuContainer.height();
|
const contextMenuHeight = $contextMenuContainer.outerHeight() + 30;
|
||||||
|
|
||||||
let top;
|
let top;
|
||||||
|
|
||||||
if (clickPosition + contextMenuHeight > clientHeight) {
|
if (clickPosition + contextMenuHeight > clientHeight) {
|
||||||
|
|||||||
@@ -296,12 +296,28 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
|||||||
*/
|
*/
|
||||||
this.createNoteLink = linkService.createNoteLink;
|
this.createNoteLink = linkService.createNoteLink;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds given text to the editor cursor
|
||||||
|
*
|
||||||
|
* @param {string} text - this must be clear text, HTML is not supported.
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
|
this.addTextToActiveTabEditor = linkService.addTextToEditor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method
|
* @method
|
||||||
* @returns {NoteFull} active note (loaded into right pane)
|
* @returns {NoteFull} active note (loaded into right pane)
|
||||||
*/
|
*/
|
||||||
this.getActiveTabNote = noteDetailService.getActiveTabNote;
|
this.getActiveTabNote = noteDetailService.getActiveTabNote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @returns {Editor|null} CKEditor instance or null (e.g. if active note is not a text note)
|
||||||
|
*/
|
||||||
|
this.getActiveTabTextEditor = noteDetailService.getActiveEditor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method
|
* @method
|
||||||
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
|
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
|
||||||
|
|||||||
@@ -201,17 +201,13 @@ async function loadNoteDetail(origNotePath, options = {}) {
|
|||||||
const newTab = !!options.newTab;
|
const newTab = !!options.newTab;
|
||||||
const activate = !!options.activate;
|
const activate = !!options.activate;
|
||||||
|
|
||||||
const notePath = await treeService.resolveNotePath(origNotePath);
|
let notePath = await treeService.resolveNotePath(origNotePath);
|
||||||
|
|
||||||
if (!notePath) {
|
if (!notePath) {
|
||||||
console.error(`Cannot resolve note path ${origNotePath}`);
|
console.error(`Cannot resolve note path ${origNotePath}`);
|
||||||
|
|
||||||
// fallback to display something
|
// fallback to display something
|
||||||
if (tabContexts.length === 0) {
|
notePath = 'root';
|
||||||
await openEmptyTab();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class NoteDetailText {
|
|||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.$component = ctx.$tabContent.find('.note-detail-text');
|
this.$component = ctx.$tabContent.find('.note-detail-text');
|
||||||
this.$editorEl = this.$component.find('.note-detail-text-editor');
|
this.$editorEl = this.$component.find('.note-detail-text-editor');
|
||||||
|
this.textEditorPromise = null;
|
||||||
this.textEditor = null;
|
this.textEditor = null;
|
||||||
|
|
||||||
this.$component.on("dblclick", "img", e => {
|
this.$component.on("dblclick", "img", e => {
|
||||||
@@ -67,44 +68,12 @@ class NoteDetailText {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async render() {
|
async render() {
|
||||||
if (!this.textEditor) {
|
if (!this.textEditorPromise) {
|
||||||
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
|
this.textEditorPromise = this.initEditor();
|
||||||
|
|
||||||
const codeBlockLanguages =
|
|
||||||
(await mimeTypesService.getMimeTypes())
|
|
||||||
.filter(mt => mt.enabled)
|
|
||||||
.map(mt => {
|
|
||||||
return {
|
|
||||||
language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
|
|
||||||
label: mt.title
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
|
|
||||||
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
|
|
||||||
// display of $component in both branches.
|
|
||||||
this.$component.show();
|
|
||||||
|
|
||||||
// textEditor might have been initialized during previous await so checking again
|
|
||||||
// looks like double initialization can freeze CKEditor pretty badly
|
|
||||||
if (!this.textEditor) {
|
|
||||||
this.textEditor = await BalloonEditor.create(this.$editorEl[0], {
|
|
||||||
placeholder: "Type the content of your note here ...",
|
|
||||||
mention: mentionSetup,
|
|
||||||
codeBlock: {
|
|
||||||
languages: codeBlockLanguages
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (glob.isDev && ENABLE_INSPECTOR) {
|
|
||||||
await import('../../libraries/ckeditor/inspector.js');
|
|
||||||
CKEditorInspector.attach(this.textEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onNoteChange(() => this.ctx.noteChanged());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.textEditorPromise;
|
||||||
|
|
||||||
// lazy loading above can take time and tab might have been already switched to another note
|
// lazy loading above can take time and tab might have been already switched to another note
|
||||||
if (this.ctx.note && this.ctx.note.type === 'text') {
|
if (this.ctx.note && this.ctx.note.type === 'text') {
|
||||||
this.textEditor.isReadOnly = await this.isReadOnly();
|
this.textEditor.isReadOnly = await this.isReadOnly();
|
||||||
@@ -115,6 +84,42 @@ class NoteDetailText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async initEditor() {
|
||||||
|
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
|
||||||
|
|
||||||
|
const codeBlockLanguages =
|
||||||
|
(await mimeTypesService.getMimeTypes())
|
||||||
|
.filter(mt => mt.enabled)
|
||||||
|
.map(mt => {
|
||||||
|
return {
|
||||||
|
language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
|
||||||
|
label: mt.title
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
|
||||||
|
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
|
||||||
|
// display of $component in both branches.
|
||||||
|
this.$component.show();
|
||||||
|
|
||||||
|
const textEditorInstance = await BalloonEditor.create(this.$editorEl[0], {
|
||||||
|
placeholder: "Type the content of your note here ...",
|
||||||
|
mention: mentionSetup,
|
||||||
|
codeBlock: {
|
||||||
|
languages: codeBlockLanguages
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (glob.isDev && ENABLE_INSPECTOR) {
|
||||||
|
await import('../../libraries/ckeditor/inspector.js');
|
||||||
|
CKEditorInspector.attach(textEditorInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.textEditor = textEditorInstance;
|
||||||
|
|
||||||
|
this.onNoteChange(() => this.ctx.noteChanged());
|
||||||
|
}
|
||||||
|
|
||||||
getContent() {
|
getContent() {
|
||||||
const content = this.textEditor.getData();
|
const content = this.textEditor.getData();
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ async function setupProtectedSession(password) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("#container").addClass('protected-session-active');
|
||||||
|
|
||||||
protectedSessionHolder.setProtectedSessionId(response.protectedSessionId);
|
protectedSessionHolder.setProtectedSessionId(response.protectedSessionId);
|
||||||
protectedSessionHolder.touchProtectedSession();
|
protectedSessionHolder.touchProtectedSession();
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ import optionsService from "./options.js";
|
|||||||
export async function initSpellCheck() {
|
export async function initSpellCheck() {
|
||||||
const options = await optionsService.waitForOptions();
|
const options = await optionsService.waitForOptions();
|
||||||
|
|
||||||
if (!options.is('spellCheckEnabled')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
||||||
const {remote, shell} = require('electron');
|
const {remote, shell} = require('electron');
|
||||||
|
|
||||||
const spellCheckHandler = new SpellCheckHandler();
|
const spellCheckHandler = new SpellCheckHandler();
|
||||||
spellCheckHandler.attachToInput();
|
|
||||||
|
// not fully disabling the spellcheck since we want to preserve the context menu
|
||||||
|
// this will just get rid of the "red squiggles"
|
||||||
|
if (options.is('spellCheckEnabled')) {
|
||||||
|
spellCheckHandler.attachToInput();
|
||||||
|
}
|
||||||
|
|
||||||
spellCheckHandler.switchLanguage(options.get('spellCheckLanguageCode'));
|
spellCheckHandler.switchLanguage(options.get('spellCheckLanguageCode'));
|
||||||
|
|
||||||
|
|||||||
@@ -350,8 +350,6 @@ class TabContext {
|
|||||||
|
|
||||||
this.$savedIndicator.fadeIn();
|
this.$savedIndicator.fadeIn();
|
||||||
|
|
||||||
this.$scriptArea.empty();
|
|
||||||
|
|
||||||
// run async
|
// run async
|
||||||
bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this);
|
bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this);
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ body {
|
|||||||
|
|
||||||
#context-menu-container {
|
#context-menu-container {
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
overflow: auto; /* make it scrollable when exceeding total height of the window */
|
/* !!! Cannot set overflow: auto, submenus will break !!! */
|
||||||
}
|
}
|
||||||
|
|
||||||
#context-menu-container, #context-menu-container .dropdown-menu {
|
#context-menu-container, #context-menu-container .dropdown-menu {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
module.exports = { buildDate:"2020-01-04T22:01:20+01:00", buildRevision: "3b8b4da149fbc1b17d09253693823f5135a55f2e" };
|
module.exports = { buildDate:"2020-01-18T20:52:14+01:00", buildRevision: "0ec11d29ba2d524ff80b49ab8dc40f3f8cf3835b" };
|
||||||
|
|||||||
@@ -18,18 +18,6 @@ class ConsistencyChecks {
|
|||||||
this.fixedIssues = false;
|
this.fixedIssues = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findIssues(query, errorCb) {
|
|
||||||
const results = await sql.getRows(query);
|
|
||||||
|
|
||||||
for (const res of results) {
|
|
||||||
logError(errorCb(res));
|
|
||||||
|
|
||||||
this.unrecoveredConsistencyErrors = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
async findAndFixIssues(query, fixerCb) {
|
async findAndFixIssues(query, fixerCb) {
|
||||||
const results = await sql.getRows(query);
|
const results = await sql.getRows(query);
|
||||||
|
|
||||||
@@ -175,13 +163,6 @@ class ConsistencyChecks {
|
|||||||
logError(`Relation ${attributeId} references missing note ${noteId}`)
|
logError(`Relation ${attributeId} references missing note ${noteId}`)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.findIssues(`
|
|
||||||
SELECT noteRevisionId, note_revisions.noteId
|
|
||||||
FROM note_revisions
|
|
||||||
LEFT JOIN notes USING (noteId)
|
|
||||||
WHERE notes.noteId IS NULL`,
|
|
||||||
({noteRevisionId, noteId}) => `Note revision ${noteRevisionId} references missing note ${noteId}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findExistencyIssues() {
|
async findExistencyIssues() {
|
||||||
@@ -335,13 +316,22 @@ class ConsistencyChecks {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.findIssues(`
|
await this.findAndFixIssues(`
|
||||||
SELECT noteId
|
SELECT noteId
|
||||||
FROM notes
|
FROM notes
|
||||||
JOIN note_contents USING (noteId)
|
JOIN note_contents USING (noteId)
|
||||||
WHERE isErased = 1
|
WHERE isErased = 1
|
||||||
AND content IS NOT NULL`,
|
AND content IS NOT NULL`,
|
||||||
({noteId}) => `Note ${noteId} content is not null even though the note is erased`);
|
async ({noteId}) => {
|
||||||
|
if (this.autoFix) {
|
||||||
|
await sql.execute(`UPDATE note_contents SET content = NULL WHERE noteId = ?`, [noteId]);
|
||||||
|
|
||||||
|
logFix(`Note ${noteId} content has been set to null since the note is erased`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logError(`Note ${noteId} content is not null even though the note is erased`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await this.findAndFixIssues(`
|
await this.findAndFixIssues(`
|
||||||
SELECT noteId, noteRevisionId
|
SELECT noteId, noteRevisionId
|
||||||
@@ -398,20 +388,40 @@ class ConsistencyChecks {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.findIssues(`
|
await this.findAndFixIssues(`
|
||||||
SELECT noteRevisionId
|
SELECT noteRevisionId
|
||||||
FROM note_revisions
|
FROM note_revisions
|
||||||
JOIN note_revision_contents USING (noteRevisionId)
|
JOIN note_revision_contents USING (noteRevisionId)
|
||||||
WHERE isErased = 1
|
WHERE isErased = 1
|
||||||
AND content IS NOT NULL`,
|
AND content IS NOT NULL`,
|
||||||
({noteRevisionId}) => `Note revision ${noteRevisionId} content is not null even though the note revision is erased`);
|
async ({noteRevisionId}) => {
|
||||||
|
if (this.autoFix) {
|
||||||
|
await sql.execute(`UPDATE note_revision_contents SET content = NULL WHERE noteRevisionId = ?`, [noteRevisionId]);
|
||||||
|
|
||||||
await this.findIssues(`
|
logFix(`Note revision ${noteRevisionId} content was set to null since the note revision is erased`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logError(`Note revision ${noteRevisionId} content is not null even though the note revision is erased`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.findAndFixIssues(`
|
||||||
SELECT noteId
|
SELECT noteId
|
||||||
FROM notes
|
FROM notes
|
||||||
WHERE isErased = 1
|
WHERE isErased = 1
|
||||||
AND isDeleted = 0`,
|
AND isDeleted = 0`,
|
||||||
({noteId}) => `Note ${noteId} is not deleted even though it is erased`);
|
async ({noteId}) => {
|
||||||
|
if (this.autoFix) {
|
||||||
|
const note = await repository.getNote(noteId);
|
||||||
|
note.isDeleted = true;
|
||||||
|
await note.save();
|
||||||
|
|
||||||
|
logFix(`Note ${noteId} was set to deleted since it is erased`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logError(`Note ${noteId} is not deleted even though it is erased`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await this.findAndFixIssues(`
|
await this.findAndFixIssues(`
|
||||||
SELECT parentNoteId
|
SELECT parentNoteId
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ async function getRootCalendarNote() {
|
|||||||
parentNoteId: 'root',
|
parentNoteId: 'root',
|
||||||
title: 'Calendar',
|
title: 'Calendar',
|
||||||
target: 'into',
|
target: 'into',
|
||||||
isProtected: false
|
isProtected: false,
|
||||||
|
type: 'text',
|
||||||
|
content: ''
|
||||||
})).note;
|
})).note;
|
||||||
|
|
||||||
await attributeService.createLabel(rootNote.noteId, CALENDAR_ROOT_LABEL);
|
await attributeService.createLabel(rootNote.noteId, CALENDAR_ROOT_LABEL);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ async function importTar(taskContext, fileBuffer, importRootNote) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr.type === 'relation' && ['internalLink', 'imageLink', 'relationMapLink'].includes(attr.name)) {
|
if (attr.type === 'relation' && ['internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink'].includes(attr.name)) {
|
||||||
// these relations are created automatically and as such don't need to be duplicated in the import
|
// these relations are created automatically and as such don't need to be duplicated in the import
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,6 +242,20 @@ function findInternalLinks(content, foundLinks) {
|
|||||||
return content.replace(/href="[^"]*#root/g, 'href="#root');
|
return content.replace(/href="[^"]*#root/g, 'href="#root');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findIncludeNoteLinks(content, foundLinks) {
|
||||||
|
const re = /<section class="include-note" data-note-id="([a-zA-Z0-9]+)">/g;
|
||||||
|
let match;
|
||||||
|
|
||||||
|
while (match = re.exec(content)) {
|
||||||
|
foundLinks.push({
|
||||||
|
name: 'includeNoteLink',
|
||||||
|
value: match[1]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
function findRelationMapLinks(content, foundLinks) {
|
function findRelationMapLinks(content, foundLinks) {
|
||||||
const obj = JSON.parse(content);
|
const obj = JSON.parse(content);
|
||||||
|
|
||||||
@@ -267,6 +281,7 @@ async function saveLinks(note, content) {
|
|||||||
if (note.type === 'text') {
|
if (note.type === 'text') {
|
||||||
content = findImageLinks(content, foundLinks);
|
content = findImageLinks(content, foundLinks);
|
||||||
content = findInternalLinks(content, foundLinks);
|
content = findInternalLinks(content, foundLinks);
|
||||||
|
content = findIncludeNoteLinks(content, foundLinks);
|
||||||
}
|
}
|
||||||
else if (note.type === 'relation-map') {
|
else if (note.type === 'relation-map') {
|
||||||
findRelationMapLinks(content, foundLinks);
|
findRelationMapLinks(content, foundLinks);
|
||||||
@@ -490,6 +505,8 @@ async function eraseDeletedNotes() {
|
|||||||
SET isErased = 1,
|
SET isErased = 1,
|
||||||
title = NULL
|
title = NULL
|
||||||
WHERE isErased = 0 AND noteId IN (???)`, noteIdsToErase);
|
WHERE isErased = 0 AND noteId IN (???)`, noteIdsToErase);
|
||||||
|
|
||||||
|
log.info(`Erased notes: ${JSON.stringify(noteIdsToErase)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function duplicateNote(noteId, parentNoteId) {
|
async function duplicateNote(noteId, parentNoteId) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
|
|
||||||
const filterRegex = /(\b(AND|OR)\s+)?@(!?)([\p{L}\p{Number}_]+|"[^"]+")\s*((=|!=|<|<=|>|>=|!?\*=|!?=\*|!?\*=\*)\s*(\S+|"[^"]+"))?/igu;
|
const filterRegex = /(\b(AND|OR)\s+)?@(!?)([\p{L}\p{Number}_]+|"[^"]+")\s*((=|!=|<|<=|>|>=|!?\*=|!?=\*|!?\*=\*)\s*([^\s=*]+|"[^"]+"))?/igu;
|
||||||
const smartValueRegex = /^(NOW|TODAY|WEEK|MONTH|YEAR) *([+\-] *\d+)?$/i;
|
const smartValueRegex = /^(NOW|TODAY|WEEK|MONTH|YEAR) *([+\-] *\d+)?$/i;
|
||||||
|
|
||||||
function calculateSmartValue(v) {
|
function calculateSmartValue(v) {
|
||||||
|
|||||||
@@ -71,22 +71,36 @@ function sendMessageToAllClients(message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fillInAdditionalProperties(sync) {
|
||||||
|
// fill in some extra data needed by the frontend
|
||||||
|
if (sync.entityName === 'attributes') {
|
||||||
|
sync.noteId = await sql.getValue(`SELECT noteId
|
||||||
|
FROM attributes
|
||||||
|
WHERE attributeId = ?`, [sync.entityId]);
|
||||||
|
} else if (sync.entityName === 'note_revisions') {
|
||||||
|
sync.noteId = await sql.getValue(`SELECT noteId
|
||||||
|
FROM note_revisions
|
||||||
|
WHERE noteRevisionId = ?`, [sync.entityId]);
|
||||||
|
} else if (sync.entityName === 'branches') {
|
||||||
|
const {noteId, parentNoteId} = await sql.getRow(`SELECT noteId, parentNoteId
|
||||||
|
FROM branches
|
||||||
|
WHERE branchId = ?`, [sync.entityId]);
|
||||||
|
|
||||||
|
sync.noteId = noteId;
|
||||||
|
sync.parentNoteId = parentNoteId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function sendPing(client) {
|
async function sendPing(client) {
|
||||||
const syncData = require('./sync_table').getEntitySyncsNewerThan(lastAcceptedSyncIds[client.id]);
|
const syncData = require('./sync_table').getEntitySyncsNewerThan(lastAcceptedSyncIds[client.id]);
|
||||||
|
|
||||||
for (const sync of syncData) {
|
for (const sync of syncData) {
|
||||||
// fill in some extra data needed by the frontend
|
try {
|
||||||
if (sync.entityName === 'attributes') {
|
await fillInAdditionalProperties(sync);
|
||||||
sync.noteId = await sql.getValue(`SELECT noteId FROM attributes WHERE attributeId = ?`, [sync.entityId]);
|
|
||||||
}
|
}
|
||||||
else if (sync.entityName === 'note_revisions') {
|
catch (e) {
|
||||||
sync.noteId = await sql.getValue(`SELECT noteId FROM note_revisions WHERE noteRevisionId = ?`, [sync.entityId]);
|
log.error("Could not fill additional properties for sync " + JSON.stringify(sync)
|
||||||
}
|
+ " because of error: " + e.message + ": " + e.stack);
|
||||||
else if (sync.entityName === 'branches') {
|
|
||||||
const {noteId, parentNoteId} = await sql.getRow(`SELECT noteId, parentNoteId FROM branches WHERE branchId = ?`, [sync.entityId]);
|
|
||||||
|
|
||||||
sync.noteId = noteId;
|
|
||||||
sync.parentNoteId = parentNoteId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<table class="table">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Homepage:</th>
|
<th>Homepage:</th>
|
||||||
<td><a href="https://github.com/zadam/trilium" class="external">https://github.com/zadam/trilium</a></td>
|
<td><a href="https://github.com/zadam/trilium" class="external">https://github.com/zadam/trilium</a></td>
|
||||||
|
|||||||
Reference in New Issue
Block a user