mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-21 22:19:41 +01:00
feat: add migration for table & checklists
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
{"version":5.2,"type":"web","date":1640684511432,"data":{"069b671dd48576dff9157120":{"id":"069b671dd48576dff9157120","contentId":"8454da84dfa427c2f75f70da","type":"note","title":"Table test note","pinned":false,"locked":false,"tags":[],"favorite":false,"dateCreated":1640684417435,"dateEdited":1640684432529,"localOnly":false,"conflicted":false},"8454da84dfa427c2f75f70da":{"noteId":"069b671dd48576dff9157120","id":"8454da84dfa427c2f75f70da","type":"tiny","data":"<table style=\"border-collapse: collapse; width: 100.063%;\" border=\"1\"><tbody><tr><td style=\"width: 34.3648%;\">Hello<br></td><td style=\"width: 34.3648%;\">World<br></td></tr><tr><td style=\"width: 34.3648%;\">My <br></td><td style=\"width: 34.3648%;\">Name<br data-mce-bogus=\"1\"></td></tr></tbody></table>","dateEdited":1640684432525,"dateCreated":1640684426583,"localOnly":false,"persistDateEdited":false},"_uk_@ammarahmed6506+5@gmail.com":{},"_uk_@ammarahmed6506+5@gmail.com@_k":{"iv":{"0":17,"1":27,"2":18,"3":72,"4":98,"5":156,"6":43,"7":0,"8":63,"9":234,"10":35,"11":22},"cipher":{}},"c5f6fa4fef9be04c0f07f80e":{"noteId":"d3a7a9fbd4bb29ca41570c5e","id":"c5f6fa4fef9be04c0f07f80e","type":"tiny","data":"<ul style=\"list-style-type: none;\" class=\"tox-checklist\"><li>Hello<br></li><li class=\"tox-checklist--checked\">world<br data-mce-bogus=\"1\"></li><li class=\"tox-checklist--checked\">123<br data-mce-bogus=\"1\"></li><li>abc<br data-mce-bogus=\"1\"></li></ul><p>test completed.<br data-mce-bogus=\"1\"></p>","dateEdited":1640684464785,"dateCreated":1640684448878,"localOnly":false,"persistDateEdited":false},"content":["8454da84dfa427c2f75f70da","c5f6fa4fef9be04c0f07f80e"],"d3a7a9fbd4bb29ca41570c5e":{"id":"d3a7a9fbd4bb29ca41570c5e","contentId":"c5f6fa4fef9be04c0f07f80e","type":"note","title":"Checklist test","headline":"test completed.","pinned":false,"locked":false,"tags":[],"favorite":false,"dateCreated":1640684443699,"dateEdited":1640684464786,"localOnly":false,"conflicted":false},"hasConflicts":false,"monographs":[],"notes":["069b671dd48576dff9157120","d3a7a9fbd4bb29ca41570c5e"],"settings":{"type":"settings","id":"87a858b33cd6427364d176d4","pins":[],"groupOptions":{},"aliases":{},"dateEdited":0,"dateCreated":0},"token":{"access_token":"9E5F461613022DB4AC77BE5EA46D8AD67069E7361B8F3FC9F9E9C74409E4CA46","expires_in":3600,"token_type":"Bearer","refresh_token":"4489400BF30C61DCA8B84960620F5B01B165A8FE5C537AE4709E5492758F49ED","scope":"IdentityServerApi notesnook.sync offline_access openid","t":1640684404249}},"hash":"7b6bc37e3338f10535486f03ca71e42d","hash_type":"md5"}
|
||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
notebookTest,
|
notebookTest,
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import v52Backup from "./__fixtures__/backup.v5.2.json";
|
import v52Backup from "./__fixtures__/backup.v5.2.json";
|
||||||
|
import v52BackupCopy from "./__fixtures__/backup.v5.2.copy.json";
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
StorageInterface.clear();
|
StorageInterface.clear();
|
||||||
@@ -64,65 +65,81 @@ test("import tempered backup", () =>
|
|||||||
})
|
})
|
||||||
));
|
));
|
||||||
|
|
||||||
describe.each([["v5.2", v52Backup]])(
|
describe.each([
|
||||||
"testing backup version: %s",
|
["v5.2", v52Backup],
|
||||||
(version, data) => {
|
["v5.2 copy", v52BackupCopy],
|
||||||
test(`import ${version} backup`, () => {
|
])("testing backup version: %s", (version, data) => {
|
||||||
return databaseTest().then(async (db) => {
|
test(`import ${version} backup`, () => {
|
||||||
await db.backup.import(JSON.stringify(data));
|
return databaseTest().then(async (db) => {
|
||||||
|
await db.backup.import(JSON.stringify(data));
|
||||||
|
|
||||||
expect(db.settings.raw.id).toBeDefined();
|
expect(db.settings.raw.id).toBeDefined();
|
||||||
expect(db.settings.raw.dateModified).toBeDefined();
|
expect(db.settings.raw.dateModified).toBeDefined();
|
||||||
expect(db.settings.raw.dateEdited).toBeUndefined();
|
expect(db.settings.raw.dateEdited).toBeUndefined();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
db.notes.all.every((v) => {
|
||||||
|
const doesNotHaveContent = v.contentId && !v.content;
|
||||||
|
const doesNotHaveColors = !v.colors && (!v.color || v.color.length);
|
||||||
|
const hasTopicsInAllNotebooks =
|
||||||
|
!v.notebooks ||
|
||||||
|
v.notebooks.every((nb) => !!nb.id && !!nb.topics && !nb.topic);
|
||||||
|
const hasDateModified = v.dateModified > 0;
|
||||||
|
return (
|
||||||
|
doesNotHaveContent &&
|
||||||
|
!v.notebook &&
|
||||||
|
hasTopicsInAllNotebooks &&
|
||||||
|
doesNotHaveColors &&
|
||||||
|
hasDateModified
|
||||||
|
);
|
||||||
|
})
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
db.notebooks.all.every((v) => v.title != null && v.dateModified > 0)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
db.attachments.all.every((v) => v.dateModified > 0 && !v.dateEdited)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
|
const allContent = await db.content.all();
|
||||||
|
expect(
|
||||||
|
allContent.every((v) => v.type === "tiny" || v.deleted)
|
||||||
|
).toBeTruthy();
|
||||||
|
expect(allContent.every((v) => !v.persistDateEdited)).toBeTruthy();
|
||||||
|
expect(allContent.every((v) => v.dateModified > 0)).toBeTruthy();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
allContent.every(
|
||||||
|
(v) =>
|
||||||
|
!v.data.includes("tox-checklist") &&
|
||||||
|
!v.data.includes("tox-checklist--checked")
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
|
const tableContent = allContent.find((a) => a.data.includes("<table"));
|
||||||
|
if (tableContent)
|
||||||
expect(
|
expect(
|
||||||
db.notes.all.every((v) => {
|
tableContent.data.includes(
|
||||||
const doesNotHaveContent = v.contentId && !v.content;
|
`<div class="table-container" contenteditable="false">`
|
||||||
const doesNotHaveColors = !v.colors && (!v.color || v.color.length);
|
)
|
||||||
const hasTopicsInAllNotebooks =
|
);
|
||||||
!v.notebooks ||
|
|
||||||
v.notebooks.every((nb) => !!nb.id && !!nb.topics && !nb.topic);
|
|
||||||
const hasDateModified = v.dateModified > 0;
|
|
||||||
return (
|
|
||||||
doesNotHaveContent &&
|
|
||||||
!v.notebook &&
|
|
||||||
hasTopicsInAllNotebooks &&
|
|
||||||
doesNotHaveColors &&
|
|
||||||
hasDateModified
|
|
||||||
);
|
|
||||||
})
|
|
||||||
).toBeTruthy();
|
|
||||||
|
|
||||||
expect(
|
|
||||||
db.notebooks.all.every((v) => v.title != null && v.dateModified > 0)
|
|
||||||
).toBeTruthy();
|
|
||||||
|
|
||||||
expect(
|
|
||||||
db.attachments.all.every((v) => v.dateModified > 0 && !v.dateEdited)
|
|
||||||
).toBeTruthy();
|
|
||||||
|
|
||||||
const allContent = await db.content.all();
|
|
||||||
expect(
|
|
||||||
allContent.every((v) => v.type === "tiny" || v.deleted)
|
|
||||||
).toBeTruthy();
|
|
||||||
expect(allContent.every((v) => !v.persistDateEdited)).toBeTruthy();
|
|
||||||
expect(allContent.every((v) => v.dateModified > 0)).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test(`verify indices of ${version} backup`, () => {
|
test(`verify indices of ${version} backup`, () => {
|
||||||
return databaseTest().then(async (db) => {
|
return databaseTest().then(async (db) => {
|
||||||
await db.backup.import(JSON.stringify(data));
|
await db.backup.import(JSON.stringify(data));
|
||||||
|
|
||||||
verifyIndex(data, db, "notes", "notes");
|
verifyIndex(data, db, "notes", "notes");
|
||||||
verifyIndex(data, db, "notebooks", "notebooks");
|
verifyIndex(data, db, "notebooks", "notebooks");
|
||||||
verifyIndex(data, db, "content", "content");
|
verifyIndex(data, db, "content", "content");
|
||||||
verifyIndex(data, db, "attachments", "attachments");
|
verifyIndex(data, db, "attachments", "attachments");
|
||||||
// verifyIndex(data, db, "trash", "trash");
|
// verifyIndex(data, db, "trash", "trash");
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
});
|
||||||
|
|
||||||
function verifyIndex(backup, db, backupCollection, collection) {
|
function verifyIndex(backup, db, backupCollection, collection) {
|
||||||
if (!backup.data[backupCollection]) return;
|
if (!backup.data[backupCollection]) return;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { parseHTML } from "./utils/html-parser";
|
||||||
|
|
||||||
export const migrations = {
|
export const migrations = {
|
||||||
5.0: {},
|
5.0: {},
|
||||||
5.1: {},
|
5.1: {},
|
||||||
@@ -7,7 +9,14 @@ export const migrations = {
|
|||||||
tag: replaceDateEditedWithDateModified(true),
|
tag: replaceDateEditedWithDateModified(true),
|
||||||
attachment: replaceDateEditedWithDateModified(true),
|
attachment: replaceDateEditedWithDateModified(true),
|
||||||
trash: replaceDateEditedWithDateModified(),
|
trash: replaceDateEditedWithDateModified(),
|
||||||
tiny: replaceDateEditedWithDateModified(),
|
tiny: (item) => {
|
||||||
|
item = replaceDateEditedWithDateModified()(item);
|
||||||
|
|
||||||
|
if (!item.data || item.data.iv) return item;
|
||||||
|
|
||||||
|
item.data = removeToxClassFromChecklist(wrapTablesWithDiv(item.data));
|
||||||
|
return item;
|
||||||
|
},
|
||||||
settings: replaceDateEditedWithDateModified(true),
|
settings: replaceDateEditedWithDateModified(true),
|
||||||
},
|
},
|
||||||
5.3: {
|
5.3: {
|
||||||
@@ -29,3 +38,30 @@ function replaceDateEditedWithDateModified(removeDateEditedProperty = false) {
|
|||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wrapTablesWithDiv(html) {
|
||||||
|
const document = parseHTML(html);
|
||||||
|
const tables = document.getElementsByTagName("table");
|
||||||
|
for (let table of tables) {
|
||||||
|
table.setAttribute("contenteditable", "true");
|
||||||
|
table.replaceWith(
|
||||||
|
`<div class="table-container" contenteditable="false">${table.outerHTML}</div>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return document.outerHTML || document.body.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeToxClassFromChecklist(html) {
|
||||||
|
const document = parseHTML(html);
|
||||||
|
const checklists = document.querySelectorAll(
|
||||||
|
".tox-checklist,.tox-checklist--checked"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let item of checklists) {
|
||||||
|
if (item.classList.contains("tox-checklist--checked"))
|
||||||
|
item.classList.replace("tox-checklist--checked", "checked");
|
||||||
|
else if (item.classList.contains("tox-checklist"))
|
||||||
|
item.classList.replace("tox-checklist", "checklist");
|
||||||
|
}
|
||||||
|
return document.outerHTML || document.body.innerHTML;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user