FS FormScript
Package@formscript/render
Specification4.25, 5.1, 7.13, 7.14, 8.1, 8.9, 12.6, 15.2, 15.3
Depends onast, types

@formscript/render

Render intents, per §15.2 and §15.3 of the specification.

FormScript emits intents, never markup (§15.2). This package computes the intent a renderer should present; the renderer maps it to a platform widget.

The fourteen intents

ts
import { RENDER_INTENT_KINDS } from '@formscript/render';

RENDER_INTENT_KINDS; // ['RenderTextInput', 'RenderNumberInput', 'RenderChoice', …]

RenderTextInput, RenderNumberInput, RenderChoice, RenderMultiSelect, RenderDate, RenderToggle, RenderFile, RenderSignature, RenderLocation, RenderGroup, RenderRepeat, RenderProgress, RenderErrorSummary, RenderMessage — the fourteen of §15.2, in the order the specification lists them. RenderIntent is a discriminated union with one variant per intent, so intent.intent === 'RenderChoice' narrows the payload.

Computing an intent

The intent is computed from the declaration alone. The input is a plain record: no expression, no evaluator, no locale, no clock.

ts
import { computeRenderIntent } from '@formscript/render';

const intent = computeRenderIntent({
  kind: 'field',
  id: 'email',
  name: 'email',
  type: { kind: 'scalar', name: 'string' },
  required: true,
  readOnly: false,
  derived: false,
  overridable: false,
  label: 'Email address',
});

intent?.intent; // 'RenderTextInput'

renderDeclarationFromBlock reads a parsed field, choice, group, repeat, section or page block into that record. It resolves only what is written down: a t("key") label needs a catalogue and a locale, and a dynamic required needs an evaluation, so the host supplies both.

Function Purpose
computeRenderIntent the intent to present; undefined when the entity is not rendered
selectRenderIntent the widget the declaration selects, whatever its applicability
renderSkipReason why no intent was produced: inapplicable, missing-type, options-type-conflict
computeRenderIntents the intents of a set of declarations, in order
renderDeclarationFromBlock reads a parsed block into a declaration
renderTypeFromRef the presentation view of a type reference
presentationPlane the presentation-plane properties of a declaration (§12.6)
checkRenderObligations the statically checkable obligations of §15.3
checkIntentCoverage the unmapped-intent warning of Spec-15.2
errorSummaryIntent, messageIntent the two intents a document does not derive from a field

The rules that select an intent

  • options or optionsFrom makes a field a constrained selection, and RenderChoice (Spec-4.24, Spec-4.27).
  • type = enum(…) makes a field a constrained selection, and RenderChoice.
  • type = array(…) makes a field a multiple selection, and RenderMultiSelect; its options come from the element type when the element is an enum.
  • A group is RenderGroup, a repeat is RenderRepeat, a page is RenderProgress, a choice is RenderChoice.
  • A derived field (value = expr) is not editable unless it is overridable (Spec-7.4, §8.9).

The two planes

label, hint, help, placeholder, unit, addLabel, removeLabel and format are the presentation plane (§12.6). presentationPlane returns them; the data plane never reads them, and this package never evaluates a value expression, so an intent cannot depend on a presentation read. The analyzer reports E-TYPE-08 when a display value reaches a data position; this package does not report it again.

Judgement calls

The specification lists the fourteen intents but never says which declaration selects which. The rules above are the most literal reading; the choices that the text leaves open are recorded here.

  • section → RenderGroup. §15.2 has no section intent. §7.14 makes a section a presentation grouping that introduces no data level, so it renders as the labelled composite a group renders as.
  • page → RenderProgress. The only page-level intent in §15.2 is RenderProgress ("Page progress").
  • duration → RenderTextInput. §15.2 has no duration intent. §5.1 lists duration beside date, so date and datetime give RenderDate and duration falls back to the free-text widget.
  • object → RenderGroup, any → RenderTextInput. §15.2 has no composite-value intent and no untyped intent.
  • A declared options list wins over the enum type's own options. §4.25 attaches labels to keys and does not say how the two sets combine; the analyzer reports a document whose two sets disagree.
  • A field with no type produces no intent (Spec-7.6 makes type required) and a field whose options conflict with its type produces no intent (Spec-4.24). Neither is re-reported here: the analyzer owns those diagnostics.
  • An inapplicable entity produces no intent (Spec-8.3: it is not rendered). selectRenderIntent still reports the widget it would use, so a renderer can keep the identity of a field that comes back.
  • format is treated as presentation-plane. §12.6 puts formatted numbers, dates and currency in the presentation plane, and format is a display format (§8.1).
  • §15.3 is only partly checkable. A label for every control, a stable identity and the placeholder prohibition are checkable from the intents and are implemented by checkRenderObligations. The focus and cursor obligations (Spec-15.4 bullets 4–5, Spec-15.5) are renderer behaviour; the stable id on every intent is what makes them achievable.

Ambiguities in the specification

  • §15.2 does not say which properties select an intent, and it has no intent for a duration, an object or an any value.
  • §7.13 says a choice is semantically a field whose type is enum, but §8.1 gives choice a type property of its own and Spec-4.27 lets a field with options be a string. This package therefore treats a choice as a choice whatever its type, and reports options-type-conflict only for a field whose type may not carry a choice set.
  • §15.2 describes RenderProgress as "Page progress" without saying whether it stands for the page or for a progress element inside it.

Public API

53 exported symbols.

checkIntentCoverage re-export
checkRenderObligations re-export
computeRenderIntent re-export
computeRenderIntents re-export
errorSummaryIntent re-export
ErrorSummaryOptions interface
findRenderNode function

The node a path names, or `undefined` when no node has it.

flattenRenderNodes function

Every node of the tree, in document order.

messageIntent re-export
MessageOptions interface
PRESENTATION_PROPERTIES const

The presentation-plane properties of §12.6.

presentationPlane function

Extracts the presentation plane; the data plane never reads these (§12.6).

PresentationProperty type
RENDER_INTENT_KINDS re-export
RenderBound interface
RenderChoiceIntent interface
RenderDateIntent interface
RenderDeclaration interface

Everything a renderer needs to choose a widget, resolved from the declaration alone.

renderDeclarationFromBlock function

Reads a block into a declaration; only written-down values are resolved.

RenderDeclarationOptions interface
RenderEntityKind type

The entity kinds that render (§7.1: a `state` declaration renders nothing).

RenderErrorEntry interface

One failing field in the error summary of §13.4.

RenderErrorSummaryIntent interface
RenderFileIntent interface
renderFormTree function

The form's entities, in document order, with the intent each one selects.

RenderFormTreeOptions interface
RenderGroupIntent interface
RenderIntent type
RenderIntentCommon interface

What every intent carries, whatever its widget.

RenderIntentIdentity interface
RenderIntentKind type
RenderLocationIntent interface
RenderMember interface
RenderMessageIntent interface
RenderMessageLevel type
RenderMultiSelectIntent interface
RenderNode interface

One entity of the form, with the declaration and the intent it selects.

RenderNumberInputIntent interface
RenderObligation interface

A renderer obligation that a set of intents does not satisfy.

RenderOption interface

A choice option: the stored value and the label a person reads (Spec-4.25).

RenderOptionsSource type

Where the choice set of a declaration comes from (Spec-4.25, Spec-4.26).

RenderPresentation interface

The presentation plane of a declaration, as a person reads it (§12.6).

RenderProgressIntent interface
RenderRepeatIntent interface
RenderSignatureIntent interface
renderSkipReason re-export
RenderSkipReason type

Why a declaration produced no intent.

RenderTextInputIntent interface
RenderTextResolver type

Resolves a presentation expression to the text a person reads.

RenderToggleIntent interface
RenderType type

The presentation view of a type reference; it keeps the labels a person reads.

renderTypeFromRef function

Converts a parsed type reference into the presentation view of a type.

selectRenderIntent re-export