@jinntec/fore 1.0.0-3 → 1.0.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/README.md +25 -34
- package/dist/fore-dev.js +43 -0
- package/dist/fore-dev.js.map +1 -0
- package/dist/fore.js +36 -1
- package/dist/fore.js.map +1 -0
- package/index.js +3 -0
- package/package.json +34 -38
- package/resources/fore.css +35 -50
- package/src/DependencyNotifyingDomFacade.js +10 -16
- package/src/ForeElementMixin.js +25 -18
- package/src/actions/abstract-action.js +17 -9
- package/src/actions/fx-action.js +6 -4
- package/src/actions/fx-append.js +8 -17
- package/src/actions/fx-confirm.js +3 -1
- package/src/actions/fx-delete.js +6 -3
- package/src/actions/fx-dispatch.js +9 -8
- package/src/actions/fx-hide.js +10 -6
- package/src/actions/fx-insert.js +49 -39
- package/src/actions/fx-message.js +3 -1
- package/src/actions/fx-refresh.js +11 -1
- package/src/actions/fx-replace.js +68 -0
- package/src/actions/fx-return.js +42 -0
- package/src/actions/fx-send.js +3 -1
- package/src/actions/fx-setvalue.js +58 -51
- package/src/actions/fx-show.js +8 -4
- package/src/actions/fx-toggle.js +15 -10
- package/src/actions/fx-update.js +3 -1
- package/src/dep_graph.js +4 -2
- package/src/drawdown.js +67 -82
- package/src/fore.js +158 -11
- package/src/functions/fx-function.js +11 -3
- package/src/fx-bind.js +42 -202
- package/src/fx-fore.js +105 -70
- package/src/fx-header.js +3 -1
- package/src/fx-instance.js +9 -1
- package/src/fx-model.js +31 -23
- package/src/fx-submission.js +73 -47
- package/src/fx-var.js +7 -4
- package/src/getInScopeContext.js +37 -11
- package/src/modelitem.js +4 -4
- package/src/relevance.js +65 -0
- package/src/ui/abstract-control.js +55 -35
- package/src/ui/fx-alert.js +7 -1
- package/src/ui/fx-case.js +3 -1
- package/src/ui/fx-container.js +7 -1
- package/src/ui/fx-control.js +283 -33
- package/src/ui/fx-dialog.js +54 -40
- package/src/ui/fx-group.js +3 -1
- package/src/ui/fx-hint.js +4 -1
- package/src/ui/fx-inspector.js +117 -17
- package/src/ui/fx-items.js +8 -8
- package/src/ui/fx-output.js +14 -5
- package/src/ui/fx-repeat.js +33 -41
- package/src/ui/fx-repeatitem.js +10 -4
- package/src/ui/fx-switch.js +3 -1
- package/src/ui/fx-trigger.js +3 -1
- package/src/xpath-evaluation.js +121 -131
- package/src/xpath-util.js +14 -7
- package/dist/fore-all.js +0 -140
- package/src/.DS_Store +0 -0
- package/src/actions/.DS_Store +0 -0
- package/src/ui/.DS_Store +0 -0
package/src/xpath-evaluation.js
CHANGED
|
@@ -10,38 +10,14 @@ import {
|
|
|
10
10
|
registerCustomXPathFunction,
|
|
11
11
|
registerXQueryModule,
|
|
12
12
|
} from 'fontoxpath';
|
|
13
|
+
import { Fore } from './fore.js';
|
|
14
|
+
|
|
13
15
|
import { XPathUtil } from './xpath-util.js';
|
|
14
16
|
|
|
15
17
|
const XFORMS_NAMESPACE_URI = 'http://www.w3.org/2002/xforms';
|
|
16
18
|
|
|
17
19
|
const createdNamespaceResolversByXPathQueryAndNode = new Map();
|
|
18
20
|
|
|
19
|
-
function prettifyXml(source) {
|
|
20
|
-
const xmlDoc = new DOMParser().parseFromString(source, 'application/xml');
|
|
21
|
-
const xsltDoc = new DOMParser().parseFromString(
|
|
22
|
-
[
|
|
23
|
-
// describes how we want to modify the XML - indent everything
|
|
24
|
-
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">',
|
|
25
|
-
' <xsl:strip-space elements="*"/>',
|
|
26
|
-
' <xsl:template match="para[content-style][not(text())]">', // change to just text() to strip space in text nodes
|
|
27
|
-
' <xsl:value-of select="normalize-space(.)"/>',
|
|
28
|
-
' </xsl:template>',
|
|
29
|
-
' <xsl:template match="node()|@*">',
|
|
30
|
-
' <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>',
|
|
31
|
-
' </xsl:template>',
|
|
32
|
-
' <xsl:output indent="yes"/>',
|
|
33
|
-
'</xsl:stylesheet>',
|
|
34
|
-
].join('\n'),
|
|
35
|
-
'application/xml',
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const xsltProcessor = new XSLTProcessor();
|
|
39
|
-
xsltProcessor.importStylesheet(xsltDoc);
|
|
40
|
-
const resultDoc = xsltProcessor.transformToDocument(xmlDoc);
|
|
41
|
-
const resultXml = new XMLSerializer().serializeToString(resultDoc);
|
|
42
|
-
return resultXml;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
21
|
function getCachedNamespaceResolver(xpath, node) {
|
|
46
22
|
if (!createdNamespaceResolversByXPathQueryAndNode.has(xpath)) {
|
|
47
23
|
return null;
|
|
@@ -62,6 +38,103 @@ const xhtmlNamespaceResolver = prefix => {
|
|
|
62
38
|
return undefined;
|
|
63
39
|
};
|
|
64
40
|
|
|
41
|
+
export function resolveId(id, sourceObject, nodeName = null) {
|
|
42
|
+
const allMatchingTargetObjects = fxEvaluateXPathToNodes(
|
|
43
|
+
'outermost(ancestor-or-self::fx-fore[1]/(descendant::fx-fore|descendant::*[@id = $id]))[not(self::fx-fore)]',
|
|
44
|
+
sourceObject,
|
|
45
|
+
null,
|
|
46
|
+
{ id },
|
|
47
|
+
{ namespaceResolver: xhtmlNamespaceResolver },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (allMatchingTargetObjects.length === 0) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
allMatchingTargetObjects.length === 1 &&
|
|
56
|
+
fxEvaluateXPathToBoolean(
|
|
57
|
+
'(ancestor::fx-fore | ancestor::fx-repeat)[last()]/self::fx-fore',
|
|
58
|
+
allMatchingTargetObjects[0],
|
|
59
|
+
null,
|
|
60
|
+
null,
|
|
61
|
+
{ namespaceResolver: xhtmlNamespaceResolver },
|
|
62
|
+
)
|
|
63
|
+
) {
|
|
64
|
+
// If the target element is not repeated, then the search for the target object is trivial since
|
|
65
|
+
// there is only one associated with the target element that bears the matching ID. This is true
|
|
66
|
+
// regardless of whether or not the source object is repeated. However, if the target element is
|
|
67
|
+
// repeated, then additional information must be used to help select a target object from among
|
|
68
|
+
// those associated with the identified target element.
|
|
69
|
+
const targetObject = allMatchingTargetObjects[0];
|
|
70
|
+
if (nodeName && targetObject.localName !== nodeName) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return targetObject;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// SPEC:
|
|
77
|
+
|
|
78
|
+
// 12.2.1 References to Elements within a repeat Element
|
|
79
|
+
|
|
80
|
+
// When the target element that is identified by the IDREF of a source object has one or more
|
|
81
|
+
// repeat elements as ancestors, then the set of ancestor repeats are partitioned into two
|
|
82
|
+
// subsets, those in common with the source element and those that are not in common. Any ancestor
|
|
83
|
+
// repeat elements of the target element not in common with the source element are descendants of
|
|
84
|
+
// the repeat elements that the source and target element have in common, if any.
|
|
85
|
+
|
|
86
|
+
// For the repeat elements that are in common, the desired target object exists in the same set of
|
|
87
|
+
// run-time objects that contains the source object. Then, for each ancestor repeat of the target
|
|
88
|
+
// element that is not in common with the source element, the current index of the repeat
|
|
89
|
+
// determines the set of run-time objects that contains the desired target object.
|
|
90
|
+
for (const ancestorRepeatItem of fxEvaluateXPathToNodes(
|
|
91
|
+
'ancestor::fx-repeatitem => reverse()',
|
|
92
|
+
sourceObject,
|
|
93
|
+
null,
|
|
94
|
+
null,
|
|
95
|
+
{ namespaceResolver: xhtmlNamespaceResolver },
|
|
96
|
+
)) {
|
|
97
|
+
const foundTargetObjects = allMatchingTargetObjects.filter(to =>
|
|
98
|
+
ancestorRepeatItem.contains(to),
|
|
99
|
+
);
|
|
100
|
+
switch (foundTargetObjects.length) {
|
|
101
|
+
case 0:
|
|
102
|
+
// Nothing found: ignore
|
|
103
|
+
break;
|
|
104
|
+
case 1: {
|
|
105
|
+
// A single one is found: the target object is directly in a common repeat
|
|
106
|
+
const targetObject = foundTargetObjects[0];
|
|
107
|
+
if (nodeName && targetObject.localName !== nodeName) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return targetObject;
|
|
111
|
+
}
|
|
112
|
+
default: {
|
|
113
|
+
// Multiple target objects are found: they are in a repeat that is not common with the source object
|
|
114
|
+
// We found a target object in a common repeat! We now need to find the one that is in the repeatitem identified at the current index
|
|
115
|
+
const targetObject = foundTargetObjects.find(to =>
|
|
116
|
+
fxEvaluateXPathToNodes(
|
|
117
|
+
'every $ancestor of ancestor::fx-repeatitem satisfies $ancestor is $ancestor/../child::fx-repeatitem[../@repeat-index]',
|
|
118
|
+
to,
|
|
119
|
+
null,
|
|
120
|
+
{},
|
|
121
|
+
),
|
|
122
|
+
);
|
|
123
|
+
if (!targetObject) {
|
|
124
|
+
// Nothing valid found for whatever reason. This might be something dynamic?
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
if (nodeName && targetObject.localName !== nodeName) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return targetObject;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// We found no target objects in common repeats. The id is unresolvable
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
65
138
|
/**
|
|
66
139
|
* Resolve a namespace. Needs a namespace prefix and the element that is most closely related to the
|
|
67
140
|
* XPath in which the namespace is being resolved. The prefix will be resolved by using the
|
|
@@ -120,7 +193,7 @@ function createNamespaceResolver(xpathQuery, formElement) {
|
|
|
120
193
|
let instance;
|
|
121
194
|
if (instanceReferences[0] === 'default') {
|
|
122
195
|
const actualForeElement = fxEvaluateXPathToFirstNode(
|
|
123
|
-
'ancestor-or-self::fx-fore',
|
|
196
|
+
'ancestor-or-self::fx-fore[1]',
|
|
124
197
|
formElement,
|
|
125
198
|
null,
|
|
126
199
|
null,
|
|
@@ -187,6 +260,10 @@ function createNamespaceResolverForNode(query, contextNode, formElement) {
|
|
|
187
260
|
return createNamespaceResolver(query, formElement);
|
|
188
261
|
}
|
|
189
262
|
|
|
263
|
+
// A global registry of function names that are declared in Fore by a developer using the
|
|
264
|
+
// `fx-function` element. These should be available without providing a prefix as well
|
|
265
|
+
export const globallyDeclaredFunctionLocalNames = [];
|
|
266
|
+
|
|
190
267
|
/**
|
|
191
268
|
* Implementation of the functionNameResolver passed to FontoXPath to
|
|
192
269
|
* redirect function resolving for unprefixed functions to either the fn or the xf namespace
|
|
@@ -207,7 +284,12 @@ function functionNameResolver({ prefix, localName }, _arity) {
|
|
|
207
284
|
case 'logtree':
|
|
208
285
|
return { namespaceURI: XFORMS_NAMESPACE_URI, localName };
|
|
209
286
|
default:
|
|
210
|
-
if (prefix === ''
|
|
287
|
+
if (prefix === '' && globallyDeclaredFunctionLocalNames.includes(localName)) {
|
|
288
|
+
// The function has been declared without a prefix and is called here without a prefix.
|
|
289
|
+
// Just make this work. It is the developer-friendly way
|
|
290
|
+
return { namespaceURI: 'http://www.w3.org/2005/xquery-local-functions', localName };
|
|
291
|
+
}
|
|
292
|
+
if (prefix === 'fn') {
|
|
211
293
|
return { namespaceURI: 'http://www.w3.org/2005/xpath-functions', localName };
|
|
212
294
|
}
|
|
213
295
|
if (prefix === 'local') {
|
|
@@ -236,9 +318,11 @@ function getVariablesInScope(formElement) {
|
|
|
236
318
|
}
|
|
237
319
|
|
|
238
320
|
const variables = {};
|
|
239
|
-
|
|
240
|
-
const
|
|
241
|
-
|
|
321
|
+
if (closestActualFormElement.inScopeVariables) {
|
|
322
|
+
for (const key of closestActualFormElement.inScopeVariables.keys()) {
|
|
323
|
+
const varElement = closestActualFormElement.inScopeVariables.get(key);
|
|
324
|
+
variables[key] = varElement.value;
|
|
325
|
+
}
|
|
242
326
|
}
|
|
243
327
|
return variables;
|
|
244
328
|
}
|
|
@@ -260,7 +344,7 @@ export function evaluateXPath(xpath, contextNode, formElement, variables = {}) {
|
|
|
260
344
|
contextNode,
|
|
261
345
|
null,
|
|
262
346
|
{ ...variablesInScope, ...variables },
|
|
263
|
-
|
|
347
|
+
fxEvaluateXPath.ALL_RESULTS_TYPE,
|
|
264
348
|
{
|
|
265
349
|
currentContext: { formElement, variables },
|
|
266
350
|
moduleImports: {
|
|
@@ -438,102 +522,6 @@ export function evaluateXPathToNumber(
|
|
|
438
522
|
/**
|
|
439
523
|
* Resolve an id in scope. Behaves like the algorithm defined on https://www.w3.org/community/xformsusers/wiki/XForms_2.0#idref-resolve
|
|
440
524
|
*/
|
|
441
|
-
export function resolveId(id, sourceObject, nodeName = null) {
|
|
442
|
-
const allMatchingTargetObjects = fxEvaluateXPathToNodes(
|
|
443
|
-
'outermost(ancestor-or-self::fx-fore[1]/(descendant::xf-fore|descendant::*[@id = $id]))[not(self::fx-fore)]',
|
|
444
|
-
sourceObject,
|
|
445
|
-
null,
|
|
446
|
-
{ id },
|
|
447
|
-
{ namespaceResolver: xhtmlNamespaceResolver },
|
|
448
|
-
);
|
|
449
|
-
|
|
450
|
-
if (allMatchingTargetObjects.length === 0) {
|
|
451
|
-
return null;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (
|
|
455
|
-
allMatchingTargetObjects.length === 1 &&
|
|
456
|
-
fxEvaluateXPathToBoolean(
|
|
457
|
-
'(ancestor::fx-fore | ancestor::fx-repeat)[last()]/self::fx-fore',
|
|
458
|
-
allMatchingTargetObjects[0],
|
|
459
|
-
null,
|
|
460
|
-
null,
|
|
461
|
-
{ namespaceResolver: xhtmlNamespaceResolver },
|
|
462
|
-
)
|
|
463
|
-
) {
|
|
464
|
-
// If the target element is not repeated, then the search for the target object is trivial since
|
|
465
|
-
// there is only one associated with the target element that bears the matching ID. This is true
|
|
466
|
-
// regardless of whether or not the source object is repeated. However, if the target element is
|
|
467
|
-
// repeated, then additional information must be used to help select a target object from among
|
|
468
|
-
// those associated with the identified target element.
|
|
469
|
-
const targetObject = allMatchingTargetObjects[0];
|
|
470
|
-
if (nodeName && targetObject.localName !== nodeName) {
|
|
471
|
-
return null;
|
|
472
|
-
}
|
|
473
|
-
return targetObject;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// SPEC:
|
|
477
|
-
|
|
478
|
-
// 12.2.1 References to Elements within a repeat Element
|
|
479
|
-
|
|
480
|
-
// When the target element that is identified by the IDREF of a source object has one or more
|
|
481
|
-
// repeat elements as ancestors, then the set of ancestor repeats are partitioned into two
|
|
482
|
-
// subsets, those in common with the source element and those that are not in common. Any ancestor
|
|
483
|
-
// repeat elements of the target element not in common with the source element are descendants of
|
|
484
|
-
// the repeat elements that the source and target element have in common, if any.
|
|
485
|
-
|
|
486
|
-
// For the repeat elements that are in common, the desired target object exists in the same set of
|
|
487
|
-
// run-time objects that contains the source object. Then, for each ancestor repeat of the target
|
|
488
|
-
// element that is not in common with the source element, the current index of the repeat
|
|
489
|
-
// determines the set of run-time objects that contains the desired target object.
|
|
490
|
-
for (const ancestorRepeatItem of fxEvaluateXPathToNodes(
|
|
491
|
-
'ancestor::fx-repeatitem => reverse()',
|
|
492
|
-
sourceObject,
|
|
493
|
-
null,
|
|
494
|
-
null,
|
|
495
|
-
{ namespaceResolver: xhtmlNamespaceResolver },
|
|
496
|
-
)) {
|
|
497
|
-
const foundTargetObjects = allMatchingTargetObjects.filter(to =>
|
|
498
|
-
ancestorRepeatItem.contains(to),
|
|
499
|
-
);
|
|
500
|
-
switch (foundTargetObjects.length) {
|
|
501
|
-
case 0:
|
|
502
|
-
// Nothing found: ignore
|
|
503
|
-
break;
|
|
504
|
-
case 1: {
|
|
505
|
-
// A single one is found: the target object is directly in a common repeat
|
|
506
|
-
const targetObject = foundTargetObjects[0];
|
|
507
|
-
if (nodeName && targetObject.localName !== nodeName) {
|
|
508
|
-
return null;
|
|
509
|
-
}
|
|
510
|
-
return targetObject;
|
|
511
|
-
}
|
|
512
|
-
default: {
|
|
513
|
-
// Multiple target objects are found: they are in a repeat that is not common with the source object
|
|
514
|
-
// We found a target object in a common repeat! We now need to find the one that is in the repeatitem identified at the current index
|
|
515
|
-
const targetObject = foundTargetObjects.find(to =>
|
|
516
|
-
fxEvaluateXPathToNodes(
|
|
517
|
-
'every $ancestor of ancestor::fx-repeatitem satisfies $ancestor is $ancestor/../child::fx-repeatitem[../@repeat-index]',
|
|
518
|
-
to,
|
|
519
|
-
null,
|
|
520
|
-
{},
|
|
521
|
-
),
|
|
522
|
-
);
|
|
523
|
-
if (!targetObject) {
|
|
524
|
-
// Nothing valid found for whatever reason. This might be something dynamic?
|
|
525
|
-
return null;
|
|
526
|
-
}
|
|
527
|
-
if (nodeName && targetObject.localName !== nodeName) {
|
|
528
|
-
return null;
|
|
529
|
-
}
|
|
530
|
-
return targetObject;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
// We found no target objects in common repeats. The id is unresolvable
|
|
535
|
-
return null;
|
|
536
|
-
}
|
|
537
525
|
|
|
538
526
|
const contextFunction = (dynamicContext, string) => {
|
|
539
527
|
const caller = dynamicContext.currentContext.formElement;
|
|
@@ -553,7 +541,7 @@ const contextFunction = (dynamicContext, string) => {
|
|
|
553
541
|
}
|
|
554
542
|
}
|
|
555
543
|
const parent = XPathUtil.getParentBindingElement(caller);
|
|
556
|
-
const p = caller.nodeName;
|
|
544
|
+
// const p = caller.nodeName;
|
|
557
545
|
// const p = dynamicContext.domFacade.getParentElement();
|
|
558
546
|
|
|
559
547
|
if (parent) return parent;
|
|
@@ -599,7 +587,7 @@ registerCustomXPathFunction(
|
|
|
599
587
|
// return JSON.stringify(instance.getDefaultContext());
|
|
600
588
|
} else {
|
|
601
589
|
const def = new XMLSerializer().serializeToString(instance.getDefaultContext());
|
|
602
|
-
return prettifyXml(def);
|
|
590
|
+
return Fore.prettifyXml(def);
|
|
603
591
|
}
|
|
604
592
|
}
|
|
605
593
|
return null;
|
|
@@ -698,7 +686,7 @@ const instance = (dynamicContext, string) => {
|
|
|
698
686
|
// TODO: handle no string passed (null will be passed instead)
|
|
699
687
|
|
|
700
688
|
const formElement = fxEvaluateXPathToFirstNode(
|
|
701
|
-
'ancestor-or-self::fx-fore',
|
|
689
|
+
'ancestor-or-self::fx-fore[1]',
|
|
702
690
|
dynamicContext.currentContext.formElement,
|
|
703
691
|
null,
|
|
704
692
|
null,
|
|
@@ -771,6 +759,8 @@ registerCustomXPathFunction(
|
|
|
771
759
|
['xs:string?'],
|
|
772
760
|
'item()?',
|
|
773
761
|
(dynamicContext, arg) => {
|
|
762
|
+
if (!dynamicContext.currentContext.variables) return [];
|
|
763
|
+
if (!arg) return [];
|
|
774
764
|
const payload = dynamicContext.currentContext.variables[arg];
|
|
775
765
|
if (payload.nodeType) {
|
|
776
766
|
console.log('got some node as js object');
|
package/src/xpath-util.js
CHANGED
|
@@ -29,10 +29,6 @@ export class XPathUtil {
|
|
|
29
29
|
return path != null && (path.startsWith('/') || path.startsWith('instance('));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
static isRepeated(element) {
|
|
33
|
-
return element.parentElement.closest('fx-repeatitem');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
32
|
static isSelfReference(ref) {
|
|
37
33
|
return ref === '.' || ref === './text()' || ref === 'text()' || ref === '' || ref === null;
|
|
38
34
|
}
|
|
@@ -57,21 +53,32 @@ export class XPathUtil {
|
|
|
57
53
|
throw new Error('no Fore element present');
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
/**
|
|
57
|
+
* returns the instance id from a complete XPath using `instance()` function.
|
|
58
|
+
*
|
|
59
|
+
* Will return 'default' in case no ref is given at all or the `instance()` function is called without arg.
|
|
60
|
+
*
|
|
61
|
+
* Otherwise instance id is extracted from function and returned. If all fails null is returned.
|
|
62
|
+
* @param ref
|
|
63
|
+
* @returns {string}
|
|
64
|
+
*/
|
|
61
65
|
static getInstanceId(ref) {
|
|
62
66
|
if (!ref) {
|
|
63
67
|
return 'default';
|
|
64
68
|
}
|
|
69
|
+
if (ref.startsWith('instance()')) {
|
|
70
|
+
return 'default';
|
|
71
|
+
}
|
|
65
72
|
if (ref.startsWith('instance(')) {
|
|
66
73
|
const result = ref.substring(ref.indexOf('(') + 1);
|
|
67
74
|
return result.substring(1, result.indexOf(')') - 1);
|
|
68
75
|
}
|
|
69
|
-
return
|
|
76
|
+
return null;
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
// todo: certainly not ideal to rely on duplicating instance id on instance document - better way later ;)
|
|
73
80
|
static getPath(node) {
|
|
74
|
-
const path = fx.
|
|
81
|
+
const path = fx.evaluateXPathToString('path()', node);
|
|
75
82
|
/*
|
|
76
83
|
const instanceId = node.ownerDocument.firstElementChild.getAttribute('id');
|
|
77
84
|
if (instanceId !== null && instanceId !== 'default') {
|