Skip to content

Commit

Permalink
feat: add mustache templates support
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Apr 13, 2020
1 parent ddea4ff commit 38e8365
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 21 deletions.
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"fast-levenshtein": "^2.0.6",
"fs-extra": "^9.0.0",
"getopts": "^2.2.4",
"mustache": "^4.0.1",
"pluralize": "^8.0.0",
"slash": "^3.0.0"
},
Expand Down
5 changes: 5 additions & 0 deletions src/Contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ export interface GeneratorFileContract {
*/
stub (fileOrContents: string, options?: { raw: boolean }): this

/**
* Instruct to use mustache templating syntax, instead of template literals
*/
useMustache (): this

/**
* The relative path to the destination directory.
*/
Expand Down
13 changes: 11 additions & 2 deletions src/Generator/File.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class GeneratorFile implements GeneratorFileContract {
private templateData: any = {}
private customDestinationPath?: string
private customAppRoot?: string
private mustache: boolean = false

constructor (
private name: string,
Expand Down Expand Up @@ -69,6 +70,14 @@ export class GeneratorFile implements GeneratorFileContract {
return this
}

/**
* Instruct to use mustache
*/
public useMustache () {
this.mustache = true
return this
}

/**
* Variables for stub subsitution
*/
Expand Down Expand Up @@ -127,8 +136,8 @@ export class GeneratorFile implements GeneratorFileContract {
const contents = this.stubContents
? (
this.isStubRaw
? template(this.stubContents, templateContents)
: templateFromFile(this.stubContents, templateContents)
? template(this.stubContents, templateContents, this.mustache)
: templateFromFile(this.stubContents, templateContents, this.mustache)
)
: ''

Expand Down
13 changes: 9 additions & 4 deletions src/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@
* file that was distributed with this source code.
*/

import Mustache from 'mustache'
import { readFileSync } from 'fs'

/**
* Process string as a template literal string and processes
* data
*/
export function template (tpl: string, data: Object) {
export function template (tpl: string, data: Object, isMustache: boolean) {
if (isMustache) {
return Mustache.render(tpl, data)
}

return tpl.replace(/\$\{([a-zA-Z0-9_-]*)}/g, (_, p1: string) => {
if (!(p1 in data)) {
throw new Error(`Missing value for "${p1}"`)
return ''
}
return String(data[p1])
})
Expand All @@ -26,7 +31,7 @@ export function template (tpl: string, data: Object) {
* Loads template file from the disk and process it contents
* using the [[template]] method
*/
export function templateFromFile (file: string, data: object): string {
export function templateFromFile (file: string, data: object, isMustache: boolean): string {
const contents = readFileSync(file, 'utf8')
return template(contents, data)
return template(contents, data, isMustache)
}
1 change: 1 addition & 0 deletions test/fixtures/template1.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello {{value1}}, {{value2}}
35 changes: 20 additions & 15 deletions test/template.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,42 @@ import { join } from 'path'
import { template, templateFromFile } from '../src/utils/template'

test.group('template', () => {
test('template: interpolate valid template', (assert) => {
test('interpolate valid template', (assert) => {
const result = template('${test} ${other}', {
test: 123,
other: 'hello',
})
}, false)
assert.strictEqual(result, '123 hello')
})

test('template: error if a value is missing', (assert) => {
assert.throws(
() => template('${param}', {}),
'Missing value for "param"'
)
test('interpolate template using mustache', (assert) => {
const result = template('{{test}} {{other}}', {
test: 123,
other: 'hello',
}, true)
assert.strictEqual(result, '123 hello')
})
})

test('templateFromFile: interpolate valid template', (assert) => {
test.group('Template From File', () => {
test('interpolate valid template', (assert) => {
const result = templateFromFile(join(__dirname, 'fixtures/template1.txt'), {
value1: 'World',
value2: 42,
})
}, false)

assert.strictEqual(result, 'Hello World, 42')
})

test('templateFromFile: error if a value is missing', (assert) => {
assert.throws(() => templateFromFile(join(__dirname, 'fixtures/template1.txt'), {
value1: 'World',
}), 'Missing value for "value2"')
test('error if file is missing', (assert) => {
assert.throws(() => templateFromFile(join(__dirname, 'fixtures/i-do-not-exist'), {}, false))
})

test('templateFromFile: error if file is missing', (assert) => {
assert.throws(() => templateFromFile(join(__dirname, 'fixtures/i-do-not-exist'), {}))
test('interpolate mustache from template file', (assert) => {
const result = templateFromFile(join(__dirname, 'fixtures/template1.mustache'), {
value1: 'World',
value2: 42,
}, true)
assert.strictEqual(result.trim(), 'Hello World, 42')
})
})

0 comments on commit 38e8365

Please sign in to comment.