# 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 in `one-render-pages` before rendering the pages using `one-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 the `global` argument passed to the render functions,

- `:one-global-function`: a function that takes two arguments `pages` (list of pages, see `one-list-pages`) and `tree` (see `one-parse-buffer`). That function is called once in `one-render-pages` and its result is used as the value of the property `:one-global-property` in the `global` 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 (see `one-list-pages`),

- `tree`: see `one-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:

1. we set our domain with protocol in the variable `domain`,

2. then we define `make-sitemap` function which will create the file `sitemap.txt` in the `public` directory (`./public/sitemap.txt`) each time be build our website,

3. Finally, to tell `one.el` to actually create `sitemap.txt` file using `make-sitemap` function each time be build our website, we add it to `one-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)

Thanks @tanrax for the code snippet (see issue #6).

## 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.