@getodk/xforms-engine 0.9.0 → 0.11.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/SelectNode.d.ts +1 -0
- package/dist/client/TextRange.d.ts +4 -0
- package/dist/index.js +133 -160
- package/dist/index.js.map +1 -1
- package/dist/instance/SelectControl.d.ts +1 -0
- package/dist/instance/text/TextRange.d.ts +11 -1
- package/dist/lib/reactivity/text/createTextRange.d.ts +1 -2
- package/dist/parse/expression/TextChunkExpression.d.ts +16 -0
- package/dist/parse/shared/parseInstanceXML.d.ts +1 -1
- package/dist/parse/text/ItemsetLabelDefinition.d.ts +2 -4
- package/dist/parse/text/MessageDefinition.d.ts +3 -7
- package/dist/parse/text/abstract/TextElementDefinition.d.ts +2 -8
- package/dist/parse/text/abstract/TextRangeDefinition.d.ts +2 -2
- package/dist/solid.js +133 -160
- package/dist/solid.js.map +1 -1
- package/package.json +2 -2
- package/src/client/SelectNode.ts +2 -0
- package/src/client/TextRange.ts +5 -1
- package/src/error/LoadFormFailureError.ts +9 -35
- package/src/instance/SelectControl.ts +6 -0
- package/src/instance/text/TextRange.ts +21 -1
- package/src/lib/reactivity/text/createTextRange.ts +56 -43
- package/src/lib/reactivity/validation/createValidation.ts +1 -3
- package/src/parse/expression/TextChunkExpression.ts +78 -0
- package/src/parse/shared/parseInstanceXML.ts +4 -2
- package/src/parse/text/ItemsetLabelDefinition.ts +8 -12
- package/src/parse/text/MessageDefinition.ts +9 -16
- package/src/parse/text/abstract/TextElementDefinition.ts +10 -26
- package/src/parse/text/abstract/TextRangeDefinition.ts +2 -2
- package/src/parse/xpath/semantic-analysis.ts +7 -2
- package/dist/parse/expression/TextLiteralExpression.d.ts +0 -9
- package/dist/parse/expression/TextOutputExpression.d.ts +0 -7
- package/dist/parse/expression/TextReferenceExpression.d.ts +0 -7
- package/dist/parse/expression/TextTranslationExpression.d.ts +0 -8
- package/dist/parse/expression/abstract/TextChunkExpression.d.ts +0 -17
- package/src/parse/expression/TextLiteralExpression.ts +0 -19
- package/src/parse/expression/TextOutputExpression.ts +0 -25
- package/src/parse/expression/TextReferenceExpression.ts +0 -14
- package/src/parse/expression/TextTranslationExpression.ts +0 -38
- package/src/parse/expression/abstract/TextChunkExpression.ts +0 -38
|
@@ -22,6 +22,7 @@ interface SelectControlStateSpec extends ValueNodeStateSpec<readonly string[]> {
|
|
|
22
22
|
readonly label: Accessor<TextRange<'label'> | null>;
|
|
23
23
|
readonly hint: Accessor<TextRange<'hint'> | null>;
|
|
24
24
|
readonly valueOptions: Accessor<SelectValueOptions>;
|
|
25
|
+
readonly isSelectWithImages: Accessor<boolean>;
|
|
25
26
|
}
|
|
26
27
|
export declare class SelectControl extends ValueNode<'string', SelectDefinition<'string'>, readonly string[], readonly string[]> implements SelectNode, XFormsXPathElement, EvaluationContext, ValidationContext, ClientReactiveSerializableValueNode {
|
|
27
28
|
static from(parent: GeneralParentNode, instanceNode: StaticLeafElement | null, definition: SelectDefinition): SelectControl;
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
import { JRResourceURL } from '../../../../common/src/jr-resources/JRResourceURL.ts';
|
|
1
2
|
import { TextRange as ClientTextRange, TextChunk, TextOrigin, TextRole } from '../../client/TextRange.ts';
|
|
3
|
+
export interface MediaSources {
|
|
4
|
+
image?: JRResourceURL;
|
|
5
|
+
video?: JRResourceURL;
|
|
6
|
+
audio?: JRResourceURL;
|
|
7
|
+
}
|
|
2
8
|
export declare class TextRange<Role extends TextRole, Origin extends TextOrigin> implements ClientTextRange<Role, Origin> {
|
|
3
9
|
readonly origin: Origin;
|
|
4
10
|
readonly role: Role;
|
|
5
11
|
protected readonly chunks: readonly TextChunk[];
|
|
12
|
+
protected readonly mediaSources?: MediaSources | undefined;
|
|
6
13
|
[Symbol.iterator](): Generator<TextChunk, void, unknown>;
|
|
7
14
|
get formatted(): Record<PropertyKey, unknown>;
|
|
8
15
|
get asString(): string;
|
|
9
|
-
|
|
16
|
+
get imageSource(): JRResourceURL | undefined;
|
|
17
|
+
get audioSource(): JRResourceURL | undefined;
|
|
18
|
+
get videoSource(): JRResourceURL | undefined;
|
|
19
|
+
constructor(origin: Origin, role: Role, chunks: readonly TextChunk[], mediaSources?: MediaSources | undefined);
|
|
10
20
|
}
|
|
@@ -5,8 +5,7 @@ import { TextRange } from '../../../instance/text/TextRange.ts';
|
|
|
5
5
|
import { TextRangeDefinition } from '../../../parse/text/abstract/TextRangeDefinition.ts';
|
|
6
6
|
type ComputedFormTextRange<Role extends TextRole> = Accessor<TextRange<Role, 'form'>>;
|
|
7
7
|
/**
|
|
8
|
-
* Creates a text range (e.g. label or hint) from the provided definition,
|
|
9
|
-
* reactive to:
|
|
8
|
+
* Creates a text range (e.g. label or hint) from the provided definition, reactive to:
|
|
10
9
|
*
|
|
11
10
|
* - The form's current language (e.g. `<label ref="jr:itext('text-id')" />`)
|
|
12
11
|
* - Direct `<output>` references within the label's children
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TextChunkSource } from '../../client/TextRange.ts';
|
|
2
|
+
import { AnyTextRangeDefinition } from '../text/abstract/TextRangeDefinition.ts';
|
|
3
|
+
import { DependentExpression } from './abstract/DependentExpression.ts';
|
|
4
|
+
interface TextChunkExpressionOptions {
|
|
5
|
+
readonly isTranslated?: true;
|
|
6
|
+
}
|
|
7
|
+
export declare class TextChunkExpression<T extends 'nodes' | 'string'> extends DependentExpression<T> {
|
|
8
|
+
readonly source: TextChunkSource;
|
|
9
|
+
readonly stringValue: string;
|
|
10
|
+
constructor(context: AnyTextRangeDefinition, resultType: T, expression: string, source: TextChunkSource, options?: TextChunkExpressionOptions, literalValue?: string);
|
|
11
|
+
static fromLiteral(context: AnyTextRangeDefinition, stringValue: string): TextChunkExpression<'string'>;
|
|
12
|
+
static fromReference(context: AnyTextRangeDefinition, ref: string): TextChunkExpression<'string'>;
|
|
13
|
+
static fromOutput(context: AnyTextRangeDefinition, element: Element): TextChunkExpression<'string'> | null;
|
|
14
|
+
static fromTranslation(context: AnyTextRangeDefinition, maybeExpression: string): TextChunkExpression<'nodes'> | null;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -15,7 +15,7 @@ import { ModelDefinition } from '../model/ModelDefinition.ts';
|
|
|
15
15
|
* @todo Aside from this being a hack, it's not very robust because it makes
|
|
16
16
|
* assumptions which are _likely but definitely not guaranteed_!
|
|
17
17
|
*
|
|
18
|
-
* - Instance XML (probably)
|
|
18
|
+
* - Instance XML (probably) doesn't declare a default namespace
|
|
19
19
|
* - Instance XML **definitely** declares non-default namespaces
|
|
20
20
|
*/
|
|
21
21
|
export declare const parseInstanceXML: (model: ModelDefinition, instanceXML: string) => StaticDocument;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { XFormDefinition } from '../../parse/XFormDefinition.ts';
|
|
2
|
-
import { ItemDefinition } from '../body/control/ItemDefinition.ts';
|
|
3
2
|
import { ItemsetDefinition } from '../body/control/ItemsetDefinition.ts';
|
|
4
|
-
import {
|
|
3
|
+
import { TextChunkExpression } from '../expression/TextChunkExpression.ts';
|
|
5
4
|
import { TextRangeDefinition } from './abstract/TextRangeDefinition.ts';
|
|
6
|
-
export type ItemLabelOwner = ItemDefinition | ItemsetDefinition;
|
|
7
5
|
export declare class ItemsetLabelDefinition extends TextRangeDefinition<'item-label'> {
|
|
8
6
|
static from(form: XFormDefinition, owner: ItemsetDefinition): ItemsetLabelDefinition | null;
|
|
9
7
|
readonly role = "item-label";
|
|
10
|
-
readonly chunks:
|
|
8
|
+
readonly chunks: ReadonlyArray<TextChunkExpression<'nodes' | 'string'>>;
|
|
11
9
|
private constructor();
|
|
12
10
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { TextTranslationExpression } from '../expression/TextTranslationExpression.ts';
|
|
1
|
+
import { TextChunkExpression } from '../expression/TextChunkExpression.ts';
|
|
3
2
|
import { BindDefinition } from '../model/BindDefinition.ts';
|
|
4
|
-
import { TextBindAttributeLocalName,
|
|
5
|
-
export type MessageSourceNode = TextSourceNode<TextBindAttributeLocalName>;
|
|
6
|
-
type MessageChunk = TextLiteralExpression | TextTranslationExpression;
|
|
3
|
+
import { TextBindAttributeLocalName, TextRangeDefinition } from './abstract/TextRangeDefinition.ts';
|
|
7
4
|
export declare class MessageDefinition<Type extends TextBindAttributeLocalName> extends TextRangeDefinition<Type> {
|
|
8
5
|
readonly role: Type;
|
|
9
6
|
static from<Type extends TextBindAttributeLocalName>(bind: BindDefinition, type: Type): MessageDefinition<Type> | null;
|
|
10
|
-
readonly chunks:
|
|
7
|
+
readonly chunks: ReadonlyArray<TextChunkExpression<'nodes' | 'string'>>;
|
|
11
8
|
private constructor();
|
|
12
9
|
}
|
|
13
10
|
export type AnyMessageDefinition = MessageDefinition<TextBindAttributeLocalName>;
|
|
14
|
-
export {};
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import { ElementTextRole } from '../../../client/TextRange.ts';
|
|
2
2
|
import { XFormDefinition } from '../../../parse/XFormDefinition.ts';
|
|
3
3
|
import { ItemDefinition } from '../../body/control/ItemDefinition.ts';
|
|
4
|
-
import {
|
|
5
|
-
import { TextOutputExpression } from '../../expression/TextOutputExpression.ts';
|
|
6
|
-
import { TextReferenceExpression } from '../../expression/TextReferenceExpression.ts';
|
|
7
|
-
import { TextTranslationExpression } from '../../expression/TextTranslationExpression.ts';
|
|
4
|
+
import { TextChunkExpression } from '../../expression/TextChunkExpression.ts';
|
|
8
5
|
import { HintDefinition } from '../HintDefinition.ts';
|
|
9
6
|
import { ItemLabelDefinition } from '../ItemLabelDefinition.ts';
|
|
10
7
|
import { ItemsetLabelDefinition } from '../ItemsetLabelDefinition.ts';
|
|
11
8
|
import { LabelDefinition, LabelOwner } from '../LabelDefinition.ts';
|
|
12
9
|
import { TextSourceNode, TextRangeDefinition } from './TextRangeDefinition.ts';
|
|
13
|
-
export type RefAttributeChunk = TextReferenceExpression | TextTranslationExpression;
|
|
14
|
-
type TextElementChildChunk = TextLiteralExpression | TextOutputExpression;
|
|
15
|
-
type TextElementChunks = readonly [RefAttributeChunk] | readonly TextElementChildChunk[];
|
|
16
10
|
type TextElementOwner = ItemDefinition | LabelOwner;
|
|
17
11
|
export declare abstract class TextElementDefinition<Role extends ElementTextRole> extends TextRangeDefinition<Role> {
|
|
18
|
-
readonly chunks:
|
|
12
|
+
readonly chunks: ReadonlyArray<TextChunkExpression<'nodes' | 'string'>>;
|
|
19
13
|
constructor(form: XFormDefinition, owner: TextElementOwner, sourceNode: TextSourceNode<Role>);
|
|
20
14
|
}
|
|
21
15
|
export type AnyTextElementDefinition = HintDefinition | ItemLabelDefinition | ItemsetLabelDefinition | LabelDefinition;
|
|
@@ -2,7 +2,7 @@ import { LocalNamedElement } from '../../../../../common/types/dom.ts';
|
|
|
2
2
|
import { TextRole } from '../../../client/TextRange.ts';
|
|
3
3
|
import { XFormDefinition } from '../../../parse/XFormDefinition.ts';
|
|
4
4
|
import { DependencyContext } from '../../expression/abstract/DependencyContext.ts';
|
|
5
|
-
import {
|
|
5
|
+
import { TextChunkExpression } from '../../expression/TextChunkExpression.ts';
|
|
6
6
|
import { AnyMessageDefinition } from '../MessageDefinition.ts';
|
|
7
7
|
import { AnyTextElementDefinition } from './TextElementDefinition.ts';
|
|
8
8
|
export type TextBindAttributeLocalName = 'constraintMsg' | 'requiredMsg';
|
|
@@ -22,7 +22,7 @@ export declare abstract class TextRangeDefinition<Role extends TextRole> extends
|
|
|
22
22
|
abstract readonly role: Role;
|
|
23
23
|
readonly parentReference: string | null;
|
|
24
24
|
readonly reference: string | null;
|
|
25
|
-
abstract readonly chunks:
|
|
25
|
+
abstract readonly chunks: ReadonlyArray<TextChunkExpression<'nodes' | 'string'>>;
|
|
26
26
|
get isTranslated(): boolean;
|
|
27
27
|
set isTranslated(value: true);
|
|
28
28
|
protected constructor(form: XFormDefinition, ownerContext: DependencyContext, sourceNode: TextSourceNode<Role>);
|
package/dist/solid.js
CHANGED
|
@@ -67,37 +67,17 @@ const formResourceMetadata = (resource) => {
|
|
|
67
67
|
rawData: null
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
|
-
return
|
|
71
|
-
description: "Raw string data",
|
|
72
|
-
rawData: resource
|
|
73
|
-
};
|
|
70
|
+
return;
|
|
74
71
|
};
|
|
75
72
|
class LoadFormFailureError extends AggregateError {
|
|
76
73
|
constructor(resource, errors) {
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
...errors.map((error) => {
|
|
82
|
-
const aggregatedMessage = error.message;
|
|
83
|
-
if (aggregatedMessage == null) {
|
|
84
|
-
return "- Unknown error";
|
|
85
|
-
}
|
|
86
|
-
return `- ${aggregatedMessage}`;
|
|
87
|
-
})
|
|
88
|
-
];
|
|
89
|
-
if (rawData != null) {
|
|
90
|
-
messageLines.push("\n- - -\n", "Raw resource data:", rawData);
|
|
91
|
-
}
|
|
92
|
-
const message = messageLines.join("\n");
|
|
74
|
+
const metadata = formResourceMetadata(resource);
|
|
75
|
+
const errorMessages = errors.map((error) => error.message || "Unknown error").join("\n");
|
|
76
|
+
const message = metadata?.description ? `Form source: ${metadata.description}
|
|
77
|
+
${errorMessages}` : errorMessages;
|
|
93
78
|
super(errors, message);
|
|
94
79
|
const [head, ...tail] = errors;
|
|
95
|
-
|
|
96
|
-
const { stack } = head;
|
|
97
|
-
if (typeof stack === "string") {
|
|
98
|
-
this.stack = stack;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
80
|
+
this.stack = typeof head?.stack === "string" && !tail.length ? head.stack : "No error trace available.";
|
|
101
81
|
}
|
|
102
82
|
}
|
|
103
83
|
|
|
@@ -9402,7 +9382,7 @@ const substring = new StringFunction(
|
|
|
9402
9382
|
return string2.substring(start, end);
|
|
9403
9383
|
}
|
|
9404
9384
|
);
|
|
9405
|
-
const string$
|
|
9385
|
+
const string$1 = new StringFunction(
|
|
9406
9386
|
"string",
|
|
9407
9387
|
[{ arityType: "optional" }],
|
|
9408
9388
|
(context, [expression]) => (expression?.evaluate(context) ?? context).toString()
|
|
@@ -9435,13 +9415,13 @@ const translate = new StringFunction(
|
|
|
9435
9415
|
}
|
|
9436
9416
|
);
|
|
9437
9417
|
|
|
9438
|
-
const string$
|
|
9418
|
+
const string$2 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
9439
9419
|
__proto__: null,
|
|
9440
9420
|
concat: concat$1,
|
|
9441
9421
|
contains,
|
|
9442
9422
|
normalizeSpace,
|
|
9443
9423
|
startsWith,
|
|
9444
|
-
string: string$
|
|
9424
|
+
string: string$1,
|
|
9445
9425
|
stringLength,
|
|
9446
9426
|
substring,
|
|
9447
9427
|
substringAfter,
|
|
@@ -9453,7 +9433,7 @@ const fn$2 = new FunctionLibrary(FN_NAMESPACE_URI, [
|
|
|
9453
9433
|
...Object.values(boolean$2),
|
|
9454
9434
|
...Object.values(nodeset$1),
|
|
9455
9435
|
...Object.values(number$3),
|
|
9456
|
-
...Object.values(string$
|
|
9436
|
+
...Object.values(string$2)
|
|
9457
9437
|
]);
|
|
9458
9438
|
|
|
9459
9439
|
class BaseStep {
|
|
@@ -11233,21 +11213,21 @@ const enk = new FunctionLibrary(ENKETO_NAMESPACE_URI, [
|
|
|
11233
11213
|
new FunctionAlias("format-date", formatDateTime)
|
|
11234
11214
|
]);
|
|
11235
11215
|
|
|
11236
|
-
const itext = new
|
|
11216
|
+
const itext = new NodeSetFunction(
|
|
11237
11217
|
"itext",
|
|
11238
11218
|
[{ arityType: "required", typeHint: "string" }],
|
|
11239
11219
|
(context, [itextIDExpression]) => {
|
|
11240
11220
|
const itextID = itextIDExpression.evaluate(context).toString();
|
|
11241
|
-
return XFormsXPathEvaluator.
|
|
11221
|
+
return XFormsXPathEvaluator.getTranslationValues(context, itextID) ?? [];
|
|
11242
11222
|
}
|
|
11243
11223
|
);
|
|
11244
11224
|
|
|
11245
|
-
const
|
|
11225
|
+
const nodeSet = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
11246
11226
|
__proto__: null,
|
|
11247
11227
|
itext
|
|
11248
11228
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
11249
11229
|
|
|
11250
|
-
const jr$2 = new FunctionLibrary(JAVAROSA_NAMESPACE_URI, [...Object.values(
|
|
11230
|
+
const jr$2 = new FunctionLibrary(JAVAROSA_NAMESPACE_URI, [...Object.values(nodeSet)]);
|
|
11251
11231
|
|
|
11252
11232
|
const booleanFromString = new BooleanFunction(
|
|
11253
11233
|
"boolean-from-string",
|
|
@@ -18950,46 +18930,39 @@ class XFormsItextTranslations {
|
|
|
18950
18930
|
return textMap.get(itextID) ?? null;
|
|
18951
18931
|
}
|
|
18952
18932
|
/**
|
|
18933
|
+
* Retrieves all translation value elements for a given Itext in the active language.
|
|
18934
|
+
*
|
|
18953
18935
|
* @package
|
|
18954
18936
|
*
|
|
18955
|
-
*
|
|
18956
|
-
*
|
|
18937
|
+
* This method fetches the `text` element matching `itextID` and returns its child `value` elements,
|
|
18938
|
+
* which may have an optional `@form` attribute.
|
|
18939
|
+
*
|
|
18940
|
+
* The operation is conceptually similar to the following XPath query:
|
|
18957
18941
|
*
|
|
18958
18942
|
* ```xpath
|
|
18959
|
-
*
|
|
18960
|
-
*
|
|
18961
|
-
* xpath3-fn:environment-variable('activeLanguage')
|
|
18962
|
-
* )
|
|
18963
|
-
* /text[@id = $itextID]
|
|
18964
|
-
* /value[not(@form)]
|
|
18943
|
+
* imaginary:itext-translation(
|
|
18944
|
+
* xpath3-fn:environment-variable('activeLanguage')
|
|
18965
18945
|
* )
|
|
18946
|
+
* /text[@id = $itextID]
|
|
18947
|
+
* /value
|
|
18966
18948
|
* ```
|
|
18967
18949
|
*
|
|
18968
18950
|
* Or alternately:
|
|
18969
18951
|
*
|
|
18970
18952
|
* ```xpath
|
|
18971
|
-
*
|
|
18972
|
-
*
|
|
18973
|
-
* /
|
|
18974
|
-
* /
|
|
18975
|
-
* /value[not(@form)]
|
|
18976
|
-
* )
|
|
18953
|
+
* imaginary:itext-root()
|
|
18954
|
+
* /translation[@lang = xpath3-fn:environment-variable('activeLanguage')]
|
|
18955
|
+
* /text[@id = $itextID]
|
|
18956
|
+
* /value
|
|
18977
18957
|
* ```
|
|
18978
|
-
*
|
|
18979
|
-
* @todo The above really feels like it adds some helpful clarity to how `jr:itext()` is designed to work, and the kinds of structures, state and input involved. Since there's already some discomfort around that API as specified, it's worth considering
|
|
18958
|
+
* Returns an array of `XFormsItextTranslationValueElement<T>`
|
|
18980
18959
|
*/
|
|
18981
|
-
|
|
18960
|
+
getTranslationValues(itextID) {
|
|
18982
18961
|
const textElement = this.getTranslationTextElement(itextID);
|
|
18983
18962
|
if (textElement == null) {
|
|
18984
|
-
return
|
|
18985
|
-
}
|
|
18986
|
-
const { domProvider } = this;
|
|
18987
|
-
for (const valueElement of domProvider.getChildrenByLocalName(textElement, "value")) {
|
|
18988
|
-
if (!domProvider.hasLocalNamedAttribute(valueElement, "form")) {
|
|
18989
|
-
return domProvider.getNodeValue(valueElement);
|
|
18990
|
-
}
|
|
18963
|
+
return [];
|
|
18991
18964
|
}
|
|
18992
|
-
return "";
|
|
18965
|
+
return [...this.domProvider.getChildrenByLocalName(textElement, "value")];
|
|
18993
18966
|
}
|
|
18994
18967
|
getLanguages() {
|
|
18995
18968
|
return this.languages;
|
|
@@ -19026,9 +18999,9 @@ class XFormsXPathEvaluator extends Evaluator {
|
|
|
19026
18999
|
assertInternalXFormsXPathEvaluatorContext(context);
|
|
19027
19000
|
return context.evaluator.secondaryInstancesById.get(id) ?? null;
|
|
19028
19001
|
}
|
|
19029
|
-
static
|
|
19002
|
+
static getTranslationValues(context, itextID) {
|
|
19030
19003
|
assertInternalXFormsXPathEvaluatorContext(context);
|
|
19031
|
-
return context.evaluator.itextTranslations.
|
|
19004
|
+
return context.evaluator.itextTranslations.getTranslationValues(itextID);
|
|
19032
19005
|
}
|
|
19033
19006
|
rootNode;
|
|
19034
19007
|
/**
|
|
@@ -19582,8 +19555,13 @@ const isTranslationFunctionCall = (syntaxNode) => {
|
|
|
19582
19555
|
]);
|
|
19583
19556
|
};
|
|
19584
19557
|
const isTranslationExpression = (expression) => {
|
|
19585
|
-
|
|
19586
|
-
|
|
19558
|
+
let result;
|
|
19559
|
+
try {
|
|
19560
|
+
result = expressionParser.parse(expression);
|
|
19561
|
+
} catch {
|
|
19562
|
+
return false;
|
|
19563
|
+
}
|
|
19564
|
+
const functionCallNode = findTypedPrincipalExpressionNode(["function_call"], result.rootNode);
|
|
19587
19565
|
if (functionCallNode == null) {
|
|
19588
19566
|
return false;
|
|
19589
19567
|
}
|
|
@@ -19747,77 +19725,43 @@ class DependentExpression {
|
|
|
19747
19725
|
}
|
|
19748
19726
|
}
|
|
19749
19727
|
|
|
19728
|
+
const isOutputElement = (element) => {
|
|
19729
|
+
return element.localName === "output" && element.hasAttribute("value");
|
|
19730
|
+
};
|
|
19750
19731
|
class TextChunkExpression extends DependentExpression {
|
|
19732
|
+
source;
|
|
19733
|
+
// Set for the literal source, blank otherwise
|
|
19751
19734
|
stringValue;
|
|
19752
|
-
constructor(context, expression, options = {}) {
|
|
19753
|
-
super(context,
|
|
19735
|
+
constructor(context, resultType, expression, source, options = {}, literalValue = "") {
|
|
19736
|
+
super(context, resultType, expression, {
|
|
19754
19737
|
semanticDependencies: {
|
|
19755
19738
|
translations: options.isTranslated
|
|
19756
19739
|
},
|
|
19757
19740
|
ignoreContextReference: true
|
|
19758
19741
|
});
|
|
19742
|
+
this.source = source;
|
|
19743
|
+
this.stringValue = literalValue;
|
|
19759
19744
|
}
|
|
19760
|
-
|
|
19761
|
-
|
|
19762
|
-
class TextLiteralExpression extends TextChunkExpression {
|
|
19763
|
-
constructor(context, stringValue) {
|
|
19764
|
-
super(context, "null");
|
|
19765
|
-
this.stringValue = stringValue;
|
|
19766
|
-
}
|
|
19767
|
-
static from(context, stringValue) {
|
|
19768
|
-
return new this(context, stringValue);
|
|
19769
|
-
}
|
|
19770
|
-
source = "literal";
|
|
19771
|
-
}
|
|
19772
|
-
|
|
19773
|
-
const isOutputElement = (element) => {
|
|
19774
|
-
return element.localName === "output" && element.hasAttribute("value");
|
|
19775
|
-
};
|
|
19776
|
-
class TextOutputExpression extends TextChunkExpression {
|
|
19777
|
-
static from(context, element) {
|
|
19778
|
-
if (isOutputElement(element)) {
|
|
19779
|
-
return new this(context, element);
|
|
19780
|
-
}
|
|
19781
|
-
return null;
|
|
19782
|
-
}
|
|
19783
|
-
source = "output";
|
|
19784
|
-
constructor(context, element) {
|
|
19785
|
-
super(context, element.getAttribute("value"));
|
|
19745
|
+
static fromLiteral(context, stringValue) {
|
|
19746
|
+
return new TextChunkExpression(context, "string", "null", "literal", {}, stringValue);
|
|
19786
19747
|
}
|
|
19787
|
-
|
|
19788
|
-
|
|
19789
|
-
class TextReferenceExpression extends TextChunkExpression {
|
|
19790
|
-
static from(context, refExpression) {
|
|
19791
|
-
return new this(context, refExpression);
|
|
19748
|
+
static fromReference(context, ref) {
|
|
19749
|
+
return new TextChunkExpression(context, "string", ref, "reference");
|
|
19792
19750
|
}
|
|
19793
|
-
|
|
19794
|
-
|
|
19795
|
-
super(context, refExpression);
|
|
19796
|
-
}
|
|
19797
|
-
}
|
|
19798
|
-
|
|
19799
|
-
class TextTranslationExpression extends TextChunkExpression {
|
|
19800
|
-
static fromMessage(context, maybeExpression) {
|
|
19801
|
-
try {
|
|
19802
|
-
expressionParser.parse(maybeExpression);
|
|
19803
|
-
} catch {
|
|
19751
|
+
static fromOutput(context, element) {
|
|
19752
|
+
if (!isOutputElement(element)) {
|
|
19804
19753
|
return null;
|
|
19805
19754
|
}
|
|
19806
|
-
|
|
19807
|
-
return new this(context, maybeExpression);
|
|
19808
|
-
}
|
|
19809
|
-
return null;
|
|
19755
|
+
return new TextChunkExpression(context, "string", element.getAttribute("value"), "output");
|
|
19810
19756
|
}
|
|
19811
|
-
static
|
|
19757
|
+
static fromTranslation(context, maybeExpression) {
|
|
19812
19758
|
if (isTranslationExpression(maybeExpression)) {
|
|
19813
|
-
return new
|
|
19759
|
+
return new TextChunkExpression(context, "nodes", maybeExpression, "translation", {
|
|
19760
|
+
isTranslated: true
|
|
19761
|
+
});
|
|
19814
19762
|
}
|
|
19815
19763
|
return null;
|
|
19816
19764
|
}
|
|
19817
|
-
source = "translation";
|
|
19818
|
-
constructor(context, expression) {
|
|
19819
|
-
super(context, expression, { isTranslated: true });
|
|
19820
|
-
}
|
|
19821
19765
|
}
|
|
19822
19766
|
|
|
19823
19767
|
const absolutePathNodeList = (pathNode) => {
|
|
@@ -20066,16 +20010,20 @@ class TextElementDefinition extends TextRangeDefinition {
|
|
|
20066
20010
|
if (refExpression == null) {
|
|
20067
20011
|
this.chunks = Array.from(sourceNode.childNodes).flatMap((childNode) => {
|
|
20068
20012
|
if (isElementNode(childNode)) {
|
|
20069
|
-
return
|
|
20013
|
+
return TextChunkExpression.fromOutput(context, childNode) ?? [];
|
|
20070
20014
|
}
|
|
20071
20015
|
if (isTextNode(childNode)) {
|
|
20072
|
-
return
|
|
20016
|
+
return TextChunkExpression.fromLiteral(context, childNode.data);
|
|
20073
20017
|
}
|
|
20074
20018
|
return [];
|
|
20075
20019
|
});
|
|
20076
20020
|
} else {
|
|
20077
|
-
const
|
|
20078
|
-
|
|
20021
|
+
const expression = TextChunkExpression.fromTranslation(context, refExpression);
|
|
20022
|
+
if (expression != null) {
|
|
20023
|
+
this.chunks = [expression];
|
|
20024
|
+
} else {
|
|
20025
|
+
this.chunks = [TextChunkExpression.fromReference(context, refExpression)];
|
|
20026
|
+
}
|
|
20079
20027
|
}
|
|
20080
20028
|
}
|
|
20081
20029
|
}
|
|
@@ -20327,8 +20275,12 @@ class ItemsetLabelDefinition extends TextRangeDefinition {
|
|
|
20327
20275
|
if (refExpression == null) {
|
|
20328
20276
|
throw new Error("<itemset><label> missing ref attribute");
|
|
20329
20277
|
}
|
|
20330
|
-
const
|
|
20331
|
-
|
|
20278
|
+
const expression = TextChunkExpression.fromTranslation(this, refExpression);
|
|
20279
|
+
if (expression != null) {
|
|
20280
|
+
this.chunks = [expression];
|
|
20281
|
+
} else {
|
|
20282
|
+
this.chunks = [TextChunkExpression.fromReference(this, refExpression)];
|
|
20283
|
+
}
|
|
20332
20284
|
}
|
|
20333
20285
|
}
|
|
20334
20286
|
|
|
@@ -21236,8 +21188,12 @@ class MessageDefinition extends TextRangeDefinition {
|
|
|
21236
21188
|
constructor(bind, role, message) {
|
|
21237
21189
|
super(bind.form, bind, null);
|
|
21238
21190
|
this.role = role;
|
|
21239
|
-
const
|
|
21240
|
-
|
|
21191
|
+
const expression = TextChunkExpression.fromTranslation(this, message);
|
|
21192
|
+
if (expression != null) {
|
|
21193
|
+
this.chunks = [expression];
|
|
21194
|
+
} else {
|
|
21195
|
+
this.chunks = [TextChunkExpression.fromLiteral(this, message)];
|
|
21196
|
+
}
|
|
21241
21197
|
}
|
|
21242
21198
|
static from(bind, type) {
|
|
21243
21199
|
const message = bind.bindElement.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, type);
|
|
@@ -27151,7 +27107,8 @@ const getWrappedInstanceRootElement = (xml) => {
|
|
|
27151
27107
|
return root;
|
|
27152
27108
|
};
|
|
27153
27109
|
const parseInstanceXML = (model, instanceXML) => {
|
|
27154
|
-
const
|
|
27110
|
+
const cleanedXML = instanceXML.replace(/<\?xml\s+[^?]*\?>\s*/, "");
|
|
27111
|
+
const wrappedXML = wrapInstanceXML(model, cleanedXML);
|
|
27155
27112
|
const root = getWrappedInstanceRootElement(wrappedXML);
|
|
27156
27113
|
return parseStaticDocumentFromDOMSubtree(root);
|
|
27157
27114
|
};
|
|
@@ -29122,10 +29079,11 @@ class TextChunk {
|
|
|
29122
29079
|
}
|
|
29123
29080
|
|
|
29124
29081
|
class TextRange {
|
|
29125
|
-
constructor(origin, role, chunks) {
|
|
29082
|
+
constructor(origin, role, chunks, mediaSources) {
|
|
29126
29083
|
this.origin = origin;
|
|
29127
29084
|
this.role = role;
|
|
29128
29085
|
this.chunks = chunks;
|
|
29086
|
+
this.mediaSources = mediaSources;
|
|
29129
29087
|
}
|
|
29130
29088
|
*[Symbol.iterator]() {
|
|
29131
29089
|
yield* this.chunks;
|
|
@@ -29136,44 +29094,56 @@ class TextRange {
|
|
|
29136
29094
|
get asString() {
|
|
29137
29095
|
return this.chunks.map((chunk) => chunk.asString).join("");
|
|
29138
29096
|
}
|
|
29097
|
+
get imageSource() {
|
|
29098
|
+
return this.mediaSources?.image;
|
|
29099
|
+
}
|
|
29100
|
+
get audioSource() {
|
|
29101
|
+
return this.mediaSources?.audio;
|
|
29102
|
+
}
|
|
29103
|
+
get videoSource() {
|
|
29104
|
+
return this.mediaSources?.video;
|
|
29105
|
+
}
|
|
29139
29106
|
}
|
|
29140
29107
|
|
|
29141
|
-
const
|
|
29142
|
-
|
|
29143
|
-
|
|
29144
|
-
const
|
|
29145
|
-
|
|
29146
|
-
source
|
|
29147
|
-
|
|
29148
|
-
|
|
29149
|
-
|
|
29150
|
-
|
|
29151
|
-
|
|
29152
|
-
|
|
29153
|
-
|
|
29154
|
-
|
|
29155
|
-
|
|
29156
|
-
|
|
29157
|
-
|
|
29158
|
-
|
|
29159
|
-
|
|
29160
|
-
|
|
29161
|
-
|
|
29162
|
-
|
|
29163
|
-
|
|
29164
|
-
|
|
29165
|
-
|
|
29166
|
-
|
|
29167
|
-
|
|
29168
|
-
|
|
29108
|
+
const createTextChunks = (context, chunkExpressions) => {
|
|
29109
|
+
return createMemo(() => {
|
|
29110
|
+
const chunks = [];
|
|
29111
|
+
const mediaSources = {};
|
|
29112
|
+
chunkExpressions.forEach((chunkExpression) => {
|
|
29113
|
+
if (chunkExpression.source === "literal") {
|
|
29114
|
+
chunks.push(new TextChunk(context, chunkExpression.source, chunkExpression.stringValue));
|
|
29115
|
+
return;
|
|
29116
|
+
}
|
|
29117
|
+
const computed = createComputedExpression(context, chunkExpression)();
|
|
29118
|
+
if (typeof computed === "string") {
|
|
29119
|
+
chunks.push(new TextChunk(context, chunkExpression.source, computed));
|
|
29120
|
+
return;
|
|
29121
|
+
} else {
|
|
29122
|
+
computed.forEach((itextForm) => {
|
|
29123
|
+
if (isEngineXPathElement(itextForm) && itextForm instanceof StaticElement) {
|
|
29124
|
+
const formAttribute = itextForm.getAttributeValue("form");
|
|
29125
|
+
if (!formAttribute) {
|
|
29126
|
+
const defaultFormValue = itextForm.getXPathValue();
|
|
29127
|
+
chunks.push(new TextChunk(context, chunkExpression.source, defaultFormValue));
|
|
29128
|
+
} else if (["image", "video", "audio"].includes(formAttribute)) {
|
|
29129
|
+
const formValue = itextForm.getXPathValue();
|
|
29130
|
+
if (JRResourceURL.isJRResourceReference(formValue)) {
|
|
29131
|
+
mediaSources[formAttribute] = JRResourceURL.from(formValue);
|
|
29132
|
+
}
|
|
29133
|
+
}
|
|
29134
|
+
}
|
|
29135
|
+
});
|
|
29136
|
+
}
|
|
29169
29137
|
});
|
|
29138
|
+
return { chunks, mediaSources };
|
|
29170
29139
|
});
|
|
29171
29140
|
};
|
|
29172
29141
|
const createTextRange = (context, role, definition) => {
|
|
29173
29142
|
return context.scope.runTask(() => {
|
|
29174
|
-
const
|
|
29143
|
+
const textChunks = createTextChunks(context, definition.chunks);
|
|
29175
29144
|
return createMemo(() => {
|
|
29176
|
-
|
|
29145
|
+
const chunks = textChunks();
|
|
29146
|
+
return new TextRange("form", role, chunks.chunks, chunks.mediaSources);
|
|
29177
29147
|
});
|
|
29178
29148
|
});
|
|
29179
29149
|
};
|
|
@@ -29340,8 +29310,7 @@ const createInstanceValueState = (context) => {
|
|
|
29340
29310
|
const engineViolationMessage = (context, role) => {
|
|
29341
29311
|
const messageText = VALIDATION_TEXT[role];
|
|
29342
29312
|
const chunk = new TextChunk(context, "literal", messageText);
|
|
29343
|
-
|
|
29344
|
-
return () => message;
|
|
29313
|
+
return () => new TextRange("engine", role, [chunk]);
|
|
29345
29314
|
};
|
|
29346
29315
|
const createViolationMessage = (context, role, definition) => {
|
|
29347
29316
|
if (definition == null) {
|
|
@@ -30518,6 +30487,9 @@ class SelectControl extends ValueNode {
|
|
|
30518
30487
|
this.appearances = definition.bodyElement.appearances;
|
|
30519
30488
|
this.selectType = definition.bodyElement.type;
|
|
30520
30489
|
const valueOptions = createItemCollection(this);
|
|
30490
|
+
const isSelectWithImages = this.scope.runTask(() => {
|
|
30491
|
+
return createMemo(() => valueOptions().some((item) => !!item.label.imageSource));
|
|
30492
|
+
});
|
|
30521
30493
|
const mapOptionsByValue = this.scope.runTask(() => {
|
|
30522
30494
|
return createMemo(() => {
|
|
30523
30495
|
return new Map(valueOptions().map((item) => [item.value, item]));
|
|
@@ -30552,7 +30524,8 @@ class SelectControl extends ValueNode {
|
|
|
30552
30524
|
children: null,
|
|
30553
30525
|
valueOptions,
|
|
30554
30526
|
value: valueState,
|
|
30555
|
-
instanceValue: this.getInstanceValue
|
|
30527
|
+
instanceValue: this.getInstanceValue,
|
|
30528
|
+
isSelectWithImages
|
|
30556
30529
|
},
|
|
30557
30530
|
this.instanceConfig
|
|
30558
30531
|
);
|