{"id":15287010,"url":"https://github.com/josh-hemphill/subslate","last_synced_at":"2025-06-30T10:33:25.664Z","repository":{"id":38173680,"uuid":"334038777","full_name":"josh-hemphill/subslate","owner":"josh-hemphill","description":"A configurable template string replacement library for Node.js, web, and Deno","archived":false,"fork":false,"pushed_at":"2025-01-31T20:50:32.000Z","size":285,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"latest","last_synced_at":"2025-06-15T22:07:45.716Z","etag":null,"topics":["deno","nodejs","parser","string-manipulation","template"],"latest_commit_sha":null,"homepage":"","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/josh-hemphill.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-01-29T04:37:19.000Z","updated_at":"2024-04-19T02:38:06.000Z","dependencies_parsed_at":"2024-09-30T15:20:33.089Z","dependency_job_id":"b2a97bea-980d-4b64-8159-77da4bdcd00f","html_url":"https://github.com/josh-hemphill/subslate","commit_stats":{"total_commits":25,"total_committers":3,"mean_commits":8.333333333333334,"dds":0.24,"last_synced_commit":"a92964b91b6f9deca8aac7caf9bdee7c54fc2e4e"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/josh-hemphill/subslate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josh-hemphill%2Fsubslate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josh-hemphill%2Fsubslate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josh-hemphill%2Fsubslate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josh-hemphill%2Fsubslate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/josh-hemphill","download_url":"https://codeload.github.com/josh-hemphill/subslate/tar.gz/refs/heads/latest","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josh-hemphill%2Fsubslate/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262756303,"owners_count":23359495,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["deno","nodejs","parser","string-manipulation","template"],"created_at":"2024-09-30T15:20:18.846Z","updated_at":"2025-06-30T10:33:25.618Z","avatar_url":"https://github.com/josh-hemphill.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# subslate\n\nA configurable template string replacement library for Node.js, web, and Deno\n\n\u003cbr /\u003e\n\n\u003c!-- cspell: disable bracketsstartstop --\u003e\n\n[![version](https://img.shields.io/github/v/tag/josh-hemphill/subslate?sort=semver\u0026style=flat-square)](https://github.com/josh-hemphill/subslate/releases)\n[![NPM](https://img.shields.io/static/v1?label=\u0026message=NPM\u0026color=informational\u0026style=flat-square)](https://npmjs.org/package/subslate)\n[![Deno](https://img.shields.io/static/v1?label=\u0026message=Deno\u0026color=informational\u0026style=flat-square)](https://deno.land/x/subslate/mod.ts)\n[![API doc](https://img.shields.io/static/v1?label=Deno\u0026message=API-Doc\u0026color=informational\u0026style=flat-square)](https://doc.deno.land/https/deno.land/x/subslate/mod.ts)\n\u003c!-- [![docs](https://img.shields.io/static/v1?label=\u0026message=Docs\u0026color=informational\u0026style=flat-square)](https://josh-hemphill.github.io/subslate/#/) --\u003e\n[![Build Status](https://img.shields.io/travis/josh-hemphill/subslate.svg?style=flat-square)](https://travis-ci.org/josh-hemphill/subslate)\n[![Codecov](https://img.shields.io/codecov/c/github/josh-hemphill/subslate.svg?style=flat-square)](https://codecov.io/gh/josh-hemphill/subslate)\n[![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/npm/subslate?label=Deps\u0026style=flat-square)](https://libraries.io/npm/subslate)\n[![Rate on Openbase](https://badges.openbase.io/js/rating/subslate.svg)](https://openbase.io/js/subslate?utm_source=embedded\u0026utm_medium=badge\u0026utm_campaign=rate-badge)\n\n## Install\n\n### Node.js \u0026 Browser\n\n```bash\nnpm install subslate\n```\n\n```js\n/* ES Module / Typescript */ import { subslate } from \"subslate\";\n/* CommonJS */ const { subslate } = require(\"subslate\");\n```\n\n### Deno\n\n```js\nimport subslate from \"https://deno.land/x/subslate/mod.ts\"\n```\n\n### Import in HTML\n\n```html\n\u003cscript type=\"text/javascript\" src=\"dist/subslate.js\"\u003e\u003c/script\u003e \u003c!-- For UMD module --\u003e\n\u003cscript type=\"text/javascript\" src=\"dist/subslate.poly.iife.js\"\u003e\u003c/script\u003e \u003c!-- For global IIFE with polyfills --\u003e\n\u003cscript type=\"module\" src=\"dist/subslate.esm.js\"\u003e\u003c/script\u003e \u003c!-- For ES Module --\u003e\n```\n\n### From CDN\n\n```html\n\u003cscript type=\"text/javascript\" src=\"https://unpkg.com/subslate\"\u003e\u003c/script\u003e\n```\n\n## Examples\n\nFor a full list see the [examples directory](./example/) (coming)\n\n### Play with it\n\n[CodePen (suggested)](##) (coming soon)\n\n[JSFiddle](##) (coming soon)\n\n## Usage\n\nCreate a template with any kind of start and stop characters and configurable object path indicators; or by default just use JS style template characters (don't forget to escape them in a JS template if you want them there to replace later)\n\n### Basic Usage\n\n```js\nimport { subslate } from \"subslate\";\n\nconst template = '${A} world ${x[\"y\"].0.z}'\n\nconst context = {A: 'hi', x:{y:[{z:', hello'}]}}\n\nconst compiled = subslate(template,context)\n\ncompiled === 'hi world, hello'\n```\n\n## Options\n\n`subslate(template,context,options)`\n\n  - [`options.startStopPairs`: `string | (string | [string, string])[]`](#with-custom-bracketsstartstop)\n  - [`options.escapeSep`: `{[K in 'json' | 'html' | 'url' | 'js']?: boolean`](#with-escaped-object-property-indicators)\n  - [`options.allowUnquotedProps`: `boolean`](#with-root-and-unquoted-brackets)\n  - [`options.allowRootBracket`: `boolean`](#with-root-and-unquoted-brackets)\n  - [`options.sanitizer`: `(v: SanitizerOptions) =\u003e string`](#with-sanitizer)\n  - `options.maxNameLength`: `number` (maximum character length between start and stop)\n\n### With Custom Brackets/Start-Stop\n\n```js\nimport { subslate } from \"subslate\";\n\nconst template = `\nSELECT * FROM ![tables.table]\n`\nconst context = {tables: {table: 'myTable'}}\n\nconst compiled = subslate(template,context,{\n  startStopPairs: ['![',']']\n  // startStopPairs gets normalized to an array of pairs, so\n  // ['![',']'] gets turned into [['![',']']]\n  // and '||' would get turned into [['||','||']]\n  // or even mixed ['||',['${','}']] = [['||','||'],['${','}']]\n})\ncompiled === `\nSELECT * FROM myTable\n`\n```\n\n### With Escaped Object Property Indicators\n\n```js\nimport { subslate } from \"subslate\";\n\nconst template = `\n\u003cp\u003e\n  \u003c% x%5B%22y%22%5D\\\\u2E0\u0026period;z %\u003e\n\u003c/p\u003e\n`\n\nconst context = {x:{y:[{z:'hello'}]}}\n\nconst compiled = subslate(template,context,{\n  startStopPairs: ['\u003c%','%\u003e'],\n  escapeSep: {\n    json: true\n    html: true\n    url: true\n    js: true\n  }\n})\ncompiled === `\n\u003cp\u003e\n  hello\n\u003c/p\u003e\n`\n```\n\n### With Sanitizer\n\nThe sanitizer recieves all errors and empty fields as well as successful values. So you have a chance to to correct how you want the final string to be injected. A sanitizer must allways return a string, otherwise the library throws an error.\n\n```ts\nimport { subslate } from \"subslate\";\n\nconst template = 'SELECT * FROM ${myTable}${blabla}'\nconst context = {myTable:'hello'}\n\ntype SanitizerOptions = {\n  // If there was no characters between the start and stop\n  isEmpty: boolean,\n\n  // The full id that was between start and stop\n  id: string,\n\n  // The index in the id where parsing stopped if there was a problem\n  at?: number,\n\n  // The value that was successfully found for a givin id\n  value?: unknown,\n}\n\nfunction sanitizer: string (opts: SanitizerOptions) {\n  if (opts.isEmpty || opts.at !== undefined) return ''; // to silence errors from resulting in the stringified \"undefined\" being injected.\n  return opts.value;\n}\n\nconst compiled = subslate(template,context,{sanitizer})\ncompiled === 'SELECT * FROM hello'\n```\n\n### With Root and Unquoted Brackets\n\n```js\nimport { subslate } from \"subslate\";\n\nconst template = `\n\u003cp\u003e\n  \u003c% [x].y %\u003e\n\u003c/p\u003e\n`\n\nconst context = {x:{y:'hello'}}\n\nconst compiled = subslate(template,context,{\n  startStopPairs: ['\u003c%','%\u003e'],\n  allowUnquotedProps: true\n  allowRootBracket: true\n})\ncompiled === `\n\u003cp\u003e\n  hello\n\u003c/p\u003e\n`\n```\n\n\u003c!-- markdownlint-disable-next-line--\u003e\n## Reademe rewrite in progress...\n\n## Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjosh-hemphill%2Fsubslate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjosh-hemphill%2Fsubslate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjosh-hemphill%2Fsubslate/lists"}