core: add block ids before returning content

This commit is contained in:
Abdullah Atta
2024-03-09 23:16:55 +05:00
parent 4506e5e90a
commit ccb9c492a8
4 changed files with 94 additions and 22 deletions

View File

@@ -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,

View File

@@ -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;

View File

@@ -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)
)
}))
);
}

View File

@@ -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"