Skip to content

15. Conformance

Contents of FBL 0.9

15.1 Conformance classes

Class Requirements
FBL document Validates against $defs/Document and passes the checks of section 14.1 without errors.
Validator Implements section 14.1, (FBL 0.9) building every grammar a binding carries, and reports problems with JSON Pointers; checks registrations against $defs/Registration and fixtures against $defs/Fixture and section 15.3.
Host — declared Implements the lossless readings of the families it supports (section 4), rules (section 5), the splice catalogue and new-text rules (section 6), history and drift (section 7), the registration (section 8), several readings (section 9), routing and templates (sections 12, 13), and passes every fixture of the families it supports. It states which families it supports.
Host — full Host — declared for the six families of FBL 0.8, plus folder subjects (section 10) and the plugin contract (section 11). (FBL 0.9) No host is required to support the grammar family; a host that does says so and passes its fixtures byte for byte, every host producing the same splices (section 6.5).
Persistence plugin Meets section 11.4 for its format.

A host that does not support a binding's family or plugin MUST open its documents read-only, if it can read them at all, and say why; this is DISL's rule for a missing required plugin (DISL §13.1).

15.2 Graceful degradation

A host that cannot watch files reads bodies on open and on request only, and says so. A host that cannot keep the registration (a read-only workspace) keeps positions for the session only, and says so. Nothing else in this document degrades: byte preservation, exact undo and drift refusal are required of every host.

15.3 Round-trip fixtures

fixtures/<name>/fixture.json, validated by $defs/Fixture, is a conformance test for hosts:

Property Description
binding The binding under test, relative to the fixture.
input The input body, a file beside the fixture, compared byte for byte (the repository keeps these files from line-ending conversion).
read What reading the input yields: (FBL 0.7) document, the attributes of the document as attributes below, elements (id, type, (FBL 0.7) optionally parent, the id of the element it is contained in or null at the top level, and (FBL 0.5) optionally attributes, the values read for the attributes it names, a JSON string for a text and a JSON number, bool or null otherwise), findings (rule, line), unreadable.
steps In order: an edit (add, set, remove, (FBL 0.3) move, place, (FBL 0.7) setting, or save without change; an add or a move carries a position as section 11.2 gives it, and (FBL 0.5) an add the slot it fills, as section 11.2's add does, which a host needs when one type fills several slots of one parent), an undo or a redo; the splices it must produce, as {operation, start, end, text} with UTF-8 byte offsets into the document before the step; the document after it (expect, or expectFile); refused with the reason when the edit must be refused and write nothing.

(FBL 0.7) elements lists every element the body's entries yield, in reading order, and, when the input is a registration, the elements the tool type's specification makes of its blocks as well (DESL sections 5.5, 7.7.2). An attribute with many is stated as a JSON array of its items in order, and an enumeration's value by its key. A step's edit is one change, or a list of changes that one transaction makes, planned in order as one edit (section 6.4); a set or remove may carry occurrence, the place in reading order of the holder of a duplicated id it concerns (2 for the second). Its splices are listed in the order section 6.5 applies them: by offset, and at one offset in the order the edit made them. A setting on a list block that is absent is planned as the tool type's specification gives it, which may write the whole list (DESL section 5.5).

A host passes a fixture when reading the input gives what read lists (for an element with attributes, each attribute named there has that value and that JSON type; attributes not named are not compared) and every step produces exactly its splices and its document. For a refused step it passes when it refuses the edit and writes nothing: the text of refused is informative, because FBL leaves a refusal's wording to the host except where a binding gives the reason itself (readOnly, section 3.4), and then it is that reason. The repository's validator checks every fixture's consistency: each step's splices turn the document before it into its expect, and back by their inverses; an undo returns the document the undone edit started from; a save and a refused edit change nothing. Undo steps list the inverse splices under the operation of the splice each inverts.

(FBL 0.7) A setting edit changes an entry of a declared block of the registration, which is then the fixture's input: it names the block and the entry's key, and gives its new value, its new position in a kept block ({index}, {after: key} or {before: key}), a new key as rename, or remove: true; a setting with a position and no value moves the entry. When the input is a registration, the fixture's read is that of the document it opens: the elements of the body it names, and the findings, a registration finding's line being a line of the registration. A fixture for a registration that createOnFirstPlacement creates starts from the text section 8.4 creates. A step whose setting writes a block outside the history is no step of the history, so an undo after it undoes the edit before it.

Together the fixtures exercise every operation of section 6.1.

Referenced from