feat(14.2.1-03): document ML fields and regenerate admin artifacts
- Document markdown, mltext, and mlmarkdown plus TranslationWriter save semantics - Extend the SPA registry tests and rebuild committed boardwalk dist Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -97,8 +97,11 @@ for _, f := range form.Fields {
|
||||
| `datepicker` | A date, date and time, or time of day; see [Date pickers](#date-pickers). |
|
||||
| `permissioneditor` | A list of permissions to allow, deny or leave inherited; see [Permission editor](#permission-editor). |
|
||||
| `password` | A masked input with a show and hide button. It is a form-only field: the value is sent with a save and never returned; see [Form-only fields](#form-only-fields). |
|
||||
| `markdown` | A source editor for a host text column, with a sanitized preview; see [Markdown and multilingual fields](#markdown-and-multilingual-fields). |
|
||||
| `mltext` | A text field with one editor per locale; see [Markdown and multilingual fields](#markdown-and-multilingual-fields). |
|
||||
| `mlmarkdown` | A markdown field with one editor per locale; see [Markdown and multilingual fields](#markdown-and-multilingual-fields). |
|
||||
|
||||
The WinterCMS widgets that are not in this list (the rich editor, the markdown editor, the code editor, the color picker, the media finder, the repeater, the tag list and the others) are not provided. A field with one of those types stops the start-up.
|
||||
The WinterCMS widgets that are not in this list (the rich editor, the code editor, the color picker, the media finder, the repeater, the tag list and the others) are not provided. A field with one of those types stops the start-up.
|
||||
|
||||
### Field options
|
||||
|
||||
@@ -318,8 +321,34 @@ func (MembersController) AdminSetPermissionValues(_ context.Context, field strin
|
||||
- A save that does not send the field leaves the stored permissions alone, and the field's `context` applies as for any field.
|
||||
- The keys `options`, `default`, `nameFrom`, `emptyOption`, `relation` and `preset` are refused on the type. A field without `mode`, or on a controller that does not implement the provider, stops the start-up. The type is not available on settings forms or relation forms.
|
||||
|
||||
## Markdown and multilingual fields
|
||||
|
||||
`type: markdown` edits markdown source on a host text column. The admin SPA shows a source editor and may preview HTML from `cabana.RenderMarkdown`, which uses the pinned goldmark engine without unsafe HTML. Output that still contains a script or iframe tag, an event handler, or a javascript, vbscript or data URL is refused, so translated raw HTML cannot become executable preview content.
|
||||
|
||||
`type: mltext` and `type: mlmarkdown` reuse the ordinary text and markdown editors with a locale selector. `mlmarkdown` composes the markdown control rather than a second parser. Each ML field shows its own selector; changing one selector changes every ML control on the form. Copy-from-locale fills the active locale from another code already in the value.
|
||||
|
||||
The save body sends every locale as a JSON object of code to string. Extra YAML keys are not accepted: the types reuse `label`, `comment`, `span`, `size`, `required`, `tab` and `context`. An unknown type such as `mlunknown` stops the start-up.
|
||||
|
||||
```yaml
|
||||
fields:
|
||||
title:
|
||||
label: acme.blog::lang.posts.title
|
||||
type: mltext
|
||||
span: full
|
||||
excerpt:
|
||||
label: acme.blog::lang.posts.excerpt
|
||||
type: markdown
|
||||
body:
|
||||
label: acme.blog::lang.posts.body
|
||||
type: mlmarkdown
|
||||
size: huge
|
||||
tab: acme.blog::lang.posts.tab_content
|
||||
```
|
||||
|
||||
A save of `{ "title": { "en": "Hello", "pl": "Witaj" } }` lifts the nested map before `cabana.ProjectWritableFields` drops nested values. The default locale fills the host column; other locales are written through a published `cabana.TranslationWriter` after the host row has a primary key, still inside the controller's permissioned save transaction. The default locale is not duplicated into the translation store. A non-string value, an undeclared locale, a missing default locale, or a nested map on a field that is not declared multilingual is a 422 on that field. Generic nested objects on other field types are still dropped. Cabana never imports a translate plugin and never exposes a public translate-write route: if no writer is published, a nested ML map is a 422.
|
||||
|
||||
## What a save may write
|
||||
|
||||
The form's writable fields are bound to model columns at boot. A save passes only those fields that are also in the model's `Fillable` list, drops unknown keys, case variants and nested objects, and fills the model with `lagoon.Fill` (see [Models](../database/models.md)). The model's validation rules (a `Rules` method returning `lagoon.Validate` rule strings) and the form's `required` flags are checked in the save's transaction, and a failure is a 422 with messages per field. A value that does not fit its column is also a 422 on that field. A controller implementing `pact.FormRules` supplies its own rule set per operation, which replaces the model's rules for admin saves.
|
||||
The form's writable fields are bound to model columns at boot. A save passes only those fields that are also in the model's `Fillable` list, drops unknown keys, case variants and nested objects, and fills the model with `lagoon.Fill` (see [Models](../database/models.md)). Declared `mltext` and `mlmarkdown` locale maps are the exception: they are lifted first, as [Markdown and multilingual fields](#markdown-and-multilingual-fields). The model's validation rules (a `Rules` method returning `lagoon.Validate` rule strings) and the form's `required` flags are checked in the save's transaction, and a failure is a 422 with messages per field. A value that does not fit its column is also a 422 on that field. A controller implementing `pact.FormRules` supplies its own rule set per operation, which replaces the model's rules for admin saves.
|
||||
|
||||
[Form-only fields](#form-only-fields) are never written by cabana. Their submitted values are validated, when a rule names them, and handed to the controller's hooks; what is stored from them is the hook's decision.
|
||||
|
||||
Reference in New Issue
Block a user