Hyde logo

The evil nature of webmastering

A snapshot from the 1920 movie “Dr. Jekyll and Mr. Hyde”
A confrontation of good and evil.
Ruby JekyllHTML code correctness is entirely up to you.
(Lisp) HydePartial validation is provided, all without getting in your way.

Hyde only makes sure your HTML is syntactically valid, no semantic analysis is done. E.g. tag overlapping is not possible, because round brackets close tags and they are all the same:

(i "Hyde has " (b "killed") " — Jekyll!")

outputs

<i>Hyde has <b>killed</b> &mdash; Jekyll!</i>

There is no way to make up a string like this:

<i>Hyde has <b>killed</i> &mdash; Jekyll!</b>

other than printing it directly in HTML with Lisp, of course.

Note attribute names and values are not checked, so you can use any non-standard or custom attribute on any tag.

You are free to create your own HTML elements too. A Lisp macro called def-elem is provided to ease this task. E.g.:

(def-elem marquee :desc "Scroll text.")
 (marquee :direction "right" "The only way to get rid of a temptation is to yield to it.")

Of course browsers know nothing of elements you invent. They just ignore them, unless it is a non-standard extension to HTML a browser recognizes. If you want to make a custom element look and function right, you will have to hook up some CSS and Javascript too.

Tag nesting is not checked too. You still have to validate generated HTML pages against the W3C tools. Hyde does not even try to replace that.

External files inclusions in Hyde work at the element level. You cannot have the same element generated by two or more different files, that is you cannot break an element among two or more files. Of course inner text and other nested elements can be generated from different files, that is you can divide an element's content among different files, but not the element itself. This is not a limitation, rather it is good for you.

E.g. this means Jekyll does not allow you to have a start tag in a file and the corresponding eng tag in another file. Is that a good thing? Nope, if you look at both files singularly in your editor, their structure is not clear. Where does an element begins and where it does end? You have to open another file to see that! This can also be a source of layout bugs and bad HTML code, since you may forget to close a tag.

Ruby JekyllYou have to take care of XHTML compliance.
(Lisp) HydeFull XHTML compatibility is provided effortlessly with a uniform syntax.
E.g. (br) becomes <br /> instead of <br>, but (script :src "myscript.js") produces <script src="myscript.js"></script>. Hyde uses the same syntax for both void and empty elements, so that you do not have to think about it.
Ruby JekyllDisk space required for static assets is double, and copying or updating of many or big static files may be slow.
(Lisp) HydeThere is only one copy for each non-generated static file.

E.g. if a site has a lot of media files, Jekyll will make a copy of them inside _site, a separate sub-directory where your site is generated. Every time you update a file (e.g. think of a big movie file), Jekyll has to update the copy inside _site too. So in this case you loose both time and disk space and making your site will be slower. Of course, you could exclude these files from generation, but if you do so, you won't be ablet to test links to them from your HTML pages. Too bad!

With Hyde, you just add or update a single copy of each non-generated file and nothing else has to be done, because Hyde generates your site in the same directory it is served from. You can still publish the site via git or any other version control system. And if, for some reason, you do not want your source .lisp files to be uploaded, every self-respecting version control system, including git, provides a way to exclude certain file types.

Moreover Hyde just ignores all static assets (e.g. CSS, JavaScript files), while Jekyll foolishly processes them looking for a valid YAML front matter as they were .html files, unless you bother to exclude them one by one in the config file.

Hyde only processes .lisp files, resulting in much faster site build when there are a lot of static assets, which is typical of large static sites. I have never been in the need of generating an image, CSS or Javascript file statically, only HTML files, have you? Should I need that, I would use another ad-hoc program. But what's static is static. The reason why you use a site generator is to overcome HTML limitations, mainly complete lack of modularity. This is also a milder problem of JavaScript, but there are programmatic solutions to that, you do not need an external generator.

Ruby JekyllThe generator is an external program, not particularly easy to install and not really part of your site.
(Lisp) HydeEach Hyde installation is lighter than Jekyll, easier to setup on both Windows, Linux or both and is bundled-in with your site.

If something changes in new versions of Hyde that breaks compatibility, each site you develop with Hyde will still build, because it embodies and uses the same Hyde version with which it was made. You decide if and when to upgrade Hyde for each of your sites. By unpacking the Windows and Linux binary versions of Hyde in the same directory, you can even develop the same site on both OSs.

Ruby JekyllJekyll forces a layout on your site, you have to know and respect its conventions.
(Lisp) HydeHyde lets you free to organize your site's assets, layouts, includes (aka partial views), blog posts, etc. the way you see fit.

Templates, includes and layouts are all the same thing in Hyde. Indeed they are implemented using the same simple, uniform mechanism: an inc tag, the one missing from HTML, which you use simply like this: (inc "path/file.lisp").

You can always pair what you think should be paired. You are free to choose the names of your files and directories, create as many directory nesting levels and different conventions in each directory as you wish, in order to match your site logical structure.

The only conventions Hyde enforces on you are quite simple and reasonable. First, a .lisp file generates a .html file. Second, only two .lisp file names are reserved: in the document root of your site: hyde-dependencies.lisp is a file generated by Hyde to keep track of dependencies between your .lisp files (you should not edit it) and hyde-exclude-list.lisp is a file you can optionally create and keep up-to-date in any directory.

The latter contains a list of files and directory belonging to the current directory to exclude from the generation process.

That's all. Initially there are no such files, so you get a simple empty document root to start with, just as if you weren't using Hyde at all. No need for a Hyde-bootstrap program like the Jekyll-bootstrap.

Ruby JekyllJekyll forces you to learn another syntax and another template language, named Liquid, and different from HTML.
(Lisp) HydeHyde uses a simple uniform syntax for both data (mostly HTML, but also data structures defined by you) and code.

Hyde syntax is that of a powerful yet simple programming language: Lisp, which stands for LISt Processing. This syntax is just a simplification of the HTML syntax, so easier than HTML.

With Hyde you actually write HTML at the DOM level, the same format you can see when inspecting an element with a browser (e.g. with Mozilla Firebug, the Chrome or Opera Inspect Element feature, etc), but instead of tags, you use parentheses, which are easier to type and are matched or balanced automatically by any smart editor.

The wonderful thing is that you can embed any processing logic and code as it were data, using the same simple syntax, everything, including your processing logic, is like a tag, a function or markup if you prefer.

E.g. a very common webmastering task is to generate the main navigation menu of your site. You usually do not want it to contain a link to all the HTML pages in your document root, but only to the main ones. And as the link text, instead of the actual title of the page, you want something shorter.

In Hyde you can do this programmatically, using the powerful Common Lisp loop function, which is like a special tag for looping:

(defconstant +pages+
  '(("home" "Home") ("about" "About us") ("product" "Products")))
 ...
 (nav
  (loop for (name title) in +pages+ collect
   (a :href (cat name ".html")
    (if (equal name %selected%) '(:class "selected"))
    title
   )))

That way you have a central place where you define your menu, e.g. at the top of the include or layout file that generates it. You can also avoid defining the constant +pages+ and put the list of links inline, in place of its name, that is inside the loop, near the code the processes it.

To do exactly something like that in Jekyll is a pain in the ass, because of Liquid's limitations, and you have to restart Jekyll every time you want to add a new page. Here is another solution that does not force you to restart the Jekyll server, but unfortunately it is not very simple and forces you to group all pages in categories. This can be overkill for such a simple task of generating a custom main navigation menu for a simple site, so that in Jekyll you rather end up doing it in plain HTML, unrolling the loop with no code embedded.

So Liquid restricts what you are allowed to do, it is not a complete programming language and that limits its usefulness. To overcome these restrictions, you have to learn yet another language, that is Ruby and develop Jekyll's plugins using Ruby's, which means you cannot embed powerful script code simply along with HTML, because plugins are a separate thing.

To make things worse there are also other two minor markup languages in Jekyll, Markdown and Textile. IMO these lightweight HTML variants are misplaced here, where the main purpose is generating a static web site. Think about it: you are a webmaster and you already know HTML well and you probably need or will need some features that only HTML provides. So, why dabbling at other non-standard inferior markup languages? They can be useful in other contexts, but certainly not for generating full-fledged HTML sites.

In Hyde, you only need to learn Common Lisp, only one language for everything, including HTML, and more! That knowledge will give you full scripting ability, anyway it is still only needed for advanced Hyde usage. Most non-programmers will be able to apply and edit generic Common Lisp recipes like the one above, code simple conditional forms and loops without a full understanding of the language.

But if you want to learn Common Lisp and become a programmer too, everything you learn about it from other sources can be applied unmodified to Hyde. Moreover Common Lisp fully supports functional programming, which is simpler and safer than both procedural and object oriented programming techniques promoted by other languages.

Ruby JekyllOffers no easy way to capture repeated patterns in my HTML code.
(Lisp) HydeGives you the full power of Lisp functions and macros.

Another great advantage of working at the DOM level is that you can use functions and macros to modularize your HTML code. These are functions or custom tags you create that generate more complex HTML code. By using them, you type less, your HTML code becomes less boring, less error-prone, simpler and clearer.

E.g. handling footnotes and references is a bit of a chore both in standard and plain Hyde HTML, especially if you have a lot of them as in an online book. A footnote looks like:

<p id="fn1"><a href="#r1">[1]</a> ...footnote text...
 (p :id "fn1" (a :href "#r1" "[1]") " ...footnote text...") 
and a footnote link like:
<sup><a href="#fn1" id="r1">[1]</a></sup>
 (sup (a :href "#fn1" :id "r1" "[1]"))

Here is a couple of function to make your life easier. Note how easy is to turn Hyde HTML code into a parametric function to generate it: it is the same code wrapped into a function definition.

cat is a very useful feline, a function provided by Hyde that just concatenates its string arguments. While in Javascript you can write "fn" + number, in Lisp you cannot use the + operator for string concatenation, only for arithmetic addition. Syntax is different too. In Lisp everything is a parenthetical expression (a list!) where the operator is the first element and the arguments follow: (cat "fn" number)

;;; Make it easier to typeset a footnote.
 (defun fn (number &rest args)
  (p :id (cat "fn" number)
   (a :href (cat "#r" number) "[" number "]")
   " " args))

 ;;; ... and a footnote link!
 (defun fn-lnk (number)
  (cat
   (sup
    (a :href (cat "#fn" number) :id (cat "r" number) "[" number "]"))
   " "))

These definitions can be put at the top of your Lisp file or, if you want to use them in multiple files, in a Lisp library file whose name is added to hyde-exclude-list.lisp. You can load this file using the same include-tag you use for loading HTML includes, you just ignore its return value, since it does not return anything, only defines a few useful functions: (inc "util.lisp"). Please do not use the Lisp standard load form, because it does not track dependencies between source files. Example usage:

(p "In each of us," (fn-lnk 1) "two natures are at war — the good and the evil.")
 ...
 (fn 1 "First slide of the 1920 silent film “Dr. Jekyll and Mr. Hyde”, starring John Barrymore.")