Bluephrase Templating

Create web page templates using enclosures

by Joe Honton

The use of templates to create web documents is a time-tested strategy. Templates provide authors with the consistency and variability needed to fashion a set of documents into a cohesive website. The BLUEPHRASE language has declarative templating features that are well-suited to this job.

We consider BLUEPHRASE to be declarative because it doesn't have functional or procedural syntax. But the language is not static: it has variables, which can be used to turn generic templates into specific documents.

Let's examine the three language statements that allow us to turn textual content into server-ready HTML.

  • The !include pragma — this is used to inject the contents of a secondary file into the document being compiled.
  • The !enclosure pragma — this wraps the contents of the compiled document with the outer contents of a template file.
  • The !use pragma — this parses the contents of an external file, but instead of injecting its contents, it keeps any declared variables in memory for use by the compiled document.

Source files and secondary files for these three pragmas follow BLUEPHRASE syntax rules. When compiled, the result is an HTML file ready to be served over HTTP. This type of language compilation is sometimes called server-side rendering.

A classic web page layout

Anyone familiar with WordPress and its knockoffs will recognize the familiar include mechanism. It grabs the inner text of the referenced file and inserts it into the calling document at that point.

Consider a classic mom-and-pop website, with just a handful of static pages. Its standard page layout might be composed of masthead, menu, and footer. These would be included into the main contents of the page to form the full document body.

For simplicity, we can leave to our imaginations what the inner text of the three included files might be. The important lesson is what the include syntax looks like and how it's used within the body of the document.

Let's look at the content.blue file, which contains the author's story wrapped with masthead, menu and footer. It would be written using BLUEPHRASE notation something like this:

body {
div {
!include `masthead.blue`
}
menu {
!include `menu.blue`
}
div #textblock {
h1 Our Story
p Tangled Web Services is a professional design firm for ...
}
footer {
!include `footer.blue`
}
}

A fully formed web page

As it now stands, the compiled output for our mom-and-pop page is not quite ready to be sent over HTTP to the browser. It's missing the all important <head> with the specification of the document's <title>, <meta> and <link> tags.

Furthermore, many developers will opt to put any dynamic scripts that need to be executed at the bottom of the document. Thus, building on the first example, a more fully formed web page would follow this schematic:

With those additions above and below the document's <body>, the page is browser-ready. For illustrative purposes, a bare bones example of the std-head.blue file might look like this:

head {
title $TITLE
meta *charset=UTF-8
meta *name=viewport *content='width=device-width, initial-scale=1'
meta *name=description *content='$DESCRIPTION'
meta *name=keywords *content='$KEYWORDS'
script `/js/our-story.js` *type=text/javascript
link `/css/our-story.css` *type=text/css *rel=stylesheet
link `/fonts/our-sans.woff2` *as=font *crossorigin
}

The enclosure approach

Using include pragmas is an easy way for beginners to approach the problem. But for websites that have more than just a few pages, this approach quickly becomes untenable because each page needs to duplicate the same structural pattern. Besides being repetitious, it also prevents the developer from pursuing future structural solutions with a different arrangement of masthead, menu, and footer.

This is where enclosures come in. The idea is to turn the include mechanism inside-out. In effect, the author's content is enclosed by the template document.

Semantically, we consider enclosures to be triggered rather than included. The rules are straightforward:

  1. The template file contains free form text, using BLUEPHRASE notation.
  2. Somewhere within the template file its creator specifies the insertion point for documents being enclosed. This is done by placing a !target-matter pragma at the desired point.
  3. The document containing the author's story specifies the template's filename using the !enclosure pragma.
  4. The author chooses a selector to be used as a triggering mechanism. Selectors may be element IDs, CSS classnames, or HTML element tagnames.

Conceptually, the above schematic looks similar to our working example, but in terms of code, the difference is significant. Here's what the document is reduced to:

!enclosure #textblock `std-page.blue`

div #textblock {
h1 Our Story
p Tangled Web Services is a professional design firm for ...
}

Everything else is moved into the std-page.blue file, which becomes the template for all of the website's documents. Future changes to the layout are now centralized.

html {    
!include `std-head.blue`
body {
!include `masthead.blue`
!include `menu.blue`

!target-matter

!include `footer.blue`
!include `std-script.blue`
}
}

Using variables

Careful readers will have noticed that the std-page.blue file has three variables: TITLE, DESCRIPTION, and KEYWORDS. These are arbitrary names chosen by the template creator. The intent is that authors will declare values for each of these, for each page they create, so that the compiler can use them when the template is triggered.

For the working example, we would place these declarations near the beginning of the content.blue file:

$TITLE="Our Story"    
$DESCRIPTION="Tangled Web Services is a professional design firm for ..."
$KEYWORDS="web services, professional design"

Declaring variables this way, within the document itself, is an acceptable practice for many types of websites. An alternative approach is to create a separate variables-only file for each document. This approach is useful when building pages such as a table of contents, or hashtag listings, or month-by-month blog posts.

When a file only contains variable declarations, the use pragma can be invoked instead of the include pragma. This will instruct the compiler not to inject any text into the document, but to keep any variable declarations it encounters in memory for subsequent use by the document. The author of content.blue would add this statement to the document:

!use `vars.blue`

Review

  • The BLUEPHRASE language is well suited to creating web pages using templates and variables.
  • Three pragmas provide the basis for templates: include, enclosure and use.
  • Variables provide the means to turn any BLUEPHRASE file into a template.

Bluephrase Templating — Create web page templates using enclosures

🔎