create-ng-tailwind 3.1.0 → 4.1.0
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.
Potentially problematic release.
This version of create-ng-tailwind might be problematic. Click here for more details.
- package/CHANGELOG.md +96 -341
- package/README.md +111 -157
- package/lib/cli/index.js +74 -3
- package/lib/cli/interactive.js +26 -1
- package/lib/managers/ProjectManager.js +2 -5
- package/lib/templates/base/components.js +243 -0
- package/lib/templates/base/index.js +207 -0
- package/lib/templates/base/infrastructure.js +314 -0
- package/lib/templates/base/linting.js +359 -0
- package/lib/templates/base/pwa.js +103 -0
- package/lib/templates/base/services.js +362 -0
- package/lib/templates/blog/app.js +250 -0
- package/lib/templates/blog/components.js +360 -0
- package/lib/templates/blog/i18n.js +77 -0
- package/lib/templates/blog/index.js +126 -0
- package/lib/templates/blog/pages.js +554 -0
- package/lib/templates/blog/services.js +390 -0
- package/lib/templates/dashboard/app.js +320 -0
- package/lib/templates/dashboard/charts.js +305 -0
- package/lib/templates/dashboard/components.js +410 -0
- package/lib/templates/dashboard/i18n.js +340 -0
- package/lib/templates/dashboard/index.js +141 -0
- package/lib/templates/dashboard/layout.js +310 -0
- package/lib/templates/dashboard/pages.js +681 -0
- package/lib/templates/ecommerce/app.js +315 -0
- package/lib/templates/ecommerce/components.js +496 -0
- package/lib/templates/ecommerce/i18n.js +389 -0
- package/lib/templates/ecommerce/index.js +152 -0
- package/lib/templates/ecommerce/layout.js +270 -0
- package/lib/templates/ecommerce/pages.js +969 -0
- package/lib/templates/ecommerce/services.js +300 -0
- package/lib/templates/index.js +12 -0
- package/lib/templates/landing/index.js +1117 -0
- package/lib/templates/portfolio/index.js +1160 -0
- package/lib/templates/saas/index.js +1371 -0
- package/lib/templates/starter/app.js +364 -0
- package/lib/templates/starter/i18n.js +856 -0
- package/lib/templates/starter/index.js +52 -4060
- package/lib/templates/starter/layout.js +852 -0
- package/lib/templates/starter/pages.js +1241 -0
- package/lib/utils/nodeCompat.js +85 -0
- package/package.json +1 -1
- package/lib/templates/starter/features.js +0 -867
- package/lib/utils/ai-config.js +0 -641
- /package/lib/templates/{starter → base}/advanced-features.js +0 -0
- /package/lib/templates/{starter → base}/seo-assets.js +0 -0
- /package/lib/templates/{starter → base}/seo-features.js +0 -0
- /package/lib/templates/{starter → base}/ui-features.js +0 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create Button Component
|
|
6
|
+
*/
|
|
7
|
+
async function createButtonComponent(config) {
|
|
8
|
+
const buttonComponent = `import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
9
|
+
|
|
10
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger';
|
|
11
|
+
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
12
|
+
|
|
13
|
+
@Component({
|
|
14
|
+
selector: 'app-button',
|
|
15
|
+
standalone: true,
|
|
16
|
+
imports: [],
|
|
17
|
+
template: \`
|
|
18
|
+
<button
|
|
19
|
+
[class]="buttonClasses"
|
|
20
|
+
[disabled]="disabled || loading"
|
|
21
|
+
(click)="handleClick($event)"
|
|
22
|
+
[type]="type">
|
|
23
|
+
|
|
24
|
+
@if (loading) {
|
|
25
|
+
<svg class="animate-spin -ml-1 mr-3 h-4 w-4" fill="none" viewBox="0 0 24 24">
|
|
26
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" class="opacity-25"></circle>
|
|
27
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
28
|
+
</svg>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
<ng-content></ng-content>
|
|
32
|
+
</button>
|
|
33
|
+
\`
|
|
34
|
+
})
|
|
35
|
+
export class ButtonComponent {
|
|
36
|
+
@Input() variant: ButtonVariant = 'primary';
|
|
37
|
+
@Input() size: ButtonSize = 'md';
|
|
38
|
+
@Input() disabled = false;
|
|
39
|
+
@Input() loading = false;
|
|
40
|
+
@Input() type: 'button' | 'submit' | 'reset' = 'button';
|
|
41
|
+
@Input() fullWidth = false;
|
|
42
|
+
|
|
43
|
+
@Output() clicked = new EventEmitter<Event>();
|
|
44
|
+
|
|
45
|
+
get buttonClasses(): string {
|
|
46
|
+
const baseClasses = 'inline-flex items-center justify-center font-medium rounded-lg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';
|
|
47
|
+
|
|
48
|
+
const sizeClasses = {
|
|
49
|
+
sm: 'text-sm px-3 py-2 h-9',
|
|
50
|
+
md: 'text-sm px-4 py-2 h-10',
|
|
51
|
+
lg: 'text-base px-8 py-3 h-11'
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const variantClasses = {
|
|
55
|
+
primary: 'bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500',
|
|
56
|
+
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300 focus:ring-gray-400',
|
|
57
|
+
outline: 'border-2 border-primary-600 text-primary-600 hover:bg-primary-600 hover:text-white focus:ring-primary-500',
|
|
58
|
+
ghost: 'hover:bg-gray-100 hover:text-gray-900 focus:ring-gray-400',
|
|
59
|
+
danger: 'bg-danger-600 text-white hover:bg-danger-700 focus:ring-danger-500'
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const widthClass = this.fullWidth ? 'w-full' : '';
|
|
63
|
+
|
|
64
|
+
return \`\${baseClasses} \${sizeClasses[this.size]} \${variantClasses[this.variant]} \${widthClass}\`.trim();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
handleClick(event: Event): void {
|
|
68
|
+
if (!this.disabled && !this.loading) {
|
|
69
|
+
this.clicked.emit(event);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}`;
|
|
73
|
+
|
|
74
|
+
await fs.writeFile(
|
|
75
|
+
path.join(config.fullPath, 'src/app/shared/components/button/button.component.ts'),
|
|
76
|
+
buttonComponent
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Create Card Component
|
|
82
|
+
*/
|
|
83
|
+
async function createCardComponent(config) {
|
|
84
|
+
const cardComponent = `import { Component, Input } from '@angular/core';
|
|
85
|
+
|
|
86
|
+
@Component({
|
|
87
|
+
selector: 'app-card',
|
|
88
|
+
standalone: true,
|
|
89
|
+
imports: [],
|
|
90
|
+
template: \`
|
|
91
|
+
<div [class]="cardClasses">
|
|
92
|
+
@if (title || subtitle) {
|
|
93
|
+
<div class="px-6 py-4 border-b border-gray-200">
|
|
94
|
+
@if (title) {
|
|
95
|
+
<h3 class="text-lg font-semibold text-gray-900">
|
|
96
|
+
{{ title }}
|
|
97
|
+
</h3>
|
|
98
|
+
}
|
|
99
|
+
@if (subtitle) {
|
|
100
|
+
<p class="text-sm text-gray-600 mt-1">
|
|
101
|
+
{{ subtitle }}
|
|
102
|
+
</p>
|
|
103
|
+
}
|
|
104
|
+
</div>
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
<div [class]="contentClasses">
|
|
108
|
+
<ng-content></ng-content>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
@if (hasFooter) {
|
|
112
|
+
<div class="px-6 py-4 border-t border-gray-200 bg-gray-50">
|
|
113
|
+
<ng-content select="[slot=footer]"></ng-content>
|
|
114
|
+
</div>
|
|
115
|
+
}
|
|
116
|
+
</div>
|
|
117
|
+
\`
|
|
118
|
+
})
|
|
119
|
+
export class CardComponent {
|
|
120
|
+
@Input() title?: string;
|
|
121
|
+
@Input() subtitle?: string;
|
|
122
|
+
@Input() padding = true;
|
|
123
|
+
@Input() shadow = true;
|
|
124
|
+
@Input() hover = false;
|
|
125
|
+
@Input() hasFooter = false;
|
|
126
|
+
|
|
127
|
+
get cardClasses(): string {
|
|
128
|
+
const baseClasses = 'bg-white border border-gray-200 rounded-lg overflow-hidden';
|
|
129
|
+
const shadowClasses = this.shadow ? 'shadow-sm' : '';
|
|
130
|
+
const hoverClasses = this.hover ? 'hover:shadow-md transition-shadow duration-200' : '';
|
|
131
|
+
|
|
132
|
+
return \`\${baseClasses} \${shadowClasses} \${hoverClasses}\`.trim();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get contentClasses(): string {
|
|
136
|
+
return this.padding ? 'p-6' : '';
|
|
137
|
+
}
|
|
138
|
+
}`;
|
|
139
|
+
|
|
140
|
+
await fs.writeFile(
|
|
141
|
+
path.join(config.fullPath, 'src/app/shared/components/card/card.component.ts'),
|
|
142
|
+
cardComponent
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create Loading Spinner Component
|
|
148
|
+
*/
|
|
149
|
+
async function createLoadingSpinnerComponent(config) {
|
|
150
|
+
const spinnerComponent = `import { Component, Input } from '@angular/core';
|
|
151
|
+
|
|
152
|
+
export type SpinnerSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
153
|
+
|
|
154
|
+
@Component({
|
|
155
|
+
selector: 'app-loading-spinner',
|
|
156
|
+
standalone: true,
|
|
157
|
+
imports: [],
|
|
158
|
+
template: \`
|
|
159
|
+
<div [class]="containerClasses">
|
|
160
|
+
<svg [class]="spinnerClasses" fill="none" viewBox="0 0 24 24">
|
|
161
|
+
<circle
|
|
162
|
+
cx="12" cy="12" r="10"
|
|
163
|
+
stroke="currentColor"
|
|
164
|
+
stroke-width="4"
|
|
165
|
+
class="opacity-25">
|
|
166
|
+
</circle>
|
|
167
|
+
<path
|
|
168
|
+
class="opacity-75"
|
|
169
|
+
fill="currentColor"
|
|
170
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
|
|
171
|
+
</path>
|
|
172
|
+
</svg>
|
|
173
|
+
@if (text) {
|
|
174
|
+
<span [class]="textClasses">{{ text }}</span>
|
|
175
|
+
}
|
|
176
|
+
</div>
|
|
177
|
+
\`
|
|
178
|
+
})
|
|
179
|
+
export class LoadingSpinnerComponent {
|
|
180
|
+
@Input() size: SpinnerSize = 'md';
|
|
181
|
+
@Input() text?: string;
|
|
182
|
+
@Input() centered = false;
|
|
183
|
+
@Input() color = 'primary';
|
|
184
|
+
|
|
185
|
+
private readonly sizeClasses = {
|
|
186
|
+
sm: 'h-4 w-4',
|
|
187
|
+
md: 'h-8 w-8',
|
|
188
|
+
lg: 'h-12 w-12',
|
|
189
|
+
xl: 'h-16 w-16'
|
|
190
|
+
} as const;
|
|
191
|
+
|
|
192
|
+
private readonly colorClasses = {
|
|
193
|
+
primary: 'text-primary-600',
|
|
194
|
+
secondary: 'text-secondary-600',
|
|
195
|
+
accent: 'text-accent-600',
|
|
196
|
+
success: 'text-success-600',
|
|
197
|
+
danger: 'text-danger-600',
|
|
198
|
+
warning: 'text-warning-600',
|
|
199
|
+
info: 'text-info-600',
|
|
200
|
+
gray: 'text-gray-600',
|
|
201
|
+
white: 'text-white'
|
|
202
|
+
} as const;
|
|
203
|
+
|
|
204
|
+
protected readonly textClasses = 'text-sm text-gray-600';
|
|
205
|
+
|
|
206
|
+
get containerClasses(): string {
|
|
207
|
+
const baseClasses = 'flex items-center';
|
|
208
|
+
const centerClasses = this.centered ? 'justify-center' : '';
|
|
209
|
+
const directionClasses = this.text ? 'flex-col space-y-2' : '';
|
|
210
|
+
|
|
211
|
+
return \`\${baseClasses} \${centerClasses} \${directionClasses}\`.trim();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
get spinnerClasses(): string {
|
|
215
|
+
const baseClasses = 'animate-spin';
|
|
216
|
+
return \`\${baseClasses} \${this.sizeClasses[this.size]} \${this.colorClasses[this.color as keyof typeof this.colorClasses] || this.colorClasses.primary}\`.trim();
|
|
217
|
+
}
|
|
218
|
+
}`;
|
|
219
|
+
|
|
220
|
+
await fs.writeFile(
|
|
221
|
+
path.join(
|
|
222
|
+
config.fullPath,
|
|
223
|
+
'src/app/shared/components/loading-spinner/loading-spinner.component.ts'
|
|
224
|
+
),
|
|
225
|
+
spinnerComponent
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Create all shared components
|
|
231
|
+
*/
|
|
232
|
+
async function createSharedComponents(config) {
|
|
233
|
+
await createButtonComponent(config);
|
|
234
|
+
await createCardComponent(config);
|
|
235
|
+
await createLoadingSpinnerComponent(config);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = {
|
|
239
|
+
createButtonComponent,
|
|
240
|
+
createCardComponent,
|
|
241
|
+
createLoadingSpinnerComponent,
|
|
242
|
+
createSharedComponents,
|
|
243
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
// Import modular components
|
|
5
|
+
const { createCoreServices } = require('./services');
|
|
6
|
+
const { createSharedComponents } = require('./components');
|
|
7
|
+
const {
|
|
8
|
+
createDirectoryStructure,
|
|
9
|
+
createEnvironments,
|
|
10
|
+
createGuards,
|
|
11
|
+
createModels,
|
|
12
|
+
createPipes,
|
|
13
|
+
} = require('./infrastructure');
|
|
14
|
+
const {
|
|
15
|
+
createVSCodeSettings,
|
|
16
|
+
updateTsConfig,
|
|
17
|
+
setupLinting,
|
|
18
|
+
formatCode,
|
|
19
|
+
} = require('./linting');
|
|
20
|
+
const { setupPWA } = require('./pwa');
|
|
21
|
+
|
|
22
|
+
// Import existing modular components
|
|
23
|
+
const {
|
|
24
|
+
createAuthInterceptor,
|
|
25
|
+
createErrorInterceptor,
|
|
26
|
+
createLoadingInterceptor,
|
|
27
|
+
createCachingInterceptor,
|
|
28
|
+
createToastService,
|
|
29
|
+
createToastComponent,
|
|
30
|
+
createLoadingService,
|
|
31
|
+
createCacheService,
|
|
32
|
+
} = require('./advanced-features');
|
|
33
|
+
|
|
34
|
+
const {
|
|
35
|
+
createModalService,
|
|
36
|
+
createModalComponent,
|
|
37
|
+
createTruncatePipe,
|
|
38
|
+
createClickOutsideDirective,
|
|
39
|
+
createTooltipDirective,
|
|
40
|
+
} = require('./ui-features');
|
|
41
|
+
|
|
42
|
+
const { createSEOService, createStructuredDataUtil, createRobotsTxt } = require('./seo-features');
|
|
43
|
+
|
|
44
|
+
const {
|
|
45
|
+
createDefaultOGImage,
|
|
46
|
+
createFavicon,
|
|
47
|
+
createAppleTouchIcon,
|
|
48
|
+
createAndroidIcon,
|
|
49
|
+
createAndroidIconLarge,
|
|
50
|
+
createLogo,
|
|
51
|
+
} = require('./seo-assets');
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Base Template
|
|
55
|
+
* Contains all core infrastructure: services, guards, interceptors, pipes, directives, etc.
|
|
56
|
+
* UI templates (starter, dashboard, ecommerce) extend this base.
|
|
57
|
+
*/
|
|
58
|
+
const base = {
|
|
59
|
+
info: {
|
|
60
|
+
name: 'Base',
|
|
61
|
+
description: 'Core infrastructure template with services, guards, interceptors, and shared components',
|
|
62
|
+
features: [
|
|
63
|
+
'Modern standalone Angular 20+ architecture with signals',
|
|
64
|
+
'HTTP Interceptors (Auth, Error, Loading, Caching)',
|
|
65
|
+
'Core services (API, Auth, Storage, Cache, Loading, SEO)',
|
|
66
|
+
'Toast/Notification system with auto-dismiss',
|
|
67
|
+
'Modal/Dialog system with confirm & alert',
|
|
68
|
+
'Essential UI components (Button, Card, Spinner, Toast, Modal)',
|
|
69
|
+
'Truncate pipe for text truncation',
|
|
70
|
+
'Useful Directives (ClickOutside, Tooltip)',
|
|
71
|
+
'TypeScript interfaces and models',
|
|
72
|
+
'ESLint + Prettier + simple-git-hooks (pre-commit)',
|
|
73
|
+
'PWA-ready with service worker configuration',
|
|
74
|
+
'Icons library (@ng-icons/heroicons)',
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
async apply(config, spinner) {
|
|
79
|
+
this.spinner = spinner;
|
|
80
|
+
const chalk = require('chalk');
|
|
81
|
+
|
|
82
|
+
const completeStep = (message) => {
|
|
83
|
+
if (spinner) {
|
|
84
|
+
spinner.stop();
|
|
85
|
+
console.log(chalk.green(' ✔') + chalk.white(' ' + message));
|
|
86
|
+
spinner.start();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Create core infrastructure
|
|
91
|
+
if (spinner) spinner.update('Setting up base project structure...');
|
|
92
|
+
await createDirectoryStructure(config);
|
|
93
|
+
await createEnvironments(config);
|
|
94
|
+
await createCoreServices(config);
|
|
95
|
+
await this.createSEOFeatures(config);
|
|
96
|
+
await this.createHttpInterceptors(config);
|
|
97
|
+
await createGuards(config);
|
|
98
|
+
await createSharedComponents(config);
|
|
99
|
+
await createLoadingService(config);
|
|
100
|
+
await createCacheService(config);
|
|
101
|
+
await this.createToastSystem(config);
|
|
102
|
+
await this.createModalSystem(config);
|
|
103
|
+
await createPipes(config);
|
|
104
|
+
await this.createAdditionalPipes(config);
|
|
105
|
+
await this.createDirectives(config);
|
|
106
|
+
await createModels(config);
|
|
107
|
+
await createVSCodeSettings(config);
|
|
108
|
+
await updateTsConfig(config);
|
|
109
|
+
await setupLinting(config);
|
|
110
|
+
await setupPWA(config);
|
|
111
|
+
|
|
112
|
+
if (spinner) spinner.stop();
|
|
113
|
+
|
|
114
|
+
// Show base template summary
|
|
115
|
+
console.log('');
|
|
116
|
+
completeStep('Core infrastructure configured');
|
|
117
|
+
completeStep('HTTP interceptors (Auth, Error, Loading, Cache)');
|
|
118
|
+
completeStep('Core services (9 services including SEO)');
|
|
119
|
+
completeStep('UI components (Button, Card, Toast, Modal, Spinner)');
|
|
120
|
+
completeStep('Utility pipes & directives');
|
|
121
|
+
completeStep('PWA support configured');
|
|
122
|
+
completeStep('ESLint + Prettier + simple-git-hooks');
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
async createSEOFeatures(config) {
|
|
126
|
+
// Create SEO Service
|
|
127
|
+
const seoService = createSEOService();
|
|
128
|
+
await fs.writeFile(
|
|
129
|
+
path.join(config.fullPath, 'src/app/core/services/seo.service.ts'),
|
|
130
|
+
seoService
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// Create Structured Data Utility
|
|
134
|
+
const structuredDataUtil = createStructuredDataUtil();
|
|
135
|
+
await fs.writeFile(
|
|
136
|
+
path.join(config.fullPath, 'src/app/core/utils/structured-data.ts'),
|
|
137
|
+
structuredDataUtil
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
// Create robots.txt in public folder
|
|
141
|
+
const robotsTxt = createRobotsTxt();
|
|
142
|
+
await fs.writeFile(path.join(config.fullPath, 'public/robots.txt'), robotsTxt);
|
|
143
|
+
|
|
144
|
+
// Create default OG image (SVG as placeholder)
|
|
145
|
+
const ogImage = createDefaultOGImage(config.projectName);
|
|
146
|
+
await fs.writeFile(path.join(config.fullPath, 'public/assets/images/og-default.svg'), ogImage);
|
|
147
|
+
|
|
148
|
+
// Create favicon
|
|
149
|
+
const favicon = createFavicon(config.projectName);
|
|
150
|
+
await fs.writeFile(path.join(config.fullPath, 'public/favicon.svg'), favicon);
|
|
151
|
+
|
|
152
|
+
// Create Apple Touch Icon (SVG as placeholder)
|
|
153
|
+
const appleTouchIcon = createAppleTouchIcon(config.projectName);
|
|
154
|
+
await fs.writeFile(
|
|
155
|
+
path.join(config.fullPath, 'public/assets/icons/apple-touch-icon.svg'),
|
|
156
|
+
appleTouchIcon
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Create Android Chrome icons (SVG as placeholder)
|
|
160
|
+
const androidIcon = createAndroidIcon(config.projectName);
|
|
161
|
+
await fs.writeFile(
|
|
162
|
+
path.join(config.fullPath, 'public/assets/icons/android-chrome-192x192.svg'),
|
|
163
|
+
androidIcon
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const androidIconLarge = createAndroidIconLarge(config.projectName);
|
|
167
|
+
await fs.writeFile(
|
|
168
|
+
path.join(config.fullPath, 'public/assets/icons/android-chrome-512x512.svg'),
|
|
169
|
+
androidIconLarge
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// Create logo
|
|
173
|
+
const logo = createLogo(config.projectName);
|
|
174
|
+
await fs.writeFile(path.join(config.fullPath, 'public/assets/images/logo.svg'), logo);
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
async createHttpInterceptors(config) {
|
|
178
|
+
await createAuthInterceptor(config);
|
|
179
|
+
await createErrorInterceptor(config);
|
|
180
|
+
await createLoadingInterceptor(config);
|
|
181
|
+
await createCachingInterceptor(config);
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
async createToastSystem(config) {
|
|
185
|
+
await createToastService(config);
|
|
186
|
+
await createToastComponent(config);
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
async createModalSystem(config) {
|
|
190
|
+
await createModalService(config);
|
|
191
|
+
await createModalComponent(config);
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
async createAdditionalPipes(config) {
|
|
195
|
+
await createTruncatePipe(config);
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
async createDirectives(config) {
|
|
199
|
+
await createClickOutsideDirective(config);
|
|
200
|
+
await createTooltipDirective(config);
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
// Expose formatCode for child templates to use
|
|
204
|
+
formatCode,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
module.exports = base;
|