JSON Schema

We define the schema for federated wiki pages to the depth that we know it. We use a BNF-like notation to suggest JSON elements. Any ambiguity will be resolved by examining the example. We close with a brief reflection on the successes of the format.

A page is an object with three optional fields.

page = { title, story, journal }

A title is an ascii string in mixed case with spaces and punctuation. Wiki converts titles to slugs in hyphenated lower case.

title = "War and Peace"

A story is an array of paragraph-like items. The type identifies the plugin that can render the item.

Items have an id that is preserved through edits. Some precaution (aliasing) should ensure that ids are not duplicated within a page.

story = [ item ] item = { type, id, text, ... } type = "paragraph|image|factory|reference|..." id = "67b842ac89e61cc3" text = "The strongest of all warriors..."

While many items contain text of a type-specific markup, or DSL. Some items also add extra items, e.g. the data plugin adds `data` and `column` items, while the image plugin add a `url` and `caption`, and the map plugin adds items for `lat/lon`, tile server url and credits.

The journal contains a sequence of actions that creates the story. Actions are of a small number of types relating to editing actions.

The date and id identify when and where the action took place. The item as modified is copied in the action.

When site is present it means that the contents came from another site. The "fork" action means an entire page was copied from another site.

journal = [ action ] action = { type, id, date, item, site } type = "create|add|move|edit|remove|fork" id = "67b842ac89e61cc3" date = 1383278468000 site = "fed.wiki.org"

Example

Here we provide a complete example by creating a new page, adding a factory, and then double-clicking the factory to make a paragraph.

{ "title": "War and Peace", "story": [ { "type": "paragraph", "id": "08eaf0295b21d267", "text": "The strongest of all warriors..." } ], "journal": [ { "type": "create", "item": { "title": "War and Peace", "story": [] }, "date": 1383279726841 }, { "type": "add", "item": { "type": "factory", "id": "08eaf0295b21d267" }, "id": "08eaf0295b21d267", "date": 1383279861391 }, { "type": "edit", "item": { "type": "paragraph", "id": "08eaf0295b21d267", "text": "The strongest of all warriors..." }, "id": "08eaf0295b21d267", "date": 1383279872956 } ] }

The JSON of any page is available for viewing from a link at the bottom of each page. Refresh the web page if the JSON does not include recent change.

Some items will display their JSON when shift-double-clicked.

To see an action's JSON, click the action and then double-click the timestamp of the retrieved version.

Extensions

The item types name plugins that interpret the remainder of the json subtree for the item. One server (the origin server) provides all the plugins for the content being browsed in a single browser window.

It is possible that unexpected item types will be encountered. One can turn to the source site for the plugins it uses. These plugins will include documentation that describes where to find source code and support community for any new data format.

Plugins have the freedom to communicate with each other between pages in the browser. This has some analogies with unix commands connected with pipes. In both cases, small is beautiful.

Importers

The simplicity of the format and wiki's tolerance of omission makes writing foreign format importers easy. They've been written perl or even shell with no support from JSON libraries. The more complex importers use a nested DSL style of callbacks in script languages that favor that style. node ruby

The "create" action facilitates inserting whole pages from imports into the journal. Multiple runs of an importer can add multiple creates for comparing improvements to the import logic. It is also convenient to stash certification and provenience details in each create. I've included the git commit of the importer code.

Where an importer performs complex transformations, say from excel formulas to method plugin formulas, I've found it convenient to capture the source line numbers of the transformation code and include it in the method items. When numbers don't match a quick peek at the JSON (shift-double-click for methods) directs ongoing importer development.

See How To Import Documents

See also Coding Tips