FS FormScript

Rendering

FormScript does not describe a page. It describes a form, and a renderer turns that form into whatever the platform wants: a web page, a phone screen, a kiosk, a printable document.

The rule that makes this work: FormScript emits intents, never markup.

The intents

Intent What it is What a web renderer does with it
RenderTextInput free text <input type=text>
RenderNumberInput a number, formatted for the locale <input type=number>
RenderChoice a constrained selection radio buttons or a select
RenderMultiSelect several of many a checkbox group
RenderDate a date a date input or a picker
RenderToggle a boolean a switch or a checkbox
RenderFile an attachment a file input
RenderSignature a signature a canvas
RenderLocation a place a map picker
RenderGroup a labelled composite a fieldset
RenderRepeat a list that can grow repeated fieldsets
RenderProgress how far through a progress element
RenderErrorSummary why the submit failed an alert region
RenderMessage an inline message text with aria-live

A renderer must map every intent it receives. An unmapped intent is a conformance failure, and the runtime surfaces it as a warning rather than silently dropping the field — a form that quietly loses a question is worse than one that complains.

A renderer may map an intent to a different widget, as long as the mapping preserves the intent's accessibility, validation and keyboard semantics. Mapping RenderChoice to a control that cannot be operated by the keyboard alone is not allowed.

Why intents and not markup

Because markup is a platform decision, and the questions in a form are not.

A document that says "the applicant is asked for a guarantor when the loan is over ten thousand" has said everything about the form. Whether that is a radio group, a dropdown, a field revealed by JavaScript or a printed line with a box beside it is a decision for the renderer — and a decision that has to be made again, differently, on every platform.

The intents keep the first kind of statement in the language and the second kind of statement in the renderer.

What a renderer must do

The specification's obligations for a renderer (Level 2 and above) are about behaving like the form says:

  • maintain a labelled control for every active field;
  • expose the field's state to assistive technology;
  • keep the keyboard order the same as the document's order;
  • make an inapplicable field disappear, rather than hide it in a way that leaves it in the tab order;
  • show the validation messages where the constraint says they belong.

And the whole of §13, on accessibility, applies to the renderer rather than to the document: the document says what the question is, and the renderer makes sure a person can answer it.

Seeing it for yourself

The playground renders a form with the reference implementation's own renderer, and the language page shows the intents the real code produces for a real document.

The packages are:

Package What it does
@formscript/render the intents, and the contract
@formscript/render-dom renders intents into a DOM
@formscript/render-html renders intents into HTML

The conformance levels

The levels say how much of this a runtime has implemented:

  • Level 0 — the document is read and analysed: it can be linted, and the diagnostics are right.
  • Level 1 — the document is evaluated: the output document is right.
  • Level 2 — the intents are produced, and a renderer exists.
  • Level 3 — the whole of the language, including the parts this site documents at a glance: the remote data model, the action model, the accessibility contract.

The reference implementation declares Level 3, and the conformance page lists the evidence for each part of the claim.

The level is checked, not claimed: npm run formscript -- level prints the declaration and the evidence behind it.