{"id":51166415,"url":"https://github.com/shahradelahi/ts-template","last_synced_at":"2026-06-26T19:02:39.099Z","repository":{"id":364997292,"uuid":"1268318026","full_name":"shahradelahi/ts-template","owner":"shahradelahi","description":"⚡ High-performance, async-first templating engine with built-in filters and TypeScript type safety","archived":false,"fork":false,"pushed_at":"2026-06-15T11:06:47.000Z","size":83,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-15T13:07:33.978Z","etag":null,"topics":["async-rendering","compiler","filters","mustache","performance","template-engine","type-safe","typescript"],"latest_commit_sha":null,"homepage":"https://npmjs.com/@se-oss/template","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shahradelahi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-13T11:45:50.000Z","updated_at":"2026-06-15T11:06:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shahradelahi/ts-template","commit_stats":null,"previous_names":["shahradelahi/ts-template"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/shahradelahi/ts-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fts-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fts-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fts-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fts-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shahradelahi","download_url":"https://codeload.github.com/shahradelahi/ts-template/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fts-template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34829415,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async-rendering","compiler","filters","mustache","performance","template-engine","type-safe","typescript"],"created_at":"2026-06-26T19:02:37.661Z","updated_at":"2026-06-26T19:02:39.089Z","avatar_url":"https://github.com/shahradelahi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003csup\u003e@se-oss/template\u003c/sup\u003e\n  \u003cbr\u003e\n  \u003ca href=\"https://github.com/shahradelahi/ts-template/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/shahradelahi/ts-template/actions/workflows/ci.yml/badge.svg?branch=main\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@se-oss/template\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@se-oss/template.svg\" alt=\"NPM Version\"\u003e\u003c/a\u003e\n  \u003ca href=\"/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-blue.svg?style=flat\" alt=\"MIT License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/package/@se-oss/template\"\u003e\u003cimg src=\"https://img.shields.io/bundlephobia/minzip/@se-oss/template\" alt=\"npm bundle size\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://packagephobia.com/result?p=@se-oss/template\"\u003e\u003cimg src=\"https://packagephobia.com/badge?p=@se-oss/template\" alt=\"Install Size\"\u003e\u003c/a\u003e\n\u003c/h1\u003e\n\n_@se-oss/template_ is a high-performance, safe, and highly extensible templating engine supporting Mustache syntax, pipelines, and native asynchronous execution.\n\n## Benefits\n\n- **Performance First:** Automated compiled function caching using a dynamic LRU cache.\n- **Async Architecture:** Native support for asynchronous filters, block iterations, and partial resolution.\n- **Filter Pipelines:** Chainable built-in and custom filters with parameter support.\n- **Fail-Safe Operators:** Integrated nullish coalescing (`??`) and logical OR (`||`) operators.\n- **Whitespace Control:** Automatic standalone tag detection and whitespace slurping.\n- **Type-Level Magic:** Zero-config TypeScript schema inference directly from template string literals.\n- **World-Class Errors:** Informative compiler errors coupled with syntax-highlighted code frames.\n- **Secure by Default:** Active protection preventing prototype pollution and unsafe property access.\n\n---\n\n- [Benefits](#benefits)\n- [Installation](#-installation)\n- [Usage](#-usage)\n- [Migration Guidelines](#-migration-guidelines)\n- [Documentation](#-documentation)\n- [Contributing](#-contributing)\n- [License](#license)\n\n## 📦 Installation\n\n```bash\npnpm add @se-oss/template\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eInstall using your favorite package manager\u003c/summary\u003e\n\n**npm**\n\n```bash\nnpm install @se-oss/template\n```\n\n**yarn**\n\n```bash\nyarn add @se-oss/template\n```\n\n\u003c/details\u003e\n\n## 📖 Usage\n\n### Basic Usage\n\n```ts\nimport { render } from '@se-oss/template';\n\nconst result = render('Hello {{name}}!', { name: 'Shahrad' });\n// Output: Hello Shahrad!\n```\n\n### HTML Escaping \u0026 Raw Outputs\n\nBy default, HTML characters are escaped. Use triple curlies or the ampersand operator to output raw HTML.\n\n```ts\n// Escaped (Default)\nrender('Hello {{name}}', { name: '\u003cb\u003eShahrad\u003c/b\u003e' });\n// Output: Hello \u0026lt;b\u0026gt;Shahrad\u0026lt;\u0026#x2F;b\u0026gt;\n\n// Raw (Triple Curlies)\nrender('Hello {{{name}}}', { name: '\u003cb\u003eShahrad\u003c/b\u003e' });\n// Output: Hello \u003cb\u003eShahrad\u003c/b\u003e\n\n// Raw (Ampersand)\nrender('Hello {{\u0026name}}', { name: '\u003cb\u003eShahrad\u003c/b\u003e' });\n// Output: Hello \u003cb\u003eShahrad\u003c/b\u003e\n```\n\n### Null Coalescing \u0026 Logical Fallbacks\n\nSafely resolve undefined or empty values inside expressions.\n\n```ts\n// Nullish Coalescing (??)\nrender('Hello {{user.nickname ?? user.name ?? \"Guest\"}}', {\n  user: { nickname: null, name: 'Shahrad' },\n});\n// Output: Hello Shahrad\n\n// Logical OR (||)\nrender('Hello {{user.name || \"Guest\"}}', { user: { name: '' } });\n// Output: Hello Guest\n```\n\n### Conditionals\n\nHandle logical flows with standard conditional blocks.\n\n```ts\nconst tpl = '{{#if active}}Active{{else}}Inactive{{/if}}';\n\nrender(tpl, { active: true }); // Output: Active\nrender(tpl, { active: false }); // Output: Inactive\n```\n\n```ts\n// Inverse conditionals using \"unless\"\nrender('{{#unless active}}Inactive{{/unless}}', { active: false });\n// Output: Inactive\n```\n\n### Loops \u0026 Iteration\n\nIterate arrays and objects while exposing index metadata.\n\n```ts\n// Array Iteration\nconst tpl =\n  '{{#each users}}{{this}} (index: {{@index}}, first: {{@first}}, last: {{@last}}){{/each}}';\nrender(tpl, { users: ['A', 'B'] });\n// Output: A (index: 0, first: true, last: false)B (index: 1, first: false, last: true)\n\n// Object Key-Value Iteration\nrender('{{#each user}}{{@key}}: {{.}}, {{/each}}', {\n  user: { name: 'Shahrad', role: 'admin' },\n});\n// Output: name: Shahrad, role: admin,\n```\n\n### Mustache-Style Sections\n\nSeamless generic sections supporting scope-shifting, looping, and inverted fallbacks.\n\n```ts\n// Scope shifting and nested lookup\nconst tpl = '{{#user}}{{name}} is {{role}}{{/user}}';\nrender(tpl, { user: { name: 'Shahrad', role: 'admin' } });\n// Output: Shahrad is admin\n\n// Inverted section (executes if array/value is empty or falsy)\nrender('{{^items}}Empty{{/items}}', { items: [] });\n// Output: Empty\n```\n\n### Built-in \u0026 Custom Filters\n\nChain multiple filters using the pipe syntax.\n\n```ts\n// Built-in pipeline with arguments\nrender('{{name | trim | capitalize | default(\"Guest\")}}', {\n  name: '  shahrad  ',\n});\n// Output: Shahrad\n\n// Custom local filters\nrender('{{name | reverse}}', { name: 'shahrad' }, undefined, {\n  filters: {\n    reverse: (val) =\u003e String(val).split('').reverse().join(''),\n  },\n});\n// Output: darhahs\n```\n\n### Async Resolution\n\nPerfect for rendering templates depending on async API calls or database lookups.\n\n```ts\nimport { renderAsync } from '@se-oss/template';\n\nconst asyncFilter = async (val) =\u003e {\n  return new Promise((resolve) =\u003e\n    setTimeout(() =\u003e resolve(String(val).toUpperCase()), 10)\n  );\n};\n\nawait renderAsync(\n  'Hello {{name | toUpper}}!',\n  { name: 'shahrad' },\n  undefined,\n  {\n    filters: { toUpper: asyncFilter },\n  }\n);\n// Output: Hello SHAHRAD!\n```\n\n### Partials\n\nModularize your templates. Partials compile recursively and resolve dynamically.\n\n```ts\nconst partials = {\n  userCard: 'Name: {{name}} (Role: {{\u003e roleTag}}) | ',\n  roleTag: '\u003cu\u003e{{role}}\u003c/u\u003e',\n};\n\nrender(\n  '{{#each users}}{{\u003e userCard}}{{/each}}',\n  {\n    users: [\n      { name: 'Shahrad', role: 'Admin' },\n      { name: 'Alice', role: 'User' },\n    ],\n  },\n  partials\n);\n// Output: Name: Shahrad (Role: \u003cu\u003eAdmin\u003c/u\u003e) | Name: Alice (Role: \u003cu\u003eUser\u003c/u\u003e) |\n```\n\n#### Async Partial Resolvers\n\nDynamically fetch partials as needed during asynchronous renders.\n\n```ts\nawait renderAsync('Welcome, {{\u003e header}}!', { name: 'Shahrad' }, undefined, {\n  resolvePartial: async (name) =\u003e {\n    return name === 'header' ? '\u003cb\u003e{{name}}\u003c/b\u003e' : '';\n  },\n});\n// Output: Welcome, \u003cb\u003eShahrad\u003c/b\u003e!\n```\n\n### Global Configuration\n\nRegister global options, filters, partials, or strict-mode checks.\n\n```ts\nimport { configure } from '@se-oss/template';\n\nconfigure({\n  strict: true, // Throw error on undefined variables\n  cacheSize: 1000, // Dynamic LRU cache limit\n  filters: {\n    globalUpper: (val) =\u003e String(val).toUpperCase(),\n  },\n  partials: {\n    baseLayout: 'Layout: {{\u003e content}}',\n  },\n});\n```\n\n### TypeScript Typings\n\nAutomatic compile-time schema inference. Your IDE will know the exact fields your template expects.\n\n```ts\nimport { compile } from '@se-oss/template';\n\nconst myTemplate = compile('Hello {{user.name}}, you are {{age}}');\n\n// TypeScript errors if properties are missing or of incorrect types\nmyTemplate({\n  user: { name: 'Shahrad' },\n  age: 25,\n});\n```\n\n### Error Reporting\n\nGet immediate, pinpoint accuracy on compilation and parsing errors.\n\n```ts\ntry {\n  render('Hello {{#if active}}World{{/each}}', { active: true });\n} catch (err) {\n  console.log(err.message);\n}\n/*\nError: Mismatched block end: expected \"if\" but found \"each\"\n  at template:1:21\n\n\u003e 1 | {{#if active}}Hello{{/each}}\n    |                    ^\n*/\n```\n\n## 🚀 Migration Guidelines\n\nMigrating from another template engine? We have detailed step-by-step migration guides to help you transition smoothly:\n\n- [Migrating from mustache.js](migration/mustache.md)\n- [Migrating from Handlebars.js](migration/handlebars.md)\n\n## 📚 Documentation\n\nFor all configuration options, please see [the API docs](https://www.jsdocs.io/package/@se-oss/template).\n\n## 🤝 Contributing\n\nWant to contribute? Awesome! To show your support is to star the project, or to raise issues on [GitHub](https://github.com/shahradelahi/ts-template).\n\nThanks again for your support, it is much appreciated! 🙏\n\n## License\n\n[MIT](/LICENSE) © [Shahrad Elahi](https://github.com/shahradelahi) and [contributors](https://github.com/shahradelahi/ts-template/graphs/contributors).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshahradelahi%2Fts-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshahradelahi%2Fts-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshahradelahi%2Fts-template/lists"}