As I have said about a zillion times already, when RubyFrontier processes a renderable page object, it will attempt to embed such an object into a template. I have already shown you a screen shot of the same page object passed through three different templates, to give you the general idea.
The template is usually how a Web page gets its overall appearance. A template can contain literal HTML as well as macro calls, and it usually contains both. In particular, it usually determines what goes in the document’s <head>
area (including its CSS) as well as common content such as unifying navigation to appear on multiple pages.
Thus, you need to know how the template is located and how this insertion is performed.
The template associated with any given renderable page object can either be a directive object or specified through a scalar directive.
If there is a scalar directive :directTemplate
, its value is taken to be the string that constitutes the template, and that’s the end of the search. (This is called a direct template.) This is to allow you to produce templates programatically. This would probably be a fairly advanced technique, and most RubyFrontier users wouldn’t use it. For example, you might produce the template in the page filter and stuff it into the page table as the value of the :directTemplate
directive.
If, as the page table is being built and RubyFrontier starts walking up the folder hierarchy from the page object being rendered, it encounters a file called #template.txt
, that’s the template (a directive object). (This is called an object template.)
It should not escape your attention that this fact immediately suggests a simple way of using the folder structure within your source folder as a way to group together page objects that share a common template. I have already made this point in a general way, but it is worth making again, explicity and with regard to templates specifically.
For example, suppose page A and page B look alike and are united by one kind of navigation, and page C and page D look alike and are united by a different kind of navigation. So you’d like A and B to share a template, and you’d like C and D to share a template. Then you might put A and B together with their template in a folder, and C and D together with their template in another folder, like this:
#template.txt
folder1
#template.txt
A
B
folder2
#template.txt
C
D
E
In the above schema, pages A
and B
will be handled by the #template.txt
that is together with them in folder1
, and pages C
and D
will be handled by the #template.txt
that is together with them in folder2
. In both cases, the top-level #template.txt
is overshadowed and ignored. The page object E
, on the other hand, will be handled by the top-level #template.txt
.
If the template is specified through the scalar directive :template
, and if its value is a Pathname, this Pathname is taken to be a file whose contents are the template. (This is called an address template.)
If the template is specified through the scalar directive :template
, and if its value is a String, this value is taken to be the simple string name of a .txt
file that is to function as the template. This file will be sought in the first #templates
folder discovered on the way up the hierarchy, or, if that search fails, in the user/templates
folder. Note that #templates
is not a “folded” directive; the usual approach is to have just one #templates
folder, at the top level of the site. (This is called a named template.)
So, for example, imagine in a text page object this line appears at the start:
#template "mytemplate"
This causes the directive :template
to be defined with the value "mytemplate"
, and so when the time comes to embed this page object in a template, a file mytemplate.txt
will be sought, first in the #templates
folder, then in the user/templates
folder.
The user/templates
folder includes by default two templates brought over from Frontier; their purpose will be discussed in a moment.
A template is a flexible beast, but certain features of templates are quite common, so here is a quick guide.
There must be a template. It is an error if there isn’t one.
The template should contain the pseudo-tag <bodytext>
. Alternatively, it can contain a <p>
tag whose id
is "bodytext"
, like this: <p id="bodytext"></p>
. (The regular expression by which this <p>
tag is located is rather crude, so try to imitate the example.) This is the point at which the page object will be substituted — that is to say, the page object, as rendered up to that point in the :bodytext
entry of the page table, will replace the tag. It is an error if no place to embed the page object is found.
Indeed, the minimum template would consist of only the pseudo-tag <bodytext>
. There are times when this strategy is useful, and so such a template is included in the user/templates
folder: it is called (for Frontier-related historical reasons) bbedit
. You would use this template if your page object itself consists of all the HTML required for your Web page, the use of the template being a superfluous (though necessary) formality.
The template should consist of, or should contain macros to generate, literal HTML. The typical strategy is to have the template generate, at least, all the HTML from the start of the page up to and including the <body>
tag, and, at the end of the page, the closing </body>
and </html>
tags.
And, again, this strategy is sufficiently common that such a template is included in the user/templates
folder: it is called (for Frontier-related historical reasons) white
. It goes like this:
<%= pageheader() %>
<bodytext>
<%= pagefooter() %>
To understand what that does, read up on the pageheader and pagefooter macros. That is also the default template when you create a new site in RubyFrontier, and it packs enough power that it should be sufficient for most purposes initially (as I’ve already mentioned).
A template (unless it is a direct template) may also contain scalar directives. As with a page object, these should be clumped together at the very start of the template. This is actually quite a useful mechanism because of the fact (made clear by the narrative of how a page gets rendered) that by the time the template’s directives are handled, the page object’s directives have been handled already; the one can thus depend upon the results of the other.
The reason a direct template is not processed for scalar directives is that it is assumed that, when you calculated the template and put it into the page table, at that moment you also put any desired scalar directive values directly in the page table.
This documentation prepared
by Matt Neuburg, phd = matt at tidbits dot com
(http://www.apeth.net/matt/),
using RubyFrontier.
Download RubyFrontier from
GitHub.