Falz Docs

JavaScript API

Custom pipes run synchronously in an ES2020 JavaScript runtime. Their TypeScript entry point is bundled before execution.

export function transform(this: tCtx, input: Buffer): string | Buffer | TransformResult
export function index(this: iCtx, input: Buffer): unknown

The generated declarations are in .falz/types/.

Transform context: tCtx

Property Type Meaning
file FileInfo Source file metadata.
globals Record<string, unknown> Project variables, after environment expansion.
vars Record<string, string> <Var> values from the matching <Content>.
entry { type: string, tag: string } type is content or asset; tag is the content/asset name.
kv KV Read-only cross-entry index data.
blob Blob This entry's own cached index() return value.

Fragment context: fCtx

Fragment transforms receive the following context:

Property Type Meaning
name string The <Fragment name="..."> value.
file FileInfo (optional) Source metadata when src exists; paths are relative to the scheme root.
globals Record<string, unknown> Project variables, after environment expansion, as in normal pipes.
vars Record<string, string> Content <Var> values used to compile the layout.
entry { type: "fragment", tag: string } Fragment type and declared name (tag equals name).
debug Debug start() starts a timer; end(message) logs the elapsed duration at debug level.

A source-less fragment has no file and receives an empty input buffer. Content variables remain available as top-level properties for compatibility (for example, this.lang), but cannot overwrite context fields. All values, including colliding names, remain accessible through this.vars.

Fragments are rendered per layout context, not per page: they do not receive a current page or output URL. Fragment indexing and KV access are not supported.

export function transform(this: fCtx): string {
  switch (this.name) {
    case 'nav': return renderNav(this.vars.lang)
    case 'footer': return renderFooter(this.vars.lang)
    default: throw new Error(`Unknown fragment: ${this.name}`)
  }
}

Declare <Fragment name="nav" pipe="shell"/> without a dummy source file. See Layout reference.

FileInfo

For content/posts/hello.md:

Property Example Meaning
path content/posts/hello.md Slash-normalized path relative to project root.
dir content/posts Parent directory.
name hello.md Filename with extension.
stem hello Filename without final extension.
ext md Extension without dot.
baseDir content/posts Directory from which this entry is scoped by its layout.

TransformResult

interface TransformResult {
  content: string | Buffer
  alias?: string
  vars?: Record<string, string>
}

Fields:

  • content — transformed output inserted into the matching content slot;
  • alias — optional value for {ALIAS} in the output path;
  • vars — optional string values added to the layout variables. Keys identify layout placeholders and variables in expressions.

Returning another JavaScript value converts it to a string, but relying on that is less clear. Returning null or undefined is an error. An object must contain a string or Buffer content field.

Index context: iCtx

iCtx has file, globals, vars, and entry, with the same meanings as above. It also has kv: IndexKV, the write-only collector used to publish cross-entry values during indexing.

The return value of index() must be JSON-serializable. Falz stores it as this entry's blob, making it available later through this.blob.get() in transform(). See Index phase.

Index data

IndexKV

  • set(key: string, value: unknown): void — store a JSON-serializable value during index(). key must have the form namespace:key, and the namespace must be in contract.provides.

KV

  • get(key: string): unknown — return a decoded value, or null when missing.
  • keys(prefix: string): string[] — return matching full keys in sorted order.

Only namespaces declared in the pipe's contract.consumes are loaded for its transforms.

Blob

  • get(): unknown — lazily decode this entry's own index() result, or return null if none exists.

Repeated calls in one transform return the same decoded value.

Built-in modules

Use ESM imports:

import { text, json } from "fs"
import { get } from "http"
import { toHtml } from "md"

Falz externalizes these names during bundling and provides them at runtime.

fs

The fs module is read-only and rooted at the project source tree. It cannot read the scheme tree, output tree, or arbitrary host paths.

Method Result Behavior
bytes(path) Uint8Array | undefined Read bytes; missing files return undefined.
text(path) string | undefined Read UTF-8 text; missing files return undefined.
json(path) any | undefined Read and parse JSON; malformed JSON throws.
exists(path) boolean Test whether any filesystem entry exists.
isFile(path) boolean Test for a regular file.
isDirectory(path) boolean Test for a directory.
size(path) number | undefined File size in bytes.
lastModified(path) Date | undefined Last modification time.
list(path) FileEntry[] Direct children only. Throws if path is not a directory.
walk(path) FileEntry[] Recursive flat list in lexical order. Symlinks are not followed.

FileEntry has name, /-prefixed slash-normalized path, size, modTime, isFile, isDirectory, and isSymlink. Directories report size 0.

Example:

import { json, walk } from "fs"

const settings = json("data/settings.json") ?? {}
const images = walk("images").filter(entry => entry.isFile)

Reads through fs are available to the pipe, but they are not automatically represented as individual layout dependencies. If output freshness depends on another file, arrange your workflow so a relevant entry changes or use an indexed namespace to fan out invalidation.

http

The HTTP API is synchronous. Configure an allowlist in the pipe's config.yaml; no hosts are allowed by default.

Method Signature
get get(url, headers?): Response
post post(url, body?, headers?): Response
put put(url, body?, headers?): Response
patch patch(url, body?, headers?): Response
del del(url, body?, headers?): Response
head head(url, headers?): Response

url may be a string or URL. Headers may be a Headers object, a string-valued object, or [name, value][].

Body encoding:

  • string: text/plain;charset=UTF-8;
  • Buffer, Uint8Array, or ArrayBuffer: application/octet-stream;
  • object or array: JSON with application/json;charset=UTF-8.

Set Content-Type explicitly in headers to override inference.

All methods throw for non-2xx responses. The error has status and response properties:

import { get, type Response } from "http"

try {
  const value = get("https://api.example.com/item").json()
} catch (error) {
  const e = error as Error & { status: number, response: Response }
  console.error(e.status, e.response.text())
}

Response

Properties:

  • status: number — status code;
  • statusText: string — standard status text;
  • ok: boolean — true for 2xx;
  • redirected: boolean — whether the final URL differs;
  • url: string — final URL;
  • headers: Headers — response headers.

Methods:

  • text(): string — decode body bytes as text;
  • json(): any — parse JSON; throws for empty or malformed bodies;
  • bytes(): Buffer — return a Buffer;
  • arrayBuffer(): ArrayBuffer — return an ArrayBuffer.

The body is buffered, so these accessors may be called more than once.

Headers

Construct with new Headers(), another Headers, a plain object, or pairs.

  • append(name, value) — add another value;
  • delete(name) — remove all values for the name;
  • get(name) — comma-join values, or return null;
  • has(name) — test whether the name exists;
  • set(name, value) — replace existing values;
  • entries() — iterator of [name, value] pairs;
  • keys() — iterator of names;
  • values() — iterator of values;
  • forEach(callback, thisArg?) — visit (value, name, headers);
  • getSetCookie() — return separate Set-Cookie values.

md

toHtml(markdown, options?)

Converts a string or Buffer to an HTML string.

import { commonOptions, toHtml } from "md"
return toHtml(input, commonOptions)

With no options, no optional parser/renderer flags are enabled. commonOptions enables common parsing features and smart punctuation.

options.parser boolean flags:

Flag Effect
NoIntraEmphasis Ignore emphasis markers inside words.
Tables Parse tables.
FencedCode Parse fenced code blocks.
Autolink Link bare URLs.
Strikethrough Parse ~~text~~.
LaxHTMLBlocks Loosen HTML block parsing.
SpaceHeadings Require spaces in prefix headings.
HardLineBreak Turn newlines into line breaks.
NonBlockingSpace Convert backspace spaces to non-breaking spaces.
TabSizeEight Expand tabs to eight spaces instead of four.
Footnotes Parse Pandoc-style footnotes.
NoEmptyLineBeforeBlock Allow blocks without a preceding empty line.
HeadingIDs Parse explicit heading IDs.
Titleblock Parse Pandoc title blocks.
AutoHeadingIDs Generate heading IDs from text.
BackslashLineBreak Parse trailing backslashes as line breaks.
DefinitionLists Parse definition lists.
MathJax Parse MathJax notation.
OrderedListStart Preserve the first ordered-list number.
Attributes Parse block attributes.
SuperSubscript Parse super/subscript notation.
EmptyLinesBreakList Let two empty lines end a list.
Includes Enable include syntax.
Mmark Enable Mmark syntax.

options.renderer boolean flags:

Flag Effect
SkipHTML, SkipImages, SkipLinks Omit that kind of output.
Safelink Allow only trusted link protocols.
NofollowLinks, NoreferrerLinks, NoopenerLinks Add the corresponding link relation.
HrefTargetBlank Add target="_blank".
CompletePage Emit a complete HTML page.
UseXHTML Emit XHTML-style output.
FootnoteReturnLinks Add links back from footnotes.
FootnoteNoHRTag Omit the horizontal rule before footnotes.
Smartypants Enable smart punctuation.
SmartypantsFractions, SmartypantsDashes, SmartypantsLatexDashes, SmartypantsAngledQuotes, SmartypantsQuotesNBSP Tune smart punctuation.
TOC Generate a table of contents.
LazyLoadImages Add loading="lazy" to images.

Unknown option keys are ignored.

tpl

render(template, variables)

Renders a string or Buffer with Plush and returns a string:

import { render } from "tpl"
return render("Hello <%= name %>", { name: "Ada" })

<%= expression %> emits escaped output; <% statement %> executes control flow without output. Syntax and missing-variable errors throw.

fasttpl

compile(template, params, config?)

Replaces tagged placeholders and returns a string:

import { compile } from "fasttpl"
compile("Hello {{name}}", { name: "Ada" })

Values may be strings or zero-argument functions returning strings. Unknown tags remain unchanged. config.startTag and config.endTag change delimiters; defaults are {{ and }}.

yaml

  • parse(src: string | Buffer): any — parse one YAML document; malformed YAML throws.
  • stringify(value, options?): string — serialize a value and include a trailing newline. options.indent is a positive number and defaults to 2. Function-valued and symbol-keyed properties are omitted.

Globals

console

  • console.log(...data) and console.info(...data) — info log;
  • console.warn(...data) — warning;
  • console.error(...data) — error;
  • console.dump(...data) — pretty-print JSON-like values at info level.

Buffer

A Node-compatible Buffer subset is global. Common static methods are:

  • Buffer.from(string | array | ArrayBuffer, encoding?);
  • Buffer.alloc(size, fill?, encoding?);
  • Buffer.concat(buffers, totalLength?);
  • Buffer.isBuffer(value) and Buffer.isEncoding(name);
  • Buffer.byteLength(value, encoding?) and Buffer.compare(a, b).

Instances provide write, toString, equals, numeric reads (readUInt*, readInt*, readBigInt*, readFloat*, readDouble*) and matching numeric writes. UInt/Uint aliases are available. Endian-specific methods use LE or BE.

Supported general encodings are utf8, utf-8, base64, base64url, and hex. Buffer.from() and buffer.toString() additionally accept latin1 and binary.

Base64

  • atob(input): string — decode base64 to Latin-1 code points;
  • btoa(input): string — encode Latin-1; throws for characters above 0xff.

URL

URL supports construction with an optional base; mutable hash, host, hostname, href, password, pathname, port, protocol, search, and username; read-only origin and searchParams; and toString()/toJSON().

URLSearchParams provides append, delete, entries, forEach, get, getAll, has, keys, set, sort, toString, values, size, and iteration.

Current declarations also mention domainToASCII and domainToUnicode, but the runtime only installs URL and URLSearchParams as globals. Do not depend on those domain helpers.

Not available

Do not assume a full browser or Node environment. In particular, use the Falz modules instead of global fetch, Node's writable fs, process, or worker APIs. An unknown runtime require() returns undefined and logs a warning; npm imports should have been bundled before runtime.