Do not consider edit mode as a history entry

This commit is contained in:
2026-07-20 17:31:59 +02:00
parent 34f750beff
commit 28d22c040f
6 changed files with 93 additions and 2 deletions
+40 -1
View File
@@ -140,7 +140,46 @@
function syncContent() {
hidden.value = view.state.doc.toString();
}
form.addEventListener('submit', syncContent);
// Save POSTs via fetch and then rewrites the *editor's* history entry with
// the resulting page, so the edit session and its result share a single
// entry (see history-nav.js). A plain form submit would push a second one
// and leave the editor sitting in history behind the saved page.
//
// The server answers 204 + X-Target instead of a 303 because the target may
// carry a #section anchor the client cannot compute, and fetch drops the
// fragment from a followed redirect.
function postSave() {
syncContent();
var body = new URLSearchParams(new FormData(form)).toString();
fetch(form.action, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Save-Mode': 'replace',
},
body: body,
}).then(function (res) {
if (!res.ok) {
return res.text().then(function (msg) {
alert(msg || ('Save failed (' + res.status + ')'));
});
}
var target = res.headers.get('X-Target') || form.action;
// replaceState + reload rather than location.replace: if target
// differs from the current URL only by fragment the browser would
// skip the re-fetch and show pre-save content.
window.history.replaceState(null, '', target);
window.location.reload();
}).catch(function () {
alert('Network error — the page was not saved');
});
}
form.addEventListener('submit', function (e) {
e.preventDefault();
postSave();
});
// --- Actions ---
+2 -1
View File
@@ -4,7 +4,8 @@
switch (e.key) {
case 'E':
e.preventDefault();
window.location.href = window.location.pathname + '?edit';
// replace, not assign — same reasoning as history-nav.js.
window.location.replace(window.location.pathname + '?edit');
break;
case 'N':
e.preventDefault();
+33
View File
@@ -0,0 +1,33 @@
// Keeps the page editor out of the browser history.
//
// Opening the editor for the page you are already on is a mode switch, not a
// new destination, so it replaces the current history entry instead of pushing
// one; CANCEL replaces it right back, and SAVE does the same via postSave in
// editor/main.js. Without this, page -> edit -> save leaves
// [prev, page, editor, page'] behind and Back walks through the editor and a
// stale pre-save snapshot of the page before reaching prev.
//
// Links to a *different* page's editor (new page, new child) still push — the
// page you started from has to stay in history.
(function () {
function isEdit(loc) {
return new URLSearchParams(loc.search).has('edit');
}
document.addEventListener('click', function (e) {
if (e.defaultPrevented || e.button !== 0) return;
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
var a = e.target.closest ? e.target.closest('a[href]') : null;
if (!a || a.target || a.hasAttribute('download')) return;
var url = new URL(a.href, window.location.href);
if (url.origin !== window.location.origin) return;
if (url.pathname !== window.location.pathname) return;
// Same page: only editor entry/exit is a mode switch. Plain anchor
// links share the pathname too and must keep their normal behaviour.
if (!isEdit(url) && !isEdit(window.location)) return;
e.preventDefault();
window.location.replace(url.href);
});
}());
+1
View File
@@ -10,6 +10,7 @@
<link rel="stylesheet" href="/_/style.css" />
<script src="/_/modal.js"></script>
<script src="/_/global-shortcuts.js"></script>
<script src="/_/history-nav.js"></script>
<script src="/_/search-suggest.js" defer></script>
<script src="/_/tree-picker.js"></script>
<script src="/_/companion.js" defer></script>