image

RubyFrontier Documentation

Stylesheets and JavaScript Files

As you know, an HTML page can link to one or more CSS stylesheets. Specifying what CSS stylesheets a page object should be linked to presents certain special challenges for RubyFrontier:

NOTE: These considerations apply equally to javascript files, which work almost exactly like stylesheets and are dealt with later on this page.

How to Specify Linked Stylesheets

In the face of all this, RubyFrontier must provide a mechanism that allows you, the programmer, to specify for each page object what stylesheet(s) it should link to, in a manner consistent with the structure of the hierarchy and directives. This is not something that the original Frontier handled terribly well. My solution is as follows:

The Stylesheets Themselves

The actual stylesheets are .css files in a #stylesheets folder. You can use as many #stylesheets folders as you like throughout your site; just keep in mind that stylesheets are gathered up the hierarchy as the page is rendered, so the page being rendered must be able to “see” a #stylesheets folder in order to use the stylesheets within it. And of course if there is a name conflict — that is, if there is more than one stylesheet with the same name in the #stylesheets folders found upwards through the hierarchy — it is the first such stylesheet encountered that will be designated by that name. This arrangement allows you to maintain multiple #stylesheets folders, each of which will become a folder in the rendered site. In the simplest and most common case, however, there will be just one #stylesheets folder, located at the top level of the site where all pages can see it.

TextMate is good at editing .css files, so maintaining your stylesheets should be no problem.

How Stylesheets Get Written to Disk and Linked

Late in the page rendering process, the page header is prefixed to the page. The page header will typically contain a call to the linkstylesheets() standard macro. This macro fetches the :linkstylesheets array from the page table and, for each element in turn, calls linkstylesheet() with that element as parameter. The result is that (1) the stylesheet itself is written out to disk, into a stylesheets folder at the top level of the site, and (2) a <link> tag is inserted into the page’s <head> region, linking to that stylesheet.

Thus, the order of the stylesheet names in the the :linkstylesheets array is the order in which the <link> tags are created. This solves the problem we set out to solve.

Alternative Approaches

The page header can call linkstylesheet() and supply a parameter value directly (a string representing the name of one stylesheet). The stylesheet is written to disk and a <link> tag to it is substituted for the macro call. (As already mentioned, a linkstylesheets() call is actually translated for you into a series of linkstylesheet() calls.)

Another alternative is that you might want to embed a stylesheet in the page itself. To do so, the page header can call embedstylesheet(). But this isn’t very flexible, so a more common approach is to set a scalar directive :embedstylesheet (whose value is the name of the stylesheet) at the start of the page object; if you do so, the linkstylesheets() standard macro in the page header calls embedstylesheet() for you.

Support for LESS and SASS

At some point, I discovered LESS, a more convenient way of writing and structuring CSS. I instantly added LESS support to RubyFrontier. This had to be done at the core RubyFrontier level because it affected two of the standard macros, linkstylesheet() and embedstylesheet().

However, the developer of LESS stopped supporting it as a Ruby gem and turned it into a JavaScript thing. So I had to change the nature of RubyFrontier’s support. Initially, as a replacement for LESS, RubyFrontier started supported SASS instead. This meant modifying linkstylesheet() and embedstylesheet() again. Clearly, this was not going to be a maintainable approach going forward.

Ultimately, therefore, I just threw up my hands and added a filter, cssFilter, which is used by the linkstylesheet() and embedstylesheet() macros. As with other filters, you are expected to put a file cssFilter.rb in the #filters folder; its top-level cssFilter method is called the way filters are normally called, namely with one parameter — the page table. At that moment, the page table contains a :csstext string entry consisting of the contents of the style sheet file now being processed by linkstylesheet() or embedstylesheet(); it’s up to you to modify this as desired.

So, for example, to run SASS against the stylesheet, you could say:

def cssFilter(adrPageTable)
  adrPageTable[:csstext] = Sass::Engine.new(adrPageTable[:csstext], 
    :syntax => :scss, :style => :expanded).render
end

In that example, running SASS is unconditional; if you wanted to make it conditional, of course, you could. For example you might introduce a directive and check its value. To help you, the page table contains a :sheetName string telling you the name of the stylesheet being processed.

To get you started, this approach to using SASS is illustrated both by the source for this documentation (RubyFrontier > Show RubyFrontier Docs Source) and by the new model site that you get when you create a new site (RubyFrontier > New Site).

JavaScript Files

JavaScript files are handled almost exactly like stylesheet files. So, the main points are precisely parallel to everything I’ve just said about stylesheets:

ERB Support

Both CSS and JavaScript files are passed through ERB as they are processed. Essentially, this means they are macro-processed, except that the snazzy name-resolution of full-fledged macro-processing is not present. But the current context is the PageMaker object, so its methods are available, and the page table is available (as adrPageTable). Moreover, if the stylesheet or JavaScript file is being linked to (as opposed to being embedded), its file URL within the Web site folder is available as adrPageTable[:sheetLoc].

The purpose of this feature (introduced in RubyFrontier 0.9.9.6) is to make it easier for a CSS or JavaScript file to link to an image file, or similar, via a relative URL. For a full example, see the page discussing images.

Next: Standard Macros and Other Convenience Methods

This documentation prepared by Matt Neuburg, phd = matt at tidbits dot com (http://www.apeth.net/matt/), using RubyFrontier.
Download RubyFrontier from GitHub.