refactor(element): field types defined once in Go #165
No reviewers
Labels
No labels
bug
enhancement
needs-triage
ready-for-agent
ready-for-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle!165
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/163"
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 #163
What
Each of the eleven field types is now defined once, in its own file in
internal/element(ftype_<name>.go). Every file implements the unexportedfieldKindinterface, and that one definition owns everything about the type:options,pageType,default), the scope rule (multiselectonly in page-type fields), and the name binding (categories);<name>Targetsetting;Uses,Compare,FilterMatch).A type that lacks a job doesn't compile.
TestFieldTypesMatchRegistryfails whenFieldTypes()and the registry differ.Every server path now goes through these definitions:
Schema.Check(values, site)replacesValidateValues,CoerceValues,CheckPageParamsandCheckCategoryParams. It runs for element saves, item rows, properties saves, page create and the rich-text body save. The caller hands in the site lookup,pageops.NewSite, which builds the page tree and reads the categories lazily.FieldType.Readserves properties, the module list and the page date.MergeParams/FrontMatterChangeswrite throughParam.ShortcodeValue/Param.FrontMatterValueoverSchema.Managed().ElementSummaryandLinkParamValuesuseUses().Behavior changes (as specified)
datetime: any spellingcontent.DateRFC3339reads is accepted from any source, sidecar defaults included. A value without an offset is read as UTC, and the value is stored as a quoted RFC3339 string.default: next tuesdayis a load error naming the file.multiselect: a single string (tags: events) reads as["events"]in properties and in the module list, and a properties save keeps it.number: an unreadable value is no value. Properties show the default, else empty ("", the number input's empty value), and the module list leaves it out. A save never writes0.start="2026-07-10"becomes"2026-07-10T00:00:00Z". Undeclared params are left untouched, as on an element save.pagefield that names a missing page or a page of the wrong type.Follow-on effects worth knowing
"5"for a number,5for a text field, a single string for a multiselect,"a,b"for categories. Error messages for datetimes now say "must be a valid datetime, e.g. …".""in properties, where it used to read0.content.DateRFC3339formats withtime.RFC3339, so a datetime with fractional seconds loses them."", or a categories list where every slug is stale) is now left out of module entries.The issue's assumptions were checked:
DateRFC3339uses the same cast layouts as Hugo'shtime. The only difference is UTC instead of the site's time zone.ToStringSlicePreserveString).Verification
go build ./...andgo vet ./...pass.go test ./...passes.npm testpasses all 1860 tests.Checkwith a fake site;pagefield;🤖 Generated with Claude Code
[autoland] verdict: pass
PASS — validated, awaiting the human's merge go-ahead.
ci / build-and-test (pull_request)green (run 151, 9m3s) — Go build/vet/test plus the web suite. Not re-run.Closes #163present; headafk/163is current withmain(no conflict).scaffold/site/AGENTS.md(and README) updated for datetime defaults in any spelling, single-string multiselect, and inline-element checks on body saves; drift test now readsFieldTypes().fieldKind(internal/element/ftype_*.go), with a registry/order test.Schema.Checkreplaces ValidateValues/CoerceValues/CheckPageParams/CheckCategoryParams on element saves, item rows, properties saves, page create and inline body elements, through a lazypageops.NewSite. Reads go throughFieldType.Read(properties, module list, page date); writes go throughShortcodeValue/FrontMatterValueoverManaged(). TheUsessets match the old editormodule/sorter/summary/LinkParamValues tables exactly. No per-type switches remain outsideinternal/elementexcept built-in param declarations.""(renders empty, omits it on save). Chip insertion is configure-first, so the new inline check doesn't block fresh chips. The items-without-collection guard still runs beforeitemSchema.Check. deckle-hosted imports no deckle Go packages.No CONCERNS. Documented, intended behaviour changes: sub-second datetime precision is dropped, a numeric datetime reads as Unix seconds, and an inline chip naming a since-deleted page now blocks its parent's body save until the chip is edited.