← Playground index

.apiext — extended element-API format

A superset of WebObjects' .api format adding per-element and per-binding documentation, binding types, directionality, and value interpretation — enough to render an element's API in an editor. Proposal stage; in use here. The element reference renders entirely from .apiext files.

The current/old .api declares an element's bindings — names, a few flags, cross-binding validation — and little to nothing about what a binding means or it's typing. .apiext adds that as a strict superset: existing .api files validate unchanged, and the new information is additive. The WO runtime does not read .api; only tooling does (WOLips, Parslips), so a successor format is constrained only by "don't break existing files".

Format

Same skeleton as .api (<wodefinitions> / <wo> / <binding> / <validation>); extensions in green:

<wodefinitions>
  <wo class="WOCheckBox" wocomponentcontent="false" passthrough="true">

    <doc><![CDATA[A checkbox. Use **either** `checked` or `value`+`selection`.]]></doc>

    <binding name="checked">
      <pull><type interpretation="truthy">java.lang.Object</type></pull>
      <push><type>java.lang.Boolean</type></push>
      <doc>The checked state.</doc>
    </binding>

    <validation message="A WOCheckBox uses either 'checked' or 'value', not both.">
      <bound name="checked"/> <bound name="value"/>
    </validation>

  </wo>
</wodefinitions>

Documentation

Each element and binding may carry a <doc>. Bodies use an injection-safe Markdown subset (inline `code`, **bold**, *italic*, links, fenced code blocks); a plain consumer can show the raw text.

Types

A binding declares one or more <type> — a fully-qualified Java class (or, later, a value-set name). Multiple types mean "accepts any of these" (e.g. updateContainerID: String or List). Intended for validation, not only display.

Directionality — <pull> / <push>

A binding's type can differ by direction: a checkbox's checked pulls any value (read as a boolean) and pushes back a Boolean. The type lives inside a direction block; the presence of <pull>/<push> declares the direction (no separate direction= attribute).

Only type is direction-specific; name, doc, and required stay on the binding. A <type> is always inside a direction block, never a direct child of <binding>.

Interpretation — interpretation="truthy"

Some bindings read a value by a coercion rule, not by type. WOConditional.condition accepts anything but reads it as a boolean (null, 0, false → false). The interpretation attribute names that rule without changing the type: <type interpretation="truthy">java.lang.Object</type>. The type remains the validatable constraint (Object); the interpretation is shown as a qualifier, Object (truthy).

Out of scope

The format describes a binding's contract, not the runtime. A type that is only determined at runtime is declared as its widest honest type. Example: WOTextField.value pushes a String, Number, or NSTimestamp depending on the bound formatter (anything, for a custom one), so its push type is declared Object, with the detail in <doc>.

Status

CapabilityStatus
per-element / per-binding doc (Markdown)present
typed bindings (multi-type)present (declared; enforcement is future work)
required, cross-binding validationpresent (verbatim from .api)
directionality (pull / push)present
value interpretation (truthiness)present
default values, deprecation, value-sets, unknown-binding policynot yet

Validates as a superset of WO's DTD (including WebObjectsDefinitions.xml). The format spec — grammar (apiext.dtd), field-by-field reference, examples, and status — lives in its own repository: github.com/undur/apiext-format.