ORT-JAVASCRIPT(1) General Commands Manual ORT-JAVASCRIPT(1)

ort-javascriptproduce ort TypeScript interface

ort-javascript [-S sharedir] [config...]

Accepts ort(5) config files, defaulting to standard input, and creates a TypeScript interface that format the JSON produced by ort-c-header(1) () functions and ort-nodejs(1) exports. Its arguments are as follows:

sharedir
Directory containing external source files. The default is to use the install-time directory.

Output consists of the "ort" namespace with classes that fill data from the JSON into a DOM tree by operating on elements having specific classes. The output of is fully documented using TypeDoc.

All data produced by ort-javascript is contained within a namespace "ort". For example, let "foo" be a struct defined in the configuration.

namespace ort {
  export interface DataCallbacks { ... }
  export interface fooData { ... }
  export class foo { ... }
}

Each struct in the configuration is rendered as a TypeScript interface suffixed "Data", for example, ort.fooData for a structure named "foo". Each native field is mapped to a native type. For references, the type is the referenced interface type.

namespace ort {
  export interface fooData {
    sometext: string;
    someint: string|number;
    somenumber: number;
    areference: barData;
  }
}

Types are mapped as follows, from ort(5) configuration type to the TypeScript type along with any notes.

number|string
number|string
number|string
number|string
number
string base-64 encoded
string
string
number|string
number|string

Front-ends should be attentive to integer types being either string or numeric. This is to accommodate for the 53-bit limit of what's stored as 64-bit integers.

If a field may not be exported due to role restrictions, it is marked as optional within the interface.

In addition to this, a ort.DataCallbacks interface is defined for Customisation and contains callback functions for each field for formatting purposes.

Each struct in the configuration is rendered as a class whose members may be used for formatting output. They are named as found in the configuration.

The following methods are generated for each structure.

new (obj: ort.fooData|ort.fooData[]): foo
Constructor passed an object or array. The array may consist of zero objects.
fillInner(e: HTMLElement|null, custom?: ort.DataCallbacks|null): void
Fill labelled elements within (but not including) element e, with optional call-backs custom. If e is null, does nothing.
(e: HTMLElement|null, name: string, custom?: ort.DataCallbacks|null): void
Convenience method for invoking fillInner() over all descendents of element e having class name. If e is null, does nothing. The "inner" applies to both e and the matched descendents.
(e: HTMLElement|null, custom?: ort.DataCallbacks|null): void
Fill labelled elements within (including) element e, with optional call-backs custom. If e is null, does nothing.
(e: HTMLElement|null, name: string, custom?: ort.DataCallbacks|null): void
Convenience method for invoking fill() over all descendents of (and including) element e having class name. If e is null, does nothing.
(e: HTMLElement|null, custom?: ort.DataCallbacks|null): void
First adds the "hide" class to e, then invokes fill() repeatedly over the objects (or standalone object) passed at construction time by removing, then subsequently cloning and appending, the first element of e. The fill() function is passed the new element's root and custom. If e is null or empty, does nothing except add the "hide" class to e.
(e: HTMLElement|null, name: string, custom?: ort.DataCallbacks|null): void
Convenience method for invoking fillArray() over all descendents of (and including) element e having class name. If e is null, does nothing.
(e: HTMLElement|null, toshow: HTMLElement|null, custom?: ort.DataCallbacks|null): void
Convenience method around fillArray removing the "hide" class from toshow if the object or objects at construction are non-empty.
(e: HTMLElement|null, tohide: HTMLElement|null, custom?: ort.DataCallbacks|null): void
Convenience method around fillArray adding the "hide" class to tohide if the object or objects at construction are empty.

Formatting within the elements passed to these methods operates on specific class names.

The following class names are recognised, letting "foo" be the name of a structure in the config and "xxxx" be any of its fields. If the field is not exported at all or in the given role, no action is taken at all on the following.

Sets or unsets the checked attribute depending upon whether the input's value attribute (if found), as a bit index, is set in the object as a bit-field. Only applicable to bit and bitfield types.
Replaces the contents of the element with the ISO 8601 date of the object's value. Only applicable to date and epoch types. Does nothing if the object is null.
Sets the value attribute to the ISO 8601 date of the object's value. Only applicable to date and epoch types. Does nothing if the object is null.
Sets or unsets the selected attribute on descending (non-inclusive) <option> elements depending upon whether the input's value attribute (if found) matches.
For structures, creates and invokes the () method on the nested structure at the given element and its descendents. This is only applicable for structure types.
Replaces the contents of the element with the field value. This is not applicable to blob native types.
Sets the value attribute (as in a form submission) with the field value. This is not applicable to blob native types.
Sets or unsets the checked attribute depending upon whether the input's value attribute matches the objects. This is not applicable to blob or structure types.
Remove the "hide" class if the object is null, otherwise add the "hide" class.
Add the “hide” class if the object is null, otherwise remove the “hide” class.

All class methods accept an optional argument for providing custom per-field or per-structure callbacks. Keys in the object must consist of the structure name, followed by a dash, followed by the field name. For example, assuming a structure “client” with a field “dob” consisting of a UNIX epoch:

const custom: ort.DataCallbacks = {
  'client-dob': formatDate
};
new ort.client(obj).fillInner(document.body, custom);

And letting a formatting function be:

function formatDate(e: HTMLElement,
  name: string, v: number|string|null): void {
    /* Do something... */
}

The same can be applied to structures instead of to fields within structures. The keys for these are simply the structure name.

const custom: ort.DataCallbacks = {
  'client': formatClient
};
new ort.client(obj).fillInner(document.body, custom);

The callback will then be provided the full client object.

function formatClient(e: HTMLElement,
  name: string, v: ort.clientData|null): void {
    /* Do something... */
}

In either case, the value for the custom key may also be an array of functions just as above. Each will be invoked in the order given, in the same way.

const custom: ort.DataCallbacks = {
  'client': [ format1, format2 ]
};

The callback function (or functions) will be invoked regardless of whether the value has been set. In the event of an unset field value, the function is passed null.

For example, to fill in the label of an enumeration enum someenum on a field named val, provide a custom callback.

const e: HTMLElement|null =
  document.getElementById('foo');
const obj: ort.fooData =
  <ort.fooData>JSON.parse(response);
const custom: ort.DataCallbacks = {
  'foo-val': ort.someenum.format
};

new ort.foo(obj).fill(e, custom);

Each enumeration and bitfield corresponds to a class with field values and formatting static methods.

Enumeration classes contains static members with the string value of its items. For example, an enumeration "foo" will produce a class "foo" with static members corresponding to each enumeration item.

Bitfield classes are similarly named and contain two static members per item: one for the bit index, one for the generated bit mask. The former is prefixed BITI_ and is a number, the latter with BITF_ and is a string. Thus an item "bar" creates numeric static members BITI_bar and BITF_bar. There is always a BITI__MAX that is one greater than the largest item's value.

Each enumeration corresponds to a class with field values and formatting static methods. These take advantage of the jslabel enumeration label described in ort(5).

(e: HTMLElement, name: string|null, value: string|number|null): void
Fills in all elements (not inclusive) descending from e having class name-label with the configuration label corresponding to the enumeration value value. If name is null, the element itself has its contents filled in.

If value is null, the "ort-class" is added and the isnull label is used (or an empty string).

If a language is specified in the root of the HTML or XML document with the "lang" attribute, it is first matched a label for that language. If there is no language, or none for that label, the default label is used. If there is no default label, an empty string is used instead. An empty string is also used for invalid enumeration values.

A common label fill idiom is as follows:

<div id="place">
  <span class="foo-val-label>label</span>:
  <span class="foo-val-text>text</span>
</div>

Letting the field "val" have type enum anenum, both label and text may be filled in as follows:

const custom: ort.DataCallbacks = {
  'foo-val': ort.anenum.format
};

This will fill in both the jslabel of the value's corresponding item and the value itself.

Bitfields behave similarly and have the same member.

(e: HTMLElement, name: string|null, value: string|number|null): void
Fills in all elements (not inclusive) descending from e having class name-label with all configuration labels with corresponding bits set in value. If name is null, the element itself has its contents filled in.

If value is null, the "ort-null" class is added and the isnull label is used (or an empty string). If value is zero, the "ort-unset" class is added and the isunset label is used (or an empty string). Multiple matching labels are separated by a comma and space. If any given bit doesn't have or match a label, it is not given any label text.

The ort-javascript utility exits 0 on success, and >0 if an error occurs.

Start with a means to contact a CGI script producing JSON data formatted by the json_xxxx() family of ort-c-header(1). This does not do any error checking. Let this file be called script.ts.

function init(): void
{
  let xmh: XMLHttpRequest = new XMLHttpRequest();
  xmh.onreadystatechange = function(){
    let v: string = xmh.responseText;
    if (xmh.readyState === 4 && xmh.status === 200)
        success(v);
  };
  xmh.open('GET', 'https://your-cgi-script', true);
  xmh.send();
}

Now in the same file, define success() to parse the JSON response content using the classes and methods defined in the output of ort-javascript.

function success(resp: string): void
{
  let obj: ort.fooData =
    <ort.fooData>JSON.parse(resp);
  new ort.foo(obj).fill
    (document.getElementById('place'));
}

To drive the script, cause init() to be invoked when the page has loaded.

window.addEventListener('load', init);

The following abbreviated HTML in which to display the contents of these objects. Let foo.js be the concatenated output of tsc(1) over all TypeScript files.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Example</title>
    <script src="foo.js"></script>
  </head>
  <body>
    <div id="place">
      <span class="foo-xxxx-text>
        Replaced by the "text" field.
      </span>
    </div>
  </body>
</html>

Assuming a configuration file foo.ort, the following creates the single JavaScript file:

% ort-javascript foo.ort > foo.ts
% tsc --alwaysStrict --strict --outFile foo.js foo.ts script.ts

ort-c-header(1), ort-nodejs(1), tsc(1), typedoc(1), ort(5)

October 25, 2021 OpenBSD 6.7