* one.el
:PROPERTIES:
:ONE: one-default-with-sidebar
:CUSTOM_ID: /
:END:
** Static Site Generator for Emacs Lisp programmers

[[youtube:GGP2mxZn4mY]]

Have you ever wanted to write a blog:

- contained in a unique org file,
- rendered with only one Emacs command,
- that can be modified by writing Emacs Lisp code (and CSS too),
- with "html templates" that are plain Emacs Lisp data,
- with no config file,
- and no dependencies on external static site generators?

If so, you might be interested in ~one.el~ a simple *Static Site
Generator* for *Emacs Lisp* programmers and *org-mode* users.

To get started right away check [[#/docs/install-one-el/][Install one.el]] and [[#/docs/getting-started/][Getting started]]
pages.

You can find the code here: https://github.com/tonyaldon/one.el.

Athough ~one.el~ uses org-mode not all the org elements are useful to
build technical blog sites (see [[#/#why][Why one.el?]]).  So only a few org
elements have an transcoder function implemented in [[#/docs/one-ox/][one-ox]], the org
backend used by ~one.el~ to build the default website (see [[#/docs/one-default-render-function/][one-default
render function]]).  Please check [[#/docs/one-ox/#org-elements-not-supported][Org elements not supported]] before
relying on ~one.el~.

In ~one.el~, the following org document defines a website with 3 pages
that we build by calling ~one-build~ command while we are visiting it:

#+BEGIN_SRC org
,* My website
:PROPERTIES:
:ONE: one-default-home
:CUSTOM_ID: /
:END:

Welcome to my website!

,* Blog post 1
:PROPERTIES:
:ONE: one-default
:CUSTOM_ID: /blog/page-1/
:END:

My first blog post!

,* Blog post 2
:PROPERTIES:
:ONE: one-default
:CUSTOM_ID: /blog/page-2/
:END:

My second blog post!
#+END_SRC

Note that if we want to use the default css style sheet we can add it
by calling ~one-default-add-css-file~ before building the website.

The path ~/~ in the first ~CUSTOM_ID~ org property tells ~one.el~ that the
page "My website" is the home page.  That page is rendered using
~one-default-home~ render function, value of ~ONE~ org property of the
same headline.

The path ~/blog/page-1/~ in the second ~CUSTOM_ID~ org property tells
~one.el~ that we want to render "Blog post 1" page in such a way
that when we serve our website locally at ~http://localhost:3000~ for
instance, that page is served at ~http://localhost:3000/blog/page-1/~.
How that page is rendered is determined by the value of ~ONE~ org
property of the same headline which is ~one-default~, a render
function.

The same goes for the last page "Blog post 2".

As you might have noticed, a ~one.el~ website is an org file where the
pages are the headlines of level 1 with the org properties ~ONE~ and
~CUSTOM_ID~ set.  Nothing more!

~ONE~ is the only org property added by ~one.el~.  Its value, an Emacs Lisp
function which returns an HTML string, for a given page determines how
~one.el~ renders that page.

Paths of pages are set using ~CUSTOM_ID~ org property.

With that said, if you want to try it you can check [[#/docs/install-one-el/][Install one.el]] and
[[#/docs/getting-started/][Getting started]] pages.

** Why one.el?
:PROPERTIES:
:CUSTOM_ID: /#why
:END:

I wrote ~one.el~ because I didn't find an existing static site generator
with the following requirements:

- I'm not looking for a solution for every type of websites, only for
  technical blog sites which are basically chunks of code surrounded
  by text,
- I want something simple that I understand and that I can modify
  only by writting some Emacs Lisp,
- I want websites to be written to a single org file,
- I want something with no dependencies other than emacs packages
  that are not bridges to feed other static site frameworks,
- I want something with no configuration options, if you want to
  modify something you write Emacs Lisp code and
- Finally, I want an Emacs solution for an Emacs user.

Following those requirements led me to ~one.el~, an opiniated static
site generator for Emacs Lisp programmers and Org mode users that
works well if you want to build websites like

- [[https://minibuffer.tonyaldon.com][minibuffer]] ([[https://github.com/tonyaldon/minibuffer.tonyaldon.com][source]]): learn Emacs Lisp one sexp at a time,
- [[https://posts.tonyaldon.com][Elisp posts]]: some articles about Emacs Lisp,
- [[https://jack.tonyaldon.com][jack]]: HTML generator library for Emacs Lisp,
- [[https://one.tonyaldon.com][one.el]]: documentation of one.el package,
- [[https://lnroom.live][LNROOM]]: learn how to hack on Core Lightning and
- https://tonyaldon.com.

all built with ~one.el~.

* Install one.el
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/install-one-el/
:END:
** Manually

~one.el~ depends on [[https://jack.tonyaldon.com/][jack]] and [[https://github.com/hniksic/emacs-htmlize][htmlize]] packages that are available on
[[https://melpa.org/][Melpa]].  Once you have them installed you can add ~one.el~ to your
~load-path~ and require it like this:

#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path "/path/to/one.el/")
(require 'one)
#+END_SRC

** With package-install

~one.el~ is also available on [[https://melpa.org/][Melpa]] so you can install it like this:

#+BEGIN_SRC text
M-x package-install <RET> one <RET>
#+END_SRC

** With straight.el

If you're using [[https://github.com/radian-software/straight.el][straight.el]], to install ~one.el~ you just have to add
this sexp to your init file:

#+BEGIN_SRC emacs-lisp
(straight-use-package
 '(one :type git :host github :repo "tonyaldon/one.el"
       :build (:not compile)))
#+END_SRC

Note that ~:build (:not compile)~ is important.  It tells ~straight.el~
not to byte compile ~one.el~.  Something happened in ~straight.el~
between commits ~3eca39d~ and ~b3760f5~ which broke byte compilation of
~one.el~ if done by ~straight.el~.

** Let's go

Now you can create a new website by calling ~one-default-new-project~
(preferably in an empty directory) and you can build it by calling
~one-build~ command.

If this is the first time you try ~one.el~ reading [[#/docs/getting-started/][Getting started]]
page might be helpful.

* Getting started
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/getting-started/
:END:
** Start a new project

By calling ~one-default-new-project~ command (preferably in an empty
directory) we produce a new ~one.el~ project with the following
structure:

#+BEGIN_SRC text
.
├── assets
│   └── one.css
└── one.org
#+END_SRC

Once done we can build the website under the directory ~./public/~
by calling ~one-build~ command while we are in the file ~one.org~.  Our
project's structure is now:

#+BEGIN_SRC text
.
├── assets
│   └── one.css
├── one.org
└── public
    ├── blog
    │   ├── default
    │   │   └── index.html
    │   ├── default-home-list-pages
    │   │   └── index.html
    │   ├── one-default-doc
    │   │   └── index.html
    │   ├── one-default-with-sidebar
    │   │   └── index.html
    │   └── one-default-with-toc
    │       └── index.html
    ├── index.html
    └── one.css
#+END_SRC

** Modify the content with live reloading

To get our website up and running, we serve the files in ~./public/~
subdirectory using [[https://browsersync.io][brower-sync]] (any webserver serving files is OK).
Once we have it installed, to start a webserver with live reloading,
we run the following commands (in a terminal):

#+BEGIN_SRC text
$ cd public
$ browser-sync start -s -w --files "*"
#+END_SRC

Assuming the port ~3000~ isn't used we have our website served at
~http://localhost:3000~.

Now we can modify the content of ~one.org~ file and see the changes
reflected in the browser after we rebuild/re-render the whole website
or part of it using the following commands ~one-build~, ~one-render-pages~
and ~one-render-page-at-point~ or the asynchronous version of those
commands ~one-build-async~, ~one-render-pages-async~ and
~one-render-page-at-point-async~.

** CSS style sheet

When we call ~one-build~ (or ~one-build-async~) command the pages of the
website are rendered in the directory ~./public/~ and the files in
~./assets/~ directory are copied into ~./public/~ subdirectory.

When we build a ~one.el~ website with the default render functions and
the default CSS style sheet (this is the case if we used
~one-default-new-project~ as we did above) the style sheet that applies
is ~./public/one.css~ file which is a copy of ~./assets/one.css~ file.

So in that case, to modify the website's layout we just have to modify
the file ~./assets/one.css~ and copy it in ~./public/~ directory either
with ~one-build~, ~one-build-async~ or ~one-copy-assets-to-public~.

*** Modify the CSS style sheet with live reloading

To get the file ~./assets/one.css~ copied into ~./public/~ directory each
time we modify it we can use [[https://eradman.com/entrproject/][entr]] utility like this (being at the root
of our project):

#+BEGIN_SRC text
$ ls assets/one.css | entr -s 'cp assets/one.css public/'
#+END_SRC

Combined with ~browser-sync~ live reloading I think we get a decent
programmer experience.

*** Source blocks

When we use the default render functions and the default CSS style
sheet, the org content is exported into HTML strings using ~one-ox~ org
export backend.  Consequently, ~src-block~ elements are highlighted
using [[https://github.com/hniksic/emacs-htmlize][htmlize]].

See [[#/docs/one-ox-src-block/][one-ox | src-block]] for more information.

* How does one.el work?
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/how-does-one-el-work/
:END:

In an org file containing all the pages of our website we can build
the website under ~./public/~ subdirectory by calling either ~one-build~
or ~one-render-pages~ commands.

The only difference between those two commands is that before
producing the HTML pages calling ~one-render-pages~, ~one-build~ command
cleans the subdirectory ~./public/~ and copies the content of ~./assets/~
subdirectory into ~./public/~ subdirectory.

So let's focus on ~one-render-pages~ command.

For each page of our website, the function ~one-render-pages~ uses
the render function set in ~ONE~ org property of the page to produce the
HTML string representing the page and stores it in an ~index.html~ file
whom path is determined by ~CUSTOM_ID~ org property of the page.

Render functions are at the heart of ~one.el~ mechanism.  They
determined how pages are rendered.  Specifically, render functions are
regular Elisp functions that takes 3 arguments

- ~page-tree~: corresponding to the parsed tree of the org entry defining
  the page,
- ~pages~: the list of pages,
- ~global~: a plist of global informations that are computed once
  in ~one-render-pages~ (see ~one-add-to-global~) before rendering the
  pages

and return HTML strings.

For instance, the following ~hello-world~ function

#+BEGIN_SRC emacs-lisp
(defun hello-world (page-tree pages global)
      "<h1>Hello world!</h1>")
#+END_SRC

defines a valid render function.  We can use it to build a website
like this.  In an empty directory, we create a file named ~one.org~ with
the following content:

#+BEGIN_SRC org
,* The home page
:PROPERTIES:
:ONE: hello-world
:CUSTOM_ID: /
:END:
,* Blog post 1
:PROPERTIES:
:ONE: hello-world
:CUSTOM_ID: /blog/page-1/
:END:
#+END_SRC

We visit that file and call ~one-build~ command.  It produces the
following files

#+BEGIN_SRC text
.
├── one.org (already there)
└── public
    ├── blog
    │   └── page-1
    │       └── index.html
    └── index.html
#+END_SRC

and both files ~./public/blog/page-1/index.html~ and
~./public/index.html~ have the same content:

#+BEGIN_SRC html
<h1>Hello world!</h1>
#+END_SRC

Therefore if we serve the website in ~./public/~ directory at
~http://localhost:3000~ we can access the two "Hello world!" pages
at ~http://localhost:3000/blog/page-1/~ and ~http://localhost:3000~.

That's it!  This is how ~one.el~ works under the hood.

~one.el~ comes with predefined render functions, a custom CSS style
sheet and a custom [[#/docs/one-ox/][org export backend]] which are used all together to
build that documentation for instance.

See [[#/docs/getting-started/][Getting started]] to start a new project with those defaults.

See [[#/docs/one-default-render-function/][one-default render function]] to take inspiration and write your own
render functions.

* one-default render function
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-default-render-function/
:END:

In [[#/docs/how-does-one-el-work/][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

#+BEGIN_SRC emacs-lisp
(defun hello-world (page-tree pages global)
      "<h1>Hello world!</h1>")
#+END_SRC

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:

#+BEGIN_SRC org
,* The home page
:PROPERTIES:
:ONE: hello-world
:CUSTOM_ID: /
:END:
,* Blog post 1
:PROPERTIES:
:ONE: hello-world
:CUSTOM_ID: /blog/page-1/
:END:
#+END_SRC

~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 [[#/docs/one-ox/][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 [[#/docs/getting-started/][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:

#+BEGIN_SRC org
,* 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]]

#+END_SRC

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:

#+BEGIN_SRC text
.
├── assets
│   └── one.css
└── one.org
#+END_SRC

*** 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:

#+BEGIN_SRC text
.
├── assets
│   └── one.css
├── one.org
└── public
    ├── blog
    │   ├── page-1
    │   │   └── index.html
    │   └── page-2
    │       └── index.html
    ├── index.html
    └── one.css
#+END_SRC

*** 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):

#+BEGIN_SRC 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>Home</title>
  </head>
  <body>
    <div class="header">Home</div>
    <div class="content">
      <div id="home"><div></div></div>
    </div>
  </body>
</html>
#+END_SRC

*** 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):

#+BEGIN_SRC 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>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>
#+END_SRC

*** 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):

#+BEGIN_SRC 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>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>
#+END_SRC

*** 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:

#+BEGIN_SRC emacs-lisp
((: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" ...) ...)))
#+END_SRC

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":

#+BEGIN_SRC emacs-lisp
(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\")"
      ...))))))
#+END_SRC

In ~one-default~ the org content of "Page 1" was exported into a HTML
string using ~org-export-data-with-backend~ and [[#/docs/one-ox/][one-ox]] custom org export
backend.  Then this HTML string was used in a data structure
representing the HTML page.  Finally, ~jack-html~ (see [[https://jack.tonyaldon.com/][jack]]) transformed
that data structure into a HTML string which was written on the file
~./public/blog/page-1/index.html~:

#+BEGIN_SRC emacs-lisp
(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))))))
#+END_SRC

* Miscellaneous
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/miscellaneous/
:END:
** 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
:PROPERTIES:
:CUSTOM_ID: /docs/miscellaneous/#one-add-to-global
:END:

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

#+BEGIN_SRC emacs-lisp
((:one-global-property :one-tree
  :one-global-function (lambda (pages tree) tree)))
#+END_SRC

then ~global~ local variable will be set to

#+BEGIN_SRC emacs-lisp
((:one-tree tree))
#+END_SRC

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 [[#/docs/miscellaneous/#one-add-to-global][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 [[https://minibuffer.tonyaldon.com][minibuffer.tonyaldon.com]]
website.  You can check ~onerc.el~ file of
[[https://github.com/tonyaldon/minibuffer.tonyaldon.com][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~):

#+BEGIN_SRC text
User-Agent: *
Allow: /
Sitemap: https://domain.com/sitemap.txt
#+END_SRC

**** 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~:

#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC

Thanks [[https://github.com/tanrax][@tanrax]] for the code snippet (see [[https://github.com/tonyaldon/one.el/issues/6][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:

#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC

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

#+BEGIN_SRC emacs-lisp
'("-l" "/path/to/some-elisp-file.el")
#+END_SRC

then ~command~ becomes

#+BEGIN_SRC emacs-lisp
(let* (...
       (command `(,emacs "--batch"
                         "-l" "/path/to/some-elisp-file.el"
                         "--eval" ,sexp))
       ...)
  ...)
#+END_SRC

** Extend one-ox org backend
:PROPERTIES:
:CUSTOM_ID: /docs/miscellaneous/#extend-one-ox-org-backend
:END:

When we use the default render functions, the org content of the
webpages is exported using [[#/docs/one-ox/][one-ox]] org backend like this

#+BEGIN_SRC emacs-lisp
(org-export-data-with-backend
 (org-element-contents page-tree)
 'one-ox nil)
#+END_SRC

where ~page-tree~ is the parsed tree of the headline containing the page
being rendered (see [[#/docs/one-default-render-function/][one-default render function]]).

While ~one-ox~ exports enough org elements for my use cases (see [[#/#why][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>"~:

#+BEGIN_SRC emacs-lisp
(defun my-horizontal-rule (_ _ _) "<hr>")
#+END_SRC

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:

#+BEGIN_SRC emacs-lisp
(org-export-define-derived-backend 'one-ox-with-hr 'one-ox
  :translate-alist
  '((horizontal-rule . my-horizontal-rule)))
#+END_SRC

Then we can export the org content of the webpages (including the
~horizontal-rule~) using ~one-ox-with-hr~ org backend like this

#+BEGIN_SRC emacs-lisp
(org-export-data-with-backend
 (org-element-contents page-tree)
 'one-ox-with-hr nil)
#+END_SRC

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~:

  #+BEGIN_SRC org
  ,* Home page
  :PROPERTIES:
  :ONE: my-render-function
  :CUSTOM_ID: /
  :END:

  foo

  -----

  bar

  -----

  baz
  #+END_SRC

- ~onerc.el~:

  #+BEGIN_SRC emacs-lisp
  (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)))))
  #+END_SRC

Now while visiting ~one.org~ file we call ~one-build~ to build our website
with ~<hr>~ tags.

* one-ox
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox/
:END:
** Org export backend used by the default render functions

~one.el~ (specifically the default render functions) uses its own org
export backend called ~one-ox~ to export the org content of the pages
into HTML strings.

For instance, the render function ~one-default~ takes as first argument
~page-tree~ which is the current page being rendered (~page-tree~ is the
org parsed data structure representing the page) and exports it as an
HTML string using ~org-export-data-with-backend~ function and ~one-ox~
export backend and uses it to render the HTML page:

#+BEGIN_SRC emacs-lisp
(defun one-default (page-tree pages _global)
  "..."
  (let* (...
         (content (org-export-data-with-backend
                   (org-element-contents page-tree)
                   'one-ox nil))
         ...)
    (jack-html
     "<!DOCTYPE html>"
     `(:html
       (:head ...)
       (:body ... (:div.content ... ,content ,nav))))))
#+END_SRC

This org backend is taylor for ~one.el~ usage.  So it doesn't try to
export all the org elements unlike ~html~ backend and when the org
elements are exported they differ from what we can expect from ~html~
backend.

For instance ~headline~ elements don't take into account markups
neither links.

Another example are the ~link~ elements.  They don't support org fuzzy
links and links to local files that are not in the subdirectories
~./public/~ or ~./assets/~ raise errors.

You can read how the supported org elements are exported by ~one-ox~ org
backend in the following page:

- [[#/docs/one-ox-headline/][one-ox | headline]],
- [[#/docs/one-ox-src-block/][one-ox | src-block]],
- [[#/docs/one-ox-quote-block/][one-ox | quote-block]],
- [[#/docs/one-ox-fixed-width-and-example-block/][one-ox | fixed-width and example-block]],
- [[#/docs/one-ox-links/][one-ox | links]] and
- [[#/docs/one-ox-plain-list/][one-ox | plain-list]].

** Org elements not supported
:PROPERTIES:
:CUSTOM_ID: /docs/one-ox/#org-elements-not-supported
:END:

The org elements that are not supported are the following:
~center-block~, ~clock~, ~drawer~, ~dynamic-block~, ~entity~, ~export-block~,
~export-snippet~, ~footnote-reference~, ~horizontal-rule~, ~inline-src-block~,
~inlinetask~, ~keyword~, ~latex-environment~, ~latex-fragment~, ~line-break~,
~node-property~, ~planning~, ~property-drawer~, ~radio-target~, ~special-block~,
~statistics-cookie~, ~target~, ~timestamp~, ~verse-block~.

Note that "not supported" means they are not rendered by default by
~one.el~ but we can still use them or even extend ~one-ox~ org export
backend to take some of them into account.

Why doesn't ~one.el~ support all org elements?

1. I don't need those org elements to write my technical blogs:

   - I don't do math.  No support for Latex,
   - etc.

2. ~one-ox~ org backend is used only by the default render functions, so
   if you need more org elements you can either use another org
   backend or extend ~one-ox~ org backend and use this other org backend
   in your own render functions (See [[#/docs/miscellaneous/#extend-one-ox-org-backend][Extend one-ox org backend]]).

* one-ox | headline
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox-headline/
:END:

Note that markups and links are not exported if used in headlines, only
the raw value string.

So don't use them in headlines.

* one-ox | src-block
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox-src-block/
:END:
** Code highlighting with htmlize
*** Description

~one-ox~ highlights code via the function ~one-ox-htmlize~ that uses
[[https://github.com/hniksic/emacs-htmlize][htmlize]] to do the work.

For a given piece of code ~X~ in a certain language ~Y~, ~X~ will be
highlighted as it would be in the emacs mode ~Z~ used to edit ~Y~ code.

For instance, ~clojure-mode~ is used to highlight Clojure code and
~sh-mode~ is used to highlight Bash code.

Attributes of a face (like ~background-color~ or ~foreground-color~)
are not taken directly.  A generated name for the face is produced and
used as the CSS class for the parts of the code ~X~ that are highlighted
with that face.

For instance, in ~sh-mode~, the word ~echo~ is highlighted with the face
~font-lock-builtin-face~.  So, the word ~echo~ in a piece of Shell (or
Bash) code will be transformed into:

#+BEGIN_SRC html
<span class="one-hl-builtin">echo</span>
#+END_SRC

The whole piece of code ~X~, once the previously described operations
have been done, is wrapped:

1) for a normal block with the component:

   #+BEGIN_SRC html
   <pre><code class="one-hl one-hl-block">...</code></pre>
   #+END_SRC

2) for a result block with the component:

   #+BEGIN_SRC html
   <pre><code class="one-hl one-hl-results">...</code></pre>
   #+END_SRC

   See section [[#/docs/one-ox-src-block/#org-keywords-results-and-attr_one_results][org keyword RESULTS]].

*** Example with Bash code

For instance, the following org src-block, containing some ~bash~ code:

#+BEGIN_SRC org
,#+BEGIN_SRC bash
echo "list file's extensions in current dir:"
for f in `ls`; do
    echo ${f##*.}
done
,#+END_SRC
#+END_SRC

is exported as follow:

#+BEGIN_SRC html
<pre><code class="one-hl one-hl-block"><span class="one-hl-builtin">echo</span> <span class="one-hl-string">"list file's extensions in current dir:"</span>
<span class="one-hl-keyword">for</span> f<span class="one-hl-keyword"> in</span> <span class="one-hl-sh-quoted-exec">`ls`</span>; <span class="one-hl-keyword">do</span>
    <span class="one-hl-builtin">echo</span> ${<span class="one-hl-variable-name">f</span>##*.}
<span class="one-hl-keyword">done</span></code></pre>
</div>
#+END_SRC

and rendered like this:

#+BEGIN_SRC bash
echo "list file's extensions in current dir:"
for f in `ls`; do
    echo ${f##*.}
done
#+END_SRC

Note that ~one-ox-htmlize~ has produced and used the following CSS
classes (listed with their corresponding emacs faces):

#+BEGIN_SRC text
# from font-lock
one-hl-builtin        --> font-lock-builtin-face
one-hl-keyword        --> font-lock-keyword-face
one-hl-string         --> font-lock-string-face
one-hl-variable-name  --> font-lock-variable-name-face

# specific to sh-mode
one-hl-sh-quoted-exec --> sh-quoted-exec
#+END_SRC

You might have notice the pattern used for ~font-lock~ faces and the one
used for mode specific faces.

~one.el~ provides a default style sheet (~one-default-css~) that has the
CSS classes defined for all the ~font-lock~ faces (faces starting by
~font-lock-~) but not the specific faces used by each prog mode.

You can add the CSS classes specific to the prog modes you use as you
go and need them.

** Org keyword RESULTS
:PROPERTIES:
:CUSTOM_ID: /docs/one-ox-src-block/#org-keywords-results-and-attr_one_results
:END:

Result blocks are preceded by a line starting with ~#+RESULTS:~.  Blocks
that are not result blocks are normal blocks.

When exported, normal blocks and result blocks differ only by their
CSS classes:

- ~one-hl one-hl-block~ for normal blocks,
- ~one-hl one-hl-results~ for result blocks.

This way result blocks can be rendered with a different style
than normal blocks as we can see in the following example.

*** Example using org keyword 'RESULTS'

The following org snippet:

#+BEGIN_SRC org
,#+BEGIN_SRC bash :results output
ls
,#+END_SRC

,#+RESULTS:
: assets
: docs.org
: public
#+END_SRC

is exported by ~one-ox~ as follow:

#+BEGIN_SRC html
<pre><code class="one-hl one-hl-block">ls</code></pre>
<pre><code class="one-hl one-hl-results">assets
docs.org
public</code></pre>
#+END_SRC

and is rendered by ~one-ox~ with the first block (normal block) having a
different style from second block (result block):

#+BEGIN_SRC bash :results output
ls
#+END_SRC

#+RESULTS:
: assets
: docs.org
: public

** Code blocks inside list

Lists can contain source blocks as we can see in the following org
snippet

#+BEGIN_SRC org
1. item 1

   ,#+BEGIN_SRC emacs-lisp
   (message "src-block in item 1")
   ,#+END_SRC

2. item 2
3. item 3
#+END_SRC

which is exported by ~one~ as follow

#+BEGIN_SRC html
<ol>
  <li>
    <p>item 1</p>
    <pre><code class="one-hl one-hl-block">(message <span class="one-hl-string">"src-block in item 1"</span>)</code></pre>
  </li>
  <li><p>item 2</p></li>
  <li><p>item 3</p></li>
</ol>
#+END_SRC

and is rendered by ~one-ox~ like this:

1. item 1

   #+BEGIN_SRC emacs-lisp
   (message "src-block in item 1")
   #+END_SRC

2. item 2
3. item 3

* one-ox | quote-block
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox-quote-block/
:END:

Blocks defined with ~#+BEGIN_QUOTE ... #+END_QUOTE~ pattern are
quote-block.

They are exported by ~one-ox~ in a ~<blockquote>...</blockquote>~
component with the CSS class ~one-blockquote~.

The following org snippet:

#+BEGIN_SRC org
,#+BEGIN_QUOTE
A quitter never wins and a winner never quits. —Napoleon Hill
,#+END_QUOTE
#+END_SRC

defines a quote and is exported by ~one-ox~ as follow

#+BEGIN_SRC html
<blockquote class="one-blockquote"><p>A quitter never wins and a winner never quits. —Napoleon Hill</p></blockquote>
#+END_SRC

and looks like this

#+BEGIN_QUOTE
A quitter never wins and a winner never quits. —Napoleon Hill
#+END_QUOTE

* one-ox | fixed-width and example-block
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox-fixed-width-and-example-block/
:END:
** Description

A line starting with a colon ~:~ followed by a space defines a
~fixed-width~ element.  A ~fixed-width~ element can span several
lines.

Blocks defined with ~#+BEGIN_EXAMPLE ... #+END_EXAMPLE~ pattern are
~example-block~ elements.

Both ~fixed-width~ and ~example-block~ blocks are treated as [[#/docs/one-ox-src-block/][src-block]] in
~text-mode~.  So:

1. they are highlighted as ~text-mode~ would do,
2. they are exported in ~<pre><code>...</code></pre>~ components
   (indentation and newlines are respected) and
3. the CSS classes used depend on the block's type:

   - normal blocks use ~one-hl one-hl-block~ CSS classes and
   - result blocks use ~one-hl one-hl-results~ CSS classes (see [[#/docs/one-ox-src-block/#org-keywords-results-and-attr_one_results][org
     keyword RESULTS]]).

** Example

The following org snippet

#+BEGIN_SRC org
Here is a ~fixed-width~ element (one line):

: I'm a fixed-width element

~fixed-width~ elements can also be used within lists:

- item 1

  : fixed-width element

- item 2

  ,#+BEGIN_SRC bash :results output
  printf 'multiline fixed-width element\nthat is also a result block,\nso has a different style.'
  ,#+END_SRC

  ,#+RESULTS:
  : multiline fixed-width element
  : that is also a result block,
  : so has a different style.

Although I don't often use ~example-block~ elements, here is one:

,#+BEGIN_EXAMPLE
This    is
        an    example!
,#+END_EXAMPLE
#+END_SRC

is exported by ~one~ as follow

#+BEGIN_SRC html
<p>Here is a <code class="one-hl one-hl-inline">fixed-width</code> element (one line):
</p>

<pre><code class="one-hl one-hl-block">I'm a fixed-width element</code></pre>


<p><code class="one-hl one-hl-inline">fixed-width</code> elements can also be used within lists:
</p>

<ul><li><p>item 1
</p>

<pre><code class="one-hl one-hl-block">fixed-width element</code></pre>
</li>

<li><p>item 2
</p>

<pre><code class="one-hl one-hl-block"><span class="one-hl-builtin">printf</span> <span class="one-hl-string">'multiline fixed-width element\nthat is also a result block,\nso has a different style.'</span></code></pre>

<pre><code class="one-hl one-hl-results">multiline fixed-width element
that is also a result block,
so has a different style.</code></pre>
</li>
</ul>

<p>Although I don&apos;t often use <code class="one-hl one-hl-inline">example-block</code> elements, here is one:
</p>

<pre><code class="one-hl one-hl-block">This    is
        an    example!</code></pre>
#+END_SRC

and looks like this:

Here is a ~fixed-width~ element (one line):

: I'm a fixed-width element

~fixed-width~ elements can also be used within lists:

- item 1

  : fixed-width element

- item 2

  #+BEGIN_SRC bash :results output
  printf 'multiline fixed-width element\nthat is also a result block,\nso has a different style.'
  #+END_SRC

  #+RESULTS:
  : multiline fixed-width element
  : that is also a result block,
  : so has a different style.

Although I don't often use ~example-block~ elements, here is one:

#+BEGIN_EXAMPLE
This    is
        an    example!
#+END_EXAMPLE

* one-ox | links
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox-links/
:END:
** http, https, mailto links

Web links (starting by ~http~ or ~https~) and links to message
composition (starting by ~mailto~) are exported as we expect.

For instance the following link

#+BEGIN_SRC org
http://tonyaldon.com
#+END_SRC

is exported as follow

#+BEGIN_SRC html
<a href="http://tonyaldon.com">http://tonyaldon.com</a>
#+END_SRC

and rendered like this: http://tonyaldon.com.

This following link with a description

#+BEGIN_SRC org
[[https://tonyaldon.com][Tony Aldon (https)]]
#+END_SRC

is exported as follow

#+BEGIN_SRC html
<a href="https://tonyaldon.com">Tony Aldon (https)</a>
#+END_SRC

and rendered like this: [[https://tonyaldon.com][Tony Aldon (https)]].

This ~mailto~ link

#+BEGIN_SRC org
[[mailto:tony@tonyaldon.com][send me an email]]
#+END_SRC

is exported as follow

#+BEGIN_SRC html
<a href="mailto:tony@tonyaldon.com">send me an email</a>
#+END_SRC

and rendered like this: [[mailto:tony@tonyaldon.com][send me an email]].

** Custom ID links

In ~one.el~, ~CUSTOM_ID~ org property is used to defined the path of pages
or the path to specific heading in pages.

Considering the following org document

#+BEGIN_SRC org
,* Home Page
:PROPERTIES:
:ONE: one-default-home
:CUSTOM_ID: /
:END:

- [[#/blog/page-1/]]
- [[#/blog/page-1/#headline-1]]

,* Page 1
:PROPERTIES:
:ONE: one-default
:CUSTOM_ID: /blog/page-1/
:END:
,** headline 1 in Page 1
:PROPERTIES:
:CUSTOM_ID: /blog/page-1/#headline-1
:END:
#+END_SRC

the link ~[[#/blog/page-1/]]~ in "Home Page" targets "Page 1" page
and the link ~[[#/blog/page-1/#headline-1]]~ in "Home Page" targets the
heading "headline 1 in page Page 1" in the "Page 1" page.

Those paths define valid web urls starting at the root of the website
if we respect the following rules for ~CUSTOM_ID~ values:

1. we use only url-encoded characters,
2. we start them with a ~/~ and end them with ~/~ excepted for the home
   page which is a single ~/~,
3. we use ~#~ character to start the last part of the path when we are
   targeting a heading tag with its ~id~ being the last part after the ~#~
   character.

The benefits of these "rules/conventions" are:

1. when we export ~custom-id~ links using ~one-ox~ org backend we can
   leave them as they are and
2. the navigation between pages inside emacs using ~custom-id~ links
   works out-of-the-box.

*** Example of a link to a page

The following link

#+BEGIN_SRC org
[[#/docs/one-ox-plain-list/][one-ox | plain-list]]
#+END_SRC

is exported to this anchor tag that links to the page ~/docs/one-ox-plain-list/~:

#+BEGIN_SRC html
<a href="/docs/one-ox-plain-list/">one-ox | plain-list</a>
#+END_SRC

and is rendered like this [[#/docs/one-ox-plain-list/][one-ox | plain-list]].

*** Example of a link to a heading in a page

The following link

#+BEGIN_SRC org
[[#/docs/one-ox-plain-list/#unordered-lists][unordered lists heading in the page about plain-list]]
#+END_SRC

is exported to this anchor tag that links to the heading with the ~id~
set to ~unordered-lists~ on the page ~/docs/one-ox-plain-list/~:

#+BEGIN_SRC html
<a href="/docs/one-ox-plain-list/#unordered-lists">unordered lists heading in the page about plain-list</a>
#+END_SRC

and is rendered like this [[#/docs/one-ox-plain-list/#unordered-lists][unordered lists heading in the page about
plain-list]].

** Fuzzy links

I don't use ~fuzzy~ links.  So, if there is a ~fuzzy~ link
in the document, that means I wrote the link wrong.

Broken links are bad user experience.  I don't like them.

So I decided that ~one-ox~ raises an error (hard-coded) when we try to
export a fuzzy link to HTML.

For instance, the following ~fuzzy~ link:

#+BEGIN_SRC org
[[fuzzy search]]
#+END_SRC

raise an error like the following:

#+BEGIN_SRC emacs-lisp
(one-link-broken "fuzzy search" "fuzzy links not supported" "goto-char: 5523")
#+END_SRC

** File links
*** Links to local files in assets and public directories

Links to local files in ~./assets/~ and ~./public/~ directories like

#+BEGIN_SRC org
[[./assets/foo/bar.txt][Bar file]]
[[./public/foo/baz.txt][Baz file]]
#+END_SRC

are exported with the prefixes ~./assets~ and ~./public~ of the path
removed like this:

#+BEGIN_SRC html
<a href="/foo/bar.txt">Bar file</a>
<a href="/foo/baz.txt">Baz file</a>
#+END_SRC

*** Local file links that raise one-link-broken error

Any file link that doesn't point to a file in ~./assets/~ or ~./public/~
subdirectories raises an ~one-link-broken~ error when we try to
export it with ~one-ox~ org backend

For instance if we try to export using ~one-ox~ org backend the
following link to the file ~foo.txt~ in the directory ~/tmp/~

#+BEGIN_SRC org
[[/tmp/foo.txt]]
#+END_SRC

which is not in ~./public/~ subdirectory nor in ~./assets/~ subdirectory
we will get an error like the following:

#+BEGIN_SRC emacs-lisp
(one-link-broken "/tmp/" "goto-char: 26308")
#+END_SRC

*** Links to images

Links to local files in ~./assets/~ and ~./public/~ directories whom path
matches ~one-ox-link-image-extensions~ regexp are exported with an ~img~
tag.

For instance the following link to an image in ~./assets/img/~ directory

#+BEGIN_SRC org
[[./assets/img/keep-learning.png][Keep Learning]]
#+END_SRC

is exported as follow

#+BEGIN_SRC html
<img href="/img/keep-learning.png" alt="Keep Learning"></a>
#+END_SRC

and rendered like this

[[./assets/img/keep-learning.png][Keep Learning]]

* one-ox | plain-list and item
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox-plain-list/
:END:

Only unordered and ordered lists are supported.

** Unordered lists
:PROPERTIES:
:CUSTOM_ID: /docs/one-ox-plain-list/#unordered-lists
:END:

The following org snippet (unordered list):

#+BEGIN_SRC org
- a thing,
- another thing,
- and the last one.
#+END_SRC

is exported by ~one-ox~ as follow

#+BEGIN_SRC html
<ul>
  <li>
    <p>a thing,</p>
  </li>
  <li>
    <p>another thing,</p>
  </li>
  <li>
    <p>and the last one.</p>
  </li>
</ul>
#+END_SRC

and is rendered like this:

- a thing,
- another thing,
- and the last one.

** Ordered list

The following org snippet (unordered list):

#+BEGIN_SRC org
1. first,
2. second,
3. third.
#+END_SRC

is exported by ~one-ox~ as follow

#+BEGIN_SRC html
<ol>
  <li>
    <p>a thing,</p>
  </li>
  <li>
    <p>another thing,</p>
  </li>
  <li>
    <p>and the last one.</p>
  </li>
</ol>
#+END_SRC

and is rendered like this:

1. first,
2. second,
3. third.

* one-ox | table
:PROPERTIES:
:ONE: one-default-doc
:CUSTOM_ID: /docs/one-ox-table/
:END:

Tables with header rows are supported.

The following org snippet:

#+BEGIN_SRC org
| Name  | Age | City     |
|-------+-----+----------|
| Alice |  30 | New York |
| Bob   |  25 | London   |
#+END_SRC

is exported by ~one-ox~ as follow

#+BEGIN_SRC html
<table>
  <tr>
    <th>Name</th>
    <th>Age</th>
    <th>City</th>
  </tr>
  <tr>
    <td>Alice</td>
    <td>30</td>
    <td>New York</td>
  </tr>
  <tr>
    <td>Bob</td>
    <td>25</td>
    <td>London</td>
  </tr>
</table>
#+END_SRC

The first row is automatically exported as ~<th>~ (header) tags when
separated by a horizontal rule (~|---+---|~), and subsequent rows use
~<td>~ (data) tags.
