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-pages
before rendering the pages usingone-add-to-global
variable.
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 theglobal
argument 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-pages
and its result is used as the value of the property:one-global-property
in theglobal
argument 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-sitemap
function which will create the filesitemap.txt
in thepublic
directory (./public/sitemap.txt
) each time be build our website,Finally, to tell
one.el
to actually createsitemap.txt
file usingmake-sitemap
function 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: / :END: foo ----- bar ----- baz
onerc.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.