Compare commits

..

48 Commits

Author SHA1 Message Date
zadam a79a063d17 release 0.40.0-beta 2020-01-11 09:54:31 +01:00
zadam 5e91b1b5e0 package updates 2020-01-11 09:50:05 +01:00
zadam 7877443fb4 Merge branch 'stable' 2020-01-11 09:41:42 +01:00
zadam 759e47bfcf using included note should create a relation, closes #820 2020-01-10 21:41:00 +01:00
zadam 67bdffb27b expose text editor instance and method to add text to editor, closes #819 2020-01-10 20:10:17 +01:00
zadam 3386dace3b provide context menu in text editor also with disabled spellcheck 2020-01-10 19:56:27 +01:00
zadam f3a2e2cbde Merge branch 'stable' 2020-01-08 21:39:17 +01:00
zadam 3cf3fc13b9 release 0.39.5 2020-01-08 21:01:24 +01:00
zadam 2b69abf8ab fix filter parser for >=, <=, *=* 2020-01-08 20:23:41 +01:00
zadam 3e49a7dbfa all consistency checkers have now fixers 2020-01-08 19:28:22 +01:00
zadam 4c7c3105e8 Merge branch 'stable'
# Conflicts:
#	src/services/notes.js
2020-01-07 22:29:54 +01:00
zadam f782d2bef9 don't empty script area on save 2020-01-07 22:29:15 +01:00
zadam ccaa9eae3a fix context submenus, closes #810 2020-01-07 20:53:41 +01:00
zadam 24c5388e0c protection against text note initialization race conditions 2020-01-07 19:48:26 +01:00
zadam 1cd2711097 Merge branch 'stable' 2020-01-05 20:02:19 +01:00
zadam f0dfe7d552 release 0.39.4 2020-01-04 22:01:20 +01:00
zadam 3b8b4da149 task context progress fixes 2020-01-04 21:59:28 +01:00
zadam 2150619d62 activateNewNote does not reload whole tree anymore 2020-01-04 21:53:49 +01:00
zadam acb76e0630 added notification to empty book notes otherwise they look suspiciously empty 2020-01-04 21:24:39 +01:00
zadam fdb46f9329 fallback image saving without optimization will still compress image 2020-01-04 20:10:30 +01:00
zadam ca587cccf6 book note type has automatically empty mime type 2020-01-04 19:34:01 +01:00
zadam 571772069a force SQLite to choose particular index for attribute search since it sometimes led to very inefficient query plans 2020-01-04 19:22:16 +01:00
zadam 79e7762c72 indent data notes 2020-01-04 18:44:54 +01:00
zadam d025cfee1b empty note with just included note should be saved, closes #807 2020-01-04 13:22:07 +01:00
zadam 7793552443 fix display of show sidebar button 2020-01-04 10:05:03 +01:00
zadam f377a84fa1 hide/show button z-index tweak 2020-01-04 09:21:42 +01:00
zadam b8f2797abf better behavior of note info widget in tight width 2020-01-04 09:04:08 +01:00
zadam 54d89a9f47 allow configuring the time period before deleted notes are erased (and changed the default to 7 days) 2020-01-03 22:32:49 +01:00
zadam 1699646b39 fix undelete info messages 2020-01-03 21:32:41 +01:00
zadam 94a0a31f17 refactoring of tree handling to recommended fancytree 2020-01-03 21:15:45 +01:00
zadam 10219fb9dd Merge branch 'stable' 2020-01-03 20:13:13 +01:00
zadam 50431dd55a hide "show/hide sidebar" button in zen mode, fixes #805 2020-01-03 20:12:19 +01:00
zadam 17b23d92ef delete/undelete fixes 2020-01-03 13:41:44 +01:00
zadam 14f3c783f2 undelete note WIP 2020-01-03 13:14:43 +01:00
zadam c1d0a1e07b undelete note WIP 2020-01-03 10:48:36 +01:00
zadam 1d3608b7bf fix recent note dialog for deleted notes 2020-01-03 09:04:38 +01:00
zadam d0c655f66a fix removeAttribute to take into account attribute name, closes #804 2020-01-03 08:55:13 +01:00
zadam ac75fd2ca3 focus and activate should work together 2020-01-02 19:07:50 +01:00
zadam 3b98428c8c change order of execution to mitigate race conditions 2020-01-02 19:03:54 +01:00
zadam 7d877d0fef release 0.39.3 2020-01-02 10:43:41 +01:00
zadam cb79f2c7eb updated ckeditor build to support cuttonote 2020-01-02 10:38:29 +01:00
zadam 547a5714ae fancytree 2.34.0 2020-01-01 23:13:49 +01:00
zadam 82420fe5f6 reactivate "cut to note", closes #795 2020-01-01 22:59:51 +01:00
zadam 395913d1bb API docs update 2020-01-01 22:03:27 +01:00
zadam f3a29b55ba remove @child:child:sorted label from calendar root in demo document since currently @sorted is added automatically in the code, closes #799 2020-01-01 20:58:59 +01:00
zadam 232321f3a4 fix searching multi-valued attributes, closes #800 2020-01-01 20:49:26 +01:00
zadam 51dddb0bbb fix scrolling behavior in firefox 2020-01-01 19:57:57 +01:00
zadam 8b9bf6e46f expand to note to be able to activate note 2020-01-01 19:46:27 +01:00
65 changed files with 1569 additions and 827 deletions
+164 -119
View File
@@ -2,7 +2,7 @@
<dataSource name="document.db">
<database-model serializer="dbm" dbms="SQLITE" family-id="SQLITE" format-version="4.17">
<root id="1">
<ServerVersion>3.16.1</ServerVersion>
<ServerVersion>3.25.1</ServerVersion>
</root>
<schema id="2" parent="1" name="main">
<Current>1</Current>
@@ -57,6 +57,7 @@
<index id="24" parent="6" name="sqlite_autoindex_api_tokens_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>apiTokenId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="25" parent="6">
@@ -111,529 +112,573 @@
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="35" parent="7" name="hash">
<column id="35" parent="7" name="deleteId">
<Position>10</Position>
<DataType>TEXT|0s</DataType>
<DefaultExpression>NULL</DefaultExpression>
</column>
<column id="36" parent="7" name="hash">
<Position>11</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="36" parent="7" name="isInheritable">
<Position>11</Position>
<column id="37" parent="7" name="isInheritable">
<Position>12</Position>
<DataType>int|0s</DataType>
<DefaultExpression>0</DefaultExpression>
</column>
<index id="37" parent="7" name="sqlite_autoindex_attributes_1">
<index id="38" parent="7" name="sqlite_autoindex_attributes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>attributeId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="38" parent="7" name="IDX_attributes_noteId_index">
<index id="39" parent="7" name="IDX_attributes_noteId_index">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="39" parent="7" name="IDX_attributes_name_value">
<index id="40" parent="7" name="IDX_attributes_name_value">
<ColNames>name
value</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="40" parent="7" name="IDX_attributes_value_index">
<index id="41" parent="7" name="IDX_attributes_value_index">
<ColNames>value</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="41" parent="7">
<key id="42" parent="7">
<ColNames>attributeId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_attributes_1</UnderlyingIndexName>
</key>
<column id="42" parent="8" name="branchId">
<column id="43" parent="8" name="branchId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="43" parent="8" name="noteId">
<column id="44" parent="8" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="44" parent="8" name="parentNoteId">
<column id="45" parent="8" name="parentNoteId">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="45" parent="8" name="notePosition">
<column id="46" parent="8" name="notePosition">
<Position>4</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="46" parent="8" name="prefix">
<column id="47" parent="8" name="prefix">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="47" parent="8" name="isExpanded">
<column id="48" parent="8" name="isExpanded">
<Position>6</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="48" parent="8" name="isDeleted">
<column id="49" parent="8" name="isDeleted">
<Position>7</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="49" parent="8" name="utcDateModified">
<column id="50" parent="8" name="deleteId">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>NULL</DefaultExpression>
</column>
<column id="50" parent="8" name="utcDateCreated">
<column id="51" parent="8" name="utcDateModified">
<Position>9</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="51" parent="8" name="hash">
<column id="52" parent="8" name="utcDateCreated">
<Position>10</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="53" parent="8" name="hash">
<Position>11</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<index id="52" parent="8" name="sqlite_autoindex_branches_1">
<index id="54" parent="8" name="sqlite_autoindex_branches_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>branchId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="53" parent="8" name="IDX_branches_noteId_parentNoteId">
<index id="55" parent="8" name="IDX_branches_noteId_parentNoteId">
<ColNames>noteId
parentNoteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="54" parent="8" name="IDX_branches_parentNoteId">
<index id="56" parent="8" name="IDX_branches_parentNoteId">
<ColNames>parentNoteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="55" parent="8">
<key id="57" parent="8">
<ColNames>branchId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName>
</key>
<column id="56" parent="9" name="noteId">
<column id="58" parent="9" name="noteId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="57" parent="9" name="content">
<column id="59" parent="9" name="content">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<DefaultExpression>NULL</DefaultExpression>
</column>
<column id="58" parent="9" name="hash">
<column id="60" parent="9" name="hash">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="59" parent="9" name="utcDateModified">
<column id="61" parent="9" name="utcDateModified">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="60" parent="9" name="sqlite_autoindex_note_contents_1">
<index id="62" parent="9" name="sqlite_autoindex_note_contents_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="61" parent="9">
<key id="63" parent="9">
<ColNames>noteId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_contents_1</UnderlyingIndexName>
</key>
<column id="62" parent="10" name="noteRevisionId">
<column id="64" parent="10" name="noteRevisionId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="63" parent="10" name="content">
<column id="65" parent="10" name="content">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="64" parent="10" name="hash">
<column id="66" parent="10" name="hash">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<column id="65" parent="10" name="utcDateModified">
<column id="67" parent="10" name="utcDateModified">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="66" parent="10" name="sqlite_autoindex_note_revision_contents_1">
<index id="68" parent="10" name="sqlite_autoindex_note_revision_contents_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteRevisionId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="67" parent="10">
<key id="69" parent="10">
<ColNames>noteRevisionId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_revision_contents_1</UnderlyingIndexName>
</key>
<column id="68" parent="11" name="noteRevisionId">
<column id="70" parent="11" name="noteRevisionId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="69" parent="11" name="noteId">
<column id="71" parent="11" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="70" parent="11" name="title">
<column id="72" parent="11" name="title">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="71" parent="11" name="contentLength">
<column id="73" parent="11" name="contentLength">
<Position>4</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="72" parent="11" name="isErased">
<column id="74" parent="11" name="isErased">
<Position>5</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="73" parent="11" name="isProtected">
<column id="75" parent="11" name="isProtected">
<Position>6</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="74" parent="11" name="utcDateLastEdited">
<column id="76" parent="11" name="utcDateLastEdited">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="75" parent="11" name="utcDateCreated">
<column id="77" parent="11" name="utcDateCreated">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="76" parent="11" name="utcDateModified">
<column id="78" parent="11" name="utcDateModified">
<Position>9</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="77" parent="11" name="dateLastEdited">
<column id="79" parent="11" name="dateLastEdited">
<Position>10</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="78" parent="11" name="dateCreated">
<column id="80" parent="11" name="dateCreated">
<Position>11</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="79" parent="11" name="type">
<column id="81" parent="11" name="type">
<Position>12</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<column id="80" parent="11" name="mime">
<column id="82" parent="11" name="mime">
<Position>13</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<column id="81" parent="11" name="hash">
<column id="83" parent="11" name="hash">
<Position>14</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<index id="82" parent="11" name="sqlite_autoindex_note_revisions_1">
<index id="84" parent="11" name="sqlite_autoindex_note_revisions_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteRevisionId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="83" parent="11" name="IDX_note_revisions_noteId">
<index id="85" parent="11" name="IDX_note_revisions_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="84" parent="11" name="IDX_note_revisions_utcDateLastEdited">
<index id="86" parent="11" name="IDX_note_revisions_utcDateLastEdited">
<ColNames>utcDateLastEdited</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="85" parent="11" name="IDX_note_revisions_utcDateCreated">
<index id="87" parent="11" name="IDX_note_revisions_utcDateCreated">
<ColNames>utcDateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="86" parent="11" name="IDX_note_revisions_dateLastEdited">
<index id="88" parent="11" name="IDX_note_revisions_dateLastEdited">
<ColNames>dateLastEdited</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="87" parent="11" name="IDX_note_revisions_dateCreated">
<index id="89" parent="11" name="IDX_note_revisions_dateCreated">
<ColNames>dateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="88" parent="11">
<key id="90" parent="11">
<ColNames>noteRevisionId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
</key>
<column id="89" parent="12" name="noteId">
<column id="91" parent="12" name="noteId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="90" parent="12" name="title">
<column id="92" parent="12" name="title">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;note&quot;</DefaultExpression>
</column>
<column id="91" parent="12" name="contentLength">
<column id="93" parent="12" name="contentLength">
<Position>3</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="92" parent="12" name="isProtected">
<column id="94" parent="12" name="isProtected">
<Position>4</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="93" parent="12" name="type">
<column id="95" parent="12" name="type">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;text&apos;</DefaultExpression>
</column>
<column id="94" parent="12" name="mime">
<column id="96" parent="12" name="mime">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;text/html&apos;</DefaultExpression>
</column>
<column id="95" parent="12" name="hash">
<column id="97" parent="12" name="hash">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="96" parent="12" name="isDeleted">
<column id="98" parent="12" name="isDeleted">
<Position>8</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="97" parent="12" name="isErased">
<column id="99" parent="12" name="deleteId">
<Position>9</Position>
<DataType>TEXT|0s</DataType>
<DefaultExpression>NULL</DefaultExpression>
</column>
<column id="100" parent="12" name="isErased">
<Position>10</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="98" parent="12" name="dateCreated">
<Position>10</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="99" parent="12" name="dateModified">
<column id="101" parent="12" name="dateCreated">
<Position>11</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="100" parent="12" name="utcDateCreated">
<column id="102" parent="12" name="dateModified">
<Position>12</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="101" parent="12" name="utcDateModified">
<column id="103" parent="12" name="utcDateCreated">
<Position>13</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="102" parent="12" name="sqlite_autoindex_notes_1">
<column id="104" parent="12" name="utcDateModified">
<Position>14</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="105" parent="12" name="sqlite_autoindex_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="103" parent="12" name="IDX_notes_title">
<index id="106" parent="12" name="IDX_notes_title">
<ColNames>title</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="104" parent="12" name="IDX_notes_type">
<index id="107" parent="12" name="IDX_notes_type">
<ColNames>type</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="105" parent="12" name="IDX_notes_isDeleted">
<index id="108" parent="12" name="IDX_notes_isDeleted">
<ColNames>isDeleted</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="106" parent="12" name="IDX_notes_dateCreated">
<index id="109" parent="12" name="IDX_notes_dateCreated">
<ColNames>dateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="107" parent="12" name="IDX_notes_dateModified">
<index id="110" parent="12" name="IDX_notes_dateModified">
<ColNames>dateModified</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="108" parent="12" name="IDX_notes_utcDateCreated">
<index id="111" parent="12" name="IDX_notes_utcDateCreated">
<ColNames>utcDateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="109" parent="12" name="IDX_notes_utcDateModified">
<index id="112" parent="12" name="IDX_notes_utcDateModified">
<ColNames>utcDateModified</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="110" parent="12">
<key id="113" parent="12">
<ColNames>noteId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
</key>
<column id="111" parent="13" name="name">
<column id="114" parent="13" name="name">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="112" parent="13" name="value">
<column id="115" parent="13" name="value">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="113" parent="13" name="isSynced">
<column id="116" parent="13" name="isSynced">
<Position>3</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="114" parent="13" name="hash">
<column id="117" parent="13" name="hash">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="115" parent="13" name="utcDateCreated">
<column id="118" parent="13" name="utcDateCreated">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="116" parent="13" name="utcDateModified">
<column id="119" parent="13" name="utcDateModified">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="117" parent="13" name="sqlite_autoindex_options_1">
<index id="120" parent="13" name="sqlite_autoindex_options_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>name</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="118" parent="13">
<key id="121" parent="13">
<ColNames>name</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
</key>
<column id="119" parent="14" name="noteId">
<column id="122" parent="14" name="noteId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="120" parent="14" name="notePath">
<column id="123" parent="14" name="notePath">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="121" parent="14" name="hash">
<column id="124" parent="14" name="hash">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="122" parent="14" name="utcDateCreated">
<column id="125" parent="14" name="utcDateCreated">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="123" parent="14" name="isDeleted">
<column id="126" parent="14" name="isDeleted">
<Position>5</Position>
<DataType>INT|0s</DataType>
</column>
<index id="124" parent="14" name="sqlite_autoindex_recent_notes_1">
<index id="127" parent="14" name="sqlite_autoindex_recent_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="125" parent="14">
<key id="128" parent="14">
<ColNames>noteId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
</key>
<column id="126" parent="15" name="sourceId">
<column id="129" parent="15" name="sourceId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="127" parent="15" name="utcDateCreated">
<column id="130" parent="15" name="utcDateCreated">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="128" parent="15" name="sqlite_autoindex_source_ids_1">
<index id="131" parent="15" name="sqlite_autoindex_source_ids_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>sourceId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="129" parent="15" name="IDX_source_ids_utcDateCreated">
<index id="132" parent="15" name="IDX_source_ids_utcDateCreated">
<ColNames>utcDateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="130" parent="15">
<key id="133" parent="15">
<ColNames>sourceId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
</key>
<column id="131" parent="16" name="type">
<column id="134" parent="16" name="type">
<Position>1</Position>
<DataType>text|0s</DataType>
</column>
<column id="132" parent="16" name="name">
<column id="135" parent="16" name="name">
<Position>2</Position>
<DataType>text|0s</DataType>
</column>
<column id="133" parent="16" name="tbl_name">
<column id="136" parent="16" name="tbl_name">
<Position>3</Position>
<DataType>text|0s</DataType>
</column>
<column id="134" parent="16" name="rootpage">
<column id="137" parent="16" name="rootpage">
<Position>4</Position>
<DataType>integer|0s</DataType>
<DataType>int|0s</DataType>
</column>
<column id="135" parent="16" name="sql">
<column id="138" parent="16" name="sql">
<Position>5</Position>
<DataType>text|0s</DataType>
</column>
<column id="136" parent="17" name="name">
<column id="139" parent="17" name="name">
<Position>1</Position>
</column>
<column id="137" parent="17" name="seq">
<column id="140" parent="17" name="seq">
<Position>2</Position>
</column>
<column id="138" parent="18" name="id">
<column id="141" parent="18" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<SequenceIdentity>1</SequenceIdentity>
</column>
<column id="139" parent="18" name="entityName">
<column id="142" parent="18" name="entityName">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="140" parent="18" name="entityId">
<column id="143" parent="18" name="entityId">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="141" parent="18" name="sourceId">
<column id="144" parent="18" name="sourceId">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="142" parent="18" name="utcSyncDate">
<column id="145" parent="18" name="utcSyncDate">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="143" parent="18" name="IDX_sync_entityName_entityId">
<index id="146" parent="18" name="IDX_sync_entityName_entityId">
<ColNames>entityName
entityId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="144" parent="18" name="IDX_sync_utcSyncDate">
<index id="147" parent="18" name="IDX_sync_utcSyncDate">
<ColNames>utcSyncDate</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="145" parent="18">
<key id="148" parent="18">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
BIN
View File
Binary file not shown.
+81
View File
@@ -0,0 +1,81 @@
CREATE TABLE IF NOT EXISTS "notes_mig" (
`noteId` TEXT NOT NULL,
`title` TEXT NOT NULL DEFAULT "note",
`contentLength` INT NOT 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,
`deleteId` TEXT DEFAULT NULL,
`isErased` INT NOT NULL DEFAULT 0,
`dateCreated` TEXT NOT NULL,
`dateModified` TEXT NOT NULL,
`utcDateCreated` TEXT NOT NULL,
`utcDateModified` TEXT NOT NULL,
PRIMARY KEY(`noteId`));
INSERT INTO notes_mig (noteId, title, contentLength, isProtected, type, mime, hash, isDeleted, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified)
SELECT noteId, title, -1, isProtected, type, mime, hash, isDeleted, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified FROM notes;
DROP TABLE notes;
ALTER TABLE notes_mig RENAME TO notes;
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`);
CREATE INDEX `IDX_notes_title` ON `notes` (`title`);
CREATE INDEX `IDX_notes_type` ON `notes` (`type`);
CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`);
CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`);
CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`);
CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`);
CREATE TABLE IF NOT EXISTS "branches_mig" (
`branchId` TEXT NOT NULL,
`noteId` TEXT NOT NULL,
`parentNoteId` TEXT NOT NULL,
`notePosition` INTEGER NOT NULL,
`prefix` TEXT,
`isExpanded` INTEGER NOT NULL DEFAULT 0,
`isDeleted` INTEGER NOT NULL DEFAULT 0,
`deleteId` TEXT DEFAULT NULL,
`utcDateModified` TEXT NOT NULL,
utcDateCreated TEXT NOT NULL,
hash TEXT DEFAULT "" NOT NULL,
PRIMARY KEY(`branchId`));
INSERT INTO branches_mig (branchId, noteId, parentNoteId, notePosition, prefix, isExpanded, isDeleted, utcDateModified, utcDateCreated, hash)
SELECT branchId, noteId, parentNoteId, notePosition, prefix, isExpanded, isDeleted, utcDateModified, utcDateCreated, hash FROM branches;
DROP TABLE branches;
ALTER TABLE branches_mig RENAME TO branches;
CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (`noteId`,`parentNoteId`);
CREATE INDEX IDX_branches_parentNoteId ON branches (parentNoteId);
CREATE TABLE IF NOT EXISTS "attributes_mig"
(
attributeId TEXT not null primary key,
noteId TEXT not null,
type TEXT not null,
name TEXT not null,
value TEXT default '' not null,
position INT default 0 not null,
utcDateCreated TEXT not null,
utcDateModified TEXT not null,
isDeleted INT not null,
`deleteId` TEXT DEFAULT NULL,
hash TEXT default "" not null,
isInheritable int DEFAULT 0 NULL);
INSERT INTO attributes_mig (attributeId, noteId, type, name, value, position, utcDateCreated, utcDateModified, isDeleted, hash, isInheritable)
SELECT attributeId, noteId, type, name, value, position, utcDateCreated, utcDateModified, isDeleted, hash, isInheritable FROM attributes;
DROP TABLE attributes;
ALTER TABLE attributes_mig RENAME TO attributes;
CREATE INDEX IDX_attributes_name_value
on attributes (name, value);
CREATE INDEX IDX_attributes_noteId_index
on attributes (noteId);
CREATE INDEX IDX_attributes_value_index
on attributes (value);
+58 -55
View File
@@ -27,19 +27,6 @@ CREATE TABLE IF NOT EXISTS "options"
utcDateCreated TEXT not null,
utcDateModified TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS "attributes"
(
attributeId TEXT not null primary key,
noteId TEXT not null,
type TEXT not null,
name TEXT not null,
value TEXT default '' not null,
position INT default 0 not null,
utcDateCreated TEXT not null,
utcDateModified TEXT not null,
isDeleted INT not null,
hash TEXT default "" not null,
isInheritable int DEFAULT 0 NULL);
CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` (
`entityName`,
`entityId`
@@ -47,12 +34,6 @@ CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` (
CREATE INDEX `IDX_sync_utcSyncDate` ON `sync` (
`utcSyncDate`
);
CREATE INDEX IDX_attributes_name_value
on attributes (name, value);
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" (
`noteId` TEXT NOT NULL,
`content` TEXT NULL DEFAULT NULL,
@@ -68,46 +49,10 @@ CREATE TABLE recent_notes
utcDateCreated TEXT not null,
isDeleted INT
);
CREATE TABLE IF NOT EXISTS "branches" (
`branchId` TEXT NOT NULL,
`noteId` TEXT NOT NULL,
`parentNoteId` TEXT NOT NULL,
`notePosition` INTEGER NOT NULL,
`prefix` TEXT,
`isExpanded` INTEGER NOT NULL DEFAULT 0,
`isDeleted` INTEGER NOT NULL DEFAULT 0,
`utcDateModified` TEXT NOT NULL,
utcDateCreated TEXT NOT NULL,
hash TEXT DEFAULT "" NOT NULL,
PRIMARY KEY(`branchId`));
CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (`noteId`,`parentNoteId`);
CREATE INDEX IDX_branches_parentNoteId ON branches (parentNoteId);
CREATE TABLE IF NOT EXISTS "note_revision_contents" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
`content` TEXT,
hash TEXT DEFAULT '' NOT NULL,
`utcDateModified` TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS "notes" (
`noteId` TEXT NOT NULL,
`title` TEXT NOT NULL DEFAULT "note",
`contentLength` INT NOT 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,
`isErased` INT NOT NULL DEFAULT 0,
`dateCreated` TEXT NOT NULL,
`dateModified` TEXT NOT NULL,
`utcDateCreated` TEXT NOT NULL,
`utcDateModified` TEXT NOT NULL,
PRIMARY KEY(`noteId`));
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`);
CREATE INDEX `IDX_notes_title` ON `notes` (`title`);
CREATE INDEX `IDX_notes_type` ON `notes` (`type`);
CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`);
CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`);
CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`);
CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`);
CREATE TABLE IF NOT EXISTS "note_revisions" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
`noteId` TEXT NOT NULL,
`title` TEXT,
@@ -127,3 +72,61 @@ CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCr
CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`);
CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`);
CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`);
CREATE TABLE IF NOT EXISTS "notes" (
`noteId` TEXT NOT NULL,
`title` TEXT NOT NULL DEFAULT "note",
`contentLength` INT NOT 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,
`deleteId` TEXT DEFAULT NULL,
`isErased` INT NOT NULL DEFAULT 0,
`dateCreated` TEXT NOT NULL,
`dateModified` TEXT NOT NULL,
`utcDateCreated` TEXT NOT NULL,
`utcDateModified` TEXT NOT NULL,
PRIMARY KEY(`noteId`));
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`);
CREATE INDEX `IDX_notes_title` ON `notes` (`title`);
CREATE INDEX `IDX_notes_type` ON `notes` (`type`);
CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`);
CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`);
CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`);
CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`);
CREATE TABLE IF NOT EXISTS "branches" (
`branchId` TEXT NOT NULL,
`noteId` TEXT NOT NULL,
`parentNoteId` TEXT NOT NULL,
`notePosition` INTEGER NOT NULL,
`prefix` TEXT,
`isExpanded` INTEGER NOT NULL DEFAULT 0,
`isDeleted` INTEGER NOT NULL DEFAULT 0,
`deleteId` TEXT DEFAULT NULL,
`utcDateModified` TEXT NOT NULL,
utcDateCreated TEXT NOT NULL,
hash TEXT DEFAULT "" NOT NULL,
PRIMARY KEY(`branchId`));
CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (`noteId`,`parentNoteId`);
CREATE INDEX IDX_branches_parentNoteId ON branches (parentNoteId);
CREATE TABLE IF NOT EXISTS "attributes"
(
attributeId TEXT not null primary key,
noteId TEXT not null,
type TEXT not null,
name TEXT not null,
value TEXT default '' not null,
position INT default 0 not null,
utcDateCreated TEXT not null,
utcDateModified TEXT not null,
isDeleted INT not null,
`deleteId` TEXT DEFAULT NULL,
hash TEXT default "" not null,
isInheritable int DEFAULT 0 NULL);
CREATE INDEX IDX_attributes_name_value
on attributes (name, value);
CREATE INDEX IDX_attributes_noteId_index
on attributes (noteId);
CREATE INDEX IDX_attributes_value_index
on attributes (value);
+1 -1
View File
@@ -553,7 +553,7 @@ class Note extends Entity {
const attributes = await this.loadOwnedAttributesToCache();
for (const attribute of attributes) {
if (attribute.type === type &amp;&amp; (value === undefined || value === attribute.value)) {
if (attribute.type === type &amp;&amp; attribute.name === name &amp;&amp; (value === undefined || value === attribute.value)) {
attribute.isDeleted = true;
await attribute.save();
@@ -232,7 +232,7 @@ function BackendScriptApi(currentNote, apiParams) {
this.createDataNote = async (parentNoteId, title, content = {}) => await noteService.createNewNote({
parentNoteId,
title,
content: JSON.stringify(content),
content: JSON.stringify(content, null, '\t'),
type: 'code',
mime: 'application/json'
});
+6 -6
View File
@@ -241,7 +241,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line17">line 17</a>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line16">line 16</a>
</li></ul></dd>
@@ -357,7 +357,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line13">line 13</a>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line12">line 12</a>
</li></ul></dd>
@@ -415,7 +415,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line11">line 11</a>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line10">line 10</a>
</li></ul></dd>
@@ -473,7 +473,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line15">line 15</a>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line14">line 14</a>
</li></ul></dd>
@@ -549,7 +549,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line21">line 21</a>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line20">line 20</a>
</li></ul></dd>
@@ -651,7 +651,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line26">line 26</a>
<a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line25">line 25</a>
</li></ul></dd>
+374 -30
View File
@@ -807,7 +807,7 @@
<div class="description">
Activates newly created note. Compared to this.activateNote() also refreshes tree.
Activates newly created note. Compared to this.activateNote() also makes sure that frontend has been fully synced.
</div>
@@ -1240,6 +1240,143 @@
<h4 class="name" id="addTextToActiveTabEditor"><span class="type-signature"></span>addTextToActiveTabEditor<span class="signature">(text)</span><span class="type-signature"></span></h4>
<div class="description">
Adds given text to the editor cursor
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>text</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line305">line 305</a>
</li></ul></dd>
</dl>
@@ -1366,7 +1503,7 @@
<dt class="tag-source">Source:</dt>
<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#line384">line 384</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line406">line 406</a>
</li></ul></dd>
@@ -1546,7 +1683,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#line291">line 291</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line297">line 297</a>
</li></ul></dd>
@@ -1679,7 +1816,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#line235">line 235</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line241">line 241</a>
</li></ul></dd>
@@ -1785,7 +1922,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#line297">line 297</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line311">line 311</a>
</li></ul></dd>
@@ -1891,7 +2028,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#line303">line 303</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line325">line 325</a>
</li></ul></dd>
@@ -1949,6 +2086,119 @@
<h4 class="name" id="getActiveTabTextEditor"><span class="type-signature"></span>getActiveTabTextEditor<span class="signature">()</span><span class="type-signature"> &rarr; {Editor|null}</span></h4>
<div class="description">
See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line319">line 319</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
CKEditor instance or null (e.g. if active note is not a text note)
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Editor</span>
|
<span class="param-type">null</span>
</dd>
</dl>
<h4 class="name" id="getDateNote"><span class="type-signature"></span>getDateNote<span class="signature">(date)</span><span class="type-signature"> &rarr; {Promise.&lt;<a href="NoteShort.html">NoteShort</a>>}</span></h4>
@@ -2050,7 +2300,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#line350">line 350</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line372">line 372</a>
</li></ul></dd>
@@ -2157,7 +2407,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#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#line234">line 234</a>
</li></ul></dd>
@@ -2312,7 +2562,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#line359">line 359</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line381">line 381</a>
</li></ul></dd>
@@ -2468,7 +2718,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#line200">line 200</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line206">line 206</a>
</li></ul></dd>
@@ -2669,7 +2919,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#line212">line 212</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line218">line 218</a>
</li></ul></dd>
@@ -2775,7 +3025,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#line341">line 341</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line363">line 363</a>
</li></ul></dd>
@@ -2930,7 +3180,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#line368">line 368</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line390">line 390</a>
</li></ul></dd>
@@ -3039,7 +3289,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line314">line 314</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line336">line 336</a>
</li></ul></dd>
@@ -3194,7 +3444,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line322">line 322</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line344">line 344</a>
</li></ul></dd>
@@ -3327,7 +3577,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line242">line 242</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line248">line 248</a>
</li></ul></dd>
@@ -3433,7 +3683,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line333">line 333</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line355">line 355</a>
</li></ul></dd>
@@ -3521,7 +3771,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line274">line 274</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line280">line 280</a>
</li></ul></dd>
@@ -3627,7 +3877,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line282">line 282</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line288">line 288</a>
</li></ul></dd>
@@ -3733,7 +3983,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line266">line 266</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line272">line 272</a>
</li></ul></dd>
@@ -3888,7 +4138,7 @@ note.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line220">line 220</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line226">line 226</a>
</li></ul></dd>
@@ -3924,7 +4174,7 @@ note.
<h4 class="name" id="runOnServer"><span class="type-signature"></span>runOnServer<span class="signature">(script, params)</span><span class="type-signature"> &rarr; {Promise.&lt;*>}</span></h4>
<h4 class="name" id="runOnBackend"><span class="type-signature"></span>runOnBackend<span class="signature">(script, params)</span><span class="type-signature"> &rarr; {Promise.&lt;*>}</span></h4>
@@ -3932,7 +4182,7 @@ note.
<div class="description">
Executes given anonymous function on the server.
Executes given anonymous function on the backend.
Internally this serializes the anonymous function into string and sends it to backend via AJAX.
</div>
@@ -4101,6 +4351,92 @@ Internally this serializes the anonymous function into string and sends it to ba
<h4 class="name" id="runOnServer"><span class="type-signature"></span>runOnServer<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="important tag-deprecated">Deprecated:</dt><dd><ul class="dummy"><li>new name of this API call is runOnBackend so use that</li></ul></dd>
<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#line166">line 166</a>
</li></ul></dd>
</dl>
@@ -4209,7 +4545,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#line188">line 188</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line194">line 194</a>
</li></ul></dd>
@@ -4365,7 +4701,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#line170">line 170</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line176">line 176</a>
</li></ul></dd>
@@ -4520,7 +4856,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#line377">line 377</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line399">line 399</a>
</li></ul></dd>
@@ -4671,7 +5007,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#line328">line 328</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line350">line 350</a>
</li></ul></dd>
@@ -4808,7 +5144,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#line258">line 258</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line264">line 264</a>
</li></ul></dd>
@@ -4945,7 +5281,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#line250">line 250</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line256">line 256</a>
</li></ul></dd>
@@ -4988,6 +5324,14 @@ Internally this serializes the anonymous function into string and sends it to ba
<div class="description">
Trilium runs in backend and frontend process, when something is changed on the backend from script,
frontend will get asynchronously synchronized.
This method returns a promise which resolves once all the backend -> frontend synchronization is finished.
Typical use case is when new note has been created, we should wait until it is synced into frontend and only then activate it.
</div>
@@ -5029,7 +5373,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#line389">line 389</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line417">line 417</a>
</li></ul></dd>
@@ -34,7 +34,6 @@ class Branch {
this.branchId = row.branchId;
/** @param {string} */
this.noteId = row.noteId;
this.note = null;
/** @param {string} */
this.parentNoteId = row.parentNoteId;
/** @param {int} */
@@ -86,13 +86,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
};
/**
* Activates newly created note. Compared to this.activateNote() also refreshes tree.
* Activates newly created note. Compared to this.activateNote() also makes sure that frontend has been fully synced.
*
* @param {string} notePath (or noteId)
* @return {Promise&lt;void>}
*/
this.activateNewNote = async notePath => {
await treeService.reload();
await ws.waitForMaxKnownSyncId();
await treeService.activateNote(notePath, noteDetailService.focusAndSelectTitle);
};
@@ -153,14 +153,14 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
}
/**
* Executes given anonymous function on the server.
* Executes given anonymous function on the backend.
* Internally this serializes the anonymous function into string and sends it to backend via AJAX.
*
* @param {string} script - script to be executed on the backend
* @param {Array.&lt;?>} params - list of parameters to the anonymous function to be send to backend
* @return {Promise&lt;*>} return value of the executed function on the backend
*/
this.runOnServer = async (script, params = []) => {
this.runOnBackend = async (script, params = []) => {
if (typeof script === "function") {
script = script.toString();
}
@@ -187,6 +187,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
}
};
/**
* @deprecated new name of this API call is runOnBackend so use that
* @method
*/
this.runOnServer = this.runOnBackend;
/**
* This is a powerful search method - you can search by attributes and their values, e.g.:
* "@dateModified =* MONTH AND @log". See full documentation for all options at: https://github.com/zadam/trilium/wiki/Search
@@ -318,12 +324,28 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
*/
this.createNoteLink = linkService.createNoteLink;
/**
* Adds given text to the editor cursor
*
* @param {string} text
* @method
*/
this.addTextToActiveTabEditor = linkService.addTextToEditor;
/**
* @method
* @returns {NoteFull} active note (loaded into right pane)
*/
this.getActiveTabNote = noteDetailService.getActiveTabNote;
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
*
* @method
* @returns {Editor|null} CKEditor instance or null (e.g. if active note is not a text note)
*/
this.getActiveTabTextEditor = noteDetailService.getActiveEditor;
/**
* @method
* @returns {Promise&lt;string|null>} returns note path of active note or null if there isn't active note
@@ -412,6 +434,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
this.bindGlobalShortcut = utils.bindGlobalShortcut;
/**
* Trilium runs in backend and frontend process, when something is changed on the backend from script,
* frontend will get asynchronously synchronized.
*
* This method returns a promise which resolves once all the backend -> frontend synchronization is finished.
* Typical use case is when new note has been created, we should wait until it is synced into frontend and only then activate it.
*
* @method
*/
this.waitUntilSynced = ws.waitForMaxKnownSyncId;
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+171 -73
View File
@@ -1,4 +1,4 @@
/*! jQuery Fancytree Plugin - 2.33.0 - 2019-10-29T08:00:07Z
/*! jQuery Fancytree Plugin - 2.34.0 - 2019-12-26T14:16:19Z
* https://github.com/mar10/fancytree
* Copyright (c) 2019 Martin Wendt; Licensed MIT
*/
@@ -1365,8 +1365,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
/** Core Fancytree module.
@@ -4156,11 +4156,18 @@ var uniqueId = $.fn.extend( {
delete this._tempCache[key];
return null;
},
/* Check if this tree has extension `name` enabled.
*
* @param {string} name name of the required extension
*/
_usesExtension: function(name) {
return $.inArray(name, this.options.extensions) >= 0;
},
/* Check if current extensions dependencies are met and throw an error if not.
*
* This method may be called inside the `treeInit` hook for custom extensions.
*
* @param {string} extension name of the required extension
* @param {string} name name of the required extension
* @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present
* @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)
* @param {string} [message] optional error message (defaults to a descriptve error message)
@@ -4417,6 +4424,13 @@ var uniqueId = $.fn.extend( {
consoleApply("log", arguments);
}
},
/** Destroy this widget, restore previous markup and cleanup resources.
*
* @since 2.34
*/
destroy: function() {
this.widget.destroy();
},
/** Enable (or disable) the tree control.
*
* @param {boolean} [flag=true] pass false to disable
@@ -4795,6 +4809,20 @@ var uniqueId = $.fn.extend( {
* @returns {boolean}
*/
hasFocus: function() {
// var ae = document.activeElement,
// hasFocus = !!(
// ae && $(ae).closest(".fancytree-container").length
// );
// if (hasFocus !== !!this._hasFocus) {
// this.warn(
// "hasFocus(): fix inconsistent container state, now: " +
// hasFocus
// );
// this._hasFocus = hasFocus;
// this.$container.toggleClass("fancytree-treefocus", hasFocus);
// }
// return hasFocus;
return !!this._hasFocus;
},
/** Write to browser console if debugLevel >= 3 (prepending tree name)
@@ -5120,6 +5148,26 @@ var uniqueId = $.fn.extend( {
setOption: function(optionName, value) {
return this.widget.option(optionName, value);
},
/**
* Call console.time() when in debug mode (verbose >= 4).
*
* @param {string} label
*/
debugTime: function(label) {
if (this.options.debugLevel >= 4) {
window.console.time(this + " - " + label);
}
},
/**
* Call console.timeEnd() when in debug mode (verbose >= 4).
*
* @param {string} label
*/
debugTimeEnd: function(label) {
if (this.options.debugLevel >= 4) {
window.console.timeEnd(this + " - " + label);
}
},
/**
* Return all nodes as nested list of {@link NodeData}.
*
@@ -5185,7 +5233,7 @@ var uniqueId = $.fn.extend( {
* @since 2.28
*/
visitRows: function(fn, opts) {
if (!this.rootNode.children) {
if (!this.rootNode.hasChildren()) {
return false;
}
if (opts && opts.reverse) {
@@ -5314,7 +5362,8 @@ var uniqueId = $.fn.extend( {
/**
* These additional methods of the {@link Fancytree} class are 'hook functions'
* that can be used and overloaded by extensions.
* (See <a href="https://github.com/mar10/fancytree/wiki/TutorialExtensions">writing extensions</a>.)
*
* @see [writing extensions](https://github.com/mar10/fancytree/wiki/TutorialExtensions)
* @mixin Fancytree_Hooks
*/
$.extend(
@@ -6005,6 +6054,7 @@ var uniqueId = $.fn.extend( {
* Call this method to create new nodes, or after the strucuture
* was changed (e.g. after moving this node or adding/removing children)
* nodeRenderTitle() and nodeRenderStatus() are implied.
*
* ```html
* <li id='KEY' ftnode=NODE>
* <span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>
@@ -7493,14 +7543,28 @@ var uniqueId = $.fn.extend( {
*/
/**
* The plugin (derrived from <a href=" http://api.jqueryui.com/jQuery.widget/">jQuery.Widget</a>).<br>
* This constructor is not called directly. Use `$(selector).fancytree({})`
* to initialize the plugin instead.<br>
* <pre class="sh_javascript sunlight-highlight-javascript">// Access widget methods and members:
* var tree = $("#tree").fancytree("getTree");
* var node = $("#tree").fancytree("getActiveNode", "1234");
* </pre>
* The plugin (derrived from [jQuery.Widget](http://api.jqueryui.com/jQuery.widget/)).
*
* **Note:**
* These methods implement the standard jQuery UI widget API.
* It is recommended to use methods of the {Fancytree} instance instead
*
* @example
* // DEPRECATED: Access jQuery UI widget methods and members:
* var tree = $("#tree").fancytree("getTree", "#myTree");
* var node = $.ui.fancytree.getTree("#tree").getActiveNode();
*
* // RECOMMENDED: Use the Fancytree object API
* var tree = $.ui.fancytree.getTree("#myTree");
* var node = tree.getActiveNode();
*
* // or you may already have stored the tree instance upon creation:
* import {createTree, version} from 'jquery.fancytree'
* const tree = createTree('#tree', { ... });
* var node = tree.getActiveNode();
*
* @see {Fancytree_Static#getTree}
* @deprecated Use methods of the {Fancytree} instance instead
* @mixin Fancytree_Widget
*/
@@ -7584,6 +7648,17 @@ var uniqueId = $.fn.extend( {
lazyLoad: null,
postProcess: null,
},
_deprecationWarning: function(name) {
var tree = this.tree;
if (tree && tree.options.debugLevel >= 3) {
tree.warn(
"$().fancytree('" +
name +
"') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html"
);
}
},
/* Set up the widget, Called on first $().fancytree() */
_create: function() {
this.tree = new Fancytree(this);
@@ -7701,11 +7776,11 @@ var uniqueId = $.fn.extend( {
},
/** Use the destroy method to clean up any modifications your widget has made to the DOM */
destroy: function() {
_destroy: function() {
this._unbind();
this.tree._callHook("treeDestroy", this.tree);
// In jQuery UI 1.8, you must invoke the destroy method from the base widget
$.Widget.prototype.destroy.call(this);
// $.Widget.prototype.destroy.call(this);
// TODO: delete tree and nodes to make garbage collect easier?
// TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method
},
@@ -7898,27 +7973,35 @@ var uniqueId = $.fn.extend( {
},
/** Return the active node or null.
* @returns {FancytreeNode}
* @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
*/
getActiveNode: function() {
this._deprecationWarning("getActiveNode");
return this.tree.activeNode;
},
/** Return the matching node or null.
* @param {string} key
* @returns {FancytreeNode}
* @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
*/
getNodeByKey: function(key) {
this._deprecationWarning("getNodeByKey");
return this.tree.getNodeByKey(key);
},
/** Return the invisible system root node.
* @returns {FancytreeNode}
* @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
*/
getRootNode: function() {
this._deprecationWarning("getRootNode");
return this.tree.rootNode;
},
/** Return the current tree instance.
* @returns {Fancytree}
* @deprecated Use `$.ui.fancytree.getTree()` instead (<a href="Fancytree_Widget.html">example above</a>).
*/
getTree: function() {
this._deprecationWarning("getTree");
return this.tree;
},
}
@@ -7928,12 +8011,14 @@ var uniqueId = $.fn.extend( {
FT = $.ui.fancytree;
/**
* Static members in the `$.ui.fancytree` namespace.<br>
* <br>
* <pre class="sh_javascript sunlight-highlight-javascript">// Access static members:
* Static members in the `$.ui.fancytree` namespace.
* This properties and methods can be accessed without instantiating a concrete
* Fancytree instance.
*
* @example
* // Access static members:
* var node = $.ui.fancytree.getNode(element);
* alert($.ui.fancytree.version);
* </pre>
*
* @mixin Fancytree_Static
*/
@@ -7941,11 +8026,14 @@ var uniqueId = $.fn.extend( {
$.ui.fancytree,
/** @lends Fancytree_Static# */
{
/** @type {string} */
version: "2.33.0", // Set to semver by 'grunt release'
/** @type {string} */
/** Version number `"MAJOR.MINOR.PATCH"`
* @type {string} */
version: "2.34.0", // Set to semver by 'grunt release'
/** @type {string}
* @description `"production" for release builds` */
buildType: "production", // Set to 'production' by 'grunt build'
/** @type {int} */
/** @type {int}
* @description 0: silent .. 5: verbose (default: 3 for release builds). */
debugLevel: 3, // Set to 3 by 'grunt build'
// Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
@@ -7954,9 +8042,15 @@ var uniqueId = $.fn.extend( {
_extensions: {},
// focusTree: null,
/** Expose class object as $.ui.fancytree._FancytreeClass */
/** Expose class object as `$.ui.fancytree._FancytreeClass`.
* Useful to extend `$.ui.fancytree._FancytreeClass.prototype`.
* @type {Fancytree}
*/
_FancytreeClass: Fancytree,
/** Expose class object as $.ui.fancytree._FancytreeNodeClass */
/** Expose class object as $.ui.fancytree._FancytreeNodeClass
* Useful to extend `$.ui.fancytree._FancytreeNodeClass.prototype`.
* @type {FancytreeNode}
*/
_FancytreeNodeClass: FancytreeNode,
/* Feature checks to provide backwards compatibility */
jquerySupports: {
@@ -7983,10 +8077,8 @@ var uniqueId = $.fn.extend( {
* @since 2.25
*/
createTree: function(el, opts) {
var tree = $(el)
.fancytree(opts)
.fancytree("getTree");
return tree;
var $tree = $(el).fancytree(opts);
return FT.getTree($tree);
},
/** Return a function that executes *fn* at most every *timeout* ms.
* @param {integer} timeout
@@ -8191,11 +8283,17 @@ var uniqueId = $.fn.extend( {
if (!el.length) {
el = $(orgEl).eq(0); // el was a selector: use first match
}
} else if (
el instanceof Element ||
el instanceof HTMLDocument
) {
el = $(el);
} else if (el instanceof $) {
el = el.eq(0); // el was a jQuery object: use the first DOM element
el = el.eq(0); // el was a jQuery object: use the first
} else if (el.originalEvent !== undefined) {
el = $(el.target); // el was an Event
}
// el is a jQuery object wit one element here
el = el.closest(":ui-fancytree");
widget = el.data("ui-fancytree") || el.data("fancytree"); // the latter is required by jQuery <= 1.8
return widget ? widget.tree : null;
@@ -8203,11 +8301,11 @@ var uniqueId = $.fn.extend( {
/** Return an option value that has a default, but may be overridden by a
* callback or a node instance attribute.
*
* Evaluation sequence:<br>
* Evaluation sequence:
*
* If tree.options.<optionName> is a callback that returns something, use that.<br>
* Else if node.<optionName> is defined, use that.<br>
* Else if tree.options.<optionName> is a value, use that.<br>
* If `tree.options.<optionName>` is a callback that returns something, use that.
* Else if `node.<optionName>` is defined, use that.
* Else if `tree.options.<optionName>` is a value, use that.
* Else use `defaultValue`.
*
* @param {string} optionName name of the option property (on node and tree)
@@ -8565,8 +8663,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
// To keep the global namespace clean, we wrap everything in a closure.
@@ -8602,7 +8700,7 @@ var uniqueId = $.fn.extend( {
// New member functions can be added to the `Fancytree` class.
// This function will be available for every tree instance:
//
// var tree = $("#tree").fancytree("getTree");
// var tree = $.ui.fancytree.getTree("#tree");
// tree.countSelected(false);
$.ui.fancytree._FancytreeClass.prototype.countSelected = function(topOnly) {
@@ -8685,7 +8783,7 @@ var uniqueId = $.fn.extend( {
// Every extension must be registered by a unique name.
name: "childcounter",
// Version information should be compliant with [semver](http://semver.org)
version: "2.33.0",
version: "2.34.0",
// Extension specific options and their defaults.
// This options will be available as `tree.options.childcounter.hideExpanded`
@@ -8796,8 +8894,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -9155,7 +9253,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "clones",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
@@ -9317,8 +9415,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
/*
@@ -10322,7 +10420,7 @@ var uniqueId = $.fn.extend( {
$.ui.fancytree.registerExtension({
name: "dnd5",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
autoExpandMS: 1500, // Expand nodes after n milliseconds of hovering
@@ -10455,8 +10553,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -10748,7 +10846,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "edit",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
adjustWidthOfs: 4, // null: don't adjust input size to content
@@ -10859,8 +10957,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -11198,7 +11296,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "filter",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
autoApply: true, // Re-apply last filter if lazy data is loaded
@@ -11318,8 +11416,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -11502,7 +11600,7 @@ var uniqueId = $.fn.extend( {
$.ui.fancytree.registerExtension({
name: "glyph",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
preset: null, // 'awesome3', 'awesome4', 'bootstrap3', 'material'
@@ -11656,8 +11754,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -11774,7 +11872,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "gridnav",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
autofocusInput: false, // Focus first embedded input if node gets activated
@@ -11881,8 +11979,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -11911,7 +12009,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "multi",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
allowNoSelect: false, //
@@ -12013,8 +12111,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -12154,7 +12252,7 @@ var uniqueId = $.fn.extend( {
/**
* [ext-persist] Remove persistence data of the given type(s).
* Called like
* $("#tree").fancytree("getTree").clearCookies("active expanded focus selected");
* $.ui.fancytree.getTree("#tree").clearCookies("active expanded focus selected");
*
* @alias Fancytree#clearPersistData
* @requires jquery.fancytree.persist.js
@@ -12191,7 +12289,7 @@ var uniqueId = $.fn.extend( {
* [ext-persist] Return persistence information from cookies
*
* Called like
* $("#tree").fancytree("getTree").getPersistData();
* $.ui.fancytree.getTree("#tree").getPersistData();
*
* @alias Fancytree#getPersistData
* @requires jquery.fancytree.persist.js
@@ -12214,7 +12312,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "persist",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
cookieDelimiter: "~",
@@ -12507,8 +12605,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -12591,7 +12689,7 @@ var uniqueId = $.fn.extend( {
$.ui.fancytree.registerExtension({
name: "table",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
@@ -13057,8 +13155,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -13081,7 +13179,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "themeroller",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
activeClass: "ui-state-active", // Class added to active node
@@ -13177,8 +13275,8 @@ var uniqueId = $.fn.extend( {
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
*/
(function(factory) {
@@ -13308,7 +13406,7 @@ var uniqueId = $.fn.extend( {
*/
$.ui.fancytree.registerExtension({
name: "wide",
version: "2.33.0",
version: "2.34.0",
// Default options for this extension.
options: {
iconWidth: null, // Adjust this if @fancy-icon-width != "16px"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -13,8 +13,8 @@
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.33.0
* @date 2019-10-29T08:00:07Z
* @version 2.34.0
* @date 2019-12-26T14:16:19Z
******************************************************************************/
/*------------------------------------------------------------------------------
* Helpers
+122 -301
View File
@@ -1,6 +1,6 @@
{
"name": "trilium",
"version": "0.39.0-beta",
"version": "0.39.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -552,6 +552,11 @@
"defer-to-connect": "^1.0.1"
}
},
"@tokenizer/token": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz",
"integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w=="
},
"@types/debug": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
@@ -722,29 +727,29 @@
"integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="
},
"app-builder-bin": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.4.tgz",
"integrity": "sha512-Xib+wgdK+8zZhbZr5pma3pNB23Y4JRY5Yt6h8peou6MTFSQzXdIkqalh/ezy9SMLuS43S4b0s7jTVAmUs8WVmA==",
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.3.tgz",
"integrity": "sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg==",
"dev": true
},
"app-builder-lib": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.1.0.tgz",
"integrity": "sha512-jDTfWsVS/MePO4FexqiSQcsWM9Yfr81ETIYbmVbKmW05o0dn9k1DvMOMoLb0kTLQpW+pWBVvGMAOPfk68HnBrg==",
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.2.0.tgz",
"integrity": "sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A==",
"dev": true,
"requires": {
"7zip-bin": "~5.0.3",
"@develar/schema-utils": "~2.1.0",
"async-exit-hook": "^2.0.1",
"bluebird-lst": "^1.0.9",
"builder-util": "22.1.0",
"builder-util-runtime": "8.4.0",
"builder-util": "21.2.0",
"builder-util-runtime": "8.3.0",
"chromium-pickle-js": "^0.2.0",
"debug": "^4.1.1",
"ejs": "^2.7.1",
"electron-publish": "22.1.0",
"ejs": "^2.6.2",
"electron-publish": "21.2.0",
"fs-extra": "^8.1.0",
"hosted-git-info": "^3.0.0",
"hosted-git-info": "^2.7.1",
"is-ci": "^2.0.0",
"isbinaryfile": "^4.0.2",
"js-yaml": "^3.13.1",
@@ -752,26 +757,11 @@
"minimatch": "^3.0.4",
"normalize-package-data": "^2.5.0",
"read-config-file": "5.0.0",
"sanitize-filename": "^1.6.3",
"sanitize-filename": "^1.6.2",
"semver": "^6.3.0",
"temp-file": "^3.3.4"
},
"dependencies": {
"ejs": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
"dev": true
},
"hosted-git-info": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.2.tgz",
"integrity": "sha512-ezZMWtHXm7Eb7Rq4Mwnx2vs79WUx2QmRg3+ZqeGroKzfDO+EprOcgRPYghsOP9JuYBfK18VojmRTGCg8Ma+ktw==",
"dev": true,
"requires": {
"lru-cache": "^5.1.1"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -990,12 +980,11 @@
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"axios": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
"integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.1.tgz",
"integrity": "sha512-Yl+7nfreYKaLRvAvjNPkvfjnQHJM1yLBY3zhqAwcJSwR/6ETkanUgylgtIvkvz0xJ+p/vZuNw8X7Hnb7Whsbpw==",
"requires": {
"follow-redirects": "1.5.10",
"is-buffer": "^2.0.2"
"follow-redirects": "1.5.10"
}
},
"bagpipe": {
@@ -1381,16 +1370,16 @@
}
},
"builder-util": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.1.0.tgz",
"integrity": "sha512-BPvpWvxQ5XOzm2WepIgmOAyo2IyaM/Bd1LJmeTYy5CtknNAtxgmAPQJfCHCikMKKQA4Obz/KYecXQiGpGJ2ThA==",
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.2.0.tgz",
"integrity": "sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A==",
"dev": true,
"requires": {
"7zip-bin": "~5.0.3",
"@types/debug": "^4.1.5",
"app-builder-bin": "3.4.4",
"@types/debug": "^4.1.4",
"app-builder-bin": "3.4.3",
"bluebird-lst": "^1.0.9",
"builder-util-runtime": "8.4.0",
"builder-util-runtime": "8.3.0",
"chalk": "^2.4.2",
"debug": "^4.1.1",
"fs-extra": "^8.1.0",
@@ -1439,9 +1428,9 @@
}
},
"builder-util-runtime": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz",
"integrity": "sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ==",
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz",
"integrity": "sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@@ -1786,13 +1775,13 @@
}
},
"commonmark": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.29.0.tgz",
"integrity": "sha512-Wc3kvAIm0EK85pHsM95Fev31wEN6/zQpwd2qcLDL8psjHRoUFvUeGHevIJAdToWUuFoX8WI/gmeDauqy32xgJQ==",
"version": "0.29.1",
"resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.29.1.tgz",
"integrity": "sha512-DafPdNYFXoEhsSiR4O+dJ45UJBfDL4cBTks4B+agKiaWt7qjG0bIhg5xuCE0RqU71ikJcBIf4/sRHh9vYQVF8Q==",
"requires": {
"entities": "~ 1.1.1",
"mdurl": "~ 1.0.1",
"minimist": "~ 1.2.0",
"entities": "~1.1.1",
"mdurl": "~1.0.1",
"minimist": "~1.2.0",
"string.prototype.repeat": "^0.2.0"
}
},
@@ -2096,9 +2085,9 @@
"integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI="
},
"dayjs": {
"version": "1.8.18",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.18.tgz",
"integrity": "sha512-JBMJZghNK8TtuoPnKNIzW9xavVVigld/zmZNpZSyQbkb2Opp55YIfZUpE4OEqPF/iyUVQTKcn1bC2HtC8B7s3g=="
"version": "1.8.19",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.19.tgz",
"integrity": "sha512-7kqOoj3oQSmqbvtvGFLU5iYqies+SqUiEGNT0UtUPPxcPYgY1BrkXR0Cq2R9HYSimBXN+xHkEN4Hi399W+Ovlg=="
},
"debug": {
"version": "4.1.1",
@@ -2424,122 +2413,6 @@
"sanitize-filename": "^1.6.2"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"app-builder-bin": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.3.tgz",
"integrity": "sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg==",
"dev": true
},
"app-builder-lib": {
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.2.0.tgz",
"integrity": "sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A==",
"dev": true,
"requires": {
"7zip-bin": "~5.0.3",
"@develar/schema-utils": "~2.1.0",
"async-exit-hook": "^2.0.1",
"bluebird-lst": "^1.0.9",
"builder-util": "21.2.0",
"builder-util-runtime": "8.3.0",
"chromium-pickle-js": "^0.2.0",
"debug": "^4.1.1",
"ejs": "^2.6.2",
"electron-publish": "21.2.0",
"fs-extra": "^8.1.0",
"hosted-git-info": "^2.7.1",
"is-ci": "^2.0.0",
"isbinaryfile": "^4.0.2",
"js-yaml": "^3.13.1",
"lazy-val": "^1.0.4",
"minimatch": "^3.0.4",
"normalize-package-data": "^2.5.0",
"read-config-file": "5.0.0",
"sanitize-filename": "^1.6.2",
"semver": "^6.3.0",
"temp-file": "^3.3.4"
},
"dependencies": {
"ejs": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
"dev": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
"builder-util": {
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.2.0.tgz",
"integrity": "sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A==",
"dev": true,
"requires": {
"7zip-bin": "~5.0.3",
"@types/debug": "^4.1.4",
"app-builder-bin": "3.4.3",
"bluebird-lst": "^1.0.9",
"builder-util-runtime": "8.3.0",
"chalk": "^2.4.2",
"debug": "^4.1.1",
"fs-extra": "^8.1.0",
"is-ci": "^2.0.0",
"js-yaml": "^3.13.1",
"source-map-support": "^0.5.13",
"stat-mode": "^0.3.0",
"temp-file": "^3.3.4"
}
},
"builder-util-runtime": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz",
"integrity": "sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw==",
"dev": true,
"requires": {
"debug": "^4.1.1",
"sax": "^1.2.4"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"electron-publish": {
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.2.0.tgz",
"integrity": "sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA==",
"dev": true,
"requires": {
"bluebird-lst": "^1.0.9",
"builder-util": "~21.2.0",
"builder-util-runtime": "8.3.0",
"chalk": "^2.4.2",
"fs-extra": "^8.1.0",
"lazy-val": "^1.0.4",
"mime": "^2.4.4"
}
},
"iconv-lite": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz",
@@ -2548,27 +2421,6 @@
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"mime": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
"dev": true
},
"stat-mode": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.3.0.tgz",
"integrity": "sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
@@ -2748,32 +2600,26 @@
}
},
"electron-builder": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.1.0.tgz",
"integrity": "sha512-uu2W9BLG38D0i2PG6dHupmOYc+q/TRL+Ztf8xitqK+2Quq33PFbeN0ipfySuVEDg4I6whDRBOgxBEWwnUYqZZQ==",
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.2.0.tgz",
"integrity": "sha512-x8EXrqFbAb2L3N22YlGar3dGh8vwptbB3ovo3OF6K7NTpcsmM2zEoJv7GhFyX73rNzSG2HaWpXwGAtOp2JWiEw==",
"dev": true,
"requires": {
"app-builder-lib": "22.1.0",
"app-builder-lib": "21.2.0",
"bluebird-lst": "^1.0.9",
"builder-util": "22.1.0",
"builder-util-runtime": "8.4.0",
"builder-util": "21.2.0",
"builder-util-runtime": "8.3.0",
"chalk": "^2.4.2",
"dmg-builder": "21.2.0",
"fs-extra": "^8.1.0",
"is-ci": "^2.0.0",
"lazy-val": "^1.0.4",
"read-config-file": "5.0.0",
"sanitize-filename": "^1.6.3",
"sanitize-filename": "^1.6.2",
"update-notifier": "^3.0.1",
"yargs": "^14.0.0"
"yargs": "^13.3.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -2783,12 +2629,6 @@
"color-convert": "^1.9.0"
}
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -2800,41 +2640,6 @@
"supports-color": "^5.3.0"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -2843,35 +2648,6 @@
"requires": {
"has-flag": "^3.0.0"
}
},
"yargs": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.0.tgz",
"integrity": "sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg==",
"dev": true,
"requires": {
"cliui": "^5.0.0",
"decamelize": "^1.2.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^15.0.0"
}
},
"yargs-parser": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
"integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
@@ -3191,14 +2967,14 @@
}
},
"electron-publish": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.1.0.tgz",
"integrity": "sha512-jHjMCaL2dFU+iOq8wW568F59+DW1jFJGT3vc2xqm9iXyZ8gWlQ+NVve4bq9HZG7m4iNqWbGw9StmZcOzmIBxMQ==",
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.2.0.tgz",
"integrity": "sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA==",
"dev": true,
"requires": {
"bluebird-lst": "^1.0.9",
"builder-util": "~22.1.0",
"builder-util-runtime": "8.4.0",
"builder-util": "~21.2.0",
"builder-util-runtime": "8.3.0",
"chalk": "^2.4.2",
"fs-extra": "^8.1.0",
"lazy-val": "^1.0.4",
@@ -3847,9 +3623,15 @@
}
},
"file-type": {
"version": "12.4.2",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz",
"integrity": "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg=="
"version": "13.0.3",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-13.0.3.tgz",
"integrity": "sha512-fe3+9mnMLbpP8nRQm/cJgehypv375SOFOXFdLYyYe7hWxdWgS5hkDpWnld5At/vvfVEN6rVqKA3EOKMP03tJGg==",
"requires": {
"readable-web-to-node-stream": "^2.0.0",
"strtok3": "^5.0.1",
"token-types": "^2.0.0",
"typedarray-to-buffer": "^3.1.5"
}
},
"filename-regex": {
"version": "2.0.1",
@@ -5000,6 +4782,13 @@
"make-dir": "^3.0.0",
"p-pipe": "^3.0.0",
"replace-ext": "^1.0.0"
},
"dependencies": {
"file-type": {
"version": "12.4.2",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz",
"integrity": "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg=="
}
}
},
"imagemin-giflossy": {
@@ -5197,11 +4986,6 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-buffer": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
},
"is-bzip2": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz",
@@ -5449,9 +5233,9 @@
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isbinaryfile": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.2.tgz",
"integrity": "sha512-C3FSxJdNrEr2F4z6uFtNzECDM5hXk+46fxaa+cwBe5/XrWSmzdG8DDgyjfX6/NRdBB21q2JXuRAzPCUs+fclnQ==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.3.tgz",
"integrity": "sha512-GQ9Gjhp3AsEbo8/L/pA+MYl/c4hRm5O/+uCkF4LMx1a556Wh4/d75H13qu9LldmhU4yKnlfNKBmEcCaze3b2Gw==",
"dev": true
},
"isexe": {
@@ -6201,17 +5985,17 @@
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
},
"mime-types": {
"version": "2.1.25",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
"integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
"version": "2.1.26",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
"requires": {
"mime-db": "1.42.0"
"mime-db": "1.43.0"
},
"dependencies": {
"mime-db": {
"version": "1.42.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
"version": "1.43.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
}
}
},
@@ -7691,6 +7475,11 @@
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
},
"peek-readable": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.0.tgz",
"integrity": "sha512-KGuODSTV6hcgdZvDrIDBUkN0utcAVj1LL7FfGbM0viKTtCHmtZcuEJ+lGqsp0fTFkGqesdtemV2yUSMeyy3ddA=="
},
"pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -8664,6 +8453,11 @@
"util-deprecate": "~1.0.1"
}
},
"readable-web-to-node-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-2.0.0.tgz",
"integrity": "sha512-+oZJurc4hXpaaqsN68GoZGQAQIA3qr09Or4fqEsargABnbe5Aau8hFn6ISVleT3cpY/0n/8drn7huyyEvTbghA=="
},
"redent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
@@ -9390,9 +9184,9 @@
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
},
"string-similarity": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-3.0.0.tgz",
"integrity": "sha512-7kS7LyTp56OqOI2BDWQNVnLX/rCxIQn+/5M0op1WV6P8Xx6TZNdajpuqQdiJ7Xx+p1C5CsWMvdiBp9ApMhxzEQ=="
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.1.tgz",
"integrity": "sha512-v36MJzloekKVvKAsYi6O/qpn2mIuvwEFIT9Gx3yg4spkNjXYsk7yxc37g4ZTyMVIBvt/9PZGxnqEtme8XHK+Mw=="
},
"string-width": {
"version": "1.0.2",
@@ -9499,6 +9293,16 @@
"escape-string-regexp": "^1.0.2"
}
},
"strtok3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-5.0.1.tgz",
"integrity": "sha512-AWliiIjyb87onqO8pM+1Hozm+PPcR4YYIWbFUT5OKQ+tOMwgdT8HwJd/IS8v3/gKdAtE5aE2p3FhcWqryuZPLQ==",
"requires": {
"@tokenizer/token": "^0.1.0",
"debug": "^4.1.1",
"peek-readable": "^3.1.0"
}
},
"sum-up": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz",
@@ -9600,9 +9404,9 @@
"integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0="
},
"temp-file": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.4.tgz",
"integrity": "sha512-qSZ5W5q54iyGnP8cNl49RE0jTJc5CrzNocux5APD5yIxcgonoMuMSbsZfaZy8rTGCYo0Xz6ySVv3adagZ8gffg==",
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.6.tgz",
"integrity": "sha512-7TPldi8QJqRlPIF/Y33mVvo8+xDfi6+aVTCK4CrCaLqCoaOnVtf3SA4hCU0T5nhYDdOC7erw7o2uWfvijlk4Ug==",
"dev": true,
"requires": {
"async-exit-hook": "^2.0.1",
@@ -9788,6 +9592,15 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"token-types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/token-types/-/token-types-2.0.0.tgz",
"integrity": "sha512-WWvu8sGK8/ZmGusekZJJ5NM6rRVTTDO7/bahz4NGiSDb/XsmdYBn6a1N/bymUHuWYTWeuLUg98wUzvE4jPdCZw==",
"requires": {
"@tokenizer/token": "^0.1.0",
"ieee754": "^1.1.13"
}
},
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
@@ -9901,6 +9714,14 @@
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"requires": {
"is-typedarray": "^1.0.0"
}
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+8 -8
View File
@@ -2,7 +2,7 @@
"name": "trilium",
"productName": "Trilium Notes",
"description": "Trilium Notes",
"version": "0.39.2-beta",
"version": "0.40.0-beta",
"license": "AGPL-3.0-only",
"main": "electron.js",
"bin": {
@@ -21,13 +21,13 @@
},
"dependencies": {
"async-mutex": "0.1.4",
"axios": "0.19.0",
"axios": "0.19.1",
"body-parser": "1.19.0",
"cls-hooked": "4.2.2",
"commonmark": "0.29.0",
"commonmark": "0.29.1",
"cookie-parser": "1.4.4",
"csurf": "1.10.0",
"dayjs": "1.8.18",
"dayjs": "1.8.19",
"debug": "4.1.1",
"ejs": "2.7.4",
"electron-debug": "3.0.1",
@@ -37,7 +37,7 @@
"electron-window-state": "5.0.3",
"express": "4.17.1",
"express-session": "1.17.0",
"file-type": "12.4.2",
"file-type": "13.0.3",
"fs-extra": "8.1.0",
"helmet": "3.21.2",
"html": "1.0.0",
@@ -51,7 +51,7 @@
"imagemin-pngquant": "8.0.0",
"ini": "1.3.5",
"jimp": "0.9.3",
"mime-types": "2.1.25",
"mime-types": "2.1.26",
"moment": "2.24.0",
"multer": "1.4.2",
"node-abi": "2.13.0",
@@ -69,7 +69,7 @@
"simple-node-logger": "18.12.23",
"sqlite": "3.0.3",
"sqlite3": "4.1.1",
"string-similarity": "3.0.0",
"string-similarity": "4.0.1",
"tar-stream": "2.1.0",
"turndown": "5.0.3",
"turndown-plugin-gfm": "1.0.2",
@@ -78,7 +78,7 @@
},
"devDependencies": {
"electron": "6.0.12",
"electron-builder": "22.1.0",
"electron-builder": "21.2.0",
"electron-packager": "14.1.1",
"electron-rebuild": "1.8.8",
"jsdoc": "3.6.3",
+1
View File
@@ -16,6 +16,7 @@ const sql = require('../services/sql');
* @property {int} position
* @property {boolean} isInheritable
* @property {boolean} isDeleted
* @property {string|null} deleteId - ID identifying delete transaction
* @property {string} utcDateCreated
* @property {string} utcDateModified
*
+2 -1
View File
@@ -16,6 +16,7 @@ const sql = require('../services/sql');
* @property {string} prefix
* @property {boolean} isExpanded
* @property {boolean} isDeleted
* @property {string|null} deleteId - ID identifying delete transaction
* @property {string} utcDateModified
* @property {string} utcDateCreated
*
@@ -25,7 +26,7 @@ class Branch extends Entity {
static get entityName() { return "branches"; }
static get primaryKeyName() { return "branchId"; }
// notePosition is not part of hash because it would produce a lot of updates in case of reordering
static get hashedProperties() { return ["branchId", "noteId", "parentNoteId", "isDeleted", "prefix"]; }
static get hashedProperties() { return ["branchId", "noteId", "parentNoteId", "isDeleted", "deleteId", "prefix"]; }
constructor(row = {}) {
super(row);
+4 -3
View File
@@ -24,6 +24,7 @@ const RELATION_DEFINITION = 'relation-definition';
* @property {int} contentLength - length of content
* @property {boolean} isProtected - true if note is protected
* @property {boolean} isDeleted - true if note is deleted
* @property {string|null} deleteId - ID identifying delete transaction
* @property {boolean} isErased - true if note's content is erased after it has been deleted
* @property {string} dateCreated - local date time (with offset)
* @property {string} dateModified - local date time (with offset)
@@ -35,7 +36,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", "type", "isProtected", "isDeleted"]; }
static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted", "deleteId"]; }
/**
* @param row - object containing database row from "notes" table
@@ -525,7 +526,7 @@ class Note extends Entity {
const attributes = await this.loadOwnedAttributesToCache();
for (const attribute of attributes) {
if (attribute.type === type && (value === undefined || value === attribute.value)) {
if (attribute.type === type && attribute.name === name && (value === undefined || value === attribute.value)) {
attribute.isDeleted = true;
await attribute.save();
@@ -805,7 +806,7 @@ class Note extends Entity {
WHERE noteId = ? AND
isDeleted = 0 AND
type = 'relation' AND
name IN ('internalLink', 'imageLink', 'relationMapLink')`, [this.noteId]);
name IN ('internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink')`, [this.noteId]);
}
/**
@@ -6,7 +6,7 @@ const TPL = `
<div>
<h4>Spell check</h4>
<p>These options apply only for desktop builds, browsers will use their own native spell check.</p>
<p>These options apply only for desktop builds, browsers will use their own native spell check. App restart is required after change.</p>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="spell-check-enabled">
@@ -37,6 +37,20 @@ const TPL = `
</div>
</div>
<div>
<h4>Note erasure timeout</h4>
<p>Deleted notes are at first only marked as deleted and it is possible to recover them
from Recent Notes dialog. After period of time, deleted notes are "erased" which means
their content is not recoverable anymore. This setting allows you to configure the length
of the period between deleting and erasing the note.</p>
<div class="form-group">
<label for="erase-notes-after-time-in-seconds">Erase notes after X seconds</label>
<input class="form-control" id="erase-notes-after-time-in-seconds" type="number" min="0">
</div>
</div>
<div>
<h4>Protected session timeout</h4>
@@ -81,6 +95,20 @@ export default class ProtectedSessionOptions {
return false;
});
this.$eraseNotesAfterTimeInSeconds = $("#erase-notes-after-time-in-seconds");
this.$eraseNotesAfterTimeInSeconds.on('change', () => {
const eraseNotesAfterTimeInSeconds = this.$eraseNotesAfterTimeInSeconds.val();
server.put('options', { 'eraseNotesAfterTimeInSeconds': eraseNotesAfterTimeInSeconds }).then(() => {
optionsService.reloadOptions();
toastService.showMessage("Options change have been saved.");
});
return false;
});
this.$protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
this.$protectedSessionTimeout.on('change', () => {
@@ -126,6 +154,7 @@ export default class ProtectedSessionOptions {
this.$spellCheckEnabled.prop("checked", options['spellCheckEnabled'] === 'true');
this.$spellCheckLanguageCode.val(options['spellCheckLanguageCode']);
this.$eraseNotesAfterTimeInSeconds.val(options['eraseNotesAfterTimeInSeconds']);
this.$protectedSessionTimeout.val(options['protectedSessionTimeout']);
this.$noteRevisionsTimeInterval.val(options['noteRevisionSnapshotTimeInterval']);
@@ -12,7 +12,7 @@ const TPL = `
<div class="form-group">
<label for="sync-server-timeout">Sync timeout (milliseconds)</label>
<input class="form-control" id="sync-server-timeout" min="1" max="10000000" type="number">
<input class="form-control" id="sync-server-timeout" min="1" max="10000000" type="number" style="text-align: left;">
</div>
<div class="form-group">
@@ -28,31 +28,60 @@ export async function showDialog() {
const groupedByDate = groupByDate(result);
for (const [dateDay, dayChanges] of groupedByDate) {
const changesListEl = $('<ul>');
const $changesList = $('<ul>');
const dayEl = $('<div>').append($('<b>').html(utils.formatDate(dateDay))).append(changesListEl);
const dayEl = $('<div>').append($('<b>').html(utils.formatDate(dateDay))).append($changesList);
for (const change of dayChanges) {
const formattedTime = utils.formatTime(utils.parseDate(change.date));
let noteLink;
let $noteLink;
if (change.current_isDeleted) {
noteLink = change.current_title;
$noteLink = $("<span>").text(change.current_title);
if (change.canBeUndeleted) {
const $undeleteLink = $(`<a href="javascript:">`)
.text("undelete")
.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to undelete this note and its sub-notes?';
if (await confirmDialog.confirm(text)) {
await server.put(`notes/${change.noteId}/undelete`);
$dialog.modal('hide');
await treeCache.reloadNotes([change.noteId]);
treeService.activateNote(change.noteId);
}
});
$noteLink
.append(' (')
.append($undeleteLink)
.append(')');
}
}
else {
const note = await treeCache.getNote(change.noteId);
const notePath = await treeService.getSomeNotePath(note);
noteLink = await linkService.createNoteLink(notePath, {
title: change.title,
showNotePath: true
});
if (notePath) {
$noteLink = await linkService.createNoteLink(notePath, {
title: change.title,
showNotePath: true
});
}
else {
$noteLink = $("<span>").text(note.title);
}
}
changesListEl.append($('<li>')
$changesList.append($('<li>')
.append(formattedTime + ' - ')
.append(noteLink));
.append($noteLink));
}
$content.append(dayEl);
@@ -85,5 +114,6 @@ function groupByDate(result) {
groupedByDate.get(dateDay).push(row);
}
return groupedByDate;
}
+2 -2
View File
@@ -37,12 +37,12 @@ $detail.on("click", ".close-detail-button",() => {
});
async function showTree() {
const tree = await treeService.loadTree();
const treeData = await treeService.loadTreeData();
$tree.fancytree({
autoScroll: true,
extensions: ["dnd5", "clones"],
source: tree,
source: treeData,
scrollParent: $tree,
minExpandLevel: 2, // root can't be collapsed
click: (event, data) => {
@@ -265,6 +265,24 @@ ws.subscribeToMessages(async message => {
}
});
ws.subscribeToMessages(async message => {
if (message.taskType !== 'undelete-notes') {
return;
}
if (message.type === 'task-error') {
toastService.closePersistent(message.taskId);
toastService.showError(message.message);
} else if (message.type === 'task-progress-count') {
toastService.showPersistent(makeToast(message.taskId, "Undeleting notes in progress: " + message.progressCount));
} else if (message.type === 'task-succeeded') {
const toast = makeToast(message.taskId, "Undeleting notes finished successfully.");
toast.closeAfter = 5000;
toastService.showPersistent(toast);
}
});
export default {
moveBeforeNode,
moveAfterNode,
+6 -6
View File
@@ -1,4 +1,4 @@
import treeUtils from "./tree_utils.js";
import treeService from "./tree.js";
import treeChangesService from "./branches.js";
import cloningService from "./cloning.js";
import toastService from "./toast.js";
@@ -19,7 +19,7 @@ async function pasteAfter(afterNode) {
}
if (clipboardMode === 'cut') {
const nodes = clipboardNodeKeys.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
const nodes = clipboardNodeKeys.map(nodeKey => treeService.getNodeByKey(nodeKey));
await treeChangesService.moveAfterNode(nodes, afterNode);
@@ -28,7 +28,7 @@ async function pasteAfter(afterNode) {
}
else if (clipboardMode === 'copy') {
for (const nodeKey of clipboardNodeKeys) {
const clipNode = treeUtils.getNodeByKey(nodeKey);
const clipNode = treeService.getNodeByKey(nodeKey);
await cloningService.cloneNoteAfter(clipNode.data.noteId, afterNode.data.branchId);
}
@@ -46,7 +46,7 @@ async function pasteInto(parentNode) {
}
if (clipboardMode === 'cut') {
const nodes = clipboardNodeKeys.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
const nodes = clipboardNodeKeys.map(nodeKey => treeService.getNodeByKey(nodeKey));
await treeChangesService.moveToNode(nodes, parentNode);
@@ -57,7 +57,7 @@ async function pasteInto(parentNode) {
}
else if (clipboardMode === 'copy') {
for (const nodeKey of clipboardNodeKeys) {
const clipNode = treeUtils.getNodeByKey(nodeKey);
const clipNode = treeService.getNodeByKey(nodeKey);
await cloningService.cloneNoteTo(clipNode.data.noteId, parentNode.data.noteId);
}
@@ -92,7 +92,7 @@ function cut(nodes) {
}
function isClipboardEmpty() {
clipboardNodeKeys = clipboardNodeKeys.filter(key => !!treeUtils.getNodeByKey(key));
clipboardNodeKeys = clipboardNodeKeys.filter(key => !!treeService.getNodeByKey(key));
return clipboardNodeKeys.length === 0;
}
@@ -76,8 +76,7 @@ async function initContextMenu(event, contextMenu) {
// in such case we'll position it above click coordinates so it will fit into client
const clickPosition = event.pageY;
const clientHeight = document.documentElement.clientHeight;
const contextMenuHeight = $contextMenuContainer.height();
const contextMenuHeight = $contextMenuContainer.outerHeight() + 30;
let top;
if (clickPosition + contextMenuHeight > clientHeight) {
@@ -58,13 +58,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
};
/**
* Activates newly created note. Compared to this.activateNote() also refreshes tree.
* Activates newly created note. Compared to this.activateNote() also makes sure that frontend has been fully synced.
*
* @param {string} notePath (or noteId)
* @return {Promise<void>}
*/
this.activateNewNote = async notePath => {
await treeService.reload();
await ws.waitForMaxKnownSyncId();
await treeService.activateNote(notePath, noteDetailService.focusAndSelectTitle);
};
@@ -296,12 +296,28 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
*/
this.createNoteLink = linkService.createNoteLink;
/**
* Adds given text to the editor cursor
*
* @param {string} text - this must be clear text, HTML is not supported.
* @method
*/
this.addTextToActiveTabEditor = linkService.addTextToEditor;
/**
* @method
* @returns {NoteFull} active note (loaded into right pane)
*/
this.getActiveTabNote = noteDetailService.getActiveTabNote;
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
*
* @method
* @returns {Editor|null} CKEditor instance or null (e.g. if active note is not a text note)
*/
this.getActiveTabTextEditor = noteDetailService.getActiveEditor;
/**
* @method
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
+13 -5
View File
@@ -10,6 +10,12 @@ function getNotePathFromUrl(url) {
}
async function createNoteLink(notePath, options = {}) {
if (!notePath || !notePath.trim()) {
console.error("Missing note path");
return $("<span>").text("[missing note]");
}
let noteTitle = options.title;
const showTooltip = options.showTooltip === undefined ? true : options.showTooltip;
const showNotePath = options.showNotePath === undefined ? false : options.showNotePath;
@@ -35,13 +41,15 @@ async function createNoteLink(notePath, options = {}) {
if (showNotePath) {
notePath = await treeService.resolveNotePath(notePath);
const noteIds = notePath.split("/");
noteIds.pop(); // remove last element
if (notePath) {
const noteIds = notePath.split("/");
noteIds.pop(); // remove last element
const parentNotePath = noteIds.join("/").trim();
const parentNotePath = noteIds.join("/").trim();
if (parentNotePath) {
$container.append($("<small>").text(" (" + await treeUtils.getNotePathTitle(parentNotePath) + ")"));
if (parentNotePath) {
$container.append($("<small>").text(" (" + await treeUtils.getNotePathTitle(parentNotePath) + ")"));
}
}
}
@@ -174,7 +174,11 @@ async function showTab(tabId) {
if (newActiveTabContext && newActiveTabContext.notePath) {
const newActiveNode = await treeService.getNodeFromPath(newActiveTabContext.notePath);
if (newActiveNode && newActiveNode.isVisible()) {
if (newActiveNode) {
if (!newActiveNode.isVisible()) {
await treeService.expandToNote(newActiveTabContext.notePath);
}
newActiveNode.setActive(true, {noEvents: true});
}
}
@@ -197,17 +201,13 @@ async function loadNoteDetail(origNotePath, options = {}) {
const newTab = !!options.newTab;
const activate = !!options.activate;
const notePath = await treeService.resolveNotePath(origNotePath);
let notePath = await treeService.resolveNotePath(origNotePath);
if (!notePath) {
console.error(`Cannot resolve note path ${origNotePath}`);
// fallback to display something
if (tabContexts.length === 0) {
await openEmptyTab();
}
return;
notePath = 'root';
}
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
@@ -43,6 +43,7 @@ class NoteDetailBook {
this.$zoomInButton = this.$component.find('.book-zoom-in-button');
this.$zoomOutButton = this.$component.find('.book-zoom-out-button');
this.$expandChildrenButton = this.$component.find('.expand-children-button');
this.$help = this.$component.find('.note-detail-book-help');
this.$zoomInButton.on('click', () => this.setZoom(this.zoomLevel - 1));
this.$zoomOutButton.on('click', () => this.setZoom(this.zoomLevel + 1));
@@ -105,6 +106,7 @@ class NoteDetailBook {
async render() {
this.$content.empty();
this.$help.hide();
if (this.isAutoBook()) {
const $addTextLink = $('<a href="javascript:">here</a>').on('click', () => {
@@ -124,7 +126,9 @@ class NoteDetailBook {
}
async renderIntoElement(note, $container) {
for (const childNote of await note.getChildNotes()) {
const childNotes = await note.getChildNotes();
for (const childNote of childNotes) {
const childNotePath = this.ctx.notePath + '/' + childNote.noteId;
const {type, renderedContent} = await noteContentRenderer.getRenderedContent(childNote);
@@ -152,6 +156,10 @@ class NoteDetailBook {
$container.append($card);
}
if (childNotes.length === 0) {
this.$help.show();
}
}
/** @return {boolean} true if this is "auto book" activated (empty text note) and not explicit book note */
@@ -2,7 +2,8 @@ import libraryLoader from "./library_loader.js";
import treeService from './tree.js';
import noteAutocompleteService from './note_autocomplete.js';
import mimeTypesService from './mime_types.js';
import treeCache from "./tree_cache.js";
const ENABLE_INSPECTOR = false;
const mentionSetup = {
feeds: [
@@ -46,6 +47,7 @@ class NoteDetailText {
this.ctx = ctx;
this.$component = ctx.$tabContent.find('.note-detail-text');
this.$editorEl = this.$component.find('.note-detail-text-editor');
this.textEditorPromise = null;
this.textEditor = null;
this.$component.on("dblclick", "img", e => {
@@ -66,44 +68,12 @@ class NoteDetailText {
}
async render() {
if (!this.textEditor) {
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
const codeBlockLanguages =
(await mimeTypesService.getMimeTypes())
.filter(mt => mt.enabled)
.map(mt => {
return {
language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
label: mt.title
}
});
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
// display of $component in both branches.
this.$component.show();
// textEditor might have been initialized during previous await so checking again
// looks like double initialization can freeze CKEditor pretty badly
if (!this.textEditor) {
this.textEditor = await BalloonEditor.create(this.$editorEl[0], {
placeholder: "Type the content of your note here ...",
mention: mentionSetup,
codeBlock: {
languages: codeBlockLanguages
}
});
if (glob.isDev) {
await import('../../libraries/ckeditor/inspector.js');
CKEditorInspector.attach(this.textEditor);
}
this.onNoteChange(() => this.ctx.noteChanged());
}
if (!this.textEditorPromise) {
this.textEditorPromise = this.initEditor();
}
await this.textEditorPromise;
// lazy loading above can take time and tab might have been already switched to another note
if (this.ctx.note && this.ctx.note.type === 'text') {
this.textEditor.isReadOnly = await this.isReadOnly();
@@ -114,16 +84,56 @@ class NoteDetailText {
}
}
async initEditor() {
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
const codeBlockLanguages =
(await mimeTypesService.getMimeTypes())
.filter(mt => mt.enabled)
.map(mt => {
return {
language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
label: mt.title
}
});
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
// display of $component in both branches.
this.$component.show();
const textEditorInstance = await BalloonEditor.create(this.$editorEl[0], {
placeholder: "Type the content of your note here ...",
mention: mentionSetup,
codeBlock: {
languages: codeBlockLanguages
}
});
if (glob.isDev && ENABLE_INSPECTOR) {
await import('../../libraries/ckeditor/inspector.js');
CKEditorInspector.attach(textEditorInstance);
}
this.textEditor = textEditorInstance;
this.onNoteChange(() => this.ctx.noteChanged());
}
getContent() {
let content = this.textEditor.getData();
const content = this.textEditor.getData();
// if content is only tags/whitespace (typically <p>&nbsp;</p>), then just make it empty
// this is important when setting new note to code
if (jQuery(content).text().trim() === '' && !content.includes("<img")) {
content = '';
}
return this.isContentEmpty(content) ? '' : content;
}
return content;
isContentEmpty(content) {
content = content.toLowerCase();
return jQuery(content).text().trim() === ''
&& !content.includes("<img")
&& !content.includes("<section")
}
async isReadOnly() {
@@ -42,6 +42,8 @@ async function setupProtectedSession(password) {
return;
}
$("#container").addClass('protected-session-active');
protectedSessionHolder.setProtectedSessionId(response.protectedSessionId);
protectedSessionHolder.touchProtectedSession();
@@ -3,15 +3,16 @@ import optionsService from "./options.js";
export async function initSpellCheck() {
const options = await optionsService.waitForOptions();
if (!options.is('spellCheckEnabled')) {
return;
}
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
const {remote, shell} = require('electron');
const spellCheckHandler = new SpellCheckHandler();
spellCheckHandler.attachToInput();
// not fully disabling the spellcheck since we want to preserve the context menu
// this will just get rid of the "red squiggles"
if (options.is('spellCheckEnabled')) {
spellCheckHandler.attachToInput();
}
spellCheckHandler.switchLanguage(options.get('spellCheckLanguageCode'));
@@ -162,9 +162,6 @@ class TabContext {
this.noteChangeDisabled = false;
}
// after loading new note make sure editor is scrolled to the top
this.getComponent().scrollToTop();
this.setTitleBar();
this.cleanup(); // esp. on windows autocomplete is not getting closed automatically
@@ -186,6 +183,9 @@ class TabContext {
}
bundleService.executeRelationBundles(this.note, 'runOnNoteView', this);
// after loading new note make sure editor is scrolled to the top
this.getComponent().scrollToTop();
}
async show() {
@@ -350,8 +350,6 @@ class TabContext {
this.$savedIndicator.fadeIn();
this.$scriptArea.empty();
// run async
bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this);
+30 -34
View File
@@ -16,6 +16,8 @@ import TreeContextMenu from "./tree_context_menu.js";
import bundle from "./bundle.js";
import keyboardActionService from "./keyboard_actions.js";
let tree;
const $tree = $("#tree");
const $createTopLevelNoteButton = $("#create-top-level-note-button");
const $collapseTreeButton = $("#collapse-tree-button");
@@ -30,8 +32,6 @@ const frontendLoaded = new Promise(resolve => { setFrontendAsLoaded = resolve; }
* @return {FancytreeNode|null}
*/
function getFocusedNode() {
const tree = $tree.fancytree("getTree");
return tree.getFocusNode();
}
@@ -40,7 +40,7 @@ function getFocusedNode() {
* @return {FancytreeNode|null}
*/
function getActiveNode() {
return $tree.fancytree("getActiveNode");
return tree.getActiveNode();
}
/** @return {FancytreeNode[]} */
@@ -56,7 +56,7 @@ async function getNodesByBranchId(branchId) {
function getNodesByNoteId(noteId) {
utils.assertArguments(noteId);
const list = getTree().getNodesByRef(noteId);
const list = tree.getNodesByRef(noteId);
return list ? list : []; // if no nodes with this refKey are found, fancy tree returns null
}
@@ -191,9 +191,7 @@ async function activateNote(notePath, noteLoadedListener) {
noteDetailService.addDetailLoadedListener(node.data.noteId, noteLoadedListener);
}
// we use noFocus because when we reload the tree because of background changes
// we don't want the reload event to steal focus from whatever was focused before
await node.setActive(true, { noFocus: true });
await node.setActive(true);
clearSelectedNodes();
@@ -311,13 +309,15 @@ async function getSomeNotePath(note) {
const parents = await cur.getParentNotes();
if (!parents.length) {
toastService.throwError(`Can't find parents for note ${cur.noteId}`);
console.error(`Can't find parents for note ${cur.noteId}`);
return;
}
cur = parents[0];
}
path.push('root');
return path.reverse().join('/');
}
@@ -331,7 +331,7 @@ async function setExpandedToServer(branchId, isExpanded) {
/** @return {FancytreeNode[]} */
function getSelectedNodes(stopOnParents = false) {
return getTree().getSelectedNodes(stopOnParents);
return tree.getSelectedNodes(stopOnParents);
}
/** @return {FancytreeNode[]} */
@@ -429,14 +429,14 @@ async function treeInitialized() {
setFrontendAsLoaded();
}
async function initFancyTree(tree) {
utils.assertArguments(tree);
async function initFancyTree(treeData) {
utils.assertArguments(treeData);
$tree.fancytree({
autoScroll: true,
keyboard: false, // we takover keyboard handling in the hotkeys plugin
extensions: ["hotkeys", "dnd5", "clones"],
source: tree,
source: treeData,
scrollParent: $tree,
minExpandLevel: 2, // root can't be collapsed
click: (event, data) => {
@@ -523,19 +523,16 @@ async function initFancyTree(tree) {
return false; // blocks default browser right click menu
});
}
/** @return {Fancytree} */
function getTree() {
return $tree.fancytree('getTree');
tree = $.ui.fancytree.getTree("#tree");
}
async function reload() {
const notes = await loadTree();
const notes = await loadTreeData();
const activeNotePath = getActiveNode() !== null ? await treeUtils.getNotePath(getActiveNode()) : null;
await getTree().reload(notes);
await tree.reload(notes);
// reactivate originally activated node, but don't trigger note loading
if (activeNotePath) {
@@ -559,7 +556,7 @@ function getHashValueFromAddress() {
return str.split("-");
}
async function loadTree() {
async function loadTreeData() {
const resp = await server.get('tree');
treeCache.load(resp.notes, resp.branches);
@@ -580,7 +577,7 @@ async function collapseTree(node = null) {
}
function focusTree() {
getTree().setFocus();
tree.setFocus();
}
async function scrollToActiveNote() {
@@ -637,12 +634,6 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
if (noteDetailService.getActiveTabNoteType() !== 'text') {
extraOptions.saveSelection = false;
}
else {
// just disable this feature altogether - there's a problem that note containing image or table at the beginning
// of the content will be auto-selected by CKEditor and then CTRL-P with no user interaction will automatically save
// the selection - see https://github.com/ckeditor/ckeditor5/issues/1384
extraOptions.saveSelection = false;
}
if (extraOptions.saveSelection) {
[extraOptions.title, extraOptions.content] = parseSelectedHtml(window.cutToNote.getSelectedHtml());
@@ -760,9 +751,9 @@ async function sortAlphabetically(noteId) {
}
async function showTree() {
const tree = await loadTree();
const treeData = await loadTreeData();
await initFancyTree(tree);
await initFancyTree(treeData);
}
ws.subscribeToMessages(message => {
@@ -820,13 +811,13 @@ keyboardActionService.setGlobalActionHandler('CreateNoteAfter', async () => {
});
});
async function createNoteInto() {
async function createNoteInto(saveSelection = false) {
const node = getActiveNode();
if (node) {
await createNote(node, node.data.noteId, 'into', {
isProtected: node.data.isProtected,
saveSelection: true
saveSelection: saveSelection
});
}
}
@@ -875,7 +866,9 @@ async function reloadNotes(noteIds, activateNotePath = null) {
}
}
window.glob.createNoteInto = createNoteInto;
window.glob.cutIntoNote = () => createNoteInto(true);
keyboardActionService.setGlobalActionHandler('CutIntoNote', () => createNoteInto(true));
keyboardActionService.setGlobalActionHandler('CreateNoteInto', createNoteInto);
@@ -916,6 +909,9 @@ async function duplicateNote(noteId, parentNoteId) {
toastService.showMessage(`Note "${origNote.title}" has been duplicated`);
}
function getNodeByKey(key) {
return tree.getNodeByKey(key);
}
keyboardActionService.setGlobalActionHandler('CollapseTree', () => collapseTree()); // don't use shortened form since collapseTree() accepts argument
$collapseTreeButton.on('click', () => collapseTree());
@@ -935,13 +931,12 @@ export default {
setNoteTitle,
setPrefix,
createNote,
createNoteInto,
getSelectedNodes,
getSelectedOrActiveNodes,
clearSelectedNodes,
sortAlphabetically,
showTree,
loadTree,
loadTreeData,
treeInitialized,
setExpandedToServer,
getNodesByNoteId,
@@ -953,5 +948,6 @@ export default {
getSomeNotePath,
focusTree,
scrollToActiveNote,
duplicateNote
duplicateNote,
getNodeByKey
};
@@ -2,16 +2,10 @@ import utils from './utils.js';
import hoistedNoteService from './hoisted_note.js';
import treeCache from "./tree_cache.js";
const $tree = $("#tree");
async function getParentProtectedStatus(node) {
return await hoistedNoteService.isRootNode(node) ? 0 : node.getParent().data.isProtected;
}
function getNodeByKey(key) {
return $tree.fancytree('getNodeByKey', key);
}
function getNoteIdFromNotePath(notePath) {
if (!notePath) {
return null;
@@ -123,7 +117,6 @@ async function getNotePathTitle(notePath) {
export default {
getParentProtectedStatus,
getNodeByKey,
getNotePath,
getNoteIdFromNotePath,
getNoteIdAndParentIdFromNotePath,
+5 -1
View File
@@ -213,7 +213,11 @@ function closeActiveDialog() {
}
function isHtmlEmpty(html) {
return $("<div>").html(html).text().trim().length === 0 && !html.toLowerCase().includes('<img');
html = html.toLowerCase();
return $("<div>").html(html).text().trim().length === 0
&& !html.includes('<img')
&& !html.includes('<section');
}
async function clearBrowserCache() {
+19 -10
View File
@@ -1,18 +1,18 @@
import StandardWidget from "./standard_widget.js";
const TPL = `
<table class="note-info-table">
<table class="note-info-table" style="table-layout: fixed; width: 100%;">
<tr>
<th>Note ID:</th>
<td colspan="3" class="note-info-note-id"></td>
<th nowrap>Note ID:</th>
<td nowrap colspan="3" class="note-info-note-id"></td>
</tr>
<tr>
<th>Created:</th>
<td colspan="3" class="note-info-date-created"></td>
<th nowrap>Created:</th>
<td nowrap colspan="3" style="overflow: hidden; text-overflow: ellipsis;" class="note-info-date-created"></td>
</tr>
<tr>
<th>Modified:</th>
<td colspan="3" class="note-info-date-modified"></td>
<th nowrap>Modified:</th>
<td nowrap colspan="3" style="overflow: hidden; text-overflow: ellipsis;" class="note-info-date-modified"></td>
</tr>
<tr>
<th>Type:</th>
@@ -39,10 +39,19 @@ class NoteInfoWidget extends StandardWidget {
const note = this.ctx.note;
$noteId.text(note.noteId);
$dateCreated.text(note.dateCreated);
$dateModified.text(note.dateModified);
$dateCreated
.text(note.dateCreated)
.attr("title", note.dateCreated);
$dateModified
.text(note.dateModified)
.attr("title", note.dateCreated);
$type.text(note.type);
$mime.text(note.mime).attr("title", note.mime);
$mime
.text(note.mime)
.attr("title", note.mime);
}
eventReceived(name, data) {
+2 -2
View File
@@ -110,7 +110,7 @@ body {
#context-menu-container {
max-height: 100vh;
overflow: auto; /* make it scrollable when exceeding total height of the window */
/* !!! Cannot set overflow: auto, submenus will break !!! */
}
#context-menu-container, #context-menu-container .dropdown-menu {
@@ -407,7 +407,7 @@ body {
position: fixed;
bottom: 10px;
right: 10px;
z-index: 100000;
z-index: 1000;
}
#right-pane {
+11 -1
View File
@@ -594,7 +594,7 @@ table.promoted-attributes-in-tooltip td, table.promoted-attributes-in-tooltip th
padding: 10px;
}
.note-detail-render-help {
.note-detail-render-help, .note-detail-book-help {
margin: 50px;
padding: 20px;
}
@@ -967,4 +967,14 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
padding: 20px;
border-radius: 10px;
background-color: var(--accented-background-color);
}
.include-note.ck-placeholder::before { /* remove placeholder in otherwise empty note */
content: '' !important;
}
.alert-warning {
color: var(--main-text-color) !important;
background-color: var(--accented-background-color) !important;
border-color: var(--main-border-color) !important;
}
+2 -1
View File
@@ -101,7 +101,8 @@ async function deleteBranch(req) {
const branch = await repository.getBranch(req.params.branchId);
const taskContext = TaskContext.getInstance(req.query.taskId, 'delete-notes');
const noteDeleted = await notes.deleteBranch(branch, taskContext);
const deleteId = utils.randomString(10);
const noteDeleted = await notes.deleteBranch(branch, deleteId, taskContext);
if (last) {
taskContext.taskSucceeded();
+15 -1
View File
@@ -55,12 +55,15 @@ async function deleteNote(req) {
const taskId = req.query.taskId;
const last = req.query.last === 'true';
// note how deleteId is separate from taskId - single taskId produces separate deleteId for each "top level" deleted note
const deleteId = utils.randomString(10);
const note = await repository.getNote(noteId);
const taskContext = TaskContext.getInstance(taskId, 'delete-notes');
for (const branch of await note.getBranches()) {
await noteService.deleteBranch(branch, taskContext);
await noteService.deleteBranch(branch, deleteId, taskContext);
}
if (last) {
@@ -68,6 +71,16 @@ async function deleteNote(req) {
}
}
async function undeleteNote(req) {
const note = await repository.getNote(req.params.noteId);
const taskContext = TaskContext.getInstance(utils.randomString(10), 'undelete-notes');
await noteService.undeleteNote(note, note.deleteId, taskContext);
await taskContext.taskSucceeded();
}
async function sortNotes(req) {
const noteId = req.params.noteId;
@@ -169,6 +182,7 @@ module.exports = {
getNote,
updateNote,
deleteNote,
undeleteNote,
createNote,
sortNotes,
protectSubtree,
+1
View File
@@ -6,6 +6,7 @@ const attributes = require('../../services/attributes');
// options allowed to be updated directly in options dialog
const ALLOWED_OPTIONS = new Set([
'eraseNotesAfterTimeInSeconds',
'protectedSessionTimeout',
'noteRevisionSnapshotTimeInterval',
'zoomFactor',
+23 -4
View File
@@ -2,6 +2,7 @@
const sql = require('../../services/sql');
const protectedSessionService = require('../../services/protected_session');
const noteService = require('../../services/notes');
async function getRecentChanges() {
const recentChanges = await sql.getRows(
@@ -10,6 +11,8 @@ async function getRecentChanges() {
SELECT
notes.noteId,
notes.isDeleted AS current_isDeleted,
notes.deleteId AS current_deleteId,
notes.isErased AS current_isErased,
notes.title AS current_title,
notes.isProtected AS current_isProtected,
note_revisions.title,
@@ -19,21 +22,23 @@ async function getRecentChanges() {
JOIN notes USING(noteId)
ORDER BY
note_revisions.utcDateCreated DESC
LIMIT 1000
LIMIT 200
)
UNION ALL SELECT * FROM (
SELECT
notes.noteId,
notes.isDeleted AS current_isDeleted,
notes.deleteId AS current_deleteId,
notes.isErased AS current_isErased,
notes.title AS current_title,
notes.isProtected AS current_isProtected,
notes.title,
notes.utcDateCreated AS date
notes.utcDateModified AS date
FROM
notes
ORDER BY
utcDateCreated DESC
LIMIT 1000
utcDateModified DESC
LIMIT 200
)
ORDER BY date DESC
LIMIT 200`);
@@ -48,6 +53,20 @@ async function getRecentChanges() {
change.title = change.current_title = "[Protected]";
}
}
if (change.current_isDeleted) {
if (change.current_isErased) {
change.canBeUndeleted = false;
}
else {
const deleteId = change.current_deleteId;
const undeletedParentBranches = await noteService.getUndeletedParentBranches(change.noteId, deleteId);
// note (and the subtree) can be undeleted if there's at least one undeleted parent (whose branch would be undeleted by this op)
change.canBeUndeleted = undeletedParentBranches.length > 0;
}
}
}
return recentChanges;
+1
View File
@@ -131,6 +131,7 @@ function register(app) {
apiRoute(GET, '/api/notes/:noteId', notesApiRoute.getNote);
apiRoute(PUT, '/api/notes/:noteId', notesApiRoute.updateNote);
apiRoute(DELETE, '/api/notes/:noteId', notesApiRoute.deleteNote);
apiRoute(PUT, '/api/notes/:noteId/undelete', notesApiRoute.undeleteNote);
apiRoute(POST, '/api/notes/:parentNoteId/children', notesApiRoute.createNote);
apiRoute(PUT, '/api/notes/:noteId/sort', notesApiRoute.sortNotes);
apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectSubtree);
+2 -2
View File
@@ -4,8 +4,8 @@ const build = require('./build');
const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir');
const APP_DB_VERSION = 155;
const SYNC_VERSION = 13;
const APP_DB_VERSION = 156;
const SYNC_VERSION = 14;
const CLIPPER_PROTOCOL_VERSION = "1.0";
module.exports = {
+1 -1
View File
@@ -204,7 +204,7 @@ function BackendScriptApi(currentNote, apiParams) {
this.createDataNote = async (parentNoteId, title, content = {}) => await noteService.createNewNote({
parentNoteId,
title,
content: JSON.stringify(content),
content: JSON.stringify(content, null, '\t'),
type: 'code',
mime: 'application/json'
});
+1 -1
View File
@@ -1 +1 @@
module.exports = { buildDate:"2019-12-30T19:48:54+01:00", buildRevision: "3f1d0e5872d5d9185a3c24b92bcb080d70bcae60" };
module.exports = { buildDate:"2020-01-11T09:54:31+01:00", buildRevision: "5e91b1b5e0fa04affbc1a5a43a874cadc382fe11" };
+9 -6
View File
@@ -21,17 +21,20 @@ module.exports = function(filters, selectedColumns = 'notes.*') {
"notes": null
};
let attrFilterId = 1;
function getAccessor(property) {
let accessor;
if (!VIRTUAL_ATTRIBUTES.includes(property)) {
const alias = "attr_" + property;
// not reusing existing filters to support multi-valued filters e.g. "@tag=christmas @tag=shopping"
// can match notes because @tag can be both "shopping" and "christmas"
const alias = "attr_" + property + "_" + attrFilterId++;
if (!(alias in joins)) {
joins[alias] = `LEFT JOIN attributes AS ${alias} `
+ `ON ${alias}.noteId = notes.noteId `
+ `AND ${alias}.name = '${property}' AND ${alias}.isDeleted = 0`;
}
// forcing to use particular index since SQLite query planner would often choose something pretty bad
joins[alias] = `LEFT JOIN attributes AS ${alias} INDEXED BY IDX_attributes_noteId_index `
+ `ON ${alias}.noteId = notes.noteId `
+ `AND ${alias}.name = '${property}' AND ${alias}.isDeleted = 0`;
accessor = `${alias}.value`;
}
+35 -25
View File
@@ -18,18 +18,6 @@ class ConsistencyChecks {
this.fixedIssues = false;
}
async findIssues(query, errorCb) {
const results = await sql.getRows(query);
for (const res of results) {
logError(errorCb(res));
this.unrecoveredConsistencyErrors = true;
}
return results;
}
async findAndFixIssues(query, fixerCb) {
const results = await sql.getRows(query);
@@ -175,13 +163,6 @@ class ConsistencyChecks {
logError(`Relation ${attributeId} references missing note ${noteId}`)
}
});
await this.findIssues(`
SELECT noteRevisionId, note_revisions.noteId
FROM note_revisions
LEFT JOIN notes USING (noteId)
WHERE notes.noteId IS NULL`,
({noteRevisionId, noteId}) => `Note revision ${noteRevisionId} references missing note ${noteId}`);
}
async findExistencyIssues() {
@@ -335,13 +316,22 @@ class ConsistencyChecks {
}
});
await this.findIssues(`
await this.findAndFixIssues(`
SELECT noteId
FROM notes
JOIN note_contents USING (noteId)
WHERE isErased = 1
AND content IS NOT NULL`,
({noteId}) => `Note ${noteId} content is not null even though the note is erased`);
async ({noteId}) => {
if (this.autoFix) {
await sql.execute(`UPDATE note_contents SET content = NULL WHERE noteId = ?`, [noteId]);
logFix(`Note ${noteId} content has been set to null since the note is erased`);
}
else {
logError(`Note ${noteId} content is not null even though the note is erased`);
}
});
await this.findAndFixIssues(`
SELECT noteId, noteRevisionId
@@ -398,20 +388,40 @@ class ConsistencyChecks {
}
});
await this.findIssues(`
await this.findAndFixIssues(`
SELECT noteRevisionId
FROM note_revisions
JOIN note_revision_contents USING (noteRevisionId)
WHERE isErased = 1
AND content IS NOT NULL`,
({noteRevisionId}) => `Note revision ${noteRevisionId} content is not null even though the note revision is erased`);
async ({noteRevisionId}) => {
if (this.autoFix) {
await sql.execute(`UPDATE note_revision_contents SET content = NULL WHERE noteRevisionId = ?`, [noteRevisionId]);
await this.findIssues(`
logFix(`Note revision ${noteRevisionId} content was set to null since the note revision is erased`);
}
else {
logError(`Note revision ${noteRevisionId} content is not null even though the note revision is erased`);
}
});
await this.findAndFixIssues(`
SELECT noteId
FROM notes
WHERE isErased = 1
AND isDeleted = 0`,
({noteId}) => `Note ${noteId} is not deleted even though it is erased`);
async ({noteId}) => {
if (this.autoFix) {
const note = await repository.getNote(noteId);
note.isDeleted = true;
await note.save();
logFix(`Note ${noteId} was set to deleted since it is erased`);
}
else {
logError(`Note ${noteId} is not deleted even though it is erased`);
}
});
await this.findAndFixIssues(`
SELECT parentNoteId
+10 -8
View File
@@ -75,14 +75,17 @@ async function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSw
}
async function shrinkImage(buffer, originalName) {
const resizedImage = await resize(buffer);
// we do resizing with max (100) quality which will be trimmed during optimization step next
const resizedImage = await resize(buffer, 100);
let finalImageBuffer;
const jpegQuality = await optionService.getOptionInt('imageJpegQuality');
try {
finalImageBuffer = await optimize(resizedImage);
finalImageBuffer = await optimize(resizedImage, jpegQuality);
} catch (e) {
log.error("Failed to optimize image '" + originalName + "'\nStack: " + e.stack);
finalImageBuffer = resizedImage;
finalImageBuffer = await resize(buffer, jpegQuality);
}
// if resizing & shrinking did not help with size then save the original
@@ -94,7 +97,7 @@ async function shrinkImage(buffer, originalName) {
return finalImageBuffer;
}
async function resize(buffer) {
async function resize(buffer, quality) {
const imageMaxWidthHeight = await optionService.getOptionInt('imageMaxWidthHeight');
const image = await jimp.read(buffer);
@@ -106,8 +109,7 @@ async function resize(buffer) {
image.resize(jimp.AUTO, imageMaxWidthHeight);
}
// we do resizing with max quality which will be trimmed during optimization step next
image.quality(100);
image.quality(quality);
// when converting PNG to JPG we lose alpha channel, this is replaced by white to match Trilium white background
image.background(0xFFFFFFFF);
@@ -115,11 +117,11 @@ async function resize(buffer) {
return image.getBufferAsync(jimp.MIME_JPEG);
}
async function optimize(buffer) {
async function optimize(buffer, jpegQuality) {
return await imagemin.buffer(buffer, {
plugins: [
imageminMozJpeg({
quality: await optionService.getOptionInt('imageJpegQuality')
quality: jpegQuality
}),
imageminPngQuant({
quality: [0, 0.7]
+2 -2
View File
@@ -1,5 +1,5 @@
const sax = require("sax");
const fileType = require('file-type');
const FileType = require('file-type');
const stream = require('stream');
const log = require("../log");
const utils = require("../utils");
@@ -242,7 +242,7 @@ async function importEnex(taskContext, file, parentNote) {
const mediaRegex = new RegExp(`<en-media hash="${hash}"[^>]*>`, 'g');
const fileTypeFromBuffer = fileType(resource.content);
const fileTypeFromBuffer = await FileType.fromBuffer(resource.content);
if (fileTypeFromBuffer) {
// If fileType returns something for buffer, then set the mime given
resource.mime = fileTypeFromBuffer.mime;
+1 -1
View File
@@ -147,7 +147,7 @@ async function importTar(taskContext, fileBuffer, importRootNote) {
continue;
}
if (attr.type === 'relation' && ['internalLink', 'imageLink', 'relationMapLink'].includes(attr.name)) {
if (attr.type === 'relation' && ['internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink'].includes(attr.name)) {
// these relations are created automatically and as such don't need to be duplicated in the import
continue;
}
+5
View File
@@ -255,6 +255,11 @@ const DEFAULT_KEYBOARD_ACTIONS = [
defaultShortcuts: [],
description: "Pastes Markdown from clipboard into text note"
},
{
actionName: "CutIntoNote",
defaultShortcuts: [],
description: "Cuts the selection from the current note and creates subnote with the selected text"
},
{
separator: "Other"
+135 -12
View File
@@ -48,7 +48,7 @@ function deriveMime(type, mime) {
mime = 'text/plain';
} else if (['relation-map', 'search'].includes(type)) {
mime = 'application/json';
} else if (type === 'render') {
} else if (['render', 'book'].includes(type)) {
mime = '';
}
@@ -242,6 +242,20 @@ function findInternalLinks(content, foundLinks) {
return content.replace(/href="[^"]*#root/g, 'href="#root');
}
function findIncludeNoteLinks(content, foundLinks) {
const re = /<section class="include-note" data-note-id="([a-zA-Z0-9]+)">/g;
let match;
while (match = re.exec(content)) {
foundLinks.push({
name: 'includeNoteLink',
value: match[1]
});
}
return content;
}
function findRelationMapLinks(content, foundLinks) {
const obj = JSON.parse(content);
@@ -267,6 +281,7 @@ async function saveLinks(note, content) {
if (note.type === 'text') {
content = findImageLinks(content, foundLinks);
content = findInternalLinks(content, foundLinks);
content = findIncludeNoteLinks(content, foundLinks);
}
else if (note.type === 'relation-map') {
findRelationMapLinks(content, foundLinks);
@@ -389,8 +404,14 @@ async function updateNote(noteId, noteUpdates) {
};
}
/** @return {boolean} - true if note has been deleted, false otherwise */
async function deleteBranch(branch, taskContext) {
/**
* @param {Branch} branch
* @param {string} deleteId
* @param {TaskContext} taskContext
*
* @return {boolean} - true if note has been deleted, false otherwise
*/
async function deleteBranch(branch, deleteId, taskContext) {
taskContext.increaseProgressCount();
if (!branch || branch.isDeleted) {
@@ -405,26 +426,32 @@ async function deleteBranch(branch, taskContext) {
}
branch.isDeleted = true;
branch.deleteId = deleteId;
await branch.save();
const note = await branch.getNote();
const notDeletedBranches = await note.getBranches();
if (notDeletedBranches.length === 0) {
note.isDeleted = true;
await note.save();
for (const childBranch of await note.getChildBranches()) {
await deleteBranch(childBranch, taskContext);
await deleteBranch(childBranch, deleteId, taskContext);
}
// first delete children and then parent - this will show up better in recent changes
note.isDeleted = true;
note.deleteId = deleteId;
await note.save();
for (const attribute of await note.getOwnedAttributes()) {
attribute.isDeleted = true;
attribute.deleteId = deleteId;
await attribute.save();
}
for (const relation of await note.getTargetRelations()) {
relation.isDeleted = true;
relation.deleteId = deleteId;
await relation.save();
}
@@ -435,6 +462,88 @@ async function deleteBranch(branch, taskContext) {
}
}
/**
* @param {Note} note
* @param {string} deleteId
* @param {TaskContext} taskContext
*/
async function undeleteNote(note, deleteId, taskContext) {
const undeletedParentBranches = await getUndeletedParentBranches(note.noteId, deleteId);
if (undeletedParentBranches.length === 0) {
// cannot undelete if there's no undeleted parent
return;
}
for (const parentBranch of undeletedParentBranches) {
await undeleteBranch(parentBranch, deleteId, taskContext);
}
}
/**
* @param {Branch} branch
* @param {string} deleteId
* @param {TaskContext} taskContext
*/
async function undeleteBranch(branch, deleteId, taskContext) {
if (!branch.isDeleted) {
return;
}
const note = await branch.getNote();
if (note.isDeleted && note.deleteId !== deleteId) {
return;
}
branch.isDeleted = false;
await branch.save();
taskContext.increaseProgressCount();
if (note.isDeleted && note.deleteId === deleteId) {
note.isDeleted = false;
await note.save();
const attrs = await repository.getEntities(`
SELECT * FROM attributes
WHERE isDeleted = 1
AND deleteId = ?
AND (noteId = ?
OR (type = 'relation' AND value = ?))`, [deleteId, note.noteId, note.noteId]);
for (const attr of attrs) {
attr.isDeleted = false;
await attr.save();
}
const childBranches = await repository.getEntities(`
SELECT branches.*
FROM branches
WHERE branches.isDeleted = 1
AND branches.deleteId = ?
AND branches.parentNoteId = ?`, [deleteId, note.noteId]);
for (const childBranch of childBranches) {
await undeleteBranch(childBranch, deleteId, taskContext);
}
}
}
/**
* @return return deleted branches of an undeleted parent note
*/
async function getUndeletedParentBranches(noteId, deleteId) {
return await repository.getEntities(`
SELECT branches.*
FROM branches
JOIN notes AS parentNote ON parentNote.noteId = branches.parentNoteId
WHERE branches.noteId = ?
AND branches.isDeleted = 1
AND branches.deleteId = ?
AND parentNote.isDeleted = 0`, [noteId, deleteId]);
}
async function scanForLinks(noteId) {
const note = await repository.getNote(noteId);
if (!note || !['text', 'relation-map'].includes(note.type)) {
@@ -453,7 +562,9 @@ async function scanForLinks(noteId) {
}
async function eraseDeletedNotes() {
const cutoffDate = new Date(Date.now() - 48 * 3600 * 1000);
const eraseNotesAfterTimeInSeconds = await optionService.getOptionInt('eraseNotesAfterTimeInSeconds');
const cutoffDate = new Date(Date.now() - eraseNotesAfterTimeInSeconds * 1000);
const noteIdsToErase = await sql.getColumn("SELECT noteId FROM notes WHERE isDeleted = 1 AND isErased = 0 AND notes.utcDateModified <= ?", [dateUtils.utcDateStr(cutoffDate)]);
@@ -467,10 +578,11 @@ async function eraseDeletedNotes() {
// - we don't want change the hash since this erasing happens on each instance separately
// and changing the hash would fire up the sync errors temporarily
// setting contentLength to zero would serve no benefit and it leaves potentially useful trail
await sql.executeMany(`
UPDATE notes
SET isErased = 1
SET title = '[deleted]',
contentLength = 0,
isErased = 1
WHERE noteId IN (???)`, noteIdsToErase);
await sql.executeMany(`
@@ -488,8 +600,17 @@ async function eraseDeletedNotes() {
await sql.executeMany(`
UPDATE note_revisions
SET isErased = 1,
title = NULL
title = NULL,
contentLength = 0
WHERE isErased = 0 AND noteId IN (???)`, noteIdsToErase);
await sql.executeMany(`
UPDATE attributes
SET name = 'deleted',
value = ''
WHERE noteId IN (???)`, noteIdsToErase);
log.info(`Erased notes: ${JSON.stringify(noteIdsToErase)}`);
}
async function duplicateNote(noteId, parentNoteId) {
@@ -542,7 +663,9 @@ module.exports = {
createNewNoteWithTarget,
updateNote,
deleteBranch,
undeleteNote,
protectNoteRecursively,
scanForLinks,
duplicateNote
duplicateNote,
getUndeletedParentBranches
};
+2 -1
View File
@@ -80,7 +80,8 @@ const defaultOptions = [
{ name: 'leftPaneWidth', value: '25', isSynced: false },
{ name: 'rightPaneWidth', value: '25', isSynced: false },
{ name: 'rightPaneVisible', value: 'true', isSynced: false },
{ name: 'nativeTitleBarVisible', value: 'false', isSynced: false }
{ name: 'nativeTitleBarVisible', value: 'false', isSynced: false },
{ name: 'eraseNotesAfterTimeInSeconds', value: '604800', isSynced: true } // default is 7 days
];
async function initStartupOptions() {
+1 -1
View File
@@ -1,6 +1,6 @@
const dayjs = require("dayjs");
const filterRegex = /(\b(AND|OR)\s+)?@(!?)([\p{L}\p{Number}_]+|"[^"]+")\s*((=|!=|<|<=|>|>=|!?\*=|!?=\*|!?\*=\*)\s*(\S+|"[^"]+"))?/igu;
const filterRegex = /(\b(AND|OR)\s+)?@(!?)([\p{L}\p{Number}_]+|"[^"]+")\s*((=|!=|<|<=|>|>=|!?\*=|!?=\*|!?\*=\*)\s*([^\s=*]+|"[^"]+"))?/igu;
const smartValueRegex = /^(NOW|TODAY|WEEK|MONTH|YEAR) *([+\-] *\d+)?$/i;
function calculateSmartValue(v) {
-1
View File
@@ -2,7 +2,6 @@ const sql = require('./sql');
const ScriptContext = require('./script_context');
const repository = require('./repository');
const cls = require('./cls');
const sourceIdService = require('./source_id');
const log = require('./log');
async function executeNote(note, apiParams) {
+8 -2
View File
@@ -12,8 +12,14 @@ class TaskContext {
this.data = data;
// progressCount is meant to represent just some progress - to indicate the task is not stuck
this.progressCount = 0;
this.lastSentCountTs = Date.now();
this.progressCount = -1; // we're incrementing immediatelly
this.lastSentCountTs = 0; // 0 will guarantee first message will be sent
// just the fact this has been initialized is a progress which should be sent to clients
// this is esp. important when importing big files/images which take long time to upload/process
// which means that first "real" increaseProgressCount() will be called quite late and user is without
// feedback until then
this.increaseProgressCount();
}
/** @return {TaskContext} */
+1 -1
View File
@@ -137,7 +137,7 @@
</div>
</div>
<div style="display: flex; height: 100%;">
<div style="display: flex; flex-grow: 1; flex-shrink: 1; min-height: 0;">
<div id="left-pane" class="hide-in-zen-mode">
<div id="global-buttons">
<a id="create-top-level-note-button" title="Create new top level note" class="icon-action bx bx-folder-plus"></a>
+4
View File
@@ -13,5 +13,9 @@
title="Zoom Out"></button>
</div>
<div class="note-detail-book-help alert alert-warning">
This note of type Book doesn't have any child notes so there's nothing to display. See <a href="https://github.com/zadam/trilium/wiki/Book-note">wiki</a> for details.
</div>
<div class="note-detail-book-content"></div>
</div>
+1 -1
View File
@@ -9,7 +9,7 @@
</button>
</div>
<div class="modal-body">
<table class="table">
<table class="table table-borderless">
<tr>
<th>Homepage:</th>
<td><a href="https://github.com/zadam/trilium" class="external">https://github.com/zadam/trilium</a></td>
+2 -2
View File
@@ -1,5 +1,5 @@
<button id="hide-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-right" title="Hide sidebar"></button>
<button id="show-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-left" title="Show sidebar"></button>
<button id="hide-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-right hide-in-zen-mode" title="Hide sidebar"></button>
<button id="show-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-left hide-in-zen-mode" title="Show sidebar"></button>
<div id="right-pane" class="hide-in-zen-mode">
<div id="sidebar-container"></div>