iri: iri resource includer
TL;DR The iri resource includer is available on Github for free and licensed under the GNU General Public License 3.0.
When I was reorganizing my website, I wanted to make it more static and remove the dependency on JavaScript to load a article. The site have never had a dynamic backend, primary to keep the complexity down - but also to make it really easy to move from one server to another.
Before to avoid having a dynamic backend, when a user visited a url like https://citroner.blog/article/test/, the index.html in that folder contained a script that took the filepath /article/test/ and redirected the browser to the root path with that path appended as a fragment https://citroner.blog/#/article/test/. The index.html in the root then run another script that took that fragment and loaded /article/test/article.html in that html shell. It was a bit of a hack but it worked. However it required JavaScript and was not that cache friendly.
That made me look around for static html build system. Some sounded promising like Hugo or Jekyll, but really what I was looking for was something like a static version of Server Side Includes. A simple, build-system agnostic include tool that is easy to integrate in a project. I didn't really find any so I set out to create one.
Basics
iri is a file includer that work by processing a base document with include directives and then letting you separately supply what files to include in a particular run. Considering these files:
charlie@laptop:~/project/site$ ls
document.html content.htmlContaining following markup, noting that document.html contains a html comment <!-- include content.html -->:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>My website</title>
</head>
<body>
<!-- include content.html -->
</body>
</html><article>
<p>This is my content.</p>
</article>Iri reads a base document from standard input and writes the result to standard output, by using shell redirection a file from disk can be used for input. The user have to specify the media type for the base document as the program will look for include directives as comments in the document. By running the following command:
charlie@laptop:~/project/site$ iri --media-type text/html --include content.html <document.html >index.html
Every instance of <!-- include content.html --> in the document will be replaced by the content of content.html, with the result outputed into the file index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>My website</title>
</head>
<body>
<article>
<p>This is my content.</p>
</article>
</body>
</html>Of course it's possible to have multiple includes to the same file or includes of different files. As long as they are specified on the command-line and have the same name as in the include directives. Please use your shell's shell expansion to make includes easier, for example --include *.html.
Multiple runs, different includes
By having the user specify the path to the files to include every run, instead of having a absolute path in the include directive, it is possible to generate different documents. This is particular of use for me, as my website's structure consists of a shell that is the same on every page except for the article content.
charlie@laptop:~/project/site$ tree
.
├── article-1
│ └── content.html
├── article-2
│ └── content.html
└── shell.html
3 directories, 3 filesIn this directory structure above, I have a shell document (identical to the document.html in previous figure), and two directories each containing the content of a article. By running iri two times each time specifying a different directory we incorporate the content of the articles in the shell document.
$ iri --media-type text/html --include article-1/*.html <shell.html >article-1/index.html
$ iri --media-type text/html --include article-2/*.html <shell.html >article-2/index.html
$ tree
.
├── article-1
│ ├── content.html
│ └── index.html
├── article-2
│ ├── content.html
│ └── index.html
└── shell.html
3 directories, 5 filesThe directive
The syntax for the include directive is that of a comment native to the media type. For text/html and text/xml that is <!-- include 'filename' -->, for text/css and text/javascript it is /* include 'filename' */. The use of native comments helps reading and editing the file in all types of editors, without them screaming about syntax errors.
As of now the directive only has one type of action include, which inserts the content of a file. Maybe it would be interesting to allow some command facility, but that opens up a jar of worms for exploits. Instead, maybe I will add some variables the directive can query, like the current time or date. Time will tell.
Practical usage info
The command-line arguments is by design quite terse, so iri is best paired with a build tool, for example make.
If an error occurs the program will print a message to standard error and return not zero. As the command continuously parses the input it may midthru stop if a directive tries to include a file that is not supplied. It is therefore inportant to check the return value before using the output.
Compile and install
iri can be compiled from source and is hosted on Github, licensed under the GNU General Public License 3.0. Required tools are a C++26 compiler (makefile uses gcc), git and make. The repository contains a git submodule as the project uses one of my other projects, the C++ library common_good.