Introduction

FormatStack1 is a plugin for Movable Type that allows the composition of text formatters from formatters provided by other Movable Type plugins. If you have ever thought “it would be nice to use this format and that other one at the same time”, then you will find FormatStack useful.

Background and Overview

FormatStack requires

To understand FormatStack, we have to introduct a bit of terminology. We call any plugin capability to reformat, filter, modify, or alter text a text formatter. The base MT 4.2 release has two types of formatters, text filters and text modifiers2. Text filters are the formatting options you have when editing a post. Text modifiers can be accessed via attributes on template tags to perform formatting operations on the generated content of the tag. For brevity, we will omit the leading “text” and just refer to formatters, filters, and modifiers.

What FormatStack does is create new filters from existing formatters. These filters can then be used anywhere standard MT text filters can be, such as formatting for a post or comments. There are two main benefits to this

  1. It is no longer necessary to do custom coding in order to run multiple text filters on a post. For example, this was done with Markdown to create the “Markdown with Smart-Pants” filter. That is exactly the kind of thing that can be done with FormatStack without any code changes to the Markdown or Smart-Pants plugins. Other formatters need no longer modify the post text directly in order to function.
  2. Modifiers can be used to format posts, either by themselves, in groups, or in conjuction with filters. This means that new formatters, if provided as modifiers, can still be used as filters so an implementer does not need to worry about which to provide.

FormatStack came out of my need for exactly this kind of functionality for other plugins I had built. I wanted to use my plugin formatting and existing formatting. In addition, while I wanted to use the formatting for posts and comments, there were also places where it would be handy to use as a modifier. With FormatStack I just provide the formatting as modifiers and FormatStack handles all the other details. As far as I can tell, I am the only one who has ever found this useful, but it’s good practice to go through the motions as if it will be used by others. I am sure my future self with thank me for it.

Usage

Installation

  1. Get the distribution
  2. Copy the files under cgi-bin to your MT install directory, maintaining the nested directory structure.
  3. Copy the files under mt-static to your MT static directory, maintaining the nested directory structure.

Managing Format Stacks

The main page of FormatStack lists the existing formatters defined in FormatStack. Each formatted has a ‘tag’ and a ‘label’. The tag is a simple string consisting of only letters, numbers, and underscores, that identifies the formatter to Movable Type. All internal references (such as a from a post to a formatter) use this string and so it must be unique among all formatters both from FormatStack and any other plugin, filters or modifier3. The label is a string used for display in lists and menus. For instance, when editing a post, the label will be used in the list of available formats. There is no uniqueness requirement but confusion is likely to result from having duplicates. The label should identify the formatter for humans.

To create a formatter click the “New” button. This sends you to the formatter editing page. Here you enter a tag and label for the formatter, then select the component formatters. On the right is a block of formatters which are already available. This includes all filters and modifiers defined by any plugin. To use an existing formatter drag it from the block over to the “Component Formatters” list. Drag any other formatters desired, and use dragging to arrange them in the desired order.

Those formatters which are modifiers can (or must in some cases) have arguments which affect their behavior. To add an argument, click the pencil icon in the upper right of the formatter in the “Component Filter” list. If there is no such icon, the formatter is a text filter and doesn’t process arguments. Use the pencil icon to add the appropriate number of arguments. For each argument, fill in the text box with the text for the argument. Use the garbage can to remove an argument. You can remove a formatter by dragging it off the component list and dropping it anywhere else.

Click ‘Save’ to save your changes and return to the main page, ‘Cancel’ to return to the main page without saving, and ‘Apply’ to save and continue editing.

To edit an existing formatter, click on the icon on the far right of the table in the ‘Edit’ column. This will bring up the formatter editing page as for a new formatter. You can change the tag3 or label by editing the appropriate text boxes and change the component formatters and arguments.

Once a formatter is created, the label should appear anywhere you can select a format for stored text, including the ‘Edit Entry’ page and selecting formatting for comments.

Examples

Markdown with a signature

Suppose you wanted to use Markdown with an automatic signature. Create a formatter. Use the tag ‘markdown_with_signature’ and the label “Markdown With Signature”. Drag Markdown from the left to the formatter list. Then add the “cat” modifier. Add an argument to “cat” and put the signature in it. Click ‘Save’ to create the formatter.

Now you can edit a post, set the format to “Markdown with Signature”, and the post will be formatted with Markdown and then the signature appended. If you set that as the default format, then you get a signature all the time without further effort. A few key points are

  • The post is not modified internally, so if you change the argument to the ‘cat’ modifier and republish, the signatures will change. This can be a feature or a bug.
  • With multiple authors, each can define his own formatter which can have different signatures.

Use with Textile

Textile has the ability to use other text formatting. This is done with the notation ==|formatter|text== where formatter is the tag for the text formatter and text is the text to format. Any composite formatter created by FormatStack can be used. Because FormatStack can use any text modifier, you can combine a set of modifiers for a specific style of formatting and then use on just a section of text in an entry that is formatted with Textile. This provides both a simpler and more memorable single name to use (instead of a string of formatters) and lets you modify the formatting used globally by modifying the composite formatter and republishing.

My setup

I use three formatting plugins, WikiVar, Textile, and Webiki. This combination is the reason FormatStack exists. Because I set them in that order I can use WikiVar to generate output in Textile format. Webiki was written as a modifier instead of text filter so that I could use it (via FormatStack) for posts and also for widgets in the sidebar. Textile automatically includes Smarty-Pants if available, or I would add the latter to the composite formatter.

Temporary formatting

Suppose you wanted to be able to do different formatting on your posts in a temporary fashion, e.g. switch to pirate talk or add an extra tagline. To do this globally, you would initially set up a format stack containing just your normal text filter, e.g. if you normally used Textile you would set up a format stack “Normal” containing just Textile and use “Normal” to format your posts. Then, when you wanted something different, you would just edit the “Normal” format stack to add another formatter (say, “cat” with some text to add at the end). Republish and all of the posts are updated. When you get tired of that, just edit the format stack again and republish.

If you wanted to flip specific posts, then you could create a format stack with the different formatting and then changing any particular post consist of just going to the edit page for that post, changing the formatter, and saving.

Issues and future work

It would be nice if FormatStack could be told the minimum and maximum arguments counts for modifiers and then auto-create the minimum arguments and not allow more than the maximum. It would be straight forward, just some work.

It might be useful to be able to set a composite formatter to also be a modifier. This would require that the composite formatter accept arguments that can be redistributed to its component formatters. I would probably use the notation <$_n_$> to represent the nth argument passed to the composite formatter. This would then be entered in the arguments for the component formatters to pass the argument on to that component formatter. I would probably not force a composite formatter to choose; instead it could be both a filter and a modifier. I would need to check if it’s allowed to have the same tag for both (otherwise we would need a text field for filter and another for the modifier).

Would it be worthwhile to let the arguments be dragged? Or is it fine that they can be moved around via cut and paste? At some point the complexity becomes enough that one should just write a plugin.


1 Originally called “Filter Stack” but changing MT terminology made that a poor name choice.

2 Text modifiers were called “global filters” in earlier versions of Movable Type.

3 It should be noted that it is risky to change the tag for a formatter because any use of the formatter will be keyed to that string.