Informl has an extension mechanism so developers can extend the functionality of the wiki. There's a general mark-up for extensions and a convention for how to package up the code for implementing the extension. There are a number of examples of using extensions in the demo site.

Mark-up

There are two ways of marking up an extension: wrapper and attribute addition.

Wrapper

The wrapper mark-up for using an extension looks like:

<<extension_name param1, param2, ... >>

or

<<extension_name param1, param2, ... >>
optional  
text  
block
<</extension_name>>

In both wrapper forms, we assume that whatever the parameter, if it's a reference to a value, field or page the general form described in the referencing page should be used. The parameters are in YAML inline (very similar to JSON), and can include numbers, strings, arrays and hashes.

In the second form, an optional text block will be passed to the extension. The format is similar to an HTML beginning and end tag but with double less-than, << and greater-than, >>, symbols.

Attribute Addition

The general HTML attribute addition mark-up can be used to transform text using an extension. You do this by adding the do="<extension name>" args="<extension arguments>" attributes to a block. This might look something like this:

I have the following important points: *[:point:] *{: do="iterate" }.

Built-in extensions

date, float, integer

These simple extensions are used to create fields whose corresponding database column will be of the appropriate type.

birthdate:: <<date>>

This will cause this column to be added to the schema for the page:

t.column "birthday", :date

count, sum, average, maximum, minimum

These operate either on a page (count) or field (the others). The set of entries to be used can be selected using a filter.

<<count (year=2007)orders>>
<<sum (year=2007)cost::orders>>

succinct_result, full_result

succinct_result creates a barebones recap of an entry to a form, giving each field and its value. full_result re-renders the entire page with each form element replaced by the appropriate value. These are intended to be used in :result pages.

table

table creates a sortable table for all or some of the entries on a page. The set (and ordering) of the fields to be included can be provided, and defaults to all of the user defined fields (and not things like id or created_at). Examples:

<<table>>
<<table (report=[:id:])Expense, [date, amount, item]>>

table is used in the default :summary page, and can also be quite useful in other pages as well.

refers_to

refers_to is for creating a field that refers to entries in another page (for programmers, these are foreign keys). If you want the user of a form to select an entry from another page, this is what you use.

report:: <<refers_to activity::Expense Report>>

In this example, there will be a field in the current page called report. Each entry in the report field will identify a particular expense report. For its user interface, refers_to creates a selection field populated with the values of the specified field from the other page. So in the example above, the options the user will have will be all of the values that have been provided to the activity field on the Expense Report page.

Note: For this to work properly, the Expense Report page must already exist at the time that this referring page is created. If this is not the case you would need to go and create the Expense Report page, then come back to this page and re-save it. Otherwise Informl is unable to establish the correct foreign key reference that relates the two pages.

iterate

[We are planning to make some changes to the way iterate works in the future.]

iterate is used for bringing data from other pages into the current page. iterate is provided with a text block that acts as a template, a template that is rendered for each matching entry from the specified page.

For example,

<<iterate (year=1998 & wine_type=Red)wines::wine>>
* [:name:], _[:name.winery:]_
<</iterate>>

becomes a bullet list of all of the red wines from 1998 in the database table associated with the wines page in the wine book. For each matching wine, the name of the wine and the name of the winery that produced the wine are given. The winery names are italicized (note the _ underscore characters).

If you wanted to create a table and iterate over the rows of the table but also put a header on the table you could use the following markup (using the attribute addtion markup):

[! Name |! Description |]
[| [:name:] || [:description:] |] {: do="iterate" }

This applies an iteration to the row of the table for every entry in context.

See the page on referencing for more details on iterate and scoping.

Other extensions

These extensions are provided as examples.

  • selects_from

  • google_map_picker, google_map_summary

Programming extensions

TBD

Future work

In a span case, the text block can be delimited by a closing function tag:

My first paragrah <<my_func>> and more text.
My paragraph <<my_func>>some text passed to func<</my_func>> and more text.
powered by tartan and informl from folklogic