ProvenPin Install

mustache sections, partials and HTML escaping: working versions (tested 2026-10-16)

Render mustache templates with nested and inverted sections, partials and escaped vs unescaped output, asserting that user content is HTML-escaped by default offline.

passed4 passed · 0 failed2026-10-16 02:18 UTC
Status
passed
Last passed
2026-10-16 02:18 UTC
Tests
4 / 4
Language
TypeScript
Runtime
node v22.23.3
pinned versions4
mustache@4.2.0@types/mustache@4.2.6@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38839686104

The code

Exactly the files that passed. Your agent can pull them with get_recipe("mustache-html-escape") (install), or see them on GitHub.

package.json
{
  "name": "mustache-html-escape",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --import tsx --test test/*.test.ts"
  },
  "dependencies": {
    "mustache": "4.2.0"
  },
  "devDependencies": {
    "@types/mustache": "4.2.6",
    "@types/node": "26.6.5",
    "tsx": "4.23.15"
  }
}
src/render.ts
import Mustache from "mustache";

export type Part = { label: string };
export type Item = { name: string; qty: number; parts: Part[] };

export type OrderView = {
  customer: string;
  items: Item[];
  comments: string[];
};

const templates = {
  order: [
    "Hi {{customer}},",
    "{{#items}}",
    "- {{name}} x{{qty}}",
    "{{#parts}}",
    "  * {{label}}",
    "{{/parts}}",
    "{{/items}}",
    "{{^items}}",
    "No items.",
    "{{/items}}",
    "{{#comments}}",
    "> {{.}}",
    "{{/comments}}",
    "{{^comments}}",
    "No comments.",
    "{{/comments}}",
    "{{> signature}}",
  ].join("\n"),
  signature: "-- {{customer}}",
};

export function renderOrder(view: OrderView): string {
  return Mustache.render(templates.order, view, {
    signature: templates.signature,
  });
}

export function renderEscaped(value: string): string {
  return Mustache.render("{{value}}", { value });
}

export function renderTriple(value: string): string {
  return Mustache.render("{{{value}}}", { value });
}

export function renderAmpersand(value: string): string {
  return Mustache.render("{{&value}}", { value });
}
test/render.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import {
  renderOrder,
  renderEscaped,
  renderTriple,
  renderAmpersand,
  type OrderView,
} from "../src/render.ts";

const view: OrderView = {
  customer: "Ada",
  items: [
    { name: "Widget", qty: 2, parts: [{ label: "bolt" }, { label: "nut" }] },
    { name: "Gadget", qty: 1, parts: [] },
  ],
  comments: ["first", "second"],
};

test("renders nested sections and a partial", () => {
  const out = renderOrder(view);
  assert.match(out, /Hi Ada,/);
  assert.match(out, /- Widget x2/);
  assert.match(out, / {2}\* bolt/);
  assert.match(out, / {2}\* nut/);
  assert.match(out, /- Gadget x1/);
  assert.match(out, /-- Ada/);
});

test("inverted sections render for empty collections", () => {
  const out = renderOrder({ customer: "Ada", items: [], comments: [] });
  assert.match(out, /No items\./);
  assert.match(out, /No comments\./);
});

test("escapes user content by default", () => {
  const value = "<script>alert('x')</script>";
  assert.equal(
    renderEscaped(value),
    "&lt;script&gt;alert(&#39;x&#39;)&lt;&#x2F;script&gt;",
  );
});

test("triple and ampersand allow unescaped output", () => {
  const value = "<b>bold</b> & <i>italic</i>";
  assert.equal(renderTriple(value), value);
  assert.equal(renderAmpersand(value), value);
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.