diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 9e7aa02..3b39527 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -15,14 +15,15 @@ jobs: strategy: matrix: - node-version: [14.x, 16.x, 18.x] - angular-version: [13.1.4, 14.0.2, 15.0.3, 16.2.1, 17.0.0] + node-version: [14.x, 16.x, 18.x, 20.x] + angular-version: [13.2.6, 14.0.2, 15.0.3, 16.2.1, 17.0.0] exclude: - node-version: 18.x + - node-version: 20.x - angular-version: 17.0.0 include: - - angular-version: 13.1.4 - devkit-version: 0.1301.4 + - angular-version: 13.2.6 + devkit-version: 0.1302.6 - angular-version: 14.0.2 devkit-version: 0.1400.2 - angular-version: 15.0.3 @@ -35,6 +36,9 @@ jobs: - angular-version: 17.0.0 devkit-version: 0.1700.0 node-version: 18.x + - angular-version: 17.0.0 + devkit-version: 0.1700.0 + node-version: 20.x steps: - uses: actions/checkout@v2 @@ -43,11 +47,11 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: rm package-lock.json # otherwise we cannot overwrite the peerDependencies version of @angular-devkit/build-angular below - - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" + - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" "@angular/compiler-cli@${{ matrix.angular-version }}" - run: npm i - run: npm ls || true - run: npm run build - - run: npm run test-coverage + - run: NODE_OPTIONS=--experimental-vm-modules npm run test-coverage - name: Coveralls uses: coverallsapp/github-action@v1.1.2 with: diff --git a/README.md b/README.md index 803fff2..d3f13e4 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,8 @@ In your `angular.json` the target `extract-i18n` that can be configured with the | Name | Default | Description | |------------------------------|----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `browserTarget` | Inferred from current setup by `ng add` | A browser builder target to extract i18n messages in the format of `project:target[:configuration]`. See https://angular.io/cli/extract-i18n#options | +| ~~`browserTarget`~~ | Inferred from current setup by `ng add` | _Deprecated_: Use `buildTarget`. A browser builder target to extract i18n messages in the format of `project:target[:configuration]`. See https://angular.io/cli/extract-i18n#options | +| `buildTarget` | Inferred from current setup by `ng add` | A build builder target to extract i18n messages in the format of `project:target[:configuration]`. See https://angular.io/cli/extract-i18n#options | | `format` | Inferred from current setup by `ng add` | Any of `xlf`, `xlif`, `xliff`, `xlf2`, `xliff2` | | `outputPath` | Inferred from current setup by `ng add` | Path to folder containing all (source and target) translation files. | | `targetFiles` | Inferred from current setup by `ng add` | Filenames (relative to `outputPath` of all target translation files (e.g. `["messages.fr.xlf", "messages.de.xlf"]`). | @@ -57,7 +58,7 @@ In your `angular.json` the target `extract-i18n` that can be configured with the | `includeContext` | `false` | Whether to include the context information (like notes) in the translation files. This is useful for sending the target translation files to translation agencies/services. When `sourceFileOnly`, the context is retained only in the `sourceFile`. | | `newTranslationTargetsBlank` | `false` | When `false` (default) the "target" of new translation units is set to the "source" value. When `true`, an empty string is used. When `'omit'`, no target element is created. | | `sort` | `"stableAppendNew"` (will change to `stableAlphabetNew` with v3.0.0) | Sorting of all translation units in source and target translation files. Supported:
`"idAsc"` (sort by translation IDs),
`"stableAppendNew"` (keep existing sorting, append new translations at the end),
`"stableAlphabetNew"` (keep existing sorting, sort new translations next to alphabetical close IDs). | -| `builderI18n` | `"@angular-devkit/build-angular:extract-i18n"` | The builder to use for i18n extraction. Any custom builder should handle the same options as the default angular builder (browserTarget, outputPath, outFile, format, progress). | +| `builderI18n` | `"@angular-devkit/build-angular:extract-i18n"` | The builder to use for i18n extraction. Any custom builder should handle the same options as the default angular builder (buildTarget, outputPath, outFile, format, progress). | | `verbose` | `false` | Extended/debug output - it is recommended to use this only for manual debugging. | ## Contribute diff --git a/jest.config.ts b/jest.config.ts index 5998d00..4b56be3 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,14 +1,16 @@ -import type {Config} from '@jest/types'; +import {JestConfigWithTsJest} from 'ts-jest'; // Sync object -const config: Config.InitialOptions = { +const config: JestConfigWithTsJest = { preset: 'ts-jest', testEnvironment: 'node', verbose: false, + maxWorkers: 100, + maxConcurrency: 1, + testTimeout: 30_000, testMatch: undefined, testRegex: '.*\.spec\.ts$', collectCoverageFrom: ['src/**/*.ts'], // exclude coverage from schematic as it only collects from js (instead of ts).. coveragePathIgnorePatterns: ['src/rmSafe.ts'], - }; export default config; diff --git a/package-lock.json b/package-lock.json index 28e76ee..3dc8f00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ng-extract-i18n-merge", - "version": "2.9.1", + "version": "2.10.0-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ng-extract-i18n-merge", - "version": "2.9.1", + "version": "2.10.0-2", "license": "MIT", "dependencies": { "@angular-devkit/architect": "^0.1301.0 || ^0.1401.0 || ^0.1501.0 || ^0.1601.0 || ^0.1700.0", @@ -27,7 +27,8 @@ "node": ">=14.0.0" }, "peerDependencies": { - "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "@angular/core": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "node_modules/@ampproject/remapping": { @@ -390,6 +391,22 @@ "typescript": ">=5.2 <5.3" } }, + "node_modules/@angular/core": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.0.1.tgz", + "integrity": "sha512-yVwU+oz0G8g6Q5ORyOCpgqMPdSiCdfW+uQhjI37WROnXHja3jY843AqrYTKE6mMx1r6q9h1wbDy+x2E61OWP7A==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.14.0" + } + }, "node_modules/@assemblyscript/loader": { "version": "0.10.1", "license": "Apache-2.0", @@ -3521,9 +3538,10 @@ } }, "node_modules/@types/jest": { - "version": "29.5.5", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, - "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -13046,6 +13064,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zone.js": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.3.tgz", + "integrity": "sha512-jYoNqF046Q+JfcZSItRSt+oXFcpXL88yq7XAZjb/NKTS7w2hHpKjRJ3VlFD1k75wMaRRXNUt5vrZVlygiMyHbA==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + } } }, "dependencies": { @@ -13271,6 +13298,15 @@ "yargs": "^17.2.1" } }, + "@angular/core": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.0.1.tgz", + "integrity": "sha512-yVwU+oz0G8g6Q5ORyOCpgqMPdSiCdfW+uQhjI37WROnXHja3jY843AqrYTKE6mMx1r6q9h1wbDy+x2E61OWP7A==", + "peer": true, + "requires": { + "tslib": "^2.3.0" + } + }, "@assemblyscript/loader": { "version": "0.10.1", "peer": true @@ -15336,7 +15372,9 @@ } }, "@types/jest": { - "version": "29.5.5", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, "requires": { "expect": "^29.0.0", @@ -21461,6 +21499,15 @@ "yocto-queue": { "version": "0.1.0", "devOptional": true + }, + "zone.js": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.3.tgz", + "integrity": "sha512-jYoNqF046Q+JfcZSItRSt+oXFcpXL88yq7XAZjb/NKTS7w2hHpKjRJ3VlFD1k75wMaRRXNUt5vrZVlygiMyHbA==", + "peer": true, + "requires": { + "tslib": "^2.3.0" + } } } } diff --git a/package.json b/package.json index 45e7681..5230300 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng-extract-i18n-merge", - "version": "2.9.1", + "version": "2.10.0-2", "description": "Extract and merge i18n xliff translation files for angular projects.", "main": "index.js", "builders": "builders.json", @@ -43,7 +43,8 @@ "xmldoc": "^1.1.2" }, "peerDependencies": { - "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "@angular/core": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" }, "devDependencies": { "@types/jest": "^28.1.8 || ^29.0.0", diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index 4c42127..6cbd5b8 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,5 +1,6 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; @@ -23,16 +24,17 @@ function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { export default function (): Rule { return (tree: Tree, context: SchematicContext) => { updateNpmScript(tree, context.logger); - return updateWorkspace((workspace) => { + return updateWorkspace(async (workspace) => { workspace.projects.forEach((project, projectName) => { const i18nMergeTarget = project.targets.get('extract-i18n-merge'); if (i18nMergeTarget) { context.logger.info(`updating extract-i18n(-merge) targets for project ${projectName}..`) + const buildTargetAttribute = extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; const i18nTarget = {...(project.targets.get('extract-i18n') ?? {builder: 'ng-extract-i18n-merge:ng-extract-i18n-merge'})}; i18nTarget.builder = 'ng-extract-i18n-merge:ng-extract-i18n-merge'; i18nTarget.options = { ...i18nMergeTarget.options, - browserTarget: i18nTarget.options?.browserTarget ?? `${projectName}:build` + [buildTargetAttribute]: i18nTarget.options?.browserTarget ?? i18nTarget.options?.buildTarget ?? `${projectName}:build` } project.targets.delete('extract-i18n'); // 'project.targets.set' not working!? project.targets.add({name: 'extract-i18n', ...i18nTarget}); diff --git a/schematics/ng-add/index.spec.ts b/schematics/ng-add/index.spec.ts index bcc0428..0a37d08 100644 --- a/schematics/ng-add/index.spec.ts +++ b/schematics/ng-add/index.spec.ts @@ -4,9 +4,14 @@ import * as path from 'path'; import {Schema as WorkspaceOptions} from '@schematics/angular/workspace/schema'; import {Schema as ApplicationOptions, Style} from '@schematics/angular/application/schema'; import {Tree} from '@angular-devkit/schematics'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; const collectionPath = path.join(__dirname, '../collection.json'); +async function getBuildTargetAttribute() { + return extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; +} + const workspaceOptions: WorkspaceOptions = { name: 'workspace', newProjectRoot: 'projects', @@ -46,11 +51,12 @@ describe('ngAdd', () => { }); it('works', async () => { + const buildTargetAttribute = await getBuildTargetAttribute(); const tree = await runSchematic(runner, 'ng-add', {}, appTree); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf2",\n' + ' "outputPath": "src/locales",\n' + ' "targetFiles": []\n' + @@ -72,11 +78,11 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -105,11 +111,11 @@ describe('ngAdd', () => { appTree.create('/src/some-path/my-messages.xlf', '<>'); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/some-path",\n' + ' "targetFiles": [ "../other-path/messages.fr.xlf" ],\n' + @@ -131,11 +137,11 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -153,11 +159,11 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -181,11 +187,11 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -210,11 +216,11 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf2",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index 639d841..6bdca6f 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -4,6 +4,7 @@ import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; import {Options} from '../../src/options'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { const locales = i18nExtension?.locales ? (Object.values(i18nExtension?.locales) as JsonArray | string[] | undefined) : undefined; @@ -57,7 +58,7 @@ function getOutFileRelativeToOutputPath(outFile: string, outputPathFromExtractI1 // noinspection JSUnusedGlobalSymbols export function ngAdd(_options: Schema): Rule { return (tree: Tree, context: SchematicContext) => { - return updateWorkspace((workspace) => { + return updateWorkspace(async (workspace) => { const projectName = _options.project || Array.from(workspace.projects.keys())[0]; const projectWorkspace = workspace.projects.get(projectName)!; if (!projectWorkspace) { @@ -81,7 +82,7 @@ export function ngAdd(_options: Schema): Rule { const outputPath = normalize(outputPathFromExtractI18nOptions ?? outputPathFromTargetFiles ?? 'src/locales'); context.logger.info(`inferred output path: ${outputPath}`); - const browserTarget = existingI18nTargetOptions?.browserTarget as string | undefined ?? `${projectName}:build`; + const buildTarget = existingI18nTargetOptions?.browserTarget as string | undefined ?? existingI18nTargetOptions?.buildTarget as string | undefined ?? `${projectName}:build`; // infer format: const formatFromExtractI18nOptions = existingI18nTargetOptions?.format as Options['format'] | undefined; @@ -93,8 +94,9 @@ export function ngAdd(_options: Schema): Rule { const filesWithoutOutputPath = files?.map(f => relative(`/${outputPath}` as Path, `/${f}` as Path)); const target = projectWorkspace.targets.get('extract-i18n'); + const buildTargetAttribute = extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; const builderOptions: Partial = { - browserTarget, + [buildTargetAttribute]: buildTarget, format, outputPath, targetFiles: filesWithoutOutputPath ?? [] diff --git a/src/builder.ts b/src/builder.ts index 848bfef..c465f99 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,6 +8,7 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; const STATE_INITIAL_XLF_2_0 = 'initial'; @@ -106,8 +107,9 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const sourcePath = join(normalize(outputPath), options.sourceFile ?? 'messages.xlf'); const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); + const buildTargetAttribute = extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { - browserTarget: options.browserTarget, + [buildTargetAttribute]: options.browserTarget ?? options.buildTarget, outputPath: dirname(sourcePath), outFile: basename(sourcePath), format, diff --git a/src/options.ts b/src/options.ts index 819f32d..8e980f6 100644 --- a/src/options.ts +++ b/src/options.ts @@ -16,7 +16,9 @@ export interface Options extends JsonObject { includeContext: boolean | 'sourceFileOnly', newTranslationTargetsBlank: boolean | 'omit', sort: 'idAsc' | 'stableAppendNew' | 'stableAlphabetNew', - browserTarget: string, + /** @deprecated use `buildTarget` instead */ + browserTarget: string | null, + buildTarget: string | null, builderI18n: string, verbose: boolean } diff --git a/src/schema.json b/src/schema.json index 9e63516..abf77db 100644 --- a/src/schema.json +++ b/src/schema.json @@ -113,6 +113,12 @@ "browserTarget": { "type": "string", "description": "A browser builder target use for rendering the app shell in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.", + "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$", + "x-deprecated": "Use `buildTarget` instead." + }, + "buildTarget": { + "type": "string", + "description": "A build builder target use for rendering the app shell in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.", "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$" }, "builderI18n": { @@ -127,8 +133,12 @@ } }, "additionalProperties": false, - "required": [ - "targetFiles", - "browserTarget" + "anyOf": [ + { + "required": ["browserTarget", "targetFiles"] + }, + { + "required": ["buildTarget", "targetFiles"] + } ] } diff --git a/tsconfig.json b/tsconfig.json index 3f587b3..b82a18b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ @@ -52,6 +52,7 @@ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "resolveJsonModule": true, // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */