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-defaultbut with a table of content at the top of the page andone-default-with-sidebar: same asone-defaultbut with a sidebar listing all the pages in the website,one-default-doc: same asone-default-with-sidebarbut 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.htmlrespecting the path information/inCUSTOM_IDorg property andits HTML content has been created using
one-default-homerender function specified inONEorg 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.htmlrespecting the path information/blog/page-1/inCUSTOM_IDorg property andits HTML content has been created using
one-defaultrender function specified inONEorg 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.htmlrespecting the path information/blog/page-2/inCUSTOM_IDorg property andits HTML content has been created using
one-defaultrender function specified inONEorg 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))))))