diff --git a/docs/docs/usage/01-templates.md b/docs/docs/usage/01-templates.md index c29be5a..7b7d4ee 100644 --- a/docs/docs/usage/01-templates.md +++ b/docs/docs/usage/01-templates.md @@ -1,31 +1,40 @@ --- -title: Template Files +title: Templates --- -# Preparing template files +# Templates -Put your template files anywhere, and fill them with tokens for replacement. +Templates are regular files in a directory. Both **file names** and **file contents** support +[Handlebars.js](https://handlebarsjs.com/) syntax for token replacement. -Each template (not file) in the config array is parsed individually, and copied to the output -directory. If a single template path contains multiple files (e.g. if you use a folder path or a -glob pattern), the first directory up the tree of that template will become the base inside the -defined output path for that template, while copying files recursively and maintaining their -relative structure. +## How Templates Are Resolved -Examples: +Each path in the `templates` array is resolved individually. If a path points to a directory or glob +pattern containing multiple files, the first directory up the tree becomes the base path — files are +then copied recursively into `output`, preserving their relative structure. -> In the following examples, the config `name` is `AppName`, and the config `output` is `src`. +> In the examples below, `name` is `AppName` and `output` is `src`. -| Input template | Files in template | Output path(s) | +| Template path | Files found | Output | | ----------------------------- | ------------------------------------------------------ | ------------------------------------------------------------ | | `./templates/{{ name }}.txt` | `./templates/{{ name }}.txt` | `src/AppName.txt` | | `./templates/directory` | `outer/{{name}}.txt`,
`outer2/inner/{{name}}.txt` | `src/outer/AppName.txt`,
`src/outer2/inner/AppName.txt` | | `./templates/others/**/*.txt` | `outer/{{name}}.jpg`,
`outer2/inner/{{name}}.txt` | `src/outer2/inner/AppName.txt` | -## Ignoring files +### Glob Patterns & Exclusions -You can create a `.scaffoldignore` file in your template directory to exclude files from being -copied to the output. It works like `.gitignore` — one pattern per line, comments with `#`. +Template paths support glob patterns and negation with `!`: + +```js +{ + templates: ["templates/component/**", "!templates/component/README.md"] +} +``` + +## Ignoring Files + +Place a `.scaffoldignore` file in your template directory to exclude files. It works like +`.gitignore` — one pattern per line, `#` for comments. ```text # .scaffoldignore @@ -38,120 +47,88 @@ dist/** The `.scaffoldignore` file itself is never copied to the output. Patterns are matched against both the file's basename and its path relative to the template -directory, so `README.md` will match at any depth, while `dist/**` only matches a `dist` directory -at the template root. +directory, so `README.md` matches at any depth while `dist/**` only matches a `dist` directory at +the template root. -## Variable/token replacement +## Token Replacement -Scaffolding will replace `{{ varName }}` in both the file name and its contents and put the -transformed files in the output directory. +Handlebars expressions like `{{ name }}` are replaced in both file names and file contents. The +`name` variable is always available — it's the name you pass when running the scaffold. -The data available for the template parser is the data you pass to the `data` config option (or -`--data` argument in CLI). - -For example, using the following command: +Any additional data from `--data`, `-D`, `data` config, or [inputs](configuration_files#inputs) is +also available. ```bash -npx simple-scaffold@latest \ - --templates templates/components/{{name}}.jsx \ - --output src/components \ - --create-sub-folder true \ +npx simple-scaffold \ + -t templates/component/{{name}}.jsx \ + -o src/components \ MyComponent ``` -Will output a file with the path: +This produces `src/components/MyComponent.jsx`, with all tokens inside the file replaced as well. -```text -/src/components/MyComponent.jsx -``` +All standard Handlebars features work — `{{#if}}`, `{{#each}}`, `{{#with}}`, and more. See +[Handlebars.js Language Features](https://handlebarsjs.com/guide/#language-features) for details. -The contents of the file will be transformed in a similar fashion. +## Built-in Helpers -Your `data` will be pre-populated with the following: +Simple Scaffold includes helpers you can use in templates and file names. Helpers can also be +nested: `{{ pascalCase (snakeCase name) }}`. -- `{{name}}`: raw name of the component as you entered it +### Case Helpers -> Simple-Scaffold uses [Handlebars.js](https://handlebarsjs.com/) for outputting the file contents. -> Any `data` you add in the config will be available for use with their names wrapped in `{{` and -> `}}`. Other Handlebars built-ins such as `each`, `if` and `with` are also supported, see -> [Handlebars.js Language Features](https://handlebarsjs.com/guide/#language-features) for more -> information. +| Helper | Usage | `my name` becomes | +| ------------ | ----------------------- | ----------------- | +| _(none)_ | `{{ name }}` | `my name` | +| `camelCase` | `{{ camelCase name }}` | `myName` | +| `pascalCase` | `{{ pascalCase name }}` | `MyName` | +| `snakeCase` | `{{ snakeCase name }}` | `my_name` | +| `kebabCase` | `{{ kebabCase name }}` | `my-name` | +| `hyphenCase` | `{{ hyphenCase name }}` | `my-name` | +| `startCase` | `{{ startCase name }}` | `My Name` | +| `upperCase` | `{{ upperCase name }}` | `MY NAME` | +| `lowerCase` | `{{ lowerCase name }}` | `my name` | -## Helpers +### Date Helpers -### Built-in Helpers +Both `now` and `date` use [`date-fns`](https://date-fns.org/docs/format) format tokens. -Simple-Scaffold provides some built-in text transformation filters usable by Handlebars. +| Helper | Example | Output | +| -------------------- | ---------------------------------------------------------------- | ------------------- | +| `now` | `{{ now "yyyy-MM-dd HH:mm" }}` | `2042-01-01 15:00` | +| `now` (with offset) | `{{ now "yyyy-MM-dd HH:mm" -1 "hours" }}` | `2042-01-01 14:00` | +| `date` | `{{ date "2042-01-01T15:00:00Z" "yyyy-MM-dd HH:mm" }}` | `2042-01-01 15:00` | +| `date` (with offset) | `{{ date "2042-01-01T15:00:00Z" "yyyy-MM-dd HH:mm" -1 "days" }}` | `2041-12-31 15:00` | +| `date` (from data) | `{{ date myCustomDate "yyyy-MM-dd HH:mm" }}` | _(depends on data)_ | -For example, you may use `{{ snakeCase name }}` inside a template file or filename, and it will -replace `My Name` with `my_name` when producing the final value. - -#### Capitalization Helpers - -| Helper name | Example code | Example output | -| ------------ | ----------------------- | -------------- | -| [None] | `{{ name }}` | my name | -| `camelCase` | `{{ camelCase name }}` | myName | -| `snakeCase` | `{{ snakeCase name }}` | my_name | -| `startCase` | `{{ startCase name }}` | My Name | -| `kebabCase` | `{{ kebabCase name }}` | my-name | -| `hyphenCase` | `{{ hyphenCase name }}` | my-name | -| `pascalCase` | `{{ pascalCase name }}` | MyName | -| `upperCase` | `{{ upperCase name }}` | MY NAME | -| `lowerCase` | `{{ lowerCase name }}` | my name | - -#### Date helpers - -| Helper name | Description | Example code | Example output | -| -------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | ------------------ | -| `now` | Current date with format | `{{ now "yyyy-MM-dd HH:mm" }}` | `2042-01-01 15:00` | -| `now` (with offset) | Current date with format, and with offset | `{{ now "yyyy-MM-dd HH:mm" -1 "hours" }}` | `2042-01-01 14:00` | -| `date` | Custom date with format | `{{ date "2042-01-01T15:00:00Z" "yyyy-MM-dd HH:mm" }}` | `2042-01-01 15:00` | -| `date` (with offset) | Custom date with format, and with offset | `{{ date "2042-01-01T15:00:00Z" "yyyy-MM-dd HH:mm" -1 "days" }}` | `2041-31-12 15:00` | -| `date` (with date from `--data`) | Custom date with format, with data from the `data` config option | `{{ date myCustomDate "yyyy-MM-dd HH:mm" }}` | `2042-01-01 12:00` | - -Further details: - -- We use [`date-fns`](https://date-fns.org/docs/) for parsing/manipulating the dates. If you want - more information on the date tokens to use, refer to - [their format documentation](https://date-fns.org/docs/format). - -- The date helper format takes the following arguments: - - ```typescript - ( - date: string, - format: string, - offsetAmount?: number, - offsetType?: "years" | "months" | "weeks" | "days" | "hours" | "minutes" | "seconds" - ) - ``` - -- **The now helper** (for current time) takes the same arguments, minus the first one (`date`) as it - is implicitly the current date: - - ```typescript - ( - format: string, - offsetAmount?: number, - offsetType?: "years" | "months" | "weeks" | "days" | "hours" | "minutes" | "seconds" - ) - ``` - -### Custom Helpers - -You may also add your own custom helpers using the `helpers` options when using the JS API (rather -than the CLI). The `helpers` option takes an object whose keys are helper names, and values are the -transformation functions. For example, `upperCase` is implemented like so: +**Signatures:** ```typescript -config.helpers = { - upperCase: (text) => text.toUpperCase(), +now(format: string, offsetAmount?: number, offsetType?: "years" | "months" | "weeks" | "days" | "hours" | "minutes" | "seconds") + +date(date: string, format: string, offsetAmount?: number, offsetType?: "years" | "months" | "weeks" | "days" | "hours" | "minutes" | "seconds") +``` + +## Custom Helpers + +You can register custom Handlebars helpers via the `helpers` config option: + +```js +module.exports = { + component: { + templates: ["templates/component"], + output: "src/components", + helpers: { + shout: (text) => text.toUpperCase() + "!!!", + }, + }, } ``` -All of the above helpers (built in and custom) will also be available to you when using -`subdirHelper` (`--sub-dir-helper`/`-H`) as a possible value. +Then use in templates: `{{ shout name }}`. -> To see more information on how helpers work and more features, see -> [Handlebars.js docs](https://handlebarsjs.com/guide/#custom-helpers). +All helpers (built-in and custom) are also available as values for `subdirHelper` (`--subdir-helper` +/ `-H`). + +For more on Handlebars helpers, see the +[Handlebars.js docs](https://handlebarsjs.com/guide/#custom-helpers). diff --git a/docs/docs/usage/02-configuration_files.md b/docs/docs/usage/02-configuration_files.md index 6df3739..000f731 100644 --- a/docs/docs/usage/02-configuration_files.md +++ b/docs/docs/usage/02-configuration_files.md @@ -2,53 +2,137 @@ title: Configuration Files --- -If you want to have reusable configurations which are complex and don't fit into command lines -easily, or just want to manage your templates easier, you can use configuration files to load your -scaffolding configurations. +# Configuration Files -## Creating config files +Config files let you define reusable scaffold definitions — template paths, output directories, +custom data, inputs, and hooks — all in one place. -Configuration files should be valid `.js`/`.mjs`/`.cjs`/`.json` files that contain valid Scaffold -configurations. +## Creating a Config File -Each file hold multiple scaffolds. Each scaffold is a key, and its value is the configuration. For -example: +The fastest way is to run `init`: + +```sh +npx simple-scaffold init +``` + +This creates a `scaffold.config.js` and an example template in `templates/default/`. See +[`init` command](cli#init) for options. + +### Config Structure + +A config file exports an object mapping **template keys** to scaffold configurations: ```js +// scaffold.config.js module.exports = { component: { templates: ["templates/component"], output: "src/components", }, + page: { + templates: ["templates/page"], + output: "src/pages", + subdir: true, + }, } ``` -For the full configuration options, see [ScaffoldConfig](../api/interfaces/ScaffoldConfig). +For the full list of options, see [ScaffoldConfig](../api/interfaces/ScaffoldConfig) or the +[Node.js API](node) page. -If you want to supply functions inside the configurations, you must use a `.js`/`.cjs`/`.mjs` file -as JSON does not support non-primitives. +### Dynamic Configs -Another feature of using a JS file is you can export a function which will be loaded with the CMD -config provided to Simple Scaffold. The `extra` key contains any values not consumed by built-in -flags, so you can pre-process your args before outputting a config: +JS config files can export a **function** that receives the CLI config and returns the scaffold map. +This lets you pre-process arguments or add logic: ```js /** @type {import('simple-scaffold').ScaffoldConfigFile} */ -module.exports = (config) => { - console.log("Config:", config) - return { - component: { - templates: ["templates/component"], - output: "src/components", - }, - } +module.exports = (config) => ({ + component: { + templates: ["templates/component"], + output: "src/components", + data: { timestamp: Date.now() }, + }, +}) +``` + +The function can also be `async`. + +### Supported Formats + +- `.js` (CommonJS) +- `.cjs` (CommonJS, explicit) +- `.mjs` (ESM) +- `.json` + +:::note The correct extension may depend on your `package.json` `"type"` field. Packages with +`"type": "module"` may require `.mjs` or `.cjs` instead of `.js`. ::: + +## Using a Config File + +### Auto-detection + +Simple Scaffold automatically searches the current directory for a config file — no `--config` flag +needed. The following names are tried in order: + +1. `scaffold.config.{mjs,cjs,js,json}` +2. `scaffold.{mjs,cjs,js,json}` +3. `.scaffold.{mjs,cjs,js,json}` + +```sh +# Just run from the project root — config is found automatically +npx simple-scaffold -k component MyComponent +``` + +### Explicit Path + +Use `--config` (`-c`) to point to a specific file or directory: + +```sh +npx simple-scaffold -c path/to/scaffold.config.js -k component MyComponent +``` + +When a directory is given, the auto-detection order above is used within that directory. + +### Default Template Key + +If you don't provide `--key`, the `default` key is used: + +```js +module.exports = { + default: { + templates: ["templates/default"], + output: "src", + }, } ``` -### Template Inputs +```sh +# Uses the "default" key — no -k needed +npx simple-scaffold MyProject +``` -You can define **inputs** in your config to prompt users for custom values when scaffolding. Each -input becomes a template data variable: +If multiple keys exist and no `--key` is provided, you'll be prompted to select one interactively. + +### Providing a Default Name + +If your template doesn't need a dynamic name (e.g. common config files), set `name` in the config: + +```js +module.exports = { + eslint: { + name: ".eslintrc", + templates: ["templates/eslint"], + output: ".", + }, +} +``` + +The name can still be overridden with `--name` on the command line. + +## Inputs + +Inputs define custom fields that are prompted interactively and become template data variables: ```js module.exports = { @@ -69,146 +153,53 @@ module.exports = { } ``` -In your templates, use these as `{{ author }}`, `{{ license }}`, `{{ private }}`, `{{ port }}`. +Use them in templates as `{{ author }}`, `{{ license }}`, `{{ private }}`, `{{ port }}`. -Supported input types: `text` (default), `select`, `confirm`, `number`. See -[Template Inputs](cli#template-inputs) for the full reference. +**Input types:** -- **Required** inputs are prompted interactively if not provided via `--data` or `-D` +| Type | Description | Value type | +| --------- | ------------------------------ | ---------- | +| `text` | Free-form text input (default) | `string` | +| `select` | Choose from a list of options | `string` | +| `confirm` | Yes/no prompt | `boolean` | +| `number` | Numeric input | `number` | + +**Behavior:** + +- **Required** inputs are prompted if not provided via `--data` or `-D` - **Select and confirm** inputs are always prompted unless pre-provided -- **Optional** inputs with a `default` use that value silently if not provided -- In non-interactive environments, only defaults are applied +- **Optional** inputs with a `default` use that value silently +- In non-interactive environments (CI, piped input), only defaults are applied -If you want to provide templates that need no name (such as common config files which are easily -portable between projects), you may provide the `name` property in the config object. - -You will always be able to override it using `--name NewName`, but it will be given a value by -default and therefore it will no longer be required in the CLI arguments. - -## Using a config file - -### Auto-detection - -By default, Simple Scaffold automatically searches the current working directory for a config file. -No `--config` flag is needed if your config file uses one of the standard names. - -The following files are tried in order: - -1. `scaffold.config.mjs` -2. `scaffold.config.cjs` -3. `scaffold.config.js` -4. `scaffold.config.json` -5. `scaffold.mjs` -6. `scaffold.cjs` -7. `scaffold.js` -8. `scaffold.json` -9. `.scaffold.mjs` -10. `.scaffold.cjs` -11. `.scaffold.js` -12. `.scaffold.json` - -If a config file is found, it is loaded automatically. If multiple templates are defined and no -`--key` is provided, you'll be prompted to select one interactively. +Pre-fill inputs from the CLI: ```sh -# Just run from a directory containing scaffold.config.js — no flags needed -simple-scaffold MyComponentName +npx simple-scaffold -k component -D author=John -D license=MIT MyComponent ``` -### Explicit config path +## Remote Templates (Git) -You can also provide a specific file or directory path using `--config` (or `-c`), optionally -alongside `--key` or `-k`: - -```sh -simple-scaffold -c -k -``` - -For example: - -```sh -simple-scaffold -c scaffold.json -k component MyComponentName -``` - -When a directory is given, the same auto-detection order listed above is used to find a config file -within that directory. - -### Default template key - -If you don't supply a template key (e.g. `component`), `default` will be used: - -```js -/** @type {import('simple-scaffold').ScaffoldConfigFile} */ -module.exports = { - default: { - // ... - }, -} -``` - -```sh -# will use 'default' template -simple-scaffold -c scaffold.json MyComponentName -``` - -If multiple keys exist and no key is specified, you'll be prompted to choose one interactively. - -### Supported file types - -Any importable file is supported, depending on your build process. - -Common extensions: - -- `.mjs` -- `.cjs` -- `.js` -- `.json` - -Note that you might need to find the correct extension of `.js`, `.cjs` or `.mjs` depending on your -build process and your package type (for example, packages with `"type": "module"` in their -`package.json` might be required to use `.mjs`.) - -### Git/GitHub Templates - -You may specify a git or GitHub url to use remote templates. - -The command line option is `--git` or `-g`. - -- You may specify a full git or HTTPS git URL, which will be tried -- You may specify a git username and project if the project is on GitHub +Load config files and templates from any Git repository: ```sh # GitHub shorthand -simple-scaffold -g / [-c ] [-k ] +npx simple-scaffold -g username/repo -k component MyComponent -# Any git URL, git:// and https:// are supported -simple-scaffold -g git://gitlab.com// [-c ] [-k ] -simple-scaffold -g https://gitlab.com//.git [-c ] [-k ] +# Full Git URL (GitLab, Bitbucket, etc.) +npx simple-scaffold -g https://gitlab.com/user/repo.git -k component MyComponent ``` -When a config file path is omitted, the files given in the list above will be tried on the root -directory of the git repository. +When `--config` is omitted, the standard auto-detection order is used within the cloned repo. The +repository is cloned to a temporary directory and cleaned up automatically. -**Note:** The repository will be cloned to a temporary directory and removed after the scaffolding -has been done. - -## Use In Node.js - -You can also start a scaffold from Node.js with a remote file or URL config. - -Just use the `Scaffold.fromConfig` function: +### From Node.js ```ts -Scaffold.fromConfig( - "scaffold.config.js", // file or HTTPS git URL - { - // name of the generated component - name: "My Component", - // key to load from the config - key: "component", - }, - { - // other config overrides - }, +import Scaffold from "simple-scaffold" + +const scaffold = await Scaffold.fromConfig( + "https://github.com/user/repo.git", // or a local file path + { name: "MyComponent", key: "component" }, ) +await scaffold.run() ``` diff --git a/docs/docs/usage/03-cli.md b/docs/docs/usage/03-cli.md index 1b695bc..e72e8c3 100644 --- a/docs/docs/usage/03-cli.md +++ b/docs/docs/usage/03-cli.md @@ -1,243 +1,162 @@ --- -title: CLI Usage +title: CLI --- -## Available flags +# CLI -```text -Usage: simple-scaffold [options] +```sh +npx simple-scaffold [options] [name] ``` -To see this and more information anytime, add the `-h` or `--help` flag to your call, e.g. -`npx simple-scaffold@latest -h`. +Use `--help` (`-h`) to see all available options at any time. -Options: +## Commands -| Option/flag \| Alias | Description | -| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `--name` \| `-n` | Name to be passed to the generated files. `{{name}}` and other data parameters inside contents and file names will be replaced accordingly. If omitted in an interactive terminal, you will be prompted. | -| `--config` \| `-c` | Filename or directory to load config from. If omitted, the current directory is searched automatically for a config file (see [Auto-detection](configuration_files#auto-detection)). | -| `--git` \| `-g` | Git URL or GitHub path to load a template from. | -| `--key` \| `-k` | Key to load inside the config file. If omitted and multiple templates are available, you will be prompted to select one. | -| `--output` \| `-o` | Path to output to. If `--subdir` is enabled, the subdir will be created inside this path. If omitted in an interactive terminal, you will be prompted. | -| `--templates` \| `-t` | Template files to use as input. You may provide multiple files, each of which can be a relative or absolute path, or a glob pattern for multiple file matching easily. If omitted in an interactive terminal, you will be prompted for a comma-separated list. | -| `--overwrite` \| `-w` \| `--no-overwrite` \| `-W` | Enable to override output files, even if they already exist. (default: false) | -| `--data` \| `-d` | Add custom data to the templates. By default, only your app name is included. | -| `--append-data` \| `-D` | Append additional custom data to the templates, which will overwrite `--data`, using an alternate syntax, which is easier to use with CLI: `-D key1=string -D key2:=raw` | -| `--subdir` \| `-s` \| `--no-subdir` \| `-S` | Create a parent directory with the input name (and possibly `--subdir-helper` (default: false) | -| `--subdir-helper` \| `-H` | Default helper to apply to subdir name when using `--subdir`. | -| `--quiet` \| `-q` | Suppress output logs (Same as `--log-level none`)(default: false) | -| `--log-level` \| `-l` | Determine amount of logs to display. The values are: `none, debug, info, warn, error`. The provided level will display messages of the same level or higher. (default: info) | -| `--before-write` \| `-B` | Run a script before writing the files. This can be a command or a path to a file. A temporary file path will be passed to the given command and the command should return a string for the final output. | -| `--after-scaffold` \| `-A` | Run a shell command after all files have been written. The command is executed in the output directory (e.g. `--after-scaffold 'npm install'`). | -| `--dry-run` \| `-dr` | Don't emit files. This is good for testing your scaffolds and making sure they don't fail, without having to write actual file contents or create directories. (default: false) | -| `--version` \| `-v` | Display version. | - -### Interactive Mode - -When running in a terminal (TTY), Simple Scaffold will prompt for any missing required values: - -- **Name** — text input if `--name` is not provided -- **Template key** — selectable list if `--key` is not provided and the config file has multiple - templates -- **Output directory** — text input if `--output` is not provided -- **Template paths** — comma-separated text input if `--templates` is not provided - -In non-interactive environments (CI, piped input), missing values will cause an error instead of -prompting. - -### Template Inputs - -Config files can define **inputs** — custom fields that are prompted interactively and injected as -template data. This is useful for templates that need user-specific values like author name, -license, or description. - -```js -module.exports = { - component: { - templates: ["templates/component"], - output: "src/components", - inputs: { - author: { message: "Author name", required: true }, - license: { - type: "select", - message: "License", - options: ["MIT", "Apache-2.0", "GPL-3.0"], - }, - private: { type: "confirm", message: "Private package?", default: false }, - port: { type: "number", message: "Dev server port", default: 3000 }, - description: { message: "Description" }, - }, - }, -} -``` - -Each input becomes available as a Handlebars variable in your templates (e.g., `{{ author }}`, -`{{ license }}`). - -**Input types:** - -| Type | Description | Value type | -| --------- | ------------------------------ | ---------- | -| `text` | Free-form text input (default) | `string` | -| `select` | Choose from a list of options | `string` | -| `confirm` | Yes/no prompt | `boolean` | -| `number` | Numeric input | `number` | - -- **Required inputs** without a value will be prompted interactively -- **Select and confirm** inputs are always prompted (unless pre-provided) -- **Optional text/number inputs** with a `default` will use that value silently -- All inputs can be pre-provided via `--data` or `-D` to skip the prompt: - -```shell -simple-scaffold -c scaffold.config.js -k component -D author=John -D license=Apache-2.0 MyComponent -``` - -### Before Write option - -This option allows you to preprocess a file before it is being written, such as running a formatter, -linter or other commands. - -To use this option, pass it the command you would like to run. The following tokens will be replaced -in your string: - -- `{{path}}` - the temporary file path for you to read from -- `{{rawpath}}` - a different file path containing the raw file contents **before** they were - handled by Handlebars.js. - -If none of these tokens are found, the regular (non-raw) path will be appended to the end of the -command. - -```shell -simple-scaffold -c . --before-write prettier -# command: prettier /tmp/somefile - -simple-scaffold -c . --before-write 'cat {{path}} | my-linter' -# command: cat /tmp/somefile | my-linter -``` - -The command should return the string to write to the file through standard output (stdout), and not -re-write the tmp file as it is not used for writing. Returning an empty string (after trimming) will -discard the result and write the original file contents. - -See -[beforeWrite](https://chenasraf.github.io/simple-scaffold/docs/api/interfaces/ScaffoldConfig#beforewrite) -Node.js API for more details. Instead of returning `undefined` to keep the default behavior, you can -output `''` for the same effect. - -### After Scaffold option - -This option runs a shell command after all files have been written. The command is executed in the -output directory, making it useful for post-scaffolding tasks like installing dependencies or -initializing a git repo. - -```shell -simple-scaffold -c . --after-scaffold 'npm install' -simple-scaffold -c . --after-scaffold 'git init && git add .' -``` - -In a config file, you can use a function for more control: - -```js -module.exports = { - default: { - templates: ["templates/app"], - output: ".", - afterScaffold: async ({ config, files }) => { - console.log(`Created ${files.length} files in ${config.output}`) - // run any post-processing here - }, - }, -} -``` - -The function receives a context with the resolved `config` and an array of `files` (absolute paths) -that were written. - -## Available Commands: - -| Command \| Alias | Description | -| ---------------- | ------------------------------------------------------------------------------------ | -| `init` | Initialize a new scaffold config file and example template in the current directory. | -| `list` \| `ls` | List all available templates for a given config. See `list -h` for more information. | +| Command | Description | +| ------------- | ----------------------------------------- | +| _(default)_ | Generate files from a template | +| `init` | Create a config file and example template | +| `list` / `ls` | List available template keys in a config | ### `init` -Creates a scaffold config file and an example template directory to get you started quickly. +Scaffolds a config file and example template directory to get you started: -```shell -simple-scaffold init +```sh +npx simple-scaffold init +npx simple-scaffold init --format mjs +npx simple-scaffold init --dir packages/my-lib ``` -Options: +| Option | Description | +| ----------------- | ----------------------------------------------------------------- | +| `--dir` / `-d` | Directory to create the config in (defaults to current directory) | +| `--format` / `-f` | Config format: `js`, `mjs`, or `json` (prompts if omitted) | -| Option | Description | -| ------------------ | -------------------------------------------------------------------- | -| `--dir` \| `-d` | Directory to create the config in. Defaults to current directory. | -| `--format` \| `-f` | Config format: `js`, `mjs`, or `json`. If omitted, you are prompted. | - -The command creates: +Creates: - A config file (`scaffold.config.js` by default) with a `default` template key - A `templates/default/` directory with an example `{{name}}.md` template Existing files are never overwritten. -## Examples: +### `list` -> See -> [Configuration Files](https://chenasraf.github.io/simple-scaffold/docs/usage/configuration_files) -> for organizing multiple scaffold types into easy-to-maintain files +Lists all template keys defined in a config file: -Usage with config file - -```shell -$ simple-scaffold -c scaffold.cmd.js -k component MyComponent +```sh +npx simple-scaffold list +npx simple-scaffold list -c path/to/config.js +npx simple-scaffold list -g username/repo ``` -Usage with GitHub config file +## Options -```shell -$ simple-scaffold -g chenasraf/simple-scaffold -k component MyComponent +| Flag | Short | Description | Default | +| -------------------------------- | --------- | ----------------------------------------------------- | --------------- | +| `--name` | `-n` | Name for generated files (can also be positional arg) | | +| `--config` | `-c` | Path to config file or directory | _(auto-detect)_ | +| `--git` | `-g` | Git URL or GitHub shorthand (`user/repo`) | | +| `--key` | `-k` | Template key from config | `default` | +| `--output` | `-o` | Output directory | | +| `--templates` | `-t` | Template paths or glob patterns (repeatable) | | +| `--data` | `-d` | Custom data as JSON string | | +| `--append-data` | `-D` | Key-value data (`key=string`, `key:=raw`), repeatable | | +| `--subdir` / `--no-subdir` | `-s`/`-S` | Create parent directory with the input name | `false` | +| `--subdir-helper` | `-H` | Helper to transform subdir name | | +| `--overwrite` / `--no-overwrite` | `-w`/`-W` | Overwrite existing files | `false` | +| `--dry-run` | `-dr` | Preview output without writing files | `false` | +| `--before-write` | `-B` | Command to run before each file is written | | +| `--after-scaffold` | `-A` | Shell command to run after all files are written | | +| `--quiet` | `-q` | Suppress output (same as `--log-level none`) | | +| `--log-level` | `-l` | Log level: `none`, `debug`, `info`, `warn`, `error` | `info` | +| `--version` | `-v` | Show version | | +| `--help` | `-h` | Show help | | + +## Interactive Mode + +When running in a terminal (TTY), Simple Scaffold prompts for any missing required values: + +- **Name** — if `--name` is not provided +- **Template key** — if `--key` is not provided and the config has multiple templates +- **Output directory** — if `--output` is not provided +- **Template paths** — if `--templates` is not provided (comma-separated) + +[Inputs](configuration_files#inputs) defined in config files are also prompted interactively. + +In non-interactive environments (CI, piped input), missing required values cause an error. + +## Hooks + +### Before Write + +Runs a command before each file is written. The command receives a temporary file path and should +output the final content to stdout. + +```sh +# Appends file path automatically +npx simple-scaffold -c . --before-write prettier + +# Use tokens for explicit control +npx simple-scaffold -c . --before-write 'cat {{path}} | my-linter' ``` -Usage with https git URL (for non-GitHub) +**Tokens:** -```shell -$ simple-scaffold \ - -g https://example.com/user/template.git \ - -c scaffold.cmd.js \ - -k component \ - MyComponent +- `{{path}}` — temporary file path with Handlebars-processed contents +- `{{rawpath}}` — temporary file path with raw (unprocessed) contents + +If no tokens are found, `{{path}}` is appended automatically. Returning an empty string (after +trimming) discards the result and writes the original contents. + +### After Scaffold + +Runs a shell command after all files are written. The command executes in the output directory: + +```sh +npx simple-scaffold -c . --after-scaffold 'npm install' +npx simple-scaffold -c . --after-scaffold 'git init && git add .' ``` -Full syntax with config path and template key (applicable to all above methods) +See the [Node.js API](node#after-scaffold-hook) for the function-based equivalent. -```shell -$ simple-scaffold -c scaffold.cmd.js -k component MyComponent +## CLI Examples + +```sh +# Use auto-detected config, default key +npx simple-scaffold MyProject + +# Specify config and key +npx simple-scaffold -c scaffold.config.js -k component MyComponent + +# GitHub remote template +npx simple-scaffold -g username/repo -k component MyComponent + +# Full Git URL +npx simple-scaffold -g https://gitlab.com/user/repo.git -k component MyComponent + +# One-off (no config file) +npx simple-scaffold -t templates/component -o src/components MyComponent + +# With custom data +npx simple-scaffold -k component -D author=John -D license:='"MIT"' MyComponent + +# Dry run +npx simple-scaffold -k component --dry-run MyComponent ``` -Excluded template key, assumes 'default' key - -```shell -$ simple-scaffold -c scaffold.cmd.js MyComponent -``` - -Shortest syntax for GitHub, assumes file 'scaffold.cmd.js' and template key 'default' - -```shell -$ simple-scaffold -g chenasraf/simple-scaffold MyComponent -``` - -You can also add this as a script in your `package.json`: +### package.json Scripts ```json { "scripts": { - "scaffold-cfg": "npx simple-scaffold -c scaffold.cmd.js -k component", - "scaffold-gh": "npx simple-scaffold -g chenasraf/simple-scaffold -k component", - "scaffold": "npx simple-scaffold@latest -t scaffolds/component/**/* -o src/components -d '{\"myProp\": \"propName\", \"myVal\": 123}'" - "scaffold-component": "npx simple-scaffold -c scaffold.cmd.js -k" + "scaffold": "simple-scaffold -k component", + "scaffold:page": "simple-scaffold -k page" } } ``` + +```sh +npm run scaffold -- MyComponent +npm run scaffold:page -- Dashboard +``` diff --git a/docs/docs/usage/04-node.md b/docs/docs/usage/04-node.md index 2d6f4f5..21a1a41 100644 --- a/docs/docs/usage/04-node.md +++ b/docs/docs/usage/04-node.md @@ -1,28 +1,54 @@ --- -title: Node.js Usage +title: Node.js API --- -## Overview +# Node.js API -You can build the scaffold yourself, if you want to create more complex arguments, scaffold groups, -etc - simply pass a config object to the Scaffold function when you are ready to start. +Use Simple Scaffold programmatically for more complex workflows, custom logic, or integration into +build tools. -The config takes similar arguments to the command line. See the full -[API documentation](https://chenasraf.github.io/simple-scaffold/docs/api/interfaces/ScaffoldConfig) -for all configuration options and their behavior. +## Basic Usage -```ts +```typescript +import Scaffold from "simple-scaffold" + +const scaffold = new Scaffold({ + name: "MyComponent", + templates: ["templates/component"], + output: "src/components", +}) +await scaffold.run() +``` + +## Loading from a Config File + +```typescript +import Scaffold from "simple-scaffold" + +const scaffold = await Scaffold.fromConfig( + "scaffold.config.js", // local path or HTTPS Git URL + { name: "MyComponent", key: "component" }, + { + /* optional config overrides */ + }, +) +await scaffold.run() +``` + +## Config Interface + +```typescript interface ScaffoldConfig { name: string templates: string[] output: FileResponse subdir?: boolean + subdirHelper?: string data?: Record overwrite?: FileResponse - logLevel?: LogLevel + logLevel?: "none" | "debug" | "info" | "warn" | "error" dryRun?: boolean helpers?: Record - subdirHelper?: DefaultHelpers | string inputs?: Record beforeWrite?( content: Buffer, @@ -31,43 +57,56 @@ interface ScaffoldConfig { ): string | Buffer | undefined | Promise afterScaffold?: AfterScaffoldHook } - -interface ScaffoldInput { - type?: "text" | "select" | "confirm" | "number" - message?: string - required?: boolean - default?: string | boolean | number - options?: (string | { name: string; value: string })[] // for type: "select" -} - -interface AfterScaffoldContext { - config: ScaffoldConfig - files: string[] // absolute paths of written files -} - -type AfterScaffoldHook = ((context: AfterScaffoldContext) => void | Promise) | string ``` -### Before Write option +For the full API reference, see [ScaffoldConfig](../api/interfaces/ScaffoldConfig). -This option allows you to preprocess a file before it is being written, such as running a formatter, -linter or other commands. +### Options -To use this option, you can run any async/blocking command, and return a string as the final output -to be used as the file contents. +| Option | Type | Description | +| --------------- | ------------------------------- | ------------------------------------------------------------------------ | +| `name` | `string` | Name for generated files _(required)_ | +| `templates` | `string[]` | Template paths or globs; prefix with `!` to exclude _(required)_ | +| `output` | `string \| Function` | Output directory, or a function for per-file control | +| `data` | `Record` | Custom data available in templates | +| `inputs` | `Record` | Interactive input definitions (see [Inputs](configuration_files#inputs)) | +| `helpers` | `Record` | Custom Handlebars helpers | +| `subdir` | `boolean` | Create a parent directory with the input name (default: `false`) | +| `subdirHelper` | `string` | Helper to transform the subdir name (e.g. `"pascalCase"`) | +| `overwrite` | `boolean \| Function` | Overwrite existing files (default: `false`); function for per-file logic | +| `dryRun` | `boolean` | Preview without writing files (default: `false`) | +| `logLevel` | `string` | Log verbosity (default: `"info"`) | +| `beforeWrite` | `Function` | Async hook before each file is written | +| `afterScaffold` | `Function \| string` | Hook after all files are written | -Returning `undefined` will keep the file contents as-is, after normal Handlebars.js procesing by -Simple Scaffold. +## Hooks -### After Scaffold hook +### Before Write -The `afterScaffold` option runs after all files have been written. It receives a context object with -the resolved config and the list of files that were created. +Runs before each file is written. Return a `string` or `Buffer` to replace the file contents, or +`undefined` to keep the default (Handlebars-processed) output. ```typescript -import Scaffold from "simple-scaffold" +await new Scaffold({ + name: "MyComponent", + templates: ["templates/component"], + output: "src/components", + beforeWrite: async (content, rawContent, outputPath) => { + // Format the output, transform it, or return undefined to keep as-is + return content.toString().trim() + }, +}).run() +``` -await Scaffold({ +### After Scaffold Hook + +Runs after all files have been written. Pass a **function** for full control, or a **string** to run +a shell command in the output directory. + +**Function:** + +```typescript +await new Scaffold({ name: "my-app", templates: ["templates/app"], output: ".", @@ -75,32 +114,37 @@ await Scaffold({ console.log(`Created ${files.length} files`) // e.g. run npm install, git init, open editor, etc. }, -}) +}).run() ``` -You can also pass a shell command string, which will be executed in the output directory: +**Shell command:** ```typescript -await Scaffold({ +await new Scaffold({ name: "my-app", templates: ["templates/app"], output: "my-app", afterScaffold: "npm install && git init", -}) +}).run() +``` + +The context object: + +```typescript +interface AfterScaffoldContext { + config: ScaffoldConfig + files: string[] // absolute paths of written files +} ``` In dry-run mode, the hook is still called but the `files` array will be empty. -### Inputs +## Inputs -The `inputs` option lets you define fields that will be prompted interactively (when running in a -TTY) and merged into the template data. This is useful when your templates need user-specific -values. +Define interactive prompts that merge into template data: ```typescript -import Scaffold from "simple-scaffold" - -await Scaffold({ +await new Scaffold({ name: "component", templates: ["templates/component"], output: "src/components", @@ -114,27 +158,36 @@ await Scaffold({ private: { type: "confirm", message: "Private package?", default: false }, port: { type: "number", message: "Dev server port", default: 3000 }, }, -}) -// In templates: {{ author }}, {{ license }} +}).run() +// In templates: {{ author }}, {{ license }}, {{ private }}, {{ port }} +``` + +```typescript +interface ScaffoldInput { + type?: "text" | "select" | "confirm" | "number" + message?: string + required?: boolean + default?: string | boolean | number + options?: (string | { name: string; value: string })[] // for type: "select" +} ``` - **Required** inputs are prompted if not already in `data` - **Optional** inputs with a `default` are applied silently - Pre-providing values in `data` skips the prompt for that input -## Example - -This is an example of loading a complete scaffold via Node.js: +## Full Example ```typescript +import path from "path" import Scaffold from "simple-scaffold" -await Scaffold({ - name: "component", +await new Scaffold({ + name: "MyComponent", templates: [path.join(__dirname, "scaffolds", "component")], output: path.join(__dirname, "src", "components"), subdir: true, - subdirHelper: "upperCase", + subdirHelper: "pascalCase", data: { property: "value", }, @@ -145,8 +198,11 @@ await Scaffold({ author: { message: "Author name", required: true }, license: { message: "License", default: "MIT" }, }, - // return a string to replace the final file contents after pre-processing, or `undefined` - // to keep it as-is - beforeWrite: (content, rawContent, outputPath) => content.toString().toUpperCase(), -}) + beforeWrite: (content, rawContent, outputPath) => { + return content.toString().toUpperCase() + }, + afterScaffold: async ({ config, files }) => { + console.log(`Created ${files.length} files in ${config.output}`) + }, +}).run() ``` diff --git a/docs/docs/usage/05-examples.md b/docs/docs/usage/05-examples.md index 90c23d5..899a203 100644 --- a/docs/docs/usage/05-examples.md +++ b/docs/docs/usage/05-examples.md @@ -2,139 +2,185 @@ title: Examples --- -## Example files +# Examples -### Input +## React Component -- Input file path: +### Template - ```text - project → scaffold → {{Name}}.js → src → components - ``` +**File:** `templates/component/{{pascalCase name}}.tsx` -- Input file contents: +```tsx +/** + * Author: {{ author }} + * Date: {{ now "yyyy-MM-dd" }} + */ +import React from "react" - ```typescript - /** - * Author: {{ author }} - * Date: {{ now "yyyy-MM-dd" }} - */ - import React from 'react' +export default {{ pascalCase name }}: React.FC = (props) => { + return ( +
{{ pascalCase name }} Component
+ ) +} +``` - export default {{camelCase name}}: React.FC = (props) => { - return ( -
{{camelCase name}} Component
- ) - } - ``` +### Config + +```js +// scaffold.config.js +module.exports = { + component: { + templates: ["templates/component"], + output: "src/components", + data: { + author: "My Name", + }, + }, +} +``` + +### Running + +```sh +npx simple-scaffold -k component MyComponent +``` ### Output -- Output file path: - - With `subdir = false` (default): +**File:** `src/components/MyComponent.tsx` - ```text - project → src → components → MyComponent.js - ``` +```tsx +/** + * Author: My Name + * Date: 2077-01-01 + */ +import React from "react" - - With `subdir = true`: - - ```text - project → src → components → MyComponent → MyComponent.js - ``` - - - With `subdir = true` and `subdirHelper = 'upperCase'`: - - ```text - project → src → components → MYCOMPONENT → MyComponent.js - ``` - -- Output file contents: - - ```typescript - /** - * Author: My Name - * Date: 2077-01-01 - */ - import React from 'react' - - export default MyComponent: React.FC = (props) => { - return ( -
MyComponent Component
- ) - } - ``` - -## Example run commands - -### Command Example - -```bash -simple-scaffold \ - -t project/scaffold/**/* \ - -o src/components \ - -d '{"className": "myClassName","author": "My Name"}' - MyComponent +export default MyComponent: React.FC = (props) => { + return ( +
MyComponent Component
+ ) +} ``` -### Equivalent Node Module Example +## Subdir Variations + +Given the template and config above, the output path changes based on `subdir` settings: + +| Setting | Output path | +| ------------------------------------------- | -------------------------------------------- | +| `subdir: false` (default) | `src/components/MyComponent.tsx` | +| `subdir: true` | `src/components/MyComponent/MyComponent.tsx` | +| `subdir: true`, `subdirHelper: "upperCase"` | `src/components/MYCOMPONENT/MyComponent.tsx` | + +## CLI One-liner (No Config) + +```sh +npx simple-scaffold \ + -t templates/component/**/* \ + -o src/components \ + -d '{"author": "My Name"}' \ + MyComponent +``` + +## Node.js Equivalent ```typescript import Scaffold from "simple-scaffold" -async function main() { - await Scaffold({ - name: "MyComponent", - templates: ["project/scaffold/**/*"], - output: ["src/components"], - data: { - className: "myClassName", - author: "My Name", - }, - }) - console.log("Done.") +await new Scaffold({ + name: "MyComponent", + templates: ["templates/component"], + output: "src/components", + data: { + author: "My Name", + }, +}).run() +``` + +## Reusable Config Files + +### CommonJS (`scaffold.config.js`) + +```js +module.exports = { + default: { + templates: ["templates/component"], + output: "src/components", + }, } ``` -### Re-usable config +### ESM (`scaffold.config.mjs`) -#### Shell - -```bash -# cjs -simple-scaffold -c scaffold.cjs MyComponent \ - -d '{"className": "myClassName","author": "My Name"}' -# mjs -simple-scaffold -c scaffold.mjs MyComponent \ - -d '{"className": "myClassName","author": "My Name"}' +```js +export default { + default: { + templates: ["templates/component"], + output: "src/components", + }, +} ``` -#### scaffold.cjs +### Dynamic Config (with function) ```js module.exports = (config) => ({ default: { - templates: ["project/scaffold/**/*"], - output: ["src/components"], + templates: ["templates/component"], + output: "src/components", data: { - className: "myClassName", - author: "My Name", + generatedAt: new Date().toISOString(), }, }, }) ``` -#### scaffold.mjs +## With Inputs ```js -export default (config) => ({ - default: { - templates: ["project/scaffold/**/*"], - output: ["src/components"], - data: { - className: "myClassName", - author: "My Name", +// scaffold.config.js +module.exports = { + package: { + templates: ["templates/package"], + output: "packages", + subdir: true, + inputs: { + description: { message: "Package description", required: true }, + author: { message: "Author", default: "Team" }, + license: { + type: "select", + message: "License", + options: ["MIT", "Apache-2.0", "ISC"], + }, + private: { type: "confirm", message: "Private package?", default: true }, }, }, -}) +} +``` + +```sh +# Interactive — prompts for each input +npx simple-scaffold -k package my-lib + +# Non-interactive — provide all values upfront +npx simple-scaffold -k package -D description="A utility library" -D author=John my-lib +``` + +## With Hooks + +```js +module.exports = { + app: { + templates: ["templates/app"], + output: ".", + subdir: true, + afterScaffold: "cd {{name}} && npm install && git init", + }, +} +``` + +```sh +npx simple-scaffold -k app my-app +# Files are generated, then npm install and git init run automatically ``` diff --git a/docs/docs/usage/06-migration.md b/docs/docs/usage/06-migration.md index b11d13d..c8dd10b 100644 --- a/docs/docs/usage/06-migration.md +++ b/docs/docs/usage/06-migration.md @@ -2,60 +2,63 @@ title: Migration --- +# Migration + ## v1.x to v2.x -### CLI option changes +### CLI Changes -- Several changes to how remote configs are loaded via CLI: - - The `:template_key` syntax has been removed. You can still use `-k template_key` to achieve the - same result. - - The `--github` (`-gh`) flag has been replaced by a generic `--git` (`-g`) one, which handles any - git URL. Providing a partial GitHub path will default to trying to find the project on GitHub, - e.g. `-g username/project` - - The `#template_file` syntax has been removed, you may use `--config` or `-c` to tell Simple - Scaffold which file to look for inside the git project. There is a default file priority list - which can find the file for you if it is in one of the supported filenames. -- `verbose` can now take the names `debug`, `info`, `warn`, `error` or `none` (case insensitive). -- `--create-sub-folder` (`-s`) has been renamed to `--subdir` (`-s`) in the CLI. The Node.js names - have been changed as well. -- `--sub-folder-name-helper` (`-sh`) has been renamed to `--subdir-helper` (`-sh`). The Node.js - names have been changed as well. -- All boolean flags no longer take a value. `-q` instead of `-q 1` or `-q true`, `-s` instead of - `-s 1`, `-w` instead of `-w 1`, etc. +**Remote config syntax:** -### Behavior changes +- The `:template_key` suffix syntax has been removed. Use `-k template_key` instead. +- `--github` (`-gh`) is now `--git` (`-g`) and supports any Git URL. GitHub shorthand still works: + `-g username/project`. +- The `#template_file` suffix syntax has been removed. Use `--config` (`-c`) to specify which file + to look for inside the Git project. -- Data is no longer auto-populated with `Name` (PascalCase) by default. You can just use the helper - in your templates contents and file names, simply use `{{ pascalCase name }}` instead of - `{{ Name }}`. `Name` was arbitrary and it is confusing (is it `Title Case`? `PascalCase`? only - reading the docs can tell). Alternatively, you can inject the transformed name into your `data` - manually using a scaffold config file, by using the Node API or by appending the data to the CLI - invocation. +**Renamed flags:** + +| v1.x | v2.x | +| ---------------------------------- | -------------------------------------------------------- | +| `--create-sub-folder` / `-s` | `--subdir` / `-s` | +| `--sub-folder-name-helper` / `-sh` | `--subdir-helper` / `-H` | +| `--verbose` (true/false) | `--log-level` (`debug`, `info`, `warn`, `error`, `none`) | + +**Boolean flags** no longer take a value. Use `-q` instead of `-q true`, `-s` instead of `-s 1`, +etc. + +### Behavior Changes + +**`{{ Name }}` removed.** The auto-populated `Name` (PascalCase) variable is gone. Use +`{{ pascalCase name }}` in your templates instead. If you need the old behavior, inject it manually +via `data`: + +```js +module.exports = { + default: { + templates: ["templates/default"], + output: "src", + data: { Name: "{{ pascalCase name }}" }, // or set it programmatically + }, +} +``` ## v0.x to v1.x -In Simple Scaffold v1.0, the entire codebase was overhauled, yet usage remains mostly the same -between versions. With these notable exceptions: +In v1.0, the codebase was overhauled but usage remained mostly the same. -- Some of the argument names have changed -- Template syntax has been improved -- The command to run Scaffold has been simplified from `new SimpleScaffold(opts).run()` to - `SimpleScaffold(opts)`, which now returns a promise that you can await to know when the process - has been completed. +### API Changes -### Argument changes +| v0.x | v1.x | +| -------------------------------- | ------------------------------------------ | +| `new SimpleScaffold(opts).run()` | `SimpleScaffold(opts)` (returns a Promise) | +| `locals` option | `data` option | +| `--locals` / `-l` flag | `--data` / `-d` flag | -- `locals` has been renamed to `data`. The appropriate command line args have been updated as well - to `--data` | `-d`. -- Additional options have been added to both CLI and Node interfaces. See - [Command Line Interface (CLI) usage](https://chenasraf.github.io/simple-scaffold/docs/usage/cli) - and [Node.js usage](https://chenasraf.github.io/simple-scaffold/docs/usage/node) for more - information. +### Template Syntax -### Template syntax changes +Templates still use Handlebars.js. v1.x added **built-in helpers** (case transformations, date +formatting), removing the need to pre-process template data for common operations like `camelCase`, +`snakeCase`, etc. -Simple Scaffold still uses Handlebars.js to handle template content and file names. However, helpers -have been added to remove the need for you to pre-process the template data on simple use-cases such -as case type manipulation (converting to camel case, snake case, etc) - -See the readme for the full information on how to use these helpers and which are available. +See [Templates](templates#built-in-helpers) for the full list of available helpers. diff --git a/docs/docs/usage/index.md b/docs/docs/usage/index.md index 64927a5..2b9503c 100644 --- a/docs/docs/usage/index.md +++ b/docs/docs/usage/index.md @@ -3,9 +3,16 @@ title: Usage sidebar_position: 0 --- -- [Template Files](templates) -- [Configuration Files](configuration_files) -- [CLI Usage](cli) -- [Node.js Usage](node) -- [Examples](examples) -- [Migration](migration) +# Usage + +Simple Scaffold can be used as a **CLI tool** or as a **Node.js library**. Both approaches share the +same core concepts: templates, configuration files, and Handlebars-based token replacement. + +- [Templates](./usage/templates) — how template files and directories work, built-in helpers, and + custom helpers +- [Configuration Files](./usage/configuration_files) — reusable scaffold definitions, + auto-detection, inputs, and remote Git templates +- [CLI](./usage/cli) — all commands, flags, interactive mode, and hooks +- [Node.js API](./usage/node) — programmatic usage, full config interface, and hooks +- [Examples](./usage/examples) — end-to-end examples for CLI and Node.js +- [Migration](./usage/migration) — upgrading from v1.x or v0.x to the latest version