Skip to content

Commit 4a2fc6f

Browse files
LucaVazzhansl
authored andcommitted
extended Schematics README regarding templating
to include basic info and an example about it
1 parent e72d1c3 commit 4a2fc6f

File tree

1 file changed

+79
-10
lines changed

1 file changed

+79
-10
lines changed

packages/angular_devkit/schematics/README.md

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
> A scaffolding library for the modern web.
33
44
## Description
5-
Schematics are generators that transform an existing filesystem. It can create files, refactor existing files, or move files around.
5+
Schematics are generators that transform an existing filesystem. They can create files, refactor existing files, or move files around.
66

77
What distinguishes Schematics from other generators, such as Yeoman or Yarn Create, is that schematics are purely descriptive; no changes are applied to the actual filesystem until everything is ready to be committed. There is no side effect, by design, in Schematics.
88

@@ -51,7 +51,7 @@ A Collection is defined by a `collection.json` file (in the reference CLI). This
5151
## Schematic
5252

5353
# Operators, Sources and Rules
54-
A `Source` is a generator of `Tree`; it creates a root tree from nothing. A `Rule` is a transformation from one `Tree` to another. A `Schematic` (at the root) is a `Rule` that is normally applied on the filesystem.
54+
A `Source` is a generator of a `Tree`; it creates an entirely new root tree from nothing. A `Rule` is a transformation from one `Tree` to another. A `Schematic` (at the root) is a `Rule` that is normally applied on the filesystem.
5555

5656
## Operators
5757
`FileOperator`s apply changes to a single `FileEntry` and return a new `FileEntry`. The result follows these rules:
@@ -62,37 +62,60 @@ A `Source` is a generator of `Tree`; it creates a root tree from nothing. A `Rul
6262

6363
It is impossible to create files using a `FileOperator`.
6464

65+
## Provided Operators
66+
The Schematics library provides multiple `Operator` factories by default that cover basic use cases:
67+
6568
| FileOperator | Description |
6669
|---|---|
6770
| `contentTemplate<T>(options: T)` | Apply a content template (see the Template section) |
6871
| `pathTemplate<T>(options: T)` | Apply a path template (see the Template section) |
6972

7073
## Provided Sources
71-
The Schematics library provides multiple `Source` factories by default that cover basic use cases:
74+
The Schematics library additionally provides multiple `Source` factories by default:
7275

7376
| Source | Description |
7477
|---|---|
75-
| `source(tree: Tree)` | Creates a source that returns the tree passed in argument. |
76-
| `empty()` | Creates a source that returns an empty tree. |
77-
| `apply(source: Source, rules: Rule[])` | Apply a list of rules to a source, and return the result. |
78-
| `url(url: string)` | Loads a list of files from a URL and returns a Tree with the files as `CreateAction` applied to an empty `Tree` |
78+
| `empty()` | Creates a source that returns an empty `Tree`. |
79+
| `source(tree: Tree)` | Creates a `Source` that returns the `Tree` passed in as argument. |
80+
| `url(url: string)` | Loads a list of files from the given URL and returns a `Tree` with the files as `CreateAction` applied to an empty `Tree`. |
81+
| `apply(source: Source, rules: Rule[])` | Apply a list of `Rule`s to a source, and return the resulting `Source`. |
7982

8083
## Provided Rules
8184
The schematics library also provides `Rule` factories by default:
8285

8386
| Rule | Description |
8487
|---|---|
8588
| `noop()` | Returns the input `Tree` as is. |
86-
| `chain(rules: Rule[])` | Returns a `Rule` that's the concatenation of other rules. |
89+
| `chain(rules: Rule[])` | Returns a `Rule` that's the concatenation of other `Rule`s. |
8790
| `forEach(op: FileOperator)` | Returns a `Rule` that applies an operator to every file of the input `Tree`. |
8891
| `move(root: string)` | Moves all the files from the input to a subdirectory. |
89-
| `merge(other: Tree)` | Merge the input `tree` with the other `Tree`. |
92+
| `merge(other: Tree)` | Merge the input `Tree` with the other `Tree`. |
9093
| `contentTemplate<T>(options: T)` | Apply a content template (see the Template section) to the entire `Tree`. |
9194
| `pathTemplate<T>(options: T)` | Apply a path template (see the Template section) to the entire `Tree`. |
9295
| `template<T>(options: T)` | Apply both path and content templates (see the Template section) to the entire `Tree`. |
9396
| `filter(predicate: FilePredicate<boolean>)` | Returns the input `Tree` with files that do not pass the `FilePredicate`. |
9497

9598

99+
# Templating
100+
As referenced above, some functions are based upon a file templating system, which consists of path and content templating.
101+
102+
The system operates on placeholders defined inside files or their paths as loaded in the `Tree` and fills these in as defined in the following, using values passed into the `Rule` which applies the templating (i.e. `template<T>(options: T)`).
103+
104+
## Path Templating
105+
| Placeholder | Description |
106+
|---|---|
107+
| __variable__ | Replaced with the value of `variable`. |
108+
| __varaiable@function__ | Replaced with the result of the call `function(variable)`. Can be chained to the left (`__variable@function1@function2__ ` etc). |
109+
110+
## Content Templating
111+
| Placeholder | Description |
112+
|---|---|
113+
| <%= expression %> | Replaced with the result of the call of the given expression. This only supports direct expressions, no structural (for/if/...) JavaScript. |
114+
| <%- expression %> | Same as above, but the value of the result will be escaped for HTML when inserted (i.e. replacing '<' with '&lt;') |
115+
| <% inline code %> | Inserts the given code into the template structure, allowing to insert structural JavaScript. |
116+
| <%# text %> | A comment, which gets entirely dropped. |
117+
118+
96119
# Examples
97120

98121
## Simple
@@ -114,8 +137,54 @@ A few things from this example:
114137
1. The function receives the list of options from the tooling.
115138
1. It returns a [`Rule`](src/engine/interface.ts#L73), which is a transformation from a `Tree` to another `Tree`.
116139

117-
# Future Work
140+
## Templating
141+
A simplified example of a Schematics which creates a file containing a new Class, using an option to determine its name:
142+
143+
```typescript
144+
// files/__name@dasherize__.ts
118145

146+
export class <%= classify(name) %> {
147+
}
148+
```
149+
150+
```typescript
151+
// index.ts
152+
153+
import { strings } from '@angular-devkit/core';
154+
import {
155+
Rule, SchematicContext, SchematicsException, Tree,
156+
apply, branchAndMerge, mergeWith, template, url,
157+
} from '@angular-devkit/schematics';
158+
import { Schema as ClassOptions } from './schema';
159+
160+
export default function (options: ClassOptions): Rule {
161+
return (tree: Tree, context: SchematicContext) => {
162+
if (!options.name) {
163+
throw new SchematicsException('Option (name) is required.');
164+
}
165+
166+
const templateSource = apply(
167+
url('./files'),
168+
[
169+
template({
170+
...strings,
171+
...options,
172+
}),
173+
]
174+
);
175+
176+
return branchAndMerge(mergeWith(templateSource));
177+
};
178+
}
179+
```
180+
181+
Additional things from this example:
182+
1. `strings` provides the used `dasherize` and `classify` functions, among others.
183+
1. The files are on-disk in the same root directory as the `index.ts` and loaded into a `Tree`.
184+
1. Then the `template` `Rule` fills in the specified templating placeholders. For this, it only knows about the variables and functions passed to it via the options-object.
185+
1. Finally, the resulting `Tree`, containing the new file, is merged with the existing files of the project which the Schematic is run on.
186+
187+
# Future Work
119188
Schematics is not done yet. Here's a list of things we are considering:
120189

121190
* Smart defaults for Options. Having a JavaScript function for default values based on other default values.

0 commit comments

Comments
 (0)