Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ddfd29ea0e | |||
| 3f2beafd94 |
+1
-1
@@ -141,7 +141,7 @@ header {
|
||||
padding: var(--space-3) var(--space-4);
|
||||
border-bottom: var(--border-dashed);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr minmax(0, 60rem) 1fr;
|
||||
grid-template-columns: 1fr minmax(0, 50rem) 1fr;
|
||||
grid-template-areas: "crumbs search actions";
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
|
||||
@@ -426,9 +426,14 @@ func (h *handler) handlePost(w http.ResponseWriter, r *http.Request, urlPath, fs
|
||||
}
|
||||
rawMD, _ := os.ReadFile(indexPath)
|
||||
sections := splitSections(rawMD)
|
||||
if sectionIndex < len(sections) {
|
||||
sections[sectionIndex] = []byte(content)
|
||||
// Out of range means the file changed under the editor (or the index
|
||||
// never matched it). Writing back the untouched file would swallow the
|
||||
// edit silently, so refuse and keep the editor's content in the browser.
|
||||
if sectionIndex >= len(sections) {
|
||||
http.Error(w, "section no longer exists — the page changed since you opened the editor", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
sections[sectionIndex] = []byte(content)
|
||||
content = string(joinSections(sections))
|
||||
// Section index ≥ 1 is a heading-anchored section. Redirect to its
|
||||
// anchor so the user lands on the section they just saved, even if
|
||||
@@ -441,12 +446,15 @@ func (h *handler) handlePost(w http.ResponseWriter, r *http.Request, urlPath, fs
|
||||
}
|
||||
}
|
||||
|
||||
// A save must never remove a page. An empty POST — a truncated mobile
|
||||
// request, a lost `section` field, an editor that came up blank — is
|
||||
// indistinguishable from "clear this page", and deleting index.md on that
|
||||
// signal loses the whole file even though the user only edited one section.
|
||||
// Removing a page is the explicit ?delete action's job (moves.go).
|
||||
if strings.TrimSpace(content) == "" {
|
||||
if err := os.Remove(indexPath); err != nil && !os.IsNotExist(err) {
|
||||
http.Error(w, "delete failed: "+err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, "refusing to save empty content — use DELETE to remove this page", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Stat first so we know whether MkdirAll actually created the folder
|
||||
// — if it did, the search index needs a new entry.
|
||||
_, statErr := os.Stat(fsPath)
|
||||
@@ -464,7 +472,6 @@ func (h *handler) handlePost(w http.ResponseWriter, r *http.Request, urlPath, fs
|
||||
folderIndexAdd(filepath.ToSlash(rel))
|
||||
}
|
||||
}
|
||||
}
|
||||
// The editor saves via fetch so the save and its result share one history
|
||||
// entry (see assets/history-nav.js). Hand it the target instead of a 303:
|
||||
// the browser would follow the redirect into a second entry, and fetch
|
||||
|
||||
Reference in New Issue
Block a user