{"_id":"@codincod/codemirror-lang-haskell","_rev":"4-098a1cd9aa28d5f196a86fd50c03a8d3","name":"@codincod/codemirror-lang-haskell","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@codincod/codemirror-lang-haskell","version":"0.1.0","keywords":["editor","code","haskell","codemirror"],"author":{"name":"CodinCod","email":"hello@codincod.com"},"license":"MIT","_id":"@codincod/codemirror-lang-haskell@0.1.0","maintainers":[{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"}],"homepage":"https://codincod.com/","dist":{"shasum":"20f5d6d6955ded37a5f425d22ac292149e0f821b","tarball":"https://registry.npmjs.org/@codincod/codemirror-lang-haskell/-/codemirror-lang-haskell-0.1.0.tgz","fileCount":14,"integrity":"sha512-SJM24rERMiaj8VLyZ+4XR7dbk/4OLSKBQ1UGUBcWAuNxpn1H7le4ECWDUm4ssC77Oo3/ahAdOV5QHHcyR9Wwxg==","signatures":[{"sig":"MEUCIQCOVW4+z1w3luqPCv9JW7XRaeWYbX/jlWJJKTd+5UmIZAIgd2K7gcQf6i9Z9XN5QnHhsRrPlJZlFSe9VhSGUk8m7XM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":178794},"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":"146311e254a850d4c995006880bc62ac384fba23","scripts":{"test":"npm run build && node --test \"test/*.test.ts\"","build":"rm -rf dist && lezer-generator src/haskell.grammar -o src/parser.js && cm-buildhelper src/haskell.ts","corpus":"npm run build && node test/corpus.ts","prepare":"npm run build","build-debug":"lezer-generator src/haskell.grammar --names -o src/parser.js && cm-buildhelper src/haskell.ts"},"_npmUser":{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"},"repository":{"url":"git+https://codeberg.org/reeven/codemirror-lang-haskell.git","type":"git"},"_npmVersion":"11.6.2","description":"Haskell 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-haskell_0.1.0_1785523853551_0.4372369808801966","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@codincod/codemirror-lang-haskell","version":"0.1.1","keywords":["editor","code","haskell","codemirror"],"author":{"name":"CodinCod","email":"hello@codincod.com"},"license":"MIT","_id":"@codincod/codemirror-lang-haskell@0.1.1","maintainers":[{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"}],"homepage":"https://codincod.com/","dist":{"shasum":"3c90d76618e42e65275ae71b37f91b614437abee","tarball":"https://registry.npmjs.org/@codincod/codemirror-lang-haskell/-/codemirror-lang-haskell-0.1.1.tgz","fileCount":14,"integrity":"sha512-ozoytEEcAxJiibbxVZcz10TZ0jFNGBY/7j8px+9WkLu/zCSzLOoaGCJmwU/2X73rNoQJAsjfLQD4Zxe9oFLy4g==","signatures":[{"sig":"MEUCIC/z+2yiLp0anDTgVBNrKQQXysD70K6okRymGnJsp4E1AiEA/0Pl6UzNmx8TdlZqM8FqdguX+qeZPSqRxFTEkm24D30=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":178899},"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":"3c1c10a5187846f9a00a415d1029503f91a08299","scripts":{"gaps":"npm run build && node ../lezer-survey/src/cli.ts gaps --group top","test":"npm run build && node --test \"test/*.test.ts\"","build":"rm -rf dist && lezer-generator src/haskell.grammar -o src/parser.js && cm-buildhelper src/haskell.ts","corpus":"npm run build && node ../lezer-survey/src/cli.ts measure --group top","prepare":"npm run build","build-debug":"lezer-generator src/haskell.grammar --names -o src/parser.js && cm-buildhelper src/haskell.ts"},"_npmUser":{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"},"repository":{"url":"https://codeberg.org/reeven/codemirror-lang-haskell","type":"git"},"_npmVersion":"11.6.2","description":"Haskell 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-haskell_0.1.1_1785970454617_0.3361132112642613","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@codincod/codemirror-lang-haskell","version":"0.2.0","keywords":["editor","code","haskell","codemirror"],"author":{"name":"CodinCod","email":"hello@codincod.com"},"license":"MIT","_id":"@codincod/codemirror-lang-haskell@0.2.0","maintainers":[{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"}],"homepage":"https://codincod.com/","dist":{"shasum":"bfcef16f93ea96cbb52314fdaecb98ca90050f82","tarball":"https://registry.npmjs.org/@codincod/codemirror-lang-haskell/-/codemirror-lang-haskell-0.2.0.tgz","fileCount":14,"integrity":"sha512-aBvtBahPHAQVPZzvizzVeBCyrXrqCuI4xN7DslmXWvMs2eq1ACTtWfntmYaQoGSrD4+JLOmBlxgIAc7+Y5NZPA==","signatures":[{"sig":"MEUCIHC88CCGuWkkzHYXlavj+bQfEwsH8TwwlvA4LG3PpOhTAiEA5F2K0RsOO0SH11qDwyps53Hw2YfsAqUS5LBNPM5wCrw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":209071},"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":"05bd48b97333af8c77f119507532d714e23f6105","scripts":{"fuzz":"npm run build && node ../lezer-survey/src/cli.ts fuzz","gaps":"npm run build && node ../lezer-survey/src/cli.ts gaps --group top","test":"npm run build && node --test \"test/*.test.ts\"","build":"rm -rf dist && lezer-generator src/haskell.grammar -o src/parser.js && cm-buildhelper src/haskell.ts","measure":"npm run build && node ../lezer-survey/src/cli.ts measure --group top","prepare":"npm run build","build-debug":"lezer-generator src/haskell.grammar --names -o src/parser.js && cm-buildhelper src/haskell.ts"},"_npmUser":{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"},"repository":{"url":"https://codeberg.org/reeven/codemirror-lang-haskell","type":"git"},"_npmVersion":"11.6.2","description":"Haskell 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/state":"^6.7.1","@codemirror/language":"^6.0.0","@codemirror/autocomplete":"^6.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.6.0","@lezer/generator":"^1.7.0","@codemirror/buildhelper":"^1.0.2"},"_npmOperationalInternal":{"tmp":"tmp/codemirror-lang-haskell_0.2.0_1786659551518_0.6692400668071519","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@codincod/codemirror-lang-haskell","version":"0.3.0","description":"Haskell language support for the CodeMirror code editor","keywords":["editor","code","haskell","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/haskell.grammar -o src/parser.js && cm-buildhelper src/haskell.ts","build-debug":"lezer-generator src/haskell.grammar --names -o src/parser.js && cm-buildhelper src/haskell.ts","prepare":"npm run build","test":"npm run build && node --test \"test/*.test.ts\"","measure":"npm run build && node ../lezer-survey/src/cli.ts measure --group top","fuzz":"npm run build && node ../lezer-survey/src/cli.ts fuzz","gaps":"npm run build && node ../lezer-survey/src/cli.ts gaps --group top"},"dependencies":{"@codemirror/autocomplete":"^6.0.0","@codemirror/language":"^6.0.0","@codemirror/state":"^6.7.1","@lezer/common":"^1.0.0","@lezer/highlight":"^1.0.0","@lezer/lr":"^1.0.0"},"devDependencies":{"@codemirror/buildhelper":"^1.0.2","@lezer/generator":"^1.7.0","typescript":"^5.6.0"},"homepage":"https://codincod.com/","repository":{"type":"git","url":"https://codeberg.org/reeven/codemirror-lang-haskell"},"gitHead":"05bd48b97333af8c77f119507532d714e23f6105","_id":"@codincod/codemirror-lang-haskell@0.3.0","_nodeVersion":"25.0.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-AwYE7K7s4UzyJYf8okIB6MqCsCuZL9HpyvaG/9EPjtY7/BJXPwDJJZImONvc2BexBjbfA2Sc1NWamWD+boOM8Q==","shasum":"e595cb133dc5d413acc2ac5e6ff1a8c45c08781d","tarball":"https://registry.npmjs.org/@codincod/codemirror-lang-haskell/-/codemirror-lang-haskell-0.3.0.tgz","fileCount":14,"unpackedSize":209071,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBzK9YPG7M0q/pWPsDjjZ/QTLfmAazX08DdhtHlSSuBUAiEAmiXWiW7NKaLlFIYh0UdHPsTRUaMNAmMqjgPcbewms3I="}]},"_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-haskell_0.3.0_1786759656874_0.18536828643871517"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-31T18:50:53.323Z","modified":"2026-08-15T02:07:37.202Z","0.1.0":"2026-07-31T18:50:53.688Z","0.1.1":"2026-08-05T22:54:14.743Z","0.2.0":"2026-08-13T22:19:11.685Z","0.3.0":"2026-08-15T02:07:37.029Z"},"author":{"name":"CodinCod","email":"hello@codincod.com"},"license":"MIT","homepage":"https://codincod.com/","keywords":["editor","code","haskell","codemirror"],"repository":{"type":"git","url":"https://codeberg.org/reeven/codemirror-lang-haskell"},"description":"Haskell language support for the CodeMirror code editor","maintainers":[{"name":"juicemitapfelndrin","email":"juicemitapfelndrin@gmail.com"}],"readme":"# @codincod/codemirror-lang-haskell\n\nThis package implements Haskell 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 has never shipped Haskell. What a CodeMirror 6 editor can fall back\non is the stream mode from CodeMirror 5, which colours keywords and literals a\ntoken at a time and knows nothing about the shape of what it is reading. No\nLezer grammar for Haskell existed anywhere before this one.\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-haskell/src/branch/master/LICENSE).\n\n## Usage\n\n```javascript\nimport {EditorView, basicSetup} from \"codemirror\"\nimport {haskell} from \"@codincod/codemirror-lang-haskell\"\n\nconst view = new EditorView({\n  parent: document.body,\n  doc: `module Main where\n\nimport Data.List (sort)\n\nmain :: IO ()\nmain = do\n  input <- getContents\n  mapM_ print (sort (map read (lines input) :: [Int]))\n`,\n  extensions: [basicSetup, haskell()]\n})\n```\n\n## Coverage\n\nHaskell 2010, and the extensions GHC 9 turns on for ordinary code: bang\npatterns, lambda case, multi-way if, GADTs, standalone and strategy deriving,\ntype families, functional dependencies, pattern synonyms, view patterns, tuple\nsections, `BlockArguments`, `ImportQualifiedPost`, `MagicHash`, `PackageImports`,\n`RecordWildCards`, `UnicodeSyntax`, the arrow `proc` notation, quasi quotes, and\nthe Template Haskell quotations and splices written `[| |]`, `[e| |]`, `[p| |]`,\n`[t| |]`, `[d| |]`, `[|| ||]`, `''Name` and `$( )`.\n\nMeasured against 51365 files of Haskell that somebody else wrote, drawn from\n297 projects and from Hackage, 97.49% parse with no error node. The largest\ngroups in it:\n\n| | files | clean |\n| --- | --- | --- |\n| [amazonka](https://github.com/brendanhay/amazonka) | 498 | 100.00% |\n| [wire-server](https://github.com/wireapp/wire-server) | 486 | 99.79% |\n| [plutus](https://github.com/IntersectMBO/plutus) | 491 | 98.37% |\n| Hackage releases | 15481 | 97.85% |\n| [clash-compiler](https://github.com/clash-lang/clash-compiler) | 467 | 97.22% |\n| [haskell-language-server](https://github.com/haskell/haskell-language-server) | 449 | 96.88% |\n| [ghc](https://gitlab.haskell.org/ghc/ghc) | 495 | 93.94% |\n| | **51365** | **97.49%** |\n\nThe first release was measured against six libraries, and against a 12000-file\nsample of this corpus it read 81.41%. Reading those failures is what the 0.2.0\nchangelog entry is.\n\nThe corpus does not ship with this package. It belongs to the projects in it and\ncarries their licences, so `npm run measure` takes the path to your own copy of\nit.\n\n## What a tokenizer has to settle\n\nMost of Haskell can be written down as a grammar. Seven things cannot, and\nthey are the whole of `tokens.ts`.\n\n**Indentation opens and closes blocks.** A `where`, a `do`, a `let` or an `of`\nopens a block at the column of the token after it, a line beginning at exactly\nthat column starts a new item, and the first token to the left of it ends the\nblock. Almost no Haskell writes the braces and semicolons the report says are\nthere, so the tokenizer puts them back: it hands the parser a `blockOpen`, a\n`blockSep` and a `blockEnd` with no text in them, standing where the\nindentation put them. Where somebody did write the braces, they are read as the\nsame two tokens, which is what lets one rule in the grammar serve both.\n\n**A block also closes where the parser would fail.** `let x = 1 in x` keeps the\n`in` on the same line and nothing is indented differently, so no column says\nthe block is over. The report closes an implicit block wherever the parser\nwould otherwise fail, and the only thing that knows is the parser, so the\ntokenizer asks it: before `in`, `then`, `else`, `of`, `where`, a closing\nbracket or a comma, it checks whether the parser could shift that token, and\nends the block where it could not.\n\n**A block that opens too far left is empty.** A `where` with nothing under it,\nfollowed by a declaration at the left margin, opens a block and closes it in\nthe same place. That is the rule that keeps the declaration below it a\ndeclaration rather than an error.\n\n**Block comments nest.** `{- {- -} -}` is one comment rather than two, which no\nregular token can count. Two things ride along with them: `{-# ... #-}` is a\npragma rather than a comment, and Haddock's `-- |`, `-- ^`, `{-| ... -}` and\n`{-^ ... -}` are documentation rather than either, so a highlighter can give\nall three different colours. A line comment is two or more dashes that no\nsymbol character follows, which is what keeps `-->` an operator.\n\n**A name may carry its module.** `Data.Map.insert` is one name in three parts,\nand the dots in it are not the composition operator. The tokenizer reads the\nmodule part off the front and hands it over as a token of its own, so it can be\ncoloured as the namespace it is, and so `M.map`, `M.Map` and `M.!` need one\nrule each rather than three. Which of the three follows is decided there as\nwell: `f M.x` applies a function and `f M.+ y` does not, and one token of\nlookahead is not enough to tell them apart afterwards.\n\n**A bracket and a bar open a quotation or a comprehension.** `[t| Int64 |]` is\nTemplate Haskell and `[t|t<-ts]` is a list comprehension, and which is meant\ndepends on whether `TemplateHaskell` is on, which is written in a pragma or in\nthe file that builds the package. The bracket that closes the run says it\ninstead: a quotation ends on `|]` and a comprehension on `]`, so the tokenizer\nreads ahead, counting the brackets it passes, and sees which comes first.\n\n**Whitespace says what `!` and `~` mean.** `m ! k` looks something up and\n`f !x = ...` takes a strict argument, and the difference is the space. GHC\ndecides it that way and so does this: a `!` or a `~` with space in front of it\nand none behind it marks a pattern, and everywhere else it is an operator.\n\n**A name being declared looks like any other name.** `f x = x` declares `f`,\nand `xs !! n = ...` declares the operator and neither name around it. Which one\nit is depends on what stands after the name, and an LR parser cannot hold both\nreadings open long enough to find out, so the tokenizer looks one token ahead\nand decides, the same way it does for Odin. An operator behind the name means\nthe name is not the one being declared, and `::`, `∷`, `=` and `|` are what say\notherwise: the first two open a signature and the others open a body.\n\n## What the tree does not say\n\n**Patterns are expressions.** Haskell writes them with the same syntax, and the\ndifference between `Just x` in a `case` and `Just x` in an argument is which\nside of the equals sign it stands on. Reading them as one thing accepts a few\nprograms GHC rejects and refuses none that it accepts, which is the trade every\nhighlighting grammar makes.\n\n**Types are their own small grammar.** That is the opposite decision, and it is\nmade for the highlighter: a name in a type is a type name, and the only way to\nsay so is for the tree to know it is in a type. Types are read as a flat run of\nelements rather than as a tree of arrows, because nothing that reads this tree\ncares how `a -> b -> c` associates.\n\n**An operator chain is flat as well.** Haskell resolves fixity after parsing,\nwith `infixl` declarations the parser may never have read, so `a + b * c` is\none run of three operands rather than a tree. A run that begins or ends on its\noperator is a section, a negation, or `(+)` on its own, and all three are the\nsame shape here.\n\n**A lambda ends where its chain ends.** `\\x -> a + b` reads the whole of\n`a + b` as the body, which is what Haskell means, and it is why a lambda, a\n`let` and an `if` stand at the end of an operator chain and nowhere else in\none. A `do` and a `case` end on a block instead, and the block says where they\nend, so a chain may carry on after those.\n\n## What is left out\n\n**A quasi quoter's body.** `[sql| ... |]` holds somebody else's language, so\nthe whole run from the bracket to the `|]` arrives as one `QuasiQuote` token and\nnothing inside it is read. A grammar that reads SQL is a grammar for SQL.\n\n**The C preprocessor.** `#if`, `#else` and `#endif` lines are skipped the way\ncomments are, which is right for a file that turns one feature on and wrong for\na file that writes a declaration twice. Both branches reach the parser, and one\nof them is usually the error.\n","readmeFilename":"README.md"}