Rework category labels, slug validation, and task-list checkboxes

- Remove the section-header  "add landing page" button; landing pages are
  now created via the page editor pen.
- Treat saving a page with empty (after stripping) Markdown as deleting it:
  childless nodes are removed, nodes with children become content-less labels.
- Restrict server-side slugs to [a-z0-9_-] with no leading underscore or dot;
  drop the reserved-filename blacklist.
- Render placeholder pages for content-less category labels and link them to
  their first published child in the navigation.
- Make task-list checkboxes live, non-disabled inputs: toggling updates the
  Markdown source, updates the open CodeMirror document when the page editor is
  open, and persists to the server when no editor is open. Errors revert the UI.
- Update docs and AGENTS.md conventions accordingly.
This commit is contained in:
2026-08-16 19:04:55 +00:00
parent 3dc438f8df
commit a8cf5a6a82
12 changed files with 304 additions and 131 deletions
+2 -9
View File
@@ -5,8 +5,8 @@
// Every node is real: a label whose title and slug are always editable
// inline — the title saves while typing (and focusing it opens the page),
// the slug commits on blur/Enter since it renames the path, moving the
// whole subtree. Nodes without content are category labels that redirect
// to their first child; the on their row gives them a landing page.
// whole subtree. Nodes without content are category labels whose URL
// renders a placeholder page; the on their row gives them a landing page.
// Every non-empty list (and the root list) ends with a footer row:
// clicking it adds a *pending* row (a local-only item persisted to the
// server only on commit, ✓/Enter, Esc discards) at the end of that list,
@@ -140,13 +140,6 @@ function onEnd() {
/>
<span class="acts">
<span v-if="!element.published" class="draft">draft</span>
<button
v-if="!element.has_content"
type="button"
class="act"
title="add a landing page (currently redirects to the first child)"
@click="handlers.addContent(element)"
></button>
<button
type="button"
class="act del"