Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rjz/ts-mustache
Infer TypeScript types from Mustache templates
https://github.com/rjz/ts-mustache
Last synced: about 2 months ago
JSON representation
Infer TypeScript types from Mustache templates
- Host: GitHub
- URL: https://github.com/rjz/ts-mustache
- Owner: rjz
- License: isc
- Created: 2023-07-29T19:00:05.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-08-03T14:18:30.000Z (5 months ago)
- Last Synced: 2024-11-02T00:50:24.340Z (about 2 months ago)
- Language: TypeScript
- Size: 125 KB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# ts-mustache
[Mustache][mustache] is a pretty good templating libary, but it doesn't play
well with TypeScript. `ts-mustache` makes it better, adding:1. type inference from existing Mustache templates
2. facilities for declaring types and rendering templates## Test
```sh
$ npm i
$ npm test
```## Usage
```ts
import { DefaultLoader, Declarer, Renderer } from 'ts-mustache'const loader = new DefaultLoader({
dir: './templates',
})// Generate typedefs
const declarer = new Declarer(loader)
declarer.declare()
.then(types => fs.writeFileSync('./mustacheTypes.ts', types)
```### CLI
The same behavior is also available via a small CLI:
```sh
ts-mustache --dir=./templates -o ./templates/types.ts
```### Rendering typed templates
Once types exist in a `TemplateMap`, the `Renderer` class provides a convenient
way to use them:```ts
import { TemplateMap } from './mustacheTypes'const loader = new DefaultLoader({
dir: './templates',
})const renderer = new Renderer(loader)
renderer.render('post', { title: 'Foobar' })
.then(rendered => console.log(rendered))
```## Philosophy
Mustache goes to heroic efforts to resolve and/or handle missing data at
runtime, recursing through previously-seen context to attempt to fill in
references with _something_. Further, a template like `{{ name }}` implies that
a variable called `name` is expected, but nothing about its type (integer?
string? vegetable? mineral?) or nullability. Clearly, indeterminate behavior
makes inference a challenge.The `Declarer` class in this library attempts an imperfect balancing act between
overly-restrictive and so-broad-as-to-be-functionally-useless type declarations
based on the [Mustache spec][mustache] and common usage patterns seen in the
wild.Using `ts-mustache` with an existing template library is likely to turn
up some cases where types can't be neatly inferred.```
{{#items.length}}
- {{name}}
{{#items}}
{{/items}}
{{/items.length}}
```
A JavaScript programmer will easily recognize that the `{{ items }}` referenced
in the template likely correspond to an array, and that the template is using
type coercion from `items.length` to skip rendering an empty array.
This library isn't that smart.
Fortunately, most of these cases can be resolved by tweaking how data are
prepared--and type-checking will make these changes relatively safe to enact!
```ts
const templateData = {
arr: items.length ? items : undefined
}
```
```
{{#arr}}
- {{name}}
{{#items}}
{{/items}}
{{/arr}}
```
There are likely many other cases that can/should be resolved by this library,
too--if you find one, please [submit an issue or pull request][contributing]!
## License
ISC
[mustache]: http://mustache.github.io/mustache.5.html
[contributing]: ./CONTRIBUTING.md