mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	note content refactoring, WIP
This commit is contained in:
		| @@ -363,324 +363,330 @@ parentNoteId</ColNames> | |||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <DefaultExpression>NULL</DefaultExpression> |       <DefaultExpression>NULL</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <index id="87" parent="11" name="sqlite_autoindex_note_contents_1"> |     <column id="87" parent="11" name="hash"> | ||||||
|  |       <Position>5</Position> | ||||||
|  |       <DataType>TEXT|0s</DataType> | ||||||
|  |       <NotNull>1</NotNull> | ||||||
|  |       <DefaultExpression>""</DefaultExpression> | ||||||
|  |     </column> | ||||||
|  |     <index id="88" parent="11" name="sqlite_autoindex_note_contents_1"> | ||||||
|       <NameSurrogate>1</NameSurrogate> |       <NameSurrogate>1</NameSurrogate> | ||||||
|       <ColNames>noteContentId</ColNames> |       <ColNames>noteContentId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|       <Unique>1</Unique> |       <Unique>1</Unique> | ||||||
|     </index> |     </index> | ||||||
|     <index id="88" parent="11" name="IDX_note_contents_noteId"> |     <index id="89" parent="11" name="IDX_note_contents_noteId"> | ||||||
|       <ColNames>noteId</ColNames> |       <ColNames>noteId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|     </index> |     </index> | ||||||
|     <key id="89" parent="11"> |     <key id="90" parent="11"> | ||||||
|       <ColNames>noteContentId</ColNames> |       <ColNames>noteContentId</ColNames> | ||||||
|       <Primary>1</Primary> |       <Primary>1</Primary> | ||||||
|       <UnderlyingIndexName>sqlite_autoindex_note_contents_1</UnderlyingIndexName> |       <UnderlyingIndexName>sqlite_autoindex_note_contents_1</UnderlyingIndexName> | ||||||
|     </key> |     </key> | ||||||
|     <column id="90" parent="12" name="noteRevisionId"> |     <column id="91" parent="12" name="noteRevisionId"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="91" parent="12" name="noteId"> |     <column id="92" parent="12" name="noteId"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="92" parent="12" name="title"> |     <column id="93" parent="12" name="title"> | ||||||
|       <Position>3</Position> |       <Position>3</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="93" parent="12" name="content"> |     <column id="94" parent="12" name="content"> | ||||||
|       <Position>4</Position> |       <Position>4</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="94" parent="12" name="isProtected"> |     <column id="95" parent="12" name="isProtected"> | ||||||
|       <Position>5</Position> |       <Position>5</Position> | ||||||
|       <DataType>INT|0s</DataType> |       <DataType>INT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>0</DefaultExpression> |       <DefaultExpression>0</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="95" parent="12" name="dateModifiedFrom"> |     <column id="96" parent="12" name="dateModifiedFrom"> | ||||||
|       <Position>6</Position> |       <Position>6</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="96" parent="12" name="dateModifiedTo"> |     <column id="97" parent="12" name="dateModifiedTo"> | ||||||
|       <Position>7</Position> |       <Position>7</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="97" parent="12" name="type"> |     <column id="98" parent="12" name="type"> | ||||||
|       <Position>8</Position> |       <Position>8</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>''</DefaultExpression> |       <DefaultExpression>''</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="98" parent="12" name="mime"> |     <column id="99" parent="12" name="mime"> | ||||||
|       <Position>9</Position> |       <Position>9</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>''</DefaultExpression> |       <DefaultExpression>''</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="99" parent="12" name="hash"> |     <column id="100" parent="12" name="hash"> | ||||||
|       <Position>10</Position> |       <Position>10</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>""</DefaultExpression> |       <DefaultExpression>""</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <index id="100" parent="12" name="sqlite_autoindex_note_revisions_1"> |     <index id="101" parent="12" name="sqlite_autoindex_note_revisions_1"> | ||||||
|       <NameSurrogate>1</NameSurrogate> |       <NameSurrogate>1</NameSurrogate> | ||||||
|       <ColNames>noteRevisionId</ColNames> |       <ColNames>noteRevisionId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|       <Unique>1</Unique> |       <Unique>1</Unique> | ||||||
|     </index> |     </index> | ||||||
|     <index id="101" parent="12" name="IDX_note_revisions_noteId"> |     <index id="102" parent="12" name="IDX_note_revisions_noteId"> | ||||||
|       <ColNames>noteId</ColNames> |       <ColNames>noteId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|     </index> |     </index> | ||||||
|     <index id="102" parent="12" name="IDX_note_revisions_dateModifiedFrom"> |     <index id="103" parent="12" name="IDX_note_revisions_dateModifiedFrom"> | ||||||
|       <ColNames>dateModifiedFrom</ColNames> |       <ColNames>dateModifiedFrom</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|     </index> |     </index> | ||||||
|     <index id="103" parent="12" name="IDX_note_revisions_dateModifiedTo"> |     <index id="104" parent="12" name="IDX_note_revisions_dateModifiedTo"> | ||||||
|       <ColNames>dateModifiedTo</ColNames> |       <ColNames>dateModifiedTo</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|     </index> |     </index> | ||||||
|     <key id="104" parent="12"> |     <key id="105" parent="12"> | ||||||
|       <ColNames>noteRevisionId</ColNames> |       <ColNames>noteRevisionId</ColNames> | ||||||
|       <Primary>1</Primary> |       <Primary>1</Primary> | ||||||
|       <UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName> |       <UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName> | ||||||
|     </key> |     </key> | ||||||
|     <column id="105" parent="13" name="noteId"> |     <column id="106" parent="13" name="noteId"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="106" parent="13" name="title"> |     <column id="107" parent="13" name="title"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>"note"</DefaultExpression> |       <DefaultExpression>"note"</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="107" parent="13" name="isProtected"> |     <column id="108" parent="13" name="isProtected"> | ||||||
|       <Position>3</Position> |       <Position>3</Position> | ||||||
|       <DataType>INT|0s</DataType> |       <DataType>INT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>0</DefaultExpression> |       <DefaultExpression>0</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="108" parent="13" name="type"> |     <column id="109" parent="13" name="type"> | ||||||
|       <Position>4</Position> |       <Position>4</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>'text'</DefaultExpression> |       <DefaultExpression>'text'</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="109" parent="13" name="mime"> |     <column id="110" parent="13" name="mime"> | ||||||
|       <Position>5</Position> |       <Position>5</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>'text/html'</DefaultExpression> |       <DefaultExpression>'text/html'</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="110" parent="13" name="hash"> |     <column id="111" parent="13" name="hash"> | ||||||
|       <Position>6</Position> |       <Position>6</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>""</DefaultExpression> |       <DefaultExpression>""</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="111" parent="13" name="isDeleted"> |     <column id="112" parent="13" name="isDeleted"> | ||||||
|       <Position>7</Position> |       <Position>7</Position> | ||||||
|       <DataType>INT|0s</DataType> |       <DataType>INT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>0</DefaultExpression> |       <DefaultExpression>0</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="112" parent="13" name="dateCreated"> |     <column id="113" parent="13" name="dateCreated"> | ||||||
|       <Position>8</Position> |       <Position>8</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="113" parent="13" name="dateModified"> |     <column id="114" parent="13" name="dateModified"> | ||||||
|       <Position>9</Position> |       <Position>9</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <index id="114" parent="13" name="sqlite_autoindex_notes_1"> |     <index id="115" parent="13" name="sqlite_autoindex_notes_1"> | ||||||
|       <NameSurrogate>1</NameSurrogate> |       <NameSurrogate>1</NameSurrogate> | ||||||
|       <ColNames>noteId</ColNames> |       <ColNames>noteId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|       <Unique>1</Unique> |       <Unique>1</Unique> | ||||||
|     </index> |     </index> | ||||||
|     <index id="115" parent="13" name="IDX_notes_isDeleted"> |     <index id="116" parent="13" name="IDX_notes_isDeleted"> | ||||||
|       <ColNames>isDeleted</ColNames> |       <ColNames>isDeleted</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|     </index> |     </index> | ||||||
|     <key id="116" parent="13"> |     <key id="117" parent="13"> | ||||||
|       <ColNames>noteId</ColNames> |       <ColNames>noteId</ColNames> | ||||||
|       <Primary>1</Primary> |       <Primary>1</Primary> | ||||||
|       <UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName> |       <UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName> | ||||||
|     </key> |     </key> | ||||||
|     <column id="117" parent="14" name="name"> |     <column id="118" parent="14" name="name"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="118" parent="14" name="value"> |     <column id="119" parent="14" name="value"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="119" parent="14" name="dateModified"> |     <column id="120" parent="14" name="dateModified"> | ||||||
|       <Position>3</Position> |       <Position>3</Position> | ||||||
|       <DataType>INT|0s</DataType> |       <DataType>INT|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="120" parent="14" name="isSynced"> |     <column id="121" parent="14" name="isSynced"> | ||||||
|       <Position>4</Position> |       <Position>4</Position> | ||||||
|       <DataType>INTEGER|0s</DataType> |       <DataType>INTEGER|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>0</DefaultExpression> |       <DefaultExpression>0</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="121" parent="14" name="hash"> |     <column id="122" parent="14" name="hash"> | ||||||
|       <Position>5</Position> |       <Position>5</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>""</DefaultExpression> |       <DefaultExpression>""</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="122" parent="14" name="dateCreated"> |     <column id="123" parent="14" name="dateCreated"> | ||||||
|       <Position>6</Position> |       <Position>6</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression> |       <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <index id="123" parent="14" name="sqlite_autoindex_options_1"> |     <index id="124" parent="14" name="sqlite_autoindex_options_1"> | ||||||
|       <NameSurrogate>1</NameSurrogate> |       <NameSurrogate>1</NameSurrogate> | ||||||
|       <ColNames>name</ColNames> |       <ColNames>name</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|       <Unique>1</Unique> |       <Unique>1</Unique> | ||||||
|     </index> |     </index> | ||||||
|     <key id="124" parent="14"> |     <key id="125" parent="14"> | ||||||
|       <ColNames>name</ColNames> |       <ColNames>name</ColNames> | ||||||
|       <Primary>1</Primary> |       <Primary>1</Primary> | ||||||
|       <UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName> |       <UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName> | ||||||
|     </key> |     </key> | ||||||
|     <column id="125" parent="15" name="branchId"> |     <column id="126" parent="15" name="branchId"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="126" parent="15" name="notePath"> |     <column id="127" parent="15" name="notePath"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="127" parent="15" name="hash"> |     <column id="128" parent="15" name="hash"> | ||||||
|       <Position>3</Position> |       <Position>3</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <DefaultExpression>""</DefaultExpression> |       <DefaultExpression>""</DefaultExpression> | ||||||
|     </column> |     </column> | ||||||
|     <column id="128" parent="15" name="dateCreated"> |     <column id="129" parent="15" name="dateCreated"> | ||||||
|       <Position>4</Position> |       <Position>4</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="129" parent="15" name="isDeleted"> |     <column id="130" parent="15" name="isDeleted"> | ||||||
|       <Position>5</Position> |       <Position>5</Position> | ||||||
|       <DataType>INT|0s</DataType> |       <DataType>INT|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <index id="130" parent="15" name="sqlite_autoindex_recent_notes_1"> |     <index id="131" parent="15" name="sqlite_autoindex_recent_notes_1"> | ||||||
|       <NameSurrogate>1</NameSurrogate> |       <NameSurrogate>1</NameSurrogate> | ||||||
|       <ColNames>branchId</ColNames> |       <ColNames>branchId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|       <Unique>1</Unique> |       <Unique>1</Unique> | ||||||
|     </index> |     </index> | ||||||
|     <key id="131" parent="15"> |     <key id="132" parent="15"> | ||||||
|       <ColNames>branchId</ColNames> |       <ColNames>branchId</ColNames> | ||||||
|       <Primary>1</Primary> |       <Primary>1</Primary> | ||||||
|       <UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName> |       <UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName> | ||||||
|     </key> |     </key> | ||||||
|     <column id="132" parent="16" name="sourceId"> |     <column id="133" parent="16" name="sourceId"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="133" parent="16" name="dateCreated"> |     <column id="134" parent="16" name="dateCreated"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <index id="134" parent="16" name="sqlite_autoindex_source_ids_1"> |     <index id="135" parent="16" name="sqlite_autoindex_source_ids_1"> | ||||||
|       <NameSurrogate>1</NameSurrogate> |       <NameSurrogate>1</NameSurrogate> | ||||||
|       <ColNames>sourceId</ColNames> |       <ColNames>sourceId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|       <Unique>1</Unique> |       <Unique>1</Unique> | ||||||
|     </index> |     </index> | ||||||
|     <key id="135" parent="16"> |     <key id="136" parent="16"> | ||||||
|       <ColNames>sourceId</ColNames> |       <ColNames>sourceId</ColNames> | ||||||
|       <Primary>1</Primary> |       <Primary>1</Primary> | ||||||
|       <UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName> |       <UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName> | ||||||
|     </key> |     </key> | ||||||
|     <column id="136" parent="17" name="type"> |     <column id="137" parent="17" name="type"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|       <DataType>text|0s</DataType> |       <DataType>text|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="137" parent="17" name="name"> |     <column id="138" parent="17" name="name"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|       <DataType>text|0s</DataType> |       <DataType>text|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="138" parent="17" name="tbl_name"> |     <column id="139" parent="17" name="tbl_name"> | ||||||
|       <Position>3</Position> |       <Position>3</Position> | ||||||
|       <DataType>text|0s</DataType> |       <DataType>text|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="139" parent="17" name="rootpage"> |     <column id="140" parent="17" name="rootpage"> | ||||||
|       <Position>4</Position> |       <Position>4</Position> | ||||||
|       <DataType>integer|0s</DataType> |       <DataType>integer|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="140" parent="17" name="sql"> |     <column id="141" parent="17" name="sql"> | ||||||
|       <Position>5</Position> |       <Position>5</Position> | ||||||
|       <DataType>text|0s</DataType> |       <DataType>text|0s</DataType> | ||||||
|     </column> |     </column> | ||||||
|     <column id="141" parent="18" name="name"> |     <column id="142" parent="18" name="name"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|     </column> |     </column> | ||||||
|     <column id="142" parent="18" name="seq"> |     <column id="143" parent="18" name="seq"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|     </column> |     </column> | ||||||
|     <column id="143" parent="19" name="id"> |     <column id="144" parent="19" name="id"> | ||||||
|       <Position>1</Position> |       <Position>1</Position> | ||||||
|       <DataType>INTEGER|0s</DataType> |       <DataType>INTEGER|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|       <SequenceIdentity>1</SequenceIdentity> |       <SequenceIdentity>1</SequenceIdentity> | ||||||
|     </column> |     </column> | ||||||
|     <column id="144" parent="19" name="entityName"> |     <column id="145" parent="19" name="entityName"> | ||||||
|       <Position>2</Position> |       <Position>2</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="145" parent="19" name="entityId"> |     <column id="146" parent="19" name="entityId"> | ||||||
|       <Position>3</Position> |       <Position>3</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="146" parent="19" name="sourceId"> |     <column id="147" parent="19" name="sourceId"> | ||||||
|       <Position>4</Position> |       <Position>4</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <column id="147" parent="19" name="syncDate"> |     <column id="148" parent="19" name="syncDate"> | ||||||
|       <Position>5</Position> |       <Position>5</Position> | ||||||
|       <DataType>TEXT|0s</DataType> |       <DataType>TEXT|0s</DataType> | ||||||
|       <NotNull>1</NotNull> |       <NotNull>1</NotNull> | ||||||
|     </column> |     </column> | ||||||
|     <index id="148" parent="19" name="IDX_sync_entityName_entityId"> |     <index id="149" parent="19" name="IDX_sync_entityName_entityId"> | ||||||
|       <ColNames>entityName |       <ColNames>entityName | ||||||
| entityId</ColNames> | entityId</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|       <Unique>1</Unique> |       <Unique>1</Unique> | ||||||
|     </index> |     </index> | ||||||
|     <index id="149" parent="19" name="IDX_sync_syncDate"> |     <index id="150" parent="19" name="IDX_sync_syncDate"> | ||||||
|       <ColNames>syncDate</ColNames> |       <ColNames>syncDate</ColNames> | ||||||
|       <ColumnCollations></ColumnCollations> |       <ColumnCollations></ColumnCollations> | ||||||
|     </index> |     </index> | ||||||
|     <key id="150" parent="19"> |     <key id="151" parent="19"> | ||||||
|       <ColNames>id</ColNames> |       <ColNames>id</ColNames> | ||||||
|       <Primary>1</Primary> |       <Primary>1</Primary> | ||||||
|     </key> |     </key> | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS "note_contents" ( | |||||||
|   `noteId`	TEXT NOT NULL, |   `noteId`	TEXT NOT NULL, | ||||||
|   `isProtected`	INT NOT NULL DEFAULT 0, |   `isProtected`	INT NOT NULL DEFAULT 0, | ||||||
|   `content`	TEXT NULL DEFAULT NULL, |   `content`	TEXT NULL DEFAULT NULL, | ||||||
|  |   `hash` TEXT DEFAULT "" NOT NULL, | ||||||
|   PRIMARY KEY(`noteContentId`) |   PRIMARY KEY(`noteContentId`) | ||||||
| ); | ); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -67,6 +67,13 @@ class Note extends Entity { | |||||||
|         return this.noteContent; |         return this.noteContent; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** @returns {Promise<*>} */ | ||||||
|  |     async getContent() { | ||||||
|  |         const noteContent = await this.getNoteContent(); | ||||||
|  |  | ||||||
|  |         return noteContent.content; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */ |     /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */ | ||||||
|     isRoot() { |     isRoot() { | ||||||
|         return this.noteId === 'root'; |         return this.noteId === 'root'; | ||||||
| @@ -606,10 +613,6 @@ class Note extends Entity { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     beforeSaving() { |     beforeSaving() { | ||||||
|         if (this.isJson() && this.jsonContent) { |  | ||||||
|             this.content = JSON.stringify(this.jsonContent, null, '\t'); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // we do this here because encryption needs the note ID for the IV |         // we do this here because encryption needs the note ID for the IV | ||||||
|         this.generateIdIfNecessary(); |         this.generateIdIfNecessary(); | ||||||
|  |  | ||||||
| @@ -637,7 +640,6 @@ class Note extends Entity { | |||||||
|             else { |             else { | ||||||
|                 // updating protected note outside of protected session means we will keep original ciphertexts |                 // updating protected note outside of protected session means we will keep original ciphertexts | ||||||
|                 pojo.title = pojo.titleCipherText; |                 pojo.title = pojo.titleCipherText; | ||||||
|                 pojo.content = pojo.contentCipherText; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -645,7 +647,6 @@ class Note extends Entity { | |||||||
|         delete pojo.isContentAvailable; |         delete pojo.isContentAvailable; | ||||||
|         delete pojo.__attributeCache; |         delete pojo.__attributeCache; | ||||||
|         delete pojo.titleCipherText; |         delete pojo.titleCipherText; | ||||||
|         delete pojo.contentCipherText; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ function showDialog() { | |||||||
|  |  | ||||||
|     $dialog.modal(); |     $dialog.modal(); | ||||||
|  |  | ||||||
|     const noteText = noteDetailService.getCurrentNote().content; |     const noteText = noteDetailService.getCurrentNote().noteContent.content; | ||||||
|  |  | ||||||
|     $noteSource.text(formatHtml(noteText)); |     $noteSource.text(formatHtml(noteText)); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -117,7 +117,7 @@ async function saveNote() { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     note.title = $noteTitle.val(); |     note.title = $noteTitle.val(); | ||||||
|     note.content = getCurrentNoteContent(note); |     note.noteContent.content = getCurrentNoteContent(note); | ||||||
|  |  | ||||||
|     // it's important to set the flag back to false immediatelly after retrieving title and content |     // it's important to set the flag back to false immediatelly after retrieving title and content | ||||||
|     // otherwise we might overwrite another change (especially async code) |     // otherwise we might overwrite another change (especially async code) | ||||||
|   | |||||||
| @@ -111,13 +111,13 @@ async function renderTooltip(note, attributes) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (note.type === 'text') { |     if (note.type === 'text') { | ||||||
|         // surround with <div> for a case when note.content is pure text (e.g. "[protected]") which |         // surround with <div> for a case when note's content is pure text (e.g. "[protected]") which | ||||||
|         // then fails the jquery non-empty text test |         // then fails the jquery non-empty text test | ||||||
|         content += '<div>' + note.content + '</div>'; |         content += '<div>' + note.noteContent.content + '</div>'; | ||||||
|     } |     } | ||||||
|     else if (note.type === 'code') { |     else if (note.type === 'code') { | ||||||
|         content += $("<pre>") |         content += $("<pre>") | ||||||
|             .text(note.content) |             .text(note.noteContent.content) | ||||||
|             .prop('outerHTML'); |             .prop('outerHTML'); | ||||||
|     } |     } | ||||||
|     else if (note.type === 'image') { |     else if (note.type === 'image') { | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ async function downloadNoteFile(noteId, res) { | |||||||
|     res.setHeader('Content-Disposition', utils.getContentDisposition(fileName)); |     res.setHeader('Content-Disposition', utils.getContentDisposition(fileName)); | ||||||
|     res.setHeader('Content-Type', note.mime); |     res.setHeader('Content-Type', note.mime); | ||||||
|  |  | ||||||
|     res.send(note.content); |     res.send((await note.getNoteContent()).content); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function downloadFile(req, res) { | async function downloadFile(req, res) { | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ async function returnImage(req, res) { | |||||||
|  |  | ||||||
|     res.set('Content-Type', image.mime); |     res.set('Content-Type', image.mime); | ||||||
|  |  | ||||||
|     res.send(image.content); |     res.send((await note.getNoteContent()).content); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function uploadImage(req) { | async function uploadImage(req) { | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ async function exportToOpml(branch, res) { | |||||||
|         const title = (branch.prefix ? (branch.prefix + ' - ') : '') + note.title; |         const title = (branch.prefix ? (branch.prefix + ' - ') : '') + note.title; | ||||||
|  |  | ||||||
|         const preparedTitle = prepareText(title); |         const preparedTitle = prepareText(title); | ||||||
|         const preparedContent = prepareText(note.content); |         const preparedContent = prepareText(await note.getContent()); | ||||||
|  |  | ||||||
|         res.write(`<outline title="${preparedTitle}" text="${preparedContent}">\n`); |         res.write(`<outline title="${preparedTitle}" text="${preparedContent}">\n`); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,30 +18,32 @@ async function exportSingleNote(branch, format, res) { | |||||||
|  |  | ||||||
|     let payload, extension, mime; |     let payload, extension, mime; | ||||||
|  |  | ||||||
|  |     const noteContent = await note.getNoteContent(); | ||||||
|  |  | ||||||
|     if (note.type === 'text') { |     if (note.type === 'text') { | ||||||
|         if (format === 'html') { |         if (format === 'html') { | ||||||
|             if (!note.content.toLowerCase().includes("<html")) { |             if (!noteContent.content.toLowerCase().includes("<html")) { | ||||||
|                 note.content = '<html><head><meta charset="utf-8"></head><body>' + note.content + '</body></html>'; |                 noteContent.content = '<html><head><meta charset="utf-8"></head><body>' + noteContent.content + '</body></html>'; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             payload = html.prettyPrint(note.content, {indent_size: 2}); |             payload = html.prettyPrint(noteContent.content, {indent_size: 2}); | ||||||
|             extension = 'html'; |             extension = 'html'; | ||||||
|             mime = 'text/html'; |             mime = 'text/html'; | ||||||
|         } |         } | ||||||
|         else if (format === 'markdown') { |         else if (format === 'markdown') { | ||||||
|             const turndownService = new TurndownService(); |             const turndownService = new TurndownService(); | ||||||
|             payload = turndownService.turndown(note.content); |             payload = turndownService.turndown(noteContent.content); | ||||||
|             extension = 'md'; |             extension = 'md'; | ||||||
|             mime = 'text/markdown' |             mime = 'text/markdown' | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else if (note.type === 'code') { |     else if (note.type === 'code') { | ||||||
|         payload = note.content; |         payload = noteContent.content; | ||||||
|         extension = mimeTypes.extension(note.mime) || 'code'; |         extension = mimeTypes.extension(note.mime) || 'code'; | ||||||
|         mime = note.mime; |         mime = note.mime; | ||||||
|     } |     } | ||||||
|     else if (note.type === 'relation-map' || note.type === 'search') { |     else if (note.type === 'relation-map' || note.type === 'search') { | ||||||
|         payload = note.content; |         payload = noteContent.content; | ||||||
|         extension = 'json'; |         extension = 'json'; | ||||||
|         mime = 'application/json'; |         mime = 'application/json'; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -123,7 +123,7 @@ async function exportToTar(branch, format, res) { | |||||||
|         const childBranches = await note.getChildBranches(); |         const childBranches = await note.getChildBranches(); | ||||||
|  |  | ||||||
|         // if it's a leaf then we'll export it even if it's empty |         // if it's a leaf then we'll export it even if it's empty | ||||||
|         if (note.content.length > 0 || childBranches.length === 0) { |         if ((await note.getContent()).length > 0 || childBranches.length === 0) { | ||||||
|             meta.dataFileName = getDataFileName(note, baseFileName, existingFileNames); |             meta.dataFileName = getDataFileName(note, baseFileName, existingFileNames); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -147,19 +147,21 @@ async function exportToTar(branch, format, res) { | |||||||
|         return meta; |         return meta; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     function prepareContent(note, format) { |     async function prepareContent(note, format) { | ||||||
|  |         const content = await note.getContent(); | ||||||
|  |  | ||||||
|         if (format === 'html') { |         if (format === 'html') { | ||||||
|             if (!note.content.toLowerCase().includes("<html")) { |             if (!content.toLowerCase().includes("<html")) { | ||||||
|                 note.content = '<html><head><meta charset="utf-8"></head><body>' + note.content + '</body></html>'; |                 note.content = '<html><head><meta charset="utf-8"></head><body>' + content + '</body></html>'; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return html.prettyPrint(note.content, {indent_size: 2}); |             return html.prettyPrint(content, {indent_size: 2}); | ||||||
|         } |         } | ||||||
|         else if (format === 'markdown') { |         else if (format === 'markdown') { | ||||||
|             return turndownService.turndown(note.content); |             return turndownService.turndown(content); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             return note.content; |             return content; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -179,7 +181,7 @@ async function exportToTar(branch, format, res) { | |||||||
|         notePaths[note.noteId] = path + (noteMeta.dataFileName || noteMeta.dirFileName); |         notePaths[note.noteId] = path + (noteMeta.dataFileName || noteMeta.dirFileName); | ||||||
|  |  | ||||||
|         if (noteMeta.dataFileName) { |         if (noteMeta.dataFileName) { | ||||||
|             const content = prepareContent(note, noteMeta.format); |             const content = await prepareContent(note, noteMeta.format); | ||||||
|  |  | ||||||
|             pack.entry({name: path + noteMeta.dataFileName, size: content.length}, content); |             pack.entry({name: path + noteMeta.dataFileName, size: content.length}, content); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -218,6 +218,8 @@ async function importEnex(file, parentNote) { | |||||||
|             mime: 'text/html' |             mime: 'text/html' | ||||||
|         })).note; |         })).note; | ||||||
|  |  | ||||||
|  |         const noteContent = await noteEntity.getNoteContent(); | ||||||
|  |  | ||||||
|         for (const resource of resources) { |         for (const resource of resources) { | ||||||
|             const hash = utils.md5(resource.content); |             const hash = utils.md5(resource.content); | ||||||
|  |  | ||||||
| @@ -238,8 +240,8 @@ async function importEnex(file, parentNote) { | |||||||
|  |  | ||||||
|               const resourceLink = `<a href="#root/${resourceNote.noteId}">${utils.escapeHtml(resource.title)}</a>`; |               const resourceLink = `<a href="#root/${resourceNote.noteId}">${utils.escapeHtml(resource.title)}</a>`; | ||||||
|  |  | ||||||
|               noteEntity.content = noteEntity.content.replace(mediaRegex, resourceLink); |               noteContent.content = noteContent.content.replace(mediaRegex, resourceLink); | ||||||
|             } |             }; | ||||||
|  |  | ||||||
|             if (["image/jpeg", "image/png", "image/gif"].includes(resource.mime)) { |             if (["image/jpeg", "image/png", "image/gif"].includes(resource.mime)) { | ||||||
|               try { |               try { | ||||||
| @@ -249,12 +251,12 @@ async function importEnex(file, parentNote) { | |||||||
|  |  | ||||||
|                 const imageLink = `<img src="${url}">`; |                 const imageLink = `<img src="${url}">`; | ||||||
|  |  | ||||||
|                 noteEntity.content = noteEntity.content.replace(mediaRegex, imageLink); |                 noteContent.content = noteContent.content.replace(mediaRegex, imageLink); | ||||||
|  |  | ||||||
|                 if (!note.content.includes(imageLink)) { |                 if (!noteContent.content.includes(imageLink)) { | ||||||
|                     // if there wasn't any match for the reference, we'll add the image anyway |                     // if there wasn't any match for the reference, we'll add the image anyway | ||||||
|                     // otherwise image would be removed since no note would include it |                     // otherwise image would be removed since no note would include it | ||||||
|                     note.content += imageLink; |                     noteContent.content += imageLink; | ||||||
|                 } |                 } | ||||||
|               } catch (e) { |               } catch (e) { | ||||||
|                 log.error("error when saving image from ENEX file: " + e); |                 log.error("error when saving image from ENEX file: " + e); | ||||||
| @@ -267,7 +269,7 @@ async function importEnex(file, parentNote) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // save updated content with links to files/images |         // save updated content with links to files/images | ||||||
|         await noteEntity.save(); |         await noteContent.save(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     saxStream.on("closetag", async tag => { |     saxStream.on("closetag", async tag => { | ||||||
|   | |||||||
| @@ -245,8 +245,10 @@ async function importTar(fileBuffer, importRootNote) { | |||||||
|         let note = await repository.getNote(noteId); |         let note = await repository.getNote(noteId); | ||||||
|  |  | ||||||
|         if (note) { |         if (note) { | ||||||
|             note.content = content; |             const noteContent = await note.getNoteContent(); | ||||||
|             await note.save(); |  | ||||||
|  |             noteContent.content = content; | ||||||
|  |             await noteContent.save(); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             const noteTitle = getNoteTitle(filePath, noteMeta); |             const noteTitle = getNoteTitle(filePath, noteMeta); | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ const eventService = require('./events'); | |||||||
| const repository = require('./repository'); | const repository = require('./repository'); | ||||||
| const cls = require('../services/cls'); | const cls = require('../services/cls'); | ||||||
| const Note = require('../entities/note'); | const Note = require('../entities/note'); | ||||||
|  | const NoteContent = require('../entities/note_content'); | ||||||
| const Link = require('../entities/link'); | const Link = require('../entities/link'); | ||||||
| const NoteRevision = require('../entities/note_revision'); | const NoteRevision = require('../entities/note_revision'); | ||||||
| const Branch = require('../entities/branch'); | const Branch = require('../entities/branch'); | ||||||
| @@ -87,12 +88,16 @@ async function createNewNote(parentNoteId, noteData) { | |||||||
|     const note = await new Note({ |     const note = await new Note({ | ||||||
|         noteId: noteData.noteId, // optionally can force specific noteId |         noteId: noteData.noteId, // optionally can force specific noteId | ||||||
|         title: noteData.title, |         title: noteData.title, | ||||||
|         content: noteData.content, |  | ||||||
|         isProtected: noteData.isProtected, |         isProtected: noteData.isProtected, | ||||||
|         type: noteData.type || 'text', |         type: noteData.type || 'text', | ||||||
|         mime: noteData.mime || 'text/html' |         mime: noteData.mime || 'text/html' | ||||||
|     }).save(); |     }).save(); | ||||||
|  |  | ||||||
|  |     note.noteContent = await new NoteContent({ | ||||||
|  |         noteId: note.noteId, | ||||||
|  |         content: noteData.content | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     const branch = await new Branch({ |     const branch = await new Branch({ | ||||||
|         noteId: note.noteId, |         noteId: note.noteId, | ||||||
|         parentNoteId: parentNoteId, |         parentNoteId: parentNoteId, | ||||||
| @@ -284,6 +289,12 @@ async function saveLinks(note, content) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function saveNoteRevision(note) { | async function saveNoteRevision(note) { | ||||||
|  |     // files and images are immutable, they can't be updated | ||||||
|  |     // but we don't even version titles which is probably not correct | ||||||
|  |     if (note.type !== 'file' || note.type !== 'image' || await note.hasLabel('disableVersioning')) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     const now = new Date(); |     const now = new Date(); | ||||||
|     const noteRevisionSnapshotTimeInterval = parseInt(await optionService.getOption('noteRevisionSnapshotTimeInterval')); |     const noteRevisionSnapshotTimeInterval = parseInt(await optionService.getOption('noteRevisionSnapshotTimeInterval')); | ||||||
|  |  | ||||||
| @@ -294,16 +305,12 @@ async function saveNoteRevision(note) { | |||||||
|  |  | ||||||
|     const msSinceDateCreated = now.getTime() - dateUtils.parseDateTime(note.dateCreated).getTime(); |     const msSinceDateCreated = now.getTime() - dateUtils.parseDateTime(note.dateCreated).getTime(); | ||||||
|  |  | ||||||
|     if (note.type !== 'file' |     if (!existingNoteRevisionId && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) { | ||||||
|         && !await note.hasLabel('disableVersioning') |  | ||||||
|         && !existingNoteRevisionId |  | ||||||
|         && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) { |  | ||||||
|  |  | ||||||
|         await new NoteRevision({ |         await new NoteRevision({ | ||||||
|             noteId: note.noteId, |             noteId: note.noteId, | ||||||
|             // title and text should be decrypted now |             // title and text should be decrypted now | ||||||
|             title: note.title, |             title: note.title, | ||||||
|             content: note.content, |             content: note.noteContent.content, | ||||||
|             type: note.type, |             type: note.type, | ||||||
|             mime: note.mime, |             mime: note.mime, | ||||||
|             isProtected: false, // will be fixed in the protectNoteRevisions() call |             isProtected: false, // will be fixed in the protectNoteRevisions() call | ||||||
| @@ -320,22 +327,23 @@ async function updateNote(noteId, noteUpdates) { | |||||||
|         throw new Error(`Note ${noteId} is not available for change!`); |         throw new Error(`Note ${noteId} is not available for change!`); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (note.type === 'file' || note.type === 'image') { |  | ||||||
|         // files and images are immutable, they can't be updated |  | ||||||
|         noteUpdates.content = note.content; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     await saveNoteRevision(note); |     await saveNoteRevision(note); | ||||||
|  |  | ||||||
|     const noteTitleChanged = note.title !== noteUpdates.title; |     const noteTitleChanged = note.title !== noteUpdates.title; | ||||||
|  |  | ||||||
|     noteUpdates.content = await saveLinks(note, noteUpdates.content); |     noteUpdates.noteContent.content = await saveLinks(note, noteUpdates.noteContent.content); | ||||||
|  |  | ||||||
|     note.title = noteUpdates.title; |     note.title = noteUpdates.title; | ||||||
|     note.setContent(noteUpdates.content); |  | ||||||
|     note.isProtected = noteUpdates.isProtected; |     note.isProtected = noteUpdates.isProtected; | ||||||
|     await note.save(); |     await note.save(); | ||||||
|  |  | ||||||
|  |     if (note.type !== 'file' && note.type !== 'image') { | ||||||
|  |         const noteContent = await note.getNoteContent(); | ||||||
|  |         noteContent.content = noteUpdates.noteContent.content; | ||||||
|  |         noteContent.isProtected = noteUpdates.isProtected; | ||||||
|  |         await noteContent.save(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (noteTitleChanged) { |     if (noteTitleChanged) { | ||||||
|         await triggerNoteTitleChanged(note); |         await triggerNoteTitleChanged(note); | ||||||
|     } |     } | ||||||
| @@ -394,7 +402,7 @@ async function cleanupDeletedNotes() { | |||||||
|     // it's better to not use repository for this because it will complain about saving protected notes |     // it's better to not use repository for this because it will complain about saving protected notes | ||||||
|     // out of protected session |     // out of protected session | ||||||
|  |  | ||||||
|     await sql.execute("UPDATE notes SET content = NULL WHERE isDeleted = 1 AND content IS NOT NULL AND dateModified <= ?", [dateUtils.dateStr(cutoffDate)]); |     await sql.execute("UPDATE note_contents SET content = NULL WHERE content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.dateModified <= ?)", [dateUtils.dateStr(cutoffDate)]); | ||||||
|  |  | ||||||
|     await sql.execute("UPDATE note_revisions SET content = NULL WHERE note_revisions.content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.dateModified <= ?)", [dateUtils.dateStr(cutoffDate)]); |     await sql.execute("UPDATE note_revisions SET content = NULL WHERE note_revisions.content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.dateModified <= ?)", [dateUtils.dateStr(cutoffDate)]); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -42,6 +42,14 @@ async function getNote(noteId) { | |||||||
|     return await getEntity("SELECT * FROM notes WHERE noteId = ?", [noteId]); |     return await getEntity("SELECT * FROM notes WHERE noteId = ?", [noteId]); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** @returns {Promise<Note|null>} */ | ||||||
|  | async function getNoteWithContent(noteId) { | ||||||
|  |     const note = await getEntity("SELECT * FROM notes WHERE noteId = ?", [noteId]); | ||||||
|  |     await note.getNoteContent(); | ||||||
|  |  | ||||||
|  |     return note; | ||||||
|  | } | ||||||
|  |  | ||||||
| /** @returns {Promise<NoteContent|null>} */ | /** @returns {Promise<NoteContent|null>} */ | ||||||
| async function getNoteContent(noteContentId) { | async function getNoteContent(noteContentId) { | ||||||
|     return await getEntity("SELECT * FROM note_contents WHERE noteContentId = ?", [noteContentId]); |     return await getEntity("SELECT * FROM note_contents WHERE noteContentId = ?", [noteContentId]); | ||||||
| @@ -126,6 +134,7 @@ module.exports = { | |||||||
|     getEntities, |     getEntities, | ||||||
|     getEntity, |     getEntity, | ||||||
|     getNote, |     getNote, | ||||||
|  |     getNoteWithContent, | ||||||
|     getNoteContent, |     getNoteContent, | ||||||
|     getBranch, |     getBranch, | ||||||
|     getAttribute, |     getAttribute, | ||||||
|   | |||||||
| @@ -56,10 +56,10 @@ async function executeBundle(bundle, apiParams = {}) { | |||||||
|  */ |  */ | ||||||
| async function executeScript(script, params, startNoteId, currentNoteId, originEntityName, originEntityId) { | async function executeScript(script, params, startNoteId, currentNoteId, originEntityName, originEntityId) { | ||||||
|     const startNote = await repository.getNote(startNoteId); |     const startNote = await repository.getNote(startNoteId); | ||||||
|     const currentNote = await repository.getNote(currentNoteId); |     const currentNote = await repository.getNoteWithContent(currentNoteId); | ||||||
|     const originEntity = await repository.getEntityFromName(originEntityName, originEntityId); |     const originEntity = await repository.getEntityFromName(originEntityName, originEntityId); | ||||||
|  |  | ||||||
|     currentNote.content = `return await (${script}\r\n)(${getParams(params)})`; |     currentNote.noteContent.content = `return await (${script}\r\n)(${getParams(params)})`; | ||||||
|     currentNote.type = 'code'; |     currentNote.type = 'code'; | ||||||
|     currentNote.mime = 'application/javascript;env=backend'; |     currentNote.mime = 'application/javascript;env=backend'; | ||||||
|  |  | ||||||
| @@ -158,7 +158,7 @@ apiContext.modules['${note.noteId}'] = {}; | |||||||
| ${root ? 'return ' : ''}await ((async function(exports, module, require, api` + (modules.length > 0 ? ', ' : '') + | ${root ? 'return ' : ''}await ((async function(exports, module, require, api` + (modules.length > 0 ? ', ' : '') + | ||||||
|             modules.map(child => sanitizeVariableName(child.title)).join(', ') + `) { |             modules.map(child => sanitizeVariableName(child.title)).join(', ') + `) { | ||||||
| try { | try { | ||||||
| ${note.content}; | ${await note.getContent()}; | ||||||
| } catch (e) { throw new Error("Load of script note \\"${note.title}\\" (${note.noteId}) failed with: " + e.message); } | } catch (e) { throw new Error("Load of script note \\"${note.title}\\" (${note.noteId}) failed with: " + e.message); } | ||||||
| if (!module.exports) module.exports = {}; | if (!module.exports) module.exports = {}; | ||||||
| for (const exportKey in exports) module.exports[exportKey] = exports[exportKey]; | for (const exportKey in exports) module.exports[exportKey] = exports[exportKey]; | ||||||
| @@ -167,7 +167,7 @@ for (const exportKey in exports) module.exports[exportKey] = exports[exportKey]; | |||||||
| `; | `; | ||||||
|     } |     } | ||||||
|     else if (note.isHtml()) { |     else if (note.isHtml()) { | ||||||
|         bundle.html += note.content; |         bundle.html += await note.getContent(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return bundle; |     return bundle; | ||||||
|   | |||||||
| @@ -48,14 +48,16 @@ async function updateEntity(sync, entity, sourceId) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function deserializeNoteContentBuffer(note) { | async function deserializeNoteContentBuffer(note) { | ||||||
|     if (note.content !== null && (note.type === 'file' || note.type === 'image')) { |     const noteContent = await note.getNoteContent(); | ||||||
|         note.content = Buffer.from(note.content, 'base64'); |  | ||||||
|  |     if (noteContent.content !== null && (note.type === 'file' || note.type === 'image')) { | ||||||
|  |         noteContent.content = Buffer.from(noteContent.content, 'base64'); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| async function updateNote(entity, sourceId) { | async function updateNote(entity, sourceId) { | ||||||
|     deserializeNoteContentBuffer(entity); |     await deserializeNoteContentBuffer(entity); | ||||||
|  |  | ||||||
|     const origNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [entity.noteId]); |     const origNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [entity.noteId]); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user