feat: page tree browsing — content tree API + SPA tree/element panes #21
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!21
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/4"
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?
Closes #4
What
The TYPO3-style left pane, read-only: the harness now serves the site's page tree per language, and the SPA renders it with expand/collapse, selection, and an element list in the center pane.
Backend
internal/content:FrontMatter.Decode()(Hugo's own metadecoders, all four formats) andParseFrontMatter()— front-matter extraction that survives body parse failures, so a page whose body the round-trip engine rejects still appears in the tree. Decode-only; #9 builds the write half on the same mapping.internal/pagetree(new): walks a language's content root into sections (_index.md), leaf bundles (index.md), and plain.mdpages; title/weight/draft from front matter with slug fallback plus aproblemfield instead of dropped nodes; Hugo-style ordering (weighted ascending before unweighted, then title case-insensitively, then path). Page identity is (path, lang) throughout; the language→content-root mapping lives in exactly one function (ContentRoot), socontent/en/-style layouts later change only that.internal/server:GET /api/tree?lang=andGET /api/page?path=&lang=(replaces/api/debug/tree; README updated). Traversal outside the content root → 400; directory paths, unknown lang, missing files → 404; body parse failure → 422. Strictly read-only.guides/+posts/sections, three leaf bundles (10/20/unweighted to exercise ordering), shortcodes (note,badge) with layout templates; existing plain pages and the draft page kept as-is.Frontend
TreePane: real tree (server order), chevron expand/collapse, single selection, drafts dimmed +draft-badged, ⚠ tooltip for metadata problems; path-less sections (no_index.md) expandable but not selectable./api/treepoll writes no signal when the payload is byte-identical — same discipline that keeps the preview iframe's LiveReload alive. A refetch that removes the selected page clears selection gracefully.PagePane(replaces theFormPaneplaceholder): elements of the selected page in document order, labels/icons vialookupElementSchema()(stub until #3) with shortcode-name + per-kind-glyph fallback; whitespace-only text runs hidden without renumbering document indices.createSelection()exposesselectedElement: {page: {path, lang}, elementPath: number[]}; the placeholder detail pane inPagePanemarks exactly where the schema-generated form mounts.Verification
go vet ./...,go test ./...(content, pagetree, server, supervisor) — greennpx tsc --noEmit,npm test(19 tests incl. same-DOM-node-across-identical-refetch and deleted-selected-page pruning),npm run build— green/api/page, traversal→400, directory→404, unknown lang→404, old debug route→404, SPA servedhugobuilds the extended sample site🤖 Generated with Claude Code
https://claude.ai/code/session_01HHa5His6Hs6xbbAW4ETLY2
Landing audit — #21 (page tree) × #20 (element editor) integration
#21 branched before #20 merged; the two collided across the API surface, the client data layer, and the SPA shell. Resolved via a merge of
mainintoafk/4(two-parent merge commit0ef7565), keeping both features:/api/tree+/api/page(keyed by(path, lang)) alongside/api/elements+/api/page/save, all refactored ontopagetreecontent-root resolution;savenow carrieslang;/api/debug/treedropped. Page identity is{path, lang}throughout.TreePane+PagePane+PreviewPane.PagePanelists a page’s shortcodes recursively (depth-indented) and mounts #20’s schema-generatedFormPanein its detail seam;ElementsPanesuperseded.api.tsunifies both type systems (ShortcodeNode = BlockNode | InlineNode).ElementsPane/placeholder tests replaced by the tree→element→form flow.Verification (resolution re-verified — no prior gate had seen it):
go vet/go test ./...,gofmt, 28 web tests,tsc,vite build,hugobuild of the sample site, plus a live end-to-end save through the built harness (GETtree/page/elements,POSTsave withlang, canonical file rewrite). CI green on the merge commit (run #15).mainis now an ancestor ofafk/4— the merge intomainis conflict-free. Body carriesCloses #4.Verdict: PASS — awaiting free-text merge confirmation.