@angular/build 18.0.0-next.3 → 18.0.0-next.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builders.json +5 -0
- package/package.json +9 -4
- package/src/builders/dev-server/builder.js +3 -8
- package/src/builders/dev-server/options.d.ts +0 -4
- package/src/builders/dev-server/options.js +2 -6
- package/src/builders/dev-server/schema.d.ts +3 -34
- package/src/builders/dev-server/schema.json +2 -30
- package/src/builders/extract-i18n/application-extraction.d.ts +18 -0
- package/src/builders/extract-i18n/application-extraction.js +131 -0
- package/src/builders/extract-i18n/builder.d.ts +14 -0
- package/src/builders/extract-i18n/builder.js +140 -0
- package/src/builders/extract-i18n/index.d.ts +12 -0
- package/src/builders/extract-i18n/index.js +14 -0
- package/src/builders/extract-i18n/options.d.ts +29 -0
- package/src/builders/extract-i18n/options.js +83 -0
- package/src/builders/extract-i18n/schema.d.ts +41 -0
- package/src/builders/extract-i18n/schema.js +20 -0
- package/src/builders/extract-i18n/schema.json +34 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -1
- package/src/tools/esbuild/stylesheets/less-language.js +20 -1
- package/src/tools/esbuild/utils.js +1 -1
- package/src/utils/index-file/augment-index-html.js +23 -1
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/version.js +7 -1
package/builders.json
CHANGED
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
"implementation": "./src/builders/dev-server/index",
|
|
10
10
|
"schema": "./src/builders/dev-server/schema.json",
|
|
11
11
|
"description": "Execute a development server for an application."
|
|
12
|
+
},
|
|
13
|
+
"extract-i18n": {
|
|
14
|
+
"implementation": "./src/builders/extract-i18n/index",
|
|
15
|
+
"schema": "./src/builders/extract-i18n/schema.json",
|
|
16
|
+
"description": "Extract i18n messages from an application."
|
|
12
17
|
}
|
|
13
18
|
}
|
|
14
19
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "18.0.0-next.
|
|
3
|
+
"version": "18.0.0-next.5",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,21 +23,22 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.1800.0-next.
|
|
26
|
+
"@angular-devkit/architect": "0.1800.0-next.5",
|
|
27
27
|
"@babel/core": "7.24.4",
|
|
28
28
|
"@babel/helper-annotate-as-pure": "7.22.5",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.22.6",
|
|
30
30
|
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
31
|
+
"ansi-colors": "4.1.3",
|
|
31
32
|
"browserslist": "^4.23.0",
|
|
32
33
|
"critters": "0.0.22",
|
|
33
34
|
"esbuild": "0.20.2",
|
|
34
35
|
"fast-glob": "3.3.2",
|
|
35
36
|
"https-proxy-agent": "7.0.4",
|
|
36
37
|
"inquirer": "9.2.19",
|
|
37
|
-
"less": "4.2.0",
|
|
38
38
|
"magic-string": "0.30.10",
|
|
39
39
|
"mrmime": "2.0.0",
|
|
40
40
|
"ora": "5.4.1",
|
|
41
|
+
"picomatch": "4.0.2",
|
|
41
42
|
"piscina": "4.4.0",
|
|
42
43
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
43
44
|
"postcss": "8.4.38",
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"@angular/localize": "^18.0.0 || ^18.0.0-next.0",
|
|
53
54
|
"@angular/platform-server": "^18.0.0 || ^18.0.0-next.0",
|
|
54
55
|
"@angular/service-worker": "^18.0.0 || ^18.0.0-next.0",
|
|
56
|
+
"less": "^4.2.0",
|
|
55
57
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
56
58
|
"typescript": ">=5.4 <5.5"
|
|
57
59
|
},
|
|
@@ -65,6 +67,9 @@
|
|
|
65
67
|
"@angular/service-worker": {
|
|
66
68
|
"optional": true
|
|
67
69
|
},
|
|
70
|
+
"less": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
68
73
|
"tailwindcss": {
|
|
69
74
|
"optional": true
|
|
70
75
|
}
|
|
@@ -74,7 +79,7 @@
|
|
|
74
79
|
"url": "https://github.com/angular/angular-cli.git"
|
|
75
80
|
},
|
|
76
81
|
"engines": {
|
|
77
|
-
"node": "^18.19.1 ||
|
|
82
|
+
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
|
|
78
83
|
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
|
79
84
|
"yarn": ">= 1.13.0"
|
|
80
85
|
},
|
|
@@ -45,8 +45,8 @@ async function initialize(initialOptions, projectName, context) {
|
|
|
45
45
|
await (0, internal_1.purgeStaleBuildCache)(context);
|
|
46
46
|
const normalizedOptions = await (0, options_1.normalizeOptions)(context, projectName, initialOptions);
|
|
47
47
|
const builderName = await context.getBuilderNameForTarget(normalizedOptions.buildTarget);
|
|
48
|
-
if (
|
|
49
|
-
|
|
48
|
+
if (!/^127\.\d+\.\d+\.\d+/g.test(normalizedOptions.host) &&
|
|
49
|
+
normalizedOptions.host !== '::1' &&
|
|
50
50
|
normalizedOptions.host !== 'localhost') {
|
|
51
51
|
context.logger.warn(`
|
|
52
52
|
Warning: This is a simple server for use in testing or debugging Angular applications
|
|
@@ -54,14 +54,9 @@ locally. It hasn't been reviewed for security issues.
|
|
|
54
54
|
|
|
55
55
|
Binding this server to an open connection can result in compromising your application or
|
|
56
56
|
computer. Using a different host than the one passed to the "--host" flag might result in
|
|
57
|
-
websocket connection issues.
|
|
58
|
-
case.
|
|
57
|
+
websocket connection issues.
|
|
59
58
|
`);
|
|
60
59
|
}
|
|
61
|
-
if (normalizedOptions.disableHostCheck) {
|
|
62
|
-
context.logger.warn('Warning: Running a server with --disable-host-check is a security risk. ' +
|
|
63
|
-
'See https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a for more information.');
|
|
64
|
-
}
|
|
65
60
|
normalizedOptions.port = await (0, check_port_1.checkPort)(normalizedOptions.port, normalizedOptions.host);
|
|
66
61
|
return {
|
|
67
62
|
builderName,
|
|
@@ -34,14 +34,10 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
34
34
|
workspaceRoot: string;
|
|
35
35
|
projectRoot: string;
|
|
36
36
|
cacheOptions: import("../../utils/normalize-cache").NormalizedCachedOptions;
|
|
37
|
-
allowedHosts: string[] | undefined;
|
|
38
|
-
disableHostCheck: boolean | undefined;
|
|
39
37
|
proxyConfig: string | undefined;
|
|
40
38
|
servePath: string | undefined;
|
|
41
|
-
publicHost: string | undefined;
|
|
42
39
|
ssl: boolean | undefined;
|
|
43
40
|
sslCert: string | undefined;
|
|
44
41
|
sslKey: string | undefined;
|
|
45
|
-
forceEsbuild: boolean | undefined;
|
|
46
42
|
prebundle: import("./schema").PrebundleUnion;
|
|
47
43
|
}>;
|
|
@@ -30,10 +30,10 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
30
30
|
const projectRoot = node_path_1.default.join(workspaceRoot, projectMetadata.root ?? '');
|
|
31
31
|
const cacheOptions = (0, normalize_cache_1.normalizeCacheOptions)(projectMetadata, workspaceRoot);
|
|
32
32
|
// Target specifier defaults to the current project's build target using a development configuration
|
|
33
|
-
const buildTargetSpecifier = options.buildTarget ??
|
|
33
|
+
const buildTargetSpecifier = options.buildTarget ?? `::development`;
|
|
34
34
|
const buildTarget = (0, architect_1.targetFromTargetString)(buildTargetSpecifier, projectName, 'build');
|
|
35
35
|
// Initial options to keep
|
|
36
|
-
const { host, port, poll, open, verbose, watch,
|
|
36
|
+
const { host, port, poll, open, verbose, watch, liveReload, hmr, headers, proxyConfig, servePath, ssl, sslCert, sslKey, prebundle, } = options;
|
|
37
37
|
// Return all the normalized options
|
|
38
38
|
return {
|
|
39
39
|
buildTarget,
|
|
@@ -49,15 +49,11 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
49
49
|
workspaceRoot,
|
|
50
50
|
projectRoot,
|
|
51
51
|
cacheOptions,
|
|
52
|
-
allowedHosts,
|
|
53
|
-
disableHostCheck,
|
|
54
52
|
proxyConfig,
|
|
55
53
|
servePath,
|
|
56
|
-
publicHost,
|
|
57
54
|
ssl,
|
|
58
55
|
sslCert,
|
|
59
56
|
sslKey,
|
|
60
|
-
forceEsbuild,
|
|
61
57
|
// Prebundling defaults to true but requires caching to function
|
|
62
58
|
prebundle: cacheOptions.enabled && (prebundle ?? true),
|
|
63
59
|
};
|
|
@@ -2,34 +2,12 @@
|
|
|
2
2
|
* Dev Server target options for Build Facade.
|
|
3
3
|
*/
|
|
4
4
|
export interface Schema {
|
|
5
|
-
/**
|
|
6
|
-
* List of hosts that are allowed to access the dev server. This option has no effect when
|
|
7
|
-
* using the 'application' or other esbuild-based builders.
|
|
8
|
-
*/
|
|
9
|
-
allowedHosts?: string[];
|
|
10
|
-
/**
|
|
11
|
-
* A browser builder target to serve in the format of `project:target[:configuration]`. You
|
|
12
|
-
* can also pass in more than one configuration name as a comma-separated list. Example:
|
|
13
|
-
* `project:target:production,staging`.
|
|
14
|
-
* @deprecated Use 'buildTarget' instead.
|
|
15
|
-
*/
|
|
16
|
-
browserTarget?: string;
|
|
17
5
|
/**
|
|
18
6
|
* A build builder target to serve in the format of `project:target[:configuration]`. You
|
|
19
7
|
* can also pass in more than one configuration name as a comma-separated list. Example:
|
|
20
8
|
* `project:target:production,staging`.
|
|
21
9
|
*/
|
|
22
|
-
buildTarget
|
|
23
|
-
/**
|
|
24
|
-
* Don't verify connected clients are part of allowed hosts. This option has no effect when
|
|
25
|
-
* using the 'application' or other esbuild-based builders.
|
|
26
|
-
*/
|
|
27
|
-
disableHostCheck?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Force the development server to use the 'browser-esbuild' builder when building. This is
|
|
30
|
-
* a developer preview option for the esbuild-based build system.
|
|
31
|
-
*/
|
|
32
|
-
forceEsbuild?: boolean;
|
|
10
|
+
buildTarget: string;
|
|
33
11
|
/**
|
|
34
12
|
* Custom HTTP headers to be added to all responses.
|
|
35
13
|
*/
|
|
@@ -62,8 +40,7 @@ export interface Schema {
|
|
|
62
40
|
port?: number;
|
|
63
41
|
/**
|
|
64
42
|
* Enable and control the Vite-based development server's prebundling capabilities. To
|
|
65
|
-
* enable prebundling, the Angular CLI cache must also be enabled.
|
|
66
|
-
* when using the 'browser' or other Webpack-based builders.
|
|
43
|
+
* enable prebundling, the Angular CLI cache must also be enabled.
|
|
67
44
|
*/
|
|
68
45
|
prebundle?: PrebundleUnion;
|
|
69
46
|
/**
|
|
@@ -71,13 +48,6 @@ export interface Schema {
|
|
|
71
48
|
* https://angular.io/guide/build#proxying-to-a-backend-server.
|
|
72
49
|
*/
|
|
73
50
|
proxyConfig?: string;
|
|
74
|
-
/**
|
|
75
|
-
* The URL that the browser client (or live-reload client, if enabled) should use to connect
|
|
76
|
-
* to the development server. Use for a complex dev server setup, such as one with reverse
|
|
77
|
-
* proxies. This option has no effect when using the 'application' or other esbuild-based
|
|
78
|
-
* builders.
|
|
79
|
-
*/
|
|
80
|
-
publicHost?: string;
|
|
81
51
|
/**
|
|
82
52
|
* The pathname where the application will be served.
|
|
83
53
|
*/
|
|
@@ -105,8 +75,7 @@ export interface Schema {
|
|
|
105
75
|
}
|
|
106
76
|
/**
|
|
107
77
|
* Enable and control the Vite-based development server's prebundling capabilities. To
|
|
108
|
-
* enable prebundling, the Angular CLI cache must also be enabled.
|
|
109
|
-
* when using the 'browser' or other Webpack-based builders.
|
|
78
|
+
* enable prebundling, the Angular CLI cache must also be enabled.
|
|
110
79
|
*/
|
|
111
80
|
export type PrebundleUnion = boolean | PrebundleClass;
|
|
112
81
|
export interface PrebundleClass {
|
|
@@ -4,12 +4,6 @@
|
|
|
4
4
|
"description": "Dev Server target options for Build Facade.",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"properties": {
|
|
7
|
-
"browserTarget": {
|
|
8
|
-
"type": "string",
|
|
9
|
-
"description": "A browser builder target to serve 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`.",
|
|
10
|
-
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
|
|
11
|
-
"x-deprecated": "Use 'buildTarget' instead."
|
|
12
|
-
},
|
|
13
7
|
"buildTarget": {
|
|
14
8
|
"type": "string",
|
|
15
9
|
"description": "A build builder target to serve 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`.",
|
|
@@ -67,27 +61,10 @@
|
|
|
67
61
|
"description": "Whether to reload the page on change, using live-reload.",
|
|
68
62
|
"default": true
|
|
69
63
|
},
|
|
70
|
-
"publicHost": {
|
|
71
|
-
"type": "string",
|
|
72
|
-
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies. This option has no effect when using the 'application' or other esbuild-based builders."
|
|
73
|
-
},
|
|
74
|
-
"allowedHosts": {
|
|
75
|
-
"type": "array",
|
|
76
|
-
"description": "List of hosts that are allowed to access the dev server. This option has no effect when using the 'application' or other esbuild-based builders.",
|
|
77
|
-
"default": [],
|
|
78
|
-
"items": {
|
|
79
|
-
"type": "string"
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
64
|
"servePath": {
|
|
83
65
|
"type": "string",
|
|
84
66
|
"description": "The pathname where the application will be served."
|
|
85
67
|
},
|
|
86
|
-
"disableHostCheck": {
|
|
87
|
-
"type": "boolean",
|
|
88
|
-
"description": "Don't verify connected clients are part of allowed hosts. This option has no effect when using the 'application' or other esbuild-based builders.",
|
|
89
|
-
"default": false
|
|
90
|
-
},
|
|
91
68
|
"hmr": {
|
|
92
69
|
"type": "boolean",
|
|
93
70
|
"description": "Enable hot module replacement.",
|
|
@@ -102,13 +79,8 @@
|
|
|
102
79
|
"type": "number",
|
|
103
80
|
"description": "Enable and define the file watching poll time period in milliseconds."
|
|
104
81
|
},
|
|
105
|
-
"forceEsbuild": {
|
|
106
|
-
"type": "boolean",
|
|
107
|
-
"description": "Force the development server to use the 'browser-esbuild' builder when building. This is a developer preview option for the esbuild-based build system.",
|
|
108
|
-
"default": false
|
|
109
|
-
},
|
|
110
82
|
"prebundle": {
|
|
111
|
-
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled.
|
|
83
|
+
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled.",
|
|
112
84
|
"oneOf": [
|
|
113
85
|
{ "type": "boolean" },
|
|
114
86
|
{
|
|
@@ -127,5 +99,5 @@
|
|
|
127
99
|
}
|
|
128
100
|
},
|
|
129
101
|
"additionalProperties": false,
|
|
130
|
-
"
|
|
102
|
+
"required": ["buildTarget"]
|
|
131
103
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import type { ɵParsedMessage as LocalizeMessage } from '@angular/localize';
|
|
9
|
+
import type { MessageExtractor } from '@angular/localize/tools';
|
|
10
|
+
import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
11
|
+
import type { ApplicationBuilderExtensions } from '../application/options';
|
|
12
|
+
import type { NormalizedExtractI18nOptions } from './options';
|
|
13
|
+
export declare function extractMessages(options: NormalizedExtractI18nOptions, builderName: string, context: BuilderContext, extractorConstructor: typeof MessageExtractor, extensions?: ApplicationBuilderExtensions): Promise<{
|
|
14
|
+
builderResult: BuilderOutput;
|
|
15
|
+
basePath: string;
|
|
16
|
+
messages: LocalizeMessage[];
|
|
17
|
+
useLegacyIds: boolean;
|
|
18
|
+
}>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.extractMessages = void 0;
|
|
14
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
16
|
+
const application_1 = require("../application");
|
|
17
|
+
async function extractMessages(options, builderName, context, extractorConstructor, extensions) {
|
|
18
|
+
const messages = [];
|
|
19
|
+
// Setup the build options for the application based on the buildTarget option
|
|
20
|
+
const buildOptions = (await context.validateOptions(await context.getTargetOptions(options.buildTarget), builderName));
|
|
21
|
+
buildOptions.optimization = false;
|
|
22
|
+
buildOptions.sourceMap = { scripts: true, vendor: true, styles: false };
|
|
23
|
+
buildOptions.localize = false;
|
|
24
|
+
buildOptions.budgets = undefined;
|
|
25
|
+
buildOptions.index = false;
|
|
26
|
+
buildOptions.serviceWorker = false;
|
|
27
|
+
buildOptions.ssr = false;
|
|
28
|
+
buildOptions.appShell = false;
|
|
29
|
+
buildOptions.prerender = false;
|
|
30
|
+
// Build the application with the build options
|
|
31
|
+
let builderResult;
|
|
32
|
+
try {
|
|
33
|
+
for await (const result of (0, application_1.buildApplicationInternal)(buildOptions, context, { write: false }, extensions)) {
|
|
34
|
+
builderResult = result;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
(0, node_assert_1.default)(builderResult !== undefined, 'Application builder did not provide a result.');
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
builderResult = {
|
|
41
|
+
success: false,
|
|
42
|
+
error: err.message,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Extract messages from each output JavaScript file.
|
|
46
|
+
// Output files are only present on a successful build.
|
|
47
|
+
if (builderResult.outputFiles) {
|
|
48
|
+
// Store the JS and JS map files for lookup during extraction
|
|
49
|
+
const files = new Map();
|
|
50
|
+
for (const outputFile of builderResult.outputFiles) {
|
|
51
|
+
if (outputFile.path.endsWith('.js')) {
|
|
52
|
+
files.set(outputFile.path, outputFile.text);
|
|
53
|
+
}
|
|
54
|
+
else if (outputFile.path.endsWith('.js.map')) {
|
|
55
|
+
files.set(outputFile.path, outputFile.text);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Setup the localize message extractor based on the in-memory files
|
|
59
|
+
const extractor = setupLocalizeExtractor(extractorConstructor, files, context);
|
|
60
|
+
// Attempt extraction of all output JS files
|
|
61
|
+
for (const filePath of files.keys()) {
|
|
62
|
+
if (!filePath.endsWith('.js')) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const fileMessages = extractor.extractMessages(filePath);
|
|
66
|
+
messages.push(...fileMessages);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
builderResult,
|
|
71
|
+
basePath: context.workspaceRoot,
|
|
72
|
+
messages,
|
|
73
|
+
// Legacy i18n identifiers are not supported with the new application builder
|
|
74
|
+
useLegacyIds: false,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
exports.extractMessages = extractMessages;
|
|
78
|
+
function setupLocalizeExtractor(extractorConstructor, files, context) {
|
|
79
|
+
// Setup a virtual file system instance for the extractor
|
|
80
|
+
// * MessageExtractor itself uses readFile, relative and resolve
|
|
81
|
+
// * Internal SourceFileLoader (sourcemap support) uses dirname, exists, readFile, and resolve
|
|
82
|
+
const filesystem = {
|
|
83
|
+
readFile(path) {
|
|
84
|
+
// Output files are stored as relative to the workspace root
|
|
85
|
+
const requestedPath = node_path_1.default.relative(context.workspaceRoot, path);
|
|
86
|
+
const content = files.get(requestedPath);
|
|
87
|
+
if (content === undefined) {
|
|
88
|
+
throw new Error('Unknown file requested: ' + requestedPath);
|
|
89
|
+
}
|
|
90
|
+
return content;
|
|
91
|
+
},
|
|
92
|
+
relative(from, to) {
|
|
93
|
+
return node_path_1.default.relative(from, to);
|
|
94
|
+
},
|
|
95
|
+
resolve(...paths) {
|
|
96
|
+
return node_path_1.default.resolve(...paths);
|
|
97
|
+
},
|
|
98
|
+
exists(path) {
|
|
99
|
+
// Output files are stored as relative to the workspace root
|
|
100
|
+
const requestedPath = node_path_1.default.relative(context.workspaceRoot, path);
|
|
101
|
+
return files.has(requestedPath);
|
|
102
|
+
},
|
|
103
|
+
dirname(path) {
|
|
104
|
+
return node_path_1.default.dirname(path);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
const logger = {
|
|
108
|
+
// level 2 is warnings
|
|
109
|
+
level: 2,
|
|
110
|
+
debug(...args) {
|
|
111
|
+
// eslint-disable-next-line no-console
|
|
112
|
+
console.debug(...args);
|
|
113
|
+
},
|
|
114
|
+
info(...args) {
|
|
115
|
+
context.logger.info(args.join(''));
|
|
116
|
+
},
|
|
117
|
+
warn(...args) {
|
|
118
|
+
context.logger.warn(args.join(''));
|
|
119
|
+
},
|
|
120
|
+
error(...args) {
|
|
121
|
+
context.logger.error(args.join(''));
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
125
|
+
const extractor = new extractorConstructor(filesystem, logger, {
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
127
|
+
basePath: context.workspaceRoot,
|
|
128
|
+
useSourceMaps: true,
|
|
129
|
+
});
|
|
130
|
+
return extractor;
|
|
131
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
9
|
+
import type { ApplicationBuilderExtensions } from '../application/options';
|
|
10
|
+
import { Schema as ExtractI18nBuilderOptions } from './schema';
|
|
11
|
+
/**
|
|
12
|
+
* @experimental Direct usage of this function is considered experimental.
|
|
13
|
+
*/
|
|
14
|
+
export declare function execute(options: ExtractI18nBuilderOptions, context: BuilderContext, extensions?: ApplicationBuilderExtensions): Promise<BuilderOutput>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
26
|
+
if (mod && mod.__esModule) return mod;
|
|
27
|
+
var result = {};
|
|
28
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
29
|
+
__setModuleDefault(result, mod);
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
32
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
33
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
34
|
+
};
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.execute = void 0;
|
|
37
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
38
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
39
|
+
const load_esm_1 = require("../../utils/load-esm");
|
|
40
|
+
const version_1 = require("../../utils/version");
|
|
41
|
+
const options_1 = require("./options");
|
|
42
|
+
const schema_1 = require("./schema");
|
|
43
|
+
/**
|
|
44
|
+
* @experimental Direct usage of this function is considered experimental.
|
|
45
|
+
*/
|
|
46
|
+
async function execute(options, context, extensions) {
|
|
47
|
+
// Determine project name from builder context target
|
|
48
|
+
const projectName = context.target?.project;
|
|
49
|
+
if (!projectName) {
|
|
50
|
+
context.logger.error(`The 'extract-i18n' builder requires a target to be specified.`);
|
|
51
|
+
return { success: false };
|
|
52
|
+
}
|
|
53
|
+
// Check Angular version.
|
|
54
|
+
(0, version_1.assertCompatibleAngularVersion)(context.workspaceRoot);
|
|
55
|
+
// Load the Angular localize package.
|
|
56
|
+
// The package is a peer dependency and might not be present
|
|
57
|
+
let localizeToolsModule;
|
|
58
|
+
try {
|
|
59
|
+
localizeToolsModule =
|
|
60
|
+
await (0, load_esm_1.loadEsmModule)('@angular/localize/tools');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error: `i18n extraction requires the '@angular/localize' package.` +
|
|
66
|
+
` You can add it by using 'ng add @angular/localize'.`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// Normalize options
|
|
70
|
+
const normalizedOptions = await (0, options_1.normalizeOptions)(context, projectName, options);
|
|
71
|
+
const builderName = await context.getBuilderNameForTarget(normalizedOptions.buildTarget);
|
|
72
|
+
// Extract messages based on configured builder
|
|
73
|
+
const { extractMessages } = await Promise.resolve().then(() => __importStar(require('./application-extraction')));
|
|
74
|
+
const extractionResult = await extractMessages(normalizedOptions, builderName, context, localizeToolsModule.MessageExtractor, extensions);
|
|
75
|
+
// Return the builder result if it failed
|
|
76
|
+
if (!extractionResult.builderResult.success) {
|
|
77
|
+
return extractionResult.builderResult;
|
|
78
|
+
}
|
|
79
|
+
// Perform duplicate message checks
|
|
80
|
+
const { checkDuplicateMessages } = localizeToolsModule;
|
|
81
|
+
// The filesystem is used to create a relative path for each file
|
|
82
|
+
// from the basePath. This relative path is then used in the error message.
|
|
83
|
+
const checkFileSystem = {
|
|
84
|
+
relative(from, to) {
|
|
85
|
+
return node_path_1.default.relative(from, to);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
const diagnostics = checkDuplicateMessages(
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
|
+
checkFileSystem, extractionResult.messages, 'warning',
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
|
+
extractionResult.basePath);
|
|
93
|
+
if (diagnostics.messages.length > 0) {
|
|
94
|
+
context.logger.warn(diagnostics.formatDiagnostics(''));
|
|
95
|
+
}
|
|
96
|
+
// Serialize all extracted messages
|
|
97
|
+
const serializer = await createSerializer(localizeToolsModule, normalizedOptions.format, normalizedOptions.i18nOptions.sourceLocale, extractionResult.basePath, extractionResult.useLegacyIds, diagnostics);
|
|
98
|
+
const content = serializer.serialize(extractionResult.messages);
|
|
99
|
+
// Ensure directory exists
|
|
100
|
+
const outputPath = node_path_1.default.dirname(normalizedOptions.outFile);
|
|
101
|
+
if (!node_fs_1.default.existsSync(outputPath)) {
|
|
102
|
+
node_fs_1.default.mkdirSync(outputPath, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
// Write translation file
|
|
105
|
+
node_fs_1.default.writeFileSync(normalizedOptions.outFile, content);
|
|
106
|
+
if (normalizedOptions.progress) {
|
|
107
|
+
context.logger.info(`Extraction Complete. (Messages: ${extractionResult.messages.length})`);
|
|
108
|
+
}
|
|
109
|
+
return { success: true, outputPath: normalizedOptions.outFile };
|
|
110
|
+
}
|
|
111
|
+
exports.execute = execute;
|
|
112
|
+
async function createSerializer(localizeToolsModule, format, sourceLocale, basePath, useLegacyIds, diagnostics) {
|
|
113
|
+
const { XmbTranslationSerializer, LegacyMessageIdMigrationSerializer, ArbTranslationSerializer, Xliff1TranslationSerializer, Xliff2TranslationSerializer, SimpleJsonTranslationSerializer, } = localizeToolsModule;
|
|
114
|
+
switch (format) {
|
|
115
|
+
case schema_1.Format.Xmb:
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
return new XmbTranslationSerializer(basePath, useLegacyIds);
|
|
118
|
+
case schema_1.Format.Xlf:
|
|
119
|
+
case schema_1.Format.Xlif:
|
|
120
|
+
case schema_1.Format.Xliff:
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
return new Xliff1TranslationSerializer(sourceLocale, basePath, useLegacyIds, {});
|
|
123
|
+
case schema_1.Format.Xlf2:
|
|
124
|
+
case schema_1.Format.Xliff2:
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
+
return new Xliff2TranslationSerializer(sourceLocale, basePath, useLegacyIds, {});
|
|
127
|
+
case schema_1.Format.Json:
|
|
128
|
+
return new SimpleJsonTranslationSerializer(sourceLocale);
|
|
129
|
+
case schema_1.Format.LegacyMigrate:
|
|
130
|
+
return new LegacyMessageIdMigrationSerializer(diagnostics);
|
|
131
|
+
case schema_1.Format.Arb:
|
|
132
|
+
const fileSystem = {
|
|
133
|
+
relative(from, to) {
|
|
134
|
+
return node_path_1.default.relative(from, to);
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
138
|
+
return new ArbTranslationSerializer(sourceLocale, basePath, fileSystem);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import { execute } from './builder';
|
|
9
|
+
import type { Schema as ExtractI18nBuilderOptions } from './schema';
|
|
10
|
+
export { ExtractI18nBuilderOptions, execute };
|
|
11
|
+
declare const _default: import("../../../../../angular_devkit/architect/src/internal").Builder<ExtractI18nBuilderOptions & import("../../../../../angular_devkit/core/src").JsonObject>;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.execute = void 0;
|
|
11
|
+
const architect_1 = require("@angular-devkit/architect");
|
|
12
|
+
const builder_1 = require("./builder");
|
|
13
|
+
Object.defineProperty(exports, "execute", { enumerable: true, get: function () { return builder_1.execute; } });
|
|
14
|
+
exports.default = (0, architect_1.createBuilder)(builder_1.execute);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import { BuilderContext } from '@angular-devkit/architect';
|
|
9
|
+
import { Schema as ExtractI18nOptions, Format } from './schema';
|
|
10
|
+
export type NormalizedExtractI18nOptions = Awaited<ReturnType<typeof normalizeOptions>>;
|
|
11
|
+
/**
|
|
12
|
+
* Normalize the user provided options by creating full paths for all path based options
|
|
13
|
+
* and converting multi-form options into a single form that can be directly used
|
|
14
|
+
* by the build process.
|
|
15
|
+
*
|
|
16
|
+
* @param context The context for current builder execution.
|
|
17
|
+
* @param projectName The name of the project for the current execution.
|
|
18
|
+
* @param options An object containing the options to use for the build.
|
|
19
|
+
* @returns An object containing normalized options required to perform the build.
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizeOptions(context: BuilderContext, projectName: string, options: ExtractI18nOptions): Promise<{
|
|
22
|
+
workspaceRoot: string;
|
|
23
|
+
projectRoot: string;
|
|
24
|
+
buildTarget: import("@angular-devkit/architect").Target;
|
|
25
|
+
i18nOptions: import("../../utils/i18n-options").I18nOptions;
|
|
26
|
+
format: Format.Arb | Format.Json | Format.LegacyMigrate | Format.Xliff | Format.Xliff2 | Format.Xmb;
|
|
27
|
+
outFile: string;
|
|
28
|
+
progress: boolean;
|
|
29
|
+
}>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.normalizeOptions = void 0;
|
|
14
|
+
const architect_1 = require("@angular-devkit/architect");
|
|
15
|
+
const node_assert_1 = require("node:assert");
|
|
16
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
17
|
+
const i18n_options_1 = require("../../utils/i18n-options");
|
|
18
|
+
const schema_1 = require("./schema");
|
|
19
|
+
/**
|
|
20
|
+
* Normalize the user provided options by creating full paths for all path based options
|
|
21
|
+
* and converting multi-form options into a single form that can be directly used
|
|
22
|
+
* by the build process.
|
|
23
|
+
*
|
|
24
|
+
* @param context The context for current builder execution.
|
|
25
|
+
* @param projectName The name of the project for the current execution.
|
|
26
|
+
* @param options An object containing the options to use for the build.
|
|
27
|
+
* @returns An object containing normalized options required to perform the build.
|
|
28
|
+
*/
|
|
29
|
+
async function normalizeOptions(context, projectName, options) {
|
|
30
|
+
const workspaceRoot = context.workspaceRoot;
|
|
31
|
+
const projectMetadata = await context.getProjectMetadata(projectName);
|
|
32
|
+
const projectRoot = node_path_1.default.join(workspaceRoot, projectMetadata.root ?? '');
|
|
33
|
+
// Target specifier defaults to the current project's build target with no specified configuration
|
|
34
|
+
const buildTargetSpecifier = options.buildTarget ?? ':';
|
|
35
|
+
const buildTarget = (0, architect_1.targetFromTargetString)(buildTargetSpecifier, projectName, 'build');
|
|
36
|
+
const i18nOptions = (0, i18n_options_1.createI18nOptions)(projectMetadata);
|
|
37
|
+
// Normalize xliff format extensions
|
|
38
|
+
let format = options.format;
|
|
39
|
+
switch (format) {
|
|
40
|
+
case undefined:
|
|
41
|
+
// Default format is xliff1
|
|
42
|
+
case schema_1.Format.Xlf:
|
|
43
|
+
case schema_1.Format.Xlif:
|
|
44
|
+
case schema_1.Format.Xliff:
|
|
45
|
+
format = schema_1.Format.Xliff;
|
|
46
|
+
break;
|
|
47
|
+
case schema_1.Format.Xlf2:
|
|
48
|
+
case schema_1.Format.Xliff2:
|
|
49
|
+
format = schema_1.Format.Xliff2;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
let outFile = options.outFile || getDefaultOutFile(format);
|
|
53
|
+
if (options.outputPath) {
|
|
54
|
+
outFile = node_path_1.default.join(options.outputPath, outFile);
|
|
55
|
+
}
|
|
56
|
+
outFile = node_path_1.default.resolve(context.workspaceRoot, outFile);
|
|
57
|
+
return {
|
|
58
|
+
workspaceRoot,
|
|
59
|
+
projectRoot,
|
|
60
|
+
buildTarget,
|
|
61
|
+
i18nOptions,
|
|
62
|
+
format,
|
|
63
|
+
outFile,
|
|
64
|
+
progress: options.progress ?? true,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
exports.normalizeOptions = normalizeOptions;
|
|
68
|
+
function getDefaultOutFile(format) {
|
|
69
|
+
switch (format) {
|
|
70
|
+
case schema_1.Format.Xmb:
|
|
71
|
+
return 'messages.xmb';
|
|
72
|
+
case schema_1.Format.Xliff:
|
|
73
|
+
case schema_1.Format.Xliff2:
|
|
74
|
+
return 'messages.xlf';
|
|
75
|
+
case schema_1.Format.Json:
|
|
76
|
+
case schema_1.Format.LegacyMigrate:
|
|
77
|
+
return 'messages.json';
|
|
78
|
+
case schema_1.Format.Arb:
|
|
79
|
+
return 'messages.arb';
|
|
80
|
+
default:
|
|
81
|
+
(0, node_assert_1.fail)(`Invalid Format enum value: ${format}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract i18n target options for Build Facade.
|
|
3
|
+
*/
|
|
4
|
+
export interface Schema {
|
|
5
|
+
/**
|
|
6
|
+
* A builder target to extract i18n messages in the format of
|
|
7
|
+
* `project:target[:configuration]`. You can also pass in more than one configuration name
|
|
8
|
+
* as a comma-separated list. Example: `project:target:production,staging`.
|
|
9
|
+
*/
|
|
10
|
+
buildTarget: string;
|
|
11
|
+
/**
|
|
12
|
+
* Output format for the generated file.
|
|
13
|
+
*/
|
|
14
|
+
format?: Format;
|
|
15
|
+
/**
|
|
16
|
+
* Name of the file to output.
|
|
17
|
+
*/
|
|
18
|
+
outFile?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Path where output will be placed.
|
|
21
|
+
*/
|
|
22
|
+
outputPath?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Log progress to the console.
|
|
25
|
+
*/
|
|
26
|
+
progress?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Output format for the generated file.
|
|
30
|
+
*/
|
|
31
|
+
export declare enum Format {
|
|
32
|
+
Arb = "arb",
|
|
33
|
+
Json = "json",
|
|
34
|
+
LegacyMigrate = "legacy-migrate",
|
|
35
|
+
Xlf = "xlf",
|
|
36
|
+
Xlf2 = "xlf2",
|
|
37
|
+
Xlif = "xlif",
|
|
38
|
+
Xliff = "xliff",
|
|
39
|
+
Xliff2 = "xliff2",
|
|
40
|
+
Xmb = "xmb"
|
|
41
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
|
|
3
|
+
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.Format = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* Output format for the generated file.
|
|
8
|
+
*/
|
|
9
|
+
var Format;
|
|
10
|
+
(function (Format) {
|
|
11
|
+
Format["Arb"] = "arb";
|
|
12
|
+
Format["Json"] = "json";
|
|
13
|
+
Format["LegacyMigrate"] = "legacy-migrate";
|
|
14
|
+
Format["Xlf"] = "xlf";
|
|
15
|
+
Format["Xlf2"] = "xlf2";
|
|
16
|
+
Format["Xlif"] = "xlif";
|
|
17
|
+
Format["Xliff"] = "xliff";
|
|
18
|
+
Format["Xliff2"] = "xliff2";
|
|
19
|
+
Format["Xmb"] = "xmb";
|
|
20
|
+
})(Format || (exports.Format = Format = {}));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"title": "Extract i18n Target",
|
|
4
|
+
"description": "Extract i18n target options for Build Facade.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"buildTarget": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "A builder target to extract i18n messages 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`.",
|
|
10
|
+
"pattern": "^[^:\\s]*:[^:\\s]*(:[^\\s]+)?$"
|
|
11
|
+
},
|
|
12
|
+
"format": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Output format for the generated file.",
|
|
15
|
+
"default": "xlf",
|
|
16
|
+
"enum": ["xmb", "xlf", "xlif", "xliff", "xlf2", "xliff2", "json", "arb", "legacy-migrate"]
|
|
17
|
+
},
|
|
18
|
+
"progress": {
|
|
19
|
+
"type": "boolean",
|
|
20
|
+
"description": "Log progress to the console.",
|
|
21
|
+
"default": true
|
|
22
|
+
},
|
|
23
|
+
"outputPath": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"description": "Path where output will be placed."
|
|
26
|
+
},
|
|
27
|
+
"outFile": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Name of the file to output."
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"required": ["buildTarget"]
|
|
34
|
+
}
|
package/src/index.d.ts
CHANGED
|
@@ -9,3 +9,4 @@ export { buildApplication, type ApplicationBuilderOptions, type ApplicationBuild
|
|
|
9
9
|
export { type BuildOutputFile, BuildOutputFileType } from './tools/esbuild/bundler-context';
|
|
10
10
|
export type { BuildOutputAsset } from './tools/esbuild/bundler-execution-result';
|
|
11
11
|
export { executeDevServerBuilder, DevServerBuilderOptions, DevServerBuilderOutput, } from './builders/dev-server';
|
|
12
|
+
export { execute as executeExtractI18nBuilder, ExtractI18nBuilderOptions, } from './builders/extract-i18n';
|
package/src/index.js
CHANGED
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.executeDevServerBuilder = exports.BuildOutputFileType = exports.buildApplication = void 0;
|
|
10
|
+
exports.executeExtractI18nBuilder = exports.executeDevServerBuilder = exports.BuildOutputFileType = exports.buildApplication = void 0;
|
|
11
11
|
var application_1 = require("./builders/application");
|
|
12
12
|
Object.defineProperty(exports, "buildApplication", { enumerable: true, get: function () { return application_1.buildApplication; } });
|
|
13
13
|
var bundler_context_1 = require("./tools/esbuild/bundler-context");
|
|
14
14
|
Object.defineProperty(exports, "BuildOutputFileType", { enumerable: true, get: function () { return bundler_context_1.BuildOutputFileType; } });
|
|
15
15
|
var dev_server_1 = require("./builders/dev-server");
|
|
16
16
|
Object.defineProperty(exports, "executeDevServerBuilder", { enumerable: true, get: function () { return dev_server_1.executeDevServerBuilder; } });
|
|
17
|
+
var extract_i18n_1 = require("./builders/extract-i18n");
|
|
18
|
+
Object.defineProperty(exports, "executeExtractI18nBuilder", { enumerable: true, get: function () { return extract_i18n_1.execute; } });
|
|
@@ -50,7 +50,26 @@ exports.LessStylesheetLanguage = Object.freeze({
|
|
|
50
50
|
},
|
|
51
51
|
});
|
|
52
52
|
async function compileString(data, filename, options, resolver, unsafeInlineJavaScript) {
|
|
53
|
-
|
|
53
|
+
try {
|
|
54
|
+
lessPreprocessor ??= (await Promise.resolve().then(() => __importStar(require('less')))).default;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return {
|
|
58
|
+
errors: [
|
|
59
|
+
{
|
|
60
|
+
text: 'Unable to load the "less" stylesheet preprocessor.',
|
|
61
|
+
location: null,
|
|
62
|
+
notes: [
|
|
63
|
+
{
|
|
64
|
+
text: 'Ensure that the "less" Node.js package is installed within the project. ' +
|
|
65
|
+
"If not present, installation via the project's package manager should resolve the error.",
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const less = lessPreprocessor;
|
|
54
73
|
const resolverPlugin = {
|
|
55
74
|
install({ FileManager }, pluginManager) {
|
|
56
75
|
const resolverFileManager = new (class extends FileManager {
|
|
@@ -334,7 +334,7 @@ function transformSupportedBrowsersToTargets(supportedBrowsers) {
|
|
|
334
334
|
return transformed;
|
|
335
335
|
}
|
|
336
336
|
exports.transformSupportedBrowsersToTargets = transformSupportedBrowsersToTargets;
|
|
337
|
-
const SUPPORTED_NODE_VERSIONS = '^18.19.1 ||
|
|
337
|
+
const SUPPORTED_NODE_VERSIONS = '^18.19.1 || ^20.11.1 || >=22.0.0';
|
|
338
338
|
/**
|
|
339
339
|
* Transform supported Node.js versions to esbuild target.
|
|
340
340
|
* @see https://esbuild.github.io/api/#target
|
|
@@ -12,6 +12,23 @@ const node_crypto_1 = require("node:crypto");
|
|
|
12
12
|
const node_path_1 = require("node:path");
|
|
13
13
|
const load_esm_1 = require("../load-esm");
|
|
14
14
|
const html_rewriting_stream_1 = require("./html-rewriting-stream");
|
|
15
|
+
/** A list of valid self closing HTML elements */
|
|
16
|
+
const VALID_SELF_CLOSING_TAGS = new Set([
|
|
17
|
+
'area',
|
|
18
|
+
'base',
|
|
19
|
+
'br',
|
|
20
|
+
'col',
|
|
21
|
+
'embed',
|
|
22
|
+
'hr',
|
|
23
|
+
'img',
|
|
24
|
+
'input',
|
|
25
|
+
'link',
|
|
26
|
+
'meta',
|
|
27
|
+
'param',
|
|
28
|
+
'source',
|
|
29
|
+
'track',
|
|
30
|
+
'wbr',
|
|
31
|
+
]);
|
|
15
32
|
/*
|
|
16
33
|
* Helper function used by the IndexHtmlWebpackPlugin.
|
|
17
34
|
* Can also be directly used by builder, e. g. in order to generate an index.html
|
|
@@ -120,7 +137,7 @@ async function augmentIndexHtml(params) {
|
|
|
120
137
|
const baseTagExists = html.includes('<base');
|
|
121
138
|
const foundPreconnects = new Set();
|
|
122
139
|
rewriter
|
|
123
|
-
.on('startTag', (tag) => {
|
|
140
|
+
.on('startTag', (tag, rawTagHtml) => {
|
|
124
141
|
switch (tag.tagName) {
|
|
125
142
|
case 'html':
|
|
126
143
|
// Adjust document locale if specified
|
|
@@ -153,6 +170,11 @@ async function augmentIndexHtml(params) {
|
|
|
153
170
|
}
|
|
154
171
|
}
|
|
155
172
|
break;
|
|
173
|
+
default:
|
|
174
|
+
if (tag.selfClosing && !VALID_SELF_CLOSING_TAGS.has(tag.tagName)) {
|
|
175
|
+
errors.push(`Invalid self-closing element in index HTML file: '${rawTagHtml}'.`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
156
178
|
}
|
|
157
179
|
rewriter.emitStartTag(tag);
|
|
158
180
|
})
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = void 0;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
/** Version placeholder is replaced during the build process with actual package version */
|
|
13
|
-
const VERSION = '18.0.0-next.
|
|
13
|
+
const VERSION = '18.0.0-next.5';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
package/src/utils/version.js
CHANGED
|
@@ -47,7 +47,13 @@ function assertCompatibleAngularVersion(projectRoot) {
|
|
|
47
47
|
// repository with the generated development @angular/core npm package which is versioned "0.0.0".
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
let supportedAngularSemver;
|
|
51
|
+
try {
|
|
52
|
+
supportedAngularSemver = projectRequire('@angular/build/package.json')['peerDependencies']['@angular/compiler-cli'];
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
supportedAngularSemver = projectRequire('@angular-devkit/build-angular/package.json')['peerDependencies']['@angular/compiler-cli'];
|
|
56
|
+
}
|
|
51
57
|
const angularVersion = new semver_1.SemVer(angularPkgJson['version']);
|
|
52
58
|
if (!(0, semver_1.satisfies)(angularVersion, supportedAngularSemver, { includePrerelease: true })) {
|
|
53
59
|
console.error(`This version of CLI is only compatible with Angular versions ${supportedAngularSemver},\n` +
|