JavaScript

Documentation Formatting Guide

Keeping documentation relevant, concise and up to date is very important to us. As such, we have ensured that updating and writing documentation for Ably is a simple process for Ably staff and developers, and even our customers and partners. We welcome you to fork this documentation repository, update the documentation as you see fit, and send us your pull requests so we can incorporate your changes.

Please see this documentation repository’s README for details on how to fork this repo, make changes, and send pull requests back to Ably. From a high level, the documentation within this repository is used to generate a static site hosted at docs.ably.com, which is subsequently imported into the primary Ably website documentation periodically. All documentation is formatted using Textile markup. Please refer to Promptworks for a complete Textile reference. The Textile documentation is converted into HTML using Nanoc.

Detailed below are specific Ably layout techniques that you should be aware of when writing documentation. All standard Textile markup is supported in addition to what is documented below.

At the top of each textile page, the following metadata can be included as follows:

--- title: "Enter a title that will appear in the navigation and HTML page title" section: "Specify either rest|realtime|other|none to assign to nav on the left" index: 0 # Optional integer position within the nav, 0 is reserved for index & home api_separator: #This being specified will result in a seperator between docs and API docs Section Title: #Title of a section in API separator - External Link:/external/link #External link - Internal Link#internal-link #auto-links to #internal-link jump_to: # Optional YAML tag that will insert a "jump to" navigation based on YAML "External Links": # surrounding quotes are not normally needed... - External Link 1:/external/link #Separate with a ":" to link to /external/link "Help with": - "Item 1#anchor-link-id" # links to #anchor-link-id "API methods": - "Item 2" # auto-links to #item-2 - "Item 3" # auto-links to #item-3 - "Language specific content"#language-specific-content ---
Copied!

View this page’s Textile markup for an example of the jump to navigation.

Note that if you have referenced an anchor that has language specific content, the jump to navigation will automatically update to reflect the new content for that anchor whenever a language is selected, and ignore the text you have provided. Also, if an anchor is longer visible because it is contained within a language block, the corresponding navigation item will be hidden.

The following metadata attributes are supported:

--- meta_description: "Description for this page rendeded in HTML meta description field" meta_keywords: "Keywords for this page rendeded in HTML meta keywords field" meta_image: "/images/path/to/file/in/assets/folder.png" ---
Copied!

Certain pages have additional pieces of metadata which can be used to help the website display unique information.

Pages in the /compare folder can have the following additional metadata:

--- published_date: January 3000 competitors: - "competitor1 ID, which should match the ID used on the website" - "competitor2 ID, which should match the ID used on the website" ---
Copied!

Pages in the /tutorials folder require certain metadata to make them indexable at Ably’s website. * denotes required meta fields, but isn’t valid yaml. If copy/pasting, don’t forget to remove them

--- alt_title: an alternative title to display on the website excerpt: A small blurb introduction for your tutorial category*: introduction | external-services | liberaries-integration platform*: mobile | browser | mixed authors*: * author_name: Supports multiple authors author_bio: but must be an array even if single author author_profile_url: https://authors_website.com author_image: hosted gravatar or an image present in websites images/tutorials/ folder * author_name: Second Author author_bio: "" author_profile_url: "" author_image: "" level: String (suggestions: medium | easy | hard) reading_time: Number in minutes tags: - ably-realtime - ably-features - example-apps ---
Copied!

The title of the page is automatically inserted into the page using a h1. tag. A simple breadcrumb navigation will be shown if the page has an index other than zero, and a page with index 0 exists.

 Tip

Use bq(definition). for method definitions after h6. method anchors. See blockquote definitions.

h1. used to indicate a new section such as the API reference, the title will be used within the in-context navigation. The first paragraph that follows will always contain larger text. You can continue this larger style by using a p(larger). tag. h2. used for the key secondary headings on a page, and will be used within the in-context navigation. h3. used for the key tertiary headings, all paragraph text that follows is indented h4. to h5. used for further headings decreasing in emphasis used in a typical hierarchical fashion h6. used to designate a definition or reference, see REST history section in maroon for an example of how this is used

h[1-6](#anchor-id). used with any heading tag to add an HTML ID that can be linked to using anchor tags

Absolute reference links such as <a href="http://www.google.com">Google</a> can be used as normal.

All links to other documentation pages must follow the format <a href="/rest/channels">REST Channels</a>" and must resolve to a relative path for this repository. When imported into the main Ably website, the links will be automatically modified to link to the correct page in the Ably webite documentation.

Anchor links can be used as follows <a href="/api/rest-sdk/statistics#stats">REST spec stats</a>.

Links can also contain mono-spaced code references within the link using the format <a href="/rest/channels">mono-spaced-link-text, which would appear as mono-spaced-link-text

Simple code keywords inline within your content are used commonly by wrapping them the symbol. For example <notextile><code>method</notextile> is presented as </code>[email protected]

For all code blocks, a language in lowercase must be specified. Languages currently supported are javascript, java, android, kotlin, python, php, ruby, nodejs, typescript, objc, swift, go, csharp, cplusplus, flutter, c, css, appcelerator, phonegap, curl, html, json, sh, yaml. A code block must be prefixed and suffixed with a line break, and must use the following syntax:

bc[javascript]. var a = 1; a += 1;
Copied!

Note, if multiple code blocks appear underneath each other with different languages, then a language selector will appear for the page. For example, the following Textile:

bc[javascript]. var a = 1; a += 1; // line break bc[ruby,nodejs]. a = 1 a += 1 // line break bc[csharp]. Integer a = 1; a += 1;
Copied!

generates the following where the code shown is governed by the language selected in the floating top nav

JavaScript
var a = 1; a += 1;
Copied!

Note that if you don’t include a full set of languages, or at least provide a default language, then a language selector will appear. In the example below, no language has been specified for javascript or nodejs. Select JavaScript in the top nav to see what happens when a language is not available.

Select...
# this is ruby
Copied!

As an alternative, you can use Github styled code blocks using triple backticks however the language(s) must be specified comma separated after the backticks in square brackets, for consistency with normal textile language blocks. The advantage of Github blocks over traditional Textile blocks is that line breaks are supported. Please note that lowest level indentation is stripped from the code.

```[javascript] var a = 1; a = 2; // note this works in spite of the line break ``` ```[ruby] a = 1 a = 2 ``` ```[csharp] int a = 1; a = 2; ```
Copied!

generates the following where the code shown is governed by the language selected in the floating top nav

JavaScript
var a = 1; a = 2; // note this works in spite of the line break
Copied!
 Tip

In order to publish code examples to JSBin, your /config/jsbin_config.yaml must be set up with a valid JSBin API key.

Code examples that run in your browser can be included in this documentation repo within the /content/code folder. Every code example must contain JavaScript, HTML and CSS that will be launched in our custom Ably JSBin.

The following example shows how you can easily add a “Try it” button to your code example that will launch the code from the path you provide in our Ably JSBin code editor:

bc[javascript]. var ably = new Ably.Realtime('<loading API key, please wait>');
Demo Only
Copied!

generates the following:

var ably = new Ably.Realtime('<loading API key, please wait>');
Demo Only
Copied!

Linking to code examples

If you want to link to a code example without using a code block, you can use ERB to embed the link and specify a class of external to ensure the link opens a new tab/window.

"Example":https://jsbin.ably.com:443/ekedis/latest_?javascript
Copied!

generates the following:

Example

In your code examples you can use handlebar like variables that are replaced with values at runtime. This is especially useful when you need to show examples that use a Token that may expire for example. When using the variables, please ensure that the case is matched exactly and that the variable is surrounded by single or double-quotes as CodeMirror colour coding can prevent the variables from being identified.

The following variables are supported:

  • {{API_KEY_NAME}}
  • {{API_KEY_SECRET}}
  • {{API_KEY}}
  • {{API_KEY_BASE64}}
  • {{APP_ID}}
  • {{TOKEN}}
  • {{TOKEN_BASE64}}
  • {{MS_SINCE_EPOCH}}
  • {{SECONDS_SINCE_EPOCH}}
  • {{RANDOM_CHANNEL_NAME}}
  • {{SIGNED_TOKEN_REQUEST_EXAMPLE}}

Example of the above variables being used in a code block below:

API_KEY_NAME: "{{API_KEY_NAME}}" API_KEY_NAME: "{{API_KEY_SECRET}}" API_KEY: "<loading API key, please wait>" API_KEY_BASE64: "{{API_KEY_BASE64}}" TOKEN: "{{TOKEN}}" TOKEN_BASE64: "{{TOKEN_BASE64}}" MS_SINCE_EPOCH: "{{MS_SINCE_EPOCH}}" SECONDS_SINCE_EPOCH: "{{SECONDS_SINCE_EPOCH}}" RANDOM_CHANNEL_NAME: "ray-map-ash"
Demo Only
Copied!
SIGNED_TOKEN_REQUEST_EXAMPLE: "{{SIGNED_TOKEN_REQUEST_EXAMPLE}}"

Certain pages have additional variable options.

In pages within the /compare folder, it’s possible to make use of the following variables:

  • {{COMPANY_0}}
  • {{COMPANY_1}}
  • {{COMPANY_URL_0}}
  • {{COMPANY_URL_1}}
  • {{COMPANY_ID_0}}
  • {{COMPANY_ID_1}}
  • {{PUBLISHED_DATE}}

The {{COMPANY_*}} variables make use of the correlated company listed in the metadata of the page to insert the relevant piece of information.

Examples of the above variables being used are:

First company name: {{COMPANY_0}} Second company's home page url: {{COMPANY_URL_1}} First Company's docs ID, as used in '/data/compare.yaml': {{COMPANY_ID_0}}
Copied!
The date this article was published: {{PUBLISHED_DATE}}

For both code blocks, if a single language code block appears without another contiguous language block before or after it, then it will always be shown regardless of the current language selected by the viewer. This is to ensure that should you wish to show a simple HTML block or a JavaScript code block with formatting for example, this can be done without worrying it will be hidden. For example:

bc[html]. <html> <body></body></html>
Copied!

Will always be visible as follows:

<html> <body></body></html>
Copied!

If you want to provide a non-formatted mono-spaced box with code, then use a pre. block instead without specifying a language. For example:

For example:

pre. this.code is('mono-spaced')
Copied!

will generate a box styled as follows:

this.code is('mono-spaced')

Within this documentation repository’s static site, all language specific content is wrapped in light dotted lines for clarity. However, when imported into the main Ably website, content will not be wrapped in dotted lines. Unlike code blocks, if you specify a single language specific block of content, it will only be shown if the language matches. Single language code blocks in contrast will appear regardless of which language is selected.

You can specify multiple languages per language specific content block such as <span lang="ruby,java">.

Whenever you need to vary the content based on the language selected by the user in the top language navigation, you have the following options available:

Whenever the front end detects multiple consecutive tag. markup with a language specified, the front end will automatically show the content related to the selected language, and hide all other languages. Note that the special language default can be used to provide default copy in the absence of any specific language variation existing. For example:

p[default]. Default text to appear for all languages not specified p[ruby]. Text to appear when Ruby is the chosen language
Copied!

Will result in:

Default text to appear for all languages not specified

When you need to vary large content blocks by language which can in turn contain any other HTML or Textile markup, you can use the custom blank textile markup with the lang attribute set within the square brackets. Indentation following the markup becomes significant and is used to indicate to the Textile parser that all text with indentation following the blang[lang]. markup is part of this large language block.

If a language block for the user’s currently selected language does not exist, nothing will be shown to the user.

blang[default]. p(#conditional-nav). This block will be shown by default and the nav will be visible This second line is considered part of the default block because it's still indented. blang[ruby]. This block will be shown when Ruby is selected and the conditional nav is not visible This second line is considered part of the Ruby block because it's still indented.
Copied!

Results in:

This block will be shown by default and the nav will be visible

This second line is considered part of the default block because it’s still indented.

Note that if any navigation item references an anchor that is no longer visible, it will be hidden in the navigation.

When you need to vary the content by language inline within a paragraph or another element, you can use span tags with the lang attribute set. If a language tag is missing, nothing will be shown. For example:

The language currently being viewed is: <span lang="javascript">javascript</span><span lang="ruby">ruby</span>
Copied!

Results in:

The language currently being viewed is: javascript

Here is another examples using an additional default language tag in the format <span lang="default"></span>:

The language of all is currently being viewed

When you need to vary the reference or definition of a method or object property by language, you can use h6 tags with the language defined on the next line as follows:

h6(#method-anchor-example). default: fooBar ruby: foo_bar
Copied!

will render as:

fooBar

Please refer to Definition lists below for instructions on how to specify a language for definitions and lists.

The supported languages are as follows:

language code
language name <% Ably::DOCUMENTATION_LANGUAGES.each do |lang_code, lang| %>
<=lang_code>
<=html_escape(lang[:name])> <% end %>

If you wish to add support for more languages, please refer to /lib/documentation_languages.rb

Definition lists are used frequently to list out parameters to methods, object properties or return values. They are prefixed and sufficed with a line break, and used as follows:

- value := description<br><em class="italics">Type: @[email protected]</em> - value 2 := _default description_ description<br><em class="italics">Type: @[email protected]</em>
Copied!

and renders as:

value
description
value 2
default description descriptionType: Type

Please note that:

  • The definition term (left hand part) is never code wrapped
  • Defaults are treated specially by placing _default description_ at the start of the definition description (right hand part)
  • As a convention, types are placed after the definition description (right hand part) using the format <br><em class="italics">Type: Type

Column headers for your definition lists can be specified on the first line by surrounding the definitions with an asterix. For example:

- *id heading* := *value heading* - id := description
Copied!

will render as:

id heading
value heading
id
description

Unfortunately as definition lists do not natively support specifying a language, a “hack” is used to make this work. The following example:

- value := definition - <div lang="ruby">ruby</div> := a Ruby specific definition - <div lang="default">default</div> := a generic definition - <div lang="ruby">ruby second</div> := a Ruby specific definition - <div lang="javascript">javascript second</div> := a JavaScript specific definition
Copied!

will render as:

value
definition
default
a generic definition
javascript second
a JavaScript specific definition

bc[lang] blocks cannot be used within definitions because they need to be surrounded by lines of white-space. Adding white-space would however terminate the definition list. As such, the following workaround can be used if you need to embed code in a definition:

- value := definition - another value := definition with code block <pre lang="json">@{ "name": "<event name>" }@</pre>
Copied!

will render as:

value
definition
another value
definition with code block
{ "name": "<event name>" }
Copied!

The pattern within API sections is to define a method with an h6 such as h6(#method). method, and then to define all method definitions (including any overloaded methods) with bq(definition).

bq(definition#anchor). default: send(message, options) javascript: send(message, options) java: void send(Message message, Options options)
Copied!

will render as:

send(message, options)

Inline Table of Contents are typically used at the start of a new section (such as API reference) to provide a form of navigation to the user. The Inline Table of Contents is also beneficial from a usability perspective as users can quickly get an overview of the content structure and scope. A custom textile tag has been created for this, inline-toc. An inline-toc tag can appear anywhere in a document as long as there is white space before it, the YAML within the tag appears directly after the tag, and the tag and YAML ends with white space. Here is example Textile markup:

inline-toc. Channel Object Reference: - Example: - Metadata // the anchor link #meta-data will be used automatically - Manually configured#code-blocks - Language Specific Content#language-specific-content - Conditional navigation shown when anchor is visible#conditional-nav
Copied!

The above code produces the following element:

Note that if you have referenced an anchor that has language specific content, the Table of Contents will automatically update to reflect the new content for that anchor whenever a language is selected, and ignore the text you have provided.

Although JavaScript is not a typed language, to avoid ambiguity, types are preferred before the argument name in method definitions, and the type should be linked to the type definition where available. As argument names are irrelevant when invoking a function (only the order matters), it is better to use a meaningful name in method definitions. Example:

new Ably.Realtime(ClientOptions clientOptions)

Callbacks and their method signatures should be included in code definitions. Where possible, instead of simply naming the function callback, a meaningful name should be used. Example:

subscribe(listener(Message message))

As Java is a typed language, types must be appear before variable name in method definitions, and the type should be linked to the type definition where available. The argument names should match the definition in the library. Example:

new io.ably.lib.AblyRealtime(ClientOptions clientOptions)

If the fully qualified name is too long to fit into the definition, and even more so within the navigation, then the unqualified class name can be used although it is preferable to mention the fully qualified namespace somewhere in the surrounding documentation. Example:

AblyRealtime(io.ably.lib.ClientOptions clientOptions)

Although Ruby is not a typed language, to avoid ambiguity, types are preferred before the argument name in method definitions, and the type should be linked to the type definition where available. As argument names are irrelevant when invoking a method (unless using Hash method options), it is advised to use a meaningful name in method definitions. Example:

Ably::Realtime.new(ClientOptions client_options)

If the fully qualified name is too long to fit into the definition, and even more so within the navigation, then the unqualified class name can be used although it is preferable to mention the fully qualified namespace somewhere in the surrounding documentation. Example:

Realtime.new(ClientOptions client_options)

Where methods yield blocks and/or return valueas, the following syntax is the standard:

EventMachine::Deferrable connect → yields Connection

If the block yields a number of variables and they need to be named for clarity, then the following is recommended:

foo → yields Object bacon, Object cheese

Sections of documentation are able to be minimized to help reduce the amount of content presented to developers reading the docs, whilst still allowing them to explore the detail where necessary. This is particularly useful for detailed code examples, for example. You can use this feature in one of two ways:

Click to see how to minimize by title
It is possible to create a minimizable section with the h[1-5](minimize=[Optional minimizable text]). line, with any following lines up to the next header being included in the minimizable section. If no optional minimize button text is typed, it will default to View More.
Click to see how to minimize by block
It is also possible to create a minimizable section with the minimize. [Optional minimizable text] line, with any following indented lines being included in the minimizable section. If no optional minimize button text is typed, it will default to View More.
 Tip

Tips can be shown using the markup p(tip).

Certain pages have styles and variables intended specifically for them.

Compare pages make use of the /data/compare.yaml file to automatically generate content. This yaml contains company information, and comparison points between all the companies organized under certain categories (i.e. Interoperability).

It’s possible to automatically generate a comparison table for any two companies, through the use of:

compare_table(CATEGORY, OPTIONAL_COLUMN_TITLE).

This will check if there are any comparible points between the the companies specified in the metadata of the pages, within the specified CATEGORY. If there are, a table will be generated to compare said points. The OPTIONAL_COLUMN_TITLE, if specified, will check if the category has an extras field, and if so will use that when creating the table as an additional column, using the title specified.

In order to build a stepped view mode of the tutorials, certain markup guidelines must be respected

  • Each step is marked by an h2 heading
  • Heading text will be used to create the TOC menu for navigation
  • You should assign identifiable ids to each tutorial step: otherwise a generated id will be created, but it’s name won’t be humanized
  • You can add additional piece of help at the end of a step busing the following custom block
Copied!
HelpboxTitleIf you need any extra help just ask <a href=”/example