6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
+ import { normalize } from '@angular-devkit/core' ;
9
10
import { SchematicsException , Tree } from '@angular-devkit/schematics' ;
10
11
import { InsertChange } from '@schematics/angular/utility/change' ;
11
12
import { getWorkspace , WorkspaceProject , WorkspaceSchema } from '@schematics/angular/utility/config' ;
13
+ import { join } from 'path' ;
12
14
import { getProjectFromWorkspace } from '../../utils/get-project' ;
13
15
import { getProjectStyleFile } from '../../utils/project-style-file' ;
14
16
import { Schema } from '../schema' ;
@@ -20,14 +22,14 @@ export function addThemeToAppStyles(options: Schema): (host: Tree) => Tree {
20
22
return function ( host : Tree ) : Tree {
21
23
const workspace = getWorkspace ( host ) ;
22
24
const project = getProjectFromWorkspace ( workspace , options . project ) ;
25
+ const themeName = options . theme || 'indigo-pink' ;
23
26
24
27
// Because the build setup for the Angular CLI can be changed so dramatically, we can't know
25
28
// where to generate anything if the project is not using the default config for build and test.
26
- assertDefaultProjectConfig ( project ) ;
29
+ assertDefaultBuildersConfigured ( project ) ;
27
30
28
- const themeName = options . theme || 'indigo-pink' ;
29
31
if ( themeName === 'custom' ) {
30
- insertCustomTheme ( project , options . project , host ) ;
32
+ insertCustomTheme ( project , options . project , host , workspace ) ;
31
33
} else {
32
34
insertPrebuiltTheme ( project , host , themeName , workspace , options . project ) ;
33
35
}
@@ -36,19 +38,31 @@ export function addThemeToAppStyles(options: Schema): (host: Tree) => Tree {
36
38
} ;
37
39
}
38
40
39
- /** Insert a custom theme to styles.scss file. */
40
- function insertCustomTheme ( project : WorkspaceProject , projectName : string , host : Tree ) {
41
- const stylesPath = getProjectStyleFile ( project ) ;
42
- const buffer = host . read ( stylesPath ) ;
41
+ /**
42
+ * Insert a custom theme to project style file. If no valid style file could be found, a new
43
+ * Scss file for the custom theme will be created.
44
+ */
45
+ function insertCustomTheme ( project : WorkspaceProject , projectName : string , host : Tree ,
46
+ workspace : WorkspaceSchema ) {
43
47
44
- if ( buffer ) {
45
- const insertion = new InsertChange ( stylesPath , 0 , createCustomTheme ( projectName ) ) ;
46
- const recorder = host . beginUpdate ( stylesPath ) ;
47
- recorder . insertLeft ( insertion . pos , insertion . toAdd ) ;
48
- host . commitUpdate ( recorder ) ;
49
- } else {
50
- console . warn ( `Skipped custom theme; could not find file: ${ stylesPath } ` ) ;
48
+ const stylesPath = getProjectStyleFile ( project , 'scss' ) ;
49
+ const themeContent = createCustomTheme ( projectName ) ;
50
+
51
+ if ( ! stylesPath ) {
52
+ // Normalize the path through the devkit utilities because we want to avoid having
53
+ // unnecessary path segments and windows backslash delimiters.
54
+ const customThemePath = normalize ( join ( project . sourceRoot , 'custom-theme.scss' ) ) ;
55
+
56
+ host . create ( customThemePath , themeContent ) ;
57
+ addStyleToTarget ( project . architect [ 'build' ] , host , customThemePath , workspace ) ;
58
+ return ;
51
59
}
60
+
61
+ const insertion = new InsertChange ( stylesPath , 0 , themeContent ) ;
62
+ const recorder = host . beginUpdate ( stylesPath ) ;
63
+
64
+ recorder . insertLeft ( insertion . pos , insertion . toAdd ) ;
65
+ host . commitUpdate ( recorder ) ;
52
66
}
53
67
54
68
/** Insert a pre-built theme into the angular.json file. */
@@ -87,23 +101,20 @@ function addStyleToTarget(target: any, host: Tree, asset: string, workspace: Wor
87
101
host . overwrite ( 'angular.json' , JSON . stringify ( workspace , null , 2 ) ) ;
88
102
}
89
103
90
- /** Throws if the project is not using the default build and test config. */
91
- function assertDefaultProjectConfig ( project : WorkspaceProject ) {
92
- if ( ! isProjectUsingDefaultConfig ( project ) ) {
93
- throw new SchematicsException ( 'Your project is not using the default configuration for ' +
94
- 'build and test. The Angular Material schematics can only be used with the default ' +
95
- 'configuration' ) ;
96
- }
97
- }
98
-
99
- /** Gets whether the Angular CLI project is using the default build configuration. */
100
- function isProjectUsingDefaultConfig ( project : WorkspaceProject ) {
104
+ /** Throws if the project is not using the default Angular devkit builders. */
105
+ function assertDefaultBuildersConfigured ( project : WorkspaceProject ) {
101
106
const defaultBuilder = '@angular-devkit/build-angular:browser' ;
102
107
const defaultTestBuilder = '@angular-devkit/build-angular:karma' ;
103
108
104
- return project . architect &&
109
+ const hasDefaultBuilders = project . architect &&
105
110
project . architect [ 'build' ] &&
106
111
project . architect [ 'build' ] [ 'builder' ] === defaultBuilder &&
107
112
project . architect [ 'test' ] &&
108
113
project . architect [ 'test' ] [ 'builder' ] === defaultTestBuilder ;
114
+
115
+ if ( ! hasDefaultBuilders ) {
116
+ throw new SchematicsException (
117
+ 'Your project is not using the default builders for build and test. The Angular Material ' +
118
+ 'schematics can only be used if the original builders from the Angular CLI are configured.' ) ;
119
+ }
109
120
}
0 commit comments