[
  {
    "path": ".github/FUNDING.yml",
    "content": "patreon: marijn\ncustom: ['https://www.paypal.com/paypalme/marijnhaverbeke', 'https://marijnhaverbeke.nl/fund/']\ngithub: marijnh"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/issue.yaml",
    "content": "name: Issue Report\ndescription: Report a problem\nbody:\n  - type: markdown\n    attributes:\n      value: Thanks for reporting an issue. If you have a question or request for support, use the [forum](https://discuss.codemirror.net/), **not** the bug tracker.\n  - type: textarea\n    id: descriptin\n    attributes:\n      label: Describe the issue\n    validations:\n      required: true\n  - type: input\n    id: browser\n    attributes:\n      label: Browser and platform\n      description: If there is any chance at all that this is browser or platform related, please let us know which ones you tested. If IME or a virtual keyboard was involved, please mention which.\n    validations:\n      required: false\n  - type: input\n    id: try\n    attributes:\n      label: Reproduction link\n      description: When practical, it helps a lot if you provide a script that reproduces the issue in [the CodeMirror sandbox](https://codemirror.net/try/) or another online code environment.\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: main\non: [push, repository_dispatch]\njobs:\n  build-and-test:\n    runs-on: ubuntu-latest\n    name: Build and test\n    steps:\n      - uses: styfle/cancel-workflow-action@0.9.1\n        with:\n          access_token: ${{ github.token }}\n\n      - uses: actions/checkout@v1\n\n      - uses: actions/setup-node@v2\n        with:\n          node-version: '22.11.0'\n\n      - run: node bin/cm.js install\n\n      - run: npm test\n"
  },
  {
    "path": ".gitignore",
    "content": "/node_modules\npackage-lock.json\n/demo/demo.js*\n/demo/demo.d.ts*\n/demo/test/test.js*\n/website\n/buildhelper\n/state\n/view\n/commands\n/collab\n/language\n/language-data\n/search\n/lint\n/autocomplete\n/codemirror\n/merge\n/lsp-client\n/lang-javascript\n/lang-java\n/lang-json\n/lang-cpp\n/lang-python\n/lang-go\n/lang-css\n/lang-html\n/lang-php\n/lang-sql\n/lang-rust\n/lang-xml\n/lang-markdown\n/lang-lezer\n/lang-wast\n/lang-angular\n/lang-vue\n/lang-liquid\n/lang-sass\n/lang-jinja\n/lang-less\n/lang-yaml\n/legacy-modes\n/theme-one-dark\n.tern-*\n"
  },
  {
    "path": ".npmignore",
    "content": "/*/src/*.js\n/*/src/*.ts\n!/*/src/*.d.ts\n/*/src/*.map\n/*/src/README.md\n/*/test\n/node_modules\n/demo\n/.travis.yml\n.tern-*\n/bin\n/website\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to contribute\n\n- [Getting help](#getting-help)\n- [Submitting bug reports](#submitting-bug-reports)\n- [Contributing code](#contributing-code)\n\n## Getting help\n\nCommunity discussion, questions, and informal bug reporting is done on\nthe [discuss.CodeMirror forum](http://discuss.codemirror.net).\n\n## Submitting bug reports\n\nReport bugs on the\n[GitHub issue tracker](http://github.com/codemirror/dev/issues).\nBefore reporting a bug, please read these pointers.\n\n- The issue tracker is for *bugs*, not requests for help. Questions\n  should be asked on the [forum](http://discuss.codemirror.net).\n\n- Include information about the version of the code that exhibits the\n  problem. For browser-related issues, include the browser, browser\n  version, and operating system on which the problem occurred.\n\n- Mention very precisely what went wrong. \"X is broken\" is not a good\n  bug report. What did you expect to happen? What happened instead?\n  Describe the exact steps a maintainer has to take to make the\n  problem occur. A screencast can be useful, but is no substitute for\n  a textual description.\n\n- A great way to make it easy to reproduce your problem, if it can not\n  be trivially reproduced on the website demos, is to submit a script\n  that triggers the issue. The easiest way do do that is our\n  [sandbox](https://codemirror.net/try/).\n\n## Contributing code\n\nCode written by \"AI\" language models (either partially or fully) is\n**not welcome**. Both because you cannot guarantee it's not parroting\ncopyrighted content, and because it tends to be of low quality and a\nwaste of time to review.\n\n- Make sure you have a [GitHub Account](https://github.com/signup/free)\n\n- Fork the relevant repository\n  ([how to fork a repo](https://help.github.com/articles/fork-a-repo))\n\n- Create a local checkout of the code. You can use the\n  [dev repository](https://github.com/codemirror/dev) to\n  easily check out all core modules.\n\n- Make your changes, and commit them\n\n- Follow the code style of the rest of the project (see below).\n\n- If your changes are easy to test or likely to regress, add tests in\n  the relevant `test/` directory. Either put them in an existing\n  `test-*.js` file, if they fit there, or add a new file.\n\n- Make sure all tests pass. Run `npm run test` to verify tests pass.\n\n- Submit a pull request ([how to create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)).\n  Don't put more than one feature/fix in a single pull request.\n\nBy contributing code to CodeMirror you\n\n - Agree to license the contributed code under the project's [MIT\n   license](https://github.com/CodeMirror/dev/blob/main/LICENSE).\n\n - Confirm that you have the right to contribute and license the code\n   in question. (Either you hold all rights on the code, or the rights\n   holder has explicitly granted the right to use it like this,\n   through a compatible open source license or through a direct\n   agreement with you.)\n\n### Coding standards\n\n- TypeScript, targeting an ES2018 runtime (i.e. don't use library\n  elements added after ES2018).\n\n- 2 spaces per indentation level, no tabs.\n\n- No semicolons except when necessary.\n\n- Follow the surrounding code when it comes to spacing, brace\n  placement, etc.\n\n- Brace-less single-statement bodies are encouraged (whenever they\n  don't impact readability).\n\n- [getdocs](https://github.com/marijnh/getdocs-ts)-style doc comments\n  above items that are part of the public API.\n\n- CodeMirror does *not* follow JSHint or JSLint prescribed style.\n  Patches that try to 'fix' code to pass one of these linters will not\n  be accepted.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin>, Adrian\nHeine <mail@adrianheine.de>, and others\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# CodeMirror\n\n[![Build Status](https://github.com/codemirror/dev/workflows/main/badge.svg)](https://github.com/codemirror/codemirror.next/actions)\n\nThis is the central repository for [CodeMirror](https://codemirror.net/). It holds the bug tracker and development scripts.\n\nIf you want to **use** CodeMirror, install the separate packages from npm, and ignore the contents of this repository. If you want to **develop on** CodeMirror, this repository provides scripts to install and work with the various packages.\n\nTo get started, make sure you are running [node.js](https://nodejs.org/) version 16. After cloning the repository, run\n\n    node bin/cm.js install\n\nto clone the packages that make up the system, install dependencies, and build the packages. At any time you can rebuild packages, either by running `npm run prepare` in their subdirectory, or all at once with\n\n    node bin/cm.js build\n\nDeveloping is best done by setting up\n\n    npm run dev\n\nwhich starts a server that automatically rebuilds the packages when their code changes and exposes a dev server on port 8090 running the [demo](http://localhost:8090) and [browser tests](http://localhost:8090/test/).\n\nPlease see [the website](https://codemirror.net/) for more information and [docs](https://codemirror.net/docs/ref).\n"
  },
  {
    "path": "bin/build-readme.js",
    "content": "// Function to build github-proof readmes that contain the package's API\n// docs as HTML.\n\nconst {core} = require(\"./packages\")\nconst {gather, gatherMany} = require(\"getdocs-ts\")\nconst {build, browserImports} = require(\"builddocs\")\nconst {join} = require(\"path\"), fs = require(\"fs\")\n\nexports.buildReadme = function(pkg) {\n  let imports = [type => {\n    let sibling = type.typeSource && core.find(name => type.typeSource.startsWith(\"../\" + name + \"/\"))\n    if (sibling) return \"https://codemirror.net/docs/ref#\" + sibling + \".\" + type.type\n  }, type => {\n    if (/\\blezer\\/tree\\b/.test(type.typeSource)) return `https://lezer.codemirror.net/docs/ref/#tree.${type.type}`\n    if (/\\blezer\\/common\\b/.test(type.typeSource)) return `https://lezer.codemirror.net/docs/ref/#common.${type.type}`\n    if (/\\blezer\\/lr\\b/.test(type.typeSource)) return `https://lezer.codemirror.net/docs/ref/#lr.${type.type}`\n    if (/\\blezer\\/markdown\\b/.test(type.typeSource)) return `https://github.com/lezer-parser/markdown#user-content-${type.type.toLowerCase()}`\n    if (/\\bstyle-mod\\b/.test(type.typeSource)) return \"https://github.com/marijnh/style-mod#documentation\"\n    if (/\\bvscode-languageserver-/.test(type.typeSource))\n      return `https://microsoft.github.io/language-server-protocol/specifications/specification-current#` +\n        type.type[0].toLowerCase() + type.type.slice(1)\n    if (type.type == \"TextEdit\") console.log(type.typeSource, type.type)\n  }, browserImports]\n\n  let template = fs.readFileSync(join(pkg.dir, pkg.name == \"legacy-modes\" ? \"mode\" : \"src\", \"README.md\"), \"utf8\")\n  let html = \"\"\n\n  if (pkg.name == \"legacy-modes\") {\n    let mods = fs.readdirSync(join(pkg.dir, \"mode\")).filter(f => /\\.d.ts$/.test(f)).map(file => {\n      let name = /^(.*)\\.d\\.ts$/.exec(file)[1]\n      return {name, filename: join(pkg.dir, \"mode\", file), basedir: pkg.dir}\n    }), items = gatherMany(mods)\n    for (let i = 0; i < mods.length; i++) {\n      let {name} = mods[i]\n      html += `\\n<h3 id=\"${name}\">mode/<a href=\"#${name}\">${name}</a></h3>\\n` + build({\n        name: pkg.name,\n        anchorPrefix: name + \".\",\n        allowUnresolvedTypes: false,\n        imports\n      }, items[i])\n    }\n    template += \"\\n$$$\"\n  } else {\n    let placeholders = /(^|\\n)@[^]*@\\w+|\\n@\\w+/.exec(template)\n    html = build({\n      mainText: placeholders[0],\n      name: pkg.name,\n      anchorPrefix: \"\",\n      allowUnresolvedTypes: false,\n      imports\n    }, gather({filename: pkg.main, basedir: pkg.dir}))\n    template = template.slice(0, placeholders.index) + \"\\n$$$\" + template.slice(placeholders.index + placeholders[0].length)\n  }\n\n  html = html.replace(/<\\/?span.*?>/g, \"\")\n    .replace(/id=\"(.*?)\"/g, (_, id) => `id=\"user-content-${id.toLowerCase()}\"`)\n    .replace(/href=\"#(.*?)\"/g, (_, id) => {\n      let first = /^[^^.]*/.exec(id)[0]\n      if (core.includes(first)) return `href=\"https://codemirror.net/docs/ref/#${id}\"`\n      if (first == pkg.name && id.length > first.length) id = id.slice(first.length + 1)\n      return `href=\"#user-content-${id.toLowerCase()}\"`\n    })\n\n  return template.replace(\"$$$\", html)\n}\n"
  },
  {
    "path": "bin/cm.js",
    "content": "#!/usr/bin/env node\n\n// NOTE: Don't require anything from node_modules here, since the\n// install script has to be able to run _before_ that exists.\nconst child = require(\"child_process\"), fs = require(\"fs\"), path = require(\"path\"), {join} = path\n\nlet root = join(__dirname, \"..\")\n\nconst {loadPackages, nonCore} = require(\"./packages\")\n\nlet {packages, packageNames, buildPackages} = loadPackages()\n\nfunction start() {\n  let command = process.argv[2]\n  if (command && ![\"install\", \"--help\"].includes(command)) assertInstalled()\n  let args = process.argv.slice(3)\n  let cmdFn = {\n    packages: listPackages,\n    status,\n    build,\n    devserver,\n    release,\n    unreleased,\n    install,\n    clean,\n    commit,\n    push,\n    grep,\n    \"build-readme\": buildReadme,\n    test,\n    run: runCmd,\n    \"--help\": () => help(0)\n  }[command]\n  if (!cmdFn || cmdFn.length > args.length) help(1)\n  new Promise(r => r(cmdFn.apply(null, args))).catch(e => error(e))\n}\n\nfunction help(status) {\n  console.log(`Usage:\n  cm install [--ssh]      Clone and symlink the packages, install deps, build\n  cm packages             Emit a list of all pkg names\n  cm status               Output git status, when interesting, for packages\n  cm build                Build the bundle files\n  cm clean                Delete files created by the build\n  cm devserver [--source-map]\n                          Start a dev server on port 8090\n  cm release <package> [--edit] [--version <version>]\n                          Create commits to tag a release\n  cm build-readme <pkg>   Regenerate the readme file for a non-core package\n  cm commit <args>        Run git commit in all packages that have changes\n  cm push                 Run git push in packages that have new commits\n  cm run <command>        Run the given command in each of the package dirs\n  cm test [--no-browser]  Run the test suite of all the packages\n  cm grep <pattern>       Grep through the source code for all packages\n  cm --help`)\n  process.exit(status)\n}\n\nfunction error(err) {\n  console.error(err)\n  process.exit(1)\n}\n\nfunction run(cmd, args, wd = root, { shell = false } = {}) {\n  return child.execFileSync(cmd, args, {shell, cwd: wd, encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", process.stderr]})\n}\n\nfunction replace(file, f) {\n  fs.writeFileSync(file, f(fs.readFileSync(file, \"utf8\")))\n}\n\nfunction assertInstalled() {\n  for (let p of packages) {\n    if (!fs.existsSync(p.dir)) {\n      console.error(`module ${p.name} is missing. Did you forget to run 'cm install'?`)\n      process.exit(1)\n    }\n  }\n}\n\nfunction install(arg = null) {\n  let base = arg == \"--ssh\" ? \"git@github.com:codemirror/\" : \"https://github.com/codemirror/\"\n  if (arg && arg != \"--ssh\") help(1)\n\n  for (let pkg of packages) {\n    if (fs.existsSync(pkg.dir)) {\n      console.warn(`Skipping cloning of ${pkg.name} (directory exists)`)\n    } else {\n      let origin = base + (pkg.name == \"codemirror\" ? \"basic-setup\" : pkg.name) + \".git\"\n      run(\"git\", [\"clone\", origin, pkg.dir])\n    }\n  }\n\n  console.log(\"Running npm install\")\n  run(\"npm\", [\"install\"], root, {shell: process.platform == \"win32\"})\n  console.log(\"Building modules\")\n  ;({packages, packageNames, buildPackages} = loadPackages())\n  build()\n}\n\n\nfunction listPackages() {\n  console.log(packages.map(p => p.name).join(\"\\n\"))\n}\n\nfunction status() {\n  for (let pkg of packages) {\n    let output = run(\"git\", [\"status\", \"-sb\"], pkg.dir)\n    if (output != \"## main...origin/main\\n\")\n      console.log(`${pkg.name}:\\n${output}`)\n  }\n}\n\nasync function build() {\n  console.info(\"Building...\")\n  let t0 = Date.now()\n  await require(\"@marijn/buildtool\").build(buildPackages.map(p => p.main), require(\"@codemirror/buildhelper/src/options\").options)\n  console.info(`Done in ${((Date.now() - t0) / 1000).toFixed(2)}s`)\n}\n\nfunction startServer() {\n  let serve = join(root, \"demo\")\n  let moduleserver = new (require(\"esmoduleserve/moduleserver\"))({root: serve, maxDepth: 2})\n  let serveStatic = require(\"serve-static\")(serve, {\n    setHeaders(res, path) {\n      if (/try\\/mods\\//.test(path)) res.setHeader(\"Access-Control-Allow-Origin\", \"*\")\n    }\n  })\n  require(\"http\").createServer((req, resp) => {\n    if (/^\\/test\\/?($|\\?)/.test(req.url)) {\n      let runTests = require(\"@marijn/testtool\")\n      let {browserTests} = runTests.gatherTests(buildPackages.map(p => p.dir))\n      resp.writeHead(200, {\"content-type\": \"text/html\"})\n      resp.end(runTests.testHTML(browserTests.map(f => path.relative(serve, f)), {\n        html: `<title>CM6 view tests</title>\n<h1>CM6 view tests</h1>\n<div id=\"workspace\" style=\"opacity: 0; position: fixed; top: 0; left: 0; width: 20em;\"></div>`\n      }))\n    } else {\n      moduleserver.handleRequest(req, resp) || serveStatic(req, resp, _err => {\n        resp.statusCode = 404\n        resp.end('Not found')\n      })\n    }\n  }).listen(8090, process.env.OPEN ? undefined : \"127.0.0.1\")\n  console.log(\"Dev server listening on 8090\")\n}\n\nfunction devserver(...args) {\n  let options = {\n    sourceMap : args.includes('--source-map'),\n    ...require(\"@codemirror/buildhelper/src/options\").options\n  }\n  require(\"@marijn/buildtool\").watch(buildPackages.map(p => p.main).filter(f => f), [join(root, \"demo/demo.ts\")], options)\n  startServer()\n}\n\nfunction changelog(pkg, since) {\n  let commits = run(\"git\", [\"log\", \"--format=%B%n\", \"--reverse\", since + \"..main\"], pkg.dir)\n  let result = {fix: [], feature: [], breaking: []}\n  let re = /\\n\\r?\\n(BREAKING|FIX|FEATURE):\\s*([^]*?)(?=\\r?\\n\\r?\\n|\\r?\\n?$)/g, match\n  while (match = re.exec(commits)) result[match[1].toLowerCase()].push(match[2].replace(/\\r?\\n/g, \" \"))\n  return result\n}\n\nfunction bumpVersion(version, changes) {\n  let [major, minor, patch] = version.split(\".\")\n  if (major == \"0\") return changes.breaking.length ? `0.${Number(minor) + 1}.0` : `0.${minor}.${Number(patch) + 1}`\n  if (changes.breaking.length) return `${Number(major) + 1}.0.0`\n  if (changes.feature.length) return `${major}.${Number(minor) + 1}.0`\n  if (changes.fix.length) return `${major}.${minor}.${Number(patch) + 1}`\n  throw new Error(\"No new release notes!\")\n}\n\nfunction releaseNotes(changes, version) {\n  let pad = n => n < 10 ? \"0\" + n : n\n  let d = new Date, date = d.getFullYear() + \"-\" + pad(d.getMonth() + 1) + \"-\" + pad(d.getDate())\n\n  let types = {breaking: \"Breaking changes\", fix: \"Bug fixes\", feature: \"New features\"}\n\n  let refTarget = \"https://codemirror.net/docs/ref/\"\n  let head = `## ${version} (${date})\\n\\n`, body = \"\"\n  for (let type in types) {\n    let messages = changes[type]\n    if (messages.length) body += `### ${types[type]}\\n\\n`\n    messages.forEach(message => body += message.replace(/\\]\\(##/g, \"](\" + refTarget + \"#\") + \"\\n\\n\")\n  }\n  return {head, body}\n}\n\nfunction setModuleVersion(pkg, version) {\n  let file = join(pkg.dir, \"package.json\")\n  fs.writeFileSync(file, fs.readFileSync(file, \"utf8\").replace(/\"version\":\\s*\".*?\"/, `\"version\": \"${version}\"`))\n}\n\nfunction updateDependencyVersion(pkg, version) {\n  let changed = []\n  for (let other of packages) if (other != pkg) {\n    let pkgFile = join(other.dir, \"package.json\"), text = fs.readFileSync(pkgFile, \"utf8\")\n    let updated = text.replace(new RegExp(`(\"@codemirror/${pkg.name}\": \")(.*?)\"`, \"g\"), (_, m) => m + \"^\" + version + '\"')\n    if (updated != text) {\n      changed.push(other)\n      fs.writeFileSync(pkgFile, updated)\n      run(\"git\", [\"add\", \"package.json\"], other.dir)\n      let lastMsg = run(\"git\", [\"log\", \"-1\", \"--pretty=%B\"], other.dir)\n      if (/^Bump dependency /.test(lastMsg))\n        run(\"git\", [\"commit\", \"--amend\", \"-m\", lastMsg.trimEnd() + \", @codemirror/\" + pkg.name], other.dir)\n      else\n        run(\"git\", [\"commit\", \"-m\", \"Bump dependency for @codemirror/\" + pkg.name], other.dir)\n    }\n  }\n  return changed\n}\n\nfunction version(pkg) {\n  return require(join(pkg.dir, \"package.json\")).version\n}\n\nconst mainVersion = /^0.\\d+|\\d+/\n\nfunction release(...args) {\n  let setVersion, edit = false, pkgName, pkg\n  for (let i = 0; i < args.length; i++) {\n    let arg = args[i]\n    if (arg == \"--edit\") edit = true\n    else if (arg == \"--version\" && i < args.length) setVersion = args[++i]\n    else if (!pkgName && arg[0] != \"-\") pkgName = arg\n    else help(1)\n  }\n  if (!pkgName || !(pkg = packageNames[pkgName])) help(1)\n\n  run(\"git\", [\"pull\"], pkg.dir)\n\n  let {changes, newVersion} = doRelease(pkg, setVersion, {edit})\n\n  // Turned off for now, since this creates a huge mess on accidental\n  // major version bumps. Maybe add a manual utility for it?\n  if (false && mainVersion.exec(newVersion)[0] != mainVersion.exec(version(pkg))[0]) {\n    let updated = updateDependencyVersion(pkg, newVersion)\n    if (updated.length) console.log(`Updated dependencies in ${updated.map(p => p.name).join(\", \")}`)\n  }\n}\n\nfunction doRelease(pkg, newVersion, {edit = false, defaultChanges = null}) {\n  let log = join(pkg.dir, \"CHANGELOG.md\")\n  let newPackage = !fs.existsSync(log)\n\n  let currentVersion = version(pkg)\n  let changes = newPackage ? {fix: [], feature: [], breaking: [\"First numbered release.\"]} : changelog(pkg, currentVersion)\n  if (defaultChanges && !changes.fix.length && !changes.feature.length && !changes.breaking.length) changes = defaultChanges\n  if (!newVersion) newVersion = newPackage ? currentVersion : bumpVersion(currentVersion, changes)\n  console.log(`Creating @codemirror/${pkg.name} ${newVersion}`)\n\n  let notes = releaseNotes(changes, newVersion)\n  if (edit) notes = editReleaseNotes(notes)\n\n  setModuleVersion(pkg, newVersion)\n  fs.writeFileSync(log, notes.head + notes.body + (newPackage ? \"\" : fs.readFileSync(log, \"utf8\")))\n  run(\"git\", [\"add\", \"package.json\"], pkg.dir)\n  run(\"git\", [\"add\", \"CHANGELOG.md\"], pkg.dir)\n  run(\"git\", [\"commit\", \"-m\", `Mark version ${newVersion}`], pkg.dir)\n  run(\"git\", [\"tag\", newVersion, \"-m\", `Version ${newVersion}\\n\\n${notes.body}`, \"--cleanup=verbatim\"], pkg.dir)\n\n  return {changes, newVersion}\n}\n\nfunction editReleaseNotes(notes) {\n  let noteFile = join(root, \"notes.txt\")\n  fs.writeFileSync(noteFile, notes.head + notes.body)\n  run(process.env.EDITOR || \"emacs\", [noteFile])\n  let edited = fs.readFileSync(noteFile)\n  fs.unlinkSync(noteFile)\n  if (!/\\S/.test(edited)) process.exit(0)\n  let split = /^(.*)\\n+([^]*)/.exec(edited)\n  return {head: split[1] + \"\\n\\n\", body: split[2]}\n}\n\nfunction unreleased() {\n  for (let pkg of packages) {\n    let ver = version(pkg), changes = changelog(pkg, ver)\n    if (changes.fix.length || changes.feature.length || changes.breaking.length)\n      console.log(pkg.name + \":\\n\\n\" + releaseNotes(changes, ver).body)\n  }\n}\n\nfunction clean() {\n  for (let pkg of buildPackages)\n    run(\"rm\", [\"-rf\", \"dist\"], pkg.dir)\n}\n\nfunction commit(...args) {\n  for (let pkg of packages) {\n    if (run(\"git\", [\"diff\"], pkg.dir) || run(\"git\", [\"diff\", \"--cached\"], pkg.dir))\n      console.log(pkg.name + \":\\n\" + run(\"git\", [\"commit\"].concat(args), pkg.dir))\n  }\n}\n\nfunction push(...args) {\n  for (let pkg of packages) {\n    if (/\\bahead\\b/.test(run(\"git\", [\"status\", \"-sb\"], pkg.dir)))\n      run(\"git\", [\"push\", ...args], pkg.dir)\n  }\n}\n\nfunction grep(pattern) {\n  let files = [join(root, \"demo\", \"demo.ts\")]\n  function add(dir, ext) {\n    let list\n    try { list = fs.readdirSync(dir) }\n    catch (_) { return }\n    for (let f of list) if (ext.includes(/^[^.]*(.*)/.exec(f)[1])) {\n      files.push(path.relative(process.cwd(), join(dir, f)))\n    }\n  }\n  for (let pkg of packages) {\n    if (pkg.name == \"legacy-modes\") {\n      add(join(pkg.dir, \"mode\"), [\".js\", \".d.ts\"])\n    } else {\n      add(join(pkg.dir, \"src\"), [\".ts\"])\n      add(join(pkg.dir, \"test\"), [\".ts\"])\n    }\n  }\n  try {\n    console.log(run(\"grep\", [\"--color\", \"-nH\", \"-e\", pattern].concat(files), process.cwd()))\n  } catch(e) {\n    process.exit(1)\n  }\n}\n\nfunction runCmd(cmd, ...args) {\n  for (let pkg of packages) {\n    console.log(pkg.name + \":\")\n    try {\n      console.log(run(cmd, args, pkg.dir))\n    } catch (e) {\n      console.log(e.toString())\n      process.exit(1)\n    }\n  }\n}\n\nfunction buildReadme(name) {\n  if (!nonCore.includes(name)) help(1)\n  let pkg = packageNames[name]\n  fs.writeFileSync(join(pkg.dir, \"README.md\"), require(\"./build-readme\").buildReadme(pkg))\n}\n\nfunction test(...args) {\n  let runTests = require(\"@marijn/testtool\")\n  let {tests, browserTests} = runTests.gatherTests(buildPackages.map(p => p.dir))\n  let browsers = [], grep, noBrowser = false\n  for (let i = 0; i < args.length; i++) {\n    if (args[i] == \"--firefox\") browsers.push(\"firefox\")\n    if (args[i] == \"--chrome\") browser.push(\"chrome\")\n    if (args[i] == \"--no-browser\") noBrowser = true\n    if (args[i] == \"--grep\") grep = args[++i]\n  }\n  if (!browsers.length && !noBrowser) browsers.push(\"chrome\")\n  runTests.runTests({tests, browserTests, browsers, grep}).then(failed => process.exit(failed ? 1 : 0))\n}\n\nstart()\n"
  },
  {
    "path": "bin/packages.js",
    "content": "const fs = require(\"fs\"), {join} = require(\"path\")\n\nexports.core = [\n  \"state\",\n  \"view\",\n  \"language\",\n  \"commands\",\n  \"search\",\n  \"autocomplete\",\n  \"lint\",\n  \"collab\",\n  \"language-data\",\n  \"merge\",\n  \"lsp-client\",\n  \"codemirror\",\n]\nexports.nonCore = [\n  \"lang-javascript\",\n  \"lang-java\",\n  \"lang-json\",\n  \"lang-cpp\",\n  \"lang-php\",\n  \"lang-python\",\n  \"lang-go\",\n  \"lang-css\",\n  \"lang-sass\",\n  \"lang-html\",\n  \"lang-sql\",\n  \"lang-rust\",\n  \"lang-xml\",\n  \"lang-markdown\",\n  \"lang-lezer\",\n  \"lang-wast\",\n  \"lang-angular\",\n  \"lang-vue\",\n  \"lang-liquid\",\n  \"lang-less\",\n  \"lang-yaml\",\n  \"lang-jinja\",\n  \"legacy-modes\",\n  \"theme-one-dark\"\n]\n\nexports.all = exports.core.concat(exports.nonCore)\n\nclass Pkg {\n  constructor(name) {\n    this.name = name\n    this.dir = join(__dirname, \"..\", name)\n    this.main = null\n    if (name != \"legacy-modes\" && fs.existsSync(this.dir)) {\n      let files = fs.readdirSync(join(this.dir, \"src\")).filter(f => /^[^.]+\\.ts$/.test(f))\n      let main = files.length == 1 ? files[0] : files.includes(\"index.ts\") ? \"index.ts\"\n          : files.includes(name.replace(/^(theme-|lang-)/, \"\") + \".ts\") ? name.replace(/^(theme-|lang-)/, \"\") + \".ts\" : null\n      if (!main) throw new Error(\"Couldn't find a main script for \" + name)\n      this.main = join(this.dir, \"src\", main)\n    }\n  }\n}\nexports.Pkg = Pkg\n\nexports.loadPackages = function loadPackages() {\n  let packages = exports.all.map(n => new Pkg(n))\n  let packageNames = Object.create(null)\n  for (let p of packages) packageNames[p.name] = p\n  return {packages, packageNames, buildPackages: packages.filter(p => p.main)}\n}\n"
  },
  {
    "path": "demo/demo.ts",
    "content": "import {EditorView, basicSetup} from \"codemirror\"\nimport {javascript} from \"@codemirror/lang-javascript\"\n\n;(window as any).view = new EditorView({\n  doc: 'console.log(\"Hello world\")',\n  extensions: [\n    basicSetup,\n    javascript(),\n  ],\n  parent: document.body\n})\n"
  },
  {
    "path": "demo/index.html",
    "content": "<!doctype html>\n<meta charset=utf8>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>CM6 demo</title>\n\n<style>\n.cm-editor { height: 300px; border: 1px solid #ddd}\n.cm-scroller { overflow: auto; }\n</style>\n\n<h1>CM6</h1>\n\n<script type=module src=\"_m/demo.js\"></script>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"description\": \"Development environment for the CodeMirror 6 packages\",\n  \"scripts\": {\n    \"test\": \"node bin/cm.js test\",\n    \"test-node\": \"node bin/cm.js test --no-browser\",\n    \"prepare\": \"node bin/cm.js build\",\n    \"dev\": \"node bin/cm.js devserver\"\n  },\n  \"author\": \"Marijn Haverbeke <marijn@haverbeke.berlin>\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@codemirror/buildhelper\": \"^1.0.2\",\n    \"esmoduleserve\": \"^0.2.0\",\n    \"serve-static\": \"^1.14.1\",\n    \"getdocs-ts\": \"^1.0.0\",\n    \"builddocs\": \"^1.0.0\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/codemirror/dev.git\"\n  },\n  \"workspaces\": [\n    \"*\"\n  ],\n  \"private\": true\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"es2018\", \"dom\", \"scripthost\"],\n    \"types\": [\"mocha\"],\n    \"stripInternal\": true,\n    \"typeRoots\": [\"./node_modules/@types\"],\n    \"noUnusedLocals\": true,\n    \"strict\": true,\n    \"target\": \"es2018\",\n    \"module\": \"es2020\",\n    \"newLine\": \"lf\",\n    \"moduleResolution\": \"node\",\n    \"paths\": {\n      \"@codemirror/state\": [\"./state/src/index.ts\"],\n      \"@codemirror/view\": [\"./view/src/index.ts\"],\n      \"@codemirror/commands\": [\"./commands/src/commands.ts\"],\n      \"@codemirror/collab\": [\"./collab/src/collab.ts\"],\n      \"@codemirror/language\": [\"./language/src/index.ts\"],\n      \"@codemirror/language-data\": [\"./language-data/src/language-data.ts\"],\n      \"@codemirror/search\": [\"./search/src/search.ts\"],\n      \"@codemirror/lint\": [\"./lint/src/lint.ts\"],\n      \"@codemirror/autocomplete\": [\"./autocomplete/src/index.ts\"],\n      \"@codemirror/merge\": [\"./merge/src/index.ts\"],\n      \"@codemirror/lsp-client\": [\"./lsp-client/src/index.ts\"],\n      \"codemirror\": [\"./codemirror/src/codemirror.ts\"],\n      \"@codemirror/lang-javascript\": [\"./lang-javascript/src/index.ts\"],\n      \"@codemirror/lang-java\": [\"./lang-java/src/java.ts\"],\n      \"@codemirror/lang-json\": [\"./lang-json/src/json.ts\"],\n      \"@codemirror/lang-cpp\": [\"./lang-cpp/src/cpp.ts\"],\n      \"@codemirror/lang-python\": [\"./lang-python/src/python.ts\"],\n      \"@codemirror/lang-go\": [\"./lang-go/src/index.ts\"],\n      \"@codemirror/lang-css\": [\"./lang-css/src/css.ts\"],\n      \"@codemirror/lang-html\": [\"./lang-html/src/html.ts\"],\n      \"@codemirror/lang-sql\": [\"./lang-sql/src/sql.ts\"],\n      \"@codemirror/lang-rust\": [\"./lang-rust/src/rust.ts\"],\n      \"@codemirror/lang-xml\": [\"./lang-xml/src/xml.ts\"],\n      \"@codemirror/lang-markdown\": [\"./lang-markdown/src/index.ts\"],\n      \"@codemirror/lang-lezer\": [\"./lang-lezer/src/index.ts\"],\n      \"@codemirror/lang-php\": [\"./lang-php/src/php.ts\"],\n      \"@codemirror/lang-wast\": [\"./lang-wast/src/wast.ts\"],\n      \"@codemirror/lang-angular\": [\"./lang-angular/src/angular.ts\"],\n      \"@codemirror/lang-vue\": [\"./lang-vue/src/vue.ts\"],\n      \"@codemirror/lang-liquid\": [\"./lang-vue/src/liquid.ts\"],\n      \"@codemirror/lang-sass\": [\"./lang-sass/src/sass.ts\"],\n      \"@codemirror/lang-less\": [\"./lang-less/src/less.ts\"],\n      \"@codemirror/lang-yaml\": [\"./lang-yaml/src/yaml.ts\"],\n      \"@codemirror/lang-jinja\": [\"./lang-jinja/src/jinja.ts\"],\n      \"@codemirror/theme-one-dark\": [\"./theme-one-dark/src/one-dark.ts\"]\n    }\n  },\n  \"include\": [\"*/src/*.ts\", \"*/test/*.ts\", \"demo/demo.ts\"],\n}\n"
  }
]