feat: page field type with shared page-tree picker; news-list section becomes a picked page reference #86
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!86
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/83"
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?
What
A ninth engine field type
page: a reference to a site page, stored as the page's canonical pretty URL (e.g./news/) — the same value shape aslink, so the existing linkrefs whole-value matching gives rename/move rewriting and delete-warnings with zero linkrefs changes. An optional sidecar keypageType:restricts eligible pages by their effective type (front-mattertype, else the section-name convention).Closes #83
Engine (Go)
element:TypePage+Param.PageType(pageType:legal only ontype: page, non-empty; strict-YAML viaRawParam);ValidateValuesstays pure — page values ride the generic string arm.pageops.CheckPageParams(new): the save-time half — exact-permalink lookup via new exportedpagetree.Node.FindByPermalink(real pages only; server's duplicate walk deleted), effective-type match viaeffectiveTypeOf. Messages:must reference an existing page/must reference a page of type "…".handleSavePage({"errors":[…]}, items rows namespaceditems[i].param, tree built per request only when a page param is declared) andpageops.SaveSettings({"fields":{…}}).scaffold/site/AGENTS.mddocuments the ninth type +pageType:; drift test passes.Web
TreeBrowserextracted from LinkPicker's Internal tab (rows, selection/expansion, pre-fill, loading/error states); LinkPicker composes it — its tests pass byte-unchanged.PagePicker: thin dialog over the shared tree; withpageTypeset, non-matching pages are visible but disabled (muted, out of tab order) while their chevrons stay live so nested eligible pages remain reachable; footer Choose commits the permalink.PageField: LinkField's chip pattern (Choose…/Edit…/Clear, server-resolved title viaresolveLinkwith raw-URL fallback), no free text, no<name>Targetcompanion. Works in element forms, items rows, page settings, and create dialogs via the sharedFieldWidgetdispatch.News bundle
news-list.yaml:sectionis nowtype: page+pageType: news. The shortcode is untouched — verified empirically against Hugo 0.163.3 (the CI pin):site.GetPageresolves/news/,/news, and legacy hand-typednewsalike, and a stale value degrades to an empty list. Vendored sites update by re-runningharness add news.Proof
go vet ./...clean;go test ./...fully green with hugo on PATH (hugo-gated theme/build tests included).tsc --noEmitclean.TestRenameRewritesPageParamValues), picker eligibility/disabled rows/pre-fill, chip round-trip incl. server-422 inline rendering, and the news shortcode's canonical/legacy/stale behavior.🤖 Generated with Claude Code
Landing audit — PR #86 →
mainVerdict: PASS
Verification signal relied on: Forgejo Actions
ci / build-and-test— success (5m37s, run #75). Not re-run locally. This repo pins hugo in CI, so the hugo-gated theme/build tests (including the new news-shortcode empirical tests) were exercised.Checks performed:
afk/83, body carries a workingCloses #83. ✅feat:). ✅page+pageType:are documented inscaffold/site/AGENTS.md; the mechanical drift test covers it. ✅type: pagewith optionalpageType:; value stored as canonical pretty URL (schema.go,load.go,doc.go). ✅server.gohandleSavePage withitems[i].paramnamespacing;pageops/settings.goSaveSettings) via newpageops.CheckPageParams; thefieldErrsmerge into the single 422. ✅TreeBrowser.tsx;LinkPickercomposes it and keeps its historical test-ids (tests byte-unchanged). ✅PageFieldchip (Choose…/Edit…/Clear) +PagePickerwith non-matchingpageTyperows visible-but-disabled, chevrons live. ✅news-list.yaml:sectionistype: page+pageType: news; shortcode untouched. ✅TestRenameRewritesPageParamValues. ✅internal/theme/news_test.gopins thatsite.GetPageresolves the canonical/news/, the legacynews, and degrades to an empty list on a stale/gone/— so no shortcode normalization was needed. ✅main; no resolution required.Awaiting the human's free-text go-ahead to merge.