Skip to content

Commit dc2d460

Browse files
clydinvikerman
authored andcommitted
fix(@schematics/angular): workaround schematic/json AST issues in 9.0 i18n migration
1 parent c257515 commit dc2d460

File tree

1 file changed

+83
-32
lines changed

1 file changed

+83
-32
lines changed

packages/schematics/angular/migrations/update-9/update-i18n.ts

Lines changed: 83 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,63 @@ import { getAllOptions, getProjectTarget, getTargets, getWorkspace } from './uti
2121

2222
export function updateI18nConfig(): Rule {
2323
return (tree, context) => {
24+
// this is whole process of partial change writing and repeat loading/looping is only necessary
25+
// to workaround underlying issues with the recorder and ast helper functions
26+
2427
const workspacePath = getWorkspacePath(tree);
25-
const workspace = getWorkspace(tree);
26-
const recorder = tree.beginUpdate(workspacePath);
28+
let workspaceAst = getWorkspace(tree);
2729

28-
for (const { target } of getTargets(workspace, 'build', Builders.Browser)) {
29-
addBuilderI18NOptions(recorder, target, context.logger);
30+
// Update extract targets
31+
const extractTargets = getTargets(workspaceAst, 'extract-i18n', Builders.ExtractI18n);
32+
if (extractTargets.length > 0) {
33+
const recorder = tree.beginUpdate(workspacePath);
34+
35+
for (const { target, project } of extractTargets) {
36+
addProjectI18NOptions(recorder, tree, target, project);
37+
removeExtracti18nDeprecatedOptions(recorder, target);
38+
}
39+
40+
tree.commitUpdate(recorder);
41+
42+
// workspace was changed so need to reload
43+
workspaceAst = getWorkspace(tree);
3044
}
3145

32-
for (const { target } of getTargets(workspace, 'test', Builders.Karma)) {
33-
addBuilderI18NOptions(recorder, target, context.logger);
46+
// Update base HREF values for existing configurations
47+
let recorder = tree.beginUpdate(workspacePath);
48+
for (const { target } of getTargets(workspaceAst, 'build', Builders.Browser)) {
49+
updateBaseHrefs(recorder, target);
50+
}
51+
for (const { target } of getTargets(workspaceAst, 'test', Builders.Karma)) {
52+
updateBaseHrefs(recorder, target);
3453
}
54+
tree.commitUpdate(recorder);
3555

36-
for (const { target, project } of getTargets(workspace, 'extract-i18n', Builders.ExtractI18n)) {
37-
addProjectI18NOptions(recorder, tree, target, project);
38-
removeExtracti18nDeprecatedOptions(recorder, target);
56+
// Remove i18n format option
57+
workspaceAst = getWorkspace(tree);
58+
recorder = tree.beginUpdate(workspacePath);
59+
for (const { target } of getTargets(workspaceAst, 'build', Builders.Browser)) {
60+
removeFormatOption(recorder, target);
61+
}
62+
for (const { target } of getTargets(workspaceAst, 'test', Builders.Karma)) {
63+
removeFormatOption(recorder, target);
3964
}
65+
tree.commitUpdate(recorder);
4066

67+
// Add new i18n options to build target configurations
68+
workspaceAst = getWorkspace(tree);
69+
recorder = tree.beginUpdate(workspacePath);
70+
for (const { target } of getTargets(workspaceAst, 'build', Builders.Browser)) {
71+
addBuilderI18NOptions(recorder, target, context.logger);
72+
}
73+
tree.commitUpdate(recorder);
74+
75+
// Add new i18n options to test target configurations
76+
workspaceAst = getWorkspace(tree);
77+
recorder = tree.beginUpdate(workspacePath);
78+
for (const { target } of getTargets(workspaceAst, 'test', Builders.Karma)) {
79+
addBuilderI18NOptions(recorder, target, context.logger);
80+
}
4181
tree.commitUpdate(recorder);
4282

4383
return tree;
@@ -139,24 +179,11 @@ function addBuilderI18NOptions(
139179
logger: logging.LoggerApi,
140180
) {
141181
const options = getAllOptions(builderConfig);
142-
const mainOptions = findPropertyInAstObject(builderConfig, 'options');
143-
const mainBaseHref =
144-
mainOptions &&
145-
mainOptions.kind === 'object' &&
146-
findPropertyInAstObject(mainOptions, 'baseHref');
147-
const hasMainBaseHref =
148-
!!mainBaseHref && mainBaseHref.kind === 'string' && mainBaseHref.value !== '/';
149182

150183
for (const option of options) {
151184
const localeId = findPropertyInAstObject(option, 'i18nLocale');
152185
const i18nFile = findPropertyInAstObject(option, 'i18nFile');
153186

154-
// The format is always auto-detected now
155-
const i18nFormat = findPropertyInAstObject(option, 'i18nFormat');
156-
if (i18nFormat) {
157-
removePropertyInAstObject(recorder, option, 'i18nFormat');
158-
}
159-
160187
const outputPath = findPropertyInAstObject(option, 'outputPath');
161188
if (
162189
localeId &&
@@ -165,16 +192,6 @@ function addBuilderI18NOptions(
165192
outputPath &&
166193
outputPath.kind === 'string'
167194
) {
168-
// This first block was intended to remove the redundant output path field
169-
// but due to defects in the recorder, removing the option will cause malformed json
170-
// if (
171-
// mainOutputPathValue &&
172-
// outputPath.value.match(
173-
// new RegExp(`[/\\\\]?${mainOutputPathValue}[/\\\\]${localeId.value}[/\\\\]?$`),
174-
// )
175-
// ) {
176-
// removePropertyInAstObject(recorder, option, 'outputPath');
177-
// } else
178195
if (outputPath.value.match(new RegExp(`[/\\\\]${localeId.value}[/\\\\]?$`))) {
179196
const newOutputPath = outputPath.value.replace(
180197
new RegExp(`[/\\\\]${localeId.value}[/\\\\]?$`),
@@ -206,6 +223,40 @@ function addBuilderI18NOptions(
206223
if (i18nFile) {
207224
removePropertyInAstObject(recorder, option, 'i18nFile');
208225
}
226+
}
227+
}
228+
229+
function removeFormatOption(
230+
recorder: UpdateRecorder,
231+
builderConfig: JsonAstObject,
232+
) {
233+
const options = getAllOptions(builderConfig);
234+
235+
for (const option of options) {
236+
// The format is always auto-detected now
237+
const i18nFormat = findPropertyInAstObject(option, 'i18nFormat');
238+
if (i18nFormat) {
239+
removePropertyInAstObject(recorder, option, 'i18nFormat');
240+
}
241+
}
242+
}
243+
244+
function updateBaseHrefs(
245+
recorder: UpdateRecorder,
246+
builderConfig: JsonAstObject,
247+
) {
248+
const options = getAllOptions(builderConfig);
249+
const mainOptions = findPropertyInAstObject(builderConfig, 'options');
250+
const mainBaseHref =
251+
mainOptions &&
252+
mainOptions.kind === 'object' &&
253+
findPropertyInAstObject(mainOptions, 'baseHref');
254+
const hasMainBaseHref =
255+
!!mainBaseHref && mainBaseHref.kind === 'string' && mainBaseHref.value !== '/';
256+
257+
for (const option of options) {
258+
const localeId = findPropertyInAstObject(option, 'i18nLocale');
259+
const i18nFile = findPropertyInAstObject(option, 'i18nFile');
209260

210261
// localize base HREF values are controlled by the i18n configuration
211262
const baseHref = findPropertyInAstObject(option, 'baseHref');

0 commit comments

Comments
 (0)