@bpmn-io/form-js-viewer 1.24.0 → 1.24.1

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/index.cjs CHANGED
@@ -59,7 +59,26 @@ const getFlavouredFeelVariableNames = (feelString, feelFlavour = 'expression', o
59
59
  // if using special depth accessors, use a more complex extraction
60
60
  return Array.from(_smartExtractVariableNames(node, depth, specialDepthAccessors));
61
61
  }
62
- if (depth === 0 && node.name === 'VariableName') return [node.variableName];
62
+ if (depth === 0 && node.name === 'VariableName') return [_cleanupVariableName(node.variableName)];
63
+
64
+ // skip function names - the function name is the only direct VariableName child of a
65
+ // FunctionInvocation (arguments are nested under Positional/NamedParameters), so drop it
66
+ if (node.name === 'FunctionInvocation') {
67
+ const args = node.children.filter(child => child.name !== 'VariableName');
68
+ return args.reduce((acc, child) => acc.concat(_unfoldVariables(child)), []);
69
+ }
70
+
71
+ // skip type names in instance of expressions
72
+ if (node.name === 'Type') {
73
+ return [];
74
+ }
75
+
76
+ // handle quantified (some...satisfies) and for expressions - exclude bound iteration variables
77
+ if (node.name === 'QuantifiedExpression' || node.name === 'ForExpression') {
78
+ const boundNames = _collectBoundVariableNames(node);
79
+ const variables = node.children.reduce((acc, child) => acc.concat(_unfoldVariables(child)), []);
80
+ return variables.filter(name => !boundNames.includes(name));
81
+ }
63
82
 
64
83
  // for any other kind of node, traverse its children and flatten the result
65
84
  if (node.children) {
@@ -184,6 +203,9 @@ const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
184
203
  if (node.type.name === 'VariableName') {
185
204
  nodeRepresentation.variableName = feelString.slice(node.from, node.to);
186
205
  }
206
+ if (node.type.name === 'Name') {
207
+ nodeRepresentation.variableName = feelString.slice(node.from, node.to);
208
+ }
187
209
  stack.push(nodeRepresentation);
188
210
  },
189
211
  leave: () => {
@@ -233,6 +255,53 @@ const _extractFilterExpressions = tree => {
233
255
  return flattenedExpressionTree;
234
256
  };
235
257
 
258
+ /**
259
+ * FEEL keywords that may be incorrectly absorbed into variable names by the parser.
260
+ * For example, `variable1 not in (...)` parses as VariableName "variable1 not".
261
+ */
262
+ const FEEL_TRAILING_KEYWORDS = ['not'];
263
+
264
+ /**
265
+ * Cleans up a variable name by stripping trailing FEEL keywords that the parser
266
+ * may have incorrectly included as part of the variable name.
267
+ *
268
+ * @param {string} variableName - The raw variable name from the parse tree.
269
+ * @returns {string} The cleaned variable name.
270
+ */
271
+ const _cleanupVariableName = variableName => {
272
+ for (const keyword of FEEL_TRAILING_KEYWORDS) {
273
+ if (variableName.endsWith(' ' + keyword)) {
274
+ return variableName.slice(0, -(keyword.length + 1));
275
+ }
276
+ }
277
+ return variableName;
278
+ };
279
+
280
+ /**
281
+ * Collects the names of variables bound by iteration constructs (e.g. `for x in ...`, `some x in ...`).
282
+ * These are locally scoped and should be excluded from the extracted variable set.
283
+ *
284
+ * @param {Object} node - A QuantifiedExpression or ForExpression node.
285
+ * @returns {string[]} The bound variable names.
286
+ */
287
+ const _collectBoundVariableNames = node => {
288
+ const boundNames = [];
289
+ const collect = n => {
290
+ if (n.name === 'InExpression') {
291
+ // The Name node inside an InExpression is the bound iteration variable
292
+ const nameNode = n.children.find(child => child.name === 'Name');
293
+ if (nameNode && nameNode.variableName) {
294
+ boundNames.push(nameNode.variableName);
295
+ }
296
+ }
297
+ if (n.children) {
298
+ n.children.forEach(collect);
299
+ }
300
+ };
301
+ collect(node);
302
+ return boundNames;
303
+ };
304
+
236
305
  class FeelExpressionLanguage {
237
306
  constructor(eventBus) {
238
307
  this._eventBus = eventBus;
@@ -6091,11 +6160,10 @@ function DocumentPreview(props) {
6091
6160
  if (!isValidDocumentEndpoint(finalEndpoint)) {
6092
6161
  return null;
6093
6162
  }
6094
- const requestInit = getDocumentRequestInit(documentEndpointBuilder, document);
6095
6163
  return jsxRuntime.jsx(DocumentRenderer, {
6096
6164
  documentMetadata: document,
6165
+ documentEndpointBuilder: documentEndpointBuilder,
6097
6166
  endpoint: finalEndpoint,
6098
- requestInit: requestInit,
6099
6167
  maxHeight: maxHeight,
6100
6168
  domId: `${domId}-${index}`
6101
6169
  }, document.documentId);
@@ -6277,9 +6345,9 @@ function ImageRenderer(props) {
6277
6345
  *
6278
6346
  * @param {Object} props
6279
6347
  * @param {DocumentMetadata} props.documentMetadata
6348
+ * @param {DocumentEndpointBuilder | null} props.documentEndpointBuilder
6280
6349
  * @param {string} props.endpoint
6281
6350
  * @param {string} props.domId
6282
- * @param {RequestInit|undefined} props.requestInit
6283
6351
  * @param {number|undefined} props.maxHeight
6284
6352
  *
6285
6353
  * @returns {import("preact").JSX.Element}
@@ -6287,10 +6355,10 @@ function ImageRenderer(props) {
6287
6355
  function DocumentRenderer(props) {
6288
6356
  const {
6289
6357
  documentMetadata,
6358
+ documentEndpointBuilder,
6290
6359
  endpoint,
6291
6360
  maxHeight,
6292
- domId,
6293
- requestInit
6361
+ domId
6294
6362
  } = props;
6295
6363
  const {
6296
6364
  metadata
@@ -6298,6 +6366,8 @@ function DocumentRenderer(props) {
6298
6366
  const [hasError, setHasError] = hooks.useState(false);
6299
6367
  const ref = hooks.useRef(null);
6300
6368
  const isInViewport = useInViewport(ref);
6369
+ const onError = hooks.useCallback(() => setHasError(true), []);
6370
+ const requestInit = hooks.useMemo(() => getDocumentRequestInit(documentEndpointBuilder, documentMetadata), [documentEndpointBuilder, documentMetadata]);
6301
6371
  const singleDocumentContainerClassName = `fjs-${type}-single-document-container`;
6302
6372
  const errorMessageId = `${domId}-error-message`;
6303
6373
  const errorMessage = 'Unable to download document';
@@ -6313,14 +6383,12 @@ function DocumentRenderer(props) {
6313
6383
  url: endpoint,
6314
6384
  alt: metadata.fileName,
6315
6385
  requestInit: requestInit,
6316
- onError: () => setHasError(true)
6386
+ onError: onError
6317
6387
  }), jsxRuntime.jsx(DownloadButton, {
6318
6388
  endpoint: endpoint,
6319
6389
  fileName: metadata.fileName,
6320
6390
  requestInit: requestInit,
6321
- onDownloadError: () => {
6322
- setHasError(true);
6323
- }
6391
+ onDownloadError: onError
6324
6392
  }), hasError ? jsxRuntime.jsx(Errors, {
6325
6393
  id: errorMessageId,
6326
6394
  errors: [errorMessage]
@@ -6338,7 +6406,7 @@ function DocumentRenderer(props) {
6338
6406
  url: endpoint,
6339
6407
  fileName: metadata.fileName,
6340
6408
  requestInit: requestInit,
6341
- onError: () => setHasError(true),
6409
+ onError: onError,
6342
6410
  errorMessageId: errorMessageId
6343
6411
  })
6344
6412
  });
@@ -6359,9 +6427,7 @@ function DocumentRenderer(props) {
6359
6427
  endpoint: endpoint,
6360
6428
  fileName: metadata.fileName,
6361
6429
  requestInit: requestInit,
6362
- onDownloadError: () => {
6363
- setHasError(true);
6364
- }
6430
+ onDownloadError: onError
6365
6431
  })]
6366
6432
  });
6367
6433
  }