A host from the web site; the same page kept once; deleting from the Notebooks chooser
From the development repository at 299f73d, 2026-10-11: hosting from the site documented; a page loaded from a notebook and left unchanged is not kept again; notebooks and pages are deleted from the chooser, to the system's Trash (--trash); the Notebooks button. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e3a281d65
commit
0d01e23d7c
15 files changed
+711
-63
No files matched your search
@@ -17,6 +17,26 @@ const PAGES = 'pages';
|
||||
const IDENTITY_KEY = 'kokkoja_identity';
|
||||
const CURRENT_PAGE = 'Current.svg';
|
||||
const KEPT_PAGE = /^(\d{4}_\d{2}_\d{2})_(\d{2,})\.svg$/;
|
||||
/**
|
||||
* What names a page file rather than describes the page: the session,
|
||||
* the host, the page's id and number on the root element, and the title.
|
||||
* A page loaded from a notebook is a new page with new ones of these, so
|
||||
* two files of the same page differ here and nowhere else. They stand
|
||||
* before the paper's <rect>, and only there; typed text may contain
|
||||
* anything. The same rule as page_content() in kokkoja.py.
|
||||
*/
|
||||
const VOLATILE = / data-(?:session|host|page|number)="[^"]*"|<title>[^<]*<\/title>\n?/g;
|
||||
|
||||
/**
|
||||
* @param {string} text A page file.
|
||||
* @returns {string} The file without what names it, for telling the
|
||||
* same page in two files.
|
||||
*/
|
||||
function pageContent(text) {
|
||||
const paper = text.indexOf('<rect ');
|
||||
return paper < 0 ? text.replace(VOLATILE, '')
|
||||
: text.slice(0, paper).replace(VOLATILE, '') + text.slice(paper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {object} StoredPage
|
||||
@@ -112,7 +132,7 @@ export const backend = {
|
||||
const keys = /** @type {[string, string][]} */ (await result(pages.getAllKeys()));
|
||||
return [...new Set(keys.map(([notebook]) => notebook))].sort();
|
||||
});
|
||||
return { directory: '', notebooks: names };
|
||||
return { directory: '', notebooks: names, trash: false };
|
||||
},
|
||||
|
||||
async listPages(notebook) {
|
||||
@@ -132,15 +152,17 @@ export const backend = {
|
||||
},
|
||||
|
||||
// The same rules as keep_page() in kokkoja.py: nothing is kept of a
|
||||
// blank page or of one already kept; the name is the day the page was
|
||||
// last changed and a serial number.
|
||||
// blank page or of one already kept (the same page, whatever names the
|
||||
// file); the name is the day the page was last changed and a serial
|
||||
// number.
|
||||
async keepPage(notebook) {
|
||||
return transaction('readwrite', async (pages) => {
|
||||
const current = /** @type {StoredPage | undefined} */ (await result(pages.get([notebook, CURRENT_PAGE])));
|
||||
const blank = !['data-stroke=', 'data-text=', '<image'].some((mark) => current?.text.includes(mark));
|
||||
if (!current || blank) return { kept: null, new: false };
|
||||
const kept = (await pagesOf(pages, notebook)).filter((page) => KEPT_PAGE.test(page.name));
|
||||
const same = kept.find((page) => page.text === current.text);
|
||||
const content = pageContent(current.text);
|
||||
const same = kept.find((page) => pageContent(page.text) === content);
|
||||
if (same) return { kept: same.name, new: false };
|
||||
const day = dayOf(current.changed);
|
||||
const serials = kept.map((page) => /** @type {RegExpExecArray} */ (KEPT_PAGE.exec(page.name)))
|
||||
@@ -150,4 +172,15 @@ export const backend = {
|
||||
return { kept: name, new: true };
|
||||
});
|
||||
},
|
||||
|
||||
// The browser has no trash: a deleted page is gone.
|
||||
async discardNotebook(notebook) {
|
||||
await transaction('readwrite', async (pages) => {
|
||||
for (const page of await pagesOf(pages, notebook)) await result(pages.delete([notebook, page.name]));
|
||||
});
|
||||
},
|
||||
|
||||
async discardPage(notebook, pageName) {
|
||||
await transaction('readwrite', async (pages) => { await result(pages.delete([notebook, pageName])); });
|
||||
},
|
||||
};
|
||||
Reference in new issue
Block a user