mirror of
https://github.com/zadam/trilium.git
synced 2025-11-01 02:45:54 +01:00
Compare commits
49 Commits
v0.30.0-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 | ||
|
|
6f956c2415 | ||
|
|
3533160bef | ||
|
|
60cbfdcabd | ||
|
|
604f036a54 |
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"
|
||||
--name "$DEBIAN_X64_BUILD" \
|
||||
--file "dist/$DEBIAN_X64_BUILD"
|
||||
|
||||
echo "Uploading debian x64 package"
|
||||
echo "Uploading linux x64 build"
|
||||
|
||||
github-release upload \
|
||||
--tag $TAG \
|
||||
|
||||
BIN
db/demo.tar
BIN
db/demo.tar
Binary file not shown.
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;
|
||||
@@ -96,19 +96,6 @@ CREATE TABLE attributes
|
||||
hash TEXT default "" not null, isInheritable int DEFAULT 0 NULL);
|
||||
CREATE INDEX IDX_attributes_name_value
|
||||
on attributes (name, value);
|
||||
CREATE TABLE IF NOT EXISTS "notes" (
|
||||
`noteId` TEXT NOT NULL,
|
||||
`title` TEXT NOT NULL DEFAULT "note",
|
||||
`content` TEXT NULL DEFAULT NULL,
|
||||
`isProtected` INT NOT NULL DEFAULT 0,
|
||||
`type` TEXT NOT NULL DEFAULT 'text',
|
||||
`mime` TEXT NOT NULL DEFAULT 'text/html',
|
||||
`hash` TEXT DEFAULT "" NOT NULL,
|
||||
`isDeleted` INT NOT NULL DEFAULT 0,
|
||||
`dateCreated` TEXT NOT NULL,
|
||||
`dateModified` TEXT NOT NULL,
|
||||
PRIMARY KEY(`noteId`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "links" (
|
||||
`linkId` TEXT NOT NULL,
|
||||
`noteId` TEXT NOT NULL,
|
||||
@@ -130,3 +117,26 @@ CREATE INDEX IDX_attributes_noteId_index
|
||||
on attributes (noteId);
|
||||
CREATE INDEX IDX_attributes_value_index
|
||||
on attributes (value);
|
||||
CREATE TABLE IF NOT EXISTS "note_contents" (
|
||||
`noteContentId` TEXT NOT NULL,
|
||||
`noteId` TEXT NOT NULL,
|
||||
`isProtected` INT NOT NULL DEFAULT 0,
|
||||
`content` TEXT NULL DEFAULT NULL,
|
||||
`hash` TEXT DEFAULT "" NOT NULL,
|
||||
`dateCreated` TEXT NOT NULL,
|
||||
`dateModified` TEXT NOT NULL,
|
||||
PRIMARY KEY(`noteContentId`)
|
||||
);
|
||||
CREATE UNIQUE INDEX `IDX_note_contents_noteId` ON `note_contents` (`noteId`);
|
||||
CREATE TABLE IF NOT EXISTS "notes" (
|
||||
`noteId` TEXT NOT NULL,
|
||||
`title` TEXT NOT NULL DEFAULT "note",
|
||||
`isProtected` INT NOT NULL DEFAULT 0,
|
||||
`type` TEXT NOT NULL DEFAULT 'text',
|
||||
`mime` TEXT NOT NULL DEFAULT 'text/html',
|
||||
`hash` TEXT DEFAULT "" NOT NULL,
|
||||
`isDeleted` INT NOT NULL DEFAULT 0,
|
||||
`dateCreated` TEXT NOT NULL,
|
||||
`dateModified` TEXT NOT NULL,
|
||||
PRIMARY KEY(`noteId`)
|
||||
);
|
||||
|
||||
@@ -282,7 +282,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -724,7 +724,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -505,7 +505,7 @@ Each note can have multiple (at least one) branches, meaning it can be placed in
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -352,7 +352,7 @@ this is different concept than attribute/relation.</div>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
494
docs/backend_api/NoteContent.html
Normal file
494
docs/backend_api/NoteContent.html
Normal file
@@ -0,0 +1,494 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Class: NoteContent</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Class: NoteContent</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
<h2><span class="attribs"><span class="type-signature"></span></span>NoteContent<span class="signature">(row)</span><span class="type-signature"></span></h2>
|
||||
|
||||
<div class="class-description">This represents a Note which is a central object in the Trilium Notes project.</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Constructor</h2>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="NoteContent"><span class="type-signature"></span>new NoteContent<span class="signature">(row)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>row</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">object containing database row from "note_contents" table</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5 class="subsection-title">Properties:</h5>
|
||||
|
||||
|
||||
|
||||
<table class="props">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>noteContentId</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">primary key</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>noteId</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">reference to owning note</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>isProtected</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">boolean</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">true if note content is protected</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>content</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">blob</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">note content - e.g. HTML text for text notes, file payload for files</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>dateCreated</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>dateModified</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_content.js.html">entities/note_content.js</a>, <a href="entities_note_content.js.html#line20">line 20</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<h3 class="subsection-title">Extends</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
<ul>
|
||||
<li><a href="Entity.html">Entity</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="getNote"><span class="type-signature">(async) </span>getNote<span class="signature">()</span><span class="type-signature"> → {Promise.<<a href="Note.html">Note</a>>}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_content.js.html">entities/note_content.js</a>, <a href="entities_note_content.js.html#line63">line 63</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">Promise.<<a href="Note.html">Note</a>></span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -397,7 +397,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -305,7 +305,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -282,7 +282,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -69,7 +69,7 @@ module.exports = ApiToken;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -150,7 +150,7 @@ module.exports = Attribute;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -104,7 +104,7 @@ module.exports = Branch;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -36,7 +36,10 @@ class Entity {
|
||||
*/
|
||||
constructor(row = {}) {
|
||||
for (const key in row) {
|
||||
this[key] = row[key];
|
||||
// ! is used when joint-fetching notes and note_contents objects for performance
|
||||
if (!key.startsWith('!')) {
|
||||
this[key] = row[key];
|
||||
}
|
||||
}
|
||||
|
||||
if ('isDeleted' in this) {
|
||||
@@ -87,7 +90,7 @@ module.exports = Entity;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -86,7 +86,7 @@ module.exports = Link;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
const Entity = require('./entity');
|
||||
const Attribute = require('./attribute');
|
||||
const NoteContent = require('./note_content');
|
||||
const protectedSessionService = require('../services/protected_session');
|
||||
const repository = require('../services/repository');
|
||||
const sql = require('../services/sql');
|
||||
@@ -40,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.
|
||||
*
|
||||
@@ -47,7 +50,6 @@ const RELATION_DEFINITION = 'relation-definition';
|
||||
* @property {string} type - one of "text", "code", "file" or "render"
|
||||
* @property {string} mime - MIME type, e.g. "text/html"
|
||||
* @property {string} title - note title
|
||||
* @property {string} content - note content - e.g. HTML text for text notes, file payload for files
|
||||
* @property {boolean} isProtected - true if note is protected
|
||||
* @property {boolean} isDeleted - true if note is deleted
|
||||
* @property {string} dateCreated
|
||||
@@ -58,7 +60,7 @@ const RELATION_DEFINITION = 'relation-definition';
|
||||
class Note extends Entity {
|
||||
static get entityName() { return "notes"; }
|
||||
static get primaryKeyName() { return "noteId"; }
|
||||
static get hashedProperties() { return ["noteId", "title", "content", "type", "isProtected", "isDeleted"]; }
|
||||
static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted"]; }
|
||||
|
||||
/**
|
||||
* @param row - object containing database row from "notes" table
|
||||
@@ -75,19 +77,64 @@ class Note extends Entity {
|
||||
if (this.isProtected && this.noteId) {
|
||||
this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
|
||||
|
||||
protectedSessionService.decryptNote(this);
|
||||
if (this.isContentAvailable) {
|
||||
protectedSessionService.decryptNote(this);
|
||||
}
|
||||
else {
|
||||
// saving ciphertexts in case we do want to update protected note outside of protected session
|
||||
// (which is allowed)
|
||||
this.titleCipherText = this.title;
|
||||
this.title = "[protected]";
|
||||
}
|
||||
}
|
||||
|
||||
this.setContent(this.content);
|
||||
}
|
||||
|
||||
setContent(content) {
|
||||
this.content = content;
|
||||
/** @returns {Promise<NoteContent>} */
|
||||
async getNoteContent() {
|
||||
if (!this.noteContent) {
|
||||
this.noteContent = await repository.getEntity(`SELECT * FROM note_contents WHERE noteId = ?`, [this.noteId]);
|
||||
|
||||
try {
|
||||
this.jsonContent = JSON.parse(this.content);
|
||||
if (!this.noteContent) {
|
||||
throw new Error("Note content not found for noteId=" + this.noteId);
|
||||
}
|
||||
|
||||
if (this.isStringNote()) {
|
||||
this.noteContent.content = this.noteContent.content.toString("UTF-8");
|
||||
}
|
||||
}
|
||||
catch(e) {}
|
||||
|
||||
return this.noteContent;
|
||||
}
|
||||
|
||||
/** @returns {Promise<*>} */
|
||||
async getContent() {
|
||||
const noteContent = await this.getNoteContent();
|
||||
|
||||
return noteContent.content;
|
||||
}
|
||||
|
||||
/** @returns {Promise<*>} */
|
||||
async getJsonContent() {
|
||||
const content = await this.getContent();
|
||||
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
/** @returns {Promise} */
|
||||
async setContent(content) {
|
||||
if (!this.noteContent) {
|
||||
// make sure it is loaded
|
||||
await this.getNoteContent();
|
||||
}
|
||||
|
||||
this.noteContent.content = content;
|
||||
|
||||
await this.noteContent.save();
|
||||
}
|
||||
|
||||
/** @returns {Promise} */
|
||||
async setJsonContent(content) {
|
||||
await this.setContent(JSON.stringify(content, null, '\t'));
|
||||
}
|
||||
|
||||
/** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */
|
||||
@@ -113,6 +160,13 @@ class Note extends Entity {
|
||||
return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html";
|
||||
}
|
||||
|
||||
/** @returns {boolean} true if the note has string content (not binary) */
|
||||
isStringNote() {
|
||||
return ["text", "code", "relation-map", "search"].includes(this.type)
|
||||
|| this.mime.startsWith('text/')
|
||||
|| STRING_MIME_TYPES.includes(this.mime);
|
||||
}
|
||||
|
||||
/** @returns {string} JS script environment - either "frontend" or "backend" */
|
||||
getScriptEnv() {
|
||||
if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith('env=frontend'))) {
|
||||
@@ -629,13 +683,6 @@ class Note extends Entity {
|
||||
}
|
||||
|
||||
beforeSaving() {
|
||||
if (this.isJson() && this.jsonContent) {
|
||||
this.content = JSON.stringify(this.jsonContent, null, '\t');
|
||||
}
|
||||
|
||||
// we do this here because encryption needs the note ID for the IV
|
||||
this.generateIdIfNecessary();
|
||||
|
||||
if (!this.isDeleted) {
|
||||
this.isDeleted = false;
|
||||
}
|
||||
@@ -654,12 +701,19 @@ class Note extends Entity {
|
||||
// cannot be static!
|
||||
updatePojo(pojo) {
|
||||
if (pojo.isProtected) {
|
||||
protectedSessionService.encryptNote(pojo);
|
||||
if (this.isContentAvailable) {
|
||||
protectedSessionService.encryptNote(pojo);
|
||||
}
|
||||
else {
|
||||
// updating protected note outside of protected session means we will keep original ciphertexts
|
||||
pojo.title = pojo.titleCipherText;
|
||||
}
|
||||
}
|
||||
|
||||
delete pojo.jsonContent;
|
||||
delete pojo.isContentAvailable;
|
||||
delete pojo.__attributeCache;
|
||||
delete pojo.titleCipherText;
|
||||
delete pojo.noteContent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,7 +727,7 @@ module.exports = Note;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
146
docs/backend_api/entities_note_content.js.html
Normal file
146
docs/backend_api/entities_note_content.js.html
Normal file
@@ -0,0 +1,146 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: entities/note_content.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: entities/note_content.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>"use strict";
|
||||
|
||||
const Entity = require('./entity');
|
||||
const protectedSessionService = require('../services/protected_session');
|
||||
const repository = require('../services/repository');
|
||||
const dateUtils = require('../services/date_utils');
|
||||
|
||||
/**
|
||||
* This represents a Note which is a central object in the Trilium Notes project.
|
||||
*
|
||||
* @property {string} noteContentId - primary key
|
||||
* @property {string} noteId - reference to owning note
|
||||
* @property {boolean} isProtected - true if note content is protected
|
||||
* @property {blob} content - note content - e.g. HTML text for text notes, file payload for files
|
||||
* @property {string} dateCreated
|
||||
* @property {string} dateModified
|
||||
*
|
||||
* @extends Entity
|
||||
*/
|
||||
class NoteContent extends Entity {
|
||||
static get entityName() {
|
||||
return "note_contents";
|
||||
}
|
||||
|
||||
static get primaryKeyName() {
|
||||
return "noteContentId";
|
||||
}
|
||||
|
||||
static get hashedProperties() {
|
||||
return ["noteContentId", "noteId", "isProtected", "content"];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param row - object containing database row from "note_contents" table
|
||||
*/
|
||||
constructor(row) {
|
||||
super(row);
|
||||
|
||||
this.isProtected = !!this.isProtected;
|
||||
/* true if content (meaning any kind of potentially encrypted content) is either not encrypted
|
||||
* or encrypted, but with available protected session (so effectively decrypted) */
|
||||
this.isContentAvailable = true;
|
||||
|
||||
// check if there's noteContentId, otherwise this is a new entity which wasn't encrypted yet
|
||||
if (this.isProtected && this.noteContentId) {
|
||||
this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
|
||||
|
||||
if (this.isContentAvailable) {
|
||||
protectedSessionService.decryptNoteContent(this);
|
||||
}
|
||||
else {
|
||||
// saving ciphertexts in case we do want to update protected note outside of protected session
|
||||
// (which is allowed)
|
||||
this.contentCipherText = this.content;
|
||||
this.content = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<Note>}
|
||||
*/
|
||||
async getNote() {
|
||||
return await repository.getNote(this.noteId);
|
||||
}
|
||||
|
||||
beforeSaving() {
|
||||
if (!this.dateCreated) {
|
||||
this.dateCreated = dateUtils.nowDate();
|
||||
}
|
||||
|
||||
super.beforeSaving();
|
||||
|
||||
if (this.isChanged) {
|
||||
this.dateModified = dateUtils.nowDate();
|
||||
}
|
||||
}
|
||||
|
||||
// cannot be static!
|
||||
updatePojo(pojo) {
|
||||
if (pojo.isProtected) {
|
||||
if (this.isContentAvailable) {
|
||||
protectedSessionService.encryptNoteContent(pojo);
|
||||
}
|
||||
else {
|
||||
// updating protected note outside of protected session means we will keep original ciphertext
|
||||
pojo.content = pojo.contentCipherText;
|
||||
}
|
||||
}
|
||||
|
||||
delete pojo.isContentAvailable;
|
||||
delete pojo.contentCipherText;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NoteContent;</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -85,7 +85,7 @@ module.exports = NoteRevision;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -72,7 +72,7 @@ module.exports = Option;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -69,7 +69,7 @@ module.exports = RecentNote;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line144">line 144</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line149">line 149</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -558,7 +558,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line151">line 151</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line156">line 156</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -588,7 +588,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -39,6 +39,7 @@ const repository = require('./repository');
|
||||
const axios = require('axios');
|
||||
const cloningService = require('./cloning');
|
||||
const messagingService = require('./messaging');
|
||||
const appInfo = require('./app_info');
|
||||
|
||||
/**
|
||||
* This is the main backend API interface for scripts. It's published in the local "api" object.
|
||||
@@ -46,13 +47,17 @@ const messagingService = require('./messaging');
|
||||
* @constructor
|
||||
* @hideconstructor
|
||||
*/
|
||||
function BackendScriptApi(startNote, currentNote, originEntity) {
|
||||
function BackendScriptApi(currentNote, apiParams) {
|
||||
/** @property {Note} note where script started executing */
|
||||
this.startNote = startNote;
|
||||
this.startNote = apiParams.startNote;
|
||||
/** @property {Note} note where script is currently executing */
|
||||
this.currentNote = currentNote;
|
||||
/** @property {Entity} entity whose event triggered this executions */
|
||||
this.originEntity = originEntity;
|
||||
this.originEntity = apiParams.originEntity;
|
||||
|
||||
for (const key in apiParams) {
|
||||
this[key] = apiParams[key];
|
||||
}
|
||||
|
||||
this.axios = axios;
|
||||
|
||||
@@ -196,6 +201,23 @@ function BackendScriptApi(startNote, currentNote, originEntity) {
|
||||
*/
|
||||
this.createNote = noteService.createNote;
|
||||
|
||||
/**
|
||||
* Creates new note according to given params and force all connected clients to refresh their tree.
|
||||
*
|
||||
* @method
|
||||
*
|
||||
* @param {string} parentNoteId - create new note under this parent
|
||||
* @param {string} title
|
||||
* @param {string} [content=""]
|
||||
* @param {CreateNoteExtraOptions} [extraOptions={}]
|
||||
* @returns {Promise<{note: Note, branch: Branch}>} object contains newly created entities note and branch
|
||||
*/
|
||||
this.createNoteAndRefresh = async function(parentNoteId, title, content, extraOptions) {
|
||||
await noteService.createNote(parentNoteId, title, content, extraOptions);
|
||||
|
||||
messagingService.refreshTree();
|
||||
};
|
||||
|
||||
/**
|
||||
* Log given message to trilium logs.
|
||||
*
|
||||
@@ -212,14 +234,42 @@ function BackendScriptApi(startNote, currentNote, originEntity) {
|
||||
this.getRootCalendarNote = dateNoteService.getRootCalendarNote;
|
||||
|
||||
/**
|
||||
* Returns day note for given date (YYYY-MM-DD format). If such note doesn't exist, it is created.
|
||||
* Returns day note for given date. If such note doesn't exist, it is created.
|
||||
*
|
||||
* @method
|
||||
* @param {string} date
|
||||
* @param {string} date in YYYY-MM-DD format
|
||||
* @returns {Promise<Note|null>}
|
||||
*/
|
||||
this.getDateNote = dateNoteService.getDateNote;
|
||||
|
||||
/**
|
||||
* Returns note for the first date of the week of the given date.
|
||||
*
|
||||
* @method
|
||||
* @param {string} date in YYYY-MM-DD format
|
||||
* @param {object} options - "startOfTheWeek" - either "monday" (default) or "sunday"
|
||||
* @returns {Promise<Note|null>}
|
||||
*/
|
||||
this.getWeekNote = dateNoteService.getWeekNote;
|
||||
|
||||
/**
|
||||
* Returns month note for given date. If such note doesn't exist, it is created.
|
||||
*
|
||||
* @method
|
||||
* @param {string} date in YYYY-MM format
|
||||
* @returns {Promise<Note|null>}
|
||||
*/
|
||||
this.getMonthNote = dateNoteService.getMonthNote;
|
||||
|
||||
/**
|
||||
* Returns year note for given year. If such note doesn't exist, it is created.
|
||||
*
|
||||
* @method
|
||||
* @param {string} year in YYYY format
|
||||
* @returns {Promise<Note|null>}
|
||||
*/
|
||||
this.getYearNote = dateNoteService.getYearNote;
|
||||
|
||||
/**
|
||||
* @method
|
||||
* @param {string} parentNoteId - this note's child notes will be sorted
|
||||
@@ -261,7 +311,12 @@ function BackendScriptApi(startNote, currentNote, originEntity) {
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
this.refreshTree = () => messagingService.sendMessageToAllClients({ type: 'refresh-tree' });
|
||||
this.refreshTree = messagingService.refreshTree;
|
||||
|
||||
/**
|
||||
* @return {{syncVersion, appVersion, buildRevision, dbVersion, dataDirectory, buildDate}|*} - object representing basic info about running Trilium version
|
||||
*/
|
||||
this.getAppInfo = () => appInfo
|
||||
}
|
||||
|
||||
module.exports = BackendScriptApi;</code></pre>
|
||||
@@ -274,7 +329,7 @@ module.exports = BackendScriptApi;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ApiToken.html">ApiToken</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="Entity.html">Entity</a></li><li><a href="Link.html">Link</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteContent.html">NoteContent</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -81,7 +81,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#line17">line 17</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line18">line 18</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -221,7 +221,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#line23">line 23</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line24">line 24</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -334,7 +334,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#line25">line 25</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line26">line 26</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -444,7 +444,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#line21">line 21</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line22">line 22</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -573,7 +573,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#line42">line 42</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line43">line 43</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -726,7 +726,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#line34">line 34</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line35">line 35</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -879,7 +879,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#line61">line 61</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line62">line 62</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1057,7 +1057,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#line198">line 198</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line199">line 199</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1188,7 +1188,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#line158">line 158</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line159">line 159</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1244,6 +1244,214 @@
|
||||
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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#line211">line 211</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
active note (loaded into right pane)
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type"><a href="NoteFull.html">NoteFull</a></span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="getActiveNoteContent"><span class="type-signature"></span>getActiveNoteContent<span class="signature">()</span><span class="type-signature"> → {string}</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#line205">line 205</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
content of active note (loaded into right pane)
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="getCodeMimeTypes"><span class="type-signature"></span>getCodeMimeTypes<span class="signature">()</span><span class="type-signature"> → {array}</span></h4>
|
||||
|
||||
|
||||
@@ -1292,7 +1500,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#line222">line 222</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line242">line 242</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1348,110 +1556,6 @@
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="getCurrentNoteContent"><span class="type-signature"></span>getCurrentNoteContent<span class="signature">()</span><span class="type-signature"> → {string}</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#line204">line 204</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
content of currently loaded note in the editor (HTML, code etc.)
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">string</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#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#line236">line 236</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1609,7 +1713,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<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#line151">line 151</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line152">line 152</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1808,7 +1912,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<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#line143">line 143</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line144">line 144</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1860,6 +1964,117 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="isNoteStillActive"><span class="type-signature"></span>isNoteStillActive<span class="signature">()</span><span class="type-signature"> → {boolean}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
This method checks whether user navigated away from the note from which the scripts has been started.
|
||||
This is necessary because script execution is async and by the time it is finished, the user might have
|
||||
already navigated away from this page - the end result would be that script might return data for the wrong
|
||||
note.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line222">line 222</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
returns true if the original note is still loaded, false if user switched to another
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">boolean</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="onNoteChange"><span class="type-signature"></span>onNoteChange<span class="signature">(func)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
@@ -1957,7 +2172,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<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#line210">line 210</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>
|
||||
|
||||
|
||||
@@ -2088,7 +2303,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<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#line165">line 165</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line166">line 166</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2140,6 +2355,88 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="protectActiveNote"><span class="type-signature"></span>protectActiveNote<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line259">line 259</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2196,7 +2493,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<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#line189">line 189</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line190">line 190</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2373,7 +2670,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#line111">line 111</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line112">line 112</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2526,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#line228">line 228</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>
|
||||
|
||||
|
||||
@@ -2657,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#line234">line 234</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>
|
||||
|
||||
|
||||
@@ -2792,7 +3089,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#line181">line 181</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line182">line 182</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2927,7 +3224,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#line173">line 173</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line174">line 174</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -141,7 +141,123 @@
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="content"><span class="type-signature"></span>content<span class="type-signature"></span></h4>
|
||||
<h4 class="name" id="dateCreated"><span class="type-signature"></span>dateCreated<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line14">line 14</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="dateModified"><span class="type-signature"></span>dateModified<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line17">line 17</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="noteContent"><span class="type-signature"></span>noteContent<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
@@ -198,64 +314,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="jsonContent"><span class="type-signature"></span>jsonContent<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line16">line 16</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -59,7 +59,9 @@
|
||||
get toString() {
|
||||
return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name})`;
|
||||
}
|
||||
}</code></pre>
|
||||
}
|
||||
|
||||
export default Attribute;</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -36,15 +36,13 @@ class NoteFull extends NoteShort {
|
||||
super(treeCache, row);
|
||||
|
||||
/** @param {string} */
|
||||
this.content = row.content;
|
||||
this.noteContent = row.noteContent;
|
||||
|
||||
if (this.content !== "" && this.isJson()) {
|
||||
try {
|
||||
/** @param {object} */
|
||||
this.jsonContent = JSON.parse(this.content);
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
/** @param {string} */
|
||||
this.dateCreated = row.dateCreated;
|
||||
|
||||
/** @param {string} */
|
||||
this.dateModified = row.dateModified;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -303,7 +303,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#line48">line 48</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line49">line 49</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import treeCache from './tree_cache.js';
|
||||
import noteDetailService from './note_detail.js';
|
||||
import noteTypeService from './note_type.js';
|
||||
import noteTooltipService from './note_tooltip.js';
|
||||
import protectedSessionService from'./protected_session.js';
|
||||
|
||||
/**
|
||||
* This is the main frontend API interface for scripts. It's published in the local "api" object.
|
||||
@@ -70,7 +71,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
|
||||
this.activateNewNote = async notePath => {
|
||||
await treeService.reload();
|
||||
|
||||
await treeService.activateNote(notePath, true);
|
||||
await treeService.activateNote(notePath, noteDetailService.focusAndSelectTitle);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -227,9 +228,28 @@ 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.
|
||||
* This is necessary because script execution is async and by the time it is finished, the user might have
|
||||
* already navigated away from this page - the end result would be that script might return data for the wrong
|
||||
* note.
|
||||
*
|
||||
* @method
|
||||
* @return {boolean} returns true if the original note is still loaded, false if user switched to another
|
||||
*/
|
||||
this.isNoteStillActive = () => {
|
||||
return this.originEntity.noteId === noteDetailService.getCurrentNoteId();
|
||||
};
|
||||
|
||||
/**
|
||||
* @method
|
||||
@@ -259,7 +279,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
|
||||
* @method
|
||||
* @param {object} $el - jquery object on which to setup the tooltip
|
||||
*/
|
||||
this.setupElementTooltip = noteTooltipService.setupElementTooltip
|
||||
this.setupElementTooltip = noteTooltipService.setupElementTooltip;
|
||||
|
||||
/**
|
||||
* @method
|
||||
*/
|
||||
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.29.1",
|
||||
"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.0-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,
|
||||
|
||||
@@ -5,60 +5,23 @@ const enexImportService = require('../../services/import/enex');
|
||||
const opmlImportService = require('../../services/import/opml');
|
||||
const tarImportService = require('../../services/import/tar');
|
||||
const singleImportService = require('../../services/import/single');
|
||||
const messagingService = require('../../services/messaging');
|
||||
const cls = require('../../services/cls');
|
||||
const path = require('path');
|
||||
const noteCacheService = require('../../services/note_cache');
|
||||
const log = require('../../services/log');
|
||||
|
||||
class ImportContext {
|
||||
constructor(importId, safeImport) {
|
||||
// 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;
|
||||
|
||||
// // 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();
|
||||
}
|
||||
|
||||
async increaseProgressCount() {
|
||||
this.progressCount++;
|
||||
|
||||
if (Date.now() - this.lastSentCountTs >= 500) {
|
||||
this.lastSentCountTs = Date.now();
|
||||
|
||||
await messagingService.sendMessageToAllClients({
|
||||
importId: this.importId,
|
||||
type: 'import-progress-count',
|
||||
progressCount: this.progressCount
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async importFinished(noteId) {
|
||||
await messagingService.sendMessageToAllClients({
|
||||
importId: this.importId,
|
||||
type: 'import-finished',
|
||||
noteId: noteId
|
||||
});
|
||||
}
|
||||
|
||||
// must remaing non-static
|
||||
async reportError(message) {
|
||||
await messagingService.sendMessageToAllClients({
|
||||
type: 'import-error',
|
||||
message: message
|
||||
});
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -80,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-20T21:58:31+01:00", buildRevision: "ff67b8a0ba9c37827b3d3f1e68121bbf28c80393" };
|
||||
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
|
||||
};
|
||||
@@ -13,9 +13,8 @@ const stream = require('stream');
|
||||
const path = require('path');
|
||||
const commonmark = require('commonmark');
|
||||
const mimeTypes = require('mime-types');
|
||||
|
||||
let importNoteCount;
|
||||
let lastSentCountTs = Date.now();
|
||||
const ImportContext = require('../import_context');
|
||||
const protectedSessionService = require('../protected_session');
|
||||
|
||||
/**
|
||||
* @param {ImportContext} importContext
|
||||
@@ -24,7 +23,6 @@ let lastSentCountTs = Date.now();
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
async function importTar(importContext, fileBuffer, importRootNote) {
|
||||
importNoteCount = 0;
|
||||
// maps from original noteId (in tar file) to newly generated noteId
|
||||
const noteIdMap = {};
|
||||
const attributes = [];
|
||||
@@ -135,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/')) {
|
||||
@@ -196,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);
|
||||
@@ -252,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);
|
||||
}
|
||||
@@ -274,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);
|
||||
@@ -387,8 +387,6 @@ async function importTar(importContext, fileBuffer, importRootNote) {
|
||||
}
|
||||
}
|
||||
|
||||
importContext.importFinished();
|
||||
|
||||
resolve(firstNote);
|
||||
});
|
||||
|
||||
|
||||
56
src/services/import_context.js
Normal file
56
src/services/import_context.js
Normal file
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
|
||||
const messagingService = require('./messaging');
|
||||
|
||||
// importId => ImportContext
|
||||
const importContexts = {};
|
||||
|
||||
class ImportContext {
|
||||
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 = 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++;
|
||||
|
||||
if (Date.now() - this.lastSentCountTs >= 500) {
|
||||
this.lastSentCountTs = Date.now();
|
||||
|
||||
await messagingService.sendMessageToAllClients({
|
||||
importId: this.importId,
|
||||
type: 'import-progress-count',
|
||||
progressCount: this.progressCount
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// must remaing non-static
|
||||
async reportError(message) {
|
||||
await messagingService.sendMessageToAllClients({
|
||||
type: 'import-error',
|
||||
message: message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ImportContext;
|
||||
@@ -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});
|
||||
@@ -77,16 +78,21 @@ async function createInitialDatabase(username, password) {
|
||||
await sql.executeScript(schema);
|
||||
|
||||
const Note = require("../entities/note");
|
||||
const NoteContent = require("../entities/note_content");
|
||||
const Branch = require("../entities/branch");
|
||||
|
||||
const rootNote = await new Note({
|
||||
noteId: 'root',
|
||||
title: 'root',
|
||||
content: '',
|
||||
type: 'text',
|
||||
mime: 'text/html'
|
||||
}).save();
|
||||
|
||||
const rootNoteContent = await new NoteContent({
|
||||
noteId: rootNote.noteId,
|
||||
content: ''
|
||||
}).save();
|
||||
|
||||
await new Branch({
|
||||
branchId: 'root',
|
||||
noteId: 'root',
|
||||
@@ -95,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(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