npm package: @funcstache/funcstache
Description: A JavaScript library to render mustache templates into documents. For example, webpages that are dynamically generated on a server.
Author: Richard L. McNeary II
Latest version: 0.1.16

# funcstache

A JavaScript library to render [Mustache templates](http://mustache.github.io/) into documents. For
example, webpages that are dynamically generated on a server.

- Stream-based to deliver a rendered document as quickly as possible
- Defines conventions that simplify document creation
- File-based routing

We're using: the proven pattern of rendered templates, combined with new JavaScript capabilities,
plus some conventions, to simplify rendering documents dynamically.

> [!TIP]
> What do we mean by "document?" A good example is an HTML document which renders a page in a web
> browser. However, This library is output agnostic and will render any text document that meets the
> Mustache requirements.

> [!TIP]
> There is a KOA middleware package for serving rendered HTML. See the [koa-middleware
> docs](https://codeberg.org/rlmcneary2/funcstache/src/branch/main/libs/koa-middleware).

**Contents**

- [Usage](#usage)
- [Develop](#develop)

## Usage

To use the funcstache library create an instance of a `Renderer`.

### Initialization

When created a `Renderer` instance is passed a fully-qualified path to a file system directory, this
is known as the "root directory." funcstache will be able to traverse all the directories and files
under the root. The root directory **must** contain a file named **index.js**. funcstache will read
the **index.js** file to determine which template to render at the root.

### File-based routing

funcstache uses two different files to render a document:

- A JavaScript file that **must** return a path to the Mustache file to be rendered, and optionally
  returns context information to be used when rendering the document.
- A Mustache template file that defines the document to be rendered.

#### The JavaScript file

> [!NOTE]
> The example code is written in TypeScript to illustrate the interfaces and types available to
> developers. TypeScript code must be transpiled to JavaScript code before it is provided to
> funcstache.

##### template function

The **index.js** file must export an async `template` function. This function must return template
information in one of two ways:

- a string that is the name of the template - **without** a file extension - the name **must** refer
  to a file with the same name in the same directory as the **index.js** file
- a tuple with two elements: first the name of the template file and second a path to the directory
  where the template file is located; the path is relative to the location of the **index.js** file.

##### context function

The optional async `context` function can be included in the **index.js** file. This function
returns an object whose properties match Mustache tags and their values can be used as replacements
for the tag value. The type of a context property value varies depending on the tag type. See
"stache-stream" documentation.

##### Example index.js

```ts
/* /root/index.ts */
import { type FuncStacheModule } from "@funcstache/funcstache";

export const { context, template }: FuncStacheModule = {
  context: async (options) => {
    return {
      title: "funcstache example",
    };
  },

  template: async (options) => "main",
};
```

#### Mustache template

Mustache templates are text files with optional
[tags](https://mustache.github.io/mustache.5.html#TAG-TYPES) that follow the rules defined by the
[Mustache standards](https://mustache.github.io/mustache.5.html).

> [!WARNING]
> The following tag types are implemented: variable, partial.

```mustache
<!--
/html/public/main.mustache
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>{{title}}</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
  </head>

  <body>
    <p>Hello funcstache!</p>
  </body>
</html>
```

Notice that this template has one variable tag "{{title}}" that will be replaced by context data.

### Rendering the document

An instance of the `Renderer` class is used to create a rendered document. The `Renderer`
constructor accepts a variety of options, most importantly the location of the JavaScript and
Mustache files. To begin generating the output the `render` method is invoked, it's passed a
`WritableStream` parameter, the rendered document will be written to this stream. Note that
`WritableStream` comes from the [node:stream/web
package](https://nodejs.org/api/webstreams.html#class-writablestream).

```ts
import { Renderer } from "@funcstache/funcstache";

const renderer = new Renderer({
  indexDirectory: "/html/public",
  path: "/",
  rootDirectory: "/html/public",
});

await renderer.render(writable);
```

After the files are processed, and a rendered document created, the contents of the `WritableStream`
will be an HTML document with the "{{title}}" tag replaced with the value of context's `title`
property - "funcstache example".

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>funcstache example</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
  </head>

  <body>
    <p>Hello funcstache!</p>
  </body>
</html>
```

Using these basic building blocks you can create complex templates composed of smaller individual -
partial - templates.

## Develop

### Install

```sh
npm i @funcstache/funcstache
```

### Logging

Logging can be set by adding an environment variable named `LOG_LEVEL`. The following values are
supported: "debug", "log", "warn", "error".