{"id":19687305,"url":"https://github.com/isqua/syntax-sandbox","last_synced_at":"2025-07-29T00:33:07.707Z","repository":{"id":201072608,"uuid":"686085906","full_name":"isqua/syntax-sandbox","owner":"isqua","description":"Early prototype of custom query language editor","archived":false,"fork":false,"pushed_at":"2025-07-17T19:28:52.000Z","size":452,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-17T22:55:15.868Z","etag":null,"topics":["codemirror","codemirror6","lezer","lezer-grammar","query-language"],"latest_commit_sha":null,"homepage":"https://isqua.github.io/syntax-sandbox/","language":"TypeScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/isqua.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2023-09-01T17:52:42.000Z","updated_at":"2025-07-17T19:28:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"94689ab6-f687-4386-8f29-67bfd05e0b61","html_url":"https://github.com/isqua/syntax-sandbox","commit_stats":null,"previous_names":["isqua/syntax-sandbox"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/isqua/syntax-sandbox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isqua%2Fsyntax-sandbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isqua%2Fsyntax-sandbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isqua%2Fsyntax-sandbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isqua%2Fsyntax-sandbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/isqua","download_url":"https://codeload.github.com/isqua/syntax-sandbox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isqua%2Fsyntax-sandbox/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267610345,"owners_count":24115434,"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","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["codemirror","codemirror6","lezer","lezer-grammar","query-language"],"created_at":"2024-11-11T18:33:39.823Z","updated_at":"2025-07-29T00:33:07.699Z","avatar_url":"https://github.com/isqua.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# syntax-sandbox\n\nThis repository contains my experiment on creating a query language for [the CodeMirror](https://codemirror.net/). It is a demo, not a reusable package.\n\nThe application demonstrates how to create custom Query Language for CodeMirror using [the Lezer Parser System](https://lezer.codemirror.net/). It supports autocomplete, syntax highlight, validation, and custom UI decorations.\n\nMy goal was to create query language that is unbound from an application domain. So the grammar part defines just a syntax for queries, but does not contains any properties or values. Thus, domain specific data can be defined independently of grammar.\n\n## Architecture\n\n![Components Schema](./docs/arch.drawio.svg)\n\nAt the application level users of the component describe available properties and values. Please see the example in [src/data](./src/data/properties.ts). They can also define a `Suggest` and/or `Validator` classes to implement some custom logic. Then they need to instantiate a data model with defined properties and pass it to the `Editor`, see [src/main.ts](./src/main.ts). Optionally, they can also create a `Decorator` to add some specific UI features for different properties and values: [src/decorator](./src/decorator/decorator.ts).\n\nThen, the `Editor` renders a CodeMirror instance with some plugins. In the [src/language](./src/language/language.ts) multiple CodeMirror plugins are instantiated using defined data model and decorator. The parser is generated using Lezer from the [QueryLanguage.grammar](./src/language/grammar/QueryLanguage.grammar). The mapper from syntax tree to the MongoDB-like JSON is implemented in [src/language/query](./src/language/query/query.ts).\n\nThe `Editor` emits change event with the result of parsing. The result is shaped as MongoDB-like JSON to show the query tree.\n\nWhat can be improved:\n\n- Asyncronous suggest for data-intensive applications\n- More operators, for example for numeric fields\n- Better UX for different kind of values, for example datepicker for date and time\n\n## Commands\n\nStart:\n\n```\nnpm run dev\n```\n\nRebuild grammar:\n\n```\nnpm run grammar\n```\n\nRun tests:\n\n```\nnpm test\n```\n\n## File Structure\n\n1. [main.ts](./src/main.ts) is an entrypoint. It finds the root DOM element and render the app.\n1. **Domain Specific Data**\n    1. [data](./src/data) contains some data and declarations that are related to a specific app (e.g. task manager)\n        1. [properties](./src/data/properties.ts) describes possible properties and its values available for QL\n        1. [persons](./src/data/persons.ts) contains some imaginable “users” that could be used for filtering by an author\n    1. [decorator](./src/decorator) defines how to replace query tokens with rich HTML widgets, e.g. it replaces usernames of authors with their names\n1. **Universal query language:** [language](./src/language) contains a set of CodeMirror plugins that implement work with the query language defined in Grammar\n    1. [grammar](./src/language/grammar) contains everything about parsing a text to an AST\n        1. [QueryLanguage.grammar](./src/language/grammar/QueryLanguage.grammar) grammar definition in terms of [The Lezer Parser System](https://lezer.codemirror.net/). The parser itself is autogenerated based on the grammar file.\n    1. [query](./src/language/query/query.ts) a helper to transform AST to query tree, it helps to visualize the parsing result and [test](./src/language/query/query.spec.ts) the parser\n    1. [highlighter](./src/language/highlighter) highlights different semantic tokens with different colors\n    1. [linter](./src/language/linter) shows errors for improper tokens\n    1. [decorator](./src/language/decorator) shows user-defined widgets for some tokens\n    1. [autocomplete](./src/language/autocomplete) suggests related tokens to a user\n    1. [language](./src/language/language.ts) combines them all\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisqua%2Fsyntax-sandbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fisqua%2Fsyntax-sandbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisqua%2Fsyntax-sandbox/lists"}