Schalk Neethling

Scripting on Caffiene

Html-compiler - Add Includes Support to Your HTML

| Comments

I am currently working on the new Mozilla style guide. There is an existing one but, it being part of the larger mozilla.org site, is not ideal, and makes it overly complicated for designers and UX people to contribute. It also makes sense to have this live in it's own little pod, where it can be the source of truth for others inside, and outside Mozilla.

The problem

We have a few.

Just extracting this from the mozilla.org codebase is not enough. We need to ensure that running the style guide locally is as easy as possible, requires as few dependencies as possible and, when the time comes, it is easy to deploy.

We also don't want contributors to have to learn a new template language if we can avoid it, preferring to stick as closely to pure HTML and CSS. So of I went in search of a solution.

I initially looked at some Python based solutions such as Django and Flask but, while both are valid options, they are simply more than we need. All we really need is a static site but, we want to avoid the tons of inevitable duplication as the site grows and, we definitely do not want to create a maintenance nightmare when say, a menu item needs to be added.

So, simply building the site as a, everything built by hand, static HTML site is not an option. If only HTML had includes support. Well, there is of course Jekyll. This however means having to install Ruby, Ruby Gems, and preferably, creating a virtual environment to run everything in. If you are already using Ruby, then this might just work, but in our case I felt like there has got to be something even "lighter".

A little earlier in this post I hinted at the fact that, if only pure HTML had support for includes, we would be golden but alas, it does not. There is a template element in the works but, even if it was supported it is still not exactly what we need. What we need is a pre-processor that uses directives and produces plain HTML. HTML with directives goes in, and plain HTML comes out.

With that in mind, html-compiler was born.

The solution

html-compiler is a simple Nodejs based command line utility that processes your HTML, take certain actions based on directives you include in your code, and writes out the result to a destination you specify.

To use html-compiler, go to your command line and, in the project you wish to use it, type the following(of course you will need to have Nodejs installed, if you do not, get the installer here):

1
npm install html-compiler --save-dev

Once this completes, html-compiler should be available via the command line. Let's process some HTML then.

What’s that about directives?

Directives is how you tell html-compiler what to do. Currently there are three supported directives.

#html-include=file

With the above directive you tell html-compiler that you want it to load the contents of the file you specify and replace the directive with the contents of the file, for example:

1
2
<body>
    #html-include=/includes/header.html

Let's say the header.html contains the following:

1
2
3
<header>
    <h1>Site name</h1>
</header>

When the processing is complete, the result will be:

1
2
3
4
<body>
    <header>
        <h1>Site name</h1>
    </header>

#html-include-link=destination

One of the main things you will probably use the above directive for, is to include files such as your site navigation. This will work, until the navigation is included inside a nested page. Depending on how you serve your site, you might run into a problem where relatively referencing a URL does not work.

Because you know the final URL from which your site will be served, we can absolutely link these but, having to type that in for each link you add can become tedious, html-compiler also has the #html-include-link directive. This directive works in tandem with a parameter you will pass on the command line when calling html-compiler(more about that a little later). For example:

1
2
3
4
<nav>
    <ul>
        <li><a href="#html-include-link=/page/file.html">My page</a></li>
        ...

Say for example you passed the URL https://www.mysite.com on the command line, the processed content will be:

1
2
3
4
<nav>
    <ul>
        <li><a href="https://www.mysite.com/page/file.html">My page</a></li>
        ...

#html-include-asset=asset

Technically you could use the above directive for this as well, I decided to include support for an additional directive #html-include-asset to include, you guessed it, assets. For example:

1
<img src="#html-include-asset=/path/to/file.png" alt="description" />

Again, suppose you specified https://www.mysite.com via the command line, the result will be:

1
<img src="https://www.mysite.com/path/to/file.png" alt="description" />

That covers the currently supported directives, let’s move onto how you use the command.

Using html-compiler

html-compiler uses four command line arguments, two which are optional:

  • --rootFolder
  • ---preserveRoot
  • --siteRoot
  • --dest

The --dest parameter is optional, and defaults to dist. This, as the name suggest, is the destination directory where the processed files will be written to. The other optional parameter is --preserveRoot. When writing your files to the destination directory, the original root folder is preserved.

In other words, if your files to be processed are contained inside a folder called site, and you specify the --preserveRoot option, the resulting folder structure will be something like:

dist
  -- site
  ...

If you do not specify it, it’a a boolean parameter so excluding it will equal false, the contents of the site folder will be written directly to dist.

General usage of the command will thus be:

1
html-compiler --rootFolder=foldertoprocess --siteRoot=https://www.mysite.com

As you can see from the above, you specify the folder containing the HTML to be processed using the --rootFolder parameter. The above will result in all of the files inside foldertoprocess being processed, and the result will be written to the dist folder, prepending any links or assets specified using the #html-include-link or #html-include-asset with https://www.mysite.com

If you wish to preserve your root folder and also specify a different destination folder, you would call the command as follows:

1
html-compiler --rootFolder=foldertoprocess --siteRoot=https://www.mysite.com --dest=public --preserveRoot

I would love to know your thoughts on html-compiler and how you solved the same or similar problems. Until next time.

Comments