Skip to content

Commit ce22a2c

Browse files
committed
disable overwriting files + parse JSON for locals
1 parent 7c0c347 commit ce22a2c

File tree

13 files changed

+132
-79
lines changed

13 files changed

+132
-79
lines changed

README.md

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# simple-scaffold
2+
23
Simple Scaffold allows you to create your structured files based on templates.
34

45
## Install
6+
57
You can either use it as a command line tool or import into your own code and run from there.
68

79
```bash
@@ -15,72 +17,81 @@ yarn [global] add simple-scaffold
1517

1618
### Command Line Options
1719

18-
Scaffold Generator
19-
20-
Generate scaffolds for your project based on file templates.
21-
Usage: simple-scaffold scaffold-name [options]
22-
23-
24-
-n, --name string Component output name
25-
-t, --templates File[] A glob pattern of template files to load.
26-
A template file may be of any type and extension, and supports Handlebars as
27-
a parsing engine for the file names and contents, so you may customize both
28-
with variables from your configuration.
29-
-o, --output File The output directory to put the new files in. They will attempt to maintain
30-
their regular structure as they are found, if possible.
31-
-l, --locals Key=Value[] A key-value map for the template to use in parsing.
32-
-S, --create-sub-folder Boolean Whether to create a subdirectory with {{Name}} in the output directory.
33-
default=true
34-
-h, --help Display this help message
20+
```plaintext
21+
Scaffold Generator
22+
23+
Generate scaffolds for your project based on file templates.
24+
Usage: simple-scaffold scaffold-name [options]
25+
26+
Options
27+
28+
-n, --name string Component output name
29+
-t, --templates File[] A glob pattern of template files to load.
30+
A template file may be of any type and extension, and supports Handlebars as
31+
a parsing engine for the file names and contents, so you may customize both
32+
with variables from your configuration.
33+
-o, --output File The output directory to put the new files in. They will attempt to maintain
34+
their regular structure as they are found, if possible.
35+
-l, --locals Key=Value A key-value map for the template to use in parsing.
36+
-w, --overwrite Boolean Whether to overwrite files when they are found to already exist. default=true
37+
-S, --create-sub-folder Boolean Whether to create a subdirectory with {{Name}} in the output directory.
38+
default=true
39+
-h, --help Display this help message
40+
```
3541

3642
You can add this as a script in your `package.json`:
3743

3844
```json
3945
{
4046
"scripts": {
41-
"scaffold": "node node_modules/simple-scaffold/dist/cmd.js --template scaffolds/component/**/* --output src/components --locals myProp=\"propname\",myVal=123"
47+
"scaffold": "yarn simple-scaffold --template scaffolds/component/**/* --output src/components --locals myProp=\"propname\",myVal=123"
4248
}
4349
}
4450
```
4551

4652
## Scaffolding
53+
4754
Scaffolding will replace {{vars}} in both the file name and its contents and put the transformed files
4855
in `<output>/<{{Name}}>`, as per the Handlebars formatting rules.
4956

5057
Your context will be pre-populated with the following:
58+
5159
- `{{Name}}`: CapitalizedName of the component
5260
- `{{name}}`: camelCasedName of the component
5361

5462
Any `locals` you add in the config will populate with their names wrapped in `{{` and `}}`.
5563
They are all stringified, so be sure to parse them accordingly by creating a script, if necessary.
5664

5765
### Use in Node.js
66+
5867
You can also build the scaffold yourself, if you want to create more complex arguments or scaffold groups.
5968
Simply pass a config object to the constructor, and invoke `run()` when you are ready to start.
6069
The config takes similar arguments to the command line:
6170

6271
```javascript
63-
const SimpleScaffold = require('simple-scaffold').default
72+
const SimpleScaffold = require("simple-scaffold").default
6473

6574
const scaffold = new SimpleScaffold({
66-
name: 'component',
67-
templates: [path.join(__dirname, 'scaffolds', 'component')],
68-
output: path.join(__dirname, 'src', 'components'),
75+
name: "component",
76+
templates: [path.join(__dirname, "scaffolds", "component")],
77+
output: path.join(__dirname, "src", "components"),
6978
createSubFolder: true,
7079
locals: {
71-
property: 'value',
72-
}
80+
property: "value",
81+
},
7382
}).run()
7483
```
7584

7685
The exception in the config is that `output`, when used in Node directly, may also be passed a function for each input file to output into a dynamic path:
86+
7787
```javascript
7888
config.output = (filename, basePath) => [basePath, filename].join(path.sep)
7989
```
8090

8191
## Example Scaffold Input
8292

8393
### Input Directory structure
94+
8495
```
8596
- project
8697
- scaffold
@@ -91,6 +102,7 @@ config.output = (filename, basePath) => [basePath, filename].join(path.sep)
91102
```
92103

93104
#### project/scaffold/{{Name}}.js
105+
94106
```js
95107
const React = require('react')
96108

@@ -102,6 +114,7 @@ module.exports = class {{Name}} extends React.Component {
102114
```
103115

104116
### Run Example
117+
105118
```bash
106119
simple-scaffold MyComponent \
107120
-t project/scaffold/**/* \
@@ -110,7 +123,9 @@ simple-scaffold MyComponent \
110123
```
111124

112125
## Example Scaffold Output
126+
113127
#### Directory structure
128+
114129
```
115130
- project
116131
- src
@@ -121,6 +136,7 @@ simple-scaffold MyComponent \
121136
```
122137

123138
With `createSubfolder = false`:
139+
124140
```
125141
- project
126142
- src
@@ -130,12 +146,13 @@ With `createSubfolder = false`:
130146
```
131147

132148
#### project/scaffold/MyComponent/MyComponent.js
149+
133150
```js
134-
const React = require('react')
151+
const React = require("react")
135152

136153
module.exports = class MyComponent extends React.Component {
137154
render() {
138-
<div className="my-component">MyComponent Component</div>
155+
;<div className="my-component">MyComponent Component</div>
139156
}
140157
}
141158
```

cmd.ts

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,97 @@
1-
import SimpleScaffold from './scaffold'
2-
import * as fs from 'fs'
3-
import {IScaffold} from './index'
4-
import * as cliArgs from 'command-line-args'
5-
import * as cliUsage from 'command-line-usage'
6-
import * as path from 'path'
1+
import SimpleScaffold from "./scaffold"
2+
import * as fs from "fs"
3+
import { IScaffold } from "./index"
4+
import * as cliArgs from "command-line-args"
5+
import * as cliUsage from "command-line-usage"
6+
import * as path from "path"
77

8-
type Def = cliArgs.OptionDefinition & { description?: string, typeLabel?: string }
8+
type Def = cliArgs.OptionDefinition & {
9+
description?: string
10+
typeLabel?: string
11+
}
912

1013
function localsParser(content: string) {
11-
const [key, value] = content.split('=')
12-
return { [key]: value }
14+
return JSON.parse(content)
1315
}
1416

1517
function filePathParser(content: string) {
16-
if (content.startsWith('/')) {
18+
if (content.startsWith("/")) {
1719
return content
1820
}
1921
return [process.cwd(), content].join(path.sep)
2022
}
2123

2224
function booleanParser(text: string) {
23-
return text && text.trim().length ? ['true', '1', 'on'].includes(text.trim()) : true
25+
return text && text.trim().length
26+
? ["true", "1", "on"].includes(text.trim())
27+
: true
2428
}
2529

2630
const defs: Def[] = [
2731
{
28-
name: 'name',
29-
alias: 'n',
32+
name: "name",
33+
alias: "n",
3034
type: String,
31-
description: 'Component output name',
35+
description: "Component output name",
3236
defaultOption: true,
3337
},
3438
{
35-
name: 'templates',
36-
alias: 't',
39+
name: "templates",
40+
alias: "t",
3741
type: filePathParser,
38-
typeLabel: '{underline File}[]',
42+
typeLabel: "{underline File}[]",
3943
description: `A glob pattern of template files to load.\nA template file may be of any type and extension, and supports Handlebars as a parsing engine for the file names and contents, so you may customize both with variables from your configuration.`,
4044
multiple: true,
4145
},
4246
{
43-
name: 'output',
44-
alias: 'o',
47+
name: "output",
48+
alias: "o",
4549
type: filePathParser,
46-
typeLabel: '{underline File}',
50+
typeLabel: "{underline File}",
4751
description: `The output directory to put the new files in. They will attempt to maintain their regular structure as they are found, if possible.`,
4852
},
4953
{
50-
name: 'locals',
51-
alias: 'l',
52-
description: `A key-value map for the template to use in parsing.`,
53-
multiple: true,
54-
typeLabel: '{underline Key=Value}',
54+
name: "locals",
55+
alias: "l",
56+
description: `A JSON string for the template to use in parsing.`,
57+
typeLabel: "{underline JSON string}",
5558
type: localsParser,
5659
},
5760
{
58-
name: 'create-sub-folder',
59-
alias: 'S',
60-
typeLabel: '{underline Boolean}',
61-
description: 'Whether to create a subdirectory with \\{\\{Name\\}\\} in the {underline output} directory. {bold default=true}',
61+
name: "overwrite",
62+
alias: "w",
63+
description: `Whether to overwrite files when they are found to already exist. {bold default=true}`,
64+
type: booleanParser,
65+
typeLabel: "{underline Boolean}",
66+
defaultValue: true,
67+
},
68+
{
69+
name: "create-sub-folder",
70+
alias: "S",
71+
typeLabel: "{underline Boolean}",
72+
description:
73+
"Whether to create a subdirectory with \\{\\{Name\\}\\} in the {underline output} directory. {bold default=true}",
6274
type: booleanParser,
6375
defaultValue: true,
6476
},
6577
{
66-
name: 'help',
67-
alias: 'h',
78+
name: "help",
79+
alias: "h",
6880
type: Boolean,
69-
description: 'Display this help message',
81+
description: "Display this help message",
7082
},
7183
]
7284

7385
const args = cliArgs(defs, { camelCase: true })
7486

7587
const help = [
76-
{ header: 'Scaffold Generator', content: `Generate scaffolds for your project based on file templates.\nUsage: {bold simple-scaffold} {underline scaffold-name} {underline [options]}` },
77-
{ header: 'Options', optionList: defs }
88+
{
89+
header: "Scaffold Generator",
90+
content: `Generate scaffolds for your project based on file templates.\nUsage: {bold simple-scaffold} {underline scaffold-name} {underline [options]}`,
91+
},
92+
{ header: "Options", optionList: defs },
7893
]
7994

80-
args.locals = (args.locals || []).reduce((all: object, cur: object) => ({ ...all, ...cur }), {} as IScaffold.Config['locals'])
8195
if (args.createSubFolder === null) {
8296
args.createSubFolder = true
8397
}
@@ -87,11 +101,12 @@ if (args.help || !args.name) {
87101
process.exit(0)
88102
}
89103

90-
console.info('Config:', args)
104+
console.info("Config:", args)
91105
new SimpleScaffold({
92106
name: args.name,
93107
templates: args.templates,
94108
output: args.output,
95109
locals: args.locals,
96110
createSubfolder: args.createSubFolder,
111+
overwrite: args.overwrite,
97112
}).run()

0 commit comments

Comments
 (0)