My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
Usage  

Featured
Updated Aug 18, 2008 by fux...@gmail.com

Basic Terminology

Each page FFTempl generates is created from on its source file, template file and tag file.

Source files contain the actual dynamic content of the page. For example the text you are reading right now. Source files have the ".htm" extension and can be located anywhere on your website (even inside the "fftempl" directory!). Source files can also contain page-specific Lua scripts which are to be executed.

Template files define the basic rules of transforming the source files into something that almost resembles HTML. They use the ".tpl" extension and are located inside the "fftempl" directory. The template files usually define the pages' colors, fonts and other common elements like header and footer (but can also define anything else). Many different source files can use the same template file and there can be any number of different template files, each for different part of your site.

Tag files define your own (pseudo)HTML tags. Basically, it defines which sequences of characters should be replaced by other sequences of characters or by results of running your custom scripts. For example, you can define your own HTML tag called "{crazy_divider}" which will be replaced by "

<center>
- o - o - o - o - o -
</center>

" each time it appears in your source or template file. Tag files use the ".tag" extension and are all stored in the "fftempl" directory. As with template files, many different source files can use the same tag file and there can be any number of different tag files for different parts of your site.

You must understand the paragraphs above to be able to use FFTempl. Now, experiment a little bit with the links that are included at the bottom of all pages on my website. They allow you to see source, template and tag files of every page on fuxoft.cz. Try clicking on some of them, then come back here.

How it Works

OK, done with looking? You now probably have some basic idea how FFTempl works so we can have a detailed look:

If any document ending with ".htm" is requested, FFTempl loads the source file (of the same name) from the disk (again: The ".htm" files don't contain HTML code bude "pseudocode" which is used to generate the HTML the websurfer sees). The source consists of any number of parameters and each parameter begins with line containing its name, enclosed in double parentheses.

For example, if you look at the source file of this page (click "this source" at the very bottom of that page), you can see it consists of two parameters, whose names are "TITLE" and "BODY" (TITLE is 1 line long, "BODY" has many lines).

Parameters beginning with the underscore (_TEMPLATE, _EXTRATAGS, _CODE etc...) have special meaning for FFTempl. Other parameters can have any names you desire. It's true that "TITLE" and "BODY" can remind you of similarly named HTML tags but they could be called for example "XYZZY" and "FROTZ" - it's entirely up to you how you name your parameters (except the predefined names beginning with underscores)!

Some parameters can appear more than once in the source file. These are called "multiparameters" and will be explained later.

As a next step, FFTempl loads the relevant template file. The template file is usually "fftempl/default.tpl" but this can be overriden by including parameter called _TEMPLATE in the source file.

The template files look almost like a HTML page. What FFTempl does now is that it takes the template and replaces all occurences of string "((paramname))" with the contents of parameter called paramname (from the original ".htm" source file). If the template file contains parameter which does not exist in the source file, it's silently discarded from the result.

We now have something that resembles HTML page (let's call it "intermediate page") but we are not done yet.

Now we load the relevant tag file from the disk. As was the case with the template file, tag file can be defined by parameter named _TAGS but if it's not present, "default.tag" file is used.

The tag file consists of lines which have the following format:

tag := replacement

FFTempl now looks for all instances of each tag in the intermediate page and replaces each of them with the relevant replacement. Note that both tag and replacement can be anything at all and they don't have to be enclosed in parentheses. I used parentheses because they are easily accessed even when I am using the Czech keyboard. If you are working on U.S. keyboard you should probably use some less common delimiters like "" or "{}"... Or you don't have to use the delimiters at all and write something like StartOfBoldText, if you are bold. The choice is yours.

If the tag contains a dollar sign ("$"), this dollar sign matches any string in the intermediate file. If replacement also contains dollar signs, all of them are appropriately replaced by the string that was originally used in the intermediate file. I know it sounds confusing but it's really simple. For example, let's assume your tag file contains the following line, defining the {mailto} tag:

{mailto $} := <a href="mailto:$">$</a>

Then, if you include the following text anywhere in your source file (or template - it doesn't matter because it appears in the intermediate file in both cases):

My e-mail is {mailto satan@hell.sk}, write to me!

it gets automatically expanded to:

My e-mail is <a href="mailto:satan@hell.sk">satan@hell.sk</a>, write to me!

Note that the lines in ".tag" file are interpreted and replaced one by one, from top to bottom, and this order is very significant because it can be used for nested tags!

Maybe you also noticed that some lines in the .tag file contain ":=!" instead of ":=". In these cases, the right string is not replacement string but the name of the Lua function which is invoked to get the value used for replacement (this is advanced stuff and you need to understand Lua to use it).

Now think for a little while about the possibilities all of this gives to you. However, there is lots more that FFTempl can do for you!

Advanced Usage

If you want to create dynamic content like, for example, on this page, that shows my current age in days, you need to learn Lua. The reasons I rewrote FFTempl from Ruby to Lua were Lua's great speed, small footprint and the fact that Lua scripts are easily "hackable" and modifiable during the runtine which is very useful in FFTempl. (The page mentioned above also shows you the usage of special predefined source file parameters _EXTRATAGS and _CODE which allow you to easily embed ANY dynamic content into any FFTempl page.)

After you learn Lua (which is really very simple and elegant language), just look at the main two FFTempl files: "parser.cgi" and "fftempl.lua". They contain all the functionality of FFTempl in just a few kilobytes of Lua code and you can see what other mechanisms FFTempl allows. For example, what exactly happens if someone requests non-existent .htm page.

Also note the "custom.lua" file which gets automatically included during each FFTempl invocation and contains FFTempl modifications which should apply to all .htm pages on your site. The included "custom.lua" file is used on fuxoft.cz to create simple methods which you used to view the contents of source, template and tag files. Yes - this functionality is not hard-coded and you don't have to use the "custom.lua" file if you don't want to (you can modify it as you see fit or you can simply delete it).

Multiparameters

"Multiparameter" is a term for parameter that appears more than once in the source file. For example, the source file could contain the following (apart from other parameters):

((POST))
10/11/1957: I was born
((POST))
7/5/1979: I was run over by train
(and it hurt).
((POST))
2/9/1999: I died.

This is a multiparameter consisting of three items. Now, whenever "((POST))" appears in the template file, it will be replaced by all items of the relevant multiparameter. But there is one further nuance to make your life easier. Let's have an example. Let's say that your template file contains the following lines:

Here is my diary:
{p}ENTRY: {b}((POST)){/b}{/p}
{p}End of my diary.

Let's assume that your tag file defines {p} and {b} as some sort of "bold" and "new paragraph" tags. The trick is that FFTempl doesn't just blindly insert all three values one after another but duplicates the whole template line containing the "((POST))" string required number of times! Thus, the result will be:

Here is my diary:
{p}ENTRY: {b}10/11/1957: I was born{/b}{/p}
{p}ENTRY: {b}7/5/1979: I was run over by train
(and it hurt).{/b}{/p}
{p}ENTRY: {b}2/9/1999: I died.{/b}{/p}
{p}End of my diary.

Another thing to note is that if your template file contains reference to parameter which is not included in the source file at all, FFTemplate acts as if it was multiparameter with zero items, which - as shown above - is something slighty different from "empty string". In this case, the above example template would result in:

Here is my diary:
{p}End of my diary.

Notice there is not a single occurence of "ENTRY:", which is probably exactly what you wanted.

CODE and EXTRATAGS special parameters

Parameter ((_CODE)) allows you to include any Lua code which will be exectued when the page is parsed. It's normally used to define functions that will be used for generating special dynamic content on the page. The relevant tags for these functions have to be defined in the tag file using the ":=!" operator.

However, if you use some function just on a single page on your website, it's counter-productive to reference this function in the global tag file (and force FFTempl to seach for it on each page). That's where the ((_EXTRATAGS)) parameter comes in handy. During the parsing, all contents of this parameter are added at the beginning of the current tag file (of course, they are not actually added to the ".tag" file, FFTempl just "thinks" they are there). This allows you to use custom functions to generate not only HTML but also "pseudocode" which can be automatically further expanded using standard tag mechanisms. Note than when tag replacing takes place, it doesn't matter if tag is found in a section of page that originated from the source file or from the template file! It's replaced in any case.

However, CODE parameter can also be used for setting and changing hooks (explained in detail inside the "custom.lua" file) and doing whatever crazy stuff you can think of.

Double dash parameter masking

This scary name hides rather simple feature (added in January 2007). Whenever the web client asks fftempl for a page which is named foo--bar.htm (contains double dash), this name is automagically and transparently changed to foo.htm?_dash_argument=bar. What use is this? The easiest way to explain is to look at this example. You see dozens of links on that page, which seem to point to dozens of different static pages, each of which contains a comic strip. In fact, all strips are displayed using the same page, which is called "strip.htm". For example, the URL /redmeat/strip--zoo.jpg.htm is automatically expanded to /redmeat/strip.htm?_dash_argument=zoo.jpg. The "strip.htm" page just looks at what's in the variable args._dash_argument and displays the indicated image file.

(By the way, the "args" Lua table always contains all GET arguments of the current HTTP request available for your perusal.)

Are you still asking what's this good for? It allows your parametrized dynamic pages to look as if they were static pages. That means they can be better indexed by search engines, for example, or mirrored by download programs.

Note that the part before the (first) "--" is non-greedy, i.e. the URL /foo--bar--baz.htm gets replaced by /foo.htm?_dash_argument=bar--baz. Also note that you probably encounter horrible problems if your site contains any .htm files whose name contains "--" (that was the reason why I chose this rather unusual combination).

Persistence and speed

This is probably the right time to stress that FFTempl has no status persistence at all. In contrast with mod_php or mod_ruby, everything is invoked from scratch with each request and everything is garbage collected and forgotten after handling the request. I think this is good thing because you don't have to worry whether your tricks with custom.lua, hooks and _CODE changed the FFTempl functionality in some undesired way. If you screw something up, it will be automatically corrected during the next request.

The speed (all scripts have to be compiled from scratch for each request) also doesn't seem to be a problem even on our old server. However, to lower the system load under critical conditions, you could use luac to pre-compile "fftempl.lua" and "custom.lua" files (see Lua documentation).

The only drawback is the fact that lack of persistence prohibits you from having for example some global page visit counter. However, even this can be done in FFTempl - you just have to store the dynamic data somewhere on disk (beware of the right permissions).


Sign in to add a comment
Powered by Google Project Hosting