{"_id":"@codincod/codemirror-lang-dart","_rev":"2-26ae5bb4d9e08da7627c67054009ecaa","name":"@codincod/codemirror-lang-dart","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@codincod/codemirror-lang-dart","version":"0.1.0","keywords":["editor","code","dart","flutter","codemirror"],"author":{"name":"CodinCod","email":"hello@codincod.com"},"license":"MIT","_id":"@codincod/codemirror-lang-dart@0.1.0","maintainers":[{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"}],"homepage":"https://codincod.com/","dist":{"shasum":"f8c1237d8ac6a27bfc164c085ff5f217f7611706","tarball":"https://registry.npmjs.org/@codincod/codemirror-lang-dart/-/codemirror-lang-dart-0.1.0.tgz","fileCount":14,"integrity":"sha512-mV1M37suxuNADub7sqH3po+8XLpZ7FbAha30dPTwmLzIEStOHtUsPmWvquVFRgIZuwqWqsWNjMKBkbsACSMQ9g==","signatures":[{"sig":"MEUCIBDoK0QIQ0ZYTW3rrw7HGWqYMUnRbsDlPn01HO6V6su/AiEApXYvkpl8wWoqR8iiyvJdMDrJE1JS+Nti6PeD23cJ1E4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":366323},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","exports":{"import":"./dist/index.js","require":"./dist/index.cjs"},"gitHead":"40c3c3755d198c0a7d31e81fcf2e0f2a27d1d2cd","scripts":{"test":"npm run build && node --test \"test/*.test.ts\"","build":"rm -rf dist && lezer-generator src/dart.grammar -o src/parser.js && cm-buildhelper src/dart.ts","corpus":"npm run build && node test/corpus.ts","prepare":"npm run build","build-debug":"lezer-generator src/dart.grammar --names -o src/parser.js && cm-buildhelper src/dart.ts"},"_npmUser":{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"},"repository":{"url":"git+https://codeberg.org/reeven/codemirror-lang-dart.git","type":"git"},"_npmVersion":"11.6.2","description":"Dart language support for the CodeMirror code editor","directories":{},"sideEffects":false,"_nodeVersion":"25.0.0","dependencies":{"@lezer/lr":"^1.0.0","@lezer/common":"^1.0.0","@lezer/highlight":"^1.0.0","@codemirror/language":"^6.0.0","@codemirror/autocomplete":"^6.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.6.0","@lezer/generator":"^1.7.0","@codemirror/state":"^6.7.1","@codemirror/buildhelper":"^1.0.2"},"_npmOperationalInternal":{"tmp":"tmp/codemirror-lang-dart_0.1.0_1785666932678_0.6950278511814234","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@codincod/codemirror-lang-dart","version":"0.1.1","description":"Dart language support for the CodeMirror code editor","keywords":["editor","code","dart","flutter","codemirror"],"author":{"name":"CodinCod","email":"hello@codincod.com"},"license":"MIT","type":"module","main":"dist/index.cjs","exports":{"import":"./dist/index.js","require":"./dist/index.cjs"},"module":"dist/index.js","types":"dist/index.d.ts","sideEffects":false,"scripts":{"build":"rm -rf dist && lezer-generator src/dart.grammar -o src/parser.js && cm-buildhelper src/dart.ts","build-debug":"lezer-generator src/dart.grammar --names -o src/parser.js && cm-buildhelper src/dart.ts","prepare":"npm run build","test":"npm run build && node --test \"test/*.test.ts\"","corpus":"npm run build && node ../lezer-survey/src/cli.ts measure --group top","gaps":"npm run build && node ../lezer-survey/src/cli.ts gaps --group top"},"dependencies":{"@codemirror/autocomplete":"^6.0.0","@codemirror/language":"^6.0.0","@lezer/common":"^1.0.0","@lezer/highlight":"^1.0.0","@lezer/lr":"^1.0.0"},"devDependencies":{"@codemirror/buildhelper":"^1.0.2","@codemirror/state":"^6.7.1","@lezer/generator":"^1.7.0","typescript":"^5.6.0"},"homepage":"https://codincod.com/","repository":{"type":"git","url":"https://codeberg.org/reeven/codemirror-lang-dart"},"gitHead":"9c10b375568bea861cfbf1774522055ace3a97ab","_id":"@codincod/codemirror-lang-dart@0.1.1","_nodeVersion":"25.0.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-n8RjG1iMdcCBRA+g+CWPdyoV0xfx48k7A+v+3aOI7Uzhy2KbBVfTuJ6/h58rl5iI7mifr7U7wAyB5A7cvSsP+g==","shasum":"75746463bdb66469d2113853ce530ded0bf011e3","tarball":"https://registry.npmjs.org/@codincod/codemirror-lang-dart/-/codemirror-lang-dart-0.1.1.tgz","fileCount":14,"unpackedSize":366428,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFkQ2h2a7OQpIgOJVrsHQOJanrHqL5WIZEIYHUYz6S4EAiBC6J/gSi1RbdqR6M5dSAnCEfTnn96vBgYkIIzXrBq23Q=="}]},"_npmUser":{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"},"directories":{},"maintainers":[{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/codemirror-lang-dart_0.1.1_1785970446837_0.08878051241650398"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-02T10:35:32.453Z","modified":"2026-08-05T22:54:07.163Z","0.1.0":"2026-08-02T10:35:32.819Z","0.1.1":"2026-08-05T22:54:06.977Z"},"author":{"name":"CodinCod","email":"hello@codincod.com"},"license":"MIT","homepage":"https://codincod.com/","keywords":["editor","code","dart","flutter","codemirror"],"repository":{"type":"git","url":"https://codeberg.org/reeven/codemirror-lang-dart"},"description":"Dart language support for the CodeMirror code editor","maintainers":[{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"}],"readme":"# @codincod/codemirror-lang-dart [![NPM version](https://img.shields.io/npm/v/@codincod/codemirror-lang-dart.svg)](https://www.npmjs.org/package/@codincod/codemirror-lang-dart)\n\n[ [**CHANGELOG**](https://codeberg.org/reeven/codemirror-lang-dart/src/branch/master/CHANGELOG.md) ]\n\nThis package implements Dart language support for the\n[CodeMirror](https://codemirror.net/) code editor, using a\n[Lezer](https://lezer.codemirror.net/) grammar written for this package.\n\nCodeMirror 6 has never shipped Dart, and no Lezer grammar for it existed before\nthis one. What gets used instead is the C-family stream mode ported from\nCodeMirror 5, which colours a list of keywords and builds no tree, so nothing\nabove it can fold a class, indent a `switch` or ask what the word under the\ncursor is. It also predates most of the language: string interpolation,\ncascades, null safety, records and patterns all come out as plain text or as\nsomething else entirely.\n\nWritten in part for [CodinCod](https://codincod.com/), a competitive coding\nplatform, where it colours the editor people solve puzzles in.\n\nThis code is released under an\n[MIT license](https://codeberg.org/reeven/codemirror-lang-dart/src/branch/master/LICENSE).\n\n## Usage\n\n```javascript\nimport {EditorView, basicSetup} from \"codemirror\"\nimport {dart} from \"@codincod/codemirror-lang-dart\"\n\nconst view = new EditorView({\n  parent: document.body,\n  doc: `class Greeter {\n  const Greeter(this.name);\n\n  final String name;\n\n  String greet() => 'Hello, $name!';\n}\n`,\n  extensions: [basicSetup, dart()]\n})\n```\n\n## Coverage\n\nDart 3. Classes, mixins, enums with constructors and members, extensions and\nextension types, sealed and base hierarchies, typedefs both ways, generics with\nbounds, sound null safety, records and their types, patterns everywhere Dart 3\nputs them, switch expressions and switch statements, `if`-case, cascades and\nnull-aware cascades, collection `if`, `for` and spreads, async and both kinds\nof generator, initializing and super formals, metadata, and every one of the\neight ways Dart writes a string.\n\nThe parts Dart added most recently are here too: digit separators, null-aware\nelements, dot shorthands, primary constructors and the `new` that names a\nconstructor rather than calling one.\n\nMeasured against 4 465 Dart files from six open source projects (the Flutter\nframework and its tools, the Dart SDK's own libraries and front end, Riverpod,\nbloc, Dio and `dart-lang/core`), which is 58 MiB of code, of which 98.66% parse\nwith no error node.\n\n## What the grammar cannot say\n\nThree things about Dart are settled in `src/tokens.ts` rather than in the\ngrammar, because no context free rule can decide them.\n\n**A `?` makes a type nullable or opens a conditional.** `e as String?` and\n`e is String ? a : b` disagree about one character, and the disagreement cannot\nbe settled where it stands. Lezer settles a shift against a reduce by\nprecedence rather than by trying both, because the two readings do not cover\nthe same span and so are not the kind of ambiguity a conflict marker can hold\nopen; whichever way the precedence goes, half the language breaks. The\ntokenizer answers it instead, by looking further along the line than the parser\ndoes: a colon outside every bracket means a conditional, and a semicolon, a\ncomma, an assignment or a bracket nobody opened means a type. An angle bracket\nbehind the cursor that nothing closed is what tells the `?` of\n`c ? JS<Ref?>(a) : d` from the one that opens the conditional around it.\n\n**A string is eight different languages.** The quote may be single or double,\nthe delimiter one character or three, and an `r` in front turns every escape\nback into an ordinary character. Which of the eight is being read decides what\nends the string and whether `$` opens a hole holding an expression, and none of\nit can be read off the character at the cursor. It is not remembered in the\ntokenizer either, because the parser may fork and anything remembered would be\nremembered for both halves; it is asked of the parser instead, since each\nflavour's content token can only be shifted inside its own kind of string. That\nis also what makes `'a ${b(\"c\")} d'` work: inside the hole no content token can\nbe shifted at all, so the quote there opens a string of its own.\n\n**Block comments nest, and a raw string opens with a letter.** `/* /* */ */` is\none comment in Dart and two in most other languages, which is a thing a regular\ntoken cannot say: it has to count. And `r'a'` begins with something every other\ntokenizer is happy to call an identifier, so it has to be claimed before the\ngrammar's own tokenizer is asked.\n\nTwo decisions about the tree are worth saying out loud.\n\n**Casing decides what is a type.** `Foo bar` is a declaration and `foo.bar` is\na member access, and after one identifier no amount of lookahead separates\nthem, so the parser follows the convention every Dart codebase keeps: a word\nstarting with a capital is read as a type first and an ordinary name second,\nand a word starting with a lower case letter the other way round. Both readings\nstay alive and the one that fits wins. Dart writes a private name with a\nleading underscore and generated code writes one with a dollar, so the letter\nthat decides is the first one that is a letter: `_MyWidgetState` and\n`_$FooImpl` are types.\n\n**A cascade is a member access.** `a..b()..c = 1` binds looser than anything\nelse in the real language, but a highlighter has no use for the difference, and\nreading `..` at the precedence of `.` costs no level, no conflict and no\nlookahead. The tree says `(a..b)()` where Dart says `a..(b())`; every token in\nit is still coloured by what it is.\n\n## Development\n\n```bash\nnpm test                    # build, then the parse specs and the editor tests\nnpm run corpus <directory>  # error nodes over a directory of real Dart\n```\n\n`npm run corpus` is what decides whether the grammar is finished. No corpus\nships with the package, because none of that code is ours to redistribute;\npoint it at a checkout of anything large and it will group the report by the\nproject each file came from, so a package that drags the total down names\nitself.\n","readmeFilename":"README.md"}