Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5.0 preparation #48

Merged
merged 5 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 241 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@

> 🔀 Replace {{ variables }} in all your files

[![Build status](https://travis-ci.org/gsandf/template-file.svg?branch=master)](https://travis-ci.org/gsandf/template-file)
[![Greenkeeper badge](https://badges.greenkeeper.io/gsandf/template-file.svg)](https://greenkeeper.io/)

Use variables to replace template strings in any type of file.
Use variables to replace template strings in any type of file. This is both a runnable command-line application and JavaScript/TypeScript module.

**✨ Some helpful features:**

- If you use a JavaScript file as the `dataFile` argument, whatever object the JS exports is used for replacement.
- If the value of one of the keys is a function, the result of that function is used for replacement.
- Deeply-nested keys can be used for replacements.

**⚠️ NOTE:** Keys with a period in the name will not be resolved. `{{ user.name }}` will look for `{ user: { name: '' }}` but not `{ 'user.name': ''}`. This would be easy to change, but we're leaving as-is for now for slightly better replacement performance (please open an issue if you would like the other behavior).
- If you use a JavaScript file as the `dataFile` argument, whatever object the JS exports is used for replacement.
- If the value of one of the keys is a function, the result of that function is used for replacement.
- Deeply-nested keys can be used for replacements.

## Usage

Expand All @@ -27,10 +22,10 @@ template-file <dataFile> <sourceGlob> <destination>
- **sourceGlob** - Files to process; see [glob](https://npmjs.com/glob) for syntax
- **destination** - Destination directory where processed files go

### Examples

**ℹ️ TIP:** Remember to place quotes around your arguments (if they contain asterisks, question marks, etc.) to keep your shell from expanding globs before `template-file` gets to consume them.

### Examples

Just handle one file:

```shell
Expand All @@ -49,52 +44,261 @@ Compile all HTML files in `src/` to `dist/` using the exported result of a JavaS
template-file retrieveData.js 'src/**/*.html' './dist'
```

## Templates

This uses templates similar to [mustache](https://mustache.github.io/) templates, but there are some differences.

Anything between `{{` and `}}` can be replaced with a value. Spacing doesn't matter.

```js
const template = '{{ location.name }} is {{adjective}}.';
const data = {
location: { name: 'Nashville' },
adjective: 'cool'
};

render(template, data); //» 'Nashville is cool.'
```

To render a list of items, you can use `{{#example}}` and `{{/example}}`. Empty lists and falsy values aren't rendered:

```js
const template = `
<h3>Friend List:</h3>
<ul>
{{#friends}}
<li>{{name}}</li>
{{/friends}}
</ul>
`;

const data = {
friends: [{ name: 'Amanda' }, { name: 'Bryson' }, { name: 'Josh' }]
};

render(template, data);
// <h3>Friend List:</h3>
// <ul>
// <li>Amanda</li>
// <li>Bryson</li>
// <li>Josh</li>
// </ul>
```

If you have an array of primitive values instead of objects, you can use `{{ this }}` to refer to the current value:

```js
const template = `
### Foods I Like

{{#foods}}
- {{ this }}
{{/foods}}
`;

const data = {
foods: ['steak', 'eggs', 'avocado']
};

render(template, data);
// ### Foods I Like
//
// - steak
// - eggs
// - avocado
```

If a replacement is a function, it is called with no arguments:

```js
const template = `Hello, {{name}}`;

const data = {
name: () => 'Charles'
};

render(template, data); //» Hello, Charles
```

## API

In addition to the CLI, this module exports several helpers to programmatically render templates.

**Example:**

```js
const { renderString, renderTemplateFile } = require('template-file')
import { render, renderFile } from 'template-file';

const data = {
location: {
name: 'Nashville'
},
location: { name: 'Nashville' },
adjective: 'cool'
}
};

// Replace variables in string
renderString('{{ location.name }} is {{ adjective }}.', data) // 'Nashville is cool.'
render('{{ location.name }} is {{ adjective }}.', data); //» 'Nashville is cool.'

// Replace variables in a file
renderTemplateFile('/path/to/file', data)
.then(renderedString => console.log(renderedString)) // same as above, but from file
// Replace variables in a file (same as above, but from a file)
const string = await renderFile('/path/to/file', data);
console.log(renderedString);
```

## Install
### `render`

With either [Yarn](https://yarnpkg.com/) or [npm](https://npmjs.org/) installed, run **one** of the following:
**Type:**

```shell
# If using Yarn, add to project:
yarn add template-file
```ts
function render(template: string, data: Data): string;
```

# ...or install as development dependency:
# (use this command if you're using `template-file` to build your project)
yarn add --dev template-file
Replaces values from `data` and returns the rendered string.

# ...*or* install globally to use anywhere:
yarn global add template-file
```ts
import { render } from 'template-file';

# If using npm, add to project:
npm install --save template-file
const data = {
location: { name: 'Nashville' },
adjective: 'cool'
};

# ...or install as development dependency:
# (use this command if you're using `template-file` to build your project)
npm install --save-dev template-file
render('{{ location.name }} is {{ adjective }}.', data); //» 'Nashville is cool.'
```

### `renderFile`

**Type:**

```ts
function renderFile(filepath: string, data: Data): Promise<string>;
```

Reads a file replaces values from `data`, and returns the rendered string.

```ts
import { renderFile } from 'template-file';

// example.html:
// <h1>Welcome back, {{ sites.github.username }}!</h1>

const data = {
name: 'Blake',
sites: {
github: {
username: 'blakek'
}
}
};

renderFile('./example.html', data); //» '<h1>Welcome back, blakek!</h1>'
```

### `renderGlob`

**Type:** (note, this may change in a future major version release)

```ts
function renderGlob(
sourceGlob: string,
data: Data,
onFileCallback: (filename: string, contents: string) => void
): Promise<void>;
```

Finds files matching a glob pattern, reads those files, replaces values from `data`, and calls a function for each file. Note, no string is returned from the function; values are handled through callbacks for each file.

```ts
import { renderGlob } from 'template-file';

// ./templates/profile.html:
// <h1>Welcome back, {{ name }}!</h1>

// ./templates/sign-in.html:
// <p>Currently signed in as <em>{{ sites.github.username }}<em>.</p>

const data = {
name: 'Blake',
sites: {
github: {
username: 'blakek'
}
}
};

const files = [];

renderGlob('./templates/*.html', data, (filename, contents) => {
files.push({ filename, contents });
});

console.log(files);
// [
// {
// contents: '<h1>Welcome back, Blake!</h1>',
// filename: './templates/profile.html'
// },
// {
// contents: '<p>Currently signed in as <em>blakek<em>.</p>',
// filename: './templates/sign-in.html'
// }
// ]
```

### `renderToFolder`

**Type:**

# ...*or* install globally to use anywhere:
npm install --global template-file
```ts
function renderToFolder(
sourceGlob: string,
destination: string,
data: Data
): Promise<void>;
```

```ts
import { renderToFolder } from 'template-file';

const data = {
name: 'Blake',
sites: {
github: {
username: 'blakek'
}
}
};

renderToFolder('./templates/*.html', './dist/', data);
```

Finds files matching a glob pattern, reads those files, replaces values from `data`, and writes a file with the same name to `destination`.

### Upgrading from older versions:

Version 5 renamed some functions to be simpler:

- `renderString` was renamed `render`
- `renderTemplateFile` was renamed `renderFile`
- `renderGlob` and `renderToFolder` were in v4 but were undocumented. The API for `renderGlob` may change in the future, depending on usage.

Versions < 4 could not lookup properties with a dot in the name. This should be possible since version 4. For example, this was not possible before v4.0.0:

```ts
import { render } from 'template-file';

const data = { 'with.dot': 'yep' };

render('Does this work? {{with.dot}}', data);
```

## Install

With either [Yarn](https://yarnpkg.com/) or [npm](https://npmjs.org/) installed, run **one** of the following:

| Task | with Yarn | with npm |
| ---------------------------------------- | ------------------------------- | -------------------------------------- |
| Add this to a project | `yarn add template-file` | `npm install --save template-file` |
| Install this as a development dependency | `yarn add --dev template-file` | `npm install --save-dev template-file` |
| Install this globally | `yarn global add template-file` | `npm install --global template-file` |

## License

MIT
Loading