Skip to content

Commit e8e6bd9

Browse files
committed
feat: new template system
BREAKING CHANGES: - Omit {{author_full}} in favor of {{contact}}
1 parent 1d5f8a1 commit e8e6bd9

File tree

13 files changed

+85
-40
lines changed

13 files changed

+85
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Edit files inside `templates/default`. Text files will be passed through Mustach
4444
- `{{description}}` package description
4545
- `{{author}}` author name
4646
- `{{email}}` author email
47-
- `{{author_full}}` author name formatted with `{{name}} <{{email}}>` if email given, otherwise `{{name}}`
47+
- `{{contact}}` author name formatted with `{{name}} <{{email}}>` if email given, otherwise `{{name}}`
4848
- `{{license}}` package license (e.g. `MIT`)
4949
- `{{year}}` current year (e.g. `2020`)
5050

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,16 @@
1111
},
1212
"dependencies": {
1313
"@types/inquirer": "^6.5.0",
14-
"@types/mustache": "^0.8.32",
1514
"@types/yargs-interactive": "^2.1.0",
1615
"chalk": "^2.4.2",
1716
"cross-spawn": "^7.0.0",
1817
"execa": "^2.0.5",
1918
"gitconfig": "^2.0.8",
2019
"globby": "^10.0.1",
20+
"handlebars": "^4.4.2",
2121
"inquirer": "^7.0.0",
2222
"is-utf8": "^0.2.1",
2323
"license.js": "^3.1.2",
24-
"mustache": "^3.1.0",
2524
"yargs-interactive": "^3.0.0"
2625
},
2726
"devDependencies": {

src/index.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,26 @@ import {makeLicenseSync, availableLicenses} from 'license.js';
99

1010
import {copy, getAvailableTemplates} from './template';
1111

12-
export interface Config {
13-
packageDir: string;
14-
templateDir: string;
15-
view: View;
16-
}
17-
1812
export interface View {
13+
name: string;
14+
description: string;
1915
author: string;
2016
email: string;
21-
description: string;
17+
contact: string;
2218
license: string;
2319
[key: string]: string | number | boolean | any[];
2420
}
2521

22+
export interface Config {
23+
packageDir: string;
24+
templateDir: string;
25+
view: View;
26+
}
27+
2628
export interface Options {
2729
extra?: Option;
2830
caveat?: string;
31+
after?: () => void;
2932
}
3033

3134
async function getGitUser() {
@@ -67,7 +70,7 @@ async function initGit(root: string) {
6770
await execa('git init', {shell: true, cwd: root});
6871
}
6972

70-
function authorString(author: string, email?: string) {
73+
function getContact(author: string, email?: string) {
7174
return `${author}${email ? ` <${email}>` : ''}`;
7275
}
7376

@@ -153,7 +156,7 @@ export async function create(
153156

154157
const templateDir = path.resolve(templateRoot, args.template);
155158
const year = new Date().getFullYear();
156-
const author_full = authorString(args.author, args.email);
159+
const contact = getContact(args.author, args.email);
157160

158161
if (!fs.existsSync(templateDir)) {
159162
throw new Error('No template found');
@@ -173,7 +176,7 @@ export async function create(
173176
...filterdArgs,
174177
name,
175178
year,
176-
author_full,
179+
contact,
177180
};
178181

179182
// copy files from template
@@ -189,7 +192,7 @@ export async function create(
189192
year,
190193
project: name,
191194
description: args.description,
192-
organization: authorString(args.author, args.email),
195+
organization: getContact(args.author, args.email),
193196
});
194197
const licenseText = license.header + license.text + license.warranty;
195198
fs.writeFileSync(path.resolve(packageDir, 'LICENSE'), licenseText);

src/template.ts

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,59 @@ import fs from 'fs';
22
import path from 'path';
33
import globby from 'globby';
44
import isUtf8 from 'is-utf8';
5-
import Mustache from 'mustache';
5+
import Handlebars from 'handlebars';
66
import {Config} from '.';
77

8+
function trim(text: string) {
9+
return text.replace(/[\r\n]/g, '');
10+
}
11+
Handlebars.registerHelper('trim', trim);
12+
13+
function upper(text: string) {
14+
return trim(text).toUpperCase();
15+
}
16+
Handlebars.registerHelper('upper', upper);
17+
18+
function lower(text: string) {
19+
return trim(text).toLowerCase();
20+
}
21+
Handlebars.registerHelper('lower', lower);
22+
23+
function capital(text: string, options?: any) {
24+
const space = options && options.hash && options.hash.space;
25+
return trim(text)
26+
.split(/[-_\s]+/)
27+
.map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())
28+
.join(space ? ' ' : '');
29+
}
30+
Handlebars.registerHelper('capital', capital);
31+
32+
function camel(text: string) {
33+
return capital(text).replace(/^./, (s) => s.toLowerCase());
34+
}
35+
Handlebars.registerHelper('camel', camel);
36+
37+
function snake(text: string) {
38+
return capital(text)
39+
.replace(/(?<=([a-z](?=[A-Z])|[A-Za-z](?=[0-9])))(?=[A-Z0-9])/g, '_')
40+
.toLowerCase();
41+
}
42+
Handlebars.registerHelper('snake', snake);
43+
44+
function kebab(text: string) {
45+
return snake(text).replace(/_/g, '-');
46+
}
47+
Handlebars.registerHelper('kebab', kebab);
48+
49+
function format<T>(text: Buffer | string, view: T) {
50+
const template = Handlebars.compile(text.toString());
51+
return template(view);
52+
}
53+
854
function prepareDirectory(filePath: string) {
955
try {
10-
fs.mkdirSync(path.dirname(filePath), {recursive: true});
56+
const target = path.dirname(filePath);
57+
fs.mkdirSync(target, {recursive: true});
1158
} catch {}
1259
}
1360

@@ -19,16 +66,16 @@ export async function copy(args: Config) {
1966
const templateFiles = await globby(args.templateDir, {dot: true});
2067
for (const sourcePath of templateFiles) {
2168
const relativePath = path.relative(args.templateDir, sourcePath);
22-
const targetPath = path.resolve(args.packageDir, relativePath);
23-
69+
const targetPath = format(
70+
path.resolve(args.packageDir, relativePath),
71+
args.view,
72+
);
2473
prepareDirectory(targetPath);
2574

2675
let sourceData = fs.readFileSync(sourcePath);
2776
let targetData = sourceData;
2877
if (isUtf8(sourceData)) {
29-
targetData = Buffer.from(
30-
Mustache.render(sourceData.toString(), args.view),
31-
);
78+
targetData = Buffer.from(format(sourceData, args.view));
3279
}
3380
fs.writeFileSync(targetPath, targetData, 'utf-8');
3481
}

templates/default/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# {{name}}
1+
# {{capital name space=true}}
22

33
> {{description}}
44
55
## Usage
66

77
```bash
8-
npx {{name}} <name>
8+
npx {{kebab name}} <name>
99
```

templates/default/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
2-
"name": "{{name}}",
2+
"name": "{{kebab name}}",
33
"description": "{{description}}",
44
"version": "0.0.0",
55
"dependencies": {
66
"create-whatever": "^3.0.0"
77
},
8-
"author": "{{author_full}}",
8+
"author": "{{contact}}",
99
"license": "{{license}}",
1010
"bin": "src/cli.js",
1111
"files": [

templates/default/src/cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ const caveat = `This is a caveat!
88
You can find this section in "src/cli.ts".
99
`;
1010

11-
create('{{name}}', templateRoot, {caveat});
11+
create('{{kebab name}}', templateRoot, {caveat});
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
{{=<% %>=}}
2-
# {{name}}
1+
# \{{name}}
32

4-
{{description}}
5-
<%={{ }}=%>
3+
\{{description}}

templates/typescript/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# {{name}}
1+
# {{capital name space=true}}
22

33
> {{description}}
44
55
## Usage
66

77
```bash
8-
npx {{name}} <name>
8+
npx {{kebab name}} <name>
99
```

templates/typescript/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "{{name}}",
2+
"name": "{{kebab name}}",
33
"description": "{{description}}",
44
"version": "0.0.0",
55
"scripts": {
@@ -13,7 +13,7 @@
1313
"shx": "^0.3.2",
1414
"typescript": "^3.6.3"
1515
},
16-
"author": "{{author_full}}",
16+
"author": "{{contact}}",
1717
"license": "{{license}}",
1818
"bin": "dist/cli.js",
1919
"files": [

0 commit comments

Comments
 (0)