{"id":22202182,"url":"https://github.com/rumkin/calculon","last_synced_at":"2025-06-13T22:32:21.148Z","repository":{"id":143805245,"uuid":"74413961","full_name":"rumkin/calculon","owner":"rumkin","description":"Calculon is a safe js-like language for angluar-like html expressions","archived":false,"fork":false,"pushed_at":"2017-01-25T13:47:07.000Z","size":114,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-04T01:11:50.312Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rumkin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2016-11-21T23:08:34.000Z","updated_at":"2017-01-15T18:54:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"192968ef-00ea-4961-a2af-a81f0fc95bce","html_url":"https://github.com/rumkin/calculon","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Fcalculon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Fcalculon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Fcalculon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Fcalculon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rumkin","download_url":"https://codeload.github.com/rumkin/calculon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245377989,"owners_count":20605377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-12-02T16:12:39.985Z","updated_at":"2025-03-25T00:59:23.166Z","avatar_url":"https://github.com/rumkin.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Calculon\n\nRich expressions parser and compiler for DSL written on JavaScript. Calculon is\na subset of JavaScript created for template string rendering. It's inspired by\nmany languages such a Ruby to create user friendly syntax. It simple but\nexpressive and contains construction destructuring, array slicing, filters,\npipelining, ast inlining and other cool things.\n\nCalculon is safe and doesn't allow to access to JS properties or overwrite them\nfrom expressions.\n\nCalculon is fault tolerant and tries not to produce any exceptions on runtime.\nSo undefined filters and variables are normal and produces undefined values.\n\n```calculon\n1 | add 2 | mul 5 == 15 // -\u003e true\n\"b\" | concat \"a\" _ \"c\" | toUpperCase // -\u003e \"ABC\"\n`Hi there ${ n | plural \"time\" \"times\" }!` -\u003e Hi there 1 time.\n{\n  background: n | gte 1 \"red\" \"green\",\n  border: `${ [0, 2][n] } + px solid`\n} // -\u003e {background: red, border: '2px solid'}\n[1, 2, 3, 4][0..n] // -\u003e [0, 1]\n```\n\n## Installation\n\nVia npm:\n\n```bash\nnpm i calculon\n```\n\n### Usage\n\n```javascript\nconst Calculon = require('calculon');\nconst calc = Calculon.new({\n  primitives: {\n    number: {\n      add(a, b) {\n        return a + b;\n      }\n    }\n  },\n  filters: {\n    add(a, b) {\n      return a + b;\n    }\n  }\n});\n\ncalc('1.add(1)'); // -\u003e 2\ncalc('1 | add 1'); // -\u003e 2\n```\n\n## Syntax\n\n### Primitives\n\nCalculon contains basic primitives for numbers, strings and booleans.\n\n#### Numbers\n\nNumbers could be defined like so:\n\n```calculon\n10\n-10\n1000\n1_000\n-1_023.12 == -1023.12\n```\n\nCurrently calculon supports decimal numbers only.\n\n#### Strings\n\nStrings should be surrounded with single quote, double quote or akut:\n\n```calculon\n\"Hello\"\n'Hello'\n`Hello`\n:Hello\n```\n\nStrings with akut could contain calculon expressions to evaluate:\n\n```calculon\n`Hello ${ username | toUpperCase } `\n```\n\n#### Booleans\n\nBooleans are the same as in JS:\n\n```calculon\ntrue\nfalse\n```\n\n### Arrays\n\nCalculon support arrays:\n\n```calculon\n[1, 2, 3]\n```\n\nArray could contain values of any type. To get array value by its index use square brackets:\n\n```calculon\n[1,2,3][0] // -\u003e 1\n```\n\nAlso array could return the last item by magic index `*`:\n\n```calculon\n[1,2,3,4][*] // -\u003e 4\n```\n\n### Objects\n\nObjects are the same as in JS:\n\n```calculon\n{a: 1}\n{\"a\": 1}\n{[\"a\" + \"a\"]: 1}\n```\n\n### AST\n\nCalculon allow to use ast as a first class citizen. So it allow to pass AST as an arugment or use in other way:\n\n```calculon\n@{a.toString()\n[@{a | toLowerCase}, @{1 + a}]\n```\nExample below creates single ast and array of two ast values.\n\n### Smart destructuring\n\n#### Arrays\n\nTo get slice from array you can just use simple range extraction:\n\n```calculon\n[1, 2, 3, 4][1..2] // -\u003e [2, 3]\n```\n\nOr use another array:\n\n```calculon\n[1,2,3,4][[1,2]] // -\u003e [2, 3]\n```\n\n#### Objects\n\nCalculon allow to get exact keys from object and put it into new object:\n\n```calculon\n{a: 1, b: 2, c: 3}['a', 'c'] // -\u003e {a: 1, c: 3}\n```\n\nNested objects can be destructured too:\n\n```calculon\n{a: {b: 1, c: 2}}['a':['c']] // -\u003e {a: {c: 2}}\n```\n\n\n### Filters and pipes\n\nCalculon contains filters syntax:\n\n```calculon\n\"a\" | toUpperCase // -\u003e \"A\"\n```\n\nFilters could be piped:\n\n```calculon\n\"Hello\" | toUpperCase | reverse // -\u003e \"OLLEH\"\n```\n\nFilters could have arguments separated with whitespace:\n\n```\n\"0\" | repeat 5 // -\u003e '00000'\n```\n\nTo pass filtered value to exact position in filters arguments use underscore:\n\n```\n\"b\" | concat \"a\" _ \"c\" // -\u003e \"abc\"\nusers | map :name // users=[{name:'john'}, {name: 'jack'}, {name: 'jim'}] -\u003e ['john', 'jack', 'jim']\n```\n\n#### Define filter\n\nFilters are defines when calculon instantiates with `options.filters`:\n\n```javascript\nvar eval = Calculon.new({\n  filters: {\n    add(a, b) {\n      return a + b;\n    },\n  },\n});\n```\n\n### Primitives' methods\n\nCalculon allows to override methods own methods for primitives. For example we\ncan define `not` method for booleans to invert boolean value:\n\n```javascript\nvar eval = Calculon.new({\n  primitivies: {\n    boolean: {\n      not(value) {\n        return !value;\n      }\n    }\n  }\n});\n\neval('true.not()'); //-\u003e false\neval('false.not()'); //-\u003e true\neval('isOk.not()', {isOk: true}); //-\u003e false\n```\n\n## Security\n\nCalculon doesn't allow to overwrite object constructors (or even get it) so it's\nsafe to use with untrusted code. Also calculon is read only and it has no\nconstructions to modify values or variables.\n\n## Credentials\n\nParser is made with [PegJS](https://www.npmjs.com/package/pegjs) powerful\nand simple parser generator.\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frumkin%2Fcalculon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frumkin%2Fcalculon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frumkin%2Fcalculon/lists"}