one-default render function
In How does one.el work? page we saw that render functions are at
the heart of one.el
mechanism. They determine how pages are
rendered.
We saw that
(defun hello-world (page-tree pages global)
"<h1>Hello world!</h1>")
defines a valid render function that can be used to render pages of a
one.el
website by setting ONE
org property to hello-world
like this
for instance:
* The home page
:PROPERTIES:
:ONE: hello-world
:CUSTOM_ID: /
:END:
* Blog post 1
:PROPERTIES:
:ONE: hello-world
:CUSTOM_ID: /blog/page-1/
:END:
one.el
comes with several default render functions that can be used
instead of the dummy hello-world
function:
one-default-home
: org content,one-default-home-list-pages
: org content followed by the list in reverse order of the pages of the website,one-default
: org content with navigation buttons at the bottom to go to the previous page, the next page or a random one,one-default-with-toc
: same asone-default
but with a table of content at the top of the page andone-default-with-sidebar
: same asone-default
but with a sidebar listing all the pages in the website,one-default-doc
: same asone-default-with-sidebar
but with a table of content at the top of the page.
Those default render functions use one-ox custom org export backend and
one-default-css
custom CSS style sheet.
If we want to start a new project using these defaults, we can use
one-default-new-project
command (see Getting started).
If you plan to write your own render functions you may find the following sections interesting.
The org document
Let's consider the following org document in a file named one.org
for
instance:
* Home
:PROPERTIES:
:ONE: one-default-home
:CUSTOM_ID: /
:END:
* Page 1
:PROPERTIES:
:ONE: one-default
:CUSTOM_ID: /blog/page-1/
:END:
** Headline foo 1
[[#/blog/page-2/][Link to Page 2]]
** Headline foo 2
*** Headline bar
Some content.
*** Headline baz
:PROPERTIES:
:CUSTOM_ID: /blog/page-1/#baz
:END:
#+BEGIN_SRC emacs-lisp
(message "foo bar baz")
#+END_SRC
* Page 2
:PROPERTIES:
:ONE: one-default
:CUSTOM_ID: /blog/page-2/
:END:
[[#/blog/page-1/#baz][Link to Headline baz in Page 1]]
Let's generate the file ./assets/one.css
that contains the content of
one-default-css
string by calling one-default-add-css-file
command.
Our project structure is now:
.
├── assets
│ └── one.css
└── one.org
Build the website
Now, while vising the file one.org
we call one-build
which builds
"Home", "Page 1" and "Page 2" pages under the directory ./public/
such
that our project tree is now:
.
├── assets
│ └── one.css
├── one.org
└── public
├── blog
│ ├── page-1
│ │ └── index.html
│ └── page-2
│ └── index.html
├── index.html
└── one.css
Home
The page "Home" has been generated:
in the file
./public/index.html
respecting the path information/
inCUSTOM_ID
org property andits HTML content has been created using
one-default-home
render function specified inONE
org property.
./public/index.html
(pretty printed for the demonstration):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" type="text/css" href="/one.css" />
<title>Home</title>
</head>
<body>
<div class="header">Home</div>
<div class="content">
<div id="home"><div></div></div>
</div>
</body>
</html>
Page 1
The page "Page 1" has been generated:
in the file
./public/blog/page-1/index.html
respecting the path information/blog/page-1/
inCUSTOM_ID
org property andits HTML content has been created using
one-default
render function specified inONE
org property.
./public/blog/page-1/index.html
(pretty printed for the demonstration):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" type="text/css" href="/one.css" />
<title>Page 1</title>
</head>
<body>
<div class="header"><a href="/">Home</a></div>
<div class="content">
<div class="title">
<div class="title"><h1>Page 1</h1></div>
</div>
<div></div>
<div>
<h2 id="one-df8f0f16cc">Headline foo 1</h2>
<div>
<p><a href="/blog/page-2/">Link to Page 2</a></p>
</div>
</div>
<div>
<h2 id="one-9c2f3b8536">Headline foo 2</h2>
<div>
<h3 id="one-fe469dd578">Headline bar</h3>
<div><p>Some content.</p></div>
</div>
<div>
<h3 id="baz">Headline baz</h3>
<div>
<pre><code class="one-hl one-hl-block">(message <span class="one-hl-string">"foo bar baz"</span>)</code></pre>
</div>
</div>
</div>
<div class="nav">
<a href="/">PREV</a><a href="/">RANDOM</a
><a href="/blog/page-2/">NEXT</a>
</div>
</div>
</body>
</html>
Page 2
The page "Page 2" has been generated:
in the file
./public/blog/page-2/index.html
respecting the path information/blog/page-2/
inCUSTOM_ID
org property andits HTML content has been created using
one-default
render function specified inONE
org property.
./public/blog/page-2/index.html
(pretty printed for the demonstration):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" type="text/css" href="/one.css" />
<title>Page 2</title>
</head>
<body>
<div class="header"><a href="/">Home</a></div>
<div class="content">
<div class="title">
<div class="title"><h1>Page 2</h1></div>
</div>
<div>
<p><a href="/blog/page-1/#baz">Link to Headline baz in Page 1</a></p>
</div>
<div class="nav">
<a href="/blog/page-1/">PREV</a><a href="/">RANDOM</a>
</div>
</div>
</body>
</html>
How was "Page 1" built?
When we called one-build
in one.org
buffer, the whole buffer was
parsed with the function one-parse-buffer
and a list of pages was
built from that parsed tree and looked like this:
((:one-title "Home"
:one-path "/"
:one-render-page-function one-default-home
:one-page-tree (headline (:raw-value "Home" ...) ...))
(:one-title "Page 1"
:one-path "/blog/page-1/"
:one-render-page-function one-default
:one-page-tree (headline (:raw-value "Page 1" ...) ...))
(:one-title "Page 2"
:one-path "/blog/page-2/"
:one-render-page-function one-default
:one-page-tree (headline (:raw-value "Page 2" ...) ...)))
Let's call pages
that list of pages.
Then for each page
in pages
the function one-render-page
was called
with page
, pages
and global
(see one-add-to-global
variable) as
arguments.
Finally, in one-render-page
the function one-default
or
one-default-home
was called with the arguments page-tree
, pages
and
global
to create the HTML content of each page whom path under the
directory ./public/
was determined by the value of :one-path
property
in page
and page-tree
was the value of :one-page-tree
property in
page
.
Focusing on "Page 1", the function one-default
was called with the
arguments page-tree
, page
and global
with page-tree
being the
following parsed tree of the headline defining "Page 1":
(headline
(:raw-value "Page 1"
:CUSTOM_ID "/blog/page-1/"
:ONE "one-default"
:parent (org-data ...)
:one-internal-id "one-9c81c230b6"
...)
(section (...) (property-drawer ...))
(headline
(:raw-value "Headline foo 1"
:one-internal-id "one-4df8d962d9"
...)
(section (...) (paragraph ...)))
(headline
(:raw-value "Headline foo 2"
:one-internal-id "one-9d89da8271"
...)
(headline
(:raw-value "Headline bar"
:one-internal-id "one-95fa001487"
...)
(section
(...)
(paragraph (...) #("Some content. " 0 14 (:parent #4)))))
(headline
(:raw-value "Headline baz"
:CUSTOM_ID "/blog/page-1/#baz"
:one-internal-id "baz"
...)
(section
(...)
(property-drawer ...)
(src-block
(:language "emacs-lisp"
:value "(message \"foo bar baz\")"
...))))))
In one-default
the org content of "Page 1" was exported into a HTML
string using org-export-data-with-backend
and one-ox custom org export
backend. Then this HTML string was used in a data structure
representing the HTML page. Finally, jack-html
(see jack) transformed
that data structure into a HTML string which was written on the file
./public/blog/page-1/index.html
:
(defun one-default (page-tree pages _global)
"Default render function.
See `one-is-page', `one-render-pages' and `one-default-css'."
(let* ((title (org-element-property :raw-value page-tree))
(path (org-element-property :CUSTOM_ID page-tree))
(content (org-export-data-with-backend
(org-element-contents page-tree)
'one-ox nil))
(website-name (one-default-website-name pages))
(nav (one-default-nav path pages)))
(jack-html
"<!DOCTYPE html>"
`(:html
(:head
(:meta (@ :name "viewport" :content "width=device-width,initial-scale=1"))
(:link (@ :rel "stylesheet" :type "text/css" :href "/one.css"))
(:title ,title))
(:body
(:div.header (:a (@ :href "/") ,website-name))
(:div.content
(:div.title
,(if (not (string= path "/"))
`(:div.title (:h1 ,title))
'(:div.title-empty)))
,content
,nav))))))