@angular/compiler 17.0.2 → 17.0.4
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/esm2022/src/compiler.mjs +2 -3
- package/esm2022/src/expression_parser/parser.mjs +2 -2
- package/esm2022/src/i18n/digest.mjs +4 -1
- package/esm2022/src/i18n/extractor_merger.mjs +4 -2
- package/esm2022/src/i18n/i18n_ast.mjs +27 -1
- package/esm2022/src/i18n/i18n_html_parser.mjs +2 -2
- package/esm2022/src/i18n/i18n_parser.mjs +23 -6
- package/esm2022/src/i18n/message_bundle.mjs +7 -1
- package/esm2022/src/i18n/serializers/placeholder.mjs +29 -1
- package/esm2022/src/i18n/serializers/serializer.mjs +6 -1
- package/esm2022/src/i18n/serializers/xliff.mjs +7 -1
- package/esm2022/src/i18n/serializers/xliff2.mjs +19 -1
- package/esm2022/src/i18n/serializers/xmb.mjs +12 -1
- package/esm2022/src/i18n/translation_bundle.mjs +6 -1
- package/esm2022/src/jit_compiler_facade.mjs +2 -2
- package/esm2022/src/ml_parser/ast.mjs +4 -4
- package/esm2022/src/ml_parser/defaults.mjs +24 -0
- package/esm2022/src/ml_parser/lexer.mjs +2 -2
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/component.mjs +2 -2
- package/esm2022/src/render3/partial/directive.mjs +1 -1
- package/esm2022/src/render3/partial/factory.mjs +1 -1
- package/esm2022/src/render3/partial/injectable.mjs +1 -1
- package/esm2022/src/render3/partial/injector.mjs +1 -1
- package/esm2022/src/render3/partial/ng_module.mjs +1 -1
- package/esm2022/src/render3/partial/pipe.mjs +1 -1
- package/esm2022/src/render3/r3_ast.mjs +17 -9
- package/esm2022/src/render3/r3_control_flow.mjs +7 -7
- package/esm2022/src/render3/r3_deferred_blocks.mjs +5 -5
- package/esm2022/src/render3/view/api.mjs +1 -1
- package/esm2022/src/render3/view/i18n/context.mjs +13 -1
- package/esm2022/src/render3/view/i18n/get_msg_utils.mjs +4 -1
- package/esm2022/src/render3/view/i18n/icu_serializer.mjs +4 -1
- package/esm2022/src/render3/view/i18n/localize_utils.mjs +6 -1
- package/esm2022/src/render3/view/i18n/meta.mjs +5 -4
- package/esm2022/src/render3/view/template.mjs +82 -34
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +7 -3
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +3 -3
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +14 -5
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +2 -12
- package/esm2022/src/template/pipeline/src/emit.mjs +3 -3
- package/esm2022/src/template/pipeline/src/ingest.mjs +28 -7
- package/esm2022/src/template/pipeline/src/instruction.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/apply_i18n_expressions.mjs +15 -5
- package/esm2022/src/template/pipeline/src/phases/create_i18n_contexts.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/extract_i18n_messages.mjs +23 -14
- package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +9 -3
- package/esm2022/src/template/pipeline/src/phases/i18n_text_extraction.mjs +18 -3
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_element_placeholders.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.mjs +9 -5
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_icu_placeholders.mjs +78 -0
- package/esm2022/src/template/pipeline/src/phases/wrap_icus.mjs +11 -5
- package/esm2022/src/template_parser/binding_parser.mjs +1 -1
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +479 -174
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +36 -12
- package/package.json +2 -2
- package/esm2022/src/ml_parser/interpolation_config.mjs +0 -23
- package/esm2022/src/template/pipeline/src/phases/create_i18n_icu_expressions.mjs +0 -52
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.
|
|
2
|
+
* @license Angular v17.0.4
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -539,6 +539,9 @@ class _SerializerVisitor {
|
|
|
539
539
|
visitIcuPlaceholder(ph, context) {
|
|
540
540
|
return `<ph icu name="${ph.name}">${ph.value.visit(this)}</ph>`;
|
|
541
541
|
}
|
|
542
|
+
visitBlockPlaceholder(ph, context) {
|
|
543
|
+
return `<ph block name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
|
|
544
|
+
}
|
|
542
545
|
}
|
|
543
546
|
const serializerVisitor$1 = new _SerializerVisitor();
|
|
544
547
|
function serializeNodes(nodes) {
|
|
@@ -3847,43 +3850,47 @@ class BlockNode {
|
|
|
3847
3850
|
}
|
|
3848
3851
|
}
|
|
3849
3852
|
class DeferredBlockPlaceholder extends BlockNode {
|
|
3850
|
-
constructor(children, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3853
|
+
constructor(children, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3851
3854
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3852
3855
|
this.children = children;
|
|
3853
3856
|
this.minimumTime = minimumTime;
|
|
3857
|
+
this.i18n = i18n;
|
|
3854
3858
|
}
|
|
3855
3859
|
visit(visitor) {
|
|
3856
3860
|
return visitor.visitDeferredBlockPlaceholder(this);
|
|
3857
3861
|
}
|
|
3858
3862
|
}
|
|
3859
3863
|
class DeferredBlockLoading extends BlockNode {
|
|
3860
|
-
constructor(children, afterTime, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3864
|
+
constructor(children, afterTime, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3861
3865
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3862
3866
|
this.children = children;
|
|
3863
3867
|
this.afterTime = afterTime;
|
|
3864
3868
|
this.minimumTime = minimumTime;
|
|
3869
|
+
this.i18n = i18n;
|
|
3865
3870
|
}
|
|
3866
3871
|
visit(visitor) {
|
|
3867
3872
|
return visitor.visitDeferredBlockLoading(this);
|
|
3868
3873
|
}
|
|
3869
3874
|
}
|
|
3870
3875
|
class DeferredBlockError extends BlockNode {
|
|
3871
|
-
constructor(children, nameSpan, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3876
|
+
constructor(children, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3872
3877
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3873
3878
|
this.children = children;
|
|
3879
|
+
this.i18n = i18n;
|
|
3874
3880
|
}
|
|
3875
3881
|
visit(visitor) {
|
|
3876
3882
|
return visitor.visitDeferredBlockError(this);
|
|
3877
3883
|
}
|
|
3878
3884
|
}
|
|
3879
3885
|
class DeferredBlock extends BlockNode {
|
|
3880
|
-
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, nameSpan, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan) {
|
|
3886
|
+
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, nameSpan, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3881
3887
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3882
3888
|
this.children = children;
|
|
3883
3889
|
this.placeholder = placeholder;
|
|
3884
3890
|
this.loading = loading;
|
|
3885
3891
|
this.error = error;
|
|
3886
3892
|
this.mainBlockSpan = mainBlockSpan;
|
|
3893
|
+
this.i18n = i18n;
|
|
3887
3894
|
this.triggers = triggers;
|
|
3888
3895
|
this.prefetchTriggers = prefetchTriggers;
|
|
3889
3896
|
// We cache the keys since we know that they won't change and we
|
|
@@ -3922,17 +3929,18 @@ class SwitchBlock extends BlockNode {
|
|
|
3922
3929
|
}
|
|
3923
3930
|
}
|
|
3924
3931
|
class SwitchBlockCase extends BlockNode {
|
|
3925
|
-
constructor(expression, children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3932
|
+
constructor(expression, children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3926
3933
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3927
3934
|
this.expression = expression;
|
|
3928
3935
|
this.children = children;
|
|
3936
|
+
this.i18n = i18n;
|
|
3929
3937
|
}
|
|
3930
3938
|
visit(visitor) {
|
|
3931
3939
|
return visitor.visitSwitchBlockCase(this);
|
|
3932
3940
|
}
|
|
3933
3941
|
}
|
|
3934
3942
|
class ForLoopBlock extends BlockNode {
|
|
3935
|
-
constructor(item, expression, trackBy, trackKeywordSpan, contextVariables, children, empty, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3943
|
+
constructor(item, expression, trackBy, trackKeywordSpan, contextVariables, children, empty, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3936
3944
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3937
3945
|
this.item = item;
|
|
3938
3946
|
this.expression = expression;
|
|
@@ -3942,15 +3950,17 @@ class ForLoopBlock extends BlockNode {
|
|
|
3942
3950
|
this.children = children;
|
|
3943
3951
|
this.empty = empty;
|
|
3944
3952
|
this.mainBlockSpan = mainBlockSpan;
|
|
3953
|
+
this.i18n = i18n;
|
|
3945
3954
|
}
|
|
3946
3955
|
visit(visitor) {
|
|
3947
3956
|
return visitor.visitForLoopBlock(this);
|
|
3948
3957
|
}
|
|
3949
3958
|
}
|
|
3950
3959
|
class ForLoopBlockEmpty extends BlockNode {
|
|
3951
|
-
constructor(children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3960
|
+
constructor(children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3952
3961
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3953
3962
|
this.children = children;
|
|
3963
|
+
this.i18n = i18n;
|
|
3954
3964
|
}
|
|
3955
3965
|
visit(visitor) {
|
|
3956
3966
|
return visitor.visitForLoopBlockEmpty(this);
|
|
@@ -3966,11 +3976,12 @@ class IfBlock extends BlockNode {
|
|
|
3966
3976
|
}
|
|
3967
3977
|
}
|
|
3968
3978
|
class IfBlockBranch extends BlockNode {
|
|
3969
|
-
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3979
|
+
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3970
3980
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3971
3981
|
this.expression = expression;
|
|
3972
3982
|
this.children = children;
|
|
3973
3983
|
this.expressionAlias = expressionAlias;
|
|
3984
|
+
this.i18n = i18n;
|
|
3974
3985
|
}
|
|
3975
3986
|
visit(visitor) {
|
|
3976
3987
|
return visitor.visitIfBlockBranch(this);
|
|
@@ -4240,6 +4251,21 @@ class IcuPlaceholder {
|
|
|
4240
4251
|
return visitor.visitIcuPlaceholder(this, context);
|
|
4241
4252
|
}
|
|
4242
4253
|
}
|
|
4254
|
+
class BlockPlaceholder {
|
|
4255
|
+
constructor(name, parameters, startName, closeName, children, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
4256
|
+
this.name = name;
|
|
4257
|
+
this.parameters = parameters;
|
|
4258
|
+
this.startName = startName;
|
|
4259
|
+
this.closeName = closeName;
|
|
4260
|
+
this.children = children;
|
|
4261
|
+
this.sourceSpan = sourceSpan;
|
|
4262
|
+
this.startSourceSpan = startSourceSpan;
|
|
4263
|
+
this.endSourceSpan = endSourceSpan;
|
|
4264
|
+
}
|
|
4265
|
+
visit(visitor, context) {
|
|
4266
|
+
return visitor.visitBlockPlaceholder(this, context);
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4243
4269
|
// Clone the AST
|
|
4244
4270
|
class CloneVisitor {
|
|
4245
4271
|
visitText(text, context) {
|
|
@@ -4265,6 +4291,10 @@ class CloneVisitor {
|
|
|
4265
4291
|
visitIcuPlaceholder(ph, context) {
|
|
4266
4292
|
return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan);
|
|
4267
4293
|
}
|
|
4294
|
+
visitBlockPlaceholder(ph, context) {
|
|
4295
|
+
const children = ph.children.map(n => n.visit(this, context));
|
|
4296
|
+
return new BlockPlaceholder(ph.name, ph.parameters, ph.startName, ph.closeName, children, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
|
|
4297
|
+
}
|
|
4268
4298
|
}
|
|
4269
4299
|
// Visit all the nodes recursively
|
|
4270
4300
|
class RecurseVisitor {
|
|
@@ -4282,6 +4312,9 @@ class RecurseVisitor {
|
|
|
4282
4312
|
}
|
|
4283
4313
|
visitPlaceholder(ph, context) { }
|
|
4284
4314
|
visitIcuPlaceholder(ph, context) { }
|
|
4315
|
+
visitBlockPlaceholder(ph, context) {
|
|
4316
|
+
ph.children.forEach(child => child.visit(this));
|
|
4317
|
+
}
|
|
4285
4318
|
}
|
|
4286
4319
|
/**
|
|
4287
4320
|
* Serialize the message to the Localize backtick string format that would appear in compiled code.
|
|
@@ -4312,6 +4345,10 @@ class LocalizeMessageStringVisitor {
|
|
|
4312
4345
|
visitIcuPlaceholder(ph) {
|
|
4313
4346
|
return `{$${ph.name}}`;
|
|
4314
4347
|
}
|
|
4348
|
+
visitBlockPlaceholder(ph) {
|
|
4349
|
+
const children = ph.children.map(child => child.visit(this)).join('');
|
|
4350
|
+
return `{$${ph.startName}}${children}{$${ph.closeName}}`;
|
|
4351
|
+
}
|
|
4315
4352
|
}
|
|
4316
4353
|
|
|
4317
4354
|
class Serializer {
|
|
@@ -4354,6 +4391,11 @@ class SimplePlaceholderMapper extends RecurseVisitor {
|
|
|
4354
4391
|
visitPlaceholder(ph, context) {
|
|
4355
4392
|
this.visitPlaceholderName(ph.name);
|
|
4356
4393
|
}
|
|
4394
|
+
visitBlockPlaceholder(ph, context) {
|
|
4395
|
+
this.visitPlaceholderName(ph.startName);
|
|
4396
|
+
super.visitBlockPlaceholder(ph, context);
|
|
4397
|
+
this.visitPlaceholderName(ph.closeName);
|
|
4398
|
+
}
|
|
4357
4399
|
visitIcuPlaceholder(ph, context) {
|
|
4358
4400
|
this.visitPlaceholderName(ph.name);
|
|
4359
4401
|
}
|
|
@@ -4566,6 +4608,17 @@ class _Visitor$1 {
|
|
|
4566
4608
|
new Tag(_PLACEHOLDER_TAG$3, { name: ph.name }, [exTag, interpolationAsText])
|
|
4567
4609
|
];
|
|
4568
4610
|
}
|
|
4611
|
+
visitBlockPlaceholder(ph, context) {
|
|
4612
|
+
const startAsText = new Text$1(`@${ph.name}`);
|
|
4613
|
+
const startEx = new Tag(_EXAMPLE_TAG, {}, [startAsText]);
|
|
4614
|
+
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
|
|
4615
|
+
const startTagPh = new Tag(_PLACEHOLDER_TAG$3, { name: ph.startName }, [startEx, startAsText]);
|
|
4616
|
+
const closeAsText = new Text$1(`}`);
|
|
4617
|
+
const closeEx = new Tag(_EXAMPLE_TAG, {}, [closeAsText]);
|
|
4618
|
+
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
|
|
4619
|
+
const closeTagPh = new Tag(_PLACEHOLDER_TAG$3, { name: ph.closeName }, [closeEx, closeAsText]);
|
|
4620
|
+
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
|
|
4621
|
+
}
|
|
4569
4622
|
visitIcuPlaceholder(ph, context) {
|
|
4570
4623
|
const icuExpression = ph.value.expression;
|
|
4571
4624
|
const icuType = ph.value.type;
|
|
@@ -5211,6 +5264,7 @@ class InterpolationConfig {
|
|
|
5211
5264
|
}
|
|
5212
5265
|
}
|
|
5213
5266
|
const DEFAULT_INTERPOLATION_CONFIG = new InterpolationConfig('{{', '}}');
|
|
5267
|
+
const DEFAULT_CONTAINER_BLOCKS = new Set(['switch']);
|
|
5214
5268
|
|
|
5215
5269
|
const $EOF = 0;
|
|
5216
5270
|
const $BSPACE = 8;
|
|
@@ -8852,11 +8906,11 @@ var OpKind;
|
|
|
8852
8906
|
/**
|
|
8853
8907
|
* An instruction to create an ICU expression.
|
|
8854
8908
|
*/
|
|
8855
|
-
OpKind[OpKind["
|
|
8909
|
+
OpKind[OpKind["IcuStart"] = 41] = "IcuStart";
|
|
8856
8910
|
/**
|
|
8857
8911
|
* An instruction to update an ICU expression.
|
|
8858
8912
|
*/
|
|
8859
|
-
OpKind[OpKind["
|
|
8913
|
+
OpKind[OpKind["IcuEnd"] = 42] = "IcuEnd";
|
|
8860
8914
|
/**
|
|
8861
8915
|
* An i18n context containing information needed to generate an i18n message.
|
|
8862
8916
|
*/
|
|
@@ -9105,6 +9159,10 @@ var I18nParamValueFlags;
|
|
|
9105
9159
|
* This value represents the closing of a tag.
|
|
9106
9160
|
*/
|
|
9107
9161
|
I18nParamValueFlags[I18nParamValueFlags["CloseTag"] = 8] = "CloseTag";
|
|
9162
|
+
/**
|
|
9163
|
+
* This value represents an i18n expression index.
|
|
9164
|
+
*/
|
|
9165
|
+
I18nParamValueFlags[I18nParamValueFlags["ExpressionIndex"] = 16] = "ExpressionIndex";
|
|
9108
9166
|
})(I18nParamValueFlags || (I18nParamValueFlags = {}));
|
|
9109
9167
|
/**
|
|
9110
9168
|
* Whether the active namespace is HTML, MathML, or SVG mode.
|
|
@@ -9410,6 +9468,7 @@ function createRepeaterOp(repeaterCreate, targetSlot, collection, sourceSpan) {
|
|
|
9410
9468
|
collection,
|
|
9411
9469
|
sourceSpan,
|
|
9412
9470
|
...NEW_OP,
|
|
9471
|
+
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9413
9472
|
};
|
|
9414
9473
|
}
|
|
9415
9474
|
function createDeferWhenOp(target, expr, prefetch, sourceSpan) {
|
|
@@ -9453,17 +9512,6 @@ function createI18nApplyOp(target, handle, sourceSpan) {
|
|
|
9453
9512
|
...NEW_OP,
|
|
9454
9513
|
};
|
|
9455
9514
|
}
|
|
9456
|
-
/**
|
|
9457
|
-
* Creates an op to update an ICU expression.
|
|
9458
|
-
*/
|
|
9459
|
-
function createIcuUpdateOp(xref, sourceSpan) {
|
|
9460
|
-
return {
|
|
9461
|
-
kind: OpKind.IcuUpdate,
|
|
9462
|
-
xref,
|
|
9463
|
-
sourceSpan,
|
|
9464
|
-
...NEW_OP,
|
|
9465
|
-
};
|
|
9466
|
-
}
|
|
9467
9515
|
|
|
9468
9516
|
var _a, _b, _c, _d, _e, _f;
|
|
9469
9517
|
/**
|
|
@@ -10254,8 +10302,8 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10254
10302
|
case OpKind.I18nContext:
|
|
10255
10303
|
case OpKind.I18nEnd:
|
|
10256
10304
|
case OpKind.I18nStart:
|
|
10257
|
-
case OpKind.
|
|
10258
|
-
case OpKind.
|
|
10305
|
+
case OpKind.IcuEnd:
|
|
10306
|
+
case OpKind.IcuStart:
|
|
10259
10307
|
case OpKind.Namespace:
|
|
10260
10308
|
case OpKind.Pipe:
|
|
10261
10309
|
case OpKind.Projection:
|
|
@@ -10908,20 +10956,29 @@ function createI18nEndOp(xref) {
|
|
|
10908
10956
|
};
|
|
10909
10957
|
}
|
|
10910
10958
|
/**
|
|
10911
|
-
* Creates an
|
|
10959
|
+
* Creates an ICU start op.
|
|
10912
10960
|
*/
|
|
10913
|
-
function
|
|
10961
|
+
function createIcuStartOp(xref, message, messagePlaceholder, sourceSpan) {
|
|
10914
10962
|
return {
|
|
10915
|
-
kind: OpKind.
|
|
10963
|
+
kind: OpKind.IcuStart,
|
|
10916
10964
|
xref,
|
|
10917
10965
|
message,
|
|
10918
|
-
icu,
|
|
10919
10966
|
messagePlaceholder,
|
|
10920
10967
|
context: null,
|
|
10921
10968
|
sourceSpan,
|
|
10922
10969
|
...NEW_OP,
|
|
10923
10970
|
};
|
|
10924
10971
|
}
|
|
10972
|
+
/**
|
|
10973
|
+
* Creates an ICU end op.
|
|
10974
|
+
*/
|
|
10975
|
+
function createIcuEndOp(xref) {
|
|
10976
|
+
return {
|
|
10977
|
+
kind: OpKind.IcuEnd,
|
|
10978
|
+
xref,
|
|
10979
|
+
...NEW_OP,
|
|
10980
|
+
};
|
|
10981
|
+
}
|
|
10925
10982
|
function createI18nContextOp(xref, i18nBlock, message, sourceSpan) {
|
|
10926
10983
|
return {
|
|
10927
10984
|
kind: OpKind.I18nContext,
|
|
@@ -11170,10 +11227,18 @@ function removeAnys(e) {
|
|
|
11170
11227
|
* Adds apply operations after i18n expressions.
|
|
11171
11228
|
*/
|
|
11172
11229
|
function applyI18nExpressions(job) {
|
|
11230
|
+
const i18nContexts = new Map();
|
|
11231
|
+
for (const unit of job.units) {
|
|
11232
|
+
for (const op of unit.create) {
|
|
11233
|
+
if (op.kind === OpKind.I18nContext) {
|
|
11234
|
+
i18nContexts.set(op.xref, op);
|
|
11235
|
+
}
|
|
11236
|
+
}
|
|
11237
|
+
}
|
|
11173
11238
|
for (const unit of job.units) {
|
|
11174
11239
|
for (const op of unit.update) {
|
|
11175
11240
|
// Only add apply after expressions that are not followed by more expressions.
|
|
11176
|
-
if (op.kind === OpKind.I18nExpression && needsApplication(op)) {
|
|
11241
|
+
if (op.kind === OpKind.I18nExpression && needsApplication(i18nContexts, op)) {
|
|
11177
11242
|
// TODO: what should be the source span for the apply op?
|
|
11178
11243
|
OpList.insertAfter(createI18nApplyOp(op.target, op.handle, null), op);
|
|
11179
11244
|
}
|
|
@@ -11183,13 +11248,15 @@ function applyI18nExpressions(job) {
|
|
|
11183
11248
|
/**
|
|
11184
11249
|
* Checks whether the given expression op needs to be followed with an apply op.
|
|
11185
11250
|
*/
|
|
11186
|
-
function needsApplication(op) {
|
|
11251
|
+
function needsApplication(i18nContexts, op) {
|
|
11187
11252
|
// If the next op is not another expression, we need to apply.
|
|
11188
11253
|
if (op.next?.kind !== OpKind.I18nExpression) {
|
|
11189
11254
|
return true;
|
|
11190
11255
|
}
|
|
11191
|
-
// If the next op is an expression targeting a different i18n
|
|
11192
|
-
|
|
11256
|
+
// If the next op is an expression targeting a different i18n block, we need to apply.
|
|
11257
|
+
const context = i18nContexts.get(op.context);
|
|
11258
|
+
const nextContext = i18nContexts.get(op.next.context);
|
|
11259
|
+
if (context.i18nBlock !== nextContext.i18nBlock) {
|
|
11193
11260
|
return true;
|
|
11194
11261
|
}
|
|
11195
11262
|
return false;
|
|
@@ -11850,7 +11917,7 @@ function createI18nContexts(job) {
|
|
|
11850
11917
|
case OpKind.I18nEnd:
|
|
11851
11918
|
currentI18nOp = null;
|
|
11852
11919
|
break;
|
|
11853
|
-
case OpKind.
|
|
11920
|
+
case OpKind.IcuStart:
|
|
11854
11921
|
// If an ICU represents a different message than its containing block, we give it its own
|
|
11855
11922
|
// i18n context.
|
|
11856
11923
|
if (currentI18nOp === null) {
|
|
@@ -11873,50 +11940,6 @@ function createI18nContexts(job) {
|
|
|
11873
11940
|
}
|
|
11874
11941
|
}
|
|
11875
11942
|
|
|
11876
|
-
/**
|
|
11877
|
-
* Replace the ICU update ops with i18n expression ops.
|
|
11878
|
-
*/
|
|
11879
|
-
function createI18nIcuExpressions(job) {
|
|
11880
|
-
const icus = new Map();
|
|
11881
|
-
const i18nContexts = new Map();
|
|
11882
|
-
const i18nBlocks = new Map();
|
|
11883
|
-
// Collect maps of ops that need to be referenced to create the I18nExpressionOps.
|
|
11884
|
-
for (const unit of job.units) {
|
|
11885
|
-
for (const op of unit.create) {
|
|
11886
|
-
switch (op.kind) {
|
|
11887
|
-
case OpKind.Icu:
|
|
11888
|
-
icus.set(op.xref, op);
|
|
11889
|
-
break;
|
|
11890
|
-
case OpKind.I18nContext:
|
|
11891
|
-
i18nContexts.set(op.xref, op);
|
|
11892
|
-
break;
|
|
11893
|
-
case OpKind.I18nStart:
|
|
11894
|
-
i18nBlocks.set(op.xref, op);
|
|
11895
|
-
break;
|
|
11896
|
-
}
|
|
11897
|
-
}
|
|
11898
|
-
// Replace each IcuUpdateOp with an I18nExpressionOp.
|
|
11899
|
-
for (const op of unit.update) {
|
|
11900
|
-
switch (op.kind) {
|
|
11901
|
-
case OpKind.IcuUpdate:
|
|
11902
|
-
const icuOp = icus.get(op.xref);
|
|
11903
|
-
if (icuOp?.icu.expressionPlaceholder === undefined) {
|
|
11904
|
-
throw Error('ICU should have an i18n placeholder');
|
|
11905
|
-
}
|
|
11906
|
-
if (icuOp.context === null) {
|
|
11907
|
-
throw Error('ICU should have its i18n context set');
|
|
11908
|
-
}
|
|
11909
|
-
const i18nContext = i18nContexts.get(icuOp.context);
|
|
11910
|
-
const i18nBlock = i18nBlocks.get(i18nContext.i18nBlock);
|
|
11911
|
-
OpList.replace(op, createI18nExpressionOp(i18nContext.xref, i18nBlock.xref, i18nBlock.handle, new LexicalReadExpr(icuOp.icu.expression), icuOp.icu.expressionPlaceholder,
|
|
11912
|
-
// ICU-based i18n Expressions are resolved during post-processing.
|
|
11913
|
-
I18nParamResolutionTime.Postproccessing, null));
|
|
11914
|
-
break;
|
|
11915
|
-
}
|
|
11916
|
-
}
|
|
11917
|
-
}
|
|
11918
|
-
}
|
|
11919
|
-
|
|
11920
11943
|
/**
|
|
11921
11944
|
* Defer instructions take a configuration array, which should be collected into the component
|
|
11922
11945
|
* consts. This phase finds the config options, and creates the corresponding const array.
|
|
@@ -12331,18 +12354,23 @@ function extractI18nMessages(job) {
|
|
|
12331
12354
|
// Extract messages from ICUs with their own sub-context.
|
|
12332
12355
|
for (const unit of job.units) {
|
|
12333
12356
|
for (const op of unit.create) {
|
|
12334
|
-
|
|
12335
|
-
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
12357
|
+
switch (op.kind) {
|
|
12358
|
+
case OpKind.IcuStart:
|
|
12359
|
+
if (!op.context) {
|
|
12360
|
+
throw Error('ICU op should have its context set.');
|
|
12361
|
+
}
|
|
12362
|
+
if (!i18nBlockContexts.has(op.context)) {
|
|
12363
|
+
const i18nContext = i18nContexts.get(op.context);
|
|
12364
|
+
const subMessage = createI18nMessage(job, i18nContext, op.messagePlaceholder);
|
|
12365
|
+
unit.create.push(subMessage);
|
|
12366
|
+
const parentMessage = i18nBlockMessages.get(i18nContext.i18nBlock);
|
|
12367
|
+
parentMessage?.subMessages.push(subMessage.xref);
|
|
12368
|
+
}
|
|
12369
|
+
OpList.remove(op);
|
|
12370
|
+
break;
|
|
12371
|
+
case OpKind.IcuEnd:
|
|
12372
|
+
OpList.remove(op);
|
|
12373
|
+
break;
|
|
12346
12374
|
}
|
|
12347
12375
|
}
|
|
12348
12376
|
}
|
|
@@ -12364,7 +12392,7 @@ function createI18nMessage(job, context, messagePlaceholder) {
|
|
|
12364
12392
|
*/
|
|
12365
12393
|
function formatParams(params) {
|
|
12366
12394
|
const result = new Map();
|
|
12367
|
-
for (const [placeholder, placeholderValues] of
|
|
12395
|
+
for (const [placeholder, placeholderValues] of params) {
|
|
12368
12396
|
const serializedValues = formatParamValues(placeholderValues);
|
|
12369
12397
|
if (serializedValues !== null) {
|
|
12370
12398
|
result.set(placeholder, literal(formatParamValues(placeholderValues)));
|
|
@@ -12388,6 +12416,10 @@ function formatParamValues(values) {
|
|
|
12388
12416
|
* Formats a single `I18nParamValue` into a string
|
|
12389
12417
|
*/
|
|
12390
12418
|
function formatValue(value) {
|
|
12419
|
+
// If there are no special flags, just return the raw value.
|
|
12420
|
+
if (value.flags === I18nParamValueFlags.None) {
|
|
12421
|
+
return `${value.value}`;
|
|
12422
|
+
}
|
|
12391
12423
|
let tagMarker = '';
|
|
12392
12424
|
let closeMarker = '';
|
|
12393
12425
|
if (value.flags & I18nParamValueFlags.ElementTag) {
|
|
@@ -12746,6 +12778,9 @@ class IcuSerializerVisitor {
|
|
|
12746
12778
|
visitPlaceholder(ph) {
|
|
12747
12779
|
return this.formatPh(ph.name);
|
|
12748
12780
|
}
|
|
12781
|
+
visitBlockPlaceholder(ph) {
|
|
12782
|
+
return `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
|
|
12783
|
+
}
|
|
12749
12784
|
visitIcuPlaceholder(ph, context) {
|
|
12750
12785
|
return this.formatPh(ph.name);
|
|
12751
12786
|
}
|
|
@@ -14469,12 +14504,12 @@ class Comment {
|
|
|
14469
14504
|
return visitor.visitComment(this, context);
|
|
14470
14505
|
}
|
|
14471
14506
|
}
|
|
14472
|
-
class Block {
|
|
14473
|
-
constructor(name, parameters, children, sourceSpan, nameSpan, startSourceSpan, endSourceSpan = null) {
|
|
14507
|
+
class Block extends NodeWithI18n {
|
|
14508
|
+
constructor(name, parameters, children, sourceSpan, nameSpan, startSourceSpan, endSourceSpan = null, i18n) {
|
|
14509
|
+
super(sourceSpan, i18n);
|
|
14474
14510
|
this.name = name;
|
|
14475
14511
|
this.parameters = parameters;
|
|
14476
14512
|
this.children = children;
|
|
14477
|
-
this.sourceSpan = sourceSpan;
|
|
14478
14513
|
this.nameSpan = nameSpan;
|
|
14479
14514
|
this.startSourceSpan = startSourceSpan;
|
|
14480
14515
|
this.endSourceSpan = endSourceSpan;
|
|
@@ -15160,6 +15195,24 @@ class PlaceholderRegistry {
|
|
|
15160
15195
|
getUniquePlaceholder(name) {
|
|
15161
15196
|
return this._generateUniqueName(name.toUpperCase());
|
|
15162
15197
|
}
|
|
15198
|
+
getStartBlockPlaceholderName(name, parameters) {
|
|
15199
|
+
const signature = this._hashBlock(name, parameters);
|
|
15200
|
+
if (this._signatureToName[signature]) {
|
|
15201
|
+
return this._signatureToName[signature];
|
|
15202
|
+
}
|
|
15203
|
+
const placeholder = this._generateUniqueName(`START_BLOCK_${this._toSnakeCase(name)}`);
|
|
15204
|
+
this._signatureToName[signature] = placeholder;
|
|
15205
|
+
return placeholder;
|
|
15206
|
+
}
|
|
15207
|
+
getCloseBlockPlaceholderName(name) {
|
|
15208
|
+
const signature = this._hashClosingBlock(name);
|
|
15209
|
+
if (this._signatureToName[signature]) {
|
|
15210
|
+
return this._signatureToName[signature];
|
|
15211
|
+
}
|
|
15212
|
+
const placeholder = this._generateUniqueName(`CLOSE_BLOCK_${this._toSnakeCase(name)}`);
|
|
15213
|
+
this._signatureToName[signature] = placeholder;
|
|
15214
|
+
return placeholder;
|
|
15215
|
+
}
|
|
15163
15216
|
// Generate a hash for a tag - does not take attribute order into account
|
|
15164
15217
|
_hashTag(tag, attrs, isVoid) {
|
|
15165
15218
|
const start = `<${tag}`;
|
|
@@ -15170,6 +15223,16 @@ class PlaceholderRegistry {
|
|
|
15170
15223
|
_hashClosingTag(tag) {
|
|
15171
15224
|
return this._hashTag(`/${tag}`, {}, false);
|
|
15172
15225
|
}
|
|
15226
|
+
_hashBlock(name, parameters) {
|
|
15227
|
+
const params = parameters.length === 0 ? '' : ` (${parameters.sort().join('; ')})`;
|
|
15228
|
+
return `@${name}${params} {}`;
|
|
15229
|
+
}
|
|
15230
|
+
_hashClosingBlock(name) {
|
|
15231
|
+
return this._hashBlock(`close_${name}`, []);
|
|
15232
|
+
}
|
|
15233
|
+
_toSnakeCase(name) {
|
|
15234
|
+
return name.toUpperCase().replace(/[^A-Z0-9]/g, '_');
|
|
15235
|
+
}
|
|
15173
15236
|
_generateUniqueName(base) {
|
|
15174
15237
|
const seen = this._placeHolderNameCounts.hasOwnProperty(base);
|
|
15175
15238
|
if (!seen) {
|
|
@@ -15186,17 +15249,18 @@ const _expParser = new Parser$1(new Lexer());
|
|
|
15186
15249
|
/**
|
|
15187
15250
|
* Returns a function converting html nodes to an i18n Message given an interpolationConfig
|
|
15188
15251
|
*/
|
|
15189
|
-
function createI18nMessageFactory(interpolationConfig) {
|
|
15190
|
-
const visitor = new _I18nVisitor(_expParser, interpolationConfig);
|
|
15252
|
+
function createI18nMessageFactory(interpolationConfig, containerBlocks) {
|
|
15253
|
+
const visitor = new _I18nVisitor(_expParser, interpolationConfig, containerBlocks);
|
|
15191
15254
|
return (nodes, meaning, description, customId, visitNodeFn) => visitor.toI18nMessage(nodes, meaning, description, customId, visitNodeFn);
|
|
15192
15255
|
}
|
|
15193
15256
|
function noopVisitNodeFn(_html, i18n) {
|
|
15194
15257
|
return i18n;
|
|
15195
15258
|
}
|
|
15196
15259
|
class _I18nVisitor {
|
|
15197
|
-
constructor(_expressionParser, _interpolationConfig) {
|
|
15260
|
+
constructor(_expressionParser, _interpolationConfig, _containerBlocks) {
|
|
15198
15261
|
this._expressionParser = _expressionParser;
|
|
15199
15262
|
this._interpolationConfig = _interpolationConfig;
|
|
15263
|
+
this._containerBlocks = _containerBlocks;
|
|
15200
15264
|
}
|
|
15201
15265
|
toI18nMessage(nodes, meaning = '', description = '', customId = '', visitNodeFn) {
|
|
15202
15266
|
const context = {
|
|
@@ -15283,10 +15347,26 @@ class _I18nVisitor {
|
|
|
15283
15347
|
}
|
|
15284
15348
|
visitBlock(block, context) {
|
|
15285
15349
|
const children = visitAll(this, block.children, context);
|
|
15286
|
-
|
|
15350
|
+
if (this._containerBlocks.has(block.name)) {
|
|
15351
|
+
return new Container(children, block.sourceSpan);
|
|
15352
|
+
}
|
|
15353
|
+
const parameters = block.parameters.map(param => param.expression);
|
|
15354
|
+
const startPhName = context.placeholderRegistry.getStartBlockPlaceholderName(block.name, parameters);
|
|
15355
|
+
const closePhName = context.placeholderRegistry.getCloseBlockPlaceholderName(block.name);
|
|
15356
|
+
context.placeholderToContent[startPhName] = {
|
|
15357
|
+
text: block.startSourceSpan.toString(),
|
|
15358
|
+
sourceSpan: block.startSourceSpan,
|
|
15359
|
+
};
|
|
15360
|
+
context.placeholderToContent[closePhName] = {
|
|
15361
|
+
text: block.endSourceSpan ? block.endSourceSpan.toString() : '}',
|
|
15362
|
+
sourceSpan: block.endSourceSpan ?? block.sourceSpan,
|
|
15363
|
+
};
|
|
15364
|
+
const node = new BlockPlaceholder(block.name, parameters, startPhName, closePhName, children, block.sourceSpan, block.startSourceSpan, block.endSourceSpan);
|
|
15287
15365
|
return context.visitNodeFn(block, node);
|
|
15288
15366
|
}
|
|
15289
|
-
visitBlockParameter(_parameter, _context) {
|
|
15367
|
+
visitBlockParameter(_parameter, _context) {
|
|
15368
|
+
throw new Error('Unreachable code');
|
|
15369
|
+
}
|
|
15290
15370
|
/**
|
|
15291
15371
|
* Convert, text and interpolated tokens up into text and placeholder pieces.
|
|
15292
15372
|
*
|
|
@@ -19155,17 +19235,18 @@ const setI18nRefs = (htmlNode, i18nNode) => {
|
|
|
19155
19235
|
* stored with other element's and attribute's information.
|
|
19156
19236
|
*/
|
|
19157
19237
|
class I18nMetaVisitor {
|
|
19158
|
-
constructor(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false) {
|
|
19238
|
+
constructor(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false, containerBlocks = DEFAULT_CONTAINER_BLOCKS) {
|
|
19159
19239
|
this.interpolationConfig = interpolationConfig;
|
|
19160
19240
|
this.keepI18nAttrs = keepI18nAttrs;
|
|
19161
19241
|
this.enableI18nLegacyMessageIdFormat = enableI18nLegacyMessageIdFormat;
|
|
19242
|
+
this.containerBlocks = containerBlocks;
|
|
19162
19243
|
// whether visited nodes contain i18n information
|
|
19163
19244
|
this.hasI18nMeta = false;
|
|
19164
19245
|
this._errors = [];
|
|
19165
19246
|
}
|
|
19166
19247
|
_generateI18nMessage(nodes, meta = '', visitNodeFn) {
|
|
19167
19248
|
const { meaning, description, customId } = this._parseMetadata(meta);
|
|
19168
|
-
const createI18nMessage = createI18nMessageFactory(this.interpolationConfig);
|
|
19249
|
+
const createI18nMessage = createI18nMessageFactory(this.interpolationConfig, this.containerBlocks);
|
|
19169
19250
|
const message = createI18nMessage(nodes, meaning, description, customId, visitNodeFn);
|
|
19170
19251
|
this._setMessageId(message, meta);
|
|
19171
19252
|
this._setLegacyIds(message, meta);
|
|
@@ -19466,6 +19547,9 @@ class GetMsgSerializerVisitor {
|
|
|
19466
19547
|
visitPlaceholder(ph) {
|
|
19467
19548
|
return this.formatPh(ph.name);
|
|
19468
19549
|
}
|
|
19550
|
+
visitBlockPlaceholder(ph) {
|
|
19551
|
+
return `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
|
|
19552
|
+
}
|
|
19469
19553
|
visitIcuPlaceholder(ph, context) {
|
|
19470
19554
|
return this.formatPh(ph.name);
|
|
19471
19555
|
}
|
|
@@ -19519,6 +19603,11 @@ class LocalizeSerializerVisitor {
|
|
|
19519
19603
|
visitPlaceholder(ph) {
|
|
19520
19604
|
this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan));
|
|
19521
19605
|
}
|
|
19606
|
+
visitBlockPlaceholder(ph) {
|
|
19607
|
+
this.pieces.push(this.createPlaceholderPiece(ph.startName, ph.startSourceSpan ?? ph.sourceSpan));
|
|
19608
|
+
ph.children.forEach(child => child.visit(this));
|
|
19609
|
+
this.pieces.push(this.createPlaceholderPiece(ph.closeName, ph.endSourceSpan ?? ph.sourceSpan));
|
|
19610
|
+
}
|
|
19522
19611
|
visitIcuPlaceholder(ph) {
|
|
19523
19612
|
this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan, this.placeholderToMessage[ph.name]));
|
|
19524
19613
|
}
|
|
@@ -19638,6 +19727,8 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
|
19638
19727
|
statements.push(...subMessageStatements);
|
|
19639
19728
|
messageOp.params.set(subMessage.messagePlaceholder, subMessageVar);
|
|
19640
19729
|
}
|
|
19730
|
+
// Sort the params for consistency with TemaplateDefinitionBuilder output.
|
|
19731
|
+
messageOp.params = new Map([...messageOp.params.entries()].sort());
|
|
19641
19732
|
// Check that the message has all of its parameters filled out.
|
|
19642
19733
|
assertAllParamsResolved(messageOp);
|
|
19643
19734
|
const mainVar = variable(job.pool.uniqueName(TRANSLATION_VAR_PREFIX));
|
|
@@ -19649,6 +19740,8 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
|
19649
19740
|
// If nescessary, add a post-processing step and resolve any placeholder params that are
|
|
19650
19741
|
// set in post-processing.
|
|
19651
19742
|
if (messageOp.needsPostprocessing) {
|
|
19743
|
+
// Sort the post-processing params for consistency with TemaplateDefinitionBuilder output.
|
|
19744
|
+
messageOp.postprocessingParams = new Map([...messageOp.postprocessingParams.entries()].sort());
|
|
19652
19745
|
const extraTransformFnParams = [];
|
|
19653
19746
|
if (messageOp.postprocessingParams.size > 0) {
|
|
19654
19747
|
extraTransformFnParams.push(literalMap([...messageOp.postprocessingParams].map(([key, value]) => ({ key, value, quoted: true }))));
|
|
@@ -19730,12 +19823,14 @@ function i18nGenerateClosureVar(pool, messageId, fileBasedI18nSuffix, useExterna
|
|
|
19730
19823
|
* Asserts that all of the message's placeholders have values.
|
|
19731
19824
|
*/
|
|
19732
19825
|
function assertAllParamsResolved(op) {
|
|
19733
|
-
for (
|
|
19826
|
+
for (let placeholder in op.message.placeholders) {
|
|
19827
|
+
placeholder = placeholder.trimEnd();
|
|
19734
19828
|
if (!op.params.has(placeholder) && !op.postprocessingParams.has(placeholder)) {
|
|
19735
19829
|
throw Error(`Failed to resolve i18n placeholder: ${placeholder}`);
|
|
19736
19830
|
}
|
|
19737
19831
|
}
|
|
19738
|
-
for (
|
|
19832
|
+
for (let placeholder in op.message.placeholderToMessage) {
|
|
19833
|
+
placeholder = placeholder.trimEnd();
|
|
19739
19834
|
if (!op.params.has(placeholder) && !op.postprocessingParams.has(placeholder)) {
|
|
19740
19835
|
throw Error(`Failed to resolve i18n message placeholder: ${placeholder}`);
|
|
19741
19836
|
}
|
|
@@ -19750,7 +19845,9 @@ function extractI18nText(job) {
|
|
|
19750
19845
|
// Remove all text nodes within i18n blocks, their content is already captured in the i18n
|
|
19751
19846
|
// message.
|
|
19752
19847
|
let currentI18n = null;
|
|
19848
|
+
let currentIcu = null;
|
|
19753
19849
|
const textNodeI18nBlocks = new Map();
|
|
19850
|
+
const textNodeIcus = new Map();
|
|
19754
19851
|
for (const op of unit.create) {
|
|
19755
19852
|
switch (op.kind) {
|
|
19756
19853
|
case OpKind.I18nStart:
|
|
@@ -19762,9 +19859,19 @@ function extractI18nText(job) {
|
|
|
19762
19859
|
case OpKind.I18nEnd:
|
|
19763
19860
|
currentI18n = null;
|
|
19764
19861
|
break;
|
|
19862
|
+
case OpKind.IcuStart:
|
|
19863
|
+
if (op.context === null) {
|
|
19864
|
+
throw Error('Icu op should have its context set.');
|
|
19865
|
+
}
|
|
19866
|
+
currentIcu = op;
|
|
19867
|
+
break;
|
|
19868
|
+
case OpKind.IcuEnd:
|
|
19869
|
+
currentIcu = null;
|
|
19870
|
+
break;
|
|
19765
19871
|
case OpKind.Text:
|
|
19766
19872
|
if (currentI18n !== null) {
|
|
19767
19873
|
textNodeI18nBlocks.set(op.xref, currentI18n);
|
|
19874
|
+
textNodeIcus.set(op.xref, currentIcu);
|
|
19768
19875
|
OpList.remove(op);
|
|
19769
19876
|
}
|
|
19770
19877
|
break;
|
|
@@ -19779,13 +19886,16 @@ function extractI18nText(job) {
|
|
|
19779
19886
|
continue;
|
|
19780
19887
|
}
|
|
19781
19888
|
const i18nOp = textNodeI18nBlocks.get(op.target);
|
|
19889
|
+
const icuOp = textNodeIcus.get(op.target);
|
|
19890
|
+
const contextId = icuOp ? icuOp.context : i18nOp.context;
|
|
19891
|
+
const resolutionTime = icuOp ? I18nParamResolutionTime.Postproccessing :
|
|
19892
|
+
I18nParamResolutionTime.Creation;
|
|
19782
19893
|
const ops = [];
|
|
19783
19894
|
for (let i = 0; i < op.interpolation.expressions.length; i++) {
|
|
19784
19895
|
const expr = op.interpolation.expressions[i];
|
|
19785
|
-
const placeholder = op.i18nPlaceholders[i];
|
|
19786
19896
|
// For now, this i18nExpression depends on the slot context of the enclosing i18n block.
|
|
19787
19897
|
// Later, we will modify this, and advance to a different point.
|
|
19788
|
-
ops.push(createI18nExpressionOp(
|
|
19898
|
+
ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.handle, expr, op.i18nPlaceholders[i], resolutionTime, expr.sourceSpan ?? op.sourceSpan));
|
|
19789
19899
|
}
|
|
19790
19900
|
OpList.replaceWithMany(op, ops);
|
|
19791
19901
|
break;
|
|
@@ -20852,8 +20962,8 @@ function repeaterCreate(slot, viewFnName, decls, vars, tag, constIndex, trackByF
|
|
|
20852
20962
|
}
|
|
20853
20963
|
return call(Identifiers.repeaterCreate, args, sourceSpan);
|
|
20854
20964
|
}
|
|
20855
|
-
function repeater(
|
|
20856
|
-
return call(Identifiers.repeater, [
|
|
20965
|
+
function repeater(collection, sourceSpan) {
|
|
20966
|
+
return call(Identifiers.repeater, [collection], sourceSpan);
|
|
20857
20967
|
}
|
|
20858
20968
|
function deferWhen(prefetch, expr, sourceSpan) {
|
|
20859
20969
|
return call(prefetch ? Identifiers.deferPrefetchWhen : Identifiers.deferWhen, [expr], sourceSpan);
|
|
@@ -21461,7 +21571,7 @@ function reifyUpdateOperations(_unit, ops) {
|
|
|
21461
21571
|
OpList.replace(op, conditional(op.targetSlot.slot, op.processed, op.contextValue, op.sourceSpan));
|
|
21462
21572
|
break;
|
|
21463
21573
|
case OpKind.Repeater:
|
|
21464
|
-
OpList.replace(op, repeater(op.
|
|
21574
|
+
OpList.replace(op, repeater(op.collection, op.sourceSpan));
|
|
21465
21575
|
break;
|
|
21466
21576
|
case OpKind.DeferWhen:
|
|
21467
21577
|
OpList.replace(op, deferWhen(op.prefetch, op.expr, op.sourceSpan));
|
|
@@ -21800,7 +21910,7 @@ function getSubTemplateIndexForTemplateTag(job, i18nOp, op) {
|
|
|
21800
21910
|
return i18nOp.subTemplateIndex;
|
|
21801
21911
|
}
|
|
21802
21912
|
/** Add a param value to the given params map. */
|
|
21803
|
-
function addParam(params, placeholder, value, subTemplateIndex, flags
|
|
21913
|
+
function addParam(params, placeholder, value, subTemplateIndex, flags) {
|
|
21804
21914
|
const values = params.get(placeholder) ?? [];
|
|
21805
21915
|
values.push({ value, subTemplateIndex, flags });
|
|
21806
21916
|
params.set(placeholder, values);
|
|
@@ -21825,27 +21935,100 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
21825
21935
|
}
|
|
21826
21936
|
}
|
|
21827
21937
|
}
|
|
21828
|
-
// Keep track of the next available expression index per i18n
|
|
21938
|
+
// Keep track of the next available expression index per i18n block.
|
|
21829
21939
|
const expressionIndices = new Map();
|
|
21830
21940
|
for (const unit of job.units) {
|
|
21831
21941
|
for (const op of unit.update) {
|
|
21832
21942
|
if (op.kind === OpKind.I18nExpression) {
|
|
21833
|
-
const index = expressionIndices.get(op.context) || 0;
|
|
21834
21943
|
const i18nContext = i18nContexts.get(op.context);
|
|
21944
|
+
const index = expressionIndices.get(i18nContext.i18nBlock) || 0;
|
|
21835
21945
|
const subTemplateIndex = subTemplateIndicies.get(i18nContext.i18nBlock);
|
|
21836
21946
|
// Add the expression index in the appropriate params map.
|
|
21837
21947
|
const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
|
|
21838
21948
|
i18nContext.params :
|
|
21839
21949
|
i18nContext.postprocessingParams;
|
|
21840
21950
|
const values = params.get(op.i18nPlaceholder) || [];
|
|
21841
|
-
values.push({
|
|
21951
|
+
values.push({
|
|
21952
|
+
value: index,
|
|
21953
|
+
subTemplateIndex: subTemplateIndex,
|
|
21954
|
+
flags: I18nParamValueFlags.ExpressionIndex
|
|
21955
|
+
});
|
|
21842
21956
|
params.set(op.i18nPlaceholder, values);
|
|
21843
|
-
expressionIndices.set(
|
|
21957
|
+
expressionIndices.set(i18nContext.i18nBlock, index + 1);
|
|
21844
21958
|
}
|
|
21845
21959
|
}
|
|
21846
21960
|
}
|
|
21847
21961
|
}
|
|
21848
21962
|
|
|
21963
|
+
/**
|
|
21964
|
+
* Resolves placeholders for element tags inside of an ICU.
|
|
21965
|
+
*/
|
|
21966
|
+
function resolveI18nIcuPlaceholders(job) {
|
|
21967
|
+
const contextOps = new Map();
|
|
21968
|
+
for (const unit of job.units) {
|
|
21969
|
+
for (const op of unit.create) {
|
|
21970
|
+
switch (op.kind) {
|
|
21971
|
+
case OpKind.I18nContext:
|
|
21972
|
+
contextOps.set(op.xref, op);
|
|
21973
|
+
break;
|
|
21974
|
+
}
|
|
21975
|
+
}
|
|
21976
|
+
}
|
|
21977
|
+
for (const unit of job.units) {
|
|
21978
|
+
for (const op of unit.create) {
|
|
21979
|
+
switch (op.kind) {
|
|
21980
|
+
case OpKind.IcuStart:
|
|
21981
|
+
if (op.context === null) {
|
|
21982
|
+
throw Error('Icu should have its i18n context set.');
|
|
21983
|
+
}
|
|
21984
|
+
const i18nContext = contextOps.get(op.context);
|
|
21985
|
+
for (const node of op.message.nodes) {
|
|
21986
|
+
node.visit(new ResolveIcuPlaceholdersVisitor(i18nContext.postprocessingParams));
|
|
21987
|
+
}
|
|
21988
|
+
break;
|
|
21989
|
+
}
|
|
21990
|
+
}
|
|
21991
|
+
}
|
|
21992
|
+
}
|
|
21993
|
+
/**
|
|
21994
|
+
* Visitor for i18n AST that resolves ICU params into the given map.
|
|
21995
|
+
*/
|
|
21996
|
+
class ResolveIcuPlaceholdersVisitor extends RecurseVisitor {
|
|
21997
|
+
constructor(params) {
|
|
21998
|
+
super();
|
|
21999
|
+
this.params = params;
|
|
22000
|
+
}
|
|
22001
|
+
visitContainerPlaceholder(placeholder) {
|
|
22002
|
+
// Add the start and end source span for container placeholders. These need to be recorded for
|
|
22003
|
+
// elements inside ICUs. The slots for the nodes were recorded separately under the i18n
|
|
22004
|
+
// block's context as part of the `resolveI18nElementPlaceholders` phase.
|
|
22005
|
+
if (placeholder.startName && placeholder.startSourceSpan &&
|
|
22006
|
+
!this.params.has(placeholder.startName)) {
|
|
22007
|
+
this.params.set(placeholder.startName, [{
|
|
22008
|
+
value: placeholder.startSourceSpan?.toString(),
|
|
22009
|
+
subTemplateIndex: null,
|
|
22010
|
+
flags: I18nParamValueFlags.None
|
|
22011
|
+
}]);
|
|
22012
|
+
}
|
|
22013
|
+
if (placeholder.closeName && placeholder.endSourceSpan &&
|
|
22014
|
+
!this.params.has(placeholder.closeName)) {
|
|
22015
|
+
this.params.set(placeholder.closeName, [{
|
|
22016
|
+
value: placeholder.endSourceSpan?.toString(),
|
|
22017
|
+
subTemplateIndex: null,
|
|
22018
|
+
flags: I18nParamValueFlags.None
|
|
22019
|
+
}]);
|
|
22020
|
+
}
|
|
22021
|
+
}
|
|
22022
|
+
visitTagPlaceholder(placeholder) {
|
|
22023
|
+
super.visitTagPlaceholder(placeholder);
|
|
22024
|
+
this.visitContainerPlaceholder(placeholder);
|
|
22025
|
+
}
|
|
22026
|
+
visitBlockPlaceholder(placeholder) {
|
|
22027
|
+
super.visitBlockPlaceholder(placeholder);
|
|
22028
|
+
this.visitContainerPlaceholder(placeholder);
|
|
22029
|
+
}
|
|
22030
|
+
}
|
|
22031
|
+
|
|
21849
22032
|
/**
|
|
21850
22033
|
* Resolves lexical references in views (`ir.LexicalReadExpr`) to either a target variable or to
|
|
21851
22034
|
* property reads on the top-level component context.
|
|
@@ -22896,6 +23079,7 @@ function allowConservativeInlining(decl, target) {
|
|
|
22896
23079
|
function wrapI18nIcus(job) {
|
|
22897
23080
|
for (const unit of job.units) {
|
|
22898
23081
|
let currentI18nOp = null;
|
|
23082
|
+
let addedI18nId = null;
|
|
22899
23083
|
for (const op of unit.create) {
|
|
22900
23084
|
switch (op.kind) {
|
|
22901
23085
|
case OpKind.I18nStart:
|
|
@@ -22904,11 +23088,16 @@ function wrapI18nIcus(job) {
|
|
|
22904
23088
|
case OpKind.I18nEnd:
|
|
22905
23089
|
currentI18nOp = null;
|
|
22906
23090
|
break;
|
|
22907
|
-
case OpKind.
|
|
23091
|
+
case OpKind.IcuStart:
|
|
22908
23092
|
if (currentI18nOp === null) {
|
|
22909
|
-
|
|
22910
|
-
OpList.insertBefore(createI18nStartOp(
|
|
22911
|
-
|
|
23093
|
+
addedI18nId = job.allocateXrefId();
|
|
23094
|
+
OpList.insertBefore(createI18nStartOp(addedI18nId, op.message), op);
|
|
23095
|
+
}
|
|
23096
|
+
break;
|
|
23097
|
+
case OpKind.IcuEnd:
|
|
23098
|
+
if (addedI18nId !== null) {
|
|
23099
|
+
OpList.insertAfter(createI18nEndOp(addedI18nId), op);
|
|
23100
|
+
addedI18nId = null;
|
|
22912
23101
|
}
|
|
22913
23102
|
break;
|
|
22914
23103
|
}
|
|
@@ -22942,7 +23131,6 @@ const phases = [
|
|
|
22942
23131
|
{ kind: CompilationJobKind.Tmpl, fn: createPipes },
|
|
22943
23132
|
{ kind: CompilationJobKind.Tmpl, fn: configureDeferInstructions },
|
|
22944
23133
|
{ kind: CompilationJobKind.Tmpl, fn: extractI18nText },
|
|
22945
|
-
{ kind: CompilationJobKind.Tmpl, fn: createI18nIcuExpressions },
|
|
22946
23134
|
{ kind: CompilationJobKind.Tmpl, fn: applyI18nExpressions },
|
|
22947
23135
|
{ kind: CompilationJobKind.Tmpl, fn: createVariadicPipes },
|
|
22948
23136
|
{ kind: CompilationJobKind.Both, fn: generatePureLiteralStructures },
|
|
@@ -22966,6 +23154,7 @@ const phases = [
|
|
|
22966
23154
|
{ kind: CompilationJobKind.Tmpl, fn: createDeferDepsFns },
|
|
22967
23155
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
|
|
22968
23156
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
|
|
23157
|
+
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nIcuPlaceholders },
|
|
22969
23158
|
{ kind: CompilationJobKind.Tmpl, fn: mergeI18nContexts },
|
|
22970
23159
|
{ kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
|
|
22971
23160
|
{ kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
|
|
@@ -23279,7 +23468,7 @@ function ingestText(unit, text) {
|
|
|
23279
23468
|
/**
|
|
23280
23469
|
* Ingest an interpolated text node from the AST into the given `ViewCompilation`.
|
|
23281
23470
|
*/
|
|
23282
|
-
function ingestBoundText(unit, text) {
|
|
23471
|
+
function ingestBoundText(unit, text, i18nPlaceholders) {
|
|
23283
23472
|
let value = text.value;
|
|
23284
23473
|
if (value instanceof ASTWithSource) {
|
|
23285
23474
|
value = value.ast;
|
|
@@ -23290,9 +23479,16 @@ function ingestBoundText(unit, text) {
|
|
|
23290
23479
|
if (text.i18n !== undefined && !(text.i18n instanceof Container)) {
|
|
23291
23480
|
throw Error(`Unhandled i18n metadata type for text interpolation: ${text.i18n?.constructor.name}`);
|
|
23292
23481
|
}
|
|
23293
|
-
|
|
23294
|
-
text.i18n
|
|
23295
|
-
|
|
23482
|
+
if (i18nPlaceholders === undefined) {
|
|
23483
|
+
i18nPlaceholders = text.i18n instanceof Container ?
|
|
23484
|
+
text.i18n.children
|
|
23485
|
+
.filter((node) => node instanceof Placeholder)
|
|
23486
|
+
.map(placeholder => placeholder.name) :
|
|
23487
|
+
[];
|
|
23488
|
+
}
|
|
23489
|
+
if (i18nPlaceholders.length > 0 && i18nPlaceholders.length !== value.expressions.length) {
|
|
23490
|
+
throw Error(`Unexpected number of i18n placeholders (${value.expressions.length}) for BoundText with ${value.expressions.length} expressions`);
|
|
23491
|
+
}
|
|
23296
23492
|
const textXref = unit.job.allocateXrefId();
|
|
23297
23493
|
unit.create.push(createTextOp(textXref, '', text.sourceSpan));
|
|
23298
23494
|
// TemplateDefinitionBuilder does not generate source maps for sub-expressions inside an
|
|
@@ -23458,8 +23654,22 @@ function ingestDeferBlock(unit, deferBlock) {
|
|
|
23458
23654
|
function ingestIcu(unit, icu) {
|
|
23459
23655
|
if (icu.i18n instanceof Message && isSingleI18nIcu(icu.i18n)) {
|
|
23460
23656
|
const xref = unit.job.allocateXrefId();
|
|
23461
|
-
|
|
23462
|
-
unit.
|
|
23657
|
+
const icuNode = icu.i18n.nodes[0];
|
|
23658
|
+
unit.create.push(createIcuStartOp(xref, icu.i18n, icuFromI18nMessage(icu.i18n).name, null));
|
|
23659
|
+
const expressionPlaceholder = icuNode.expressionPlaceholder?.trimEnd();
|
|
23660
|
+
if (expressionPlaceholder === undefined || icu.vars[expressionPlaceholder] === undefined) {
|
|
23661
|
+
throw Error('ICU should have a text binding');
|
|
23662
|
+
}
|
|
23663
|
+
ingestBoundText(unit, icu.vars[expressionPlaceholder], [expressionPlaceholder]);
|
|
23664
|
+
for (const [placeholder, text] of Object.entries(icu.placeholders)) {
|
|
23665
|
+
if (text instanceof BoundText) {
|
|
23666
|
+
ingestBoundText(unit, text, [placeholder]);
|
|
23667
|
+
}
|
|
23668
|
+
else {
|
|
23669
|
+
ingestText(unit, text);
|
|
23670
|
+
}
|
|
23671
|
+
}
|
|
23672
|
+
unit.create.push(createIcuEndOp(xref));
|
|
23463
23673
|
}
|
|
23464
23674
|
else {
|
|
23465
23675
|
throw Error(`Unhandled i18n metadata type for ICU: ${icu.i18n?.constructor.name}`);
|
|
@@ -25011,19 +25221,19 @@ function createIfBlock(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25011
25221
|
const branches = [];
|
|
25012
25222
|
const mainBlockParams = parseConditionalBlockParameters(ast, errors, bindingParser);
|
|
25013
25223
|
if (mainBlockParams !== null) {
|
|
25014
|
-
branches.push(new IfBlockBranch(mainBlockParams.expression, visitAll(visitor, ast.children, ast.children), mainBlockParams.expressionAlias, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.nameSpan));
|
|
25224
|
+
branches.push(new IfBlockBranch(mainBlockParams.expression, visitAll(visitor, ast.children, ast.children), mainBlockParams.expressionAlias, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.nameSpan, ast.i18n));
|
|
25015
25225
|
}
|
|
25016
25226
|
for (const block of connectedBlocks) {
|
|
25017
25227
|
if (ELSE_IF_PATTERN.test(block.name)) {
|
|
25018
25228
|
const params = parseConditionalBlockParameters(block, errors, bindingParser);
|
|
25019
25229
|
if (params !== null) {
|
|
25020
25230
|
const children = visitAll(visitor, block.children, block.children);
|
|
25021
|
-
branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan));
|
|
25231
|
+
branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n));
|
|
25022
25232
|
}
|
|
25023
25233
|
}
|
|
25024
25234
|
else if (block.name === 'else') {
|
|
25025
25235
|
const children = visitAll(visitor, block.children, block.children);
|
|
25026
|
-
branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan));
|
|
25236
|
+
branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n));
|
|
25027
25237
|
}
|
|
25028
25238
|
}
|
|
25029
25239
|
// The outer IfBlock should have a span that encapsulates all branches.
|
|
@@ -25054,7 +25264,7 @@ function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25054
25264
|
errors.push(new ParseError(block.sourceSpan, '@empty block cannot have parameters'));
|
|
25055
25265
|
}
|
|
25056
25266
|
else {
|
|
25057
|
-
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children, block.children), block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan);
|
|
25267
|
+
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children, block.children), block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n);
|
|
25058
25268
|
}
|
|
25059
25269
|
}
|
|
25060
25270
|
else {
|
|
@@ -25072,7 +25282,7 @@ function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25072
25282
|
// main `for` body, use `mainSourceSpan`.
|
|
25073
25283
|
const endSpan = empty?.endSourceSpan ?? ast.endSourceSpan;
|
|
25074
25284
|
const sourceSpan = new ParseSourceSpan(ast.sourceSpan.start, endSpan?.end ?? ast.sourceSpan.end);
|
|
25075
|
-
node = new ForLoopBlock(params.itemName, params.expression, params.trackBy.expression, params.trackBy.keywordSpan, params.context, visitAll(visitor, ast.children, ast.children), empty, sourceSpan, ast.sourceSpan, ast.startSourceSpan, endSpan, ast.nameSpan);
|
|
25285
|
+
node = new ForLoopBlock(params.itemName, params.expression, params.trackBy.expression, params.trackBy.keywordSpan, params.context, visitAll(visitor, ast.children, ast.children), empty, sourceSpan, ast.sourceSpan, ast.startSourceSpan, endSpan, ast.nameSpan, ast.i18n);
|
|
25076
25286
|
}
|
|
25077
25287
|
}
|
|
25078
25288
|
return { node, errors };
|
|
@@ -25098,7 +25308,7 @@ function createSwitchBlock(ast, visitor, bindingParser) {
|
|
|
25098
25308
|
const expression = node.name === 'case' ?
|
|
25099
25309
|
parseBlockParameterToBinding(node.parameters[0], bindingParser) :
|
|
25100
25310
|
null;
|
|
25101
|
-
const ast = new SwitchBlockCase(expression, visitAll(visitor, node.children, node.children), node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.nameSpan);
|
|
25311
|
+
const ast = new SwitchBlockCase(expression, visitAll(visitor, node.children, node.children), node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.nameSpan, node.i18n);
|
|
25102
25312
|
if (expression === null) {
|
|
25103
25313
|
defaultCase = ast;
|
|
25104
25314
|
}
|
|
@@ -25685,7 +25895,7 @@ function createDeferredBlock(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25685
25895
|
endOfLastSourceSpan = lastConnectedBlock.sourceSpan.end;
|
|
25686
25896
|
}
|
|
25687
25897
|
const sourceSpanWithConnectedBlocks = new ParseSourceSpan(ast.sourceSpan.start, endOfLastSourceSpan);
|
|
25688
|
-
const node = new DeferredBlock(visitAll(visitor, ast.children, ast.children), triggers, prefetchTriggers, placeholder, loading, error, ast.nameSpan, sourceSpanWithConnectedBlocks, ast.sourceSpan, ast.startSourceSpan, lastEndSourceSpan);
|
|
25898
|
+
const node = new DeferredBlock(visitAll(visitor, ast.children, ast.children), triggers, prefetchTriggers, placeholder, loading, error, ast.nameSpan, sourceSpanWithConnectedBlocks, ast.sourceSpan, ast.startSourceSpan, lastEndSourceSpan, ast.i18n);
|
|
25689
25899
|
return { node, errors };
|
|
25690
25900
|
}
|
|
25691
25901
|
function parseConnectedBlocks(connectedBlocks, errors, visitor) {
|
|
@@ -25748,7 +25958,7 @@ function parsePlaceholderBlock(ast, visitor) {
|
|
|
25748
25958
|
throw new Error(`Unrecognized parameter in @placeholder block: "${param.expression}"`);
|
|
25749
25959
|
}
|
|
25750
25960
|
}
|
|
25751
|
-
return new DeferredBlockPlaceholder(visitAll(visitor, ast.children, ast.children), minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
25961
|
+
return new DeferredBlockPlaceholder(visitAll(visitor, ast.children, ast.children), minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
|
|
25752
25962
|
}
|
|
25753
25963
|
function parseLoadingBlock(ast, visitor) {
|
|
25754
25964
|
let afterTime = null;
|
|
@@ -25778,13 +25988,13 @@ function parseLoadingBlock(ast, visitor) {
|
|
|
25778
25988
|
throw new Error(`Unrecognized parameter in @loading block: "${param.expression}"`);
|
|
25779
25989
|
}
|
|
25780
25990
|
}
|
|
25781
|
-
return new DeferredBlockLoading(visitAll(visitor, ast.children, ast.children), afterTime, minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
25991
|
+
return new DeferredBlockLoading(visitAll(visitor, ast.children, ast.children), afterTime, minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
|
|
25782
25992
|
}
|
|
25783
25993
|
function parseErrorBlock(ast, visitor) {
|
|
25784
25994
|
if (ast.parameters.length > 0) {
|
|
25785
25995
|
throw new Error(`@error block cannot have parameters`);
|
|
25786
25996
|
}
|
|
25787
|
-
return new DeferredBlockError(visitAll(visitor, ast.children, ast.children), ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
25997
|
+
return new DeferredBlockError(visitAll(visitor, ast.children, ast.children), ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
|
|
25788
25998
|
}
|
|
25789
25999
|
function parsePrimaryTriggers(params, bindingParser, errors, placeholder) {
|
|
25790
26000
|
const triggers = {};
|
|
@@ -26384,6 +26594,11 @@ class I18nContext {
|
|
|
26384
26594
|
const content = { type, index, ctx: this.id, isVoid: node.isVoid, closed };
|
|
26385
26595
|
updatePlaceholderMap(this.placeholders, ph, content);
|
|
26386
26596
|
}
|
|
26597
|
+
appendBlockPart(node, index, closed) {
|
|
26598
|
+
const ph = closed ? node.closeName : node.startName;
|
|
26599
|
+
const content = { type: TagType.TEMPLATE, index, ctx: this.id, closed };
|
|
26600
|
+
updatePlaceholderMap(this.placeholders, ph, content);
|
|
26601
|
+
}
|
|
26387
26602
|
get icus() {
|
|
26388
26603
|
return this._registry.icus;
|
|
26389
26604
|
}
|
|
@@ -26416,6 +26631,13 @@ class I18nContext {
|
|
|
26416
26631
|
this.appendTag(TagType.TEMPLATE, node, index, true);
|
|
26417
26632
|
this._unresolvedCtxCount++;
|
|
26418
26633
|
}
|
|
26634
|
+
appendBlock(node, index) {
|
|
26635
|
+
// add open and close tags at the same time,
|
|
26636
|
+
// since we process nested templates separately
|
|
26637
|
+
this.appendBlockPart(node, index, false);
|
|
26638
|
+
this.appendBlockPart(node, index, true);
|
|
26639
|
+
this._unresolvedCtxCount++;
|
|
26640
|
+
}
|
|
26419
26641
|
appendElement(node, index, closed) {
|
|
26420
26642
|
this.appendTag(TagType.ELEMENT, node, index, closed);
|
|
26421
26643
|
}
|
|
@@ -26694,13 +26916,19 @@ class TemplateDefinitionBuilder {
|
|
|
26694
26916
|
this.creationInstruction(null, Identifiers.pipe, [literal(slot), literal(name)]);
|
|
26695
26917
|
});
|
|
26696
26918
|
}
|
|
26697
|
-
buildTemplateFunction(nodes, variables, ngContentSelectorsOffset = 0, i18n) {
|
|
26919
|
+
buildTemplateFunction(nodes, variables, ngContentSelectorsOffset = 0, i18n, variableAliases) {
|
|
26698
26920
|
this._ngContentSelectorsOffset = ngContentSelectorsOffset;
|
|
26699
26921
|
if (this._namespace !== Identifiers.namespaceHTML) {
|
|
26700
26922
|
this.creationInstruction(null, this._namespace);
|
|
26701
26923
|
}
|
|
26702
26924
|
// Create variable bindings
|
|
26703
|
-
variables.forEach(v =>
|
|
26925
|
+
variables.forEach(v => {
|
|
26926
|
+
const alias = variableAliases?.[v.name];
|
|
26927
|
+
this.registerContextVariables(v.name, v.value);
|
|
26928
|
+
if (alias) {
|
|
26929
|
+
this.registerContextVariables(alias, v.value);
|
|
26930
|
+
}
|
|
26931
|
+
});
|
|
26704
26932
|
// Initiate i18n context in case:
|
|
26705
26933
|
// - this template has parent i18n context
|
|
26706
26934
|
// - or the template has i18n meta associated with it,
|
|
@@ -26794,12 +27022,12 @@ class TemplateDefinitionBuilder {
|
|
|
26794
27022
|
this._constants.prepareStatements.push(...statements);
|
|
26795
27023
|
return _ref;
|
|
26796
27024
|
}
|
|
26797
|
-
registerContextVariables(
|
|
27025
|
+
registerContextVariables(name, value) {
|
|
26798
27026
|
const scopedName = this._bindingScope.freshReferenceName();
|
|
26799
27027
|
const retrievalLevel = this.level;
|
|
26800
|
-
const isDirect =
|
|
26801
|
-
const lhs = variable(
|
|
26802
|
-
this._bindingScope.set(retrievalLevel,
|
|
27028
|
+
const isDirect = value === DIRECT_CONTEXT_REFERENCE;
|
|
27029
|
+
const lhs = variable(name + scopedName);
|
|
27030
|
+
this._bindingScope.set(retrievalLevel, name, scope => {
|
|
26803
27031
|
// If we're at the top level and we're referring to the context variable directly, we
|
|
26804
27032
|
// can do so through the implicit receiver, instead of renaming it. Note that this does
|
|
26805
27033
|
// not apply to listeners, because they need to restore the context.
|
|
@@ -26835,7 +27063,7 @@ class TemplateDefinitionBuilder {
|
|
|
26835
27063
|
return [
|
|
26836
27064
|
// e.g. const $items$ = x(2) for direct context references and
|
|
26837
27065
|
// const $item$ = x(2).$implicit for indirect ones.
|
|
26838
|
-
lhs.set(isDirect ? rhs : rhs.prop(
|
|
27066
|
+
lhs.set(isDirect ? rhs : rhs.prop(value || IMPLICIT_REFERENCE)).toConstDecl()
|
|
26839
27067
|
];
|
|
26840
27068
|
});
|
|
26841
27069
|
}
|
|
@@ -27258,10 +27486,15 @@ class TemplateDefinitionBuilder {
|
|
|
27258
27486
|
this.creationInstruction(span, isNgContainer$1 ? Identifiers.elementContainerEnd : Identifiers.elementEnd);
|
|
27259
27487
|
}
|
|
27260
27488
|
}
|
|
27261
|
-
prepareEmbeddedTemplateFn(children, contextNameSuffix, variables = [],
|
|
27489
|
+
prepareEmbeddedTemplateFn(children, contextNameSuffix, variables = [], i18nMeta, variableAliases) {
|
|
27262
27490
|
const index = this.allocateDataSlot();
|
|
27263
|
-
if (this.i18n &&
|
|
27264
|
-
|
|
27491
|
+
if (this.i18n && i18nMeta) {
|
|
27492
|
+
if (i18nMeta instanceof BlockPlaceholder) {
|
|
27493
|
+
this.i18n.appendBlock(i18nMeta, index);
|
|
27494
|
+
}
|
|
27495
|
+
else {
|
|
27496
|
+
this.i18n.appendTemplate(i18nMeta, index);
|
|
27497
|
+
}
|
|
27265
27498
|
}
|
|
27266
27499
|
const contextName = `${this.contextName}${contextNameSuffix}_${index}`;
|
|
27267
27500
|
const name = `${contextName}_Template`;
|
|
@@ -27272,7 +27505,7 @@ class TemplateDefinitionBuilder {
|
|
|
27272
27505
|
// be able to support bindings in nested templates to local refs that occur after the
|
|
27273
27506
|
// template definition. e.g. <div *ngIf="showing">{{ foo }}</div> <div #foo></div>
|
|
27274
27507
|
this._nestedTemplateFns.push(() => {
|
|
27275
|
-
const templateFunctionExpr = visitor.buildTemplateFunction(children, variables, this._ngContentReservedSlots.length + this._ngContentSelectorsOffset,
|
|
27508
|
+
const templateFunctionExpr = visitor.buildTemplateFunction(children, variables, this._ngContentReservedSlots.length + this._ngContentSelectorsOffset, i18nMeta, variableAliases);
|
|
27276
27509
|
this.constantPool.statements.push(templateFunctionExpr.toDeclStmt(name));
|
|
27277
27510
|
if (visitor._ngContentReservedSlots.length) {
|
|
27278
27511
|
this._ngContentReservedSlots.push(...visitor._ngContentReservedSlots);
|
|
@@ -27380,7 +27613,9 @@ class TemplateDefinitionBuilder {
|
|
|
27380
27613
|
// inside ICUs)
|
|
27381
27614
|
// - all ICU vars (such as `VAR_SELECT` or `VAR_PLURAL`) are replaced with correct values
|
|
27382
27615
|
const transformFn = (raw) => {
|
|
27383
|
-
|
|
27616
|
+
// Sort the map entries in the compiled output. This makes it easy to acheive identical output
|
|
27617
|
+
// in the template pipeline compiler.
|
|
27618
|
+
const params = Object.fromEntries(Object.entries({ ...vars, ...placeholders }).sort());
|
|
27384
27619
|
const formatted = formatI18nPlaceholderNamesInMap(params, /* useCamelCase */ false);
|
|
27385
27620
|
return invokeInstruction(null, Identifiers.i18nPostprocess, [raw, mapLiteral(formatted, true)]);
|
|
27386
27621
|
};
|
|
@@ -27427,7 +27662,7 @@ class TemplateDefinitionBuilder {
|
|
|
27427
27662
|
}
|
|
27428
27663
|
// Note: the template needs to be created *before* we process the expression,
|
|
27429
27664
|
// otherwise pipes injecting some symbols won't work (see #52102).
|
|
27430
|
-
const templateIndex = this.createEmbeddedTemplateFn(tagName, children, '_Conditional', sourceSpan, variables, attrsExprs);
|
|
27665
|
+
const templateIndex = this.createEmbeddedTemplateFn(tagName, children, '_Conditional', sourceSpan, variables, attrsExprs, undefined, branch.i18n);
|
|
27431
27666
|
const processedExpression = expression === null ? null : expression.visit(this._valueConverter);
|
|
27432
27667
|
return { index: templateIndex, expression: processedExpression, alias: expressionAlias };
|
|
27433
27668
|
});
|
|
@@ -27478,7 +27713,7 @@ class TemplateDefinitionBuilder {
|
|
|
27478
27713
|
// We have to process the block in two steps: once here and again in the update instruction
|
|
27479
27714
|
// callback in order to generate the correct expressions when pipes or pure functions are used.
|
|
27480
27715
|
const caseData = block.cases.map(currentCase => {
|
|
27481
|
-
const index = this.createEmbeddedTemplateFn(null, currentCase.children, '_Case', currentCase.sourceSpan);
|
|
27716
|
+
const index = this.createEmbeddedTemplateFn(null, currentCase.children, '_Case', currentCase.sourceSpan, undefined, undefined, undefined, currentCase.i18n);
|
|
27482
27717
|
const expression = currentCase.expression === null ?
|
|
27483
27718
|
null :
|
|
27484
27719
|
currentCase.expression.visit(this._valueConverter);
|
|
@@ -27526,23 +27761,21 @@ class TemplateDefinitionBuilder {
|
|
|
27526
27761
|
if (!metadata) {
|
|
27527
27762
|
throw new Error('Could not resolve `defer` block metadata. Block may need to be analyzed.');
|
|
27528
27763
|
}
|
|
27529
|
-
const primaryTemplateIndex = this.createEmbeddedTemplateFn(null, deferred.children, '_Defer', deferred.sourceSpan);
|
|
27530
|
-
const loadingIndex = loading ?
|
|
27531
|
-
this.createEmbeddedTemplateFn(null, loading.children, '_DeferLoading', loading.sourceSpan) :
|
|
27764
|
+
const primaryTemplateIndex = this.createEmbeddedTemplateFn(null, deferred.children, '_Defer', deferred.sourceSpan, undefined, undefined, undefined, deferred.i18n);
|
|
27765
|
+
const loadingIndex = loading ? this.createEmbeddedTemplateFn(null, loading.children, '_DeferLoading', loading.sourceSpan, undefined, undefined, undefined, loading.i18n) :
|
|
27532
27766
|
null;
|
|
27533
27767
|
const loadingConsts = loading ?
|
|
27534
27768
|
trimTrailingNulls([literal(loading.minimumTime), literal(loading.afterTime)]) :
|
|
27535
27769
|
null;
|
|
27536
27770
|
const placeholderIndex = placeholder ?
|
|
27537
|
-
this.createEmbeddedTemplateFn(null, placeholder.children, '_DeferPlaceholder', placeholder.sourceSpan) :
|
|
27771
|
+
this.createEmbeddedTemplateFn(null, placeholder.children, '_DeferPlaceholder', placeholder.sourceSpan, undefined, undefined, undefined, placeholder.i18n) :
|
|
27538
27772
|
null;
|
|
27539
27773
|
const placeholderConsts = placeholder && placeholder.minimumTime !== null ?
|
|
27540
27774
|
// TODO(crisbeto): potentially pass the time directly instead of storing it in the `consts`
|
|
27541
27775
|
// since the placeholder block can only have one parameter?
|
|
27542
27776
|
literalArr([literal(placeholder.minimumTime)]) :
|
|
27543
27777
|
null;
|
|
27544
|
-
const errorIndex = error ?
|
|
27545
|
-
this.createEmbeddedTemplateFn(null, error.children, '_DeferError', error.sourceSpan) :
|
|
27778
|
+
const errorIndex = error ? this.createEmbeddedTemplateFn(null, error.children, '_DeferError', error.sourceSpan, undefined, undefined, undefined, error.i18n) :
|
|
27546
27779
|
null;
|
|
27547
27780
|
// Note: we generate this last so the index matches the instruction order.
|
|
27548
27781
|
const deferredIndex = this.allocateDataSlot();
|
|
@@ -27696,11 +27929,18 @@ class TemplateDefinitionBuilder {
|
|
|
27696
27929
|
// are implicitly inferred by the runtime to index + 1 and index + 2.
|
|
27697
27930
|
const blockIndex = this.allocateDataSlot();
|
|
27698
27931
|
const { tagName, attrsExprs } = this.inferProjectionDataFromInsertionPoint(block);
|
|
27699
|
-
const primaryData = this.prepareEmbeddedTemplateFn(block.children, '_For', [block.item, block.contextVariables.$index, block.contextVariables.$count]
|
|
27932
|
+
const primaryData = this.prepareEmbeddedTemplateFn(block.children, '_For', [block.item, block.contextVariables.$index, block.contextVariables.$count], block.i18n, {
|
|
27933
|
+
// We need to provide level-specific versions of `$index` and `$count`, because
|
|
27934
|
+
// they're used when deriving the remaining variables (`$odd`, `$even` etc.) while at the
|
|
27935
|
+
// same time being available implicitly. Without these aliases, we wouldn't be able to
|
|
27936
|
+
// access the `$index` of a parent loop from inside of a nested loop.
|
|
27937
|
+
[block.contextVariables.$index.name]: this.getLevelSpecificVariableName('$index', this.level + 1),
|
|
27938
|
+
[block.contextVariables.$count.name]: this.getLevelSpecificVariableName('$count', this.level + 1),
|
|
27939
|
+
});
|
|
27700
27940
|
const { expression: trackByExpression, usesComponentInstance: trackByUsesComponentInstance } = this.createTrackByFunction(block);
|
|
27701
27941
|
let emptyData = null;
|
|
27702
27942
|
if (block.empty !== null) {
|
|
27703
|
-
emptyData = this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty');
|
|
27943
|
+
emptyData = this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty', undefined, block.empty.i18n);
|
|
27704
27944
|
// Allocate an extra slot for the empty block tracking.
|
|
27705
27945
|
this.allocateBindingSlots(null);
|
|
27706
27946
|
}
|
|
@@ -27730,17 +27970,44 @@ class TemplateDefinitionBuilder {
|
|
|
27730
27970
|
// Note: we don't allocate binding slots for this expression,
|
|
27731
27971
|
// because its value isn't stored in the LView.
|
|
27732
27972
|
const value = block.expression.visit(this._valueConverter);
|
|
27733
|
-
// `repeater(
|
|
27734
|
-
this.
|
|
27973
|
+
// `advance(x); repeater(iterable)`
|
|
27974
|
+
this.updateInstructionWithAdvance(blockIndex, block.sourceSpan, Identifiers.repeater, () => [this.convertPropertyBinding(value)]);
|
|
27735
27975
|
}
|
|
27736
27976
|
registerComputedLoopVariables(block, bindingScope) {
|
|
27737
|
-
const indexLocalName = block.contextVariables.$index.name;
|
|
27738
|
-
const countLocalName = block.contextVariables.$count.name;
|
|
27739
27977
|
const level = bindingScope.bindingLevel;
|
|
27740
|
-
bindingScope.set(level, block.contextVariables.$odd.name, scope =>
|
|
27741
|
-
|
|
27742
|
-
|
|
27743
|
-
|
|
27978
|
+
bindingScope.set(level, block.contextVariables.$odd.name, (scope, retrievalLevel) => {
|
|
27979
|
+
return this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index')
|
|
27980
|
+
.modulo(literal(2))
|
|
27981
|
+
.notIdentical(literal(0));
|
|
27982
|
+
});
|
|
27983
|
+
bindingScope.set(level, block.contextVariables.$even.name, (scope, retrievalLevel) => {
|
|
27984
|
+
return this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index')
|
|
27985
|
+
.modulo(literal(2))
|
|
27986
|
+
.identical(literal(0));
|
|
27987
|
+
});
|
|
27988
|
+
bindingScope.set(level, block.contextVariables.$first.name, (scope, retrievalLevel) => {
|
|
27989
|
+
return this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index')
|
|
27990
|
+
.identical(literal(0));
|
|
27991
|
+
});
|
|
27992
|
+
bindingScope.set(level, block.contextVariables.$last.name, (scope, retrievalLevel) => {
|
|
27993
|
+
const index = this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index');
|
|
27994
|
+
const count = this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$count');
|
|
27995
|
+
return index.identical(count.minus(literal(1)));
|
|
27996
|
+
});
|
|
27997
|
+
}
|
|
27998
|
+
getLevelSpecificVariableName(name, level) {
|
|
27999
|
+
// We use the `ɵ` here to ensure that there are no name conflicts with user-defined variables.
|
|
28000
|
+
return `ɵ${name}_${level}`;
|
|
28001
|
+
}
|
|
28002
|
+
/**
|
|
28003
|
+
* Gets the name of a for loop variable at a specific binding level. This allows us to look
|
|
28004
|
+
* up implicitly shadowed variables like `$index` and `$count` at a specific level.
|
|
28005
|
+
*/
|
|
28006
|
+
getLevelSpecificForLoopVariable(block, scope, retrievalLevel, name) {
|
|
28007
|
+
const scopeName = scope.bindingLevel === retrievalLevel ?
|
|
28008
|
+
block.contextVariables[name].name :
|
|
28009
|
+
this.getLevelSpecificVariableName(name, retrievalLevel);
|
|
28010
|
+
return scope.get(scopeName);
|
|
27744
28011
|
}
|
|
27745
28012
|
optimizeTrackByFunction(block) {
|
|
27746
28013
|
const indexLocalName = block.contextVariables.$index.name;
|
|
@@ -28278,7 +28545,7 @@ class BindingScope {
|
|
|
28278
28545
|
if (value.declareLocalCallback && !value.declare) {
|
|
28279
28546
|
value.declare = true;
|
|
28280
28547
|
}
|
|
28281
|
-
return typeof value.lhs === 'function' ? value.lhs(this) : value.lhs;
|
|
28548
|
+
return typeof value.lhs === 'function' ? value.lhs(this, value.retrievalLevel) : value.lhs;
|
|
28282
28549
|
}
|
|
28283
28550
|
current = current.parent;
|
|
28284
28551
|
}
|
|
@@ -28386,7 +28653,9 @@ class BindingScope {
|
|
|
28386
28653
|
const componentValue = this.map.get(SHARED_CONTEXT_KEY + 0);
|
|
28387
28654
|
componentValue.declare = true;
|
|
28388
28655
|
this.maybeRestoreView();
|
|
28389
|
-
const lhs = typeof componentValue.lhs === 'function' ?
|
|
28656
|
+
const lhs = typeof componentValue.lhs === 'function' ?
|
|
28657
|
+
componentValue.lhs(this, componentValue.retrievalLevel) :
|
|
28658
|
+
componentValue.lhs;
|
|
28390
28659
|
return name === DIRECT_CONTEXT_REFERENCE ? lhs : lhs.prop(name);
|
|
28391
28660
|
}
|
|
28392
28661
|
maybeRestoreView() {
|
|
@@ -30971,7 +31240,7 @@ function publishFacade(global) {
|
|
|
30971
31240
|
* @description
|
|
30972
31241
|
* Entry point for all public APIs of the compiler package.
|
|
30973
31242
|
*/
|
|
30974
|
-
const VERSION = new Version('17.0.
|
|
31243
|
+
const VERSION = new Version('17.0.4');
|
|
30975
31244
|
|
|
30976
31245
|
class CompilerConfig {
|
|
30977
31246
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -31204,7 +31473,8 @@ class _Visitor {
|
|
|
31204
31473
|
this._errors = [];
|
|
31205
31474
|
this._messages = [];
|
|
31206
31475
|
this._inImplicitNode = false;
|
|
31207
|
-
this._createI18nMessage =
|
|
31476
|
+
this._createI18nMessage =
|
|
31477
|
+
createI18nMessageFactory(interpolationConfig, DEFAULT_CONTAINER_BLOCKS);
|
|
31208
31478
|
}
|
|
31209
31479
|
// looks for translatable attributes
|
|
31210
31480
|
_visitAttributesOf(el) {
|
|
@@ -31512,6 +31782,12 @@ class _WriteVisitor$1 {
|
|
|
31512
31782
|
visitPlaceholder(ph, context) {
|
|
31513
31783
|
return [new Tag(_PLACEHOLDER_TAG$2, { id: ph.name, 'equiv-text': `{{${ph.value}}}` })];
|
|
31514
31784
|
}
|
|
31785
|
+
visitBlockPlaceholder(ph, context) {
|
|
31786
|
+
const ctype = `x-${ph.name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`;
|
|
31787
|
+
const startTagPh = new Tag(_PLACEHOLDER_TAG$2, { id: ph.startName, ctype, 'equiv-text': `@${ph.name}` });
|
|
31788
|
+
const closeTagPh = new Tag(_PLACEHOLDER_TAG$2, { id: ph.closeName, ctype, 'equiv-text': `}` });
|
|
31789
|
+
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
|
|
31790
|
+
}
|
|
31515
31791
|
visitIcuPlaceholder(ph, context) {
|
|
31516
31792
|
const equivText = `{${ph.value.expression}, ${ph.value.type}, ${Object.keys(ph.value.cases).map((value) => value + ' {...}').join(' ')}}`;
|
|
31517
31793
|
return [new Tag(_PLACEHOLDER_TAG$2, { id: ph.name, 'equiv-text': equivText })];
|
|
@@ -31783,6 +32059,24 @@ class _WriteVisitor {
|
|
|
31783
32059
|
disp: `{{${ph.value}}}`,
|
|
31784
32060
|
})];
|
|
31785
32061
|
}
|
|
32062
|
+
visitBlockPlaceholder(ph, context) {
|
|
32063
|
+
const tagPc = new Tag(_PLACEHOLDER_SPANNING_TAG, {
|
|
32064
|
+
id: (this._nextPlaceholderId++).toString(),
|
|
32065
|
+
equivStart: ph.startName,
|
|
32066
|
+
equivEnd: ph.closeName,
|
|
32067
|
+
type: 'other',
|
|
32068
|
+
dispStart: `@${ph.name}`,
|
|
32069
|
+
dispEnd: `}`,
|
|
32070
|
+
});
|
|
32071
|
+
const nodes = [].concat(...ph.children.map(node => node.visit(this)));
|
|
32072
|
+
if (nodes.length) {
|
|
32073
|
+
nodes.forEach((node) => tagPc.children.push(node));
|
|
32074
|
+
}
|
|
32075
|
+
else {
|
|
32076
|
+
tagPc.children.push(new Text$1(''));
|
|
32077
|
+
}
|
|
32078
|
+
return [tagPc];
|
|
32079
|
+
}
|
|
31786
32080
|
visitIcuPlaceholder(ph, context) {
|
|
31787
32081
|
const cases = Object.keys(ph.value.cases).map((value) => value + ' {...}').join(' ');
|
|
31788
32082
|
const idStr = (this._nextPlaceholderId++).toString();
|
|
@@ -32231,6 +32525,11 @@ class I18nToHtmlVisitor {
|
|
|
32231
32525
|
// An ICU placeholder references the source message to be serialized
|
|
32232
32526
|
return this._convertToText(this._srcMsg.placeholderToMessage[ph.name]);
|
|
32233
32527
|
}
|
|
32528
|
+
visitBlockPlaceholder(ph, context) {
|
|
32529
|
+
const params = ph.parameters.length === 0 ? '' : ` (${ph.parameters.join('; ')})`;
|
|
32530
|
+
const children = ph.children.map((c) => c.visit(this)).join('');
|
|
32531
|
+
return `@${ph.name}${params} {${children}}`;
|
|
32532
|
+
}
|
|
32234
32533
|
/**
|
|
32235
32534
|
* Convert a source message to a translated text string:
|
|
32236
32535
|
* - text nodes are replaced with their translation,
|
|
@@ -32383,6 +32682,12 @@ class MapPlaceholderNames extends CloneVisitor {
|
|
|
32383
32682
|
const children = ph.children.map(n => n.visit(this, mapper));
|
|
32384
32683
|
return new TagPlaceholder(ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
|
|
32385
32684
|
}
|
|
32685
|
+
visitBlockPlaceholder(ph, mapper) {
|
|
32686
|
+
const startName = mapper.toPublicName(ph.startName);
|
|
32687
|
+
const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) : ph.closeName;
|
|
32688
|
+
const children = ph.children.map(n => n.visit(this, mapper));
|
|
32689
|
+
return new BlockPlaceholder(ph.name, ph.parameters, startName, closeName, children, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
|
|
32690
|
+
}
|
|
32386
32691
|
visitPlaceholder(ph, mapper) {
|
|
32387
32692
|
return new Placeholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan);
|
|
32388
32693
|
}
|
|
@@ -32501,7 +32806,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
32501
32806
|
function compileDeclareClassMetadata(metadata) {
|
|
32502
32807
|
const definitionMap = new DefinitionMap();
|
|
32503
32808
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
32504
|
-
definitionMap.set('version', literal('17.0.
|
|
32809
|
+
definitionMap.set('version', literal('17.0.4'));
|
|
32505
32810
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
32506
32811
|
definitionMap.set('type', metadata.type);
|
|
32507
32812
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -32609,7 +32914,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
32609
32914
|
// in 16.1 is actually used.
|
|
32610
32915
|
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
32611
32916
|
definitionMap.set('minVersion', literal(minVersion));
|
|
32612
|
-
definitionMap.set('version', literal('17.0.
|
|
32917
|
+
definitionMap.set('version', literal('17.0.4'));
|
|
32613
32918
|
// e.g. `type: MyDirective`
|
|
32614
32919
|
definitionMap.set('type', meta.type.value);
|
|
32615
32920
|
if (meta.isStandalone) {
|
|
@@ -32886,7 +33191,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
32886
33191
|
function compileDeclareFactoryFunction(meta) {
|
|
32887
33192
|
const definitionMap = new DefinitionMap();
|
|
32888
33193
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
32889
|
-
definitionMap.set('version', literal('17.0.
|
|
33194
|
+
definitionMap.set('version', literal('17.0.4'));
|
|
32890
33195
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
32891
33196
|
definitionMap.set('type', meta.type.value);
|
|
32892
33197
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -32921,7 +33226,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
32921
33226
|
function createInjectableDefinitionMap(meta) {
|
|
32922
33227
|
const definitionMap = new DefinitionMap();
|
|
32923
33228
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
32924
|
-
definitionMap.set('version', literal('17.0.
|
|
33229
|
+
definitionMap.set('version', literal('17.0.4'));
|
|
32925
33230
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
32926
33231
|
definitionMap.set('type', meta.type.value);
|
|
32927
33232
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -32972,7 +33277,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
32972
33277
|
function createInjectorDefinitionMap(meta) {
|
|
32973
33278
|
const definitionMap = new DefinitionMap();
|
|
32974
33279
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
32975
|
-
definitionMap.set('version', literal('17.0.
|
|
33280
|
+
definitionMap.set('version', literal('17.0.4'));
|
|
32976
33281
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
32977
33282
|
definitionMap.set('type', meta.type.value);
|
|
32978
33283
|
definitionMap.set('providers', meta.providers);
|
|
@@ -33005,7 +33310,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
33005
33310
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
33006
33311
|
}
|
|
33007
33312
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
33008
|
-
definitionMap.set('version', literal('17.0.
|
|
33313
|
+
definitionMap.set('version', literal('17.0.4'));
|
|
33009
33314
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33010
33315
|
definitionMap.set('type', meta.type.value);
|
|
33011
33316
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -33056,7 +33361,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
33056
33361
|
function createPipeDefinitionMap(meta) {
|
|
33057
33362
|
const definitionMap = new DefinitionMap();
|
|
33058
33363
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
33059
|
-
definitionMap.set('version', literal('17.0.
|
|
33364
|
+
definitionMap.set('version', literal('17.0.4'));
|
|
33060
33365
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33061
33366
|
// e.g. `type: MyPipe`
|
|
33062
33367
|
definitionMap.set('type', meta.type.value);
|