Skip to content

Instantly share code, notes, and snippets.

@jahan-addison
Last active September 23, 2019 18:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jahan-addison/9710d83d58b7293aa40f2172ab0bb80d to your computer and use it in GitHub Desktop.
Save jahan-addison/9710d83d58b7293aa40f2172ab0bb80d to your computer and use it in GitHub Desktop.

The Schema Documentation Language

Overview

The language is designed to be entirely agnostic and platform-independent — It is primarily designed as a comment block above javascript and YAML. By building the schema language as a general-purpose compiler, we have full control over syntax or where it can be used and can build documentation or metadata (such as JSON schema) across the board anywhere in our content.

Targets

The schema language may be compiled to more than one target. Currently, it compiles to JSONSchema — but Jekyll and HTML for self-documentation are in the future roadmap.

JSONSchema

When the target is JSONSchema, the blocks of comments are translated directly into metadata that is used in Forge. Forge uses the React-JSONschema-forms project to generate forms that facilitate building and customizing blocks and components for page and pattern creation.

Previously, TOML files were stored in the components repository that became very hard to update and maintain. By designing a language that can be used in comments directly above blocks of javascript and YAML, we can verify and validate metadata at compile-time with esdoc in addition to immediate pull requests instead of maintaining multiple repositories with toml and its complexity with JSON schema.

Language

The goal of the language is to simplify complexity as much as possible and resemble other compile-time annotation languages such as Doxygen or dartdoc — while providing enough tools to at least match the requirements of jsonschema-forms. The grammar for the language can be found here.

A document is a collection of directives , props (that has types, features, with or without flags), and containers of nested structures. Containers may themselves have directives, props, placeholders, and containers that may be nested infinitely. Note that all indentation is optional.

A document describes pieces of content such as SDK blocks, components, patterns, and even pages, and their data structure.

This language was designed internally to receive feedback and encompass all of our needs for content and forge. Please send pull requests or comments!

Example: (based on this) and it compiles to this JSONSchema.

/**
 * @View
 *
 * @name email
 * @type block
 * @description Email block
 * @content
 *  @prop @required button_text type={string} title="Button Text" description="Enter Details for Email"
 *  @prop @advanced button_class type={string} title="Button Class" description="CSS Class(es) for button"
 *  @prop @advanced email_form_class type={string} description="CSS Class(es) for email form"
 */

Example 2:

/**
 * @View
 *
 * @name button
 * @type block
 * @description button block
 * @content
 *  @contains @array_of 'buttons' with:
 *    @includes @optional blocks: {{blocks}}
 *    @prop id type={string} description="button id"
 *
 *    @prop class type={string} description="class name(s)"
 *
 *    @prop @required text type={string} description="button text"
 *
 *    @prop [type] description="type of button event"
 *      "open_modal"
 *      "action"
 *
 *    @prop modal_id type={string} title="modal target id" \
 *     description="a modal id target"
 *
 *    @prop target_id type={string} title="target id" \
 *     description="a target id for your action"
 *
 *    @prop [action] title="action name" description="action to be performed"
 *      "toggle_visibility"
 *  @end
 */

Details:

Directives

A directive is a metadata tag for a container or global structure in a document.

There are 3 different types of directives — global and container level and placeholder.

Global:

Global Directives Description Parameters Example
@View Marks the beginning of document. none @View
@name Name of content for document. {String} @name email
@type Type of content. (e.g. block, component) {String} @type block
@description Description of content {String} @description My super cool block
@content (Optional) Marks the end of global directives. none @content

Container:

Container Directives Description Parameters Example
@title Title of object block structure. {Quote-String} @title "header region"
@minimum A minimum of objects in block structure. {Number} @minimum 2
@maximum A maximum of objects in block structure. {Number} @maximum 5

Placeholder:

Placeholder Directives Description Parameters Example
@includes Injects a region for nested blocks or components in current structure. {String} title: {{injection-type}}
  • @includes blocks: {{blocks}}
  • @includes layouts: {{layouts}}
  • @includes components: {{organelles}}
@excludes Excludes a block or component type during an @includes. {String} title: {{type}}
  • @includes blocks: {{blocks}} @excludes block: {{component}}

Props

Props are data properties of content in a container or global structure. They are the properties that can be defined in page YAML or in Forge jsonschema-forms.

A prop contains an identifier (name of the prop) with many attributes. header and description are the standard but ANY attribute may be defined; additionally delimited across more than one line with the backslash.

There are 2 different types of props — data and enum — each may have multiple flags, types, and one feature. The enum type has its identifier enclosed in [ ].

Examples:

* @prop @required title type={string} header="A title" description="A very cool title for this course content" language="en" @allow richText

Enum props are for multiple-selection data attributes.

 * @prop @advanced [animation] type={string} title="Animation style" default="bounce"
 *    "bounce"
 *    "pulse"
 *    "swing"
 *    "tada"
 *    "jello"
Flags Description Parameters Example
@required This prop is required. none @prop @required allowMultiple type={boolean} title="Allow multiple items"
@advanced This prop is particularly complex and may be hidden by default none @prop @advanced allowMultiple type={boolean} title="Allow multiple items"
Types Example
string @prop header type={string}
number @prop amount type={number}
boolean @prop collapsible type={boolean}
null @prop doNothing type={null}
undefined none
Features Description Parameters Example
@allow Allows a widget type in forge for a prop (ui schema) {String} @prop icon_header type={string} title="font awesome icon" @allow iconPicker

Container

Containers are nested structures within content such as inputs in a form or text items in a list. Placeholders allow containers to have rendered nested child SDK blocks or component types. Containers may themselves have containers.

Containers may have Container directives as described above for metadata on their definition. Moveover, they can be defined with flags.

The @end tag at the end of containers are required; this facilitates stacking and nesting of many.

There are 2 types of containers - regular and @array_of. The regular container are objects and are generally for placeholders that can render nested child SDK blocks or some other defined content structure. The @array_of is a container definition with more granular control of its content and meaning.

Example:

 *    @contains 'region' with:
 *      @title 'items'
 *      @includes blocks: {{blocks}}
 *    @end
 *  @contains @array_of 'bellows' with:
 *    @title "bellows"
 *    @minimum 2
 *    @maximum 5
 *    @prop @required @advanced class type={string} description="class name(s)"
 *    @prop header type={string} title="header" description="expandable "
 *    @prop description type={string} title="description" \
 *      header="expandable header text for this bellow"
 *    @prop icon_header type={string} title="font awesome icon" @allow iconPicker
 *  @end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment