From 7e81151da547a6e167101749d1aeb0395da03515 Mon Sep 17 00:00:00 2001 From: Valerio Date: Thu, 31 Oct 2024 13:27:42 +0100 Subject: [PATCH] feat: add angular schematics --- .devcontainer/scripts/postStartCommand.sh | 0 .github/workflows/run-tests.yml | 1 + README.EN.md | 110 ++++++------ README.md | 126 ++++++------- package-lock.json | 167 +++++++++++++++++- package.json | 7 +- postbuildSchematics.js | 23 +++ projects/design-angular-kit/package.json | 14 +- .../schematics/collection.json | 19 ++ .../schematics/ng-add/index.spec.ts | 45 +++++ .../schematics/ng-add/index.ts | 36 ++++ .../rules/setup-project/add-animations.ts | 7 + .../ng-add/rules/setup-project/add-assets.ts | 45 +++++ .../setup-project/add-design-angular-kit.ts | 40 +++++ .../rules/setup-project/add-http-client.ts | 7 + .../setup-project/add-import-to-style-file.ts | 120 +++++++++++++ .../rules/setup-project/add-localisation.ts | 45 +++++ .../setup-project/angular-json-helper.ts | 11 ++ .../ng-add/rules/setup-project/exceptions.ts | 13 ++ .../ng-add/rules/setup-project/index.ts | 6 + .../schematics/ng-add/schema.json | 16 ++ .../schematics/ng-add/schema.ts | 3 + .../schematics/ng-add/setup-project.spec.ts | 166 +++++++++++++++++ .../schematics/ng-add/setup-project.ts | 31 ++++ .../schematics/ng-add/utils.ts | 71 ++++++++ .../schematics/ng-add/versions-helper.ts | 41 +++++ .../src/lib/provide-design-angular-kit.ts | 8 +- .../tsconfig.schematics.json | 25 +++ 28 files changed, 1083 insertions(+), 120 deletions(-) mode change 100755 => 100644 .devcontainer/scripts/postStartCommand.sh create mode 100644 postbuildSchematics.js create mode 100644 projects/design-angular-kit/schematics/collection.json create mode 100644 projects/design-angular-kit/schematics/ng-add/index.spec.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/index.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-animations.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-assets.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-design-angular-kit.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-http-client.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-import-to-style-file.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-localisation.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/angular-json-helper.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/exceptions.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/rules/setup-project/index.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/schema.json create mode 100644 projects/design-angular-kit/schematics/ng-add/schema.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/setup-project.spec.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/setup-project.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/utils.ts create mode 100644 projects/design-angular-kit/schematics/ng-add/versions-helper.ts create mode 100644 projects/design-angular-kit/tsconfig.schematics.json diff --git a/.devcontainer/scripts/postStartCommand.sh b/.devcontainer/scripts/postStartCommand.sh old mode 100755 new mode 100644 diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 87c17ac8..b32176e0 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -24,4 +24,5 @@ jobs: - run: npm run build - run: npm run build:lib - run: npm run test + - run: npm run schematics:test - uses: codecov/codecov-action@v2 diff --git a/README.EN.md b/README.EN.md index 47399c47..43cd5ab7 100644 --- a/README.EN.md +++ b/README.EN.md @@ -64,10 +64,25 @@ npm install design-angular-kit --save Choose the version corresponding to your Angular version: | Angular | design-angular-kit | -|---------|--------------------| +| ------- | ------------------ | | 18+ | v1.1.0 + | | 17+ | v1.0.0 + | +Alternatively, you can run the command + +```sh +ng add design-angular-kit --project +``` + +He will consecutively perform: + +- choose the correct Angular version +- install the dep +- add the dep to package.json +- application configuration + +The instruction of the next chapter, **Configuration**, will be executed automatically, except for the customization of \_i18n. + ## Configuration ### App configuration @@ -84,11 +99,8 @@ initialise the library's functionality. import { provideDesignAngularKit } from 'design-angular-kit'; export const appConfig: ApplicationConfig = { - providers: [ - ... - provideDesignAngularKit(), - ] -} + providers: [...provideDesignAngularKit()], +}; ``` #### Modular application @@ -100,28 +112,21 @@ using the `forRoot` method in order to initialise the library functionality and import { DesignAngularKitModule } from 'design-angular-kit'; @NgModule({ - imports: [ - ... - DesignAngularKitModule.forRoot() - ] + imports: [...DesignAngularKitModule.forRoot()], }) -export class AppModule { } +export class AppModule {} ``` Uses the `forChild` method when importing the `DesignAngularKitModule` into other modules of the application to **import all library components**. - ```typescript import { DesignAngularKitModule } from 'design-angular-kit'; @NgModule({ - imports: [ - ... - DesignAngularKitModule.forChild() - ], + imports: [...DesignAngularKitModule.forChild()], exports: [DesignAngularKitModule], }) -export class SharedModule { } +export class SharedModule {} ``` #### Hybrid application @@ -134,11 +139,9 @@ import { provideDesignAngularKit } from 'design-angular-kit'; @NgModule({ imports: [], - providers: [ - provideDesignAngularKit(), - ] + providers: [provideDesignAngularKit()], }) -export class AppModule { } +export class AppModule {} ``` #### Configuration Parameters @@ -161,7 +164,7 @@ const initConfig: DesignAngularKitConfig | undefined = { * @default true */ loadFont: boolean | undefined, - + ... }; @@ -171,11 +174,12 @@ DesignAngularKitModule.forRoot(initConfig) ``` ### Importing bootstrap styles + Configure the required styles in the file `styles.scss`. Import the SCSS library as shown in the example below. ```scss // Importing bootstrap-italia SCSS library -@import "bootstrap-italia/src/scss/bootstrap-italia"; +@import 'bootstrap-italia/src/scss/bootstrap-italia'; ```
@@ -190,7 +194,6 @@ The use of blue #0066CC should, however, be reserved for the central administrat State, and thus one may find oneself in the position of having to customise the values of the variables colour of Bootstrap Italy, setting new values for their own needs. - This colour and the other tones are generated from the HSB triad, so the variables primary-h, primary-s and primary-b must be modified. To obtain the correspondence between the hexadecimal value of the colour and HSB, one can use the rgb.to portal, e.g. https://rgb.to/0066CC. @@ -213,6 +216,7 @@ $font-family-monospace: 'Custom Font', 'Courier New', Courier, monospace; // Importing bootstrap-italia SCSS library @import 'bootstrap-italia/src/scss/bootstrap-italia'; ``` +
### Icon and asset support @@ -250,6 +254,7 @@ Edit your `angular.json` by adding: ] } ``` + You can use the localised labels of the `design-angular-kit` library in your application, e.g. `{{'en.errors.required-field' | translate}}`. [See our labels](projects/design-angular-kit/assets/i18n/en.json) #### Existing location @@ -257,7 +262,6 @@ You can use the localised labels of the `design-angular-kit` library in your app If you already use localisation files in your app, you can use the library [ngx-translate-multi-http-loader](https://www.npmjs.com/package/ngx-translate-multi-http-loader) to load both the app's localisation files and those of the `design-angular-kit` library - **Using the `provideDesignAngularKit` function:** ```typescript @@ -269,16 +273,18 @@ import { provideDesignAngularKit } from 'design-angular-kit'; provideDesignAngularKit({ translateLoader: (itPrefix: string, itSuffix: string) => ({ provide: TranslateLoader, - useFactory: (http: HttpBackend) => new MultiTranslateHttpLoader(http, [ - { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file - { prefix: './assets/i18n/' }, // Your i18n location - ]), - deps: [HttpBackend] + useFactory: (http: HttpBackend) => + new MultiTranslateHttpLoader(http, [ + { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file + { prefix: './assets/i18n/' }, // Your i18n location + ]), + deps: [HttpBackend], }), -}) +}); ``` **Using the `DesignAngularKitModule`:** + ```typescript import { HttpBackend } from '@angular/common/http'; import { TranslateLoader } from '@ngx-translate/core'; @@ -288,18 +294,20 @@ import { DesignAngularKitModule } from 'design-angular-kit'; DesignAngularKitModule.forRoot({ translateLoader: (itPrefix: string, itSuffix: string) => ({ provide: TranslateLoader, - useFactory: (http: HttpBackend) => new MultiTranslateHttpLoader(http, [ - { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file - { prefix: './assets/i18n/' }, // Your i18n location - ]), - deps: [HttpBackend] + useFactory: (http: HttpBackend) => + new MultiTranslateHttpLoader(http, [ + { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file + { prefix: './assets/i18n/' }, // Your i18n location + ]), + deps: [HttpBackend], }), -}) +}); ``` #### Localisation customisation If you want to customise our labels: + - Do not include i18n support in your `angular.json`. - Create your custom location files in your `assets/bootstrap-italia/i18n/` folder (create the path if it does not exist) - The json must have [this format](projects/design-angular-kit/assets/i18n/en.json). @@ -317,13 +325,12 @@ import { ItAlertComponent, ItPaginationComponent, ItBreadcrumbsModule } from 'de @NgModule({ imports: [ - ItAlertComponent, - ItPaginationComponent, - ItBreadcrumbsModule // Includes ItBreadcrumbComponent and ItBreadcrumbItemComponent + ItAlertComponent, + ItPaginationComponent, + ItBreadcrumbsModule, // Includes ItBreadcrumbComponent and ItBreadcrumbItemComponent ], }) -export class YourAppModule { -} +export class YourAppModule {} ``` ```typescript @@ -333,19 +340,18 @@ import { ItAlertComponent, ItPaginationComponent, ItBreadcrumbsModule } from 'de selector: 'app-product', standalone: true, imports: [ItAlertComponent, ItPaginationComponent, ItBreadcrumbsModule], - templateUrl: './product.component.html' + templateUrl: './product.component.html', }) -export class ProductComponent { -} +export class ProductComponent {} ``` ## How to contribute 💙 👉🏻 You can contribute to the library in various ways: -* With your own code, taking charge of an issue among those open and not already assigned among [the issues](https://github.com/italia/design-angular-kit/issues) of Angular Kit (a comment on the issue is also sufficient to notify the willingness to take charge). -* By reporting bugs or improvements to the [official repository](https://github.com/italia/design-angular-kit/) of Angular Kit. -* By writing to us on Slack's [dedicated channel](https://developersitalia.slack.com/messages/C04H3C19D52/). +- With your own code, taking charge of an issue among those open and not already assigned among [the issues](https://github.com/italia/design-angular-kit/issues) of Angular Kit (a comment on the issue is also sufficient to notify the willingness to take charge). +- By reporting bugs or improvements to the [official repository](https://github.com/italia/design-angular-kit/) of Angular Kit. +- By writing to us on Slack's [dedicated channel](https://developersitalia.slack.com/messages/C04H3C19D52/). ## How to contribute the code @@ -438,9 +444,9 @@ npm run test Special thanks to those who made the development of this library possible! -[![Antonino Bonanno](https://github.com/AntoninoBonanno.png?size=100)](https://github.com/AntoninoBonanno) | [![Cristian Borelli](https://github.com/cri99.png?size=100)](https://github.com/cri99) | [![Alessio Napolitano](https://github.com/alenap93.png?size=100)](https://github.com/alenap93) | ---- | --- | --- | -Antonino Bonanno | Cristian Borelli | Alessio Napolitano | +| [![Antonino Bonanno](https://github.com/AntoninoBonanno.png?size=100)](https://github.com/AntoninoBonanno) | [![Cristian Borelli](https://github.com/cri99.png?size=100)](https://github.com/cri99) | [![Alessio Napolitano](https://github.com/alenap93.png?size=100)](https://github.com/alenap93) | +| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| Antonino Bonanno | Cristian Borelli | Alessio Napolitano | and thanks to [NetService team](https://www.net-serv.it/): @@ -448,7 +454,7 @@ and thanks to [NetService team](https://www.net-serv.it/): --- -All contributors (*made with [contributors-img](https://contrib.rocks)*) +All contributors (_made with [contributors-img](https://contrib.rocks)_) diff --git a/README.md b/README.md index 0bfb9dd7..c024c206 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,25 @@ npm install design-angular-kit --save Scegli la versione corrispondente alla tua versione Angular: | Angular | design-angular-kit | -|---------|--------------------| +| ------- | ------------------ | | 18+ | v1.1.0 + | | 17+ | v1.0.0 + | +In alternativa, puoi lanciar il comando + +```sh +ng add design-angular-kit --project +``` + +Eseguirà in serie: + +- scelta della corretta versione da installare +- installazione della dipendenza +- aggiunta della dipendenza al package.json +- configurazione dell'applicazione + +Le istruzioni del paragrafo successivo, **Configurazione**, verranno eseguite automaticamente, eccetto per la personalizzazione della configurazione di _i18n_. + ## Configurazione ### Configurazione app @@ -84,49 +99,39 @@ poter inizializzare le funzionalità della libreria. import { provideDesignAngularKit } from 'design-angular-kit'; export const appConfig: ApplicationConfig = { - providers: [ - ... - provideDesignAngularKit(), - ] -} + providers: [...provideDesignAngularKit()], +}; ``` #### Applicazione modulare -È necessario importare `DesignAngularKitModule` all'interno del modulo principale dell'applicazione (solitamente denominato **AppModule**) +È necessario importare `DesignAngularKitModule` all'interno del modulo principale dell'applicazione (solitamente denominato **AppModule**) utilizzando il metodo `forRoot` per poter inizializzare le funzionalità della libreria e **importare tutti i componenti**. ```typescript import { DesignAngularKitModule } from 'design-angular-kit'; @NgModule({ - imports: [ - ... - DesignAngularKitModule.forRoot() - ] + imports: [...DesignAngularKitModule.forRoot()], }) -export class AppModule { } +export class AppModule {} ``` Utilizza il metodo `forChild` durante l'importazione del modulo `DesignAngularKitModule` in altri moduli dell'applicazione per **importare tutti i componenti** della libreria. - ```typescript import { DesignAngularKitModule } from 'design-angular-kit'; @NgModule({ - imports: [ - ... - DesignAngularKitModule.forChild() - ], + imports: [...DesignAngularKitModule.forChild()], exports: [DesignAngularKitModule], }) -export class SharedModule { } +export class SharedModule {} ``` #### Applicazione ibrida -Se nella tua applicazione è presente il modulo **AppModule** ma vuoi utilizzare i nostri **componenti con la configurazione _standalone_**, +Se nella tua applicazione è presente il modulo **AppModule** ma vuoi utilizzare i nostri **componenti con la configurazione _standalone_**, utilizza la funzione `provideDesignAngularKit` all'interno del modulo principale dell'applicazione per poter inizializzare le funzionalità della libreria. ```typescript @@ -134,11 +139,9 @@ import { provideDesignAngularKit } from 'design-angular-kit'; @NgModule({ imports: [], - providers: [ - provideDesignAngularKit(), - ] + providers: [provideDesignAngularKit()], }) -export class AppModule { } +export class AppModule {} ``` #### Parametri di configurazione @@ -161,7 +164,7 @@ const initConfig: DesignAngularKitConfig | undefined = { * @default true */ loadFont: boolean | undefined, - + ... }; @@ -171,11 +174,12 @@ DesignAngularKitModule.forRoot(initConfig) ``` ### Importazione stili bootstrap-italia + Configura gli stili richiesti nel file `styles.scss`. Importa la libreria SCSS come mostrato nell'esempio qui sotto. ```scss // Importazione libreria SCSS di bootstrap-italia -@import "bootstrap-italia/src/scss/bootstrap-italia"; +@import 'bootstrap-italia/src/scss/bootstrap-italia'; ```
@@ -190,7 +194,6 @@ L’utilizzo del blu #0066CC dovrebbe però essere riservato alle amministrazion Stato, e quindi ci si può trovare nella condizione di dover personalizzare i valori delle variabili colore di Bootstrap Italia, impostando nuovi valori per le proprie necessità. - Questo colore e le altre tonalità vengono generate a partire dalla terna HSB, pertanto occorre modificare le variabili primary-h, primary-s e primary-b. Per avere la corrispondenza tra valore esadecimale del colore e HSB si può utilizzare il portale rgb.to, ad esempio https://rgb.to/0066CC. @@ -213,6 +216,7 @@ $font-family-monospace: 'Custom Font', 'Courier New', Courier, monospace; // Importazione libreria SCSS di bootstrap-italia @import 'bootstrap-italia/src/scss/bootstrap-italia'; ``` +
### Supporto icone e assets @@ -250,6 +254,7 @@ Modifica il tuo `angular.json` aggiungendo: ] } ``` + Puoi utilizzare le label localizzate della libreria `design-angular-kit` nella tua applicazione, ad esempio `{{'it.errors.required-field' | translate}}`. [Vedi le nostre label](projects/design-angular-kit/assets/i18n/it.json) #### Localizzazione esistente @@ -257,7 +262,6 @@ Puoi utilizzare le label localizzate della libreria `design-angular-kit` nella t Se utilizzi già i file di localizzazione nella tua app, puoi utilizzare la libreria [ngx-translate-multi-http-loader](https://www.npmjs.com/package/ngx-translate-multi-http-loader) per caricare sia i file di localizzazione dell'app che quelli della libreria `design-angular-kit` - **Utilizzando la funzione `provideDesignAngularKit`:** ```typescript @@ -269,16 +273,18 @@ import { provideDesignAngularKit } from 'design-angular-kit'; provideDesignAngularKit({ translateLoader: (itPrefix: string, itSuffix: string) => ({ provide: TranslateLoader, - useFactory: (http: HttpBackend) => new MultiTranslateHttpLoader(http, [ - { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file - { prefix: './assets/i18n/' }, // Your i18n location - ]), - deps: [HttpBackend] + useFactory: (http: HttpBackend) => + new MultiTranslateHttpLoader(http, [ + { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file + { prefix: './assets/i18n/' }, // Your i18n location + ]), + deps: [HttpBackend], }), -}) +}); ``` **Utilizzando il modulo `DesignAngularKitModule`:** + ```typescript import { HttpBackend } from '@angular/common/http'; import { TranslateLoader } from '@ngx-translate/core'; @@ -288,22 +294,24 @@ import { DesignAngularKitModule } from 'design-angular-kit'; DesignAngularKitModule.forRoot({ translateLoader: (itPrefix: string, itSuffix: string) => ({ provide: TranslateLoader, - useFactory: (http: HttpBackend) => new MultiTranslateHttpLoader(http, [ - { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file - { prefix: './assets/i18n/' }, // Your i18n location - ]), - deps: [HttpBackend] + useFactory: (http: HttpBackend) => + new MultiTranslateHttpLoader(http, [ + { prefix: itPrefix, suffix: itSuffix }, // Load library translations first, so you can edit the keys in your localization file + { prefix: './assets/i18n/' }, // Your i18n location + ]), + deps: [HttpBackend], }), -}) +}); ``` #### Personalizzazione della localizzazione Se vuoi personalizzare le nostre label: -- Non includere il supporto i18n nel tuo `angular.json` - - Crea i tuoi file di localizzazione personalizzati nella tua cartella `assets/bootstrap-italia/i18n/` (crea il percorso se non esiste) - - Il json deve avere [questo formato](projects/design-angular-kit/assets/i18n/it.json). - - Aggiungi nella configurazione iniziale della libreria il `translateLoader` custom, sostituendo la stringa `assets/bootstrap-italia/i18n/` all'attributo `itPrefix` + +- Non includere il supporto i18n nel tuo `angular.json` + - Crea i tuoi file di localizzazione personalizzati nella tua cartella `assets/bootstrap-italia/i18n/` (crea il percorso se non esiste) + - Il json deve avere [questo formato](projects/design-angular-kit/assets/i18n/it.json). + - Aggiungi nella configurazione iniziale della libreria il `translateLoader` custom, sostituendo la stringa `assets/bootstrap-italia/i18n/` all'attributo `itPrefix` - Oppure, aggiungi le localizzazioni nei tuoi file json, sovrascrivendo le [chiavi del json della libreria](projects/design-angular-kit/assets/i18n/it.json). ### Utilizzo @@ -317,13 +325,12 @@ import { ItAlertComponent, ItPaginationComponent, ItBreadcrumbsModule } from 'de @NgModule({ imports: [ - ItAlertComponent, - ItPaginationComponent, - ItBreadcrumbsModule // Include ItBreadcrumbComponent e ItBreadcrumbItemComponent + ItAlertComponent, + ItPaginationComponent, + ItBreadcrumbsModule, // Include ItBreadcrumbComponent e ItBreadcrumbItemComponent ], }) -export class YourAppModule { -} +export class YourAppModule {} ``` ```typescript @@ -333,24 +340,23 @@ import { ItAlertComponent, ItPaginationComponent, ItBreadcrumbsModule } from 'de selector: 'app-product', standalone: true, imports: [ItAlertComponent, ItPaginationComponent, ItBreadcrumbsModule], - templateUrl: './product.component.html' + templateUrl: './product.component.html', }) -export class ProductComponent { -} +export class ProductComponent {} ``` ## Come contribuire 💙 👉🏻 È possibile contribuire alla libreria in vari modi: -* Con il proprio codice, prendendo in carico una issue tra quelle aperte e non già assegnate tra [le issue](https://github.com/italia/design-angular-kit/issues) di Angular Kit (è sufficiente anche un commento sulla issue per notificare la volontà di presa in carico). -* Attraverso la segnalazione di bug o miglioramenti al [repository ufficiale](https://github.com/italia/design-angular-kit/) di Angular Kit. -* Scrivendoci sul [canale dedicato](https://developersitalia.slack.com/messages/C04H3C19D52/) di Slack. +- Con il proprio codice, prendendo in carico una issue tra quelle aperte e non già assegnate tra [le issue](https://github.com/italia/design-angular-kit/issues) di Angular Kit (è sufficiente anche un commento sulla issue per notificare la volontà di presa in carico). +- Attraverso la segnalazione di bug o miglioramenti al [repository ufficiale](https://github.com/italia/design-angular-kit/) di Angular Kit. +- Scrivendoci sul [canale dedicato](https://developersitalia.slack.com/messages/C04H3C19D52/) di Slack. ## Come contribuire con il codice Vorresti dare una mano su Design Angular Kit? **Sei nel posto giusto!** - + Se non l'hai già fatto, inizia spendendo qualche minuto per approfondire la tua conoscenza sulle [linee guida di design per i servizi web della PA](https://design-italia.readthedocs.io/it/stable/index.html), e fai riferimento alle [indicazioni su come contribuire a Design Angular Kit](https://github.com/italia/design-angular-kit/blob/main/CONTRIBUTING.md). @@ -410,7 +416,7 @@ git clone https://github.com/italia/design-angular-kit.git 3. Al caricamento, Visual Studio Code riconoscerà la presenta della configurazione di un Devcontainer. Aprire il progetto con il devcontainer. Altre info [qui](https://code.visualstudio.com/docs/devcontainers/create-dev-container). -4. Visual Studio Code effettuerà il setup del container, andando ad installare la corretta versione di NodeJs, di npm e delle estensioni dell'IDE. Le dipendenze di progetto saranno installate nel processo di creazione del container. L'ambiente di sviuppo sarà pronto a setup ultimato. +4. Visual Studio Code effettuerà il setup del container, andando ad installare la corretta versione di NodeJs, di npm e delle estensioni dell'IDE. Le dipendenze di progetto saranno installate nel processo di creazione del container. L'ambiente di sviuppo sarà pronto a setup ultimato. 5. Lanciare l'applicazione in locale @@ -438,9 +444,9 @@ npm run test Un grazie speciale a chi ha reso possibile lo sviluppo di questa libreria -[![Antonino Bonanno](https://github.com/AntoninoBonanno.png?size=100)](https://github.com/AntoninoBonanno) | [![Cristian Borelli](https://github.com/cri99.png?size=100)](https://github.com/cri99) | [![Alessio Napolitano](https://github.com/alenap93.png?size=100)](https://github.com/alenap93) | ---- | --- | --- | -Antonino Bonanno | Cristian Borelli | Alessio Napolitano | +| [![Antonino Bonanno](https://github.com/AntoninoBonanno.png?size=100)](https://github.com/AntoninoBonanno) | [![Cristian Borelli](https://github.com/cri99.png?size=100)](https://github.com/cri99) | [![Alessio Napolitano](https://github.com/alenap93.png?size=100)](https://github.com/alenap93) | +| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| Antonino Bonanno | Cristian Borelli | Alessio Napolitano | e grazie in particolare al team di [NetService](https://www.net-serv.it/): @@ -448,7 +454,7 @@ e grazie in particolare al team di [NetService](https://www.net-serv.it/): --- -Tutti i contributor (*made with [contributors-img](https://contrib.rocks)*) +Tutti i contributor (_made with [contributors-img](https://contrib.rocks)_)
diff --git a/package-lock.json b/package-lock.json index db1ef7f3..7e867ee2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@angular-devkit/schematics": "^18.0.7", "@angular/animations": "^18.0.6", + "@angular/cdk": "^18.2.10", "@angular/common": "^18.0.6", "@angular/compiler": "^18.0.6", "@angular/core": "^18.0.6", @@ -54,12 +55,14 @@ "@typescript-eslint/parser": "^7.15.0", "browserslist-config-design-italia": "^1.1.0", "concurrently": "^8.2.2", + "copyfiles": "^2.4.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "gh-pages": "^6.1.1", "husky": "^9.0.11", "is-ci": "^3.0.1", + "jasmine": "^5.4.0", "jasmine-core": "~5.1.2", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.4.3", @@ -718,6 +721,23 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/@angular/cdk": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.10.tgz", + "integrity": "sha512-Weh0slrfWNp5N6UO4m3tXzs2QBFexNsnJf1dq0oaLDBgfkuqUmxdCkurSv5+lWZRkTPLYmd/hQeJpvrhxMCleg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^18.0.0 || ^19.0.0", + "@angular/core": "^18.0.0 || ^19.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@angular/cli": { "version": "18.0.7", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.0.7.tgz", @@ -9675,6 +9695,80 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/copyfiles": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^1.0.4", + "noms": "0.0.0", + "through2": "^2.0.1", + "untildify": "^4.0.0", + "yargs": "^16.1.0" + }, + "bin": { + "copyfiles": "copyfiles", + "copyup": "copyfiles" + } + }, + "node_modules/copyfiles/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/copyfiles/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/copyfiles/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/core-js": { "version": "3.37.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", @@ -10810,7 +10904,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.12" }, @@ -14455,6 +14549,20 @@ "node": ">=8" } }, + "node_modules/jasmine": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.4.0.tgz", + "integrity": "sha512-E2u4ylX5tgGYvbynImU6EUBKKrSVB1L72FEPjGh4M55ov1VsxR26RA2JU91L9YSPFgcjo4mCLyKn/QXvEYGBkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.2.2", + "jasmine-core": "~5.4.0" + }, + "bin": { + "jasmine": "bin/jasmine.js" + } + }, "node_modules/jasmine-core": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.1.2.tgz", @@ -14471,6 +14579,13 @@ "colors": "1.4.0" } }, + "node_modules/jasmine/node_modules/jasmine-core": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.4.0.tgz", + "integrity": "sha512-T4fio3W++llLd7LGSGsioriDHgWyhoL6YTu4k37uwJLF7DzOzspz7mNxRoM3cQdLWtL/ebazQpIf/yZGJx/gzg==", + "dev": true, + "license": "MIT" + }, "node_modules/java-properties": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", @@ -17085,6 +17200,44 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, + "node_modules/noms": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", + "dev": true, + "license": "ISC", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" + } + }, + "node_modules/noms/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/noms/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/noms/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true, + "license": "MIT" + }, "node_modules/nopt": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", @@ -20860,7 +21013,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, + "devOptional": true, "dependencies": { "entities": "^4.4.0" }, @@ -24996,6 +25149,16 @@ "node": ">= 0.8" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", diff --git a/package.json b/package.json index f4925160..a48ef1fb 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "start": "npm run compodoc-compile && concurrently \"npm run nunjucks-compile -- -w --path .\" \"ng serve\"", "build": "npm run nunjucks-compile -- --path . && npm run compodoc-compile && ng build --base-href design-angular-kit", "build:lib": "ng build design-angular-kit", + "postbuild:lib": "tsc -p projects/design-angular-kit/tsconfig.schematics.json && node postbuildSchematics.js", "watch:lib": "ng build --configuration development --watch design-angular-kit", "test": "ng test design-angular-kit --browsers=ChromeHeadless --no-watch", "e2e": "npm run compodoc-compile && npm run nunjucks-compile && ng e2e", @@ -19,7 +20,8 @@ "postversion": "npm version $npm_package_version --prefix projects/design-angular-kit/ --no-git-tag-version", "documentation-deploy-to-gh-pages": "gh-pages -d dist/design-angular-kit-bundle/browser -m 'chore: update documentation'", "compodoc-compile": "compodoc -p projects/design-angular-kit/tsconfig.lib.json -e json -d src/assets", - "nunjucks-compile": "nunjucks --options nunjucks.json src/app/**/*.tpl" + "nunjucks-compile": "nunjucks --options nunjucks.json src/app/**/*.tpl", + "schematics:test": "ts-node --project projects/design-angular-kit/tsconfig.schematics.json node_modules/jasmine/bin/jasmine projects/design-angular-kit/schematics/**/*.spec.ts" }, "browserslist": [ "extends browserslist-config-design-italia" @@ -63,6 +65,7 @@ "dependencies": { "@angular-devkit/schematics": "^18.0.7", "@angular/animations": "^18.0.6", + "@angular/cdk": "^18.2.10", "@angular/common": "^18.0.6", "@angular/compiler": "^18.0.6", "@angular/core": "^18.0.6", @@ -106,12 +109,14 @@ "@typescript-eslint/parser": "^7.15.0", "browserslist-config-design-italia": "^1.1.0", "concurrently": "^8.2.2", + "copyfiles": "^2.4.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "gh-pages": "^6.1.1", "husky": "^9.0.11", "is-ci": "^3.0.1", + "jasmine": "^5.4.0", "jasmine-core": "~5.1.2", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.4.3", diff --git a/postbuildSchematics.js b/postbuildSchematics.js new file mode 100644 index 00000000..744100e6 --- /dev/null +++ b/postbuildSchematics.js @@ -0,0 +1,23 @@ +var copyfiles = require('copyfiles'); + +var callback = function(e) { + if(e) { + console.error(e) + } +}; + +// COPY collection.json + +//copyfiles -f projects/design-angular-kit/schematics/collection.json dist/design-angular-kit/schematics/ +var collectionSourcePath = 'projects/design-angular-kit/schematics/collection.json'; +var collectionDestionationPath = 'dist/design-angular-kit/schematics/'; +var collectionConfig = {verbose: true, flat: true, up: 3}; +copyfiles([collectionSourcePath, collectionDestionationPath],collectionConfig, callback); + +// COPY schematics/*/schema.json + +//copyfiles -f projects/design-angular-kit/schematics/*/schema.json dist/design-angular-kit/" +var schemajsonSourcePath = 'projects/design-angular-kit/schematics/*/schema.json'; +var schemajsonDestionationPath = 'dist/design-angular-kit/'; +var schemajsonConfig = {verbose: true, flat: false, up: 2}; +copyfiles([schemajsonSourcePath, schemajsonDestionationPath], schemajsonConfig, callback); \ No newline at end of file diff --git a/projects/design-angular-kit/package.json b/projects/design-angular-kit/package.json index d92a8e39..6c2b6443 100644 --- a/projects/design-angular-kit/package.json +++ b/projects/design-angular-kit/package.json @@ -27,6 +27,14 @@ "url": "https://www.net-serv.it/" } ], + "scripts": { + "build": "tsc -p tsconfig.schematics.json", + "postbuild": "copyfiles schematics/*/schema.json schematics/*/files/** schematics/collection.json ../../dist/my-lib/" + }, + "schematics": "./schematics/collection.json", + "ng-add": { + "save": "dependencies" + }, "dependencies": { "tslib": "^2.6.3" }, @@ -40,5 +48,9 @@ "@ngx-translate/http-loader": "^8.0.0", "bootstrap-italia": "^2.8.8" }, - "sideEffects": false + "sideEffects": false, + "devDependencies": { + "copyfiles": "file:../../node_modules/copyfiles", + "typescript": "file:../../node_modules/typescript" + } } diff --git a/projects/design-angular-kit/schematics/collection.json b/projects/design-angular-kit/schematics/collection.json new file mode 100644 index 00000000..2e9239fb --- /dev/null +++ b/projects/design-angular-kit/schematics/collection.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json", + "schematics": { + "ng-add": { + "description": "Add my Design Angular Kit to the project.", + "factory": "./ng-add/index", + "schema": "./ng-add/schema.json", + "hidden": true, + "aliases": ["install"] + }, + "ng-add-setup-project": { + "description": "Sets up the specified project after the ng-add dependencies have been installed", + "factory": "./ng-add/setup-project", + "schema": "./ng-add/schema.json", + "hidden": true, + "private": true + } + } + } \ No newline at end of file diff --git a/projects/design-angular-kit/schematics/ng-add/index.spec.ts b/projects/design-angular-kit/schematics/ng-add/index.spec.ts new file mode 100644 index 00000000..27738944 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/index.spec.ts @@ -0,0 +1,45 @@ +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; +import * as path from 'path'; +import { Schema as SchematicOptions } from './schema'; + +describe(`ng add design-angular-kit`, () => { + const collectionPath = path.join(__dirname, '../collection.json'); + const runner = new SchematicTestRunner('schematics', collectionPath); + + const defaultOptions: SchematicOptions = { + project: 'test-project', // Set your default project name + }; + + let appTree: UnitTestTree; + + beforeEach(async () => { + // Simulate an Angular workspace project before running the schematic + appTree = await runner.runExternalSchematic('@schematics/angular', 'workspace', { + name: 'workspace', + version: '6.0.0', + newProjectRoot: 'projects', + }); + + appTree = await runner.runExternalSchematic( + '@schematics/angular', + 'application', + { + name: defaultOptions.project, + standalone: false, + }, + appTree + ); + }); + + it('should add DesignAngularKitModule to package.json', async () => { + const tree = await runner.runSchematic('ng-add', defaultOptions, appTree); + + // Check if the package.json file exists + const packageJsonPath = '/package.json'; + expect(tree.files).toContain(packageJsonPath); + + // Check if the correct dependency was added + const content = tree.readContent(packageJsonPath); + expect(content).toContain(`"design-angular-kit"`); + }); +}); diff --git a/projects/design-angular-kit/schematics/ng-add/index.ts b/projects/design-angular-kit/schematics/ng-add/index.ts new file mode 100644 index 00000000..5fbf89a9 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/index.ts @@ -0,0 +1,36 @@ +import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; +import { NodePackageInstallTask, RunSchematicTask } from '@angular-devkit/schematics/tasks'; + +import { Schema } from './schema'; +import { addPackageToPackageJson, getPackageVersionFromPackageJson, toSemVerObject } from './utils'; +import { getPackageVersion } from './versions-helper'; + +const DESIGN_ANGULAR_KIT_PACKAGE_NAME = 'design-angular-kit'; +const NG_LATEST_VERSION = '19.0.0'; + +export default function (options: Schema): Rule { + return (host: Tree, context: SchematicContext) => { + // Get the version of `@angular/core` + // This tag should be preferred because all Angular dependencies should have the same version tag if possible. + const ngCoreVersionTag = getPackageVersionFromPackageJson(host, '@angular/core'); + const designAngularKitVersionRange = getPackageVersionFromPackageJson(host, DESIGN_ANGULAR_KIT_PACKAGE_NAME); + const angularDependencyVersion = ngCoreVersionTag || NG_LATEST_VERSION; + + const { major: angularMajorVersion } = toSemVerObject(angularDependencyVersion); + + const designAngularKitPackageVersion = getPackageVersion({ angularMajorVersion }); + + // The CLI inserts `design-angular-kit` into the `package.json` before this schematic runs. + // This means that we do not need to insert Design Angular Kit into `package.json` files again. + if (designAngularKitVersionRange === null) { + addPackageToPackageJson(host, DESIGN_ANGULAR_KIT_PACKAGE_NAME, designAngularKitPackageVersion); + } + + addPackageToPackageJson(host, '@angular/cdk', angularDependencyVersion); + addPackageToPackageJson(host, '@angular/animations', angularDependencyVersion); + + const installTaskId = context.addTask(new NodePackageInstallTask()); + + context.addTask(new RunSchematicTask('ng-add-setup-project', options), [installTaskId]); + }; +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-animations.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-animations.ts new file mode 100644 index 00000000..861c5ef5 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-animations.ts @@ -0,0 +1,7 @@ +import { callRule, noop, Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; + +export function addAnimations(): Rule { + //this dependency should be provided at application level instead of lib level. ref: provideDesignAngularKit + //provideAnimationsAsync(), + return (host: Tree, context: SchematicContext) => callRule(noop(), host, context); +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-assets.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-assets.ts new file mode 100644 index 00000000..2ad0f95d --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-assets.ts @@ -0,0 +1,45 @@ +import { JsonArray, JsonObject, workspaces } from '@angular-devkit/core'; +import { Rule, Tree } from '@angular-devkit/schematics'; +import { readWorkspace, writeWorkspace } from '@schematics/angular/utility'; + +import { Schema } from '../../schema'; +import { getProjectTargetOptions } from './angular-json-helper'; +import { NoProjectException } from './exceptions'; + +const ASSETS_CONFIG = { + glob: '**/*', + input: './node_modules/bootstrap-italia/', + output: '/bootstrap-italia/', +}; + +export function addAssets(options: Schema): Rule { + return async (host: Tree) => { + const workspace = await readWorkspace(host); + + const projectName = options.project || workspace.extensions.defaultProject!.toString(); + const project = workspace.projects.get(projectName); + if (!project) { + throw new NoProjectException(projectName); + } + + addAssetsToAngularJson(project); + await writeWorkspace(host, workspace); + }; +} + +function addAssetsToAngularJson(project: workspaces.ProjectDefinition) { + const targetOptions = getProjectTargetOptions(project, 'build'); + const assets = targetOptions.assets as JsonArray | undefined; + if (!assets) { + targetOptions.assets = [ASSETS_CONFIG]; + } else { + const existingAssets = assets.map(s => (typeof s === 'string' ? s : (s as JsonObject)!['input'])) as Array; + + for (const [, input] of existingAssets.entries()) { + if (input === ASSETS_CONFIG.input) { + return; + } + } + assets.push(ASSETS_CONFIG); + } +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-design-angular-kit.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-design-angular-kit.ts new file mode 100644 index 00000000..505c3791 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-design-angular-kit.ts @@ -0,0 +1,40 @@ +import { Rule, SchematicContext, Tree, callRule } from '@angular-devkit/schematics'; +import { isStandaloneApp } from '@angular/cdk/schematics'; +import { addRootImport, addRootProvider, readWorkspace } from '@schematics/angular/utility'; +import { getMainFilePath } from '@schematics/angular/utility/standalone/util'; +import { firstValueFrom, map } from 'rxjs'; +import { Schema } from '../../schema'; +import { NoMainFileException, NoProjectException } from './exceptions'; + +export function addDesignAngularKit(options: Schema): Rule { + return async (host: Tree, context: SchematicContext) => { + const workspace = await readWorkspace(host); + const projectName = options.project || (workspace.extensions.defaultProject as string); + + // 1. getting project by name + const project = workspace.projects.get(projectName); + if (!project) { + throw new NoProjectException(projectName); + } + + // 2. getting main file for project + const mainFilePath = await getMainFilePath(host, projectName); + if (!mainFilePath || !host.read(mainFilePath)) { + throw new NoMainFileException(projectName); + } + + const isNotStandaloneApp = !isStandaloneApp(host, mainFilePath); + + const rule = isNotStandaloneApp + ? addRootImport(projectName, ({ code, external }) => code`${external('DesignAngularKitModule', 'design-angular-kit')}.forRoot()\n`) + : addRootProvider(projectName, ({ code, external }) => code`${external('provideDesignAngularKit', 'design-angular-kit')}()`); + + return firstValueFrom( + callRule(rule, host, context).pipe( + map(() => { + return (): Rule => () => {}; + }) + ) + ); + }; +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-http-client.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-http-client.ts new file mode 100644 index 00000000..f0de5cae --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-http-client.ts @@ -0,0 +1,7 @@ +import { Rule, SchematicContext, Tree, callRule, noop } from '@angular-devkit/schematics'; + +export function addHttpClient(): Rule { + //this dependency should be provided at application level instead of lib level. ref: provideDesignAngularKit + //provideHttpClient(), + return (host: Tree, context: SchematicContext) => callRule(noop(), host, context); +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-import-to-style-file.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-import-to-style-file.ts new file mode 100644 index 00000000..fbbfc71a --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-import-to-style-file.ts @@ -0,0 +1,120 @@ +import { JsonArray, JsonObject, normalize, workspaces } from '@angular-devkit/core'; +import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; + +import { readWorkspace, writeWorkspace } from '@schematics/angular/utility'; +import * as path from 'path'; + +import { Schema } from '../../schema'; +import { getProjectTargetOptions } from './angular-json-helper'; +import { NoProjectException } from './exceptions'; + +const BOOTSTRAP_ITALIA_CSS_FILEPATH = 'node_modules/bootstrap-italia/dist/css/bootstrap-italia.min.css'; +const SUPPORTED_BOOTSTRAP_ITALIA_STYLE_MAP: Record = { + '.sass': ` + /* Importazione libreria SCSS di bootstrap-italia */ + @import 'bootstrap-italia/scss/bootstrap-italia' + `, + '.scss': ` + /* Importazione libreria SCSS di bootstrap-italia */ + @import '../node_modules/bootstrap-italia/src/scss/bootstrap-italia.scss'; + `, +}; + +/** + * if supported + * add to styles.scss or to style.sass + * else + * add css to assets in angular.json + * @param options + * @returns Rule + */ +export function addImportToStyleFile(options: Schema): Rule { + return async (host: Tree, context: SchematicContext) => { + const workspace = await readWorkspace(host); + + const projectName = options.project || workspace.extensions.defaultProject!.toString(); + const project = workspace.projects.get(projectName); + if (!project) { + throw new NoProjectException(projectName); + } + + const styleFilePath = getProjectStyleFile(project as any) || ''; + const styleFileExtension = path.extname(styleFilePath); + const styleFilePatch = SUPPORTED_BOOTSTRAP_ITALIA_STYLE_MAP[styleFileExtension]; + + // found supported styles + if (styleFilePatch) { + return addBootstrapItaliaToStylesFile(styleFilePath, styleFilePatch); + } else { + // found some styles, but unsupported + if (styleFileExtension !== '.css' && styleFileExtension !== '') { + context.logger.warn('messages.unsupportedStyles(styleFilePath)'); + } + + // just patching 'angular.json' + addBootstrapItaliaToAngularJson(project as any); + await writeWorkspace(host, workspace); + } + }; +} + +function addBootstrapItaliaToStylesFile(styleFilePath: string, styleFilePatch: string): Rule { + return async (host: Tree) => { + const styleContent = host.read(styleFilePath)!.toString('utf-8'); + + const recorder = host.beginUpdate(styleFilePath); + recorder.insertRight(styleContent.length, styleFilePatch); + + host.commitUpdate(recorder); + }; +} + +function addBootstrapItaliaToAngularJson(project: workspaces.ProjectDefinition) { + const targetOptions = getProjectTargetOptions(project, 'build'); + const styles = targetOptions.styles as JsonArray | undefined; + if (!styles) { + targetOptions.styles = [BOOTSTRAP_ITALIA_CSS_FILEPATH]; + } else { + const existingStyles = styles.map(s => (typeof s === 'string' ? s : (s as JsonObject)!['input'])) as Array; + + for (const [, stylePath] of existingStyles.entries()) { + if (stylePath === BOOTSTRAP_ITALIA_CSS_FILEPATH) { + return; + } + } + styles.unshift(BOOTSTRAP_ITALIA_CSS_FILEPATH); + } +} + +// Regular expression that matches all possible Angular CLI default style files +const defaultStyleFileRegex = /styles\.(c|le|sc|sa)ss/; + +// Regular expression that matches all files that have a proper stylesheet extension +const validStyleFileRegex = /\.(c|le|sc|sa)ss/; + +function getProjectStyleFile(project: workspaces.ProjectDefinition, extension?: string): string | null { + const buildOptions = getProjectTargetOptions(project, 'build'); + + if (buildOptions.styles && Array.isArray(buildOptions.styles) && buildOptions.styles.length) { + const styles = buildOptions.styles.map(s => (typeof s === 'string' ? s : (s as JsonObject)!['input'])) as Array; + + // Look for the default style file that is generated for new projects by the Angular CLI. This + // default style file is usually called `styles.ext` unless it has been changed explicitly. + const defaultMainStylePath = styles.find(file => (extension ? file === `styles.${extension}` : defaultStyleFileRegex.test(file))); + + if (defaultMainStylePath) { + return normalize(defaultMainStylePath); + } + + // If no default style file could be found, use the first style file that matches the given + // extension. If no extension specified explicitly, we look for any file with a valid style + // file extension. + const fallbackStylePath = styles.find(file => (extension ? file.endsWith(`.${extension}`) : validStyleFileRegex.test(file))); + + if (fallbackStylePath) { + return normalize(fallbackStylePath); + } + } + + return null; +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-localisation.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-localisation.ts new file mode 100644 index 00000000..8aed28eb --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/add-localisation.ts @@ -0,0 +1,45 @@ +import { JsonArray, JsonObject, workspaces } from '@angular-devkit/core'; +import { Rule, Tree } from '@angular-devkit/schematics'; +import { readWorkspace, writeWorkspace } from '@schematics/angular/utility'; + +import { Schema } from '../../schema'; +import { getProjectTargetOptions } from './angular-json-helper'; +import { NoProjectException } from './exceptions'; + +const LOCALISATION_CONFIG = { + glob: '**/*', + input: './node_modules/design-angular-kit/assets/i18n', + output: '/bootstrap-italia/i18n/', +}; + +export function addLocalisation(options: Schema): Rule { + return async (host: Tree) => { + const workspace = await readWorkspace(host); + + const projectName = options.project || workspace.extensions.defaultProject!.toString(); + const project = workspace.projects.get(projectName); + if (!project) { + throw new NoProjectException(projectName); + } + + addLocalisationToAngularJson(project); + await writeWorkspace(host, workspace); + }; +} + +function addLocalisationToAngularJson(project: workspaces.ProjectDefinition) { + const targetOptions = getProjectTargetOptions(project, 'build'); + const assets = targetOptions.assets as JsonArray | undefined; + if (!assets) { + targetOptions.assets = [LOCALISATION_CONFIG]; + } else { + const existingAssets = assets.map(s => (typeof s === 'string' ? s : (s as JsonObject)!['input'])) as Array; + + for (const [, input] of existingAssets.entries()) { + if (input === LOCALISATION_CONFIG.input) { + return; + } + } + assets.push(LOCALISATION_CONFIG); + } +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/angular-json-helper.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/angular-json-helper.ts new file mode 100644 index 00000000..ad042cf8 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/angular-json-helper.ts @@ -0,0 +1,11 @@ +import { workspaces } from '@angular-devkit/core'; +import { SchematicsException } from '@angular-devkit/schematics'; + +export function getProjectTargetOptions(project: workspaces.ProjectDefinition, buildTarget: string) { + const buildTargetObject = project.targets.get(buildTarget); + if (buildTargetObject && buildTargetObject.options) { + return buildTargetObject.options; + } + + throw new SchematicsException(`Cannot determine project target configuration for: ${buildTarget}.`); +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/exceptions.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/exceptions.ts new file mode 100644 index 00000000..40940452 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/exceptions.ts @@ -0,0 +1,13 @@ +import { SchematicsException } from '@angular-devkit/schematics'; + +export class NoProjectException extends SchematicsException { + constructor(project: string) { + super(`Unable to find project '${project}' in the workspace`); + } +} + +export class NoMainFileException extends SchematicsException { + constructor(project: string) { + super(`Unable to find 'build.options.main' file path for project "${project}`); + } +} diff --git a/projects/design-angular-kit/schematics/ng-add/rules/setup-project/index.ts b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/index.ts new file mode 100644 index 00000000..d9ba7d49 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/rules/setup-project/index.ts @@ -0,0 +1,6 @@ +export * from './add-animations'; +export * from './add-assets'; +export * from './add-design-angular-kit'; +export * from './add-http-client'; +export * from './add-import-to-style-file'; +export * from './add-localisation'; diff --git a/projects/design-angular-kit/schematics/ng-add/schema.json b/projects/design-angular-kit/schematics/ng-add/schema.json new file mode 100644 index 00000000..678a440a --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "design-angular-kit-ng-add", + "title": "Design Angular Hit ng-add schematic", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "Name of the project.", + "$default": { + "$source": "projectName" + } + } + }, + "required": [] +} \ No newline at end of file diff --git a/projects/design-angular-kit/schematics/ng-add/schema.ts b/projects/design-angular-kit/schematics/ng-add/schema.ts new file mode 100644 index 00000000..e7654820 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/schema.ts @@ -0,0 +1,3 @@ +export interface Schema { + project: string; +} diff --git a/projects/design-angular-kit/schematics/ng-add/setup-project.spec.ts b/projects/design-angular-kit/schematics/ng-add/setup-project.spec.ts new file mode 100644 index 00000000..780cc6ad --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/setup-project.spec.ts @@ -0,0 +1,166 @@ +import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; +import * as path from 'path'; +import { Schema } from './schema'; + +const createApp = async ( + runner: SchematicTestRunner, + options: Schema, + { standalone, style }: { standalone: boolean; style: 'scss' | 'css' | 'sass' } +) => { + let tree = await runner.runExternalSchematic('@schematics/angular', 'workspace', { + name: 'workspace', + version: '18.0.0', + newProjectRoot: 'projects', + }); + + tree = await runner.runExternalSchematic( + '@schematics/angular', + 'application', + { + name: options.project, + standalone, + style, + }, + tree + ); + + return { tree }; +}; + +describe(`ng add design-angular-kit | setup-project - library providing`, () => { + const collectionPath = path.join(__dirname, '../collection.json'); + const runner = new SchematicTestRunner('schematics', collectionPath); + + const defaultOptions: Schema = { + project: 'test-project', // Set your default project name + }; + + it('should add DesignAngularKitModule to the root module - NgModule app', async () => { + const { tree: appTree } = await createApp(runner, defaultOptions, { standalone: false, style: 'scss' }); + const tree = await runner.runSchematic('ng-add-setup-project', defaultOptions, appTree); + + // Check if the app.module.ts file exists + const modulePath = '/projects/test-project/src/app/app.module.ts'; + expect(tree.files).toContain(modulePath); + + // Check if the correct import statement was added + const content = tree.readContent(modulePath); + expect(content).toContain(`import { DesignAngularKitModule } from 'design-angular-kit';`); + expect(content).toContain(`DesignAngularKitModule.forRoot()`); + }); + + it('should add provideDesignAngularKit() to the app config - Standalone app', async () => { + const { tree: appTree } = await createApp(runner, defaultOptions, { standalone: true, style: 'scss' }); + const tree = await runner.runSchematic('ng-add-setup-project', defaultOptions, appTree); + + // Check if the app.module.ts file exists + const appConfigPath = '/projects/test-project/src/app/app.config.ts'; + expect(tree.files).toContain(appConfigPath); + + // Check if the correct import statement was added + const content = tree.readContent(appConfigPath); + expect(content).toContain(`import { provideDesignAngularKit } from 'design-angular-kit';`); + expect(content).toContain(`provideDesignAngularKit()`); + }); +}); + +for (const standalone of [true, false]) { + describe(`ng add design-angular-kit | setup-project for ${standalone ? 'standalone' : 'NgModule'} app - styles`, () => { + const collectionPath = path.join(__dirname, '../collection.json'); + const runner = new SchematicTestRunner('schematics', collectionPath); + + const defaultOptions: Schema = { + project: 'test-project', // Set your default project name + }; + + it('should add .scss import to project style file', async () => { + const { tree: appTree } = await createApp(runner, defaultOptions, { standalone, style: 'scss' }); + const tree = await runner.runSchematic('ng-add-setup-project', defaultOptions, appTree); + + // Check if the styles.scss file exists + const styleFilePath = '/projects/test-project/src/styles.scss'; + expect(tree.files).toContain(styleFilePath); + // Check if the correct import statement was added + const content = tree.readContent(styleFilePath); + expect(content).toContain(`@import '../node_modules/bootstrap-italia/src/scss/bootstrap-italia.scss';`); + }); + + it('should add .sass import to project style file', async () => { + const { tree: appTree } = await createApp(runner, defaultOptions, { standalone, style: 'sass' }); + const tree = await runner.runSchematic('ng-add-setup-project', defaultOptions, appTree); + + // Check if the styles.sass file exists + const styleFilePath = '/projects/test-project/src/styles.sass'; + expect(tree.files).toContain(styleFilePath); + // Check if the correct import statement was added + const content = tree.readContent(styleFilePath); + expect(content).toContain(`@import 'bootstrap-italia/scss/bootstrap-italia'`); + }); + + it('should add .css import to angular.json', async () => { + const { tree: appTree } = await createApp(runner, defaultOptions, { standalone, style: 'css' }); + const tree = await runner.runSchematic('ng-add-setup-project', defaultOptions, appTree); + + // Check if the angular.json file exists + const angularJsonPath = '/angular.json'; + expect(tree.files).toContain(angularJsonPath); + // Check if the correct import statement was added + const content = tree.readContent(angularJsonPath); + expect(content).toContain(`node_modules/bootstrap-italia/dist/css/bootstrap-italia.min.css`); + }); + }); + + describe(`ng add design-angular-kit | setup-project for ${standalone ? 'standalone' : 'NgModule'} app - assets`, () => { + const collectionPath = path.join(__dirname, '../collection.json'); + const runner = new SchematicTestRunner('schematics', collectionPath); + + const defaultOptions: Schema = { + project: 'test-project', // Set your default project name + }; + + it('should add bootstrap italia assets to angular.json', async () => { + const { tree: appTree } = await createApp(runner, defaultOptions, { standalone, style: 'css' }); + const tree = await runner.runSchematic('ng-add-setup-project', defaultOptions, appTree); + + // Check if the angular.json file exists + const angularJsonPath = '/angular.json'; + expect(tree.files).toContain(angularJsonPath); + // Check if the correct import statement was added + const content = tree.readContent(angularJsonPath); + //"./node_modules/bootstrap-italia/" + expect(content).toContain(`./node_modules/bootstrap-italia/`); + const angularJson = JSON.parse(content); + const assetsConfig = angularJson.projects[defaultOptions.project]?.architect?.build?.options?.assets?.find( + (item: { input: string }) => item.input === `./node_modules/bootstrap-italia/` + ); + expect(assetsConfig).toBeDefined(assetsConfig); + }); + }); + + describe(`ng add design-angular-kit | setup-project for ${standalone ? 'standalone' : 'NgModule'} app - localisation`, () => { + const collectionPath = path.join(__dirname, '../collection.json'); + const runner = new SchematicTestRunner('schematics', collectionPath); + + const defaultOptions: Schema = { + project: 'test-project', // Set your default project name + }; + + it('should add bootstrap italia localisation to angular.json', async () => { + const { tree: appTree } = await createApp(runner, defaultOptions, { standalone, style: 'css' }); + const tree = await runner.runSchematic('ng-add-setup-project', defaultOptions, appTree); + + // Check if the angular.json file exists + const angularJsonPath = '/angular.json'; + expect(tree.files).toContain(angularJsonPath); + // Check if the correct import statement was added + const content = tree.readContent(angularJsonPath); + //"./node_modules/bootstrap-italia/" + expect(content).toContain(`/node_modules/design-angular-kit/assets/i18n`); + const angularJson = JSON.parse(content); + const assetsConfig = angularJson.projects[defaultOptions.project]?.architect?.build?.options?.assets?.find( + (item: { input: string }) => item.input === `./node_modules/design-angular-kit/assets/i18n` + ); + expect(assetsConfig).toBeDefined(assetsConfig); + }); + }); +} diff --git a/projects/design-angular-kit/schematics/ng-add/setup-project.ts b/projects/design-angular-kit/schematics/ng-add/setup-project.ts new file mode 100644 index 00000000..554f6b8f --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/setup-project.ts @@ -0,0 +1,31 @@ +import { chain, Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; + +import { getProjectFromWorkspace } from '@angular/cdk/schematics'; +import { getWorkspace } from '@schematics/angular/utility/workspace'; +import { addAnimations, addAssets, addDesignAngularKit, addHttpClient, addImportToStyleFile, addLocalisation } from './rules/setup-project'; +import { Schema } from './schema'; + +import { ProjectType } from '@schematics/angular/utility/workspace-models'; + +export default function (options: Schema): Rule { + return async (host: Tree, context: SchematicContext) => { + const workspace = await getWorkspace(host); + const project = getProjectFromWorkspace(workspace, options.project); + const isAProject = project.extensions['projectType'] === ProjectType.Application; + + if (isAProject) { + return chain([ + addAnimations(), + addHttpClient(), + addDesignAngularKit(options), + addImportToStyleFile(options), + addAssets(options), + addLocalisation(options), + ]); + } + context.logger.warn( + `Design Angular Kit has been set in your workspace. No additional setup required.\nIf you intend to run the schematics on a specific project, please use -- project option ` + ); + return; + }; +} diff --git a/projects/design-angular-kit/schematics/ng-add/utils.ts b/projects/design-angular-kit/schematics/ng-add/utils.ts new file mode 100644 index 00000000..3e54c0b6 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/utils.ts @@ -0,0 +1,71 @@ +import { Tree } from '@angular-devkit/schematics'; + +interface PackageJson { + dependencies: Record; +} + +interface SemVerObject { + semVer?: string; + major?: string; + minor?: string; + patch?: string; + prerelease?: string; + buildmetadata?: string; +} + +const SEMVER_WITH_PREFIX_REGEX = + /^[\^~]?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/; + +function sortObjectByKeys(obj: Record) { + return Object.keys(obj) + .sort() + .reduce( + (result, key) => { + result[key] = obj[key]; + return result; + }, + {} as Record + ); +} + +/** Get a SemVerObject given a semver string */ +export function toSemVerObject(versionString: string) { + const [semVer, major, minor, patch, prerelease, buildmetadata] = versionString.match(SEMVER_WITH_PREFIX_REGEX) ?? []; + return { semVer, major, minor, patch, prerelease, buildmetadata } satisfies SemVerObject; +} + +/** Adds a package to the package.json in the given host tree. */ +export function addPackageToPackageJson(host: Tree, pkg: string, version: string): Tree { + if (host.exists('package.json')) { + const sourceText = host.read('package.json')!.toString('utf-8'); + const json = JSON.parse(sourceText) as PackageJson; + + if (!json.dependencies) { + json.dependencies = {}; + } + + if (!json.dependencies[pkg]) { + json.dependencies[pkg] = version; + json.dependencies = sortObjectByKeys(json.dependencies); + } + + host.overwrite('package.json', JSON.stringify(json, null, 2)); + } + + return host; +} + +/** Gets the version of the specified package by looking at the package.json in the given tree. */ +export function getPackageVersionFromPackageJson(tree: Tree, name: string): string | null { + if (!tree.exists('package.json')) { + return null; + } + + const packageJson = JSON.parse(tree.read('package.json')!.toString('utf8')) as PackageJson; + + if (packageJson.dependencies && packageJson.dependencies[name]) { + return packageJson.dependencies[name]; + } + + return null; +} diff --git a/projects/design-angular-kit/schematics/ng-add/versions-helper.ts b/projects/design-angular-kit/schematics/ng-add/versions-helper.ts new file mode 100644 index 00000000..fd3fb268 --- /dev/null +++ b/projects/design-angular-kit/schematics/ng-add/versions-helper.ts @@ -0,0 +1,41 @@ +const ANGULAR_VERSIONS = { + v17: '17', + v18: '18', +}; + +const KIT_VERSION_1_0_0 = '1.0.0'; +const KIT_VERSION_1_1_0 = '1.1.0'; +const DEFAULT = 'DEFAULT'; +const LATEST = 'LATEST'; + +const versionsMap: Record = { + [DEFAULT]: KIT_VERSION_1_0_0, + [ANGULAR_VERSIONS.v17]: KIT_VERSION_1_0_0, + [ANGULAR_VERSIONS.v18]: KIT_VERSION_1_1_0, + [LATEST]: KIT_VERSION_1_1_0, +}; + +// Get Design Angular Kit package version given Angular major version +export function getPackageVersion({ angularMajorVersion }: { angularMajorVersion: string }) { + if (isNaN(+angularMajorVersion)) { + throw new Error('Major version is not a number'); + } + + let version = versionsMap[DEFAULT]; + + switch (angularMajorVersion) { + case ANGULAR_VERSIONS.v17: + version = versionsMap[ANGULAR_VERSIONS.v17]; + break; + case ANGULAR_VERSIONS.v18: + version = versionsMap[ANGULAR_VERSIONS.v18]; + break; + default: { + if (Number(angularMajorVersion) > Number(ANGULAR_VERSIONS.v18)) { + version = versionsMap[LATEST]; + } + } + } + + return version; +} diff --git a/projects/design-angular-kit/src/lib/provide-design-angular-kit.ts b/projects/design-angular-kit/src/lib/provide-design-angular-kit.ts index f8f9dfb1..81389d4d 100644 --- a/projects/design-angular-kit/src/lib/provide-design-angular-kit.ts +++ b/projects/design-angular-kit/src/lib/provide-design-angular-kit.ts @@ -1,10 +1,10 @@ +import { HttpClient, provideHttpClient } from '@angular/common/http'; import { APP_INITIALIZER, EnvironmentProviders, importProvidersFrom, makeEnvironmentProviders, Provider } from '@angular/core'; -import { DesignAngularKitConfig, IT_ASSET_BASE_PATH } from './interfaces/design-angular-kit-config'; -import { loadFonts } from 'bootstrap-italia'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { HttpClient, provideHttpClient } from '@angular/common/http'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; +import { loadFonts } from 'bootstrap-italia'; +import { DesignAngularKitConfig, IT_ASSET_BASE_PATH } from './interfaces/design-angular-kit-config'; /** * Configures DesignAngularKit library diff --git a/projects/design-angular-kit/tsconfig.schematics.json b/projects/design-angular-kit/tsconfig.schematics.json new file mode 100644 index 00000000..2b1c343d --- /dev/null +++ b/projects/design-angular-kit/tsconfig.schematics.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "lib": ["es2018", "dom"], + "declaration": true, + "module": "commonjs", + "moduleResolution": "node", + "noEmitOnError": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitThis": true, + "noUnusedParameters": true, + "noUnusedLocals": true, + "rootDir": "schematics", + "outDir": "../../dist/design-angular-kit/schematics", + "skipDefaultLibCheck": true, + "skipLibCheck": true, + "sourceMap": true, + "strictNullChecks": true, + "target": "es6", + "types": ["jasmine", "node"] + }, + "include": ["schematics/**/*"], + "exclude": ["schematics/*/files/**/*"] +}