{"id":15160198,"url":"https://github.com/discretetom/tmlb","last_synced_at":"2026-01-21T01:03:00.797Z","repository":{"id":206509022,"uuid":"716830594","full_name":"DiscreteTom/tmlb","owner":"DiscreteTom","description":"TmLanguage builder.","archived":false,"fork":false,"pushed_at":"2023-12-28T00:57:01.000Z","size":155,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-31T03:32:15.474Z","etag":null,"topics":["javascript","r-compose","regex","regexp","syntax","syntax-highlighting","tmlanguage","typescript","vscode","vscode-extension"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/DiscreteTom.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}},"created_at":"2023-11-10T00:53:21.000Z","updated_at":"2023-11-11T08:04:59.000Z","dependencies_parsed_at":"2024-10-31T20:33:02.950Z","dependency_job_id":"a5e4507d-0624-4f1b-a59a-b6c789bb1054","html_url":"https://github.com/DiscreteTom/tmlb","commit_stats":{"total_commits":31,"total_committers":1,"mean_commits":31.0,"dds":0.0,"last_synced_commit":"774171ec78524e4190f1167301e22d1b764bef8a"},"previous_names":["discretetom/tmlb"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiscreteTom%2Ftmlb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiscreteTom%2Ftmlb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiscreteTom%2Ftmlb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiscreteTom%2Ftmlb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DiscreteTom","download_url":"https://codeload.github.com/DiscreteTom/tmlb/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247712401,"owners_count":20983676,"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":["javascript","r-compose","regex","regexp","syntax","syntax-highlighting","tmlanguage","typescript","vscode","vscode-extension"],"created_at":"2024-09-26T22:40:26.291Z","updated_at":"2026-01-21T01:03:00.787Z","avatar_url":"https://github.com/DiscreteTom.png","language":"TypeScript","readme":"# tmlb\n\n[![npm](https://img.shields.io/npm/v/tmlb?style=flat-square)](https://www.npmjs.com/package/tmlb)\n![coverage](https://img.shields.io/codecov/c/github/DiscreteTom/tmlb?style=flat-square)\n![build](https://img.shields.io/github/actions/workflow/status/DiscreteTom/tmlb/publish.yml?style=flat-square)\n![license](https://img.shields.io/github/license/DiscreteTom/tmlb?style=flat-square)\n\nTmLanguage builder.\n\nGenerate TmLanguage JSON files from TypeScript. Type hint. Avoid escape hell.\n\nTry it online in the [playground](https://dttk.discretetom.com/js-playground?crushed=%28%27dependencieZ%27Atmlb%25400.1Rtmlbx%7EA%2540discretetom%252Fr-cL%25400.2Rr-cLx%255D%7EcellZMPrepareEt%2520IcLWHrCLqconst%2520IkWHtmlbUtrue%7Eid%21V684787179%29%252CMConstructEt%2520zHnew%2520k%257BIscopeNameGFsource.testF*repo%257BFQsFKInameGFQ.line.testFKmatchG__%252F%252F.source*append%257BIincludeGF%2523QsF*build%257BIvalidateGtrueW%257D%253BDX%29%252CMOutputEole.log%257BJSON.stringify%257BzKnullK2%257D%257DDY%29%255D%7EpanelZVX%252CVY%255D%29*W%257Dq%2520%2520%2520%2520.Ahttps%253A%252F%252Fcdn.jsdelivr.net%252Fnpm%252FDUfalse%7Eid%21VE%27%7Ecode%21%27consF%255C%27G%253A%2520H%2520%253D%2520I%28%2520K%252C%2520LomposeM%28%27name%21%27QcommentR.2%252Fdist%252FU%27%7Ereadonly%21V1703W%2520%29X684847765Y724729746Zs%21%255B_%252F%255C%255CkTmBuilderq%255Cr%255Cnx.min.js%27zlanguage%2501zxqk_ZYXWVURQMLKIHGFEDA*_).\n\n## Install\n\n```bash\nyarn add tmlb\n```\n\n## Basic Usage\n\n\n\n```ts\nconst language = new TmBuilder({ scopeName: \"source.test\" })\n  .repo(\"comments\", { name: \"comment.line.test\", match: /\\/\\//.source })\n  .append({ include: \"#comments\" })\n  .build({ validate: true });\n```\n\n\n\nwill yield:\n\n\n\n```json\n{\n  \"$schema\": \"https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json\",\n  \"scopeName\": \"source.test\",\n  \"patterns\": [\n    {\n      \"include\": \"#comments\"\n    }\n  ],\n  \"repository\": {\n    \"comments\": {\n      \"name\": \"comment.line.test\",\n      \"match\": \"\\\\/\\\\/\"\n    }\n  }\n}\n```\n\n\n\n\u003e See: [examples/hello-world](./examples/hello-world).\n\n## Advanced\n\nWith [r-compose](https://github.com/DiscreteTom/r-compose), construct readable and maintainable `RegExp`.\n\n\u003cdetails\u003e\u003csummary\u003eClick to Expand\u003c/summary\u003e\n\n```ts\nconst language = new TmBuilder({ scopeName: \"source.test\" })\n  .append({\n    name: \"comment.line.double-slash.test\",\n    match: compose(({ concat, escape, select }) =\u003e\n      concat(\n        escape(\"//\"),\n        /.*/, // in non-multiline mode, the /./ doesn't match the /\\n/\n        select(/\\n/, /$/),\n      ),\n    ).source,\n  })\n  .append({\n    name: \"comment.block.test\",\n    begin: compose(({ escape }) =\u003e escape(\"/*\")).source,\n    end: compose(({ escape, select }) =\u003e select(escape(\"*/\"), /$/)).source,\n  })\n  .append({\n    name: \"keyword.other.test\",\n    match: compose(({ concat, select }) =\u003e\n      concat(/\\b/, select(\"if\", \"else\", \"while\"), /\\b/),\n    ).source,\n  })\n  .append({\n    name: \"string.quoted.double.test\",\n    match: compose(({ concat, any, select, not }) =\u003e\n      concat(\n        /\"/,\n        any(\n          select(\n            /\\\\./, // any escaped character\n            not(concat(/\\\\/, /\"/)), // any char except a backslash or the close quote\n          ),\n        ),\n        select(/\"/, /$/),\n      ),\n    ).source,\n  })\n  .build({ validate: true });\n```\n\n\u003c/details\u003e\n\n\u003e See [examples/r-compose](./examples/r-compose).\n\n## [CHANGELOG](./CHANGELOG.md)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiscretetom%2Ftmlb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdiscretetom%2Ftmlb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiscretetom%2Ftmlb/lists"}