@bpmn-io/feel-editor 1.12.1 → 2.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/dist/index.js CHANGED
@@ -1,20 +1,18 @@
1
- 'use strict';
2
-
3
- var autocomplete = require('@codemirror/autocomplete');
4
- var commands = require('@codemirror/commands');
5
- var language$1 = require('@codemirror/language');
6
- var lint = require('@codemirror/lint');
7
- var state = require('@codemirror/state');
8
- var view = require('@codemirror/view');
9
- var feelLint = require('@bpmn-io/feel-lint');
10
- var highlight = require('@lezer/highlight');
11
- var langFeel = require('@bpmn-io/lang-feel');
12
- var minDom = require('min-dom');
13
- var feelBuiltins = require('@camunda/feel-builtins');
14
-
15
- var linter = [ lint.linter(feelLint.cmFeelLinter()) ];
16
-
17
- const baseTheme = view.EditorView.theme({
1
+ import { snippetCompletion, completeFromList, autocompletion, closeBrackets } from '@codemirror/autocomplete';
2
+ import { defaultKeymap } from '@codemirror/commands';
3
+ import { syntaxHighlighting, HighlightStyle, syntaxTree, bracketMatching, indentOnInput } from '@codemirror/language';
4
+ import { linter as linter$1, setDiagnosticsEffect } from '@codemirror/lint';
5
+ import { Facet, Compartment, EditorState } from '@codemirror/state';
6
+ import { EditorView, tooltips, keymap, placeholder } from '@codemirror/view';
7
+ import { cmFeelLinter } from '@bpmn-io/feel-lint';
8
+ import { tags } from '@lezer/highlight';
9
+ import { keywordCompletions, snippets, feel } from '@bpmn-io/lang-feel';
10
+ import { domify } from 'min-dom';
11
+ import { camundaBuiltins } from '@camunda/feel-builtins';
12
+
13
+ var linter = [ linter$1(cmFeelLinter()) ];
14
+
15
+ const baseTheme = EditorView.theme({
18
16
  '& .cm-content': {
19
17
  padding: '0px',
20
18
  },
@@ -53,7 +51,7 @@ const baseTheme = view.EditorView.theme({
53
51
  }
54
52
  });
55
53
 
56
- const highlightTheme = view.EditorView.baseTheme({
54
+ const highlightTheme = EditorView.baseTheme({
57
55
  '& .variableName': {
58
56
  color: '#10f'
59
57
  },
@@ -75,17 +73,17 @@ const highlightTheme = view.EditorView.baseTheme({
75
73
  }
76
74
  });
77
75
 
78
- const syntaxClasses = language$1.syntaxHighlighting(
79
- language$1.HighlightStyle.define([
80
- { tag: highlight.tags.variableName, class: 'variableName' },
81
- { tag: highlight.tags.name, class: 'variableName' },
82
- { tag: highlight.tags.number, class: 'number' },
83
- { tag: highlight.tags.string, class: 'string' },
84
- { tag: highlight.tags.bool, class: 'bool' },
85
- { tag: highlight.tags.function(highlight.tags.variableName), class: 'function' },
86
- { tag: highlight.tags.function(highlight.tags.special(highlight.tags.variableName)), class: 'function' },
87
- { tag: highlight.tags.controlKeyword, class: 'control' },
88
- { tag: highlight.tags.operatorKeyword, class: 'control' }
76
+ const syntaxClasses = syntaxHighlighting(
77
+ HighlightStyle.define([
78
+ { tag: tags.variableName, class: 'variableName' },
79
+ { tag: tags.name, class: 'variableName' },
80
+ { tag: tags.number, class: 'number' },
81
+ { tag: tags.string, class: 'string' },
82
+ { tag: tags.bool, class: 'bool' },
83
+ { tag: tags.function(tags.variableName), class: 'function' },
84
+ { tag: tags.function(tags.special(tags.variableName)), class: 'function' },
85
+ { tag: tags.controlKeyword, class: 'control' },
86
+ { tag: tags.operatorKeyword, class: 'control' }
89
87
  ])
90
88
  );
91
89
 
@@ -147,7 +145,7 @@ function pathExpressionCompletion({ variables }) {
147
145
 
148
146
  return (context) => {
149
147
 
150
- const nodeBefore = language$1.syntaxTree(context.state).resolve(context.pos, -1);
148
+ const nodeBefore = syntaxTree(context.state).resolve(context.pos, -1);
151
149
 
152
150
  if (!isPathExpression(nodeBefore)) {
153
151
  return null;
@@ -279,7 +277,7 @@ function variableCompletion({ variables = [], builtins = [] }) {
279
277
  } = context;
280
278
 
281
279
  // in most cases, use what is typed before the cursor
282
- const nodeBefore = language$1.syntaxTree(state).resolve(pos, -1);
280
+ const nodeBefore = syntaxTree(state).resolve(pos, -1);
283
281
 
284
282
  if (isEmpty(nodeBefore, pos)) {
285
283
  return context.explicit ? {
@@ -359,7 +357,7 @@ function createFunctionVariable(variable, boost) {
359
357
  )).join(', ');
360
358
  const label = `${name}(${paramsSignature})`;
361
359
 
362
- return autocomplete.snippetCompletion(template, {
360
+ return snippetCompletion(template, {
363
361
  label,
364
362
  type: 'function',
365
363
  info,
@@ -386,8 +384,8 @@ function completions({ variables = [], builtins = [] }) {
386
384
  return [
387
385
  pathExpressionCompletion({ variables }),
388
386
  variableCompletion({ variables, builtins }),
389
- autocomplete.completeFromList(langFeel.snippets),
390
- ...langFeel.keywordCompletions
387
+ completeFromList(snippets),
388
+ ...keywordCompletions
391
389
  ];
392
390
  }
393
391
 
@@ -410,7 +408,7 @@ function completions({ variables = [], builtins = [] }) {
410
408
  * @return { import('@codemirror/language').LanguageSupport }
411
409
  */
412
410
  function language(options) {
413
- return langFeel.feel(options);
411
+ return feel(options);
414
412
  }
415
413
 
416
414
  /**
@@ -435,22 +433,22 @@ function createContext(variables) {
435
433
  /**
436
434
  * @type {Facet<Variable[]>}
437
435
  */
438
- const builtinsFacet = state.Facet.define();
436
+ const builtinsFacet = Facet.define();
439
437
 
440
438
  /**
441
439
  * @type {Facet<Variable[]>}
442
440
  */
443
- const variablesFacet = state.Facet.define();
441
+ const variablesFacet = Facet.define();
444
442
 
445
443
  /**
446
444
  * @type {Facet<Dialect>}
447
445
  */
448
- const dialectFacet = state.Facet.define();
446
+ const dialectFacet = Facet.define();
449
447
 
450
448
  /**
451
449
  * @type {Facet<ParserDialect>}
452
450
  */
453
- const parserDialectFacet = state.Facet.define();
451
+ const parserDialectFacet = Facet.define();
454
452
 
455
453
  /**
456
454
  * @typedef {object} Variable
@@ -524,9 +522,9 @@ function get(state) {
524
522
  };
525
523
  }
526
524
 
527
- const domifiedBuiltins = feelBuiltins.camundaBuiltins.map(builtin => ({
525
+ const domifiedBuiltins = camundaBuiltins.map(builtin => ({
528
526
  ...builtin,
529
- info: () => minDom.domify(builtin.info),
527
+ info: () => domify(builtin.info),
530
528
  }));
531
529
 
532
530
  /**
@@ -538,8 +536,8 @@ const domifiedBuiltins = feelBuiltins.camundaBuiltins.map(builtin => ({
538
536
  * @typedef { import('./language').ParserDialect } ParserDialect
539
537
  */
540
538
 
541
- const coreConf = new state.Compartment();
542
- const placeholderConf = new state.Compartment();
539
+ const coreConf = new Compartment();
540
+ const placeholderConf = new Compartment();
543
541
 
544
542
 
545
543
  /**
@@ -571,23 +569,23 @@ function FeelEditor({
571
569
  onChange = () => {},
572
570
  onKeyDown = () => {},
573
571
  onLint = () => {},
574
- placeholder = '',
572
+ placeholder: placeholder$1 = '',
575
573
  readOnly = false,
576
574
  value = '',
577
575
  builtins = domifiedBuiltins,
578
576
  variables = []
579
577
  }) {
580
578
 
581
- const changeHandler = view.EditorView.updateListener.of((update) => {
579
+ const changeHandler = EditorView.updateListener.of((update) => {
582
580
  if (update.docChanged) {
583
581
  onChange(update.state.doc.toString());
584
582
  }
585
583
  });
586
584
 
587
- const lintHandler = view.EditorView.updateListener.of((update) => {
585
+ const lintHandler = EditorView.updateListener.of((update) => {
588
586
  const diagnosticEffects = update.transactions
589
587
  .flatMap(t => t.effects)
590
- .filter(effect => effect.is(lint.setDiagnosticsEffect));
588
+ .filter(effect => effect.is(setDiagnosticsEffect));
591
589
 
592
590
  if (!diagnosticEffects.length) {
593
591
  return;
@@ -598,7 +596,7 @@ function FeelEditor({
598
596
  onLint(messages);
599
597
  });
600
598
 
601
- const keyHandler = view.EditorView.domEventHandlers(
599
+ const keyHandler = EditorView.domEventHandlers(
602
600
  {
603
601
  keydown: onKeyDown
604
602
  }
@@ -608,43 +606,43 @@ function FeelEditor({
608
606
  tooltipContainer = /** @type {HTMLElement} */ (document.querySelector(tooltipContainer));
609
607
  }
610
608
 
611
- const tooltipLayout = tooltipContainer ? view.tooltips({
609
+ const tooltipLayout = tooltipContainer ? tooltips({
612
610
  tooltipSpace: function() {
613
611
  return /** @type {HTMLElement} */ (tooltipContainer).getBoundingClientRect();
614
612
  }
615
613
  }) : [];
616
614
 
617
615
  const extensions = [
618
- autocomplete.autocompletion(),
616
+ autocompletion(),
619
617
  coreConf.of(configure({
620
618
  dialect,
621
619
  builtins,
622
620
  variables,
623
621
  parserDialect
624
622
  })),
625
- language$1.bracketMatching(),
626
- language$1.indentOnInput(),
627
- autocomplete.closeBrackets(),
628
- view.EditorView.contentAttributes.of(contentAttributes),
623
+ bracketMatching(),
624
+ indentOnInput(),
625
+ closeBrackets(),
626
+ EditorView.contentAttributes.of(contentAttributes),
629
627
  changeHandler,
630
628
  keyHandler,
631
- view.keymap.of([
632
- ...commands.defaultKeymap,
629
+ keymap.of([
630
+ ...defaultKeymap,
633
631
  ]),
634
632
  linter,
635
633
  lintHandler,
636
634
  tooltipLayout,
637
- placeholderConf.of(view.placeholder(placeholder)),
635
+ placeholderConf.of(placeholder(placeholder$1)),
638
636
  theme,
639
637
  ...editorExtensions
640
638
  ];
641
639
 
642
640
  if (readOnly) {
643
- extensions.push(view.EditorView.editable.of(false));
641
+ extensions.push(EditorView.editable.of(false));
644
642
  }
645
643
 
646
- this._cmEditor = new view.EditorView({
647
- state: state.EditorState.create({
644
+ this._cmEditor = new EditorView({
645
+ state: EditorState.create({
648
646
  doc: value,
649
647
  extensions
650
648
  }),
@@ -720,10 +718,11 @@ FeelEditor.prototype.setVariables = function(variables) {
720
718
  *
721
719
  * @param {string} placeholder
722
720
  */
723
- FeelEditor.prototype.setPlaceholder = function(placeholder) {
721
+ FeelEditor.prototype.setPlaceholder = function(placeholder$1) {
724
722
  this._cmEditor.dispatch({
725
- effects: placeholderConf.reconfigure(view.placeholder(placeholder))
723
+ effects: placeholderConf.reconfigure(placeholder(placeholder$1))
726
724
  });
727
725
  };
728
726
 
729
- module.exports = FeelEditor;
727
+ export { FeelEditor as default };
728
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/lint/index.js","../src/theme/theme.js","../src/theme/index.js","../src/autocompletion/util.js","../src/autocompletion/pathExpression.js","../src/autocompletion/variable.js","../src/autocompletion/index.js","../src/language/index.js","../src/core/facets.js","../src/core/index.js","../src/builtins/index.js","../src/index.js"],"sourcesContent":["import { cmFeelLinter } from '@bpmn-io/feel-lint';\nimport { linter } from '@codemirror/lint';\n\nexport default [ linter(cmFeelLinter()) ];","import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { EditorView } from '@codemirror/view';\nimport { tags as t } from '@lezer/highlight';\n\nexport const baseTheme = EditorView.theme({\n '& .cm-content': {\n padding: '0px',\n },\n '& .cm-line': {\n padding: '0px',\n },\n '&.cm-editor.cm-focused': {\n outline: 'none',\n },\n '& .cm-completionInfo': {\n whiteSpace: 'pre-wrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis'\n },\n '&.cm-editor': {\n height: '100%',\n },\n\n // Don't wrap whitespace for custom HTML\n '& .cm-completionInfo > *': {\n whiteSpace: 'normal'\n },\n '& .cm-completionInfo ul': {\n margin: 0,\n paddingLeft: '15px'\n },\n '& .cm-completionInfo pre': {\n marginBottom: 0,\n whiteSpace: 'pre-wrap'\n },\n '& .cm-completionInfo p': {\n marginTop: 0,\n },\n '& .cm-completionInfo p:not(:last-of-type)': {\n marginBottom: 0,\n }\n});\n\nexport const highlightTheme = EditorView.baseTheme({\n '& .variableName': {\n color: '#10f'\n },\n '& .number': {\n color: '#164'\n },\n '& .string': {\n color: '#a11'\n },\n '& .bool': {\n color: '#219'\n },\n '& .function': {\n color: '#aa3731',\n fontWeight: 'bold'\n },\n '& .control': {\n color: '#708'\n }\n});\n\nexport const syntaxClasses = syntaxHighlighting(\n HighlightStyle.define([\n { tag: t.variableName, class: 'variableName' },\n { tag: t.name, class: 'variableName' },\n { tag: t.number, class: 'number' },\n { tag: t.string, class: 'string' },\n { tag: t.bool, class: 'bool' },\n { tag: t.function(t.variableName), class: 'function' },\n { tag: t.function(t.special(t.variableName)), class: 'function' },\n { tag: t.controlKeyword, class: 'control' },\n { tag: t.operatorKeyword, class: 'control' }\n ])\n);","import { baseTheme, highlightTheme, syntaxClasses } from './theme.js';\n\nexport default [ baseTheme, highlightTheme, syntaxClasses ];","// helpers ///////////////////////////////\n\nfunction _isEmpty(node) {\n return node && node.from === node.to;\n}\n\n/**\n * @param {any} node\n * @param {number} pos\n *\n * @return {boolean}\n */\nexport function isEmpty(node, pos) {\n\n // For the special case of empty nodes, we need to check the current node\n // as well. The previous node could be part of another token, e.g.\n // when typing functions \"abs(\".\n const nextNode = node.nextSibling;\n\n return _isEmpty(node) || (\n nextNode && nextNode.from === pos && _isEmpty(nextNode)\n );\n}\n\nexport function isVariableName(node) {\n return node && node.parent && node.parent.name === 'VariableName';\n}\n\nexport function isPathExpression(node) {\n if (!node) {\n return false;\n }\n\n if (node.name === 'PathExpression') {\n return true;\n }\n\n return isPathExpression(node.parent);\n}\n","import { syntaxTree } from '@codemirror/language';\nimport { isPathExpression } from './util.js';\n\n/**\n * @typedef { import('../core').Variable } Variable\n * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource\n */\n\n/**\n * @param { {\n * variables?: Variable[],\n * } } options\n *\n * @return { CompletionSource }\n */\nexport function pathExpressionCompletion({ variables }) {\n\n return (context) => {\n\n const nodeBefore = syntaxTree(context.state).resolve(context.pos, -1);\n\n if (!isPathExpression(nodeBefore)) {\n return null;\n }\n\n const expression = findPathExpression(nodeBefore);\n\n // if the cursor is directly after the `.`, variable starts at the cursor position\n const from = nodeBefore === expression ? context.pos : nodeBefore.from;\n\n const path = getPath(expression, context);\n\n let options = variables;\n for (var i = 0; i < path.length - 1; i++) {\n var childVar = options.find(val => val.name === path[i].name);\n\n if (!childVar) {\n return null;\n }\n\n // only suggest if variable type matches\n if (\n childVar.isList !== 'optional' &&\n !!childVar.isList !== path[i].isList\n ) {\n return null;\n }\n\n options = childVar.entries;\n }\n\n if (!options) return null;\n\n const completionOptions = options.map(option => (\n {\n label: option.name,\n type: 'variable',\n info: option.info,\n detail: option.detail\n }));\n\n const result = {\n from: from,\n options: completionOptions\n };\n\n return result;\n };\n}\n\n\nfunction findPathExpression(node) {\n while (node) {\n if (node.name === 'PathExpression') {\n return node;\n }\n node = node.parent;\n }\n}\n\n// parses the path expression into a list of variable names with type information\n// e.g. foo[0].bar => [ { name: 'foo', isList: true }, { name: 'bar', isList: false } ]\nfunction getPath(node, context) {\n let path = [];\n\n for (let child = node.firstChild; child; child = child.nextSibling) {\n if (child.name === 'PathExpression') {\n path.push(...getPath(child, context));\n } else if (child.name === 'FilterExpression') {\n path.push(...getFilter(child, context));\n }\n else {\n path.push({\n name: getNodeContent(child, context),\n isList: false\n });\n }\n }\n return path;\n}\n\nfunction getFilter(node, context) {\n const list = node.firstChild;\n\n if (list.name === 'PathExpression') {\n const path = getPath(list, context);\n const last = path[path.length - 1];\n last.isList = true;\n\n return path;\n }\n\n return [ {\n name: getNodeContent(list, context),\n isList: true\n } ];\n}\n\nfunction getNodeContent(node, context) {\n return context.state.sliceDoc(node.from, node.to);\n}","import { syntaxTree } from '@codemirror/language';\nimport { snippetCompletion } from '@codemirror/autocomplete';\nimport { isEmpty, isPathExpression, isVariableName } from './util.js';\n\n/**\n * @typedef { import('../core').Variable } Variable\n * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource\n */\n\n/**\n * @param { {\n * variables?: Variable[],\n * builtins?: Variable[]\n * } } options\n *\n * @return { CompletionSource }\n */\nexport function variableCompletion({ variables = [], builtins = [] }) {\n\n const options = getVariableSuggestions(variables, builtins);\n\n if (!options.length) {\n return (context) => null;\n }\n\n return (context) => {\n\n const {\n pos,\n state\n } = context;\n\n // in most cases, use what is typed before the cursor\n const nodeBefore = syntaxTree(state).resolve(pos, -1);\n\n if (isEmpty(nodeBefore, pos)) {\n return context.explicit ? {\n from: pos,\n options\n } : null;\n }\n\n // only auto-complete variables\n if (!isVariableName(nodeBefore) || isPathExpression(nodeBefore)) {\n return null;\n }\n\n return {\n from: nodeBefore.from,\n options\n };\n };\n}\n\n/**\n * @param { Variable[] } variables\n * @param { Variable[] } builtins\n *\n * @returns {import('@codemirror/autocomplete').Completion[]}\n */\nfunction getVariableSuggestions(variables, builtins) {\n return [].concat(\n variables.map(v => createVariableSuggestion(v)),\n builtins.map(b => createVariableSuggestion(b))\n );\n}\n\n/**\n * @param {import('..').Variable} variable\n * @param {number} [boost]\n *\n * @returns {import('@codemirror/autocomplete').Completion}\n */\nfunction createVariableSuggestion(variable, boost) {\n if (variable.type === 'function') {\n return createFunctionVariable(variable, boost);\n }\n\n return {\n label: variable.name,\n type: 'variable',\n info: variable.info,\n detail: variable.detail,\n boost\n };\n}\n\n/**\n * @param {import('..').Variable} variable\n * @param {number} boost\n *\n * @returns {import('@codemirror/autocomplete').Completion}\n */\nfunction createFunctionVariable(variable, boost) {\n const {\n name,\n info,\n detail,\n params = []\n } = variable;\n\n const paramsWithNames = params.map(({ name, type }, index) => ({\n name: name || `param ${index + 1}`,\n type\n }));\n\n const template = `${name}(${paramsWithNames.map(p => '${' + p.name + '}').join(', ')})`;\n\n const paramsSignature = paramsWithNames.map(({ name, type }) => (\n type ? `${name}: ${type}` : name\n )).join(', ');\n const label = `${name}(${paramsSignature})`;\n\n return snippetCompletion(template, {\n label,\n type: 'function',\n info,\n detail,\n boost\n });\n}\n","import { snippets, keywordCompletions } from '@bpmn-io/lang-feel';\nimport { completeFromList } from '@codemirror/autocomplete';\n\nimport { pathExpressionCompletion } from './pathExpression.js';\nimport { variableCompletion } from './variable.js';\n\n/**\n * @typedef { import('../core').Variable } Variable\n * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource\n */\n\n/**\n * @param { {\n * variables?: Variable[],\n * builtins?: Variable[]\n * } } options\n *\n * @return { CompletionSource[] }\n */\nexport function completions({ variables = [], builtins = [] }) {\n\n return [\n pathExpressionCompletion({ variables }),\n variableCompletion({ variables, builtins }),\n completeFromList(snippets),\n ...keywordCompletions\n ];\n}","import { feel } from '@bpmn-io/lang-feel';\n\n/**\n * @typedef { 'expression' | 'unaryTests' } Dialect\n */\n\n/**\n * @typedef { 'camunda' | undefined } ParserDialect\n */\n\n/**\n * @param { {\n * dialect?: Dialect,\n * parserDialect?: ParserDialect,\n * context?: Record<string, any>,\n * completions?: import('@codemirror/autocomplete').CompletionSource[]\n * } } options\n *\n * @return { import('@codemirror/language').LanguageSupport }\n */\nexport function language(options) {\n return feel(options);\n}\n\n/**\n * @param { import('../core').Variable[] } variables\n *\n * @return {Record<string, any>}\n */\nexport function createContext(variables) {\n return variables.slice().reverse().reduce((context, builtin) => {\n context[builtin.name] = () => {};\n\n return context;\n }, {});\n}","import { Facet } from '@codemirror/state';\n\n/**\n * @typedef { import('../language').Dialect } Dialect\n * @typedef { import('../language').ParserDialect } ParserDialect\n * @typedef { import('..').Variable } Variable\n */\n\n/**\n * @type {Facet<Variable[]>}\n */\nexport const builtinsFacet = Facet.define();\n\n/**\n * @type {Facet<Variable[]>}\n */\nexport const variablesFacet = Facet.define();\n\n/**\n * @type {Facet<Dialect>}\n */\nexport const dialectFacet = Facet.define();\n\n/**\n * @type {Facet<ParserDialect>}\n */\nexport const parserDialectFacet = Facet.define();\n\n","import { completions as feelCompletions } from '../autocompletion/index.js';\n\nimport { createContext, language } from '../language/index.js';\n\nimport {\n variablesFacet,\n builtinsFacet,\n parserDialectFacet,\n dialectFacet\n} from './facets.js';\n\n\n/**\n * @typedef {object} Variable\n * @property {string} name name or key of the variable\n * @property {string | (() => HTMLElement)} [info] short information about the variable, e.g. type\n * @property {string} [detail] longer description of the variable content\n * @property {boolean|'optional'} [isList] whether the variable is a list\n * @property {Array<Variable>} [entries] array of child variables if the variable is a context or list\n * @property {'function'|'variable'} [type] type of the variable\n * @property {Array<{name: string, type?: string}>} [params] function parameters\n */\n\n/**\n * @typedef { {\n * dialect?: import('../language').Dialect,\n * parserDialect?: import('../language').ParserDialect,\n * variables?: Variable[],\n * builtins?: Variable[]\n * } } CoreConfig\n *\n * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource\n * @typedef { import('@codemirror/state').Extension } Extension\n */\n\n/**\n * @param { CoreConfig & { completions?: CompletionSource[] } } config\n *\n * @return { Extension }\n */\nexport function configure({\n dialect = 'expression',\n parserDialect,\n variables = [],\n builtins = [],\n completions = feelCompletions({ builtins, variables })\n}) {\n\n const context = createContext([ ...variables, ...builtins ]);\n\n return [\n dialectFacet.of(dialect),\n builtinsFacet.of(builtins),\n variablesFacet.of(variables),\n parserDialectFacet.of(parserDialect),\n language({\n dialect,\n parserDialect,\n context,\n completions\n })\n ];\n}\n\n/**\n * @param {import('@codemirror/state').EditorState } state\n *\n * @return { CoreConfig }\n */\nexport function get(state) {\n\n const builtins = state.facet(builtinsFacet)[0];\n const variables = state.facet(variablesFacet)[0];\n const dialect = state.facet(dialectFacet)[0];\n const parserDialect = state.facet(parserDialectFacet)[0];\n\n return {\n builtins,\n variables,\n dialect,\n parserDialect\n };\n}","import { domify } from 'min-dom';\nimport { camundaBuiltins } from '@camunda/feel-builtins';\n\nexport const domifiedBuiltins = camundaBuiltins.map(builtin => ({\n ...builtin,\n info: () => domify(builtin.info),\n}));","import { autocompletion, closeBrackets } from '@codemirror/autocomplete';\nimport { defaultKeymap } from '@codemirror/commands';\nimport { bracketMatching, indentOnInput } from '@codemirror/language';\nimport { setDiagnosticsEffect } from '@codemirror/lint';\nimport { Compartment, EditorState } from '@codemirror/state';\nimport { EditorView, keymap, placeholder as placeholderExt, tooltips } from '@codemirror/view';\n\nimport linter from './lint/index.js';\nimport theme from './theme/index.js';\n\nimport * as Core from './core/index.js';\n\nimport { domifiedBuiltins } from './builtins/index.js';\n\n/**\n * @typedef { import('./core').Variable } Variable\n */\n\n/**\n * @typedef { import('./language').Dialect } Dialect\n * @typedef { import('./language').ParserDialect } ParserDialect\n */\n\nconst coreConf = new Compartment();\nconst placeholderConf = new Compartment();\n\n\n/**\n * Creates a FEEL editor in the supplied container\n *\n * @param {Object} config\n * @param {DOMNode} config.container\n * @param {Extension[]} [config.extensions]\n * @param {Dialect} [config.dialect='expression']\n * @param {ParserDialect} [config.parserDialect]\n * @param {DOMNode|String} [config.tooltipContainer]\n * @param {Function} [config.onChange]\n * @param {(event: KeyboardEvent, view: import('@codemirror/view').EditorView) => boolean | void} [config.onKeyDown]\n * @param {Function} [config.onLint]\n * @param {Boolean} [config.readOnly]\n * @param {String} [config.value]\n * @param {Variable[]} [config.variables]\n * @param {Variable[]} [config.builtins]\n * @param {Object} [config.contentAttributes]\n * @param {String} [config.placeholder]\n */\nexport default function FeelEditor({\n extensions: editorExtensions = [],\n dialect = 'expression',\n parserDialect,\n container,\n contentAttributes = {},\n tooltipContainer,\n onChange = () => {},\n onKeyDown = () => {},\n onLint = () => {},\n placeholder = '',\n readOnly = false,\n value = '',\n builtins = domifiedBuiltins,\n variables = []\n}) {\n\n const changeHandler = EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n onChange(update.state.doc.toString());\n }\n });\n\n const lintHandler = EditorView.updateListener.of((update) => {\n const diagnosticEffects = update.transactions\n .flatMap(t => t.effects)\n .filter(effect => effect.is(setDiagnosticsEffect));\n\n if (!diagnosticEffects.length) {\n return;\n }\n\n const messages = diagnosticEffects.flatMap(effect => effect.value);\n\n onLint(messages);\n });\n\n const keyHandler = EditorView.domEventHandlers(\n {\n keydown: onKeyDown\n }\n );\n\n if (typeof tooltipContainer === 'string') {\n tooltipContainer = /** @type {HTMLElement} */ (document.querySelector(tooltipContainer));\n }\n\n const tooltipLayout = tooltipContainer ? tooltips({\n tooltipSpace: function() {\n return /** @type {HTMLElement} */ (tooltipContainer).getBoundingClientRect();\n }\n }) : [];\n\n const extensions = [\n autocompletion(),\n coreConf.of(Core.configure({\n dialect,\n builtins,\n variables,\n parserDialect\n })),\n bracketMatching(),\n indentOnInput(),\n closeBrackets(),\n EditorView.contentAttributes.of(contentAttributes),\n changeHandler,\n keyHandler,\n keymap.of([\n ...defaultKeymap,\n ]),\n linter,\n lintHandler,\n tooltipLayout,\n placeholderConf.of(placeholderExt(placeholder)),\n theme,\n ...editorExtensions\n ];\n\n if (readOnly) {\n extensions.push(EditorView.editable.of(false));\n }\n\n this._cmEditor = new EditorView({\n state: EditorState.create({\n doc: value,\n extensions\n }),\n parent: container\n });\n\n return this;\n}\n\n/**\n * Replaces the content of the Editor\n *\n * @param {String} value\n */\nFeelEditor.prototype.setValue = function(value) {\n this._cmEditor.dispatch({\n changes: {\n from: 0,\n to: this._cmEditor.state.doc.length,\n insert: value,\n }\n });\n};\n\n/**\n * Sets the focus in the editor.\n */\nFeelEditor.prototype.focus = function(position) {\n const cmEditor = this._cmEditor;\n\n // the Codemirror `focus` method always calls `focus` with `preventScroll`,\n // so we have to focus + scroll manually\n cmEditor.contentDOM.focus();\n cmEditor.focus();\n\n if (typeof position === 'number') {\n const end = cmEditor.state.doc.length;\n cmEditor.dispatch({ selection: { anchor: position <= end ? position : end } });\n }\n};\n\n/**\n * Returns the current selection ranges. If no text is selected, a single\n * range with the start and end index at the cursor position will be returned.\n *\n * @returns {import('@codemirror/state').EditorSelection} selection - Selection object with ranges array\n */\nFeelEditor.prototype.getSelection = function() {\n return this._cmEditor.state.selection;\n};\n\n/**\n * Set variables to be used for autocompletion.\n *\n * @param {Variable[]} variables\n */\nFeelEditor.prototype.setVariables = function(variables) {\n\n const config = Core.get(this._cmEditor.state);\n\n this._cmEditor.dispatch({\n effects: [\n coreConf.reconfigure(Core.configure({\n ...config,\n variables\n }))\n ]\n });\n};\n\n/**\n * Update placeholder text.\n *\n * @param {string} placeholder\n */\nFeelEditor.prototype.setPlaceholder = function(placeholder) {\n this._cmEditor.dispatch({\n effects: placeholderConf.reconfigure(placeholderExt(placeholder))\n });\n};"],"names":["linter","t","completions","feelCompletions","placeholder","Core.configure","placeholderExt","Core.get"],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "@bpmn-io/feel-editor",
3
- "version": "1.12.1",
3
+ "version": "2.0.0",
4
4
  "description": "Editor for FEEL expressions.",
5
- "files": [
6
- "dist"
7
- ],
8
- "main": "dist/index.js",
9
- "module": "dist/index.es.js",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "source": "./src/index.js",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./package.json": "./package.json"
11
+ },
10
12
  "scripts": {
11
13
  "all": "run-s lint check-types test build",
12
- "test": "karma start",
14
+ "test": "karma start karma.conf.cjs",
13
15
  "build": "rollup -c --bundleConfigAsCjs",
14
16
  "build:watch": "npm run build -- -w",
15
17
  "lint": "eslint .",
@@ -29,8 +31,11 @@
29
31
  "access": "public"
30
32
  },
31
33
  "engines": {
32
- "node": ">= 16"
34
+ "node": ">= 20"
33
35
  },
36
+ "files": [
37
+ "dist"
38
+ ],
34
39
  "keywords": [
35
40
  "bpmn-io",
36
41
  "feel",
@@ -48,16 +53,16 @@
48
53
  ],
49
54
  "license": "MIT",
50
55
  "dependencies": {
51
- "@bpmn-io/feel-lint": "^2.1.0",
52
- "@bpmn-io/lang-feel": "^2.4.0",
56
+ "@bpmn-io/feel-lint": "^3.0.0",
57
+ "@bpmn-io/lang-feel": "^3.0.0",
53
58
  "@camunda/feel-builtins": "^0.2.0",
54
- "@codemirror/autocomplete": "^6.16.2",
55
- "@codemirror/commands": "^6.8.0",
56
- "@codemirror/language": "^6.10.2",
57
- "@codemirror/lint": "^6.8.4",
58
- "@codemirror/state": "^6.5.1",
59
- "@codemirror/view": "^6.36.2",
60
- "@lezer/highlight": "^1.2.1",
59
+ "@codemirror/autocomplete": "^6.20.0",
60
+ "@codemirror/commands": "^6.10.0",
61
+ "@codemirror/language": "^6.11.3",
62
+ "@codemirror/lint": "^6.9.2",
63
+ "@codemirror/state": "^6.5.2",
64
+ "@codemirror/view": "^6.38.8",
65
+ "@lezer/highlight": "^1.2.3",
61
66
  "min-dom": "^4.2.1"
62
67
  },
63
68
  "devDependencies": {
@@ -68,14 +73,14 @@
68
73
  "@testing-library/user-event": "^14.6.1",
69
74
  "@types/chai": "^5.2.3",
70
75
  "@types/mocha": "^10.0.10",
71
- "@types/sinon": "^17.0.4",
76
+ "@types/sinon": "^21.0.0",
72
77
  "@types/sinon-chai": "^4.0.0",
73
78
  "babel-loader": "^9.2.1",
74
79
  "babel-plugin-istanbul": "^7.0.0",
75
- "chai": "^4.5.0",
80
+ "chai": "^6.2.1",
76
81
  "cross-env": "^7.0.3",
77
- "eslint": "^8.57.0",
78
- "eslint-plugin-bpmn-io": "^1.0.0",
82
+ "eslint": "^9.39.1",
83
+ "eslint-plugin-bpmn-io": "^2.2.0",
79
84
  "karma": "^6.4.4",
80
85
  "karma-chrome-launcher": "^3.2.0",
81
86
  "karma-coverage": "^2.2.1",
@@ -83,15 +88,14 @@
83
88
  "karma-env-preprocessor": "^0.1.1",
84
89
  "karma-firefox-launcher": "^2.1.3",
85
90
  "karma-mocha": "^2.0.1",
86
- "karma-sinon-chai": "^2.0.2",
87
91
  "karma-webpack": "^5.0.1",
88
- "mocha": "^10.8.2",
92
+ "mocha": "^11.7.5",
89
93
  "mocha-test-container-support": "^0.2.0",
90
94
  "npm-run-all": "^4.1.5",
91
- "puppeteer": "^23.1.1",
95
+ "puppeteer": "^24.32.1",
92
96
  "rollup": "^4.31.0",
93
- "sinon": "^17.0.1",
94
- "sinon-chai": "^3.7.0",
97
+ "sinon": "^21.0.0",
98
+ "sinon-chai": "^4.0.1",
95
99
  "typescript": "^5.9.3",
96
100
  "webpack": "^5.97.1"
97
101
  }
package/dist/index.es.js DELETED
@@ -1,727 +0,0 @@
1
- import { snippetCompletion, completeFromList, autocompletion, closeBrackets } from '@codemirror/autocomplete';
2
- import { defaultKeymap } from '@codemirror/commands';
3
- import { syntaxHighlighting, HighlightStyle, syntaxTree, bracketMatching, indentOnInput } from '@codemirror/language';
4
- import { linter as linter$1, setDiagnosticsEffect } from '@codemirror/lint';
5
- import { Facet, Compartment, EditorState } from '@codemirror/state';
6
- import { EditorView, tooltips, keymap, placeholder } from '@codemirror/view';
7
- import { cmFeelLinter } from '@bpmn-io/feel-lint';
8
- import { tags } from '@lezer/highlight';
9
- import { snippets, keywordCompletions, feel } from '@bpmn-io/lang-feel';
10
- import { domify } from 'min-dom';
11
- import { camundaBuiltins } from '@camunda/feel-builtins';
12
-
13
- var linter = [ linter$1(cmFeelLinter()) ];
14
-
15
- const baseTheme = EditorView.theme({
16
- '& .cm-content': {
17
- padding: '0px',
18
- },
19
- '& .cm-line': {
20
- padding: '0px',
21
- },
22
- '&.cm-editor.cm-focused': {
23
- outline: 'none',
24
- },
25
- '& .cm-completionInfo': {
26
- whiteSpace: 'pre-wrap',
27
- overflow: 'hidden',
28
- textOverflow: 'ellipsis'
29
- },
30
- '&.cm-editor': {
31
- height: '100%',
32
- },
33
-
34
- // Don't wrap whitespace for custom HTML
35
- '& .cm-completionInfo > *': {
36
- whiteSpace: 'normal'
37
- },
38
- '& .cm-completionInfo ul': {
39
- margin: 0,
40
- paddingLeft: '15px'
41
- },
42
- '& .cm-completionInfo pre': {
43
- marginBottom: 0,
44
- whiteSpace: 'pre-wrap'
45
- },
46
- '& .cm-completionInfo p': {
47
- marginTop: 0,
48
- },
49
- '& .cm-completionInfo p:not(:last-of-type)': {
50
- marginBottom: 0,
51
- }
52
- });
53
-
54
- const highlightTheme = EditorView.baseTheme({
55
- '& .variableName': {
56
- color: '#10f'
57
- },
58
- '& .number': {
59
- color: '#164'
60
- },
61
- '& .string': {
62
- color: '#a11'
63
- },
64
- '& .bool': {
65
- color: '#219'
66
- },
67
- '& .function': {
68
- color: '#aa3731',
69
- fontWeight: 'bold'
70
- },
71
- '& .control': {
72
- color: '#708'
73
- }
74
- });
75
-
76
- const syntaxClasses = syntaxHighlighting(
77
- HighlightStyle.define([
78
- { tag: tags.variableName, class: 'variableName' },
79
- { tag: tags.name, class: 'variableName' },
80
- { tag: tags.number, class: 'number' },
81
- { tag: tags.string, class: 'string' },
82
- { tag: tags.bool, class: 'bool' },
83
- { tag: tags.function(tags.variableName), class: 'function' },
84
- { tag: tags.function(tags.special(tags.variableName)), class: 'function' },
85
- { tag: tags.controlKeyword, class: 'control' },
86
- { tag: tags.operatorKeyword, class: 'control' }
87
- ])
88
- );
89
-
90
- var theme = [ baseTheme, highlightTheme, syntaxClasses ];
91
-
92
- // helpers ///////////////////////////////
93
-
94
- function _isEmpty(node) {
95
- return node && node.from === node.to;
96
- }
97
-
98
- /**
99
- * @param {any} node
100
- * @param {number} pos
101
- *
102
- * @return {boolean}
103
- */
104
- function isEmpty(node, pos) {
105
-
106
- // For the special case of empty nodes, we need to check the current node
107
- // as well. The previous node could be part of another token, e.g.
108
- // when typing functions "abs(".
109
- const nextNode = node.nextSibling;
110
-
111
- return _isEmpty(node) || (
112
- nextNode && nextNode.from === pos && _isEmpty(nextNode)
113
- );
114
- }
115
-
116
- function isVariableName(node) {
117
- return node && node.parent && node.parent.name === 'VariableName';
118
- }
119
-
120
- function isPathExpression(node) {
121
- if (!node) {
122
- return false;
123
- }
124
-
125
- if (node.name === 'PathExpression') {
126
- return true;
127
- }
128
-
129
- return isPathExpression(node.parent);
130
- }
131
-
132
- /**
133
- * @typedef { import('../core').Variable } Variable
134
- * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource
135
- */
136
-
137
- /**
138
- * @param { {
139
- * variables?: Variable[],
140
- * } } options
141
- *
142
- * @return { CompletionSource }
143
- */
144
- function pathExpressionCompletion({ variables }) {
145
-
146
- return (context) => {
147
-
148
- const nodeBefore = syntaxTree(context.state).resolve(context.pos, -1);
149
-
150
- if (!isPathExpression(nodeBefore)) {
151
- return null;
152
- }
153
-
154
- const expression = findPathExpression(nodeBefore);
155
-
156
- // if the cursor is directly after the `.`, variable starts at the cursor position
157
- const from = nodeBefore === expression ? context.pos : nodeBefore.from;
158
-
159
- const path = getPath(expression, context);
160
-
161
- let options = variables;
162
- for (var i = 0; i < path.length - 1; i++) {
163
- var childVar = options.find(val => val.name === path[i].name);
164
-
165
- if (!childVar) {
166
- return null;
167
- }
168
-
169
- // only suggest if variable type matches
170
- if (
171
- childVar.isList !== 'optional' &&
172
- !!childVar.isList !== path[i].isList
173
- ) {
174
- return null;
175
- }
176
-
177
- options = childVar.entries;
178
- }
179
-
180
- if (!options) return null;
181
-
182
- const completionOptions = options.map(option => (
183
- {
184
- label: option.name,
185
- type: 'variable',
186
- info: option.info,
187
- detail: option.detail
188
- }));
189
-
190
- const result = {
191
- from: from,
192
- options: completionOptions
193
- };
194
-
195
- return result;
196
- };
197
- }
198
-
199
-
200
- function findPathExpression(node) {
201
- while (node) {
202
- if (node.name === 'PathExpression') {
203
- return node;
204
- }
205
- node = node.parent;
206
- }
207
- }
208
-
209
- // parses the path expression into a list of variable names with type information
210
- // e.g. foo[0].bar => [ { name: 'foo', isList: true }, { name: 'bar', isList: false } ]
211
- function getPath(node, context) {
212
- let path = [];
213
-
214
- for (let child = node.firstChild; child; child = child.nextSibling) {
215
- if (child.name === 'PathExpression') {
216
- path.push(...getPath(child, context));
217
- } else if (child.name === 'FilterExpression') {
218
- path.push(...getFilter(child, context));
219
- }
220
- else {
221
- path.push({
222
- name: getNodeContent(child, context),
223
- isList: false
224
- });
225
- }
226
- }
227
- return path;
228
- }
229
-
230
- function getFilter(node, context) {
231
- const list = node.firstChild;
232
-
233
- if (list.name === 'PathExpression') {
234
- const path = getPath(list, context);
235
- const last = path[path.length - 1];
236
- last.isList = true;
237
-
238
- return path;
239
- }
240
-
241
- return [ {
242
- name: getNodeContent(list, context),
243
- isList: true
244
- } ];
245
- }
246
-
247
- function getNodeContent(node, context) {
248
- return context.state.sliceDoc(node.from, node.to);
249
- }
250
-
251
- /**
252
- * @typedef { import('../core').Variable } Variable
253
- * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource
254
- */
255
-
256
- /**
257
- * @param { {
258
- * variables?: Variable[],
259
- * builtins?: Variable[]
260
- * } } options
261
- *
262
- * @return { CompletionSource }
263
- */
264
- function variableCompletion({ variables = [], builtins = [] }) {
265
-
266
- const options = getVariableSuggestions(variables, builtins);
267
-
268
- if (!options.length) {
269
- return (context) => null;
270
- }
271
-
272
- return (context) => {
273
-
274
- const {
275
- pos,
276
- state
277
- } = context;
278
-
279
- // in most cases, use what is typed before the cursor
280
- const nodeBefore = syntaxTree(state).resolve(pos, -1);
281
-
282
- if (isEmpty(nodeBefore, pos)) {
283
- return context.explicit ? {
284
- from: pos,
285
- options
286
- } : null;
287
- }
288
-
289
- // only auto-complete variables
290
- if (!isVariableName(nodeBefore) || isPathExpression(nodeBefore)) {
291
- return null;
292
- }
293
-
294
- return {
295
- from: nodeBefore.from,
296
- options
297
- };
298
- };
299
- }
300
-
301
- /**
302
- * @param { Variable[] } variables
303
- * @param { Variable[] } builtins
304
- *
305
- * @returns {import('@codemirror/autocomplete').Completion[]}
306
- */
307
- function getVariableSuggestions(variables, builtins) {
308
- return [].concat(
309
- variables.map(v => createVariableSuggestion(v)),
310
- builtins.map(b => createVariableSuggestion(b))
311
- );
312
- }
313
-
314
- /**
315
- * @param {import('..').Variable} variable
316
- * @param {number} [boost]
317
- *
318
- * @returns {import('@codemirror/autocomplete').Completion}
319
- */
320
- function createVariableSuggestion(variable, boost) {
321
- if (variable.type === 'function') {
322
- return createFunctionVariable(variable, boost);
323
- }
324
-
325
- return {
326
- label: variable.name,
327
- type: 'variable',
328
- info: variable.info,
329
- detail: variable.detail,
330
- boost
331
- };
332
- }
333
-
334
- /**
335
- * @param {import('..').Variable} variable
336
- * @param {number} boost
337
- *
338
- * @returns {import('@codemirror/autocomplete').Completion}
339
- */
340
- function createFunctionVariable(variable, boost) {
341
- const {
342
- name,
343
- info,
344
- detail,
345
- params = []
346
- } = variable;
347
-
348
- const paramsWithNames = params.map(({ name, type }, index) => ({
349
- name: name || `param ${index + 1}`,
350
- type
351
- }));
352
-
353
- const template = `${name}(${paramsWithNames.map(p => '${' + p.name + '}').join(', ')})`;
354
-
355
- const paramsSignature = paramsWithNames.map(({ name, type }) => (
356
- type ? `${name}: ${type}` : name
357
- )).join(', ');
358
- const label = `${name}(${paramsSignature})`;
359
-
360
- return snippetCompletion(template, {
361
- label,
362
- type: 'function',
363
- info,
364
- detail,
365
- boost
366
- });
367
- }
368
-
369
- /**
370
- * @typedef { import('../core').Variable } Variable
371
- * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource
372
- */
373
-
374
- /**
375
- * @param { {
376
- * variables?: Variable[],
377
- * builtins?: Variable[]
378
- * } } options
379
- *
380
- * @return { CompletionSource[] }
381
- */
382
- function completions({ variables = [], builtins = [] }) {
383
-
384
- return [
385
- pathExpressionCompletion({ variables }),
386
- variableCompletion({ variables, builtins }),
387
- completeFromList(snippets),
388
- ...keywordCompletions
389
- ];
390
- }
391
-
392
- /**
393
- * @typedef { 'expression' | 'unaryTests' } Dialect
394
- */
395
-
396
- /**
397
- * @typedef { 'camunda' | undefined } ParserDialect
398
- */
399
-
400
- /**
401
- * @param { {
402
- * dialect?: Dialect,
403
- * parserDialect?: ParserDialect,
404
- * context?: Record<string, any>,
405
- * completions?: import('@codemirror/autocomplete').CompletionSource[]
406
- * } } options
407
- *
408
- * @return { import('@codemirror/language').LanguageSupport }
409
- */
410
- function language(options) {
411
- return feel(options);
412
- }
413
-
414
- /**
415
- * @param { import('../core').Variable[] } variables
416
- *
417
- * @return {Record<string, any>}
418
- */
419
- function createContext(variables) {
420
- return variables.slice().reverse().reduce((context, builtin) => {
421
- context[builtin.name] = () => {};
422
-
423
- return context;
424
- }, {});
425
- }
426
-
427
- /**
428
- * @typedef { import('../language').Dialect } Dialect
429
- * @typedef { import('../language').ParserDialect } ParserDialect
430
- * @typedef { import('..').Variable } Variable
431
- */
432
-
433
- /**
434
- * @type {Facet<Variable[]>}
435
- */
436
- const builtinsFacet = Facet.define();
437
-
438
- /**
439
- * @type {Facet<Variable[]>}
440
- */
441
- const variablesFacet = Facet.define();
442
-
443
- /**
444
- * @type {Facet<Dialect>}
445
- */
446
- const dialectFacet = Facet.define();
447
-
448
- /**
449
- * @type {Facet<ParserDialect>}
450
- */
451
- const parserDialectFacet = Facet.define();
452
-
453
- /**
454
- * @typedef {object} Variable
455
- * @property {string} name name or key of the variable
456
- * @property {string | (() => HTMLElement)} [info] short information about the variable, e.g. type
457
- * @property {string} [detail] longer description of the variable content
458
- * @property {boolean|'optional'} [isList] whether the variable is a list
459
- * @property {Array<Variable>} [entries] array of child variables if the variable is a context or list
460
- * @property {'function'|'variable'} [type] type of the variable
461
- * @property {Array<{name: string, type?: string}>} [params] function parameters
462
- */
463
-
464
- /**
465
- * @typedef { {
466
- * dialect?: import('../language').Dialect,
467
- * parserDialect?: import('../language').ParserDialect,
468
- * variables?: Variable[],
469
- * builtins?: Variable[]
470
- * } } CoreConfig
471
- *
472
- * @typedef { import('@codemirror/autocomplete').CompletionSource } CompletionSource
473
- * @typedef { import('@codemirror/state').Extension } Extension
474
- */
475
-
476
- /**
477
- * @param { CoreConfig & { completions?: CompletionSource[] } } config
478
- *
479
- * @return { Extension }
480
- */
481
- function configure({
482
- dialect = 'expression',
483
- parserDialect,
484
- variables = [],
485
- builtins = [],
486
- completions: completions$1 = completions({ builtins, variables })
487
- }) {
488
-
489
- const context = createContext([ ...variables, ...builtins ]);
490
-
491
- return [
492
- dialectFacet.of(dialect),
493
- builtinsFacet.of(builtins),
494
- variablesFacet.of(variables),
495
- parserDialectFacet.of(parserDialect),
496
- language({
497
- dialect,
498
- parserDialect,
499
- context,
500
- completions: completions$1
501
- })
502
- ];
503
- }
504
-
505
- /**
506
- * @param {import('@codemirror/state').EditorState } state
507
- *
508
- * @return { CoreConfig }
509
- */
510
- function get(state) {
511
-
512
- const builtins = state.facet(builtinsFacet)[0];
513
- const variables = state.facet(variablesFacet)[0];
514
- const dialect = state.facet(dialectFacet)[0];
515
- const parserDialect = state.facet(parserDialectFacet)[0];
516
-
517
- return {
518
- builtins,
519
- variables,
520
- dialect,
521
- parserDialect
522
- };
523
- }
524
-
525
- const domifiedBuiltins = camundaBuiltins.map(builtin => ({
526
- ...builtin,
527
- info: () => domify(builtin.info),
528
- }));
529
-
530
- /**
531
- * @typedef { import('./core').Variable } Variable
532
- */
533
-
534
- /**
535
- * @typedef { import('./language').Dialect } Dialect
536
- * @typedef { import('./language').ParserDialect } ParserDialect
537
- */
538
-
539
- const coreConf = new Compartment();
540
- const placeholderConf = new Compartment();
541
-
542
-
543
- /**
544
- * Creates a FEEL editor in the supplied container
545
- *
546
- * @param {Object} config
547
- * @param {DOMNode} config.container
548
- * @param {Extension[]} [config.extensions]
549
- * @param {Dialect} [config.dialect='expression']
550
- * @param {ParserDialect} [config.parserDialect]
551
- * @param {DOMNode|String} [config.tooltipContainer]
552
- * @param {Function} [config.onChange]
553
- * @param {(event: KeyboardEvent, view: import('@codemirror/view').EditorView) => boolean | void} [config.onKeyDown]
554
- * @param {Function} [config.onLint]
555
- * @param {Boolean} [config.readOnly]
556
- * @param {String} [config.value]
557
- * @param {Variable[]} [config.variables]
558
- * @param {Variable[]} [config.builtins]
559
- * @param {Object} [config.contentAttributes]
560
- * @param {String} [config.placeholder]
561
- */
562
- function FeelEditor({
563
- extensions: editorExtensions = [],
564
- dialect = 'expression',
565
- parserDialect,
566
- container,
567
- contentAttributes = {},
568
- tooltipContainer,
569
- onChange = () => {},
570
- onKeyDown = () => {},
571
- onLint = () => {},
572
- placeholder: placeholder$1 = '',
573
- readOnly = false,
574
- value = '',
575
- builtins = domifiedBuiltins,
576
- variables = []
577
- }) {
578
-
579
- const changeHandler = EditorView.updateListener.of((update) => {
580
- if (update.docChanged) {
581
- onChange(update.state.doc.toString());
582
- }
583
- });
584
-
585
- const lintHandler = EditorView.updateListener.of((update) => {
586
- const diagnosticEffects = update.transactions
587
- .flatMap(t => t.effects)
588
- .filter(effect => effect.is(setDiagnosticsEffect));
589
-
590
- if (!diagnosticEffects.length) {
591
- return;
592
- }
593
-
594
- const messages = diagnosticEffects.flatMap(effect => effect.value);
595
-
596
- onLint(messages);
597
- });
598
-
599
- const keyHandler = EditorView.domEventHandlers(
600
- {
601
- keydown: onKeyDown
602
- }
603
- );
604
-
605
- if (typeof tooltipContainer === 'string') {
606
- tooltipContainer = /** @type {HTMLElement} */ (document.querySelector(tooltipContainer));
607
- }
608
-
609
- const tooltipLayout = tooltipContainer ? tooltips({
610
- tooltipSpace: function() {
611
- return /** @type {HTMLElement} */ (tooltipContainer).getBoundingClientRect();
612
- }
613
- }) : [];
614
-
615
- const extensions = [
616
- autocompletion(),
617
- coreConf.of(configure({
618
- dialect,
619
- builtins,
620
- variables,
621
- parserDialect
622
- })),
623
- bracketMatching(),
624
- indentOnInput(),
625
- closeBrackets(),
626
- EditorView.contentAttributes.of(contentAttributes),
627
- changeHandler,
628
- keyHandler,
629
- keymap.of([
630
- ...defaultKeymap,
631
- ]),
632
- linter,
633
- lintHandler,
634
- tooltipLayout,
635
- placeholderConf.of(placeholder(placeholder$1)),
636
- theme,
637
- ...editorExtensions
638
- ];
639
-
640
- if (readOnly) {
641
- extensions.push(EditorView.editable.of(false));
642
- }
643
-
644
- this._cmEditor = new EditorView({
645
- state: EditorState.create({
646
- doc: value,
647
- extensions
648
- }),
649
- parent: container
650
- });
651
-
652
- return this;
653
- }
654
-
655
- /**
656
- * Replaces the content of the Editor
657
- *
658
- * @param {String} value
659
- */
660
- FeelEditor.prototype.setValue = function(value) {
661
- this._cmEditor.dispatch({
662
- changes: {
663
- from: 0,
664
- to: this._cmEditor.state.doc.length,
665
- insert: value,
666
- }
667
- });
668
- };
669
-
670
- /**
671
- * Sets the focus in the editor.
672
- */
673
- FeelEditor.prototype.focus = function(position) {
674
- const cmEditor = this._cmEditor;
675
-
676
- // the Codemirror `focus` method always calls `focus` with `preventScroll`,
677
- // so we have to focus + scroll manually
678
- cmEditor.contentDOM.focus();
679
- cmEditor.focus();
680
-
681
- if (typeof position === 'number') {
682
- const end = cmEditor.state.doc.length;
683
- cmEditor.dispatch({ selection: { anchor: position <= end ? position : end } });
684
- }
685
- };
686
-
687
- /**
688
- * Returns the current selection ranges. If no text is selected, a single
689
- * range with the start and end index at the cursor position will be returned.
690
- *
691
- * @returns {import('@codemirror/state').EditorSelection} selection - Selection object with ranges array
692
- */
693
- FeelEditor.prototype.getSelection = function() {
694
- return this._cmEditor.state.selection;
695
- };
696
-
697
- /**
698
- * Set variables to be used for autocompletion.
699
- *
700
- * @param {Variable[]} variables
701
- */
702
- FeelEditor.prototype.setVariables = function(variables) {
703
-
704
- const config = get(this._cmEditor.state);
705
-
706
- this._cmEditor.dispatch({
707
- effects: [
708
- coreConf.reconfigure(configure({
709
- ...config,
710
- variables
711
- }))
712
- ]
713
- });
714
- };
715
-
716
- /**
717
- * Update placeholder text.
718
- *
719
- * @param {string} placeholder
720
- */
721
- FeelEditor.prototype.setPlaceholder = function(placeholder$1) {
722
- this._cmEditor.dispatch({
723
- effects: placeholderConf.reconfigure(placeholder(placeholder$1))
724
- });
725
- };
726
-
727
- export { FeelEditor as default };