# 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 as `one-default` but with a table of content at the top of the page and

- `one-default-with-sidebar`: same as `one-default` but with a sidebar listing all the pages in the website,

- `one-default-doc`: same as `one-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 `/` in `CUSTOM_ID` org property and

- its HTML content has been created using `one-default-home` render function specified in `ONE` 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/` in `CUSTOM_ID` org property and

- its HTML content has been created using `one-default` render function specified in `ONE` 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/` in `CUSTOM_ID` org property and

- its HTML content has been created using `one-default` render function specified in `ONE` 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))))))