@wemake4u/feel-editor
v2.3.0
Published
`<feel-editor>` is an Angular editor of FEEL expressions (DMN) built on CodeMirror 6: it extends `CodeEditorComponent` of `@wemake4u/code-editor`. The editor core (`FeelEditor`, in `src/lib/feel`) is part of this package.
Readme
FeelEditor
<feel-editor> is an Angular editor of FEEL expressions (DMN) built on CodeMirror 6: it extends
CodeEditorComponent of @wemake4u/code-editor. The editor core (FeelEditor, in src/lib/feel) is part of
this package.
- Syntax colors and linting of FEEL, in the two dialects: expressions and unary tests (the input entries of a decision table).
- Completion of the names in scope (also names with spaces and the fields of contexts) and of the built-in functions, with their description.
- Formatting of an expression (
format(),formatFeel) that never changes its meaning. - Coloring without an editor (
colorizeFeel), for pages that show many expressions at once. - Angular forms: ControlValueAccessor (the model is the text).
<feel-editor formControlName="expression"
ariaLabel="Expression"
dialect="expression"
[variables]="variables"
[history]="true"
minHeight="30px" maxHeight="200px"
(lint)="problems = $event" />Inputs
| Input | Default | |
|---|---|---|
| dialect | 'expression' | 'unaryTests': the input entries of a decision table (< 18, "A", "B", -). |
| variables | none | The names in scope, FeelEntry[]: variables (FeelVariable, with entries for the fields of a context and isList) and functions (FeelFunction, with params). They can change while the editor is open. |
| builtins | the standard FEEL functions | An array adds functions of your own to the standard ones (parseBuiltins turns { name: 'f(a, b)', description } into FeelFunction); null: none. |
| history | from code-editor | Undo and redo (Ctrl+Z, Ctrl+Y), also of a formatting. |
| readonly, disabled, placeholder, lineNumbers, lintGutter, folding, lineWrapping, bracketMatching, closeBrackets, highlightActiveLine, indentOnInput, indentWithTab, syntaxHighlighting | | From code-editor. |
| ariaLabel, ariaDescribedBy | | Accessible name and description of the text area. |
| invalid | false | Error look (also automatic when the control is invalid). |
| updateMode | from code-editor | 'change': the model at each change; 'blur': when the editor loses the focus. |
| embedded | false | No border and padding, for an editor inside another component (a table cell). |
| minHeight, maxHeight | | CSS heights of the editor. |
dialect and builtins recreate the editor; variables is applied to the open editor.
Outputs
| Output | |
|---|---|
| change | The text, when the model is updated. |
| keydown | The keys pressed in the editor. |
| lint | The CodeMirror diagnostics (FEEL syntax) when they change. |
Methods
| Method | |
|---|---|
| format(options?) | Formats the expression with the dialect and the names of the editor (see Formatting); returns the FeelFormatResult. Undone with Ctrl+Z when history is on. |
The core: FeelEditor
For hosts that build their own component around the editor (e.g. the DMN editor): new FeelEditor(options) with
FeelEditorOptions:
| Option | |
|---|---|
| container | The element that holds the editor (required). |
| dialect, parserDialect | 'expression' or 'unaryTests'. |
| value, placeholder, readOnly | The text, the text shown when empty, read only. |
| variables, builtins | As the inputs of the component (here builtins replaces the standard ones). |
| onChange, onKeyDown, onLint | Callbacks: the text, the keys, the lint issues. |
| contentAttributes, tooltipContainer | Attributes of the editable element; where the tooltips are attached. |
| extensions | More CodeMirror extensions. |
| history | Undo and redo (Ctrl+Z, Ctrl+Y). Default false. |
| formatShortcut | Shift+Alt+F formats the expression. Default false. |
Methods: getValue(), setValue(text), focus(position?), getSelection(), setVariables(entries),
setPlaceholder(text), format(options?).
Formatting
formatFeel(text, options) formats a FEEL expression: one space around the operators and after commas and colons,
line breaks and indentation only where the expression does not fit (contexts and lists with an entry per line,
if/then/else and chains of else if aligned, for/return, some/every/satisfies, chains of + - and or broken before the
operator, the arguments of long calls). As in Prettier, a context or a list written with a line break right after
{ or [ stays on several lines, an entry per line, even when short (remove that line break to put it back on one
line). Strings, comments and names are kept as they are.
It returns { ok: true, text, changed }, or { ok: false, reason } when the text has syntax errors (syntax) or
the result would not be the same expression (unsafe): the text is never changed in meaning.
Options (FeelFormatOptions): dialect (expression or unaryTests), context (the names in scope, for the
names with spaces), indent (2), width (80), maxInline (60, the longest context or list on one line).
FeelEditorComponent.format() and FeelEditor.format() format the text of the editor with its dialect and names
in scope, also in read-only mode, where only the text shown changes.
import { formatFeel } from '@wemake4u/feel-editor';
const result = formatFeel('if eta>=18 then "adulto" else "minore"', { width: 30 });
// { ok: true, changed: true, text: 'if eta >= 18\nthen "adulto"\nelse "minore"' }Coloring without an editor
colorizeFeel(text, options) colors a FEEL text without creating an editor, with the same parser, names and
colors as FeelEditor, and lints it as the editor does. It is meant for pages that show many expressions at once
(e.g. the cells of a table): show the colored text and create a <feel-editor> only for the expression being
edited.
It returns { tokens, problems }: tokens covers the whole text in order, each { text, from, to, kind? } with
kind one of variableName, number, string, bool, function, control, comment (plain text has no
kind); problems are the syntax problems { from, to, severity, message }. FEEL_TOKEN_STYLES gives the color
(and weight) of each kind, the same the editor uses.
Options (FeelColorizeOptions): dialect (expression or unaryTests), parserDialect, variables (the names
in scope, for the names with spaces), builtins (default: the standard FEEL functions of the editor), lint
(default true).
import { colorizeFeel, FEEL_TOKEN_STYLES } from '@wemake4u/feel-editor';
const { tokens, problems } = colorizeFeel('Reddito mensile * 0.35', {
variables: [{ name: 'Reddito mensile' }],
});
// tokens: [{ text: "Reddito mensile", kind: "variableName", ... }, { text: " * " }, { text: "0.35", kind: "number" }]Exports
FeelEditorComponent, FeelEditor, formatFeel, colorizeFeel, FEEL_TOKEN_STYLES, parseBuiltins,
parseBuiltin, getDefaultBuiltins; the types FeelEntry, FeelEntryBase, FeelVariable, FeelFunction,
FeelFunctionParam, FeelDialect, FeelEditorOptions, FeelFormatOptions, FeelFormatResult,
FeelColorizeOptions, FeelColorizeResult, FeelToken, FeelTextProblem, FeelTokenKind, BuiltinInfo.
Dependencies
As in package.json.
Peer dependencies, installed by the application:
| Package | Version | |
|---|---|---|
| @angular/core, @angular/common, @angular/forms | >=19.0.0 <23.0.0 | Angular 19 to 22. |
| @wemake4u/code-editor | ^2.0.0 | The base component (CodeEditorComponent). |
Dependencies, installed with the package:
| Package | Version | |
|---|---|---|
| lang-feel | ^2.3.0 | The FEEL language for CodeMirror. |
| lezer-feel | ^1.9.0 | The FEEL parser. |
| @bpmn-io/feel-lint | ^1.4.0 | The FEEL lint (syntax problems), in the editor and in colorizeFeel. |
| @codemirror/autocomplete, @codemirror/commands, @codemirror/language, @codemirror/lint, @codemirror/state, @codemirror/view | ^6 | CodeMirror 6. |
| @lezer/common, @lezer/highlight | ^1.2 | Syntax trees and highlighting of CodeMirror. |
| marked | 15.0.7 | The descriptions of the built-in functions (Markdown) in the completion. |
| min-dom | ^4.2.1 | The elements of the descriptions in the completion. |
| tslib | ^2.3.0 | TypeScript runtime helpers. |
Third-party licenses
The licenses of the dependencies, and of the code derived from bpmn-io/feel-editor that is included in
src/lib/feel, are listed in THIRD_PARTY_LICENSES.txt.
