mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-02 04:01:43 +02:00
core: add block ids before returning content
This commit is contained in:
@@ -191,7 +191,12 @@ export default class Vault {
|
||||
const note = await this.db.notes.note(noteId);
|
||||
if (!note) return;
|
||||
|
||||
const content = await this.unlockNote(noteId, password, false);
|
||||
const content = await this.unlockNote(
|
||||
noteId,
|
||||
password || this.password,
|
||||
false
|
||||
);
|
||||
|
||||
if (password) {
|
||||
this.password = password;
|
||||
if (!(await this.exists())) await this.create(password);
|
||||
@@ -260,18 +265,10 @@ export default class Vault {
|
||||
.storage()
|
||||
.decrypt({ password }, encryptedContent.data);
|
||||
|
||||
const content: NoteContent<false> = {
|
||||
return <NoteContent<false>>{
|
||||
type: encryptedContent.type,
|
||||
data: JSON.parse(decryptedContent)
|
||||
};
|
||||
|
||||
// #MIGRATION: convert tiny to tiptap
|
||||
if (content.type === "tiny") {
|
||||
content.type = "tiptap";
|
||||
content.data = tinyToTiptap(content.data);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
private async lockNote(
|
||||
@@ -335,6 +332,16 @@ export default class Vault {
|
||||
if (!content || !content.locked) return;
|
||||
const decryptedContent = await this.decryptContent(content, password);
|
||||
|
||||
if (this.db.content.preProcess(decryptedContent)) {
|
||||
if (!password) password = await this.getVaultPassword();
|
||||
await this.encryptContent(
|
||||
decryptedContent,
|
||||
noteId,
|
||||
password,
|
||||
`${Date.now}`
|
||||
);
|
||||
}
|
||||
|
||||
if (perm) {
|
||||
await this.db.notes.add({
|
||||
id: noteId,
|
||||
|
||||
@@ -34,6 +34,7 @@ import { getOutputType } from "./attachments";
|
||||
import { SQLCollection } from "../database/sql-collection";
|
||||
import { NoteContent } from "./session-content";
|
||||
import { InternalLink } from "../utils/internal-link";
|
||||
import { tinyToTiptap } from "../migrations";
|
||||
|
||||
export const EMPTY_CONTENT = (noteId: string): UnencryptedContentItem => ({
|
||||
noteId,
|
||||
@@ -157,6 +158,12 @@ export class Content implements ICollection {
|
||||
async get(id: string) {
|
||||
const content = await this.collection.get(id);
|
||||
if (!content || isDeleted(content)) return;
|
||||
if (!content.locked && this.preProcess(content)) {
|
||||
await this.db.content.add({
|
||||
...content,
|
||||
sessionId: `${Date.now()}`
|
||||
});
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -208,6 +215,12 @@ export class Content implements ICollection {
|
||||
.selectAll()
|
||||
.executeTakeFirst()) as ContentItem;
|
||||
if (!content || isDeleted(content)) return;
|
||||
if (!content.locked && this.preProcess(content)) {
|
||||
await this.db.content.add({
|
||||
...content,
|
||||
sessionId: `${Date.now()}`
|
||||
});
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -300,6 +313,28 @@ export class Content implements ICollection {
|
||||
await this.add(contentItem);
|
||||
}
|
||||
|
||||
preProcess(content: NoteContent<false>) {
|
||||
let changed = false;
|
||||
|
||||
// #MIGRATION: convert tiny to tiptap
|
||||
if (content.type === "tiny") {
|
||||
content.type = "tiptap";
|
||||
content.data = tinyToTiptap(content.data);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// add block id on all appropriate nodes
|
||||
if (!content.data.includes("data-block-id")) {
|
||||
content.data = getContentFromData(
|
||||
content.type,
|
||||
content.data
|
||||
).insertBlockIds();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
async postProcess(contentItem: NoteContent<false> & { noteId: string }) {
|
||||
const content = getContentFromData(contentItem.type, contentItem.data);
|
||||
if (!content) return contentItem.data;
|
||||
|
||||
@@ -92,6 +92,34 @@ export class Tiptap {
|
||||
return tokens.some((token) => lowercase.indexOf(token) > -1);
|
||||
}
|
||||
|
||||
insertBlockIds() {
|
||||
let index = 0;
|
||||
return new HTMLRewriter({
|
||||
ontag(name, attr) {
|
||||
switch (name) {
|
||||
case "p":
|
||||
case "h1":
|
||||
case "h2":
|
||||
case "h3":
|
||||
case "h4":
|
||||
case "h5":
|
||||
case "h6":
|
||||
case "blockquote":
|
||||
case "ul":
|
||||
case "ol":
|
||||
case "pre":
|
||||
case "img":
|
||||
case "iframe":
|
||||
case "div":
|
||||
return {
|
||||
name,
|
||||
attr: { ...attr, [ATTRIBUTES.blockId]: `${name}${++index}` }
|
||||
};
|
||||
}
|
||||
}
|
||||
}).transform(this.data);
|
||||
}
|
||||
|
||||
async insertMedia(resolve: ResolveHashes) {
|
||||
const hashes: string[] = [];
|
||||
new HTMLParser({
|
||||
@@ -124,17 +152,15 @@ export class Tiptap {
|
||||
|
||||
if (types.includes("blocks")) {
|
||||
result.blocks.push(
|
||||
...document.childNodes
|
||||
.filter((element): element is Element => {
|
||||
return isTag(element) && !!element.attribs[ATTRIBUTES.blockId];
|
||||
})
|
||||
.map((node) => ({
|
||||
id: node.attribs[ATTRIBUTES.blockId],
|
||||
type: node.tagName.toLowerCase(),
|
||||
content: convertHtmlToTxt(
|
||||
this.data.slice(node.startIndex || 0, node.endIndex || 0)
|
||||
)
|
||||
}))
|
||||
...findAll((element): element is Element => {
|
||||
return isTag(element) && !!element.attribs[ATTRIBUTES.blockId];
|
||||
}, document.childNodes).map((node) => ({
|
||||
id: node.attribs[ATTRIBUTES.blockId],
|
||||
type: node.tagName.toLowerCase(),
|
||||
content: convertHtmlToTxt(
|
||||
this.data.slice(node.startIndex || 0, node.endIndex || 0)
|
||||
)
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,11 @@ export function highlightInternalLinks(
|
||||
return highlighted;
|
||||
}
|
||||
|
||||
function ellipsize(text: string, maxLength: number, from: "start" | "end") {
|
||||
export function ellipsize(
|
||||
text: string,
|
||||
maxLength: number,
|
||||
from: "start" | "end"
|
||||
) {
|
||||
const needsTruncation = text.length > maxLength;
|
||||
const offsets = needsTruncation
|
||||
? from === "start"
|
||||
|
||||
Reference in New Issue
Block a user