Origami template documents

Text files with embedded Origami expressions

Template documents represent a middle ground between documents that can contain some data in front matter and Origami files that contain templates.

  • A template document file is identified with two extensions, where the second-to-last extension is .ori, like index.ori.html or about.ori.md.
  • When you ask Origami to evaluate such a file, it will implicitly inline the results of any Origami expressions inside the file.

A template document is appropriate when you have a long template that may need portions of embedded or attached code. (For brevity, some of the samples shown below have very short templates.)

There are three different kinds of template documents:

  1. Text with embedded substitutions
  2. Body text with YAML front matter
  3. Body text with Origami front matter

These largely work the same, but with some differences described below.

Text with embedded substitutions

This template document is called inline.ori.html:

<!DOCTYPE html>
<html>
  <head>
    <style>
      ${ inline.css }
    </style>
  </head>
  <body>
    This text will be red.
  </body>
</html>

Substitutions inside a template document are full Origami expressions so, among other things, they can reference other documents. The above template includes an embedded Origami expression that references a separate file, inline.css.

/* inline.css */
body { color: red }

The result of the inline.ori.html template is a function that returns a string. (The function can accept a single parameter; see below.)

If you have ask Origami to evaluate the template, it will call that function and return the resulting text. The text will contain the results of all the expressions in the document.

In this example, evaluating the function inlines the referenced CSS file:

$ ori inline.ori.html/
<!DOCTYPE html>
<html>
  <head>
    <style>
      body { color: red }
    </style>
  </head>
  <body>
    This text will be red.
  </body>
</html>

Accepting an argument

By default, a template document like this can be called as a function with one argument referenced with a _ underscore.

<!-- bold.ori.html -->
<b>${ _ }</b>

When called as a function, any value passed to this template will be incorporated into the output:

$ ori "bold.ori.html('Hooray')"
<b>Hooray</b>

Such templates behave like simple components. You can use them decompose the construction of complex documents into smaller pieces that are easier to understand.

Body text with YAML front matter

Like other text documents, a template document can include YAML front matter at the top of the document, enclosed in lines of --- three hyphens.

Suppose shopping.ori.html contains:

---
list:
  - Loaf of Bread
  - Container of Milk
  - Stick of Butter
---

Things to buy:

<ul>
  ${ map(list, (item) => indent`
    <li>${ item }</li>
  `) }
</ul>

The front matter is treated as YAML. This can be used to define additional data — here, a list.

The front matter data is available to expressions in the body text, so the expression in the body text can reference the list:

$ ori shopping.ori.html/
list:
  - Loaf of Bread
  - Container of Milk
  - Stick of Butter
"@text": |
  Things to buy:

  <ul>
    <li>Loaf of Bread</li>
    <li>Container of Milk</li>
    <li>Stick of Butter</li>
  </ul>

The result of the template is a plain object containing all of the front matter data, plus a @text property with the result of evaluating the body text.

Body text with Origami front matter

Alternatively, front matter can be an Origami expression that returns a function, function call, object literal, etc.

Defining the value of the template document

If Origami front matter is present, that will be evaluated and returned as the result of invoking the template document. Within this front matter, you can invoke the template’s body text as @template.

Example: a website defines its “About” page as a template document called about.ori.html:

---
page.ori.html(@template())
---

<article>
  <p>We have fun making websites.</p>
</article>

The front matter of this document is an Origami expression that will be evaluated and returned as the result of the template document.

In this case, the expression invokes the template’s body text via @template, then passes that to a base page.ori.html template defined separately:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
  </head>
  <body>
    ${ _ }
  </body>
</html>

When you ask for the value of about.ori.html, that in turn calls page.ori.html:

$ ori about.ori.html/
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
  </head>
  <body>
    <article>
      <p>We have fun making websites.</p>
    </article>
  </body>
</html>

Returning an object

Sometimes a template is primarily body text but the result should include some calculated data.

This can be achieved using the above principle of placing an Origami expression in the front matter. In this case, the front matter can define an object using an object literal.

If calcs.ori.md contains:

---
{
  sum: 1 + 1
  @text: @template()
}
---

One plus one is ${ sum }.

then invoking this returns an object:

$ ori calcs.ori.md/
sum: 2
"@text": |
  One plus one is 2.

Returning a function

To define your template document as a more complex function — e.g., one that accepts multiple arguments, or that calls other functions — define a function in the front matter.

This link.ori.html template accepts href and text parameters to return an HTML link:

---
(href, text) => @template()
---

<a href="${ href }">${ text }</a>

The value of the href and link parameters are in scope for expressions in the template body.

$ ori "link.ori.html('https://weborigami.org', 'Web Origami')"
<a href="https://weborigami.org">Web Origami</a>

Behavior within a map

When used inside a tree:map function, a template document will provide a default key function to the map. This key function will add the template document’s last extension to keys in the map’s output.

For example, this template is called movie.ori.html, so it will add .html to keys in a map.

<!-- movie.ori.html -->
<article>
  <h1>${ _/title } (${ _/year })</h1>
</article>

When applied to this data:

# movies.yaml
kiki:
  title: Kiki's Delivery Service
  year: 1989
mononoke:
  title: Princess Mononoke
  year: 1997
spirited:
  title: Spirited Away
  year: 2001
heron:
  title: The Boy and the Heron
  year: 2023

the values will end up with .html extensions:

$ ori map movies.yaml, movie.ori.html
kiki.html: |
  <article>
    <h1>Kiki's Delivery Service (1989)</h1>
  </article>
mononoke.html: |
  <article>
    <h1>Princess Mononoke (1997)</h1>
  </article>
spirited.html: |
  <article>
    <h1>Spirited Away (2001)</h1>
  </article>
heron.html: |
  <article>
    <h1>The Boy and the Heron (2023)</h1>
  </article>

You can override this behavior by explicitly providing a key option to tree:map.