{"id":29131458,"url":"https://github.com/bpmn-io/feelers","last_synced_at":"2026-03-09T11:02:48.965Z","repository":{"id":65921991,"uuid":"602499350","full_name":"bpmn-io/feelers","owner":"bpmn-io","description":"A text templating solution built on top of FEEL","archived":false,"fork":false,"pushed_at":"2026-02-12T14:14:18.000Z","size":1328,"stargazers_count":14,"open_issues_count":14,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-02-12T22:58:40.890Z","etag":null,"topics":["dmn","feel","javascript","template"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bpmn-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-02-16T10:43:45.000Z","updated_at":"2026-02-10T13:36:03.000Z","dependencies_parsed_at":"2024-03-26T01:25:39.577Z","dependency_job_id":"18a00c94-26fc-4e34-a91d-20db3c8c88b8","html_url":"https://github.com/bpmn-io/feelers","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/bpmn-io/feelers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpmn-io%2Ffeelers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpmn-io%2Ffeelers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpmn-io%2Ffeelers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpmn-io%2Ffeelers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bpmn-io","download_url":"https://codeload.github.com/bpmn-io/feelers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpmn-io%2Ffeelers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30291843,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dmn","feel","javascript","template"],"created_at":"2025-06-30T05:33:38.339Z","updated_at":"2026-03-09T11:02:48.956Z","avatar_url":"https://github.com/bpmn-io.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# feelers\n\n[![CI](https://github.com/bpmn-io/feelers/actions/workflows/CI.yml/badge.svg)](https://github.com/bpmn-io/feelers/actions/workflows/CI.yml)\n\nA templating solution built on top of [DMN](https://www.omg.org/spec/DMN/) FEEL. \nLike [mustache](https://mustache.github.io/) / [handlebars](https://handlebarsjs.com/) but with FEEL.\n\n![image](https://user-images.githubusercontent.com/17801113/222329383-c3e63077-e288-41e0-832d-7e71e331d76a.png)\n\n\n## What is inside\n\n* A [lezer](https://lezer.codemirror.net/) grammar and consequently parser for the templating language\n* A parseMixed language definition which brings `feelers` templating, `feel` parsing and an optional host language together\n* An editor for feelers, build on top of [codemirror](https://codemirror.net/)\n* An interpreter to fill your templates with data, powered by [feelin](https://github.com/nikku/feelin)\n* A simple playground to showcase the language \n\n\n## Usage \n\nFeelers is a string templating tool, and will return string text or error.\n\n```js\nimport { evaluate } from 'feelers';\n```\n\nA simple string will always be returned as-is.\n\n```js\nevaluate(\"My simple string\");\n// \"My simple string\"\n```\n\nIf your string is prefixed with an =, it will be evaluated as a single FEEL expression wrapped in a string conversion function.\n\n```js\nconst context = { secondNumber: 12 };\nevaluate(\"= 2 + secondNumber\", context);\n// \"14\"\n```\n\nFinally, if your string features feelers language features, the templating engine takes over.\n\n```js\nconst context = { user: \"Dave\" };\nevaluate(\"I'm sorry {{user}}, I'm afraid I can't do that.\", context);\n// I'm sorry Dave, I'm afraid I can't do that.\n```\n\n## Feelers templating language features\n\n### Inserts\n\nThe simplest feature of feelers is inserting FEEL evaluations within your text. You may provide a variable context for the underlying FEEL engine to reference. Within these scopes, you have access to all features of the FEEL engine.\n\n```js\nconst context = { user: \"Dave\", age: 24, hobbies: [ \"surfing\", \"coding\" ] };\n\nevaluate(`Hey there {{user}}, welcome. {{if age \u003e= 18 then \"Have a beer!\" else \"Here's some apple juice.\"}}`, context);\n// Hey there Dave. Have a beer!\n\nevaluate(`Hobbies: {{hobbies}}`, context);\n// Hobbies: [\"surfing\", \"coding\"]\n\nevaluate(`{{user}}-{{user}}-{{user}}`, context);\n// Dave-Dave-Dave\n```\n\n### Conditional sections\n\nTo simply display a section of the template, you may use a conditional section. While this can already be achieved via feel itself using `if then else`, this syntax is a lot easier to manage for large sections.\n\n```js\nconst conditionExample = `{{#if count(users) \u003e 1}}There are multiple users{{/if}}\n{{#if false}}This should not display{{/if}}\n{{#if true}}This should display{{/if}}`;\n\nconst context = { users: [ \"Bob\", \"Dave\" ] };\n\nevaluate(conditionExample, context);\n// There are multiple users\n// This should display\n```\n\n### Loops\n\nTo handle dealing with arrays of data graciously, you can make use of loop tags. A special variable `this` is create granting you access to the current loop's element.\n\n```js\nconst context = { user: \"Dave\", age: 24, hobbies: [ \"surfing\", \"coding\" ] };\nconst hobbyExpression = `{{user}}'s hobbies are:\n{{#loop hobbies}}\n- {{this}}\n{{/loop}}`;\n\nevaluate(hobbyExpression, context);\n/// Dave's hobbies are:\n/// - surfing\n/// - coding\n```\n\nLoops may be nested when dealing with more complex data. When `this` is an object, you may access its variables directly within the loop. Although `this.name` would also work in the below example\n\n```js\nconst context = {\n  users: [\n    {\n      name: \"Bob\",\n      hobbies: [ \"building\", \"wearing hardhats\" ]\n    },\n    {\n      name: \"Dave\",\n      hobbies: [ \"surfing\", \"coding\" ]\n    }\n  ]\n}\n\nconst complexLoops = `{{#loop users}}\n{{name}}'s hobbies:\n{{#loop hobbies}}\n- {{this}}\n{{/loop}}\n{{/loop}}\n`\n\nevaluate(complexLoops, context);\n// Bobs's hobbies:\n// - building\n// - wearing hardhats\n// Dave's hobbies:\n// - surfing\n// - coding\n```\n\n\u003e Loops actually create 4 helper variables: `this`, `parent`, `_this_` and `_parent_`. Parent refers to the context just outside of your loop, in case you need to refer to it. The underscored variants are fallbacks in case your context include variables named `this` and `parent`.\n\n## Build and run\n\nBuild the project in a Posix environment. On Windows, that is [Git Bash](https://gitforwindows.org/) or WSL. \n\nNote we currently support development environments with Node.js version 16 (and npm version 8). We encourage you to use a Node.js version manager (e.g., [`nvm`](https://github.com/nvm-sh/nvm) or [`n`](https://github.com/tj/n)) to set up the needed versions.\n\nPrepare the project by installing all dependencies:\n\n```sh\nnpm install\n```\n\nThen, depending on your use-case you may run any of the following commands:\n\n```sh\n# run all tests\nnpm run test\n\n# runs single-start test case for development\nnpm start\nnpm run start\n\n# generate the lezer parser from its grammar definition\nnpm run generate:parser\n\n# build all dependencies locally and spool up playground\nnpm run start:playground\n\n# build all dependencies locally and build playground\nnpm run build:playground\n```\n\n## Related\n\n* [lezer-feel](https://github.com/nikku/lezer-feel) - FEEL language definition for the [Lezer](https://lezer.codemirror.net/) parser system\n* [feel-playground](https://github.com/nikku/feel-playground) - Interactive playground to learn the FEEL language\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbpmn-io%2Ffeelers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbpmn-io%2Ffeelers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbpmn-io%2Ffeelers/lists"}