@schematics/angular 21.0.0-next.1 → 21.0.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai-config/schema.json +6 -6
- package/application/index.js +21 -1
- package/application/schema.d.ts +17 -0
- package/application/schema.js +12 -1
- package/application/schema.json +6 -0
- package/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.spec.ts.template +6 -6
- package/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.ts.template +1 -1
- package/component/index.js +5 -1
- package/component/schema.d.ts +5 -0
- package/component/schema.json +5 -0
- package/directive/files/__name@dasherize__.__type@dasherize__.spec.ts.template +3 -3
- package/directive/files/__name@dasherize__.__type@dasherize__.ts.template +1 -1
- package/directive/index.js +7 -2
- package/directive/schema.d.ts +5 -0
- package/directive/schema.json +5 -0
- package/ng-new/index.js +1 -0
- package/ng-new/schema.d.ts +17 -0
- package/ng-new/schema.js +12 -1
- package/ng-new/schema.json +6 -0
- package/package.json +4 -4
- package/server/files/application-builder/standalone-src/main.server.ts.template +3 -2
- package/server/files/server-builder/standalone-src/main.server.ts.template +3 -2
- package/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template +4 -4
- package/service/files/__name@dasherize__.__type@dasherize__.ts.template +1 -1
- package/service/index.d.ts +2 -1
- package/service/index.js +20 -4
- package/service/schema.d.ts +5 -0
- package/service/schema.json +5 -0
- package/tailwind/index.d.ts +2 -3
- package/tailwind/index.js +81 -26
- package/tailwind/schema.d.ts +5 -0
- package/tailwind/schema.json +5 -0
- package/utility/ast-utils.js +21 -10
- package/utility/generate-from-files.d.ts +1 -0
- package/utility/latest-versions/package.json +1 -1
- package/utility/latest-versions.js +3 -3
- package/workspace/files/tsconfig.json.template +0 -1
- /package/application/files/common-files/src/app/{app.html.template → app__suffix__.html.template} +0 -0
- /package/application/files/module-files/src/app/{app.spec.ts.template → app__suffix__.spec.ts.template} +0 -0
- /package/application/files/module-files/src/app/{app.ts.template → app__suffix__.ts.template} +0 -0
- /package/application/files/standalone-files/src/app/{app.spec.ts.template → app__suffix__.spec.ts.template} +0 -0
- /package/application/files/standalone-files/src/app/{app.ts.template → app__suffix__.ts.template} +0 -0
package/ai-config/schema.json
CHANGED
|
@@ -20,27 +20,27 @@
|
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"value": "claude",
|
|
23
|
-
"label": "Claude
|
|
23
|
+
"label": "Claude [ https://docs.anthropic.com/en/docs/claude-code/memory ]"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"value": "cursor",
|
|
27
|
-
"label": "Cursor
|
|
27
|
+
"label": "Cursor [ https://docs.cursor.com/en/context/rules ]"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"value": "gemini",
|
|
31
|
-
"label": "Gemini
|
|
31
|
+
"label": "Gemini [ https://ai.google.dev/gemini-api/docs ]"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"value": "copilot",
|
|
35
|
-
"label": "GitHub Copilot
|
|
35
|
+
"label": "GitHub Copilot [ https://code.visualstudio.com/docs/copilot/copilot-customization ]"
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
"value": "jetbrains",
|
|
39
|
-
"label": "JetBrains AI
|
|
39
|
+
"label": "JetBrains AI [ https://www.jetbrains.com/help/junie/customize-guidelines.html ]"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"value": "windsurf",
|
|
43
|
-
"label": "Windsurf
|
|
43
|
+
"label": "Windsurf [ https://docs.windsurf.com/windsurf/cascade/memories#rules ]"
|
|
44
44
|
}
|
|
45
45
|
]
|
|
46
46
|
},
|
package/application/index.js
CHANGED
|
@@ -41,6 +41,7 @@ function default_1(options) {
|
|
|
41
41
|
options.style = schema_1.Style.Css;
|
|
42
42
|
}
|
|
43
43
|
const { appDir, appRootSelector, componentOptions, folderName, sourceDir } = await getAppOptions(host, options);
|
|
44
|
+
const suffix = options.fileNameStyleGuide === '2016' ? '.component' : '';
|
|
44
45
|
return (0, schematics_1.chain)([
|
|
45
46
|
addAppToWorkspaceFile(options, appDir),
|
|
46
47
|
addTsProjectReference('./' + (0, core_1.join)((0, core_1.normalize)(appDir), 'tsconfig.app.json')),
|
|
@@ -81,6 +82,7 @@ function default_1(options) {
|
|
|
81
82
|
relativePathToWorkspaceRoot: (0, paths_1.relativePathToWorkspaceRoot)(appDir),
|
|
82
83
|
appName: options.name,
|
|
83
84
|
folderName,
|
|
85
|
+
suffix,
|
|
84
86
|
}),
|
|
85
87
|
(0, schematics_1.move)(appDir),
|
|
86
88
|
]), schematics_1.MergeStrategy.Overwrite),
|
|
@@ -89,7 +91,7 @@ function default_1(options) {
|
|
|
89
91
|
? (0, schematics_1.filter)((path) => !path.endsWith('tsconfig.spec.json.template'))
|
|
90
92
|
: (0, schematics_1.noop)(),
|
|
91
93
|
componentOptions.inlineTemplate
|
|
92
|
-
? (0, schematics_1.filter)((path) => !path.endsWith('
|
|
94
|
+
? (0, schematics_1.filter)((path) => !path.endsWith('app__suffix__.html.template'))
|
|
93
95
|
: (0, schematics_1.noop)(),
|
|
94
96
|
(0, schematics_1.applyTemplates)({
|
|
95
97
|
utils: schematics_1.strings,
|
|
@@ -98,6 +100,7 @@ function default_1(options) {
|
|
|
98
100
|
relativePathToWorkspaceRoot: (0, paths_1.relativePathToWorkspaceRoot)(appDir),
|
|
99
101
|
appName: options.name,
|
|
100
102
|
folderName,
|
|
103
|
+
suffix,
|
|
101
104
|
}),
|
|
102
105
|
(0, schematics_1.move)(appDir),
|
|
103
106
|
]), schematics_1.MergeStrategy.Overwrite),
|
|
@@ -111,6 +114,7 @@ function default_1(options) {
|
|
|
111
114
|
isTailwind
|
|
112
115
|
? (0, schematics_1.schematic)('tailwind', {
|
|
113
116
|
project: options.name,
|
|
117
|
+
skipInstall: options.skipInstall,
|
|
114
118
|
})
|
|
115
119
|
: (0, schematics_1.noop)(),
|
|
116
120
|
]);
|
|
@@ -181,6 +185,18 @@ function addAppToWorkspaceFile(options, appDir) {
|
|
|
181
185
|
(schematics[`@schematics/angular:${type}`] ??= {}).standalone = false;
|
|
182
186
|
});
|
|
183
187
|
}
|
|
188
|
+
if (options.fileNameStyleGuide === '2016') {
|
|
189
|
+
const schematicsWithTypeSymbols = ['component', 'directive', 'service'];
|
|
190
|
+
schematicsWithTypeSymbols.forEach((type) => {
|
|
191
|
+
const schematicDefaults = (schematics[`@schematics/angular:${type}`] ??= {});
|
|
192
|
+
schematicDefaults.type = type;
|
|
193
|
+
schematicDefaults.addTypeToClassName = false;
|
|
194
|
+
});
|
|
195
|
+
const schematicsWithTypeSeparator = ['guard', 'interceptor', 'module', 'pipe', 'resolver'];
|
|
196
|
+
schematicsWithTypeSeparator.forEach((type) => {
|
|
197
|
+
(schematics[`@schematics/angular:${type}`] ??= {}).typeSeparator = '.';
|
|
198
|
+
});
|
|
199
|
+
}
|
|
184
200
|
const sourceRoot = (0, core_1.join)((0, core_1.normalize)(projectRoot), 'src');
|
|
185
201
|
let budgets = [];
|
|
186
202
|
if (options.strict) {
|
|
@@ -317,5 +333,9 @@ function getComponentOptions(options) {
|
|
|
317
333
|
style: options.style,
|
|
318
334
|
viewEncapsulation: options.viewEncapsulation,
|
|
319
335
|
};
|
|
336
|
+
if (options.fileNameStyleGuide === '2016') {
|
|
337
|
+
componentOptions.type = 'component';
|
|
338
|
+
componentOptions.addTypeToClassName = false;
|
|
339
|
+
}
|
|
320
340
|
return componentOptions;
|
|
321
341
|
}
|
package/application/schema.d.ts
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
* routing, styling, and testing.
|
|
6
6
|
*/
|
|
7
7
|
export type Schema = {
|
|
8
|
+
/**
|
|
9
|
+
* The file naming convention to use for generated files. The '2025' style guide (default)
|
|
10
|
+
* uses a concise format (e.g., `app.ts` for the root component), while the '2016' style
|
|
11
|
+
* guide includes the type in the file name (e.g., `app.component.ts`). For more
|
|
12
|
+
* information, see the Angular Style Guide (https://angular.dev/style-guide).
|
|
13
|
+
*/
|
|
14
|
+
fileNameStyleGuide?: FileNameStyleGuide;
|
|
8
15
|
/**
|
|
9
16
|
* Include the styles for the root component directly within the `app.component.ts` file.
|
|
10
17
|
* Only CSS styles can be included inline. By default, a separate stylesheet file (e.g.,
|
|
@@ -86,6 +93,16 @@ export type Schema = {
|
|
|
86
93
|
*/
|
|
87
94
|
zoneless?: boolean;
|
|
88
95
|
};
|
|
96
|
+
/**
|
|
97
|
+
* The file naming convention to use for generated files. The '2025' style guide (default)
|
|
98
|
+
* uses a concise format (e.g., `app.ts` for the root component), while the '2016' style
|
|
99
|
+
* guide includes the type in the file name (e.g., `app.component.ts`). For more
|
|
100
|
+
* information, see the Angular Style Guide (https://angular.dev/style-guide).
|
|
101
|
+
*/
|
|
102
|
+
export declare enum FileNameStyleGuide {
|
|
103
|
+
The2016 = "2016",
|
|
104
|
+
The2025 = "2025"
|
|
105
|
+
}
|
|
89
106
|
/**
|
|
90
107
|
* The type of stylesheet files to be created for components in the application.
|
|
91
108
|
*/
|
package/application/schema.js
CHANGED
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
|
|
3
3
|
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.ViewEncapsulation = exports.Style = void 0;
|
|
5
|
+
exports.ViewEncapsulation = exports.Style = exports.FileNameStyleGuide = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* The file naming convention to use for generated files. The '2025' style guide (default)
|
|
8
|
+
* uses a concise format (e.g., `app.ts` for the root component), while the '2016' style
|
|
9
|
+
* guide includes the type in the file name (e.g., `app.component.ts`). For more
|
|
10
|
+
* information, see the Angular Style Guide (https://angular.dev/style-guide).
|
|
11
|
+
*/
|
|
12
|
+
var FileNameStyleGuide;
|
|
13
|
+
(function (FileNameStyleGuide) {
|
|
14
|
+
FileNameStyleGuide["The2016"] = "2016";
|
|
15
|
+
FileNameStyleGuide["The2025"] = "2025";
|
|
16
|
+
})(FileNameStyleGuide || (exports.FileNameStyleGuide = FileNameStyleGuide = {}));
|
|
6
17
|
/**
|
|
7
18
|
* The type of stylesheet files to be created for components in the application.
|
|
8
19
|
*/
|
package/application/schema.json
CHANGED
|
@@ -127,6 +127,12 @@
|
|
|
127
127
|
"x-prompt": "Do you want to create a 'zoneless' application without zone.js?",
|
|
128
128
|
"type": "boolean",
|
|
129
129
|
"default": false
|
|
130
|
+
},
|
|
131
|
+
"fileNameStyleGuide": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"enum": ["2016", "2025"],
|
|
134
|
+
"default": "2025",
|
|
135
|
+
"description": "The file naming convention to use for generated files. The '2025' style guide (default) uses a concise format (e.g., `app.ts` for the root component), while the '2016' style guide includes the type in the file name (e.g., `app.component.ts`). For more information, see the Angular Style Guide (https://angular.dev/style-guide)."
|
|
130
136
|
}
|
|
131
137
|
},
|
|
132
138
|
"required": ["name"]
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
2
|
|
|
3
|
-
import <% if(!exportDefault) { %>{ <% }%><%=
|
|
3
|
+
import <% if(!exportDefault) { %>{ <% }%><%= classifiedName %> <% if(!exportDefault) {%>} <% }%>from './<%= dasherize(name) %><%= type ? '.' + dasherize(type): '' %>';
|
|
4
4
|
|
|
5
|
-
describe('<%=
|
|
6
|
-
let component: <%=
|
|
7
|
-
let fixture: ComponentFixture<<%=
|
|
5
|
+
describe('<%= classifiedName %>', () => {
|
|
6
|
+
let component: <%= classifiedName %>;
|
|
7
|
+
let fixture: ComponentFixture<<%= classifiedName %>>;
|
|
8
8
|
|
|
9
9
|
beforeEach(async () => {
|
|
10
10
|
await TestBed.configureTestingModule({
|
|
11
|
-
<%= standalone ? 'imports' : 'declarations' %>: [<%=
|
|
11
|
+
<%= standalone ? 'imports' : 'declarations' %>: [<%= classifiedName %>]
|
|
12
12
|
})
|
|
13
13
|
.compileComponents();
|
|
14
14
|
|
|
15
|
-
fixture = TestBed.createComponent(<%=
|
|
15
|
+
fixture = TestBed.createComponent(<%= classifiedName %>);
|
|
16
16
|
component = fixture.componentInstance;
|
|
17
17
|
fixture.detectChanges();
|
|
18
18
|
});
|
package/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.ts.template
CHANGED
|
@@ -19,6 +19,6 @@ import { <% if(changeDetection !== 'Default') { %>ChangeDetectionStrategy, <% }%
|
|
|
19
19
|
encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
|
|
20
20
|
changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %>
|
|
21
21
|
})
|
|
22
|
-
export <% if(exportDefault) {%>default <%}%>class <%=
|
|
22
|
+
export <% if(exportDefault) {%>default <%}%>class <%= classifiedName %> {
|
|
23
23
|
|
|
24
24
|
}
|
package/component/index.js
CHANGED
|
@@ -37,7 +37,9 @@ exports.default = (0, project_1.createProjectSchematic)((options, { project, tre
|
|
|
37
37
|
options.path = parsedPath.path;
|
|
38
38
|
options.selector = options.selector || buildSelector(options, (project && project.prefix) || '');
|
|
39
39
|
(0, validation_1.validateHtmlSelector)(options.selector);
|
|
40
|
-
|
|
40
|
+
const classifiedName = schematics_1.strings.classify(options.name) +
|
|
41
|
+
(options.addTypeToClassName && options.type ? schematics_1.strings.classify(options.type) : '');
|
|
42
|
+
(0, validation_1.validateClassName)(classifiedName);
|
|
41
43
|
const skipStyleFile = options.inlineStyle || options.style === schema_1.Style.None;
|
|
42
44
|
const templateSource = (0, schematics_1.apply)((0, schematics_1.url)('./files'), [
|
|
43
45
|
options.skipTests ? (0, schematics_1.filter)((path) => !path.endsWith('.spec.ts.template')) : (0, schematics_1.noop)(),
|
|
@@ -48,6 +50,8 @@ exports.default = (0, project_1.createProjectSchematic)((options, { project, tre
|
|
|
48
50
|
'if-flat': (s) => (options.flat ? '' : s),
|
|
49
51
|
'ngext': options.ngHtml ? '.ng' : '',
|
|
50
52
|
...options,
|
|
53
|
+
// Add a new variable for the classified name, conditionally including the type
|
|
54
|
+
classifiedName,
|
|
51
55
|
}),
|
|
52
56
|
!options.type
|
|
53
57
|
? (0, schematics_1.forEach)(((file) => {
|
package/component/schema.d.ts
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* optional CSS stylesheet. Use this schematic to generate a new component in your project.
|
|
5
5
|
*/
|
|
6
6
|
export type Schema = {
|
|
7
|
+
/**
|
|
8
|
+
* When true, the 'type' option will be appended to the generated class name. When false,
|
|
9
|
+
* only the file name will include the type.
|
|
10
|
+
*/
|
|
11
|
+
addTypeToClassName?: boolean;
|
|
7
12
|
/**
|
|
8
13
|
* Configures the change detection strategy for the component.
|
|
9
14
|
*/
|
package/component/schema.json
CHANGED
|
@@ -95,6 +95,11 @@
|
|
|
95
95
|
"type": "string",
|
|
96
96
|
"description": "Append a custom type to the component's filename. For example, if you set the type to `container`, the file will be named `my-component.container.ts`."
|
|
97
97
|
},
|
|
98
|
+
"addTypeToClassName": {
|
|
99
|
+
"type": "boolean",
|
|
100
|
+
"default": true,
|
|
101
|
+
"description": "When true, the 'type' option will be appended to the generated class name. When false, only the file name will include the type."
|
|
102
|
+
},
|
|
98
103
|
"skipTests": {
|
|
99
104
|
"type": "boolean",
|
|
100
105
|
"description": "Skip the generation of unit test files `spec.ts`.",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { <%=
|
|
1
|
+
import { <%= classifiedName %> } from './<%= dasherize(name) %><%= type ? '.' + dasherize(type) : '' %>';
|
|
2
2
|
|
|
3
|
-
describe('<%=
|
|
3
|
+
describe('<%= classifiedName %>', () => {
|
|
4
4
|
it('should create an instance', () => {
|
|
5
|
-
const directive = new <%=
|
|
5
|
+
const directive = new <%= classifiedName %>();
|
|
6
6
|
expect(directive).toBeTruthy();
|
|
7
7
|
});
|
|
8
8
|
});
|
package/directive/index.js
CHANGED
|
@@ -35,12 +35,17 @@ exports.default = (0, project_1.createProjectSchematic)((options, { project, tre
|
|
|
35
35
|
options.path = parsedPath.path;
|
|
36
36
|
options.selector = options.selector || buildSelector(options, project.prefix || '');
|
|
37
37
|
(0, validation_1.validateHtmlSelector)(options.selector);
|
|
38
|
-
|
|
38
|
+
const classifiedName = schematics_1.strings.classify(options.name) +
|
|
39
|
+
(options.addTypeToClassName && options.type ? schematics_1.strings.classify(options.type) : '');
|
|
40
|
+
(0, validation_1.validateClassName)(classifiedName);
|
|
39
41
|
return (0, schematics_1.chain)([
|
|
40
42
|
(0, add_declaration_to_ng_module_1.addDeclarationToNgModule)({
|
|
41
43
|
type: 'directive',
|
|
42
44
|
...options,
|
|
43
45
|
}),
|
|
44
|
-
(0, generate_from_files_1.generateFromFiles)(
|
|
46
|
+
(0, generate_from_files_1.generateFromFiles)({
|
|
47
|
+
...options,
|
|
48
|
+
classifiedName,
|
|
49
|
+
}),
|
|
45
50
|
]);
|
|
46
51
|
});
|
package/directive/schema.d.ts
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* and boilerplate code for a new directive.
|
|
6
6
|
*/
|
|
7
7
|
export type Schema = {
|
|
8
|
+
/**
|
|
9
|
+
* When true, the 'type' option will be appended to the generated class name. When false,
|
|
10
|
+
* only the file name will include the type.
|
|
11
|
+
*/
|
|
12
|
+
addTypeToClassName?: boolean;
|
|
8
13
|
/**
|
|
9
14
|
* Automatically export the directive from the specified NgModule, making it accessible to
|
|
10
15
|
* other modules in the application.
|
package/directive/schema.json
CHANGED
|
@@ -84,6 +84,11 @@
|
|
|
84
84
|
"type": {
|
|
85
85
|
"type": "string",
|
|
86
86
|
"description": "Append a custom type to the directive's filename. For example, if you set the type to `directive`, the file will be named `example.directive.ts`."
|
|
87
|
+
},
|
|
88
|
+
"addTypeToClassName": {
|
|
89
|
+
"type": "boolean",
|
|
90
|
+
"default": true,
|
|
91
|
+
"description": "When true, the 'type' option will be appended to the generated class name. When false, only the file name will include the type."
|
|
87
92
|
}
|
|
88
93
|
},
|
|
89
94
|
"required": ["name", "project"]
|
package/ng-new/index.js
CHANGED
|
@@ -41,6 +41,7 @@ function default_1(options) {
|
|
|
41
41
|
standalone: options.standalone,
|
|
42
42
|
ssr: options.ssr,
|
|
43
43
|
zoneless: options.zoneless,
|
|
44
|
+
fileNameStyleGuide: options.fileNameStyleGuide,
|
|
44
45
|
};
|
|
45
46
|
return (0, schematics_1.chain)([
|
|
46
47
|
(0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.empty)(), [
|
package/ng-new/schema.d.ts
CHANGED
|
@@ -25,6 +25,13 @@ export type Schema = {
|
|
|
25
25
|
* the workspace will be created in the current directory.
|
|
26
26
|
*/
|
|
27
27
|
directory?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The file naming convention to use for generated files. The '2025' style guide (default)
|
|
30
|
+
* uses a concise format (e.g., `app.ts` for the root component), while the '2016' style
|
|
31
|
+
* guide includes the type in the file name (e.g., `app.component.ts`). For more
|
|
32
|
+
* information, see the Angular Style Guide (https://angular.dev/style-guide).
|
|
33
|
+
*/
|
|
34
|
+
fileNameStyleGuide?: FileNameStyleGuide;
|
|
28
35
|
/**
|
|
29
36
|
* Include the styles for the initial application's root component directly within the
|
|
30
37
|
* `app.component.ts` file. By default, a separate stylesheet file (e.g.,
|
|
@@ -135,6 +142,16 @@ export type CommitObject = {
|
|
|
135
142
|
name: string;
|
|
136
143
|
[property: string]: any;
|
|
137
144
|
};
|
|
145
|
+
/**
|
|
146
|
+
* The file naming convention to use for generated files. The '2025' style guide (default)
|
|
147
|
+
* uses a concise format (e.g., `app.ts` for the root component), while the '2016' style
|
|
148
|
+
* guide includes the type in the file name (e.g., `app.component.ts`). For more
|
|
149
|
+
* information, see the Angular Style Guide (https://angular.dev/style-guide).
|
|
150
|
+
*/
|
|
151
|
+
export declare enum FileNameStyleGuide {
|
|
152
|
+
The2016 = "2016",
|
|
153
|
+
The2025 = "2025"
|
|
154
|
+
}
|
|
138
155
|
/**
|
|
139
156
|
* The package manager used to install dependencies.
|
|
140
157
|
*/
|
package/ng-new/schema.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
|
|
3
3
|
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.ViewEncapsulation = exports.Style = exports.PackageManager = exports.AiConfig = void 0;
|
|
5
|
+
exports.ViewEncapsulation = exports.Style = exports.PackageManager = exports.FileNameStyleGuide = exports.AiConfig = void 0;
|
|
6
6
|
var AiConfig;
|
|
7
7
|
(function (AiConfig) {
|
|
8
8
|
AiConfig["Claude"] = "claude";
|
|
@@ -13,6 +13,17 @@ var AiConfig;
|
|
|
13
13
|
AiConfig["None"] = "none";
|
|
14
14
|
AiConfig["Windsurf"] = "windsurf";
|
|
15
15
|
})(AiConfig || (exports.AiConfig = AiConfig = {}));
|
|
16
|
+
/**
|
|
17
|
+
* The file naming convention to use for generated files. The '2025' style guide (default)
|
|
18
|
+
* uses a concise format (e.g., `app.ts` for the root component), while the '2016' style
|
|
19
|
+
* guide includes the type in the file name (e.g., `app.component.ts`). For more
|
|
20
|
+
* information, see the Angular Style Guide (https://angular.dev/style-guide).
|
|
21
|
+
*/
|
|
22
|
+
var FileNameStyleGuide;
|
|
23
|
+
(function (FileNameStyleGuide) {
|
|
24
|
+
FileNameStyleGuide["The2016"] = "2016";
|
|
25
|
+
FileNameStyleGuide["The2025"] = "2025";
|
|
26
|
+
})(FileNameStyleGuide || (exports.FileNameStyleGuide = FileNameStyleGuide = {}));
|
|
16
27
|
/**
|
|
17
28
|
* The package manager used to install dependencies.
|
|
18
29
|
*/
|
package/ng-new/schema.json
CHANGED
|
@@ -151,6 +151,12 @@
|
|
|
151
151
|
"type": "string",
|
|
152
152
|
"enum": ["none", "gemini", "copilot", "claude", "cursor", "jetbrains", "windsurf"]
|
|
153
153
|
}
|
|
154
|
+
},
|
|
155
|
+
"fileNameStyleGuide": {
|
|
156
|
+
"type": "string",
|
|
157
|
+
"enum": ["2016", "2025"],
|
|
158
|
+
"default": "2025",
|
|
159
|
+
"description": "The file naming convention to use for generated files. The '2025' style guide (default) uses a concise format (e.g., `app.ts` for the root component), while the '2016' style guide includes the type in the file name (e.g., `app.component.ts`). For more information, see the Angular Style Guide (https://angular.dev/style-guide)."
|
|
154
160
|
}
|
|
155
161
|
},
|
|
156
162
|
"required": ["name", "version"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schematics/angular",
|
|
3
|
-
"version": "21.0.0-next.
|
|
3
|
+
"version": "21.0.0-next.3",
|
|
4
4
|
"description": "Schematics specific to Angular",
|
|
5
5
|
"homepage": "https://github.com/angular/angular-cli",
|
|
6
6
|
"keywords": [
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
},
|
|
23
23
|
"schematics": "./collection.json",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@angular-devkit/core": "21.0.0-next.
|
|
26
|
-
"@angular-devkit/schematics": "21.0.0-next.
|
|
25
|
+
"@angular-devkit/core": "21.0.0-next.3",
|
|
26
|
+
"@angular-devkit/schematics": "21.0.0-next.3",
|
|
27
27
|
"jsonc-parser": "3.3.1"
|
|
28
28
|
},
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
|
31
31
|
"url": "https://github.com/angular/angular-cli.git"
|
|
32
32
|
},
|
|
33
|
-
"packageManager": "pnpm@10.15.
|
|
33
|
+
"packageManager": "pnpm@10.15.1",
|
|
34
34
|
"engines": {
|
|
35
35
|
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
|
|
36
36
|
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { bootstrapApplication } from '@angular/platform-browser';
|
|
1
|
+
import { BootstrapContext, bootstrapApplication } from '@angular/platform-browser';
|
|
2
2
|
import { <%= appComponentName %> } from '<%= appComponentPath %>';
|
|
3
3
|
import { config } from './app/app.config.server';
|
|
4
4
|
|
|
5
|
-
const bootstrap = () =>
|
|
5
|
+
const bootstrap = (context: BootstrapContext) =>
|
|
6
|
+
bootstrapApplication(<%= appComponentName %>, config, context);
|
|
6
7
|
|
|
7
8
|
export default bootstrap;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { bootstrapApplication } from '@angular/platform-browser';
|
|
1
|
+
import { BootstrapContext, bootstrapApplication } from '@angular/platform-browser';
|
|
2
2
|
import { <%= appComponentName %> } from '<%= appComponentPath %>';
|
|
3
3
|
import { config } from './app/app.config.server';
|
|
4
4
|
|
|
5
|
-
const bootstrap = () =>
|
|
5
|
+
const bootstrap = (context: BootstrapContext) =>
|
|
6
|
+
bootstrapApplication(<%= appComponentName %>, config, context);
|
|
6
7
|
|
|
7
8
|
export default bootstrap;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { TestBed } from '@angular/core/testing';
|
|
2
2
|
|
|
3
|
-
import { <%=
|
|
3
|
+
import { <%= classifiedName %> } from './<%= dasherize(name) %><%= type ? '.' + dasherize(type) : '' %>';
|
|
4
4
|
|
|
5
|
-
describe('<%=
|
|
6
|
-
let service: <%=
|
|
5
|
+
describe('<%= classifiedName %>', () => {
|
|
6
|
+
let service: <%= classifiedName %>;
|
|
7
7
|
|
|
8
8
|
beforeEach(() => {
|
|
9
9
|
TestBed.configureTestingModule({});
|
|
10
|
-
service = TestBed.inject(<%=
|
|
10
|
+
service = TestBed.inject(<%= classifiedName %>);
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
it('should be created', () => {
|
package/service/index.d.ts
CHANGED
package/service/index.js
CHANGED
|
@@ -7,8 +7,24 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
|
|
10
|
+
const schematics_1 = require("@angular-devkit/schematics");
|
|
11
11
|
const generate_from_files_1 = require("../utility/generate-from-files");
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const parse_name_1 = require("../utility/parse-name");
|
|
13
|
+
const project_1 = require("../utility/project");
|
|
14
|
+
const validation_1 = require("../utility/validation");
|
|
15
|
+
const workspace_1 = require("../utility/workspace");
|
|
16
|
+
exports.default = (0, project_1.createProjectSchematic)((options, { project, tree }) => {
|
|
17
|
+
if (options.path === undefined) {
|
|
18
|
+
options.path = (0, workspace_1.buildDefaultPath)(project);
|
|
19
|
+
}
|
|
20
|
+
const parsedPath = (0, parse_name_1.parseName)(options.path, options.name);
|
|
21
|
+
options.name = parsedPath.name;
|
|
22
|
+
options.path = parsedPath.path;
|
|
23
|
+
const classifiedName = schematics_1.strings.classify(options.name) +
|
|
24
|
+
(options.addTypeToClassName && options.type ? schematics_1.strings.classify(options.type) : '');
|
|
25
|
+
(0, validation_1.validateClassName)(classifiedName);
|
|
26
|
+
return (0, generate_from_files_1.generateFromFiles)({
|
|
27
|
+
...options,
|
|
28
|
+
classifiedName,
|
|
29
|
+
});
|
|
30
|
+
});
|
package/service/schema.d.ts
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* process of generating a new service with the necessary files and boilerplate code.
|
|
5
5
|
*/
|
|
6
6
|
export type Schema = {
|
|
7
|
+
/**
|
|
8
|
+
* When true, the 'type' option will be appended to the generated class name. When false,
|
|
9
|
+
* only the file name will include the type.
|
|
10
|
+
*/
|
|
11
|
+
addTypeToClassName?: boolean;
|
|
7
12
|
/**
|
|
8
13
|
* Creates files at the top level of the project or the given path. If set to false, a new
|
|
9
14
|
* folder with the service's name will be created to contain the files.
|
package/service/schema.json
CHANGED
|
@@ -43,6 +43,11 @@
|
|
|
43
43
|
"type": {
|
|
44
44
|
"type": "string",
|
|
45
45
|
"description": "Append a custom type to the service's filename. For example, if you set the type to `service`, the file will be named `my-service.service.ts`."
|
|
46
|
+
},
|
|
47
|
+
"addTypeToClassName": {
|
|
48
|
+
"type": "boolean",
|
|
49
|
+
"default": true,
|
|
50
|
+
"description": "When true, the 'type' option will be appended to the generated class name. When false, only the file name will include the type."
|
|
46
51
|
}
|
|
47
52
|
},
|
|
48
53
|
"required": ["name", "project"]
|
package/tailwind/index.d.ts
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import { type Rule } from '@angular-devkit/schematics';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}) => Rule;
|
|
9
|
+
import { Schema as TailwindOptions } from './schema';
|
|
10
|
+
declare const _default: (options: TailwindOptions) => Rule;
|
|
12
11
|
export default _default;
|
package/tailwind/index.js
CHANGED
|
@@ -6,46 +6,101 @@
|
|
|
6
6
|
* Use of this source code is governed by an MIT-style license that can be
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
9
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
13
|
const schematics_1 = require("@angular-devkit/schematics");
|
|
14
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
|
+
const posix_1 = require("node:path/posix");
|
|
11
16
|
const utility_1 = require("../utility");
|
|
17
|
+
const json_file_1 = require("../utility/json-file");
|
|
12
18
|
const latest_versions_1 = require("../utility/latest-versions");
|
|
13
19
|
const project_1 = require("../utility/project");
|
|
14
20
|
const TAILWIND_DEPENDENCIES = ['tailwindcss', '@tailwindcss/postcss', 'postcss'];
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const POSTCSS_CONFIG_FILES = ['.postcssrc.json', 'postcss.config.json'];
|
|
22
|
+
function addTailwindStyles(options, project) {
|
|
23
|
+
return async (tree) => {
|
|
24
|
+
const buildTarget = project.targets.get('build');
|
|
25
|
+
if (!buildTarget) {
|
|
26
|
+
throw new schematics_1.SchematicsException(`Project "${options.project}" does not have a build target.`);
|
|
27
|
+
}
|
|
28
|
+
const styles = buildTarget.options?.['styles'];
|
|
29
|
+
let stylesheetPath;
|
|
30
|
+
if (styles) {
|
|
31
|
+
stylesheetPath = styles
|
|
32
|
+
.map((s) => (typeof s === 'string' ? s : s.input))
|
|
33
|
+
.find((p) => p.endsWith('.css'));
|
|
34
|
+
}
|
|
35
|
+
if (!stylesheetPath) {
|
|
36
|
+
const newStylesheetPath = (0, posix_1.join)(project.sourceRoot ?? 'src', 'tailwind.css');
|
|
37
|
+
tree.create(newStylesheetPath, '@import "tailwindcss";\n');
|
|
38
|
+
return (0, utility_1.updateWorkspace)((workspace) => {
|
|
39
|
+
const project = workspace.projects.get(options.project);
|
|
40
|
+
if (project) {
|
|
41
|
+
const buildTarget = project.targets.get('build');
|
|
42
|
+
(0, node_assert_1.default)(buildTarget, 'Build target should still be present');
|
|
43
|
+
// Update main styles
|
|
44
|
+
const buildOptions = buildTarget.options;
|
|
45
|
+
(0, node_assert_1.default)(buildOptions, 'Build options should still be present');
|
|
46
|
+
const existingStyles = buildOptions['styles'] ?? [];
|
|
47
|
+
buildOptions['styles'] = [newStylesheetPath, ...existingStyles];
|
|
48
|
+
// Update configuration styles
|
|
49
|
+
if (buildTarget.configurations) {
|
|
50
|
+
for (const config of Object.values(buildTarget.configurations)) {
|
|
51
|
+
if (config && 'styles' in config) {
|
|
52
|
+
const existingStyles = config['styles'] ?? [];
|
|
53
|
+
config['styles'] = [newStylesheetPath, ...existingStyles];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
let stylesheetContent = tree.readText(stylesheetPath);
|
|
62
|
+
if (!stylesheetContent.includes('@import "tailwindcss";')) {
|
|
63
|
+
stylesheetContent += '\n@import "tailwindcss";\n';
|
|
64
|
+
tree.overwrite(stylesheetPath, stylesheetContent);
|
|
65
|
+
}
|
|
21
66
|
}
|
|
22
|
-
|
|
23
|
-
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function managePostCssConfiguration(project) {
|
|
70
|
+
return async (tree) => {
|
|
71
|
+
const searchPaths = ['/', project.root]; // Workspace root and project root
|
|
72
|
+
for (const path of searchPaths) {
|
|
73
|
+
for (const configFile of POSTCSS_CONFIG_FILES) {
|
|
74
|
+
const fullPath = (0, posix_1.join)(path, configFile);
|
|
75
|
+
if (tree.exists(fullPath)) {
|
|
76
|
+
const postcssConfig = new json_file_1.JSONFile(tree, fullPath);
|
|
77
|
+
const tailwindPluginPath = ['plugins', '@tailwindcss/postcss'];
|
|
78
|
+
if (postcssConfig.get(tailwindPluginPath) === undefined) {
|
|
79
|
+
postcssConfig.modify(tailwindPluginPath, {});
|
|
80
|
+
}
|
|
81
|
+
// Config found and handled
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// No existing config found, so create one from the template
|
|
87
|
+
const templateSource = (0, schematics_1.apply)((0, schematics_1.url)('./files'), [
|
|
88
|
+
(0, schematics_1.applyTemplates)({
|
|
89
|
+
...schematics_1.strings,
|
|
90
|
+
}),
|
|
91
|
+
(0, schematics_1.move)(project.root),
|
|
92
|
+
]);
|
|
93
|
+
return (0, schematics_1.mergeWith)(templateSource);
|
|
24
94
|
};
|
|
25
95
|
}
|
|
26
96
|
exports.default = (0, project_1.createProjectSchematic)((options, { project }) => {
|
|
27
|
-
const buildTarget = project.targets.get('build');
|
|
28
|
-
if (!buildTarget) {
|
|
29
|
-
throw new schematics_1.SchematicsException(`Project "${options.project}" does not have a build target.`);
|
|
30
|
-
}
|
|
31
|
-
const styles = buildTarget.options?.['styles'];
|
|
32
|
-
if (!styles || styles.length === 0) {
|
|
33
|
-
throw new schematics_1.SchematicsException(`Project "${options.project}" does not have any global styles.`);
|
|
34
|
-
}
|
|
35
|
-
const stylesheetPath = styles[0];
|
|
36
|
-
const templateSource = (0, schematics_1.apply)((0, schematics_1.url)('./files'), [
|
|
37
|
-
(0, schematics_1.applyTemplates)({
|
|
38
|
-
...schematics_1.strings,
|
|
39
|
-
...options,
|
|
40
|
-
}),
|
|
41
|
-
(0, schematics_1.move)(project.root),
|
|
42
|
-
]);
|
|
43
97
|
return (0, schematics_1.chain)([
|
|
44
|
-
|
|
45
|
-
(
|
|
98
|
+
addTailwindStyles(options, project),
|
|
99
|
+
managePostCssConfiguration(project),
|
|
46
100
|
...TAILWIND_DEPENDENCIES.map((name) => (0, utility_1.addDependency)(name, latest_versions_1.latestVersions[name], {
|
|
47
101
|
type: utility_1.DependencyType.Dev,
|
|
48
102
|
existing: utility_1.ExistingBehavior.Skip,
|
|
103
|
+
install: options.skipInstall ? utility_1.InstallBehavior.None : utility_1.InstallBehavior.Auto,
|
|
49
104
|
})),
|
|
50
105
|
]);
|
|
51
106
|
});
|
package/tailwind/schema.d.ts
CHANGED
package/tailwind/schema.json
CHANGED
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
"$default": {
|
|
10
10
|
"$source": "projectName"
|
|
11
11
|
}
|
|
12
|
+
},
|
|
13
|
+
"skipInstall": {
|
|
14
|
+
"description": "Skip the automatic installation of packages. You will need to manually install the dependencies later.",
|
|
15
|
+
"type": "boolean",
|
|
16
|
+
"default": false
|
|
12
17
|
}
|
|
13
18
|
},
|
|
14
19
|
"required": ["project"]
|
package/utility/ast-utils.js
CHANGED
|
@@ -115,6 +115,7 @@ function insertImport(source, fileToEdit, symbolName, fileName, isDefault = fals
|
|
|
115
115
|
` from '${fileName}'${insertAtBeginning ? `;${eol}` : ''}`;
|
|
116
116
|
return insertAfterLastOccurrence(allImports, toInsert, fileToEdit, fallbackPos, ts.SyntaxKind.StringLiteral);
|
|
117
117
|
}
|
|
118
|
+
const findNodesCache = new WeakMap();
|
|
118
119
|
function findNodes(node, kindOrGuard, max = Infinity, recursive = false) {
|
|
119
120
|
if (!node || max == 0) {
|
|
120
121
|
return [];
|
|
@@ -122,6 +123,13 @@ function findNodes(node, kindOrGuard, max = Infinity, recursive = false) {
|
|
|
122
123
|
const test = typeof kindOrGuard === 'function'
|
|
123
124
|
? kindOrGuard
|
|
124
125
|
: (node) => node.kind === kindOrGuard;
|
|
126
|
+
// Caching is only supported for the entire file
|
|
127
|
+
if (ts.isSourceFile(node)) {
|
|
128
|
+
const sourceFileCache = findNodesCache.get(node);
|
|
129
|
+
if (sourceFileCache?.has(kindOrGuard)) {
|
|
130
|
+
return sourceFileCache.get(kindOrGuard);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
125
133
|
const arr = [];
|
|
126
134
|
if (test(node)) {
|
|
127
135
|
arr.push(node);
|
|
@@ -140,6 +148,14 @@ function findNodes(node, kindOrGuard, max = Infinity, recursive = false) {
|
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
}
|
|
151
|
+
if (ts.isSourceFile(node)) {
|
|
152
|
+
let sourceFileCache = findNodesCache.get(node);
|
|
153
|
+
if (!sourceFileCache) {
|
|
154
|
+
sourceFileCache = new Map();
|
|
155
|
+
findNodesCache.set(node, sourceFileCache);
|
|
156
|
+
}
|
|
157
|
+
sourceFileCache.set(kindOrGuard, arr);
|
|
158
|
+
}
|
|
143
159
|
return arr;
|
|
144
160
|
}
|
|
145
161
|
/**
|
|
@@ -149,17 +165,12 @@ function findNodes(node, kindOrGuard, max = Infinity, recursive = false) {
|
|
|
149
165
|
*/
|
|
150
166
|
function getSourceNodes(sourceFile) {
|
|
151
167
|
const nodes = [sourceFile];
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const node = nodes
|
|
155
|
-
|
|
156
|
-
result.push(node);
|
|
157
|
-
if (node.getChildCount(sourceFile) >= 0) {
|
|
158
|
-
nodes.unshift(...node.getChildren());
|
|
159
|
-
}
|
|
160
|
-
}
|
|
168
|
+
// NOTE: nodes.length changes inside of the loop but we only append to the end
|
|
169
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
170
|
+
const node = nodes[i];
|
|
171
|
+
nodes.push(...node.getChildren(sourceFile));
|
|
161
172
|
}
|
|
162
|
-
return
|
|
173
|
+
return nodes;
|
|
163
174
|
}
|
|
164
175
|
function findNode(node, kind, text) {
|
|
165
176
|
if (node.kind === kind && node.getText() === text) {
|
|
@@ -15,5 +15,6 @@ export interface GenerateFromFilesOptions {
|
|
|
15
15
|
skipTests?: boolean;
|
|
16
16
|
templateFilesDirectory?: string;
|
|
17
17
|
type?: string;
|
|
18
|
+
classifiedName?: string;
|
|
18
19
|
}
|
|
19
20
|
export declare function generateFromFiles(options: GenerateFromFilesOptions, extraTemplateValues?: Record<string, string | ((v: string) => string)>): Rule;
|
|
@@ -16,7 +16,7 @@ exports.latestVersions = {
|
|
|
16
16
|
// As Angular CLI works with same minor versions of Angular Framework, a tilde match for the current
|
|
17
17
|
Angular: '^21.0.0-next.0',
|
|
18
18
|
NgPackagr: '^21.0.0-next.0',
|
|
19
|
-
DevkitBuildAngular: '^21.0.0-next.
|
|
20
|
-
AngularBuild: '^21.0.0-next.
|
|
21
|
-
AngularSSR: '^21.0.0-next.
|
|
19
|
+
DevkitBuildAngular: '^21.0.0-next.3',
|
|
20
|
+
AngularBuild: '^21.0.0-next.3',
|
|
21
|
+
AngularSSR: '^21.0.0-next.3',
|
|
22
22
|
};
|
/package/application/files/common-files/src/app/{app.html.template → app__suffix__.html.template}
RENAMED
|
File without changes
|
|
File without changes
|
/package/application/files/module-files/src/app/{app.ts.template → app__suffix__.ts.template}
RENAMED
|
File without changes
|
|
File without changes
|
/package/application/files/standalone-files/src/app/{app.ts.template → app__suffix__.ts.template}
RENAMED
|
File without changes
|