Miscellaneous
Page at point
If we need to render only the page at point, meaning the headline of
level 1 with ONE and CUSTOM_ID org properties set, we can use the
commands one-render-page-at-point and one-render-page-at-point-async.
onerc.el file
We can use an Emacs Lisp file called onerc.el to customize our
website. It must be in the same directory of the org file containing
the content of our website.
This file is loaded first in one-render-pages before rendering the
webpages.
This is a good place to set one-add-to-global and one-hook variables
or to define our own render functions.
one-add-to-global
Render functions takes 3 arguments:
page-tree: the parsed tree of the page being rendered,pages: the list of pages,global: a plist of global informations that are computed once inone-render-pagesbefore rendering the pages usingone-add-to-globalvariable.
That means that if a render function needs extra informations, we can
use one-add-to-global variable to pass those informations to the
render function.
Specifically, elements in one-add-to-global list are plist with the
following properties:
:one-global-property: a keyword that is used as proprety in theglobalargument passed to the render functions,:one-global-function: a function that takes two argumentspages(list of pages, seeone-list-pages) andtree(seeone-parse-buffer). That function is called once inone-render-pagesand its result is used as the value of the property:one-global-propertyin theglobalargument passed to the render functions.
For instance, if one-add-to-global is set to
((:one-global-property :one-tree
:one-global-function (lambda (pages tree) tree)))
then global local variable will be set to
((:one-tree tree))
where tree is the value returned by one-parse-buffer function.
one-hook
Each function in one-hook is called once in one-render-pages.
Those functions take three arguments:
pages: list of pages (seeone-list-pages),tree: seeone-parse-buffer,global: see one-add-to-global.
As those functions take global argument they are called after
that argument has been let binded using one-add-to-global.
feed.xml example
This hook is used to build feed.xml file of minibuffer.tonyaldon.com
website. You can check onerc.el file of
tonyaldon/minibuffer.tonyaldon.com repository to see how it is done.
robot.txt and sitemap.txt
If we want to add a sitemap.txt file to our website we can do so using
one-hook.
robot.txt
First we need to indicate in a robots.txt where our sitemap.txt is
located.
Assuming our website is https://example.com and our sitemap.txt file
is at the root of it, we can add the following robots.txt file in the
assets directory (./assets/robots.txt):
User-Agent: *
Allow: /
Sitemap: https://domain.com/sitemap.txt
sitemap.txt
Now in onerc.el file:
we set our domain with protocol in the variable
domain,then we define
make-sitemapfunction which will create the filesitemap.txtin thepublicdirectory (./public/sitemap.txt) each time be build our website,Finally, to tell
one.elto actually createsitemap.txtfile usingmake-sitemapfunction each time be build our website, we add it toone-hook:
(defvar domain "https://example.com"
"Domain with protocol to be used to produce sitemap file.
See `make-sitemap'.")
(defun make-sitemap (pages tree global)
"Produce file ./public/sitemap.txt
Global variable `domain' is used as domain with protocol.
This function is meant to be added to `one-hook'."
(with-temp-file "./public/sitemap.txt"
(insert
(mapconcat 'identity
(mapcar
(lambda (page)
(let* ((path (plist-get page :one-path))
(link (concat domain path)))
link))
pages)
"\n"))))
(add-hook 'one-hook 'make-sitemap)
Async commands
The function one-render-pages-async and one-build-async spawn an
emacs subprocess in order to build html pages asynchronously. The
arguments passed to emacs depends on one-emacs-cmd-line-args-async value.
By default, when one-emacs-cmd-line-args-async is nil, we run emacs
in "batch mode", we load the user's initialization file and we
evaluate a specific sexp that builds html pages. Specifically, we
pass the following command (emacs file name followed by command line
arguments) to make-process function like this:
(let* ((emacs (file-truename
(expand-file-name invocation-name invocation-directory)))
(command `(,emacs "--batch"
"-l" ,user-init-file
"--eval" ,sexp))
(sexp ...))
(make-process
:name ...
:buffer ...
:command command))
If one-emacs-cmd-line-args-async is non-nil, we no longer load the user's
initialization file and replace "-l" ,user-init-file in command above
by the elements of one-emacs-cmd-line-args-async. For instance, if
one-emacs-cmd-line-args-async is equal to
'("-l" "/path/to/some-elisp-file.el")
then command becomes
(let* (...
(command `(,emacs "--batch"
"-l" "/path/to/some-elisp-file.el"
"--eval" ,sexp))
...)
...)
Extend one-ox org backend
When we use the default render functions, the org content of the webpages is exported using one-ox org backend like this
(org-export-data-with-backend
(org-element-contents page-tree)
'one-ox nil)
where page-tree is the parsed tree of the headline containing the page
being rendered (see one-default render function).
While one-ox exports enough org elements for my use cases (see Why
one.el?) this might not be the case for you.
I think this is not a big problem because we can extend one-ox
(precisely we can derive a new org backend from one-ox org backend)
with other transcoder functions for the org elements that miss
transcoder functions.
Let's see how we can do that with an example.
Extend one-ox with horizontal-rule org elements
Lines consisting of only dashes (at least 5) are parsed by the org
parser as horizontal-rule org elements. one-ox doesn't provide a
transcoder function for horizontal-rule so we can't use it directly if
we want to have them exported as <hr> tags in our website.
In that section we see how to derived an org backend one-ox-with-hr
from one-ox org backend that exports horizontal-rule org elements
with <hr> tags.
To do that we define a transcoder function my-horizontal-rule which
takes 3 arguments (not used) and return the string "<hr>":
(defun my-horizontal-rule (_ _ _) "<hr>")
Then we use that function in the :translate-alist alist in the body of
the function org-export-define-derived-backend to define one-ox-with-hr
org backend:
(org-export-define-derived-backend 'one-ox-with-hr 'one-ox
:translate-alist
'((horizontal-rule . my-horizontal-rule)))
Then we can export the org content of the webpages (including the
horizontal-rule) using one-ox-with-hr org backend like this
(org-export-data-with-backend
(org-element-contents page-tree)
'one-ox-with-hr nil)
where page-tree is the parsed tree of the headline containing the page
being rendered.
Now that we saw how to derive one-ox-with-hr org backend and use it,
let's build a website with only a home page with two horizontal-rule.
In an empty directory let's add the following files:
one.org:◉ Home page properties :ONE: my-render-function :CUSTOM_ID: / ⋅ foo ----- bar ----- bazonerc.el:(defun my-horizontal-rule (_ _ _) "<hr>") (org-export-define-derived-backend 'one-ox-with-hr 'one :translate-alist '((horizontal-rule . my-horizontal-rule))) (defun my-render-function (page-tree pages _global) "" (let* ((title (org-element-property :raw-value page-tree)) (content (org-export-data-with-backend (org-element-contents page-tree) 'one-ox-with-hr nil))) (jack-html "<!DOCTYPE html>" `(:html (:head (:title ,title)) (:body (:h1 ,title) ,content)))))
Now while visiting one.org file we call one-build to build our website
with <hr> tags.