From 5f8cff013c9d5c561f15867e267e12af345e2f31 Mon Sep 17 00:00:00 2001 From: Barsukov Nikita Date: Thu, 14 Jul 2022 14:36:53 +0300 Subject: [PATCH] feat!: update to Angular 12 (#2110) * feat!: update to Angular 12 * feat(demo): new utility `assets` (to get URL to file from assets) * chore: run `ng update @angular/cli@12 --migrate-only production-by-default` * fix(demo-integrations): addition to `stubExternalIcons` * fix: update `@nguniversal/express-engine`-dependency --- angular.json | 50 +++++---- package.json | 44 ++++---- projects/addon-charts/test.ts | 4 +- projects/addon-commerce/test.ts | 4 +- projects/addon-doc/package.json | 2 +- .../navigation/navigation.component.ts | 2 +- projects/addon-doc/src/test.ts | 4 +- projects/addon-editor/test.ts | 4 +- projects/addon-mobile/test.ts | 4 +- projects/addon-preview/test.ts | 4 +- projects/addon-table/test.ts | 4 +- projects/addon-tablebars/test.ts | 4 +- projects/cdk/test.ts | 4 +- projects/core/test.ts | 4 +- .../support/stub-external-icons.util.ts | 11 +- projects/demo/package.json | 4 +- projects/demo/server.ts | 2 +- .../components/button/examples/1/index.ts | 11 +- .../components/combo-box/examples/1/index.ts | 15 ++- .../examples/2/database-mock-data.ts | 6 +- .../input-phone/examples/3/index.ts | 33 +++--- .../components/input/examples/4/index.ts | 101 +++++++++--------- .../components/input/examples/8/index.ts | 23 ++-- .../multi-select/examples/2/index.ts | 25 +++-- .../components/select/examples/6/index.ts | 23 ++-- .../components/svg/examples/1/index.ts | 5 +- .../modules/components/svg/svg.component.ts | 5 +- .../dropdown-selection/examples/2/index.ts | 29 +++-- .../directives/dropdown/examples/2/index.ts | 5 +- projects/demo/src/polyfills.ts | 2 +- projects/demo/src/typings.d.ts | 6 -- projects/demo/src/utils/index.ts | 1 + projects/demo/src/utils/load-assets.ts | 6 ++ projects/demo/test.ts | 4 +- projects/kit/test.ts | 4 +- projects/taiga-schematics/package.json | 4 +- projects/taiga-schematics/test.ts | 4 +- tsconfig.json | 3 +- 38 files changed, 239 insertions(+), 231 deletions(-) create mode 100644 projects/demo/src/utils/index.ts create mode 100644 projects/demo/src/utils/load-assets.ts diff --git a/angular.json b/angular.json index b461b3eb8c4a..cda866c8b7a9 100644 --- a/angular.json +++ b/angular.json @@ -504,7 +504,6 @@ } ], "options": { - "aot": true, "outputPath": "dist/demo/browser", "index": "projects/demo/src/index.html", "main": "projects/demo/src/main.browser.ts", @@ -539,7 +538,13 @@ "node_modules/prismjs/components/prism-markup.min.js", "node_modules/prismjs/components/prism-typescript.min.js" ], - "allowedCommonJsDependencies": ["angular2-text-mask", "markdown-it"] + "allowedCommonJsDependencies": ["angular2-text-mask", "markdown-it"], + "vendorChunk": true, + "extractLicenses": false, + "buildOptimizer": false, + "sourceMap": true, + "optimization": false, + "namedChunks": true }, "configurations": { "production": { @@ -553,9 +558,6 @@ "outputHashing": "all", "sourceMap": false, "namedChunks": false, - "aot": true, - "extractLicenses": false, - "vendorChunk": true, "buildOptimizer": true, "statsJson": false, "progress": false, @@ -580,9 +582,6 @@ "outputHashing": "all", "sourceMap": false, "namedChunks": false, - "aot": true, - "extractLicenses": false, - "vendorChunk": true, "buildOptimizer": true, "statsJson": false, "progress": false, @@ -614,8 +613,10 @@ }, "ru": { "localize": ["ru"] - } - } + }, + "development": {} + }, + "defaultConfiguration": "production" }, "mkcert": { "builder": "@nrwl/workspace:run-commands", @@ -640,7 +641,6 @@ } ], "options": { - "browserTarget": "demo:build", "port": 3333, "sslCert": ".ssl/localhost.pem", "sslKey": ".ssl/localhost-key.pem" @@ -658,8 +658,12 @@ }, "ru": { "browserTarget": "demo:build:ru" + }, + "development": { + "browserTarget": "demo:build:development" } - } + }, + "defaultConfiguration": "development" }, "serve:ssl": { "builder": "@nrwl/workspace:run-commands", @@ -683,16 +687,18 @@ }, "serve:ssr": { "builder": "@nguniversal/builders:ssr-dev-server", - "options": { - "browserTarget": "demo:build", - "serverTarget": "demo:server" - }, + "options": {}, "configurations": { "production": { "browserTarget": "demo:build:production", "serverTarget": "demo:server:production" + }, + "development": { + "serverTarget": "demo:server:development", + "browserTarget": "demo:build:development" } - } + }, + "defaultConfiguration": "development" }, "serve:compiled": { "builder": "@nrwl/workspace:run-commands", @@ -706,15 +712,19 @@ "tsConfig": "projects/demo/tsconfig.server.json", "stylePreprocessorOptions": { "includePaths": ["projects/core/styles"] - } + }, + "sourceMap": true, + "optimization": false }, "configurations": { "production": { "outputHashing": "media", "sourceMap": false, "optimization": true - } - } + }, + "development": {} + }, + "defaultConfiguration": "production" }, "prerender": { "builder": "@nguniversal/builders:prerender", diff --git a/package.json b/package.json index 8fccf2a856c5..ce31cb8e5dd7 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "scripts": { "postinstall": "husky install && ngcc --async", "start": "nx serve", - "build:ssr": "nx build --prod && nx run demo:server:production", + "build:ssr": "nx build --configuration production && nx run demo:server:production", "prerender": "nx run demo:prerender", "i18n": "nx xi18n --output-path src/locale", "*** Workflow ***": "", @@ -34,8 +34,8 @@ "prettier": "prettier '**/*.{svg,yml,js,ts,html,md,less,json}' --cache node_modules/.cache/prettier", "typecheck": "tsc --noEmit --skipLibCheck --incremental false --tsBuildInfoFile null --project tsconfig.spec.json", "*** Build **": "", - "build:demo": "nx build --prod --configuration=production", - "build:demo:next": "nx build --prod --configuration=next", + "build:demo": "nx build --configuration production", + "build:demo:next": "nx build --configuration next", "postbuild:demo": "npm run exec -- ./scripts/postbuild-demo.ts", "postbuild:demo:next": "npm run exec -- ./scripts/postbuild-demo.ts", "*** Release ***": "", @@ -68,29 +68,29 @@ ] }, "dependencies": { - "@angular/animations": "~11.2.14", - "@angular/cdk": "~11.2.13", - "@angular/common": "~11.2.14", - "@angular/compiler": "~11.2.14", - "@angular/core": "~11.2.14", - "@angular/forms": "~11.2.14", - "@angular/localize": "^11.2.14", - "@angular/platform-browser": "~11.2.14", - "@angular/platform-browser-dynamic": "~11.2.14", - "@angular/platform-server": "^11.2.14", - "@angular/router": "~11.2.14", + "@angular/animations": "~12.2.16", + "@angular/cdk": "~12.2.13", + "@angular/common": "~12.2.16", + "@angular/compiler": "~12.2.16", + "@angular/core": "~12.2.16", + "@angular/forms": "~12.2.16", + "@angular/localize": "^12.2.16", + "@angular/platform-browser": "~12.2.16", + "@angular/platform-browser-dynamic": "~12.2.16", + "@angular/platform-server": "^12.2.16", + "@angular/router": "~12.2.16", "core-js": "^2.6.9", "parse5": "^6.0.1", "rxjs": "~6.6.3", "tslib": "^2.0.0", - "zone.js": "~0.10.2" + "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.1102.19", - "@angular-devkit/core": "~11.2.19", - "@angular/cli": "~11.2.19", - "@angular/compiler-cli": "~11.2.14", - "@angular/language-service": "~11.2.14", + "@angular-devkit/build-angular": "~12.2.17", + "@angular-devkit/core": "~12.2.17", + "@angular/cli": "~12.2.17", + "@angular/compiler-cli": "~12.2.16", + "@angular/language-service": "~12.2.16", "@commitlint/cli": "^17.0.2", "@commitlint/config-conventional": "^17.0.2", "@nrwl/cli": "14.3.1", @@ -119,7 +119,7 @@ "husky": "^8.0.1", "kill-port": "^2.0.0", "lint-staged": "^8.2.1", - "ng-packagr": "^11.2.4", + "ng-packagr": "^12.2.7", "postcss": "^8.4.14", "prettier": "~2.7.1", "raw-loader": "^4.0.2", @@ -127,7 +127,7 @@ "standard-version": "^8.0.2", "ts-loader": "^6.2.2", "ts-node": "~10.8.1", - "typescript": "~4.0.8", + "typescript": "~4.3.5", "wait-on": "^6.0.1" }, "engines": { diff --git a/projects/addon-charts/test.ts b/projects/addon-charts/test.ts index 662a3824e57d..04402353a417 100644 --- a/projects/addon-charts/test.ts +++ b/projects/addon-charts/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/addon-commerce/test.ts b/projects/addon-commerce/test.ts index e160ffac1291..fbe636314a4f 100644 --- a/projects/addon-commerce/test.ts +++ b/projects/addon-commerce/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/addon-doc/package.json b/projects/addon-doc/package.json index af7fb3b289a1..8c57eb685660 100644 --- a/projects/addon-doc/package.json +++ b/projects/addon-doc/package.json @@ -14,7 +14,7 @@ "repository": "https://github.com/tinkoff/taiga-ui", "license": "Apache-2.0", "dependencies": { - "@angular-devkit/schematics": "~11.2.19", + "@angular-devkit/schematics": "~12.2.17", "highlight.js": "^11.5.1", "markdown-it": "^12.3.2", "ngx-highlightjs": "^4.1.4", diff --git a/projects/addon-doc/src/components/navigation/navigation.component.ts b/projects/addon-doc/src/components/navigation/navigation.component.ts index 9ab4e7fa0087..0225b5625dc8 100644 --- a/projects/addon-doc/src/components/navigation/navigation.component.ts +++ b/projects/addon-doc/src/components/navigation/navigation.component.ts @@ -78,7 +78,7 @@ export class TuiDocNavigationComponent { changeDetectorRef.markForCheck(); titleService.setTitle(title); this.openActivePageGroup(); - this.handleAnchorLink(this.activatedRoute.snapshot.fragment); + this.handleAnchorLink(this.activatedRoute.snapshot.fragment!); }); } diff --git a/projects/addon-doc/src/test.ts b/projects/addon-doc/src/test.ts index ba47179837a1..79cc6c96c023 100644 --- a/projects/addon-doc/src/test.ts +++ b/projects/addon-doc/src/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { BrowserDynamicTestingModule, diff --git a/projects/addon-editor/test.ts b/projects/addon-editor/test.ts index 662a3824e57d..04402353a417 100644 --- a/projects/addon-editor/test.ts +++ b/projects/addon-editor/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/addon-mobile/test.ts b/projects/addon-mobile/test.ts index 662a3824e57d..04402353a417 100644 --- a/projects/addon-mobile/test.ts +++ b/projects/addon-mobile/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/addon-preview/test.ts b/projects/addon-preview/test.ts index e160ffac1291..fbe636314a4f 100644 --- a/projects/addon-preview/test.ts +++ b/projects/addon-preview/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/addon-table/test.ts b/projects/addon-table/test.ts index e160ffac1291..fbe636314a4f 100644 --- a/projects/addon-table/test.ts +++ b/projects/addon-table/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/addon-tablebars/test.ts b/projects/addon-tablebars/test.ts index 662a3824e57d..04402353a417 100644 --- a/projects/addon-tablebars/test.ts +++ b/projects/addon-tablebars/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/cdk/test.ts b/projects/cdk/test.ts index 0a3fe4d8ee6c..571341a49bb9 100644 --- a/projects/cdk/test.ts +++ b/projects/cdk/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/core/test.ts b/projects/core/test.ts index e160ffac1291..fbe636314a4f 100644 --- a/projects/core/test.ts +++ b/projects/core/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/demo-integrations/cypress/support/stub-external-icons.util.ts b/projects/demo-integrations/cypress/support/stub-external-icons.util.ts index e18c19834be0..31f58f5b9376 100644 --- a/projects/demo-integrations/cypress/support/stub-external-icons.util.ts +++ b/projects/demo-integrations/cypress/support/stub-external-icons.util.ts @@ -1,16 +1,17 @@ // not taiga ui icons export const EXTERNAL_ICONS = [ - `web-api.svg`, - `marsibarsi.*1x1small.jpg`, - `.*ng-polymorpheus.*logo.svg`, - `bf2e94ae58ee713717faf397958a8e3d.jpg`, // filename - MD5 hash value of file content (waterplea avatar) + 'web-api.svg', + 'marsibarsi.*1x1small.jpg', + '.*ng-polymorpheus.*logo.svg', + 'bf2e94ae58ee713717faf397958a8e3d.jpg', // filename - MD5 hash value of file content (waterplea avatar) + 'avatar.jpg', ]; export const stubExternalIcons = (icons: string[] = EXTERNAL_ICONS): void => { icons.forEach(iconName => { cy.intercept( { - method: `GET`, + method: 'GET', url: new RegExp(`.*${iconName}`), }, {fixture: `stubs/web-api.svg`}, diff --git a/projects/demo/package.json b/projects/demo/package.json index 60461109f888..9c8ea3602660 100644 --- a/projects/demo/package.json +++ b/projects/demo/package.json @@ -3,7 +3,7 @@ "private": true, "dependencies": { "@ng-web-apis/universal": "1.9.5", - "@nguniversal/express-engine": "^9.1.1", + "@nguniversal/express-engine": "~12.1.3", "@stackblitz/sdk": "^1.8.0", "@tinkoff/angular-contenteditable-accessor": "~1.2.0", "@tinkoff/ng-dompurify": "^3.0.0", @@ -12,7 +12,7 @@ "ngx-markdown": "^11.1.3" }, "devDependencies": { - "@nguniversal/builders": "~11.2.1", + "@nguniversal/builders": "~12.1.3", "@types/dompurify": "^2.3.3", "@types/express": "^4.17.13", "express": "^4.18.1", diff --git a/projects/demo/server.ts b/projects/demo/server.ts index f5f2c06e4b04..b2ded2446d13 100644 --- a/projects/demo/server.ts +++ b/projects/demo/server.ts @@ -1,5 +1,5 @@ import '@ng-web-apis/universal/mocks'; -import 'zone.js/dist/zone-node'; +import 'zone.js/node'; import {APP_BASE_HREF} from '@angular/common'; import {provideLocation, provideUserAgent} from '@ng-web-apis/universal'; diff --git a/projects/demo/src/modules/components/button/examples/1/index.ts b/projects/demo/src/modules/components/button/examples/1/index.ts index e2e2900ec245..0c4e823141a5 100644 --- a/projects/demo/src/modules/components/button/examples/1/index.ts +++ b/projects/demo/src/modules/components/button/examples/1/index.ts @@ -1,19 +1,18 @@ import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; - -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; +import {assets} from '@demo/utils'; @Component({ - selector: `tui-button-example-1`, - templateUrl: `./index.html`, + selector: 'tui-button-example-1', + templateUrl: './index.html', changeDetection, encapsulation, }) export class TuiButtonExample1 { - readonly avatarUrl = avatar; + readonly avatarUrl = assets`/images/avatar.jpg`; onClick(event: MouseEvent): void { - console.info(`click`, event); + console.info('click', this.avatarUrl, event); } } diff --git a/projects/demo/src/modules/components/combo-box/examples/1/index.ts b/projects/demo/src/modules/components/combo-box/examples/1/index.ts index 88c99a43b984..349dfed4df85 100644 --- a/projects/demo/src/modules/components/combo-box/examples/1/index.ts +++ b/projects/demo/src/modules/components/combo-box/examples/1/index.ts @@ -2,12 +2,11 @@ import {Component} from '@angular/core'; import {FormControl} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {TUI_DEFAULT_MATCHER} from '@taiga-ui/cdk'; import {Observable, of, Subject} from 'rxjs'; import {delay, filter, startWith, switchMap} from 'rxjs/operators'; -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; - class User { constructor( readonly firstName: string, @@ -21,14 +20,14 @@ class User { } const databaseMockData: readonly User[] = [ - new User(`Roman`, `Sedov`, `http://marsibarsi.me/images/1x1small.jpg`), - new User(`Alex`, `Inkin`, avatar), + new User('Roman', 'Sedov', 'http://marsibarsi.me/images/1x1small.jpg'), + new User('Alex', 'Inkin', assets`/images/avatar.jpg`), ]; @Component({ - selector: `tui-combo-box-example-1`, - templateUrl: `./index.html`, - styleUrls: [`./index.less`], + selector: 'tui-combo-box-example-1', + templateUrl: './index.html', + styleUrls: ['./index.less'], changeDetection, encapsulation, }) @@ -58,7 +57,7 @@ export class TuiComboBoxExample1 { */ private serverRequest(searchQuery: string | null): Observable { const result = databaseMockData.filter(user => - TUI_DEFAULT_MATCHER(user, searchQuery || ``), + TUI_DEFAULT_MATCHER(user, searchQuery || ''), ); return of(result).pipe(delay(Math.random() * 1000 + 500)); diff --git a/projects/demo/src/modules/components/combo-box/examples/2/database-mock-data.ts b/projects/demo/src/modules/components/combo-box/examples/2/database-mock-data.ts index 74613c89147b..70004eca2350 100644 --- a/projects/demo/src/modules/components/combo-box/examples/2/database-mock-data.ts +++ b/projects/demo/src/modules/components/combo-box/examples/2/database-mock-data.ts @@ -1,8 +1,8 @@ -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; +import {assets} from '@demo/utils'; import {User} from './user'; export const databaseMockData: readonly User[] = [ - new User(`Roman`, `Sedov`, `http://marsibarsi.me/images/1x1small.jpg`), - new User(`Alex`, `Inkin`, avatar), + new User('Roman', 'Sedov', 'http://marsibarsi.me/images/1x1small.jpg'), + new User('Alex', 'Inkin', assets`/images/avatar.jpg`), ]; diff --git a/projects/demo/src/modules/components/input-phone/examples/3/index.ts b/projects/demo/src/modules/components/input-phone/examples/3/index.ts index 2239f14a8819..96d366b40aa0 100644 --- a/projects/demo/src/modules/components/input-phone/examples/3/index.ts +++ b/projects/demo/src/modules/components/input-phone/examples/3/index.ts @@ -1,12 +1,11 @@ import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {TUI_DEFAULT_MATCHER, tuiPure} from '@taiga-ui/cdk'; import {combineLatest, merge, Observable, of, Subject} from 'rxjs'; import {map, share, startWith, switchMap, tap} from 'rxjs/operators'; -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; - class User { constructor( readonly firstName: string, @@ -23,18 +22,18 @@ class User { const DATA: readonly User[] = [ new User( - `Roman`, - `Sedov`, - `+75678901234`, - `http://marsibarsi.me/images/1x1small.jpg`, + 'Roman', + 'Sedov', + '+75678901234', + 'http://marsibarsi.me/images/1x1small.jpg', ), - new User(`Alex`, `Inkin`, `+75678901234`, avatar), + new User('Alex', 'Inkin', '+75678901234', assets`/images/avatar.jpg`), ]; @Component({ - selector: `tui-input-phone-example-3`, - templateUrl: `./index.html`, - styleUrls: [`./index.less`], + selector: 'tui-input-phone-example-3', + templateUrl: './index.html', + styleUrls: ['./index.less'], changeDetection, encapsulation, }) @@ -43,7 +42,7 @@ export class TuiInputPhoneExample3 { private readonly selected$ = new Subject(); - value = ``; + value = ''; readonly user$ = merge( this.selected$, @@ -65,7 +64,7 @@ export class TuiInputPhoneExample3 { ); readonly items$ = this.search$.pipe( - startWith(``), + startWith(''), switchMap(value => this.request(value).pipe( map(response => (this.isFullMatch(response, value) ? [] : response)), @@ -75,7 +74,7 @@ export class TuiInputPhoneExample3 { readonly placeholder$ = combineLatest(this.user$, this.search$).pipe( map(([user, search]) => user || this.getPlaceholder(search)), - startWith(`Phone number or name`), + startWith('Phone number or name'), ); onSearch(search: string): void { @@ -100,14 +99,14 @@ export class TuiInputPhoneExample3 { private getPlaceholder(search: string): string { if (!search) { - return `Phone number or name`; + return 'Phone number or name'; } - if (search.startsWith(`+`)) { - return `Phone number`; + if (search.startsWith('+')) { + return 'Phone number'; } - return `Name`; + return 'Name'; } private isFullMatch(response: readonly User[], value: string): boolean { diff --git a/projects/demo/src/modules/components/input/examples/4/index.ts b/projects/demo/src/modules/components/input/examples/4/index.ts index 61eaf5c9cbfe..5696348bfbb2 100644 --- a/projects/demo/src/modules/components/input/examples/4/index.ts +++ b/projects/demo/src/modules/components/input/examples/4/index.ts @@ -2,20 +2,19 @@ import {Component, ViewChild} from '@angular/core'; import {FormControl, FormGroup} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {TuiCurrency} from '@taiga-ui/addon-commerce'; import {TUI_DEFAULT_MATCHER, tuiReplayedValueChangesFrom} from '@taiga-ui/cdk'; import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; import {map} from 'rxjs/operators'; -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; - class User { constructor( readonly firstName: string, readonly lastName: string, readonly avatarUrl: string | null = null, readonly accounts: Account[] = [], - readonly card: string = ``, + readonly card: string = '', ) {} toString(): string { @@ -39,63 +38,69 @@ class Account { const accountsRoman = [ new Account( - `1`, - `RUB`, + '1', + 'RUB', 24876.55, TuiCurrency.Ruble, - `https://ng-web-apis.github.io/dist/assets/images/common.svg`, + 'https://ng-web-apis.github.io/dist/assets/images/common.svg', ), new Account( - `2`, - `USD`, + '2', + 'USD', 335, TuiCurrency.Dollar, - `https://ng-web-apis.github.io/dist/assets/images/geolocation.svg`, + 'https://ng-web-apis.github.io/dist/assets/images/geolocation.svg', ), ]; const accountsAlex = [ new Account( - `3`, - `EUR`, + '3', + 'EUR', 10000, TuiCurrency.Euro, - `https://ng-web-apis.github.io/dist/assets/images/intersection-observer.svg`, + 'https://ng-web-apis.github.io/dist/assets/images/intersection-observer.svg', ), new Account( - `4`, - `PND`, + '4', + 'PND', 100, TuiCurrency.Pound, - `https://ng-web-apis.github.io/dist/assets/images/payment-request.svg`, + 'https://ng-web-apis.github.io/dist/assets/images/payment-request.svg', ), ]; const USERS = [ - new User(`Roman`, `Sedov`, `http://marsibarsi.me/images/1x1small.jpg`, accountsRoman), - new User(`Alex`, `Inkin`, avatar, accountsAlex, `1234123412341234`), - new User(`Dmitriy`, `Demenskiy`), - new User(`Evgeniy`, `Mamaev`), - new User(`Ivan`, `Ishmametiev`), - new User(`Igor`, `Katsuba`), - new User(`Yulia`, `Tsareva`), + new User('Roman', 'Sedov', 'http://marsibarsi.me/images/1x1small.jpg', accountsRoman), + new User( + 'Alex', + 'Inkin', + assets`/images/avatar.jpg`, + accountsAlex, + '1234123412341234', + ), + new User('Dmitriy', 'Demenskiy'), + new User('Evgeniy', 'Mamaev'), + new User('Ivan', 'Ishmametiev'), + new User('Igor', 'Katsuba'), + new User('Yulia', 'Tsareva'), ]; @Component({ - selector: `tui-input-example-4`, - templateUrl: `./index.html`, - styleUrls: [`./index.less`], + selector: 'tui-input-example-4', + templateUrl: './index.html', + styleUrls: ['./index.less'], changeDetection, encapsulation, }) export class TuiInputExample4 { - @ViewChild(`avatar`) - private readonly avatar: PolymorpheusContent = ``; + @ViewChild('avatar') + private readonly avatar: PolymorpheusContent = ''; - private readonly user = new FormControl(``); + private readonly user = new FormControl(''); readonly testForm = new FormGroup({ user: this.user, - account: new FormControl(``), - card: new FormControl(``), + account: new FormControl(''), + card: new FormControl(''), }); lastUser: User | null = null; @@ -118,28 +123,28 @@ export class TuiInputExample4 { ); get card(): string | null { - const value = this.testForm.get(`card`)!.value; + const value = this.testForm.get('card')!.value; if (value.length < 7) { return null; } switch (value.charAt(0)) { - case `0`: - case `1`: - case `2`: - return `https://ng-web-apis.github.io/dist/assets/images/common.svg`; - case `3`: - case `4`: - case `5`: - return `https://ng-web-apis.github.io/dist/assets/images/geolocation.svg`; - case `6`: - case `7`: - return `https://ng-web-apis.github.io/dist/assets/images/intersection-observer.svg`; - case `8`: - case `9`: + case '0': + case '1': + case '2': + return 'https://ng-web-apis.github.io/dist/assets/images/common.svg'; + case '3': + case '4': + case '5': + return 'https://ng-web-apis.github.io/dist/assets/images/geolocation.svg'; + case '6': + case '7': + return 'https://ng-web-apis.github.io/dist/assets/images/intersection-observer.svg'; + case '8': + case '9': default: - return `https://ng-web-apis.github.io/dist/assets/images/payment-request.svg`; + return 'https://ng-web-apis.github.io/dist/assets/images/payment-request.svg'; } } @@ -147,12 +152,12 @@ export class TuiInputExample4 { return ( this.lastUser !== null && this.lastUser.toString().toLowerCase() === - this.testForm.get(`user`)!.value.toLowerCase() + this.testForm.get('user')!.value.toLowerCase() ); } get content(): PolymorpheusContent { - return this.avatar && this.isUserSelected ? this.avatar : ``; + return this.avatar && this.isUserSelected ? this.avatar : ''; } get accounts(): Account[] { @@ -161,6 +166,6 @@ export class TuiInputExample4 { onSelected(user: User): void { this.lastUser = user; - this.testForm.get(`card`)!.setValue(user.card); + this.testForm.get('card')!.setValue(user.card); } } diff --git a/projects/demo/src/modules/components/input/examples/8/index.ts b/projects/demo/src/modules/components/input/examples/8/index.ts index cdbc38f30f5d..946f4302f699 100644 --- a/projects/demo/src/modules/components/input/examples/8/index.ts +++ b/projects/demo/src/modules/components/input/examples/8/index.ts @@ -2,12 +2,11 @@ import {Component} from '@angular/core'; import {FormControl} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {TUI_DEFAULT_MATCHER} from '@taiga-ui/cdk'; import {Observable, of} from 'rxjs'; import {map, startWith, switchMap} from 'rxjs/operators'; -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; - class User { constructor( readonly firstName: string, @@ -22,26 +21,26 @@ class User { } const DATA: readonly User[] = [ - new User(`Roman`, `Sedov`, `http://marsibarsi.me/images/1x1small.jpg`), - new User(`Alex`, `Inkin`, avatar), - new User(`Gabriel José`, `de la Concordia «Gabo» García Márquez`), + new User('Roman', 'Sedov', 'http://marsibarsi.me/images/1x1small.jpg'), + new User('Alex', 'Inkin', assets`/images/avatar.jpg`), + new User('Gabriel José', 'de la Concordia «Gabo» García Márquez'), ]; @Component({ - selector: `tui-input-example-8`, - templateUrl: `./index.html`, - styleUrls: [`./index.less`], + selector: 'tui-input-example-8', + templateUrl: './index.html', + styleUrls: ['./index.less'], changeDetection, encapsulation, }) export class TuiInputExample8 { - readonly control = new FormControl(``); + readonly control = new FormControl(''); - firstName = ``; - lastName = ``; + firstName = ''; + lastName = ''; readonly items$ = this.control.valueChanges.pipe( - startWith(``), + startWith(''), switchMap(value => this.request(value).pipe( map(response => { diff --git a/projects/demo/src/modules/components/multi-select/examples/2/index.ts b/projects/demo/src/modules/components/multi-select/examples/2/index.ts index bae4ddbdbd91..82b2313b3f43 100644 --- a/projects/demo/src/modules/components/multi-select/examples/2/index.ts +++ b/projects/demo/src/modules/components/multi-select/examples/2/index.ts @@ -2,12 +2,11 @@ import {Component} from '@angular/core'; import {FormControl} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {TUI_DEFAULT_MATCHER} from '@taiga-ui/cdk'; import {Observable, of, Subject} from 'rxjs'; import {delay, filter, startWith, switchMap} from 'rxjs/operators'; -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; - class User { constructor( readonly firstName: string, @@ -21,19 +20,19 @@ class User { } const databaseMockData: readonly User[] = [ - new User(`Roman`, `Sedov`, `http://marsibarsi.me/images/1x1small.jpg`), - new User(`Alex`, `Inkin`, avatar), - new User(`Dmitriy`, `Demenskiy`), - new User(`Evgeniy`, `Mamaev`), - new User(`Ivan`, `Ishmametiev`), - new User(`Igor`, `Katsuba`), - new User(`Yulia`, `Tsareva`), + new User('Roman', 'Sedov', 'http://marsibarsi.me/images/1x1small.jpg'), + new User('Alex', 'Inkin', assets`/images/avatar.jpg`), + new User('Dmitriy', 'Demenskiy'), + new User('Evgeniy', 'Mamaev'), + new User('Ivan', 'Ishmametiev'), + new User('Igor', 'Katsuba'), + new User('Yulia', 'Tsareva'), ]; @Component({ - selector: `tui-multi-select-example-2`, - templateUrl: `./index.html`, - styleUrls: [`./index.less`], + selector: 'tui-multi-select-example-2', + templateUrl: './index.html', + styleUrls: ['./index.less'], changeDetection, encapsulation, }) @@ -59,7 +58,7 @@ export class TuiMultiSelectExample2 { */ private serverRequest(searchQuery: string | null): Observable { const result = databaseMockData.filter(user => - TUI_DEFAULT_MATCHER(user, searchQuery || ``), + TUI_DEFAULT_MATCHER(user, searchQuery || ''), ); return of(result).pipe(delay(Math.random() * 1000 + 500)); diff --git a/projects/demo/src/modules/components/select/examples/6/index.ts b/projects/demo/src/modules/components/select/examples/6/index.ts index 983000eb8a03..4027752a7489 100644 --- a/projects/demo/src/modules/components/select/examples/6/index.ts +++ b/projects/demo/src/modules/components/select/examples/6/index.ts @@ -1,12 +1,11 @@ import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {TuiBooleanHandler} from '@taiga-ui/cdk'; import {of} from 'rxjs'; import {delay} from 'rxjs/operators'; -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; - class User { constructor( readonly firstName: string, @@ -20,19 +19,19 @@ class User { } const databaseMockData: readonly User[] = [ - new User(`Roman`, `Sedov`, `http://marsibarsi.me/images/1x1small.jpg`), - new User(`Alex`, `Inkin`, avatar), - new User(`Dmitriy`, `Demenskiy`), - new User(`Evgeniy`, `Mamaev`), - new User(`Ivan`, `Ishmametiev`), - new User(`Igor`, `Katsuba`), - new User(`Yulia`, `Tsareva`), + new User('Roman', 'Sedov', 'http://marsibarsi.me/images/1x1small.jpg'), + new User('Alex', 'Inkin', assets`/images/avatar.jpg`), + new User('Dmitriy', 'Demenskiy'), + new User('Evgeniy', 'Mamaev'), + new User('Ivan', 'Ishmametiev'), + new User('Igor', 'Katsuba'), + new User('Yulia', 'Tsareva'), ]; @Component({ - selector: `tui-select-example-6`, - templateUrl: `./index.html`, - styleUrls: [`./index.less`], + selector: 'tui-select-example-6', + templateUrl: './index.html', + styleUrls: ['./index.less'], changeDetection, encapsulation, }) diff --git a/projects/demo/src/modules/components/svg/examples/1/index.ts b/projects/demo/src/modules/components/svg/examples/1/index.ts index 3afbb7f30b4c..ad50b8d6f922 100644 --- a/projects/demo/src/modules/components/svg/examples/1/index.ts +++ b/projects/demo/src/modules/components/svg/examples/1/index.ts @@ -1,13 +1,12 @@ import {Component, Inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {TuiSvgService} from '@taiga-ui/core'; import {tuiIconMaestro, tuiIconMastercard, tuiIconTimeLarge} from '@taiga-ui/icons'; import {timer} from 'rxjs'; import {mapTo} from 'rxjs/operators'; -import {default as imageUrl} from '!!file-loader!../../../../../assets/images/ts.svg'; - @Component({ selector: `tui-svg-example-1`, templateUrl: `./index.html`, @@ -18,7 +17,7 @@ import {default as imageUrl} from '!!file-loader!../../../../../assets/images/ts export class TuiSvgExample1 { readonly timeout$ = timer(0).pipe(mapTo(true)); - readonly imageUrl = `${imageUrl}#ts`; + readonly imageUrl = assets`/images/ts.svg#ts`; readonly tuiIconTimeLarge = tuiIconTimeLarge; diff --git a/projects/demo/src/modules/components/svg/svg.component.ts b/projects/demo/src/modules/components/svg/svg.component.ts index 02be2d43a230..caf88e6df7cd 100644 --- a/projects/demo/src/modules/components/svg/svg.component.ts +++ b/projects/demo/src/modules/components/svg/svg.component.ts @@ -1,9 +1,8 @@ import {Component, Inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; +import {assets} from '@demo/utils'; import {TuiDocExample} from '@taiga-ui/addon-doc'; -import {default as imageUrl} from '!!file-loader!../../../assets/images/ts.svg'; - import {TuiThemeService} from '../../app/theme.service'; @Component({ @@ -38,7 +37,7 @@ export class ExampleTuiSvgComponent { c0-0.6-0.4-1-1-1s-1,0.4-1,1v2h-1c-1.3,0-3,1.9-3,4v4.2L6.4,17H10z M3.6,19L5,14.8V11c0-2.7,1.9-5.2,4-5.8V5c0-1.7,1.3-3,3-3 s3,1.3,3,3v0.1c2.3,0.6,4,3,4,5.9v3.8l1.4,4.2h-4.5c-0.4,1.8-2,3-3.9,3c-1.8,0-3.4-1.2-3.9-3H3.6z"/> `, - `${imageUrl}#ts`, + assets`/images/ts.svg#ts`, ]; icon = this.iconVariants[0]; diff --git a/projects/demo/src/modules/directives/dropdown-selection/examples/2/index.ts b/projects/demo/src/modules/directives/dropdown-selection/examples/2/index.ts index bf236028ef4f..22a0c69b6371 100644 --- a/projects/demo/src/modules/directives/dropdown-selection/examples/2/index.ts +++ b/projects/demo/src/modules/directives/dropdown-selection/examples/2/index.ts @@ -1,12 +1,11 @@ import {Component, ElementRef, QueryList, ViewChildren} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; +import {assets} from '@demo/utils'; import {EMPTY_QUERY, setNativeFocused, TuiBooleanHandler, tuiPure} from '@taiga-ui/cdk'; import {TuiOptionComponent} from '@taiga-ui/core'; import {getWordRange} from '@taiga-ui/kit'; -import {default as avatar} from '!!file-loader!../../../../../assets/images/avatar.jpg'; - export interface User { readonly name: string; readonly avatar: string; @@ -14,9 +13,9 @@ export interface User { } @Component({ - selector: `tui-dropdown-selection-example-2`, - templateUrl: `./index.html`, - styleUrls: [`./index.less`], + selector: 'tui-dropdown-selection-example-2', + templateUrl: './index.html', + styleUrls: ['./index.less'], changeDetection, encapsulation, }) @@ -24,18 +23,18 @@ export class TuiDropdownSelectionExample2 { @ViewChildren(TuiOptionComponent, {read: ElementRef}) private readonly options: QueryList> = EMPTY_QUERY; - value = `Type @ to see a dropdown`; + value = 'Type @ to see a dropdown'; readonly items = [ { - name: `Alexander Inkin`, - avatar, - login: `a.inkin`, + name: 'Alexander Inkin', + avatar: assets`/images/avatar.jpg`, + login: 'a.inkin', }, { - name: `Roman Sedov`, - avatar: ``, - login: `r.sedov`, + name: 'Roman Sedov', + avatar: '', + login: 'r.sedov', }, ]; @@ -44,7 +43,7 @@ export class TuiDropdownSelectionExample2 { } predicate: TuiBooleanHandler = range => - getWordRange(range).toString().startsWith(`@`); + getWordRange(range).toString().startsWith('@'); onArrow(event: Event, which: 'first' | 'last'): void { const item = this.options[which]; @@ -58,7 +57,7 @@ export class TuiDropdownSelectionExample2 { } filterItems(textarea: HTMLTextAreaElement): readonly User[] { - const search = this.getCurrentSearch(textarea).replace(`@`, ``); + const search = this.getCurrentSearch(textarea).replace('@', ''); return this.getFilteredItems(this.items, search); } @@ -82,6 +81,6 @@ export class TuiDropdownSelectionExample2 { } private getCurrentSearch(textarea: HTMLTextAreaElement): string { - return textarea.value.slice(textarea.value.indexOf(`@`), textarea.selectionStart); + return textarea.value.slice(textarea.value.indexOf('@'), textarea.selectionStart); } } diff --git a/projects/demo/src/modules/directives/dropdown/examples/2/index.ts b/projects/demo/src/modules/directives/dropdown/examples/2/index.ts index 7c022f3dc177..25c570ccc09c 100644 --- a/projects/demo/src/modules/directives/dropdown/examples/2/index.ts +++ b/projects/demo/src/modules/directives/dropdown/examples/2/index.ts @@ -1,8 +1,7 @@ import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; - -import {default as avatarUrl} from '!!file-loader!../../../../../assets/images/avatar.jpg'; +import {assets} from '@demo/utils'; @Component({ selector: `tui-dropdown-example-2`, @@ -14,7 +13,7 @@ import {default as avatarUrl} from '!!file-loader!../../../../../assets/images/a export class TuiDropdownExample2 { open = false; - avatarUrl = avatarUrl; + avatarUrl = assets`/images/avatar.jpg`; onMouseEnter(): void { this.open = true; diff --git a/projects/demo/src/polyfills.ts b/projects/demo/src/polyfills.ts index c3052aeaa958..e6fa44be0b21 100644 --- a/projects/demo/src/polyfills.ts +++ b/projects/demo/src/polyfills.ts @@ -1,3 +1,3 @@ import '@angular/localize/init'; import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; +import 'zone.js'; diff --git a/projects/demo/src/typings.d.ts b/projects/demo/src/typings.d.ts index 6fc44b362c8e..ccdf2fc9ae8e 100644 --- a/projects/demo/src/typings.d.ts +++ b/projects/demo/src/typings.d.ts @@ -8,12 +8,6 @@ interface NodeModule { id: string; } -declare module '!!file-loader!*' { - const result: string; - - export = result; -} - declare module '*.html' { const result: string; diff --git a/projects/demo/src/utils/index.ts b/projects/demo/src/utils/index.ts new file mode 100644 index 000000000000..3c2265513b3a --- /dev/null +++ b/projects/demo/src/utils/index.ts @@ -0,0 +1 @@ +export * from './load-assets'; diff --git a/projects/demo/src/utils/load-assets.ts b/projects/demo/src/utils/load-assets.ts new file mode 100644 index 000000000000..e770e4ac95ae --- /dev/null +++ b/projects/demo/src/utils/load-assets.ts @@ -0,0 +1,6 @@ +export function assets(path: TemplateStringsArray): string { + const dirname = new URL('.', import.meta.url); + const relativePath = `../assets${path.join('')}`; + + return new URL(relativePath, dirname).toString(); +} diff --git a/projects/demo/test.ts b/projects/demo/test.ts index e160ffac1291..fbe636314a4f 100644 --- a/projects/demo/test.ts +++ b/projects/demo/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/kit/test.ts b/projects/kit/test.ts index e160ffac1291..fbe636314a4f 100644 --- a/projects/kit/test.ts +++ b/projects/kit/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/projects/taiga-schematics/package.json b/projects/taiga-schematics/package.json index bc8febd9c348..086dfdfeb8c2 100644 --- a/projects/taiga-schematics/package.json +++ b/projects/taiga-schematics/package.json @@ -15,12 +15,12 @@ "repository": "https://github.com/tinkoff/taiga-ui", "license": "Apache-2.0", "dependencies": { - "@angular-devkit/schematics": "~11.2.19", + "@angular-devkit/schematics": "~12.2.17", "ng-morph": "^2.0.0", "tslib": "^2.0.0" }, "devDependencies": { - "@angular-devkit/schematics-cli": "~0.1102.19" + "@angular-devkit/schematics-cli": "~12.2.17" }, "schematics": "./collection.json" } diff --git a/projects/taiga-schematics/test.ts b/projects/taiga-schematics/test.ts index d80f168d8c7a..878569f47114 100644 --- a/projects/taiga-schematics/test.ts +++ b/projects/taiga-schematics/test.ts @@ -1,8 +1,8 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/zone-testing'; +import 'zone.js'; +import 'zone.js/testing'; import {getTestBed} from '@angular/core/testing'; import { diff --git a/tsconfig.json b/tsconfig.json index f7064eeb6606..d21cbf8f69f0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -85,7 +85,8 @@ "@taiga-ui/addon-mobile": ["projects/addon-mobile/index"], "@taiga-ui/addon-mobile/*": ["projects/addon-mobile/*"], "@demo/emulate/change-detection": ["projects/demo/src/emulate/change-detection-strategy.ts"], - "@demo/emulate/encapsulation": ["projects/demo/src/emulate/view-encapsulation.ts"] + "@demo/emulate/encapsulation": ["projects/demo/src/emulate/view-encapsulation.ts"], + "@demo/utils": ["projects/demo/src/utils/index"] } } }