{"id":27642022,"url":"https://github.com/bathos/ecmascript-sublime","last_synced_at":"2025-04-23T23:52:15.004Z","repository":{"id":32171733,"uuid":"35745046","full_name":"bathos/Ecmascript-Sublime","owner":"bathos","description":"ECMAScript/JavaScript syntax (ES2015-ES2018, JSX, template highlighting, etc) with absurdly specific scopes","archived":false,"fork":false,"pushed_at":"2023-03-02T04:04:37.000Z","size":3191,"stargazers_count":88,"open_issues_count":14,"forks_count":8,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-23T23:52:05.950Z","etag":null,"topics":["ecmascript","es2015","es2016","es2017","sublime-text","syntax-highlighting"],"latest_commit_sha":null,"homepage":"","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/bathos.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}},"created_at":"2015-05-17T00:03:22.000Z","updated_at":"2023-09-29T20:19:42.000Z","dependencies_parsed_at":"2023-01-14T20:45:20.609Z","dependency_job_id":null,"html_url":"https://github.com/bathos/Ecmascript-Sublime","commit_stats":null,"previous_names":[],"tags_count":71,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2FEcmascript-Sublime","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2FEcmascript-Sublime/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2FEcmascript-Sublime/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2FEcmascript-Sublime/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bathos","download_url":"https://codeload.github.com/bathos/Ecmascript-Sublime/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250535081,"owners_count":21446506,"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":["ecmascript","es2015","es2016","es2017","sublime-text","syntax-highlighting"],"created_at":"2025-04-23T23:52:14.304Z","updated_at":"2025-04-23T23:52:14.960Z","avatar_url":"https://github.com/bathos.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Gitter](https://badges.gitter.im/Ecmascript-Sublime/community.svg)](https://gitter.im/Ecmascript-Sublime/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n\n# Ecmascript Sublime Syntax\n\nA sublime-syntax language definition for Ecmascript / Javascript / ES6 / ES2015\n/ Babel or what have you.\n\n\u003e Sublime syntax is only available in Sublime Text 3.0.\n\n**New in 2.5**\n\nAdded:\n\n- Logical assignment operators `\u0026\u0026=`, `??=` (`||=` was already present)\n- Ergonomic private field brand checks (`#foo in bar`)\n- Class static blocks\n- Import assertions\n\nRemoved:\n\n- The old bind operator proposal (`::`) has been dead for too many years to\n  justify keeping around. Goodbye old friend — you were actually pretty cool.\n- The scope `keyword.operator.assignment.conditional.mallet` was changed to\n  align with the pattern established for other augmented assignment operators.\n\nFixed:\n\n- Private generator methods no longer cause the class body context to stick\n  around past the end of the actual class body.\n\n**New in 1.6**\n\n- Nested syntax highlighting\n\nA common use of mutli-line template literals is to embed snippets of code. For instance, it could be snippets of HTML/CSS in the browser or SQL queries in node.js. For those longer template literals, it may be useful to enable nested syntax highlighting and make snippets of code easier to read. You can enable this by adding a block comment directive before a template literal. The complete syntax for the directive is as follows:\n\n```\n/* syntax: {SYNTAX_NAME} */ tag? `contents`\n```\n\nWhere the `tag` identifier may appear before or after the syntax block comment directive.\n\nOne of the perks to using this directive is that nested syntax blocks will inherit their usual functionality from their syntax definition, such as keybindings, snippets, autocompletions, and commenting:\n\n![Nested Syntaxes](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/nested-syntax-commenting.gif)\n\n**Supported Syntaxes:**\nHere's the list of currently supported syntaxes. I just went with all the ones that I assume are reasonable to use in the browser / node.js. Feel free to open an issue if you think another syntax would be useful.\n\n - `bash` | `shell`\n - `css`\n - `html`\n - `javascript` | `js`\n - `json`\n - `dot` (Graphviz)\n - `glsl` (GLslang for WebGL)\n - `lua`\n - `sql`\n - `xml`\n - `yaml`\n\nAnd here is a demonstration of all the currently supported syntaxes:\n\n![Nested Syntaxes](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/nested-syntax-highlighting.png)\n\n**New in 1.3**\n\n- Improvements to JSX scopes\n- JSX fragment support\n- Styled JSX support\n- Numeric separators support\n- BigInt support\n- Regexp features: dotall flag, property escapes, named captures, lookbehinds\n- Private instance fields\n\nThe Styled JSX additions merit some explanation. Earlier I half-assed this by\ndelegating to the CSS syntax definition when a JSX element with a template child\nmet the expected conditions for styled JSX. This doesn’t work well in practice\nbecause of the context sensitivity of the matches in the default CSS syntax\ndefinition — that is, in any position after interpolation, one was apt to get\nbad highlighting of the CSS since the it no longer knew if it was in a selector\nor a value, etc.\n\nTo address this, I added a deliberately forgiving and imprecise, simple (\"flat\")\nCSS matcher that is chiefly concerned with identifying lexical constructs for\nthis context. It uses a subset of the same scope names as the pre-bundled\nsublime CSS definition, but some of the scopes needed to be conflated due to the\nlost context awareness. The end result is CSS highlighting for Styled JSX\ntemplates that should be consistent and helpful in the great majority of cases\ndespite the lost distinctions.\n\n![Styled JSX example](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/styled-jsx-example.png)\n\nSupport for XML-style namespacing (ns colon) in JSX has been removed. It was in\nthe official grammar, but afaict it is not used in practice and isn’t supported\nby Babel’s JSX transform. Instead, scoping for member expression style component\nnames is improved, and html (lowercase / possible hyphens) names are scoped\ndistinctly from component references (pascalcase / es identifier).\n\nJSX fragments are a new way to indicate unkeyed groups of sibling nodes without\nthe need for extraneous divs: `\u003c\u003estuff\u003c/\u003e`.\n\nThe numeric separators proposal, which permits underscores within numeric\nliterals in most positions for improved readability of (mainly) hex and binary\nnotated numbers recently advanced to stage 3.\n\nThe BigInt proposal did as well. This is a new numeric type which is represented\nsyntactically by the suffixing \"n\" to a numeric literal.\n\nThe new RegExp features at stage 3 are the dotall (\"s\") flag, Unicode property\ncharacter class escapes, named capture groups and named capture backreferences,\nand positive and negative lookbehind assertions.\n\nPrivate instance fields (prefixed with '#') are included, with the caveat that\nfor practical reasons our definition can’t recognize most situations where a\nreference to such a property would be illegal.\n\nAlthough not very thorough, some color schemes have been updated a bit to\ntake advantage of the new scopes. (Always looking to add better color schemes\nif anybody has stuff to contribute!)\n\n**New in 1.1**\n\n- Most currently-stage-3 proposals (likely ES2018) and some stage 2 now covered.\n- Added new theme, Haydn\n\n![Haydn example](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/haydn-example.png)\n\n**New in 1.0**\n\n - Highlighting for merge conflict markers (cannot be perfect by its nature, but\n   better than nothing)\n - New theme, Sibelius, which is probably the first tasteful one. Between that\n   and the fact that this has been around for a year, bugs seem under control,\n   and a fair number of people are using this, I figured I should do '1.0'.\n\n![Sibelius example](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/sibelius.png)\n\n**New in 0.3**\n\n - JSX support\n - Adds source.js at root to increase compatibility with other packages\n\n![JSX example](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/example-jsx.png)\n\n**New in 0.2**\n\n - ‘Villa-Lobos’ theme\n - Async functions/methods/arrows are fully scoped the way generators are\n - \u003cstrike\u003ePromise and its methods are uniquely scoped\u003c/strike\u003e\n - Added ‘todo’ scope per http://www.sublimetext.com/forum/viewtopic.php?f=2\u0026t=18882\n - Various minor fixes, like allowing multiple spreads in an array literal\n\n\u003c!-- MarkdownTOC autolink=true bracket=round --\u003e\n\n- [Remaining Work](#remaining-work)\n- [Why Bother](#why-bother)\n- [Feature Coverage](#feature-coverage)\n  - [Non-JS extensions](#non-js-extensions)\n- [SublimeText Symbols](#sublimetext-symbols)\n- [Themes](#themes)\n- [Scopes](#scopes)\n  - [‘Official’ Scopes](#%E2%80%98official%E2%80%99-scopes)\n  - [Symbol Helper Scopes](#symbol-helper-scopes)\n  - [Interoperability Scopes](#interoperability-scopes)\n  - [Nested Syntax Scopes](#nested-syntax-scopes)\n- [About the Scope Conventions](#about-the-scope-conventions)\n- [More Infobarf for Someone Hypothetically Curious About the Definition Itself](#more-infobarf-for-someone-hypothetically-curious-about-the-definition-itself)\n  - [Why Is It Huge?](#why-is-it-huge)\n  - [Why Does Almost Everything Related to Expressions Appear Twice?](#why-does-almost-everything-related-to-expressions-appear-twice)\n  - [Does a Byzantine Maze of Context Transitions Make Highlighting Slow?](#does-a-byzantine-maze-of-context-transitions-make-highlighting-slow)\n  - [How Do I Break It?](#how-do-i-break-it)\n\n\u003c!-- /MarkdownTOC --\u003e\n\n## Remaining Work\n\n - I’d like to provide more themes with the definition package itself. The first\n   of these is ‘Excelsior,’ a kind of tacky attempt to demonstrate what can be\n   done that I’ve grown very fond of as it matured. It’s (mostly) complete now.\n   Still, it’s probably a bit much for many users.\n - The chunk of comment-delimited code starting at `assignmentExpression_NO_IN`\n   is actually possible to generate as a build step. Doing so will reduce the\n   chances of accidentally editing `assignmentExpression` without making the\n   corresponding change in `assignmentExpression_NO_IN`. I’m not sure if this\n   is worthwhile yet but it’s rolling around in my head.\n - A lot of the redundant-looking contexts exist for good reasons -- but not all\n   of them. There should be a clean-up and consolidation phase for contexts,\n   but more importantly, for patterns (or more often, pattern components).\n\n## Why Bother\n\nThere are at least three tmLanguage syntax definitions available for Javascript\nright now, and two support ES6+: JSNext and Babel Sublime (which I think is a\nfork of the former). Since they’re actually great already, I should explain what\nthe point of this fourth one is.\n\nSublime syntax is a brand new YAML syntax definition system that was introduced\nin Sublime Text dev build 3084 in April of 2015. Previously the only definition\nsystem Sublime supported was tmLanguage, originally from TextMate. In addition\nto cutting out the common build step of YAML -\u003e heinous XML, Sublime syntax\nintroduced a ‘context’ system for controlling what kinds of matches could take\nplace at a given juncture.\n\nContexts exist in a FILO stack. They can be pushed, popped, or ‘set’ (pop-push).\nAs in tmLanguage, matching cannot look past the current line, but using contexts\nbypasses some of the old consequences of that constraint, allowing more advanced\nand accurate scope assignment.\n\nThe number one reason why I made this is that it bothered me that many disparate\nelements of the grammar that just happened to look similar had to share generic\nscopes like `meta.brace.curly`. Thanks to Sublime syntax, Ecmascript Sublime\ndoesn’t have to have scopes that describe what something *looks* like. In the\ncase of braces, instead you will find scopes for block statements, object\nliterals, object binding patterns, class and function bodies, namespace imports,\netc -- the things that the braces mean.\n\nIt goes a bit beyond that, too. If you like, you can color if statements\ndifferently from loop statements for example. Generators, methods, and accessors\nare also individuated. In fact there are far more very specific scopes available\nthan anyone would ever reasonably use, but the point is to allow the theme\ndesigner to choose exactly which elements share colors (most good themes seem to\nhave relatively small palettes, really).\n\nHowever there are good reasons one might prefer one of the other choices for\nsyntax highlighting. For one, maybe you like a theme that plays better with one\nof the others. There are also differences with the approaches taken that may\nor may not suit your style. And finally, Ecmascript Sublime is a lot more rigid\nby nature, so invalid token sequences will not often pass unnoticed -- you may\nfind this useful, or you may find it bothersome.\n\nHere’s an early shot of Excelsior. I should add an updated one soon:\n\n![Early Excelsior example](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/example-okay.png)\n\nAnd here’s an example I’m fond of, using background colors to indicate the depth\nof matching groups in a regular expression:\n\n![Excelsior regex example](https://github.com/bathos/Ecmascript-Sublime/raw/master/examples/example-regex.png)\n\n## Feature Coverage\n\nECMAScript Sublime tries to stay current with the editor’s draft ES spec and any\nstage 4 proposals that introduce new syntax.\n\nSyntax-change proposals at earlier stages are supported in many cases. If a\nproposal gets withdrawn, we eventually remove it here too. To be included before\nstage 4, some combo of the following has to be true (but it’s not a science):\n\n - One or more engines have implemented it\n - The syntax is a reasonably settled aspect of the proposal\n - It’s specified clearly enough to not make us just guess\n - The proposal has high momentum/usage and the syntax is unlikely to change\n - The scope is small enough that it’s not costly to add or remove it\n\nSome earlier-than-stage-4 proposals (as of mid 2021) which are supported are:\n\n - [class static block](https://github.com/tc39/proposal-class-static-block)\n - [decorators](https://github.com/tc39/proposal-decorators)\n - [do expressions](https://github.com/tc39/proposal-do-expressions)\n - [`function.sent` meta property](https://github.com/tc39/proposal-function.sent)\n - [hashbang grammar](https://github.com/tc39/proposal-hashbang)\n - [import assertions](https://github.com/tc39/proposal-import-assertions)\n - [pipeline operator](https://github.com/tc39/proposal-pipeline-operator)\n - [export default from](https://github.com/tc39/proposal-export-default-from)\n\n### Non-JS extensions\n\nApart from the special handling for some tagged template strings, the only\nsyntactic feature supported which isn’t either JS or proposed JS is JSX. This\nis due to its popularity, low complexity (esp. w/ regard to how “isolatable” it\nis), and the unlikelihood of collision with new grammar features of JS proper.\nIt’s “safe.”\n\nTypeScript isn’t supported. It’s a distinct language that merits a distinct\nsyntax definition. TS syntactic extensions touch almost every production and\nmany occur in “unsafe” places that would make preserving the signature feature\nof ES Sublime — its relatively high specificity — very difficult.\n\n\u003e Also, despite its size, its grammar doesn’t seem to be specified! I thought\n\u003e that was pretty surprising when I first researched the viability here. I did\n\u003e find evidence of an early attempt at formalizing it, but it was pretty\n\u003e different from current TS (and it wasn’t a sound).\n\n## SublimeText Symbols\n\nA Sublime syntax definition involves more than the definition proper. These\nother items use the tmPreferences format to describe how automatic indentation\nworks, as well as how the \"symbol list\" is populated.\n\nIf you haven’t used Sublime symbol navigation before, I recommend checking it\nout. It’s a quick way to navigate the local file or all open files by keyboard\nshortcut (local is ctrl+r, global is shift+ctrl+r).\n\nIn Ecmascript Sublime, function, generator and class declarations will show up\nin Sublime’s symbol list, as well as default exports. It will also pick up\nfunction, generator, and class expressions that either have names or are\ndirectly assigned as part of a var, let or const statement. In this last case\nit will display the name of the variable the expression was bound to, and this\ncan include arrow functions.\n\nNote that only expressions that appear as the initializer in a variable or\nconstant declaration will be added to the list, so `const x = () =\u003e {}` is added\nas ‘arrow x,’ but `x = () =\u003e {}` is not.\n\nAll of these are local-only except classes. If people want the others to be\nglobal (except default exports obviously), we can change that. This is what made\nsense to me, but I pretty much only ever use the local list myself so I wasn’t\nsure what habitual global users would like to see.\n\n## Themes\n\nAt present there are four:\n\n - Carthage (eh)\n - Excelsior (most elaborate; I love it, but it’s too much)\n - Sibelius (most sane)\n - Villa-Lobos (okay)\n\nAs of version 0.1.2, I’ve also added many additional scopes and tweaked a number\nof things to increase interoperability with existing themes. Monokai, Cobalt,\nand Brogrammer were my reference themes; the goal was to make them match as\nclosely as is reasonable to how they look when using Babel Sublime. There’s a\nhandful of things that cannot be made to match because of what I guess could be\ncalled philosophical differences, but it should now be possible to use\nEcmascript Sublime with just about any theme without cringing.\n\nIf you’re interested in adding support for Ecmascript Sublime to your theme, or\nare developing a new theme with this in mind, you’ll probably want a list of\nthe targetable scopes...\n\n## Scopes\n\nIt goes without saying that only a minority of these will be truly useful to\nmost themers; on the other hand, you get to decide which those are.\n\n### ‘Official’ Scopes\n\nThese are the scopes generally intended for targeting. For readability, I’ve\nomitted the ‘.es’ suffix as well as ‘.begin.es’ and ‘.end.es’ for various\npunctuation, as these are only useful for debugging. Note that the scopes ending\nin ‘.regexp’ do not also have ‘.es’.\n\n- **Comments \u0026 Directives**\n  - `comment`\n  - `comment.block`\n  - `comment.line`\n  - `comment.line.shebang` (e.g. `#!/usr/bin/env node`)\n  - `comment.line.todo` (matches the words 'todo' and 'hack' within comments)\n  - `meta.comment.body` (content that is not part of the delimiter(s) or border)\n  - `meta.comment.border` (includes anything that seems like a border, and `//`)\n  - `meta.comment.box-drawing` (box drawing characters can be targeted)\n  - `meta.directive.use-strict` (the `'use strict'` directive)\n  - `punctuation.definition.comment` (the delimiting `//`, `/*` or `*/`)\n- **Constants \u0026 Literals**\n  - **General**\n    - `constant`\n    - `constant.language`\n    - `constant.language.boolean`\n    - `constant.language.boolean.false`\n    - `constant.language.boolean.true`\n    - `constant.language.null`\n    - `constant.language.undefined`\n  - **Arrays**\n    - `punctuation.definition.array`\n    - `punctuation.separator.array-element`\n  - **Numbers**\n    - `constant.language.infinity`\n    - `constant.language.nan`\n    - `constant.numeric`\n    - `constant.numeric.binary`\n    - `constant.numeric.decimal`\n    - `constant.numeric.hexadecimal`\n    - `constant.numeric.octal`\n    - `meta.numeric.exponent.digit`\n    - `meta.numeric.exponent.e`\n    - `meta.numeric.exponent.sign`\n    - `meta.numeric.prefix` (0x, 0b, 0o)\n    - `meta.numeric.suffix` ('n' of BigInt; may expand in the future)\n    - `punctuation.decimal`\n  - **Objects**\n    - `punctuation.definition.object` (the braces in `let x = { a: 1 };`)\n    - `punctuation.separator.key-value` (the colon in `let x = { a: 1 };` and the equals sign in the class properties proposal)\n    - `punctuation.separator.object-member` (commas between properties)\n    - `variable.other.readwrite.property.object-literal`\n    - `variable.other.readwrite.property.object-literal.allCap`\n    - `variable.other.readwrite.property.object-literal.initCap`\n    - `variable.other.readwrite.property.shorthand`\n    - `variable.other.readwrite.property.shorthand.allCap`\n    - `variable.other.readwrite.property.shorthand.initCap`\n    - `variable.other.readwrite.property.shorthand.rest`\n    - `variable.other.readwrite.property.shorthand.rest.allCap`\n    - `variable.other.readwrite.property.shorthand.rest.initCap`\n    - *see also Functions for accessors and methods*\n  - **Regexp**\n    - `constant.character.escape.control-char.regexp`\n    - `constant.character.escape.hexadecimal.regexp`\n    - `constant.character.escape.null.regexp`\n    - `constant.character.escape.pointless.regexp`\n    - `constant.character.escape.regexp`\n    - `constant.character.escape.unicode.regexp`\n    - `constant.other.character-class.predefined.regexp`\n    - `constant.other.character-class.set.regexp`\n    - `constant.other.character-class.unicode-property-name.regexp`\n    - `constant.other.character-class.unicode-property-value.regexp`\n    - `keyword.control.anchor.regexp`\n    - `keyword.operator.negation.regexp`\n    - `keyword.operator.or.regexp`\n    - `keyword.operator.quantifier.regexp`\n    - `keyword.other.back-reference.regexp`\n    - `meta.group.assertion.negative.regexp`\n    - `meta.group.assertion.positive.regexp`\n    - `meta.group.capturing.regexp`\n    - `meta.group.non-capturing.regexp`\n    - `meta.character-property.regexp`\n    - `punctuation.definition.assertion.negative.regexp`\n    - `punctuation.definition.assertion.positive.regexp`\n    - `punctuation.definition.character-class.dash.regexp`\n    - `punctuation.definition.character-class.regexp`\n    - `punctuation.definition.character-property.regexp`\n    - `punctuation.definition.string.regexp`\n    - `punctuation.definition.group.capturing.regexp`\n    - `punctuation.definition.group.non-capturing.regexp`\n    - `punctuation.separator.character-property-name-value.regexp`\n    - `string.regexp`\n    - `string.regexp.flags`\n    - `variable.other.named-capture.regexp`\n  - **Strings**\n    - `constant.character`\n    - `constant.character.escape`\n    - `constant.character.escape.hexadecimal` (e.g. `'\\\\x41'`)\n    - `constant.character.escape.newline` (a terminal backslash)\n    - `constant.character.escape.null` (i.e. `'\\\\0'`)\n    - `constant.character.escape.pointless` (an escape that is not needed)\n    - `constant.character.escape.unicode` (e.g. `'\\\\u0041'` or `'\\\\u{41}'`)\n    - `punctuation.definition.string`\n    - `punctuation.definition.string.interpolated`\n    - `punctuation.definition.string.interpolated.element`\n    - `punctuation.definition.string.quoted`\n    - `punctuation.definition.string.quoted.double`\n    - `punctuation.definition.string.quoted.double.parameter`\n    - `punctuation.definition.string.quoted.single`\n    - `punctuation.definition.string.quoted.single.parameter`\n    - `string`\n    - `string.interpolated`\n    - `string.quoted`\n    - `string.quoted.double`\n    - `string.quoted.single`\n- **Functions \u0026 Function-Related**\n  - **General**\n    - **Parameters**\n      - `entity.other.property-binding.parameter`\n      - `keyword.other.rest.parameter`\n      - `keyword.other.rest`\n      - `punctuation.definition.binding.array.parameter`\n      - `punctuation.definition.binding.object.parameter`\n      - `punctuation.separator.array-element.binding.parameter`\n      - `punctuation.separator.object-member.binding.parameter`\n      - `punctuation.separator.parameter`\n      - `punctuation.separator.property-binding.parameter`\n      - `variable.parameter`\n      - `variable.parameter.rest`\n    - **Execution \u0026 Do Expressions**\n      - `keyword.control.do-expression.do` (the keyword from ES7, not the loop)\n      - `meta.decorator.arguments`\n      - `meta.instantiation` (applied to identifier being instantiated)\n      - `meta.invocation` (applied to identifier being invoked)\n      - `punctuation.definition.arguments` (parens in invocation/instantiation)\n      - `punctuation.definition.block.do-expression` (braces in `do` expression)\n      - `punctuation.separator.argument` (comma in arguments)\n      - `variable.other.readwrite.tag` (foo in \u003ccode\u003efoo\u0026grave;str${ exp }\u0026grave;\u003c/code\u003e)\n  - **Types**\n    - **Accessors**\n      - `entity.name.accessor.get` (name of accessor)\n      - `entity.name.accessor.set` (name of accessor)\n      - `keyword.control.flow.return.accessor` (not sure why I gave it its own)\n      - `punctuation.definition.accessor`\n      - `punctuation.definition.accessor.body` (braces)\n      - `punctuation.definition.accessor.parameter` (the param id in a `set`)\n      - `punctuation.definition.parameters.accessor` (parens)\n      - `storage.modifier.accessor.get` (keyword `get`)\n      - `storage.modifier.accessor.set` (keyword `set`)\n    - **Async Functions**\n      - `entity.name.method.async` (name of async function)\n      - `entity.name.method.private.async`\n      - `entity.name.function.async`\n      - `entity.name.function.async.arrow`\n      - `keyword.control.flow.await` (keyword `await`)\n      - `punctuation.definition.function.async`\n      - `punctuation.definition.function.async.arrow`\n      - `punctuation.definition.function.async.arrow.body`\n      - `punctuation.definition.function.async.body`\n      - `punctuation.definition.method.async.body`\n      - `punctuation.definition.method.private.async.body`\n      - `punctuation.definition.parameters.function.async`\n      - `punctuation.definition.parameters.function.async.arrow`\n      - `punctuation.definition.parameters.method.async`\n      - `punctuation.definition.parameters.method.private.async`\n      - `storage.modifier.async` (keyword `async`, general)\n      - `storage.modifier.async.expression` (keyword `async`, in expression)\n      - `storage.modifier.async.method` (keyword `async`, in method declaration)\n    - **Classes**\n      - `entity.name.class`\n      - `entity.name.constructor`\n      - `meta.decorator`\n      - `meta.decorator.parenthesized`\n      - `meta.super-expression`\n      - `punctuation.definition.class.body`\n      - `punctuation.definition.class.body.block`\n      - `punctuation.definition.constructor.body`\n      - `punctuation.definition.decorator`\n      - `punctuation.definition.method.private.body`\n      - `punctuation.definition.parameters.constructor`\n      - `punctuation.terminator.property`\n      - `storage.modifier.extends`\n      - `storage.modifier.static`\n      - `storage.type.class`\n      - `storage.type.class.expression`\n      - `variable.other.readwrite.property.class.es`\n      - `variable.language.private`\n      - `variable.language.private.class`\n    - **Functions**\n      - `entity.name.function`\n      - `entity.name.function.arrow`\n      - `entity.name.function.allCap`\n      - `entity.name.function.initCap`\n      - `entity.name.method`\n      - `entity.name.method.private`\n      - `keyword.control.flow.return`\n      - `punctuation.definition.function`\n      - `punctuation.definition.function.arrow.body`\n      - `punctuation.definition.function.body`\n      - `punctuation.definition.method`\n      - `punctuation.definition.method.body`\n      - `punctuation.definition.parameters`\n      - `punctuation.definition.parameters.function`\n      - `punctuation.definition.parameters.function.arrow`\n      - `punctuation.definition.parameters.method`\n      - `punctuation.definition.parameters.method.private`\n      - `storage.type.function.arrow`\n      - `storage.type.function.async`\n      - `storage.type.function.async.arrow`\n      - `storage.type.function.async.expression`\n      - `storage.type.function`\n      - `storage.type.function.expression`\n    - **Generators**\n      - `entity.name.function.generator`\n      - `entity.name.method.generator`\n      - `keyword.control.flow.yield.iterate`\n      - `keyword.control.flow.yield`\n      - `punctuation.definition.generator`\n      - `punctuation.definition.generator.body`\n      - `punctuation.definition.method.generator`\n      - `punctuation.definition.method.generator.body`\n      - `punctuation.definition.parameters.generator`\n      - `punctuation.definition.parameters.method.generator`\n      - `storage.modifier.generator.asterisk`\n      - `storage.modifier.generator.asterisk.expression`\n      - `storage.modifier.generator.asterisk.method`\n      - `storage.type.function.generator`\n      - `storage.type.function.generator.expression`\n- **Operators**\n  - **Assignment**\n    - **General**\n      - `keyword.operator.assignment`\n      - `keyword.operator.assignment.conditional`\n      - `keyword.operator.assignment.conditional.default` (default initializer)\n      - `keyword.operator.unary.delete`\n    - **Augmented**\n      - `keyword.operator.assignment.augmented`\n      - `keyword.operator.assignment.augmented.arithmetic`\n      - `keyword.operator.assignment.augmented.arithmetic.addition`\n      - `keyword.operator.assignment.augmented.arithmetic.division`\n      - `keyword.operator.assignment.augmented.arithmetic.exponentiation`\n      - `keyword.operator.assignment.augmented.arithmetic.modulo`\n      - `keyword.operator.assignment.augmented.arithmetic.multiplication`\n      - `keyword.operator.assignment.augmented.arithmetic.subtraction`\n      - `keyword.operator.assignment.augmented.bitwise`\n      - `keyword.operator.assignment.augmented.bitwise.logical`\n      - `keyword.operator.assignment.augmented.bitwise.logical.and`\n      - `keyword.operator.assignment.augmented.bitwise.logical.or`\n      - `keyword.operator.assignment.augmented.bitwise.logical.xor`\n      - `keyword.operator.assignment.augmented.bitwise.shift`\n      - `keyword.operator.assignment.augmented.bitwise.shift.left`\n      - `keyword.operator.assignment.augmented.bitwise.shift.right`\n      - `keyword.operator.assignment.augmented.bitwise.shift.right.unsigned`\n      - `keyword.operator.assignment.augmented.logical.and`\n      - `keyword.operator.assignment.augmented.logical.or`\n      - `keyword.operator.assignment.augmented.logical.or.nullish-coalescing`\n  - **Bitwise**\n    - `keyword.operator.bitwise`\n    - `keyword.operator.bitwise.logical`\n    - `keyword.operator.bitwise.logical.and`\n    - `keyword.operator.bitwise.logical.not`\n    - `keyword.operator.bitwise.logical.or`\n    - `keyword.operator.bitwise.logical.xor`\n    - `keyword.operator.bitwise.shift`\n    - `keyword.operator.bitwise.shift.left`\n    - `keyword.operator.bitwise.shift.right`\n    - `keyword.operator.bitwise.shift.right.unsigned`\n  - **Comparison**\n    - `keyword.operator.comparison`\n    - `keyword.operator.comparison.equality`\n    - `keyword.operator.comparison.equality.coercive`\n    - `keyword.operator.comparison.equality.strict`\n    - `keyword.operator.comparison.non-equality`\n    - `keyword.operator.comparison.non-equality.coercive`\n    - `keyword.operator.comparison.non-equality.strict`\n    - `keyword.operator.relational`\n    - `keyword.operator.relational.gt`\n    - `keyword.operator.relational.gte`\n    - `keyword.operator.relational.in`\n    - `keyword.operator.relational.instanceof`\n    - `keyword.operator.relational.lt`\n    - `keyword.operator.relational.lte`\n  - **Evaluative**\n    - `keyword.operator.accessor`\n    - `keyword.operator.accessor.decorator`\n    - `keyword.operator.accessor.optional-chaining`\n    - `keyword.operator.comma`\n    - `keyword.operator.new`\n    - `keyword.operator.pipeline` (smart and F# pipelines proposals)\n    - `keyword.operator.spread`\n    - `keyword.operator.ternary`\n    - `keyword.operator.ternary.else`\n    - `keyword.operator.ternary.if`\n    - `keyword.operator.unary`\n    - `keyword.operator.unary.typeof`\n    - `keyword.operator.unary.void`\n  - **Logical**\n    - `keyword.operator.logical`\n    - `keyword.operator.logical.and`\n    - `keyword.operator.logical.not`\n    - `keyword.operator.logical.or`\n    - `keyword.operator.logical.or.nullish-coalescing`\n    - `meta.idiomatic-cast.boolean` (i.e. `!!val`)\n  - **Mathematic**\n    - `keyword.operator.arithmetic`\n    - `keyword.operator.arithmetic.addition`\n    - `keyword.operator.arithmetic.decrement`\n    - `keyword.operator.arithmetic.decrement.postfix`\n    - `keyword.operator.arithmetic.decrement.prefix`\n    - `keyword.operator.arithmetic.division`\n    - `keyword.operator.arithmetic.exponentiation`\n    - `keyword.operator.arithmetic.increment`\n    - `keyword.operator.arithmetic.increment.postfix`\n    - `keyword.operator.arithmetic.increment.prefix`\n    - `keyword.operator.arithmetic.modulo`\n    - `keyword.operator.arithmetic.multiplication`\n    - `keyword.operator.arithmetic.sign`\n    - `keyword.operator.arithmetic.sign.negative`\n    - `keyword.operator.arithmetic.sign.positive`\n    - `keyword.operator.arithmetic.subtraction`\n- **Statements**\n  - **General**\n    - `entity.name.statement` (statement label)\n    - `keyword.control.flow.break`\n    - `keyword.control.flow.throw`\n    - `punctuation.definition.block` (braces of any block statement)\n    - `punctuation.separator.label-statement` (statement label colon)\n    - `punctuation.terminator.statement` (terminal semicolon or empty statement)\n  - **Conditional Statements**\n    - `keyword.control.conditional`\n    - `keyword.control.conditional.else`\n    - `keyword.control.conditional.if`\n    - `keyword.control.switch` (the switch keyword)\n    - `keyword.control.switch.case` (the case keyword)\n    - `keyword.control.switch.case.default` (the default keyword, in a switch)\n    - `punctuation.definition.block.conditional` (braces for `if` or `else`)\n    - `punctuation.definition.block.switch` (braces for `switch`)\n    - `punctuation.definition.expression.conditional` (parens for `if`)\n    - `punctuation.definition.expression.switch` (parens for `switch`)\n    - `punctuation.separator.case-statements` (colon after `case` or `default`)\n  - **Loop Statements**\n    - `keyword.control.flow.continue`\n    - `keyword.control.flow.loop`\n    - `keyword.control.loop.do`\n    - `keyword.control.loop.each` (deprecated)\n    - `keyword.control.loop.for`\n    - `keyword.control.loop.in`\n    - `keyword.control.loop.of`\n    - `keyword.control.loop.while`\n    - `punctuation.definition.block.loop` (braces in `while (x) {...}`)\n    - `punctuation.definition.expression.loop` (parens in ``while (x) {...}``)\n    - `punctuation.separator.loop-expression` (semicolons in a C-style `for`)\n  - **Try Statements**\n    - `keyword.control.trycatch`\n    - `keyword.control.trycatch.catch`\n    - `keyword.control.trycatch.finally`\n    - `keyword.control.trycatch.try`\n    - `punctuation.definition.block.trycatch` (braces in all three)\n    - `punctuation.definition.parameters.catch` (parens in `catch (err)`)\n    - `variable.parameter.catch` (err in `catch (err)`)\n  - **Module Statements**\n    - `entity.name.module.export`\n    - `entity.name.module.import`\n    - `punctuation.definition.assertions` (braces in `import x from 'z' assert { type: \"json\" }`)\n    - `punctuation.definition.module-binding` (braces in `import { x, y } from 'z'`)\n    - `punctuation.separator.assertion` (colon in `assert { type: \"json\" }`)\n    - `punctuation.separator.assertions` (comma in `assert { type: \"json\" }`)\n    - `punctuation.separator.module-binding` (comma in `import { x, y } from 'z'`)\n    - `storage.modifier.module.as`\n    - `storage.modifier.module.assert`\n    - `storage.modifier.module.default`\n    - `storage.modifier.module.from`\n    - `storage.modifier.module.namespace` (the asterisk in `import * from z`)\n    - `storage.type.module.export`\n    - `storage.type.module.import`\n    - `variable.annotation.assertion.key` (the key “type” in `assert { type: \"json\" }`)\n    - `variable.other.readwrite.export`\n    - `variable.other.readwrite.import`\n  - **Nonsense**\n    - `keyword.control.with` (deprecated)\n    - `keyword.other.debugger` (deprecated)\n    - `punctuation.definition.block.with` (deprecated)\n    - `punctuation.definition.expression.with` (deprecated)\n- **Variables \u0026 Constants**\n  - **Declarations**\n    - `storage.type.constant`\n    - `storage.type.variable.let`\n    - `storage.type.variable.var`\n  - **Binding Patterns (Destructuring)**\n    - `entity.other.property-binding` (y in `let { y: z } = x`)\n    - `punctuation.definition.binding`\n    - `punctuation.definition.binding.array`\n    - `punctuation.definition.binding.object`\n    - `punctuation.separator.array-element.binding` (comma in array binding)\n    - `punctuation.separator.binding-binding` (the comma here: `let x, y`)\n    - `punctuation.separator.object-member.binding` (commas in object patterns)\n    - `punctuation.separator.property-binding` (colon in `let { y: z } = x`)\n    - *see also Functions for binding patterns in parameter declarations*\n- **Identifiers**\n  - **General**\n    - `variable.other.readwrite`\n    - `variable.other.readwrite.allCap`\n    - `variable.other.readwrite.initCap`\n    - `variable.other.readwrite.property`\n    - `variable.other.readwrite.property.allCap`\n    - `variable.other.readwrite.property.initCap`\n  - **Contextual References \u0026 Pseudo-References**\n    - `variable.language.arguments`\n    - `variable.language.function-sent` (proposed generator initial next arg)\n    - `variable.language.import-dynamic`\n    - `variable.language.import-meta`\n    - `variable.language.new-target.fake-accessor` (the dot in `new.target`)\n    - `variable.language.new-target.fake-object` (the new in `new.target`)\n    - `variable.language.new-target.fake-property` (the target in `new.target`)\n    - `variable.language.partial-application` (partial application proposal)\n    - `variable.language.super`\n    - `variable.language.this`\n    - `variable.language.topic` (smart pipelines proposal)\n  - **Special Properties**\n    - `variable.other.readwrite.property.proto` (i.e., `x.__proto__`; a certified Bad Part)\n    - `variable.other.readwrite.property.prototype` (i.e. `X.prototype`)\n  - **Native (\u0026 Nearly Native) Objects**\n    - `support.class.builtin` (e.g. `Array`)\n    - `support.function.builtin` (e.g. `parseInt`)\n    - `support.variable.builtin` (e.g. `Math`)\n- **JSX**\n  - `entity.name.tag.jsx` (html element name)\n  - `keyword.operator.accessor.jsx` (access dot in ‘namespaced’ element name)\n  - `keyword.operator.spread.jsx` (spread operator in attribute interpolation)\n  - `meta.interpolation.jsx` (covers interpolated sequences)\n  - `meta.namespace.jsx` (prefix sequence in component member expression)\n  - `punctuation.definition.attribute.begin.jsx` (single or double quotes)\n  - `punctuation.definition.attribute.end.jsx`\n  - `punctuation.definition.interpolation.begin.jsx` (curly braces)\n  - `punctuation.definition.interpolation.end.jsx`\n  - `punctuation.definition.tag.begin.jsx` (element tag delimiter)\n  - `punctuation.definition.tag.end.jsx`\n  - `punctuation.definition.tag.fragment.begin.jsx`\n  - `punctuation.definition.tag.fragment.end.jsx`\n  - `punctuation.separator.attribute-value.jsx` (equals sign)\n  - `string.attribute.jsx` (literal attribute value)\n  - `string.text.jsx` (literal chardata)\n  - `variable.other.entity-reference.jsx` (html/xml entity refs)\n  - `variable.other.attribute.jsx` (attribute name)\n- **Styled JSX (from Sublime’s CSS syntax)**\n  - `comment.block.css`\n  - `constant.numeric.css`\n  - `entity.other.attribute-name.class.css`\n  - `entity.other.attribute-name.id.css`\n  - `entity.other.pseudo-class.css`\n  - `entity.other.pseudo-element.css`\n  - `keyword.control.at-rule.css`\n  - `keyword.operator.attribute-selector.css`\n  - `keyword.other.unit.css`\n  - `meta.function-call.css`\n  - `meta.property-name.css`\n  - `meta.property-value.css` (actually inclusive of many other items)\n  - `meta.styled-jsx.global.jsx`\n  - `punctuation.definition.comment.css`\n  - `punctuation.section.property-list.css`\n  - `punctuation.separator.combinator.css` (inclusive of calc operators, etc)\n  - `punctuation.separator.key-value.css`\n  - `punctuation.terminator.rule.css`\n  - `source.css`\n  - `string.quoted.css`\n  - `string.unquoted.css`\n  - `support.type.custom-property.name.css`\n- **Other**\n  - `invalid`\n  - `invalid.deprecated` (e.g. `with`)\n  - `invalid.illegal.newline` (e.g., inside a single-quote string)\n  - `invalid.illegal.octal-escape` (e.g. `'\\\\101'`; not valid since ES3)\n  - `invalid.illegal.token` (syntax error)\n  - `invalid.merge-conflict`\n  - `invalid.merge-conflict.delimiter` (e.g. `'\u003c\u003c\u003c\u003c\u003c\u003c\u003c HEAD'`)\n  - `meta.whitespace`\n  - `punctuation.definition.expression` (parentheses of a parenthetic expression)\n  - `variable.other.readwrite.decorator` (if a decorator expression begins with an identifier, as is typical, it will have this scope applied)\n\n### Symbol Helper Scopes\n\nThese scopes are used to facilitate proper population of the symbol list.\n\n - `meta.symbol-helper.arrow.es`\n - `meta.symbol-helper.class.es`\n - `meta.symbol-helper.function.es`\n - `meta.symbol-helper.generator.es`\n\n### Interoperability Scopes\n\nThese scopes exist alongside others above to maximize interoperability with\nexisting themes, especially those targetting JSNext and Babel Sublime.\n\n - `constant.other.object.key.js`\n - `entity.name.class.js`\n - `entity.name.function.js`\n - `entity.name.method.js`\n - `entity.name.tag.js`\n - `entity.name.type.new`\n - `entity.quasi.element.js`\n - `entity.quasi.tag.name.js`\n - `keyword.generator.asterisk.js`\n - `keyword.operator.module.js`\n - `keyword.other.js`\n - `meta.brace.curly.js`\n - `meta.brace.round.js`\n - `meta.brace.square.js`\n - `meta.delimiter.comma.js`\n - `meta.function-call`\n - `meta.function.arrow.js`\n - `meta.function.js`\n - `meta.instance.constructor`\n - `meta.separator.comma.js`\n - `punctuation.definition.tag.js`\n - `punctuation.quasi.element.begin.js`\n - `punctuation.quasi.element.end.js`\n - `storage.type.accessor.js`\n - `storage.type.extends.js`\n - `storage.type.function.js`\n - `storage.type.js`\n - `string.regexp.js`\n - `string.unquoted.label.js`\n - `variable.language.proto`\n - `variable.language.prototype`\n\n\n### Nested Syntax Scopes\n\nThese scopes are for the contents of template strings that have a syntax directive, and are suffixed by the short name of their syntax.\n\n - `meta.interpolation.syntax.css`\n - `meta.interpolation.syntax.html`\n - `meta.interpolation.syntax.js`\n - `meta.interpolation.syntax.json`\n - `meta.interpolation.syntax.dot`\n - `meta.interpolation.syntax.glsl`\n - `meta.interpolation.syntax.shell`\n - `meta.interpolation.syntax.sql`\n - `meta.interpolation.syntax.xml`\n - `meta.interpolation.syntax.yaml`\n\n## About the Scope Conventions\n\nI’ve used existing tmLanguage conventions, plus JSNext and Babel Sublime, as\nguides for scope naming. Nonetheless there’s a fair amount of divergence. Some\nof this is just the consequence of disambiguating previously conflated elements.\n\nIn a few cases, the original Sublime JS tmLanguage had errors, and Babel and\nJSNext preserved them. I chose to correct these at the risk of decreasing\ncompatibility with existing themes. For example, ‘with’ is not an operator. But\nthere aren’t many of these and they are usually minor things that won’t affect\nmost themes.\n\nSometimes I opted to use a pre-existing tmLanguage convention over a domain-\nspecific choice. For example, Babel uses `quasi` but many tmLanguages and themes\nalready target `string.interpolated`. In cases like this I typically ‘double\nscope’ the tokens so that they can be targetted either way.\n\nOther divergences stem from the objective of the definition, which may differ a\nbit. I wanted the scopes to be very reflective of the language’s grammar. For\nexample, `entity.name.function` will appear in a function declaration, but it\nwon’t appear in function invocations; to Ecmascript Sublime, in that context\nwhat you’re looking at is an identifier (which has a scope) and an invocation\n(which also has a scope), but not an entity name.\n\nMany of the new scopes concern punctuation. The `punctuation.definition` scope\nnamespace is the existing convention for these things. So for if statements, for\nexample, you have the following to work with:\n\n - `keyword.control.conditional.else`\n - `keyword.control.conditional.if`\n - `punctuation.definition.block.conditional.begin`\n - `punctuation.definition.block.conditional.end`\n - `punctuation.definition.expression.conditional.begin`\n - `punctuation.definition.expression.conditional.end`\n\nOne would probably never have a reason to include ‘begin’ or ‘end’ but this kind\nof trailing specificity helps sometimes with debugging and in any case is an\nexisting convention. Scopes are hierarchical selectors, so if you wanted to have\none color for the whole statement, the definition in your YAML-tmTheme could\nlook like this:\n\n    - name: If / else statements\n      scope: \u003e-\n        keyword.control.conditional,\n        punctuation.definition.block.conditional,\n        punctuation.definition.expression.conditional\n      settings:\n        foreground: '#FF0000'\n\nIf you’re new to theming, make sure you grab\n[AAAPackageDev](https://packagecontrol.io/packages/AAAPackageDev) and\n[ScopeAlways](https://packagecontrol.io/packages/ScopeAlways) from\nPackage Control. The former will let you translate human-readable YAML into\ntmTheme XML, and the latter will show, in the status bar, what scopes are being\napplied where your cursor is.\n\n## More Infobarf for Someone Hypothetically Curious About the Definition Itself\n\n### Why Is It Huge?\n\nIf you’re poking around in there you might think it’s insane to have so many\nredundant components. In many cases, similar results could be achieved using\nmeta_scopes on a deeper context stack, since multiple scopes can appear in a\nselector.\n\nTo keep it brief...ish: this very un-DRY approach was the arrived at after a lot\nof experimenting. Sublime syntax is powerful, but I might be trying to do some\nstuff that wasn’t anticipated. Taking a very ‘grammatical’ approach (in fact I\nworked right off the ES6 final draft) is what lets us have all the new \u0026\ndisambiguated scopes to work with, but the price paid for syntactic precision is\nthe need to pay special attention to failing as gracefully as possible when\nfacing a bad token.\n\nThere are a few techniques I’ve found to prevent or mitigate ‘bad input\ncascade,’ and the most important is keeping the context stack as shallow as is\nreasonable at any given time -- that is, preferring linear over vertical context\ntransitions. This is what necessitates the repetition.\n\nThat said there certainly are places where we could merge things, especially by\nmaking tertiary contexts that exist only as includes for building others which\nare actually visited.\n\nIf it ever becomes possible to pop multiple contexts, like you can set multiple\ncontexts, we could probably cut the complexity and repetitiveness of the\ndefinition by a ton.\n\nThe other main technique for preventing cascade effects is to handle some of the\nillegal cases explicitly. There’s quite a bit of this ‘handmade’ correction\nactually. Since we know what kind of things are likely to be temporary artifacts\nof someone being midway through typing something that will soon be valid, we can\nmark a single bad token invalid but then still transition to what we are pretty\nsure should be next. With time I plan to add more of this sort of thing, but I\nonly discover good places for it with use.\n\n### Why Does Almost Everything Related to Expressions Appear Twice?\n\nI was absolutely determined to disambiguate ‘in’ (operator) from ‘in’ (control\nword). As far as I can tell, this is the only way we can achieve that. This idea\nis actually present in the formal grammar definition, too; I didn’t make it up\nmyself.\n\n### Does a Byzantine Maze of Context Transitions Make Highlighting Slow?\n\nSurprisingly, no. Well, I haven’t noticed a problem anyway. I don’t know about\nthe inner workings of Sublime Text, but if you think about it, if regex matches\nare the most expensive part, then sublime syntax with atomic contexts is\nprobably efficient: each context will only try matching things that are actually\nexpected to appear there.\n\n### How Do I Break It?\n\nWacky linebreaks! Actually it can correctly scope weird line break situations a\nlot more often than is possible in tmLanguage, because in linear grammar\nsequences, like those that define most statements, the context stack is all we\nneed to get 100% perfect matches. But there are cases in ES expressions -- more\nthan I initially thought, too -- where a token is ambiguous until accounting for\na later token that is allowed to be on the next line (where we can’t look).\n\nFortunately, save one, all of these linebreaks are, while legal, totally\nasinine. That is, if a person really wrote this:\n\n    label\n    : {\n      [ a,\n      b=4 ]\n      = [ (c)\n      =\u003e { c * 2, d } ]\n    }\n\n... they don’t *deserve* syntax highlighting. So consider it a feature.\n\nHowever even in these cases, Ecmascript Sublime will make a noble attempt at\nrecovering. In the example above. The binding pattern would be an array, but\nwhen it hit the `=4` it would correct the remainder. The `(c)` would be an\nexpression, but at the arrow it would figure out where it really is, etc. But\nnot everything can be salvaged: the `label` would be an identifier, but the\ncolon would seem to be invalid because at that point we have to assume we’re in\na context expecting this series of tokens to resolve to an expression.\n\nThese are some of the cases where a technically-legal-but-obnoxious linebreaks\ncan cause mismatching, where the pipe represents a problematic linebreak:\n\n - Distinguishing between ‘in’ and ‘in’ in a for loop depends on lookaheads\n   for sequences that could cross lines.\n - Statement label | `:`\n - Parameter(s) | `=\u003e`\n - `function` | `*`\n - `async` | `function` (but only in expressions -- this is because async could\n   also be an identifier, and accomodating that is important because of the\n   popular Node library)\n - identifier | `(` (identifier will not be recognized as an invocation)\n - identifier | ``` (identifier will not be recognized as a tag)\n - There are various other situations similar to the last two, mainly concerning\n   ‘secondary’ scopes like invocation rather than core scopes.\n\nOne more is a sore spot for me:\n\n - binding pattern | assignment operator\n\nUnlike the others, this one could reasonably show up in code written by a sane\nperson. But even so, it’s probably quite rare in practice.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbathos%2Fecmascript-sublime","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbathos%2Fecmascript-sublime","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbathos%2Fecmascript-sublime/lists"}