[[!meta title="one.el: the static site generator for Emacs Lisp Programmers"]] [[!meta copyright="Copyright © 2023 Tony Aldon"]] [[!inline pages="internal(2023/info/one-nav)" raw="yes"]] # one.el: the static site generator for Emacs Lisp Programmers Tony Aldon - [[!inline pages="internal(2023/info/one-before)" raw="yes"]] Have you ever wanted to write a blog: - contained in a unique org file, - rendered with only one Emacs command, - that can be modified by writing Emacs Lisp code (and CSS too), - with "html templates" that are plain Emacs Lisp data, - with no config file, - and no dependencies on external static site generators? If so, you might be interested in one.el package. In this talk, we'll look at how to get started with one.el and write a a simple blog as an example. What kind of static sites can be produced with one.el? I don't know but you can get an idea by checking those 3 websites built with one.el: - - - Below you can see the basics of a one.el website. In one.el, the following org file/buffer defines a website with 2 pages that we build by calling `one-build` command while we are visiting it: *** My website :PROPERTIES: :ONE: one-default-home :CUSTOM_ID: / :END: Welcome to my website! *** Blog post 1 :PROPERTIES: :ONE: one-default :CUSTOM_ID: /blog/page-1/ :END: My first blog post! The path ~/~ in the first ~CUSTOM_ID~ org property tells ~one.el~ that the page "My website" is the home page. That page is rendered using ~one-default-home~ render function, value of ~ONE~ org property of the same headline. The path ~/blog/page-1/~ in the second ~CUSTOM_ID~ org property tells ~one.el~ that we want to render "Blog post 1" page in such a way that when we serve our website locally at ~http://localhost:3000~ for instance, that page is served at ~http://localhost:3000/blog/page-1/~. How that page is rendered is determined by the value of ~ONE~ org property of the same headline which is ~one-default~, a render function. As you might have noticed, a ~one.el~ website is an org file where the pages are the headlines of level 1 with the org properties ~ONE~ and ~CUSTOM_ID~ set. Nothing more! ~ONE~ is the only org property added by ~one.el~. Its value (an Elisp function which returns an HTML string) for a given page determines how ~one.el~ renders that page. The paths of pages are set using ~CUSTOM_ID~ org property. That's it! note: I wanted to have a blog written in org-mode that I can modify only by evaluating some Emacs Lisp code. This is how one.el got started. Down that path I found that the Org parser and exporter do an amazing job, in fact 95 percent of the heavy work in one.el. I just had to find a way to pass org data to render functions and write an Emacs Lisp html generator package to be used by those render functions. I'm having a good user experience so far and I hope its design will fit your workflow. # Discussion ## Notes - Also provides a demo of Jack package () - Custom function for rendering by interogating the page-tree - Of use: grabbing metadata from the document/node - Easy menu and tab generation would also be great. - very cool indeed 👏 - thx for the nice presentation - Yeah, definitely a fun project that solves a problem to keep more Emacs and less external services. Static web sites are the best. :-D - I agree. I currently use Hugo, but I think this looks great! - I really like that `jack-html` is a separate project, as that looks nifty. - jack-html feels like a hiccup for elisp, nice - A very programatically solution! - I didn't watch the talk, but I use esxml to template pages that I generate from Org files: - Lisp backquotes are the best templating language :) - To be fair, pcase DSL is not easy to remember. [some discussion on IRC about pcase], recommendation of - I keep using elisp-demos with great success - adds examples to Help buffer - This looks like a nice setup. My blog is still using org-page, which was abandoned years ago. - org-page still works though - I know, I'm still using it. But it's finicky in a bunch of ways and I'd like a replacement static site generator. I don't really care if the code is elisp or not, as long as I can write in Org Mode and don't have to run Wordpress. - we have a bunch now.. ## Questions and answers - Q: does the "one" part of one.el refers to one source file? - Does one.el support #+include: to add from other (org) files? - Q: What's the main motivation for this new package? I used to use ox-hugo and use github action to build the blog.  (Curious as well, as I use ox-hugo and have almost 1000 pages) - A: Mapping from org-mode to Hugo added another system to understand; wanted Emacs centric approach.  ( has some rational) - understand. For me, it's just org-mode, ox-hugo take care of the rest. And I find it is easy for me. Maybe, I am not used it so much. Full control definiitely requires your package. - Q: Is it possible to use #+include to add content from other files? - A: Not included; the idea was to only have one file. It is possible to code what you want in elisp. - Perhaps org-transclusion would play with this? - Q: Can this generate a single site from different sources like blog.org (for example.org/blog/), videos.org (for example.org/videos/), contact.org (for example.org/contact/), etc? - A: Refer to the previous question's answer - Q:Do you have pre-made templates already along with the one.el package? - A:Yes and no. There are quite a few constructs/templates in the one.el code, you could perhaps use them to customize to get it to do what you want. - Q: What additional features are there that you would like to add to one.el in the future? - A: A full text search - (Comment not from presenter:) I've used Lunrjs which is a JS package that keeps all things local; but your site generator does need to kick out a JSON representation of the content (e.g. path, text, tags/keywords).  I've been considering - Q:Can you create navbars on a website and fancy things like carousels (pictures rolling/sliding from one to another) using one.el? - A:Sidebars, navbars are already part of the package. one.el also generates responsive. pages. pages argument used recursively can manage/mimic the carousel effect. - Q: Would there be an automated way to convert an existing HTML document into jack-html form? - A: - One challenge is that HTML documents do not need to be "precise" (you don't need to close tags).  So finding a tree-parser for HTML (perhaps treesitter?) to build the conceptual tree. - Q: Does this or you use any other Emacs Packages for your package/website ex org-publish. [[!inline pages="internal(2023/info/one-after)" raw="yes"]] [[!inline pages="internal(2023/info/one-nav)" raw="yes"]]