feat: element CRUD — picker, delete, drag & drop, nesting with placement rules, undo #23
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle!23
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/6"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Structural editing of a page's element tree, end to end. Closes #6
What landed
Placement model (
internal/element, newinternal/placement)placementblocks are now typed and strictly validated:allowedIn(parent element names, plus the reservedpagetoken for the document top level) andallowedAt(page types); absent lists mean unrestricted.type, else top-level section, elsepage(YAML/TOML/JSON front matter supported).editor/pagetypes/<type>.yaml(elements: [...]); no declaration means everything is allowed.bodyismarkdown. The rules engine answers insert (all axes) and move (parent axis only) questions and is unit-tested without HTTP.Server (
internal/server)POST /api/page/mutateapplies oneinsert/delete/moveop addressed by child-index paths. Placement rules are enforced server-side: violations are 422 with a user-facing message and the file is untouched; stale addresses are 409. Inserts carry schema defaults; deletes drop the whole subtree; moves use pre-mutation addressing with exact index adjustment, and adjacent text runs merge afterwards so canonical serialization never rejects the result. Every success rewrites only that page's file atomically through the canonical serializer.pageTypeandallowedElements; mutate responses include the new/moved node'spath.POST /api/page/undoreverts the last structural mutation (single step, server-wide), byte-verifying the file hasn't changed externally; param saves never create undo steps.Web
groupthat offers only the types allowed at that position — page-type axes from the server,allowedInfiltering client-side, server authoritative regardless.Sample site — grid/column container pair with templates and sidecars, placement declarations on hero/notice, a
postsallowlist excluding the grid, and a nested-grid sample on the home page.Verification
go vet ./...,go test ./...(25 new server tests incl. index-adjustment, text-merge regression, undo matrix),gofmtclean.tsc --noEmit,vite build._index.mdround-trips byte-identical through the serializer.🤖 Generated with Claude Code
https://claude.ai/code/session_01Mewza68Wq8JKj6H27Aw9ip
Pull request closed