@getodk/xforms-engine 0.12.0 → 0.13.0
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/dist/client/TextRange.d.ts +0 -9
- package/dist/index.js +227 -100
- package/dist/index.js.map +1 -1
- package/dist/instance/RankControl.d.ts +3 -2
- package/dist/instance/SelectControl.d.ts +3 -2
- package/dist/parse/body/control/ItemsetDefinition.d.ts +1 -1
- package/dist/parse/expression/BindComputationExpression.d.ts +1 -1
- package/dist/parse/expression/ItemsetNodesetExpression.d.ts +1 -2
- package/dist/parse/expression/TextChunkExpression.d.ts +9 -7
- package/dist/parse/expression/abstract/DependentExpression.d.ts +1 -15
- package/dist/parse/model/ModelDefinition.d.ts +6 -1
- package/dist/parse/model/generateItextChunks.d.ts +5 -0
- package/dist/parse/xpath/semantic-analysis.d.ts +1 -0
- package/dist/solid.js +227 -100
- package/dist/solid.js.map +1 -1
- package/package.json +2 -2
- package/src/client/TextRange.ts +0 -9
- package/src/instance/RankControl.ts +8 -2
- package/src/instance/SelectControl.ts +8 -2
- package/src/lib/reactivity/text/createTextRange.ts +30 -30
- package/src/parse/body/control/ItemsetDefinition.ts +2 -2
- package/src/parse/expression/BindComputationExpression.ts +2 -7
- package/src/parse/expression/ItemsetNodesetExpression.ts +2 -3
- package/src/parse/expression/ItemsetValueExpression.ts +1 -1
- package/src/parse/expression/RepeatCountControlExpression.ts +4 -4
- package/src/parse/expression/TextChunkExpression.ts +25 -35
- package/src/parse/expression/abstract/DependentExpression.ts +2 -38
- package/src/parse/model/ModelDefinition.ts +13 -0
- package/src/parse/model/generateItextChunks.ts +61 -0
- package/src/parse/text/ItemsetLabelDefinition.ts +4 -4
- package/src/parse/text/MessageDefinition.ts +4 -4
- package/src/parse/text/abstract/TextElementDefinition.ts +6 -7
- package/src/parse/xpath/semantic-analysis.ts +37 -8
|
@@ -47,15 +47,6 @@ import { ActiveLanguage } from './FormLanguage.ts';
|
|
|
47
47
|
* - `h:body//hint/@ref[not(is-translation-expr())]`
|
|
48
48
|
*
|
|
49
49
|
* (See notes above for clarification of `is-translation-expr()`.)
|
|
50
|
-
*
|
|
51
|
-
* @todo It's unclear whether this will all become simpler or more compelex when
|
|
52
|
-
* we add support for outputs in translations. In theory, the actual translation
|
|
53
|
-
* `<text>` nodes map quite well to the `TextRange` concept (i.e. they are a
|
|
54
|
-
* range of static and output chunks, just like labels and hints). The potential
|
|
55
|
-
* for complications arise from XPath implementation details being largely
|
|
56
|
-
* opaque (as in, the `jr:itext` implementation is encapsulated in the `xpath`
|
|
57
|
-
* package, and the engine doesn't really deal with itext translations at the
|
|
58
|
-
* node level at all).
|
|
59
50
|
*/
|
|
60
51
|
export type TextChunkSource = 'literal' | 'output' | 'reference' | 'translation';
|
|
61
52
|
/**
|
package/dist/index.js
CHANGED
|
@@ -11576,7 +11576,45 @@ const nodeSet = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
|
11576
11576
|
itext
|
|
11577
11577
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
11578
11578
|
|
|
11579
|
-
const
|
|
11579
|
+
const choiceName = new StringFunction(
|
|
11580
|
+
"choice-name",
|
|
11581
|
+
[
|
|
11582
|
+
{ arityType: "required", typeHint: "string" },
|
|
11583
|
+
{ arityType: "required", typeHint: "string" }
|
|
11584
|
+
],
|
|
11585
|
+
(context, [nodeExpression, valueExpression]) => {
|
|
11586
|
+
const node = nodeExpression.evaluate(context).toString();
|
|
11587
|
+
const value = valueExpression.evaluate(context).toString();
|
|
11588
|
+
const [contextNode] = context.contextNodes;
|
|
11589
|
+
const { domProvider } = context;
|
|
11590
|
+
let nodes;
|
|
11591
|
+
if (contextNode && domProvider.isElement(contextNode)) {
|
|
11592
|
+
nodes = context.evaluator.evaluateNodes(value, { contextNode });
|
|
11593
|
+
} else {
|
|
11594
|
+
nodes = context.evaluator.evaluateNodes(value);
|
|
11595
|
+
}
|
|
11596
|
+
const firstNode = nodes?.[0];
|
|
11597
|
+
if (!firstNode) {
|
|
11598
|
+
return "";
|
|
11599
|
+
}
|
|
11600
|
+
if (!("getChoiceName" in firstNode)) {
|
|
11601
|
+
throw new Error(
|
|
11602
|
+
`Evaluating 'jr:choice-name' on element '${value}' which has no possible choices.`
|
|
11603
|
+
);
|
|
11604
|
+
}
|
|
11605
|
+
return firstNode.getChoiceName(node) ?? "";
|
|
11606
|
+
}
|
|
11607
|
+
);
|
|
11608
|
+
|
|
11609
|
+
const select$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
11610
|
+
__proto__: null,
|
|
11611
|
+
choiceName
|
|
11612
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
11613
|
+
|
|
11614
|
+
const jr$2 = new FunctionLibrary(JAVAROSA_NAMESPACE_URI, [
|
|
11615
|
+
...Object.values(nodeSet),
|
|
11616
|
+
...Object.values(select$1)
|
|
11617
|
+
]);
|
|
11580
11618
|
|
|
11581
11619
|
const booleanFromString = new BooleanFunction(
|
|
11582
11620
|
"boolean-from-string",
|
|
@@ -19007,6 +19045,10 @@ const hex = /*#__PURE__*/_mergeNamespaces({
|
|
|
19007
19045
|
default: encHex
|
|
19008
19046
|
}, [encHexExports]);
|
|
19009
19047
|
|
|
19048
|
+
const base64Decode$1 = (base64Input) => {
|
|
19049
|
+
return new TextDecoder().decode(Uint8Array.from(atob(base64Input), (m) => m.charCodeAt(0)));
|
|
19050
|
+
};
|
|
19051
|
+
|
|
19010
19052
|
const toStrings = (context, expressions) => {
|
|
19011
19053
|
return expressions.flatMap((arg) => {
|
|
19012
19054
|
const result = arg.evaluate(context);
|
|
@@ -19018,6 +19060,17 @@ const toStrings = (context, expressions) => {
|
|
|
19018
19060
|
});
|
|
19019
19061
|
};
|
|
19020
19062
|
|
|
19063
|
+
const base64Decode = new StringFunction(
|
|
19064
|
+
"base64-decode",
|
|
19065
|
+
[{ arityType: "required", typeHint: "string" }],
|
|
19066
|
+
(context, [base64Expression]) => {
|
|
19067
|
+
try {
|
|
19068
|
+
return base64Decode$1(base64Expression.evaluate(context).toString());
|
|
19069
|
+
} catch {
|
|
19070
|
+
return "";
|
|
19071
|
+
}
|
|
19072
|
+
}
|
|
19073
|
+
);
|
|
19021
19074
|
const coalesce = new StringFunction(
|
|
19022
19075
|
"coalesce",
|
|
19023
19076
|
[
|
|
@@ -19107,6 +19160,23 @@ const join = new StringFunction(
|
|
|
19107
19160
|
return strings.join(glue);
|
|
19108
19161
|
}
|
|
19109
19162
|
);
|
|
19163
|
+
const pulldata = new StringFunction(
|
|
19164
|
+
"pulldata",
|
|
19165
|
+
[
|
|
19166
|
+
{ arityType: "required", typeHint: "string" },
|
|
19167
|
+
{ arityType: "required", typeHint: "string" },
|
|
19168
|
+
{ arityType: "required", typeHint: "string" },
|
|
19169
|
+
{ arityType: "required", typeHint: "string" }
|
|
19170
|
+
],
|
|
19171
|
+
(context, [instanceExpression, desiredElementExpression, queryElementExpression, queryExpression]) => {
|
|
19172
|
+
const instanceId = instanceExpression.evaluate(context).toString();
|
|
19173
|
+
const desiredElement = desiredElementExpression.evaluate(context).toString();
|
|
19174
|
+
const queryElement = queryElementExpression.evaluate(context).toString();
|
|
19175
|
+
const query = queryExpression.evaluate(context).toString();
|
|
19176
|
+
const expr = `instance('${instanceId}')/root/item[${queryElement}='${query}']/${desiredElement}`;
|
|
19177
|
+
return context.evaluator.evaluateString(expr);
|
|
19178
|
+
}
|
|
19179
|
+
);
|
|
19110
19180
|
const regex = new BooleanFunction(
|
|
19111
19181
|
"regex",
|
|
19112
19182
|
[
|
|
@@ -19185,11 +19255,13 @@ const uuid = new StringFunction(
|
|
|
19185
19255
|
|
|
19186
19256
|
const string = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
19187
19257
|
__proto__: null,
|
|
19258
|
+
base64Decode,
|
|
19188
19259
|
coalesce,
|
|
19189
19260
|
concat,
|
|
19190
19261
|
digest,
|
|
19191
19262
|
endsWith,
|
|
19192
19263
|
join,
|
|
19264
|
+
pulldata,
|
|
19193
19265
|
regex,
|
|
19194
19266
|
substr,
|
|
19195
19267
|
uuid
|
|
@@ -19903,18 +19975,32 @@ const isTranslationFunctionCall = (syntaxNode) => {
|
|
|
19903
19975
|
ANY_ARGUMENT_TYPE
|
|
19904
19976
|
]);
|
|
19905
19977
|
};
|
|
19906
|
-
const
|
|
19978
|
+
const findFunctionPrincipalExpressionNode = (expression) => {
|
|
19907
19979
|
let result;
|
|
19908
19980
|
try {
|
|
19909
19981
|
result = expressionParser.parse(expression);
|
|
19910
19982
|
} catch {
|
|
19911
|
-
return
|
|
19983
|
+
return null;
|
|
19912
19984
|
}
|
|
19913
19985
|
const functionCallNode = findTypedPrincipalExpressionNode(["function_call"], result.rootNode);
|
|
19914
19986
|
if (functionCallNode == null) {
|
|
19915
|
-
return
|
|
19987
|
+
return null;
|
|
19916
19988
|
}
|
|
19917
|
-
return
|
|
19989
|
+
return functionCallNode;
|
|
19990
|
+
};
|
|
19991
|
+
const getTranslationExpression = (expression) => {
|
|
19992
|
+
const functionCallNode = findFunctionPrincipalExpressionNode(expression);
|
|
19993
|
+
if (!functionCallNode) {
|
|
19994
|
+
return null;
|
|
19995
|
+
}
|
|
19996
|
+
if (!isTranslationFunctionCall(functionCallNode)) {
|
|
19997
|
+
return null;
|
|
19998
|
+
}
|
|
19999
|
+
const arg = functionCallNode.children.find((child) => child.type === "argument");
|
|
20000
|
+
if (!arg) {
|
|
20001
|
+
return null;
|
|
20002
|
+
}
|
|
20003
|
+
return arg.text;
|
|
19918
20004
|
};
|
|
19919
20005
|
const isCurrentFunctionCall = (syntaxNode) => {
|
|
19920
20006
|
return isCallToLocalNamedFunction(syntaxNode, "current") && hasCallSignature(syntaxNode, []);
|
|
@@ -20034,7 +20120,7 @@ const evaluatorMethodsByResultType = {
|
|
|
20034
20120
|
string: "evaluateString"
|
|
20035
20121
|
};
|
|
20036
20122
|
class DependentExpression {
|
|
20037
|
-
constructor(
|
|
20123
|
+
constructor(resultType, expression) {
|
|
20038
20124
|
this.resultType = resultType;
|
|
20039
20125
|
this.expression = expression;
|
|
20040
20126
|
if (resultType === "boolean" && isConstantTruthyExpression(expression)) {
|
|
@@ -20048,16 +20134,6 @@ class DependentExpression {
|
|
|
20048
20134
|
this.constantExpression = null;
|
|
20049
20135
|
}
|
|
20050
20136
|
this.evaluatorMethod = evaluatorMethodsByResultType[resultType];
|
|
20051
|
-
const {
|
|
20052
|
-
semanticDependencies = {
|
|
20053
|
-
translations: false
|
|
20054
|
-
}
|
|
20055
|
-
} = options;
|
|
20056
|
-
const isTranslated = semanticDependencies.translations && isTranslationExpression(expression);
|
|
20057
|
-
if (isTranslated) {
|
|
20058
|
-
this.isTranslated = true;
|
|
20059
|
-
context.isTranslated = true;
|
|
20060
|
-
}
|
|
20061
20137
|
}
|
|
20062
20138
|
isTranslated = false;
|
|
20063
20139
|
evaluatorMethod;
|
|
@@ -20081,33 +20157,32 @@ class TextChunkExpression extends DependentExpression {
|
|
|
20081
20157
|
source;
|
|
20082
20158
|
// Set for the literal source, blank otherwise
|
|
20083
20159
|
stringValue;
|
|
20084
|
-
|
|
20085
|
-
|
|
20086
|
-
|
|
20087
|
-
|
|
20088
|
-
},
|
|
20089
|
-
ignoreContextReference: true
|
|
20090
|
-
});
|
|
20160
|
+
resourceType;
|
|
20161
|
+
constructor(resultType, expression, source, literalValue = "", options = {}) {
|
|
20162
|
+
super(resultType, expression);
|
|
20163
|
+
this.resourceType = options.type ?? null;
|
|
20091
20164
|
this.source = source;
|
|
20092
20165
|
this.stringValue = literalValue;
|
|
20093
20166
|
}
|
|
20094
|
-
static fromLiteral(
|
|
20095
|
-
return new TextChunkExpression(
|
|
20167
|
+
static fromLiteral(stringValue) {
|
|
20168
|
+
return new TextChunkExpression("string", "null", "literal", stringValue);
|
|
20096
20169
|
}
|
|
20097
|
-
static fromReference(
|
|
20098
|
-
return new TextChunkExpression(
|
|
20170
|
+
static fromReference(ref) {
|
|
20171
|
+
return new TextChunkExpression("string", ref, "reference");
|
|
20099
20172
|
}
|
|
20100
|
-
static fromOutput(
|
|
20173
|
+
static fromOutput(element) {
|
|
20101
20174
|
if (!isOutputElement(element)) {
|
|
20102
20175
|
return null;
|
|
20103
20176
|
}
|
|
20104
|
-
return new TextChunkExpression(
|
|
20177
|
+
return new TextChunkExpression("string", element.getAttribute("value"), "output");
|
|
20105
20178
|
}
|
|
20106
|
-
static
|
|
20107
|
-
|
|
20108
|
-
|
|
20109
|
-
|
|
20110
|
-
|
|
20179
|
+
static fromResource(url, type) {
|
|
20180
|
+
return new TextChunkExpression("string", "null", "literal", url, { type });
|
|
20181
|
+
}
|
|
20182
|
+
static fromTranslation(maybeExpression) {
|
|
20183
|
+
const translationExpression = getTranslationExpression(maybeExpression);
|
|
20184
|
+
if (translationExpression) {
|
|
20185
|
+
return new TextChunkExpression("nodes", translationExpression, "translation");
|
|
20111
20186
|
}
|
|
20112
20187
|
return null;
|
|
20113
20188
|
}
|
|
@@ -20354,24 +20429,23 @@ class TextElementDefinition extends TextRangeDefinition {
|
|
|
20354
20429
|
chunks;
|
|
20355
20430
|
constructor(form, owner, sourceNode) {
|
|
20356
20431
|
super(form, owner, sourceNode);
|
|
20357
|
-
const context = this;
|
|
20358
20432
|
const refExpression = parseNodesetReference(owner, sourceNode, "ref");
|
|
20359
20433
|
if (refExpression == null) {
|
|
20360
20434
|
this.chunks = Array.from(sourceNode.childNodes).flatMap((childNode) => {
|
|
20361
20435
|
if (isElementNode(childNode)) {
|
|
20362
|
-
return TextChunkExpression.fromOutput(
|
|
20436
|
+
return TextChunkExpression.fromOutput(childNode) ?? [];
|
|
20363
20437
|
}
|
|
20364
20438
|
if (isTextNode(childNode)) {
|
|
20365
|
-
return TextChunkExpression.fromLiteral(
|
|
20439
|
+
return TextChunkExpression.fromLiteral(childNode.data);
|
|
20366
20440
|
}
|
|
20367
20441
|
return [];
|
|
20368
20442
|
});
|
|
20369
20443
|
} else {
|
|
20370
|
-
const
|
|
20371
|
-
if (
|
|
20372
|
-
this.chunks = [
|
|
20444
|
+
const translationChunk = TextChunkExpression.fromTranslation(refExpression);
|
|
20445
|
+
if (translationChunk) {
|
|
20446
|
+
this.chunks = [translationChunk];
|
|
20373
20447
|
} else {
|
|
20374
|
-
this.chunks = [TextChunkExpression.fromReference(
|
|
20448
|
+
this.chunks = [TextChunkExpression.fromReference(refExpression)];
|
|
20375
20449
|
}
|
|
20376
20450
|
}
|
|
20377
20451
|
}
|
|
@@ -20596,14 +20670,14 @@ class RangeControlDefinition extends ControlDefinition {
|
|
|
20596
20670
|
}
|
|
20597
20671
|
|
|
20598
20672
|
class ItemsetNodesetExpression extends DependentExpression {
|
|
20599
|
-
constructor(
|
|
20600
|
-
super(
|
|
20673
|
+
constructor(nodesetExpression) {
|
|
20674
|
+
super("nodes", nodesetExpression);
|
|
20601
20675
|
}
|
|
20602
20676
|
}
|
|
20603
20677
|
|
|
20604
20678
|
class ItemsetValueExpression extends DependentExpression {
|
|
20605
20679
|
constructor(itemset, expression) {
|
|
20606
|
-
super(
|
|
20680
|
+
super("string", expression);
|
|
20607
20681
|
this.itemset = itemset;
|
|
20608
20682
|
}
|
|
20609
20683
|
}
|
|
@@ -20624,11 +20698,11 @@ class ItemsetLabelDefinition extends TextRangeDefinition {
|
|
|
20624
20698
|
if (refExpression == null) {
|
|
20625
20699
|
throw new Error("<itemset><label> missing ref attribute");
|
|
20626
20700
|
}
|
|
20627
|
-
const
|
|
20628
|
-
if (
|
|
20629
|
-
this.chunks = [
|
|
20701
|
+
const translationChunk = TextChunkExpression.fromTranslation(refExpression);
|
|
20702
|
+
if (translationChunk) {
|
|
20703
|
+
this.chunks = [translationChunk];
|
|
20630
20704
|
} else {
|
|
20631
|
-
this.chunks = [TextChunkExpression.fromReference(
|
|
20705
|
+
this.chunks = [TextChunkExpression.fromReference(refExpression)];
|
|
20632
20706
|
}
|
|
20633
20707
|
}
|
|
20634
20708
|
}
|
|
@@ -20638,7 +20712,7 @@ class ItemsetDefinition extends BodyElementDefinition {
|
|
|
20638
20712
|
super(form, parent, element);
|
|
20639
20713
|
this.parent = parent;
|
|
20640
20714
|
const nodesetExpression = parseNodesetReference(parent, element, "nodeset");
|
|
20641
|
-
this.nodes = new ItemsetNodesetExpression(
|
|
20715
|
+
this.nodes = new ItemsetNodesetExpression(nodesetExpression);
|
|
20642
20716
|
this.reference = nodesetExpression;
|
|
20643
20717
|
const valueElement = getValueElement(element);
|
|
20644
20718
|
if (valueElement == null) {
|
|
@@ -21457,6 +21531,64 @@ const parseStaticDocumentFromDOMSubtree = (subtreeRootElement, options = {}) =>
|
|
|
21457
21531
|
});
|
|
21458
21532
|
};
|
|
21459
21533
|
|
|
21534
|
+
const JR_RESOURCE_URL_PROTOCOL = "jr:";
|
|
21535
|
+
const ALL_RESOURCE_TYPES = ["image", "audio", "video"];
|
|
21536
|
+
const isResourceType = (string) => {
|
|
21537
|
+
return ALL_RESOURCE_TYPES.includes(string);
|
|
21538
|
+
};
|
|
21539
|
+
class JRResourceURL extends URL {
|
|
21540
|
+
static create(category, fileName) {
|
|
21541
|
+
return new this(`jr://${category}/${fileName}`);
|
|
21542
|
+
}
|
|
21543
|
+
static from(url) {
|
|
21544
|
+
return new this(url);
|
|
21545
|
+
}
|
|
21546
|
+
static isJRResourceReference(reference) {
|
|
21547
|
+
return reference?.startsWith(JR_RESOURCE_URL_PROTOCOL) ?? false;
|
|
21548
|
+
}
|
|
21549
|
+
constructor(url) {
|
|
21550
|
+
super(url);
|
|
21551
|
+
}
|
|
21552
|
+
}
|
|
21553
|
+
|
|
21554
|
+
const generateChunk = (node) => {
|
|
21555
|
+
if (isElementNode(node)) {
|
|
21556
|
+
return TextChunkExpression.fromOutput(node);
|
|
21557
|
+
}
|
|
21558
|
+
if (isTextNode(node)) {
|
|
21559
|
+
const formAttribute = node.parentElement.getAttribute("form");
|
|
21560
|
+
if (isResourceType(formAttribute)) {
|
|
21561
|
+
return TextChunkExpression.fromResource(node.data, formAttribute);
|
|
21562
|
+
}
|
|
21563
|
+
return TextChunkExpression.fromLiteral(node.data);
|
|
21564
|
+
}
|
|
21565
|
+
return null;
|
|
21566
|
+
};
|
|
21567
|
+
const generateChunksForValues = (valueElement) => {
|
|
21568
|
+
return Array.from(valueElement.childNodes).map((node) => generateChunk(node)).filter((chunk) => chunk !== null);
|
|
21569
|
+
};
|
|
21570
|
+
const generateChunksForTranslation = (textElement) => {
|
|
21571
|
+
return Array.from(textElement.childNodes).flatMap(
|
|
21572
|
+
(valueElement) => generateChunksForValues(valueElement)
|
|
21573
|
+
);
|
|
21574
|
+
};
|
|
21575
|
+
const generateChunksForLanguage = (translationElement) => {
|
|
21576
|
+
return new Map(
|
|
21577
|
+
Array.from(translationElement.children).map((textElement) => {
|
|
21578
|
+
const itextId = textElement.getAttribute("id");
|
|
21579
|
+
return [itextId, generateChunksForTranslation(textElement)];
|
|
21580
|
+
})
|
|
21581
|
+
);
|
|
21582
|
+
};
|
|
21583
|
+
const generateItextChunks = (translationElements) => {
|
|
21584
|
+
return new Map(
|
|
21585
|
+
translationElements.map((translationElement) => {
|
|
21586
|
+
const lang = translationElement.getAttribute("lang");
|
|
21587
|
+
return [lang, generateChunksForLanguage(translationElement)];
|
|
21588
|
+
})
|
|
21589
|
+
);
|
|
21590
|
+
};
|
|
21591
|
+
|
|
21460
21592
|
const assertItextTranslationsDefinitionEntry = ([
|
|
21461
21593
|
key,
|
|
21462
21594
|
root
|
|
@@ -21503,8 +21635,7 @@ const bindComputationResultTypes = {
|
|
|
21503
21635
|
saveIncomplete: "boolean"
|
|
21504
21636
|
};
|
|
21505
21637
|
class BindComputationExpression extends DependentExpression {
|
|
21506
|
-
constructor(
|
|
21507
|
-
const ignoreContextReference = computation === "constraint";
|
|
21638
|
+
constructor(computation, expression) {
|
|
21508
21639
|
let isDefaultExpression;
|
|
21509
21640
|
let resolvedExpression;
|
|
21510
21641
|
if (expression == null) {
|
|
@@ -21517,9 +21648,7 @@ class BindComputationExpression extends DependentExpression {
|
|
|
21517
21648
|
isDefaultExpression = false;
|
|
21518
21649
|
resolvedExpression = expression;
|
|
21519
21650
|
}
|
|
21520
|
-
super(
|
|
21521
|
-
ignoreContextReference
|
|
21522
|
-
});
|
|
21651
|
+
super(bindComputationResultTypes[computation], resolvedExpression);
|
|
21523
21652
|
this.computation = computation;
|
|
21524
21653
|
this.isDefaultExpression = isDefaultExpression;
|
|
21525
21654
|
}
|
|
@@ -21528,7 +21657,7 @@ class BindComputationExpression extends DependentExpression {
|
|
|
21528
21657
|
if (expression == null) {
|
|
21529
21658
|
return null;
|
|
21530
21659
|
}
|
|
21531
|
-
return new this(
|
|
21660
|
+
return new this(computation, expression);
|
|
21532
21661
|
}
|
|
21533
21662
|
isDefaultExpression;
|
|
21534
21663
|
}
|
|
@@ -21537,11 +21666,11 @@ class MessageDefinition extends TextRangeDefinition {
|
|
|
21537
21666
|
constructor(bind, role, message) {
|
|
21538
21667
|
super(bind.form, bind, null);
|
|
21539
21668
|
this.role = role;
|
|
21540
|
-
const
|
|
21541
|
-
if (
|
|
21542
|
-
this.chunks = [
|
|
21669
|
+
const translationChunk = TextChunkExpression.fromTranslation(message);
|
|
21670
|
+
if (translationChunk) {
|
|
21671
|
+
this.chunks = [translationChunk];
|
|
21543
21672
|
} else {
|
|
21544
|
-
this.chunks = [TextChunkExpression.fromLiteral(
|
|
21673
|
+
this.chunks = [TextChunkExpression.fromLiteral(message)];
|
|
21545
21674
|
}
|
|
21546
21675
|
}
|
|
21547
21676
|
static from(bind, type) {
|
|
@@ -26409,16 +26538,16 @@ class RepeatCountControlExpression extends DependentExpression {
|
|
|
26409
26538
|
static from(bodyElement, initialCount) {
|
|
26410
26539
|
const { countExpression, noAddRemoveExpression } = bodyElement;
|
|
26411
26540
|
if (countExpression != null) {
|
|
26412
|
-
return new this(
|
|
26541
|
+
return new this(countExpression);
|
|
26413
26542
|
}
|
|
26414
26543
|
if (noAddRemoveExpression != null && isConstantTruthyExpression(noAddRemoveExpression)) {
|
|
26415
26544
|
const fixedCountExpression = String(Math.max(initialCount, 1));
|
|
26416
|
-
return new this(
|
|
26545
|
+
return new this(fixedCountExpression);
|
|
26417
26546
|
}
|
|
26418
26547
|
return null;
|
|
26419
26548
|
}
|
|
26420
|
-
constructor(
|
|
26421
|
-
super(
|
|
26549
|
+
constructor(expression) {
|
|
26550
|
+
super("number", expression);
|
|
26422
26551
|
}
|
|
26423
26552
|
}
|
|
26424
26553
|
|
|
@@ -26685,12 +26814,14 @@ class ModelDefinition {
|
|
|
26685
26814
|
this.root = new RootDefinition(form, this, submission, form.body.classes);
|
|
26686
26815
|
this.nodes = nodeDefinitionMap(this.root);
|
|
26687
26816
|
this.itextTranslations = ItextTranslationsDefinition.from(form.xformDOM);
|
|
26817
|
+
this.itextChunks = generateItextChunks(form.xformDOM.itextTranslationElements);
|
|
26688
26818
|
}
|
|
26689
26819
|
binds;
|
|
26690
26820
|
root;
|
|
26691
26821
|
nodes;
|
|
26692
26822
|
instance;
|
|
26693
26823
|
itextTranslations;
|
|
26824
|
+
itextChunks;
|
|
26694
26825
|
getNodeDefinition(nodeset) {
|
|
26695
26826
|
const definition = this.nodes.get(nodeset);
|
|
26696
26827
|
if (definition == null) {
|
|
@@ -26709,6 +26840,10 @@ class ModelDefinition {
|
|
|
26709
26840
|
const { form, ...rest } = this;
|
|
26710
26841
|
return rest;
|
|
26711
26842
|
}
|
|
26843
|
+
getTranslationChunks(itextId, activeLanguage) {
|
|
26844
|
+
const languageMap = this.itextChunks.get(activeLanguage.language);
|
|
26845
|
+
return languageMap?.get(itextId) ?? [];
|
|
26846
|
+
}
|
|
26712
26847
|
}
|
|
26713
26848
|
|
|
26714
26849
|
class XFormDefinition {
|
|
@@ -26734,22 +26869,6 @@ class XFormDefinition {
|
|
|
26734
26869
|
model;
|
|
26735
26870
|
}
|
|
26736
26871
|
|
|
26737
|
-
const JR_RESOURCE_URL_PROTOCOL = "jr:";
|
|
26738
|
-
class JRResourceURL extends URL {
|
|
26739
|
-
static create(category, fileName) {
|
|
26740
|
-
return new this(`jr://${category}/${fileName}`);
|
|
26741
|
-
}
|
|
26742
|
-
static from(url) {
|
|
26743
|
-
return new this(url);
|
|
26744
|
-
}
|
|
26745
|
-
static isJRResourceReference(reference) {
|
|
26746
|
-
return reference?.startsWith(JR_RESOURCE_URL_PROTOCOL) ?? false;
|
|
26747
|
-
}
|
|
26748
|
-
constructor(url) {
|
|
26749
|
-
super(url);
|
|
26750
|
-
}
|
|
26751
|
-
}
|
|
26752
|
-
|
|
26753
26872
|
const assertSecondaryInstanceDefinition = ({ root }) => {
|
|
26754
26873
|
const id = root.getAttributeValue("id");
|
|
26755
26874
|
if (id == null) {
|
|
@@ -29454,42 +29573,42 @@ class TextRange {
|
|
|
29454
29573
|
}
|
|
29455
29574
|
}
|
|
29456
29575
|
|
|
29457
|
-
const createTextChunks = (context,
|
|
29576
|
+
const createTextChunks = (context, definition) => {
|
|
29458
29577
|
return createMemo(() => {
|
|
29459
29578
|
const chunks = [];
|
|
29460
29579
|
const mediaSources = {};
|
|
29580
|
+
let chunkExpressions;
|
|
29581
|
+
if (definition.chunks[0]?.source === "translation") {
|
|
29582
|
+
const itextId = context.evaluator.evaluateString(definition.chunks[0].toString(), {
|
|
29583
|
+
contextNode: context.contextNode
|
|
29584
|
+
});
|
|
29585
|
+
chunkExpressions = definition.form.model.getTranslationChunks(
|
|
29586
|
+
itextId,
|
|
29587
|
+
context.getActiveLanguage()
|
|
29588
|
+
);
|
|
29589
|
+
} else {
|
|
29590
|
+
chunkExpressions = definition.chunks;
|
|
29591
|
+
}
|
|
29461
29592
|
chunkExpressions.forEach((chunkExpression) => {
|
|
29593
|
+
if (chunkExpression.resourceType) {
|
|
29594
|
+
mediaSources[chunkExpression.resourceType] = JRResourceURL.from(
|
|
29595
|
+
chunkExpression.stringValue
|
|
29596
|
+
);
|
|
29597
|
+
return;
|
|
29598
|
+
}
|
|
29462
29599
|
if (chunkExpression.source === "literal") {
|
|
29463
29600
|
chunks.push(new TextChunk(context, chunkExpression.source, chunkExpression.stringValue));
|
|
29464
29601
|
return;
|
|
29465
29602
|
}
|
|
29466
29603
|
const computed = createComputedExpression(context, chunkExpression)();
|
|
29467
|
-
|
|
29468
|
-
chunks.push(new TextChunk(context, chunkExpression.source, computed));
|
|
29469
|
-
return;
|
|
29470
|
-
} else {
|
|
29471
|
-
computed.forEach((itextForm) => {
|
|
29472
|
-
if (isEngineXPathElement(itextForm) && itextForm instanceof StaticElement) {
|
|
29473
|
-
const formAttribute = itextForm.getAttributeValue("form");
|
|
29474
|
-
if (!formAttribute) {
|
|
29475
|
-
const defaultFormValue = itextForm.getXPathValue();
|
|
29476
|
-
chunks.push(new TextChunk(context, chunkExpression.source, defaultFormValue));
|
|
29477
|
-
} else if (["image", "video", "audio"].includes(formAttribute)) {
|
|
29478
|
-
const formValue = itextForm.getXPathValue();
|
|
29479
|
-
if (JRResourceURL.isJRResourceReference(formValue)) {
|
|
29480
|
-
mediaSources[formAttribute] = JRResourceURL.from(formValue);
|
|
29481
|
-
}
|
|
29482
|
-
}
|
|
29483
|
-
}
|
|
29484
|
-
});
|
|
29485
|
-
}
|
|
29604
|
+
chunks.push(new TextChunk(context, chunkExpression.source, computed));
|
|
29486
29605
|
});
|
|
29487
29606
|
return { chunks, mediaSources };
|
|
29488
29607
|
});
|
|
29489
29608
|
};
|
|
29490
29609
|
const createTextRange = (context, role, definition) => {
|
|
29491
29610
|
return context.scope.runTask(() => {
|
|
29492
|
-
const textChunks = createTextChunks(context, definition
|
|
29611
|
+
const textChunks = createTextChunks(context, definition);
|
|
29493
29612
|
return createMemo(() => {
|
|
29494
29613
|
const chunks = textChunks();
|
|
29495
29614
|
return new TextRange("form", role, chunks.chunks, chunks.mediaSources);
|
|
@@ -30368,6 +30487,10 @@ class RankControl extends ValueNode {
|
|
|
30368
30487
|
this.setValueState(valuesInOrder);
|
|
30369
30488
|
return this.root;
|
|
30370
30489
|
}
|
|
30490
|
+
getChoiceName(value) {
|
|
30491
|
+
const option = this.mapOptionsByValue().get(value);
|
|
30492
|
+
return option?.label?.asString ?? null;
|
|
30493
|
+
}
|
|
30371
30494
|
}
|
|
30372
30495
|
|
|
30373
30496
|
const insertAtIndex = (currentValues, insertionIndex, newValues) => {
|
|
@@ -30932,6 +31055,10 @@ class SelectControl extends ValueNode {
|
|
|
30932
31055
|
this.setValueState(effectiveValues);
|
|
30933
31056
|
return this.root;
|
|
30934
31057
|
}
|
|
31058
|
+
getChoiceName(value) {
|
|
31059
|
+
const option = this.mapOptionsByValue().get(value);
|
|
31060
|
+
return option?.label?.asString ?? null;
|
|
31061
|
+
}
|
|
30935
31062
|
}
|
|
30936
31063
|
|
|
30937
31064
|
class Subtree extends DescendantNode {
|