[
  {
    "path": ".devcontainer/Dockerfile",
    "content": "# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.158.0/containers/typescript-node/.devcontainer/base.Dockerfile\n\n# [Choice] Node.js version: 14, 12, 10\nARG VARIANT=\"14-buster\"\nFROM mcr.microsoft.com/devcontainers/typescript-node:${VARIANT}\n\nRUN apt-get update && export DEBIAN_FRONTEND=noninteractive \\\n    && apt-get -y install --no-install-recommends libx11-dev libxkbfile-dev libsecret-1-dev rsync\n\n# copied from https://github.com/microsoft/vscode-oniguruma/blob/main/.devcontainer/Dockerfile\nRUN mkdir -p /opt/dev \\\n    && cd /opt/dev \\\n    && git clone https://github.com/emscripten-core/emsdk.git \\\n    && cd /opt/dev/emsdk \\\n    && ./emsdk install 3.1.21 \\\n    && ./emsdk activate 3.1.21\n\nENV PATH=\"/opt/dev/emsdk:/opt/dev/emsdk/node/14.18.2_64bit/bin:/opt/dev/emsdk/upstream/emscripten:${PATH}\"\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:\n// https://github.com/microsoft/vscode-dev-containers/tree/v0.158.0/containers/typescript-node\n{\n\t\"name\": \"Node.js & TypeScript\",\n\t\"build\": {\n\t\t\"dockerfile\": \"Dockerfile\",\n\t\t// Update 'VARIANT' to pick a Node version: 10, 12, 14\n\t\t\"args\": { \n\t\t\t\"VARIANT\": \"20-bullseye\"\n\t\t}\n\t},\n\n\t// Set *default* container specific settings.json values on container create.\n\t\"settings\": { \n\t\t\"terminal.integrated.shell.linux\": \"/bin/bash\"\n\t},\n\n\t// Add the IDs of extensions you want installed when the container is created.\n\t\"extensions\": [\n\t\t\"dbaeumer.vscode-eslint\"\n\t],\n\n\t// Use 'forwardPorts' to make a list of ports inside the container available locally.\n\t\"forwardPorts\": [8080],\n\n\t// Use 'postCreateCommand' to run commands after the container is created.\n\t//\"postCreateCommand\": \"npm install\",\n\n\t// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.\n\t\"remoteUser\": \"node\"\n}"
  },
  {
    "path": ".editorconfig",
    "content": "# EditorConfig is awesome: https://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n# Tab indentation\n[*]\nindent_style = tab\ntrim_trailing_whitespace = true\n\n# The indent size used in the `package.json` file cannot be changed\n# https://github.com/npm/npm/pull/3180#issuecomment-16336516\n[{*.yml,*.yaml,*.json}]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".github/config.yml",
    "content": "# Configuration for welcome - https://github.com/behaviorbot/welcome\n\n# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome\n# Comment to be posted to on first time issues\n\nnewIssueWelcomeComment: >\n  Hello there!👋 Welcome to the project!💖\n  Thank you and congrats🎉for opening your very first issue in this project.Be patient while we get back to you.😄\n\n# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome\n# Comment to be posted to on PRs from first time contributors in your repository\n\nnewPRWelcomeComment: >\n  Hello there!👋 Welcome to the project!💖\n  Thank you and congrats🎉 for opening your first pull request✨ 🙌.We will get back to you as soon as we can.😄\n\n# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge\n# Comment to be posted to on pull requests merged by a first time user\n\nfirstPRMergeComment: >\n  Congrats on merging your first pull request! 🎉🎉🎉 We here at github1s are proud of you!\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build & Test\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\njobs:\n  build:\n    strategy:\n      matrix:\n        os: [macos-14]\n        node-version: [20.x]\n\n    runs-on: ${{ matrix.os }}\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          cache: 'npm'\n          node-version: ${{ matrix.node-version }}\n\n      - run: npm install\n      - run: npm run eslint\n      - run: npm run build\n      - uses: microsoft/playwright-github-action@v1\n      - run: GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} npm run test:ci\n"
  },
  {
    "path": ".github/workflows/codacy-analysis.yaml",
    "content": "name: Codacy Security Scan\n\non:\n  push:\n    branches: ['master', 'main']\n  pull_request:\n    branches: ['master', 'main']\n\njobs:\n  codacy-security-scan:\n    name: Codacy Security Scan\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Run Codacy Analysis CLI\n        uses: codacy/codacy-analysis-cli-action@master\n        with:\n          # Run analysis without SARIF output to avoid GitHub Code Scanning integration issues\n          # See: https://github.com/codacy/codacy-analysis-cli-action/issues/142\n          # The Codacy tool generates multiple SARIF runs which is incompatible with\n          # GitHub's new policy as of July 2025\n          verbose: true\n          # Force 0 exit code to prevent workflow failures\n          max-allowed-issues: 2147483647\n          # only scan the github1s directory\n          directory: $GITHUB_WORKSPACE/extensions/github1s\n\n      # SARIF upload is temporarily disabled due to incompatibility\n      # See: https://github.com/codacy/codacy-analysis-cli-action/issues/142\n      # TODO: Re-enable when Codacy fixes the multiple runs issue\n      # - name: Upload SARIF results file\n      #   uses: github/codeql-action/upload-sarif@v4\n      #   with:\n      #     sarif_file: results.sarif\n      #     category: codacy-security-scan\n"
  },
  {
    "path": ".github/workflows/test-wtih-vscode-build.yml",
    "content": "name: Build & Test with VS Code build\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\njobs:\n  build:\n    strategy:\n      matrix:\n        os: [macos-14]\n        node-version: [22.x]\n\n    runs-on: ${{ matrix.os }}\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          cache: 'npm'\n          node-version: ${{ matrix.node-version }}\n\n      - run: npm install && cd vscode-web && npm install\n      - run: cd vscode-web && npm run build\n      - run: npm run link && npm run build\n      - uses: microsoft/playwright-github-action@v1\n      - run: GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} npm run test:ci\n"
  },
  {
    "path": ".github/workflows/welcome-first-time-contributors.yml",
    "content": "name: Welcome first time contributors\n\non:\n  pull_request_target:\n    types:\n      - opened\n  issues:\n    types:\n      - opened\n\njobs:\n  welcome:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/first-interaction@v1\n      with:\n        repo-token: ${{ secrets.GITHUB_TOKEN }}\n        issue-message: |\n          Hello there ${{ github.actor }} 👋\n\n          Welcome to github1s !!💖🥳\n\n          Thank you and congratulations 🎉 for opening your very first issue in this project. github1s fosters an open and welcoming environment for all our contributors.🌸\n\n          Incase you want to claim this issue, please comment down below! We will try to get back to you as soon as we can.👀\n\n          Feel free to visit [github1s.com](https://github1s.com/). 👩‍💻 If you have any interesting ideas, just open an issue. We would love to hear you and engage in discussions.\n\n        pr-message: |\n          Hello there ${{ github.actor }} 👋\n\n          Thank you and congrats 🎉 for opening your first PR on this project.✨\n\n          We will review it soon!\n\n          github1s fosters an open and welcoming environment for all our contributors.🌸\n\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nlib\ndist\nout\nnode_modules\n"
  },
  {
    "path": ".gitpod.Dockerfile",
    "content": "FROM gitpod/workspace-full\n\nRUN sudo apt-get update \\\n  && sudo apt-get install -y \\\n    g++ gcc make python2.7 pkg-config libx11-dev libxkbfile-dev libsecret-1-dev python-is-python3 rsync \\\n  && sudo rm -rf /var/lib/apt/lists/*"
  },
  {
    "path": ".gitpod.yml",
    "content": "image:\n  file: .gitpod.Dockerfile\ntasks:\n  - init: |\n      npm install\n      npm run build\n    command: |\n      echo \"=======================\"\n      echo \"Please run 'npm run watch'\"\n      echo \"=======================\"\n  - command: |\n      echo \"===========================================================================\"\n      echo \"Please wait for 'npm run watch' to complete compilation\"\n      echo \"===========================================================================\"\nports:\n  - port: 8080\n    onOpen: open-browser\ngithub:\n  prebuilds:\n    # enable for the master/default branch (defaults to true)\n    master: true\n    # enable for all branches in this repo (defaults to false)\n    branches: true\n    # enable for pull requests coming from this repo (defaults to true)\n    pullRequests: true\n    # enable for pull requests coming from forks (defaults to false)\n    pullRequestsFromForks: true\n    # add a check to pull requests (defaults to true)\n    addCheck: true\n    # add a \"Review in Gitpod\" button as a comment to pull requests (defaults to false)\n    addComment: true\n    # add a \"Review in Gitpod\" button to the pull request's description (defaults to false)\n    addBadge: false\n    # add a label once the prebuild is ready to pull requests (defaults to false)\n    addLabel: false\n"
  },
  {
    "path": ".husky/.gitignore",
    "content": "_"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx lint-staged\n"
  },
  {
    "path": ".prettierignore",
    "content": "lib\ndist\nout\nnode_modules\nvscode-web/src/vs\nvscode-web/extensions\nhtm.module.js\npreact.module.js\npreact-hooks.module.js\nindex.html\n"
  },
  {
    "path": ".prettierrc.js",
    "content": "export default {\n\ttabWidth: 2,\n\tuseTabs: true,\n\tsemi: true,\n\tsingleQuote: true,\n\tprintWidth: 120,\n\toverrides: [\n\t\t{\n\t\t\tfiles: ['*.yml', '*.yaml', '*.json'],\n\t\t\toptions: {\n\t\t\t\tuseTabs: false,\n\t\t\t},\n\t\t},\n\t],\n};\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright conwnet and other contributors\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 all\ncopies 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 THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "![GitHub1s](https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/logo.svg)\n\n# github1s\n\nOne second to read GitHub code with VS Code.\n\n## Usage\n\nJust add `1s` after `github` and press `Enter` in the browser address bar for any repository you want to read.\n\nFor example, try it on the VS Code repo:\n\n[https://github1s.com/microsoft/vscode](https://github1s.com/microsoft/vscode)\n\n![VS Code - GitHub1s](https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/vs-code-github1s.png)\n\nYou can also use [https://gitlab1s.com](https://gitlab1s.com) or [https://npmjs1s.com](https://npmjs1s.com) in the same way.\n\nFor browser extensions, see [Third-party Related Projects](https://github.com/conwnet/github1s#third-party-related-projects).\n\nOr save the following code snippet as a bookmarklet, you can use it to quickly switch between github.com and github1s.com (GitHub markdown doesn't allow js links, so just copy it into a bookmark).\n\n```\njavascript: window.location.href = window.location.href.replace(/github(1s)?.com/, function(match, p1) { return p1 ? 'github.com' : 'github1s.com' })\n```\n\n### Develop in the cloud\n\nTo edit files, run Docker containers, create pull requests and more, click the \"Develop your project on [Gitpod](https://www.gitpod.io)\" button in the status bar. You can also open the Command Palette (default shortcut `Ctrl+Shift+P`) and choose `GitHub1s: Edit files in Gitpod`.\n\n![Gitpod Status Bar](https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/gitpod-statusbar.png)\n\n## Documentation\n\n- [How it works](https://github.com/conwnet/github1s/blob/master/docs/guide.md)\n- [Roadmap](https://github.com/conwnet/github1s/projects/1)\n\n## Enabling Private Repositories\n\nIf you want to view non-public repositories, you need to add an OAuth token. The token is stored only in your browser, and only send to GitHub when fetching your repository's files. Click on the icon near the bottom of the left-hand row of icons, and the dialog box will prompt you for it, and even take you to your GitHub settings page to generate one, if needed.\n\n<img height=\"500px\" src=\"https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/auth-token.png\" />\n\n## Screenshots\n\n![VS Code - GitHub1s](https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/GitHub1sDemo1.gif)\n\n![VS Code - GitHub1s](https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/demo.png)\n\n## Development\n\n### Cloud-based development\n\nYou can start an online development environment with [Gitpod](https://www.gitpod.io) by clicking the following button:\n\n[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/conwnet/github1s)\n\n### Local development\n\n```bash\ngit clone git@github.com:conwnet/github1s.git\ncd github1s\nnpm install\nnpm run watch\n# The cli will automatically open http://localhost:8080 once the build is completed.\n# You can visit http://localhost:8080/conwnet/github1s if it doesn't.\n```\n\n#### Local development with full VS Code build\n\nYou need [these prerequisites (the same ones as for VS Code)](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites) for development with full VS Code build.\nPlease make sure you could build VS Code locally before the watch mode.\n\nTo verify the build:\n\n```bash\ncd github1s\nnpm run build:vscode\n```\n\nAfter the initial successful build, you could use the watch mode:\n\n```bash\ncd github1s\nnpm install\nnpm run watch-with-vscode\n# The cli will automatically open http://localhost:8080 once the build is completed.\n# You can visit http://localhost:8080/conwnet/github1s if it doesn't.\n```\n\n### ... or ... VS Code + Docker Development\n\nYou can use the VS Code plugin [Remote-Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) `Dev Container` to use a Docker container as a development environment.\n\n1. Install the Remote-Containers plugin in VS Code & Docker\n2. Open the Command Palette (default shortcut `Ctrl+Shift+P`) and choose `Remote-Containers: Clone Repository in Container Volume...`\n3. Enter the repo, in this case `https://github.com/conwnet/github1s.git` or your forked repo\n4. Pick either, `Create a unique volume` or `Create a new volume`\n\n   - Now VS Code will create the docker container and connect to the new container so you can use this as a fully setup environment!\n\n5. Open a new VS Code Terminal, then you can run the `npm install` commands listed above.\n\n```bash\nnpm install\nnpm run watch\n# The cli will automatically open http://localhost:8080 once the build is completed.\n# You can visit http://localhost:8080/conwnet/github1s if it doesn't.\n```\n\n### Format all codes\n\n```bash\nnpm run format\n```\n\nIt uses `prettier` to format all possible codes.\n\n## Build\n\n```bash\nnpm install\nnpm run build\n```\n\n## Feedback\n\n- If something is not working, [create an issue](https://github.com/conwnet/github1s/issues/new)\n\n## Sponsors\n\nThe continued development and maintenance of GitHub1s is made possible by these generous sponsors:\n\n<table><tbody><tr>\n<td><a href=\"https://sourcegraph.com/\">\n<img height=\"40px\" src=\"https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/sourcegraph-logo.svg\">\n</a></td>\n</tr></tbody></table>\n\n## Partners\n\nWe are partnered with [OSS Insight](https://ossinsight.io/?utm_source=github1s&utm_medium=github&utm_campaign=ghtrending) to get the Trending Repositories & some more Interesting Analytics. [OSS Insight](https://ossinsight.io/?utm_source=github1s&utm_medium=github&utm_campaign=ghtrending) provides deep insights into GitHub repos, developers, and curated repo lists from billions of GitHub events. It’s built with [TiDB Cloud](https://www.pingcap.com/tidb-cloud/?utm_source=github1s&utm_medium=github&utm_campaign=ghtrending).\n\n<table><tbody><tr>\n<td><a href=\"https://ossinsight.io/?utm_source=github1s&utm_medium=github&utm_campaign=ghtrending\">\n<img height=\"40px\" src=\"./resources/images/ossinsight-brand-dark.png\">\n</a></td>\n</tr></tbody></table>\n\n## Maintainers! :blush:\n\n<table>\n  <tbody><tr>\n    <td align=\"center\"><a href=\"https://github.com/conwnet\"><img alt=\"\" src=\"https://avatars.githubusercontent.com/conwnet\" width=\"100px;\"><br><sub><b>netcon</b></sub></a><br><a href=\"https://github.com/conwnet/github1s/commits?author=conwnet\" title=\"Code\">💻 🖋</a></td> </a></td>\n    <td align=\"center\"><a href=\"https://github.com/xcv58\"><img alt=\"\" src=\"https://avatars.githubusercontent.com/xcv58\" width=\"100px;\"><br><sub><b>xcv58</b></sub></a><br><a href=\"https://github.com/conwnet/github1s/commits?author=xcv58\" title=\"Code\">💻 🖋</a></td></a></td>\n    <td align=\"center\"><a href=\"https://github.com/Siddhant-K-code\"><img alt=\"\" src=\"https://avatars.githubusercontent.com/Siddhant-K-code\" width=\"100px;\"><br><sub><b>Siddhant Khare</b></sub></a><br><a href=\"https://github.com/conwnet/github1s/commits?author=Siddhant-K-code\" title=\"Code\">💻 🖋</a></td> </a></td>\n  </tr>\n</tbody></table>\n\n## Stargazers over time\n\n[![Stargazers over time](https://api.star-history.com/svg?repos=conwnet/github1s&type=Date)](https://star-history.com/#conwnet/github1s&Date)\n\n<details>\n<summary>Third-party Related Projects</summary>\n<br>\n\n### Chrome Extensions\n\n- [Repositree](https://chrome.google.com/webstore/detail/repositree/lafjldoccjnjlcmdhmniholdpjkbgajo) ([chouglesaud/repositree](https://github.com/chouglesaud/repositree))\n- [github-code-viewer](https://chrome.google.com/webstore/detail/github-code-viewer/ecddapgifccgblebfibdgkagfbdagjfn) ([febaoshan/edge-extensions-github-code-viewer](https://github.com/febaoshan/edge-extensions-github-code-viewer))\n- Github1s Extension ([Darkempire78/GitHub1s-Extension](https://github.com/Darkempire78/GitHub1s-Extension))\n- [Github Web IDE](https://chrome.google.com/webstore/detail/adjiklnjodbiaioggfpbpkhbfcnhgkfe) ([zvizvi/Github-Web-IDE](https://github.com/zvizvi/Github-Web-IDE))\n- [shortcut to github1s](https://chrome.google.com/webstore/detail/shortcut-to-github1s/gfcdbodapcbfckbfpmgeldfkkgjknceo) ([katsuhisa91/github1s-shortcut](https://github.com/katsuhisa91/github1s-shortcut))\n- [Github1s Shortut - Open source](https://github.com/Fauzdar1/Github1s)\n- [⚡️ 1s to GitHub1s!](https://github.com/holazz/webext-github1s)\n- [github1s Google Chrome Extensions](https://github.com/Lonely-Mr-zhang/github_1s_vscode)\n\n### Firefox Extensions\n\n- [Repositree](https://addons.mozilla.org/en-US/firefox/addon/repositree/) ([chouglesaud/repositree](https://github.com/chouglesaud/repositree))\n- [Github1s Extension](https://addons.mozilla.org/firefox/addon/github1s-extension) ([Darkempire78/GitHub1s-Extension](https://github.com/Darkempire78/GitHub1s-Extension))\n- [Github1s](https://addons.mozilla.org/firefox/addon/github1s/) ([mcherifi/github1s-firefox-addon](https://github.com/mcherifi/github1s-firefox-addon))\n- [Github Web IDE](https://addons.mozilla.org/firefox/addon/github-web-ide/) ([zvizvi/Github-Web-IDE](https://github.com/zvizvi/Github-Web-IDE))\n\n### Microsoft Edge Extensions\n\n- [github-code-viewer](https://microsoftedge.microsoft.com/addons/detail/githubcodeviewer/jaaaapanahkknbgdbglnlchbjfhhjlpi) ([febaoshan/edge-extensions-github-code-viewer](https://github.com/febaoshan/edge-extensions-github-code-viewer))\n- [Github Web IDE](https://microsoftedge.microsoft.com/addons/detail/akjbkjciknacicbnkfjbnlaeednpadcf) ([zvizvi/Github-Web-IDE](https://github.com/zvizvi/Github-Web-IDE))\n\n### Safari Extension\n\n- [GitHub1s-For-Safari-Extension](https://apps.apple.com/us/app/readcodeonline/id1569026520?mt=12) ([code4you2021/GitHub1s-For-Safari-Extension](https://github.com/code4you2021/GitHub1s-For-Safari-Extension))\n\n### Tampermonkey scripts\n\n- [Mr-B0b/TamperMonkeyScripts/vscode.js](https://github.com/Mr-B0b/TamperMonkeyScripts/blob/main/vscode.js)\n</details>\n"
  },
  {
    "path": "docs/guide.md",
    "content": "# How it works\n\nGitHub1s is based on [VS Code 1.66.2](https://github.com/microsoft/vscode/tree/1.66.2) now. VS Code can be built for a browser version officially. I also used the code and got inspired by [Code Server](https://github.com/cdr/code-server).\n\nThanks to the very powerful and flexible extensibility of VS Code, we can easily implement a VS Code extension that provides the custom File IO ability using [FileSystemProvider API](https://code.visualstudio.com/api/references/vscode-api#FileSystemProvider). There is an official demo named [vscode-web-playground](https://github.com/microsoft/vscode-web-playground) which shows how it is used.\n\nOn the other hand, GitHub provides the powerful [REST API](https://docs.github.com/en/rest) that can be used for a variety of tasks which includes reading directories and files for sure.\n\nAccording to the above, obviously, the core concept of GitHub1s is to implement a VS Code Extension (includes FileSystemProvider) using GitHub REST API.\n\n_We may switch to the GitHub GraphQL API for more friendly user experience in the future, thanks to @xcv58 and @kanhegaonkarsaurabh. See details at [Issue 12](https://github.com/conwnet/github1s/issues/12)._\n\n~~GitHub1s is a purely static web app (because it really doesn't need a backend service, does it?). So we just deploy it on [GitHub Pages](https://pages.github.com/) now (the `gh-pages` branch of this repository), and it is free. The service of GitHub1s could be reliable (GitHub is very reliable) because nobody needs to pay the web hosting bills.~~\n\nWe deploy GitHub1s on [Cloudflare Pages](https://cloudflare.com/) now for minimize delays in loading and better developer experience. Thanks for the wonderful service provide by Cloudflare.\n\n# Rate Limit\n\nAnother thing that needs attention is [Rate Limit](https://docs.github.com/en/rest/reference/rate-limit):\n\n> For unauthenticated requests, the rate limit allows for up to 60 requests per hour. Unauthenticated requests are associated with the originating IP address, and not the user making requests.\n\n> For API requests using Basic Authentication or OAuth, you can make up to 5,000 requests per hour.\n\nSo, if you meet some problems when you use GitHub1s, even if you are using newer browsers, you could try to set a [GitHub OAuth Token](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#oauth2-token-sent-in-a-header). Don't worry, we cannot see your token. It is only stored in your browser [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) with [VS Code Extension globalState API](https://code.visualstudio.com/api/references/vscode-api#ExtensionContext) (Actually we don't have a server, do we?).\n\nBut this does not mean the token is absolutely safe, **don't forget to clean it while you are using a device that doesn't belong to you**.\n\n# Sourcegraph API\n\nDue to the potential RateLimit of the GitHub API, we will prioritize the use of the [Sourcegraph API](https://sourcegraph.com/docs) for public repositories, with the exception of the Read interface, the code search capability is also provided by the Sourcegraph API.\n\nBy default, GitHub1s will only try to use the GitHub API when the Sourcegraph API request fails, and you can adjust this option in the settings.\n\n# Development\n\nAs you see, running GitHub1s locally is not difficult. After cloning the repository, just run these commands:\n\n```shell\n$ npm install\n$ npm run watch\n```\n\nThen, there will be a new directory named `dist` generated in the project root. The `npm run watch:dev-server` (part of `npm run watch` command) will automatically open http://localhost:8080 in the browser.\n\nIf you get a 404 error for some static files, please wait a minute for the building to complete.\n\n## Watch Mode\n\nWhat happens after you run `npm run watch-with-vscode`?\n\n1. Copy some necessary resources (`index.html`, `favicons.ico`, etc.) to the `dist` directory.\n\n2. This command will compile the codes in `src` and generate application entry script (see `webpack.config.js`). This command also compile the custom extensions (for example `github1s`) in `extensions` directory.\n\n3. Redirect vscode-web static requests (vscode, extensisions, dependencies) to `vscode-web/lib/vscode` which should be generated by vscode compile process.\n\nYou should also compile the vscode manually in another terminal.\n\n1. Go to `vscode-web` and run `npm install && npm run watch` (the native watch of vscode), it will trigger a new build if something in it has been changed.\n\n2. This command will alose watch the `vscode-web/src` and `vscode-web/extensions` directory, merge it in to `vscode-web/lib/vscode` if something in it has been changed. (When a new file is merged into `lib/vscode`, it will trigger the watcher that is described in Step 3)\n\nNote that since we have modified the source code of VS Code, it may get into trouble when merging a newer version VS Code.\n\nIt is a little laborious to complete the watch process, but I didn't think of a better solution.\n\nWhat happens after you run `npm run watch`?\n\nIt's the same procedure as `` without the step 3. Instead of the local VS Code, it uses the prebuilt [@github1s/vscode-web](https://www.npmjs.com/package/@github1s/vscode-web) version.\n\n## Build mode\n\nPut simply, we build the necessary code and do a minify. The minify script is modified from [Code Server](https://github.com/cdr/code-server).\n\n## Directory Structure\n\n- `extensions` - custom VS Code extensions that don't come with VS Code natively.\n\n- `src` - the code in here will be patched into VS Code source.\n\n- `vscode-web` - This contains the code to patch VS Code.\n\n- `scripts` - some scripts for build, watch, package, etc.\n\n- `resources` - some resource files such as templates, pictures, configuration files, etc.\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import jsdoc from 'eslint-plugin-jsdoc';\nimport tseslint from 'typescript-eslint';\nimport eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';\n\nexport default [\n\t{ ignores: ['**/dist', '**/assets', 'vscode-web/lib', '**/vs', '**/vscode.proposed.d.ts'] },\n\t...tseslint.configs.recommended,\n\tjsdoc.configs['flat/recommended-typescript'],\n\teslintPluginPrettierRecommended,\n\t{\n\t\trules: {\n\t\t\t'@typescript-eslint/no-explicit-any': 'off',\n\t\t\t'@typescript-eslint/no-unused-expressions': 'off',\n\t\t\t'@typescript-eslint/no-unused-vars': 'off',\n\t\t},\n\t},\n];\n"
  },
  {
    "path": "extensions/elm-web/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Kolja Lampe\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 all\ncopies 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 THE\nSOFTWARE.\n"
  },
  {
    "path": "extensions/elm-web/README.md",
    "content": "# This extension is a fork from [elm-language-client-vscode](https://github.com/elm-tooling/elm-language-client-vscode) for github1s.\n\n# At present only languages features is reserved\n\n# I have deleted some files and only reserved the necessary code\n\n# Elm Plugin for Visual Studio Code (VSCode)\n\n[![Version](https://vsmarketplacebadge.apphb.com/version/Elmtooling.elm-ls-vscode.svg)](https://marketplace.visualstudio.com/items?itemName=Elmtooling.elm-ls-vscode)\n[![Downloads](https://vsmarketplacebadge.apphb.com/downloads-short/Elmtooling.elm-ls-vscode.svg)](https://marketplace.visualstudio.com/items?itemName=Elmtooling.elm-ls-vscode)\n[![Rating](https://vsmarketplacebadge.apphb.com/rating-star/Elmtooling.elm-ls-vscode.svg)](https://marketplace.visualstudio.com/items?itemName=Elmtooling.elm-ls-vscode)\n![Compile](https://github.com/elm-tooling/elm-language-client-vscode/workflows/Compile/badge.svg)\n\nSupports elm 0.19 and up\n\n## Highlighted Features\n\n- Syntax Highlighting\n"
  },
  {
    "path": "extensions/elm-web/language-configuration.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"--\",\n    \"blockComment\": [\"{-\", \"-}\"]\n  },\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"]\n  ],\n  \"surroundingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"\\\"\", \"\\\"\"],\n    [\"'\", \"'\"]\n  ],\n  \"autoClosingPairs\": [\n    [\"(\", \")\"],\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    {\n      \"open\": \"\\\"\\\"\\\"\",\n      \"close\": \"\\\"\\\"\\\"\",\n      \"notIn\": [\"comment\"]\n    },\n    {\n      \"open\": \"\\\"\",\n      \"close\": \"\\\"\",\n      \"notIn\": [\"string\"]\n    },\n    {\n      \"open\": \"'\",\n      \"close\": \"'\",\n      \"notIn\": [\"string\", \"comment\"]\n    }\n  ],\n  \"folding\": {\n    \"offSide\": true\n  }\n}"
  },
  {
    "path": "extensions/elm-web/package.json",
    "content": "{\n  \"name\": \"elm-ls-vscode\",\n  \"displayName\": \"Elm\",\n  \"description\": \"Improving your Elm experience since 2019\",\n  \"publisher\": \"elmTooling\",\n  \"icon\": \"images/elm.png\",\n  \"author\": \"Kolja Lampe\",\n  \"license\": \"MIT\",\n  \"version\": \"2.0.3\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/elm-tooling/elm-language-client-vscode\"\n  },\n  \"categories\": [\n    \"Linters\",\n    \"Snippets\",\n    \"Programming Languages\"\n  ],\n  \"keywords\": [\n    \"elm\"\n  ],\n  \"engines\": {\n    \"vscode\": \"^1.52.0\"\n  },\n  \"activationEvents\": [\n    \"onLanguage:elm\"\n  ],\n  \"contributes\": {\n    \"languages\": [\n      {\n        \"id\": \"elm\",\n        \"aliases\": [\n          \"Elm\",\n          \"elm\"\n        ],\n        \"extensions\": [\n          \".elm\"\n        ],\n        \"configuration\": \"./language-configuration.json\"\n      }\n    ],\n    \"grammars\": [\n      {\n        \"scopeName\": \"markdown.elm.codeblock\",\n        \"path\": \"./syntaxes/codeblock.json\",\n        \"injectTo\": [\n          \"text.html.markdown\"\n        ],\n        \"embeddedLanguages\": {\n          \"meta.embedded.block.elm\": \"elm\",\n          \"meta.embedded.block.glsl\": \"glsl\"\n        }\n      },\n      {\n        \"language\": \"elm\",\n        \"scopeName\": \"source.elm\",\n        \"path\": \"./syntaxes/elm-syntax.json\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"compile\": \"echo done\",\n    \"watch\": \"echo done\"\n  }\n}\n"
  },
  {
    "path": "extensions/elm-web/syntaxes/codeblock.json",
    "content": "{\n  \"fileTypes\": [],\n  \"injectionSelector\": \"L:text.html.markdown\",\n  \"patterns\": [\n    {\n      \"include\": \"#fenced_code_block_elm\"\n    }\n  ],\n  \"repository\": {\n    \"fenced_code_block_elm\": {\n      \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(elm)(\\\\s+[^`~]*)?$)\",\n      \"name\": \"markup.fenced_code.block.markdown\",\n      \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n      \"beginCaptures\": {\n        \"3\": {\n          \"name\": \"punctuation.definition.markdown\"\n        },\n        \"5\": {\n          \"name\": \"fenced_code.block.language\"\n        },\n        \"6\": {\n          \"name\": \"fenced_code.block.language.attributes\"\n        }\n      },\n      \"endCaptures\": {\n        \"3\": {\n          \"name\": \"punctuation.definition.markdown\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n          \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n          \"contentName\": \"meta.embedded.block.elm\",\n          \"patterns\": [\n            {\n              \"include\": \"source.elm\"\n            }\n          ]\n        }\n      ]\n    }\n  },\n  \"scopeName\": \"markdown.elm.codeblock\"\n}\n"
  },
  {
    "path": "extensions/elm-web/syntaxes/elm-syntax.json",
    "content": "{\n  \"fileTypes\": [\"elm\"],\n  \"name\": \"Elm\",\n  \"scopeName\": \"source.elm\",\n  \"patterns\": [\n    {\n      \"include\": \"#import\"\n    },\n    {\n      \"include\": \"#module\"\n    },\n    {\n      \"include\": \"#debug\"\n    },\n    {\n      \"include\": \"#comments\"\n    },\n    {\n      \"match\": \"\\\\b(_)\\\\b\",\n      \"name\": \"keyword.unused.elm\"\n    },\n    {\n      \"include\": \"#type-signature\"\n    },\n    {\n      \"include\": \"#type-declaration\"\n    },\n    {\n      \"include\": \"#type-alias-declaration\"\n    },\n    {\n      \"include\": \"#string-triple\"\n    },\n    {\n      \"include\": \"#string-quote\"\n    },\n    {\n      \"include\": \"#char\"\n    },\n    {\n      \"comment\": \"Floats are always decimal\",\n      \"match\": \"\\\\b([0-9]+\\\\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)\\\\b\",\n      \"name\": \"constant.numeric.float.elm\"\n    },\n    {\n      \"match\": \"\\\\b([0-9]+)\\\\b\",\n      \"name\": \"constant.numeric.elm\"\n    },\n    {\n      \"match\": \"\\\\b(0x[0-9a-fA-F]+)\\\\b\",\n      \"name\": \"constant.numeric.elm\"\n    },\n    {\n      \"include\": \"#glsl\"\n    },\n    {\n      \"include\": \"#record-prefix\"\n    },\n    {\n      \"include\": \"#module-prefix\"\n    },\n    {\n      \"include\": \"#constructor\"\n    },\n    {\n      \"name\": \"meta.record.field.update.elm\",\n      \"match\": \"(\\\\{)\\\\s+([a-z][a-zA-Z0-9_]*)\\\\s+(\\\\|)\\\\s+([a-z][a-zA-Z0-9_]*)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"punctuation.bracket.elm\"\n        },\n        \"2\": {\n          \"name\": \"record.name.elm\"\n        },\n        \"3\": {\n          \"name\": \"keyword.pipe.elm\"\n        },\n        \"4\": {\n          \"name\": \"entity.name.record.field.elm\"\n        }\n      }\n    },\n    {\n      \"name\": \"meta.record.field.update.elm\",\n      \"match\": \"(\\\\|)\\\\s+([a-z][a-zA-Z0-9_]*)\\\\s+(\\\\=)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"keyword.pipe.elm\"\n        },\n        \"2\": {\n          \"name\": \"entity.name.record.field.elm\"\n        },\n        \"3\": {\n          \"name\": \"keyword.operator.assignment.elm\"\n        }\n      }\n    },\n    {\n      \"name\": \"meta.record.field.update.elm\",\n      \"match\": \"(\\\\{)\\\\s+([a-z][a-zA-Z0-9_]*)\\\\s+$\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"punctuation.bracket.elm\"\n        },\n        \"2\": {\n          \"name\": \"record.name.elm\"\n        }\n      }\n    },\n    {\n      \"name\": \"meta.record.field.elm\",\n      \"match\": \"(\\\\{)\\\\s+([a-z][a-zA-Z0-9_]*)\\\\s+(\\\\=)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"punctuation.bracket.elm\"\n        },\n        \"2\": {\n          \"name\": \"entity.name.record.field.elm\"\n        },\n        \"3\": {\n          \"name\": \"keyword.operator.assignment.elm\"\n        }\n      }\n    },\n    {\n      \"name\": \"meta.record.field.elm\",\n      \"match\": \"(,)\\\\s+([a-z][a-zA-Z0-9_]*)\\\\s+(\\\\=)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"punctuation.separator.comma.elm\"\n        },\n        \"2\": {\n          \"name\": \"entity.name.record.field.elm\"\n        },\n        \"3\": {\n          \"name\": \"keyword.operator.assignment.elm\"\n        }\n      }\n    },\n    {\n      \"match\": \"(\\\\}|\\\\{)\",\n      \"name\": \"punctuation.bracket.elm\"\n    },\n    {\n      \"include\": \"#unit\"\n    },\n    {\n      \"include\": \"#comma\"\n    },\n    {\n      \"include\": \"#parens\"\n    },\n    {\n      \"match\": \"(->)\",\n      \"name\": \"keyword.operator.arrow.elm\"\n    },\n    {\n      \"include\": \"#infix_op\"\n    },\n    {\n      \"match\": \"(\\\\=|\\\\:|\\\\||\\\\\\\\)\",\n      \"name\": \"keyword.other.elm\"\n    },\n    {\n      \"match\": \"\\\\b(type|as|port|exposing|alias|infixl|infixr|infix)\\\\s+\",\n      \"name\": \"keyword.other.elm\"\n    },\n    {\n      \"match\": \"\\\\b(if|then|else|case|of|let|in)\\\\s+\",\n      \"name\": \"keyword.control.elm\"\n    },\n    {\n      \"include\": \"#record-accessor\"\n    },\n    {\n      \"include\": \"#top_level_value\"\n    },\n    {\n      \"include\": \"#value\"\n    },\n    {\n      \"include\": \"#period\"\n    },\n    {\n      \"include\": \"#square_brackets\"\n    }\n  ],\n  \"repository\": {\n    \"comma\": {\n      \"match\": \"(,)\",\n      \"name\": \"punctuation.separator.comma.elm\"\n    },\n    \"parens\": {\n      \"match\": \"(\\\\(|\\\\))\",\n      \"name\": \"punctuation.parens.elm\"\n    },\n    \"block_comment\": {\n      \"applyEndPatternLast\": 1,\n      \"begin\": \"\\\\{-(?!#)\",\n      \"captures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.comment.elm\"\n        }\n      },\n      \"end\": \"-\\\\}\",\n      \"name\": \"comment.block.elm\",\n      \"patterns\": [\n        {\n          \"include\": \"#block_comment\"\n        }\n      ]\n    },\n    \"comments\": {\n      \"patterns\": [\n        {\n          \"captures\": {\n            \"1\": {\n              \"name\": \"punctuation.definition.comment.elm\"\n            }\n          },\n          \"begin\": \"--\",\n          \"end\": \"$\",\n          \"name\": \"comment.line.double-dash.elm\"\n        },\n        {\n          \"include\": \"#block_comment\"\n        }\n      ]\n    },\n    \"import\": {\n      \"name\": \"meta.import.elm\",\n      \"begin\": \"^\\\\b(import)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.control.import.elm\"\n        }\n      },\n      \"end\": \"\\\\n(?!\\\\s)\",\n      \"patterns\": [\n        {\n          \"match\": \"(as|exposing)\",\n          \"name\": \"keyword.control.elm\"\n        },\n        {\n          \"include\": \"#module_chunk\"\n        },\n        {\n          \"include\": \"#period\"\n        },\n        {\n          \"match\": \"\\\\s+\",\n          \"name\": \"punctuation.spaces.elm\"\n        },\n        {\n          \"include\": \"#module-exports\"\n        }\n      ]\n    },\n    \"module\": {\n      \"begin\": \"^\\\\b((port |effect )?module)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.elm\"\n        }\n      },\n      \"end\": \"\\\\n(?!\\\\s)\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.elm\"\n        }\n      },\n      \"name\": \"meta.declaration.module.elm\",\n      \"patterns\": [\n        {\n          \"include\": \"#module_chunk\"\n        },\n        {\n          \"include\": \"#period\"\n        },\n        {\n          \"match\": \"(exposing)\",\n          \"name\": \"keyword.other.elm\"\n        },\n        {\n          \"match\": \"\\\\s+\",\n          \"name\": \"punctuation.spaces.elm\"\n        },\n        {\n          \"include\": \"#module-exports\"\n        }\n      ]\n    },\n    \"string-triple\": {\n      \"name\": \"string.quoted.triple.elm\",\n      \"begin\": \"\\\"\\\"\\\"\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.begin.elm\"\n        }\n      },\n      \"end\": \"\\\"\\\"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.elm\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"match\": \"\\\\\\\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\\\\\\\\\\\\\"'\\\\&]|x[0-9a-fA-F]{1,5})\",\n          \"name\": \"constant.character.escape.elm\"\n        },\n        {\n          \"match\": \"\\\\^[A-Z@\\\\[\\\\]\\\\\\\\\\\\^_]\",\n          \"name\": \"constant.character.escape.control.elm\"\n        }\n      ]\n    },\n    \"string-quote\": {\n      \"name\": \"string.quoted.double.elm\",\n      \"begin\": \"\\\"\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.begin.elm\"\n        }\n      },\n      \"end\": \"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.elm\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"match\": \"\\\\\\\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\\\\\\\\\\\\\"'\\\\&]|x[0-9a-fA-F]{1,5})\",\n          \"name\": \"constant.character.escape.elm\"\n        },\n        {\n          \"match\": \"\\\\^[A-Z@\\\\[\\\\]\\\\\\\\\\\\^_]\",\n          \"name\": \"constant.character.escape.control.elm\"\n        }\n      ]\n    },\n    \"char\": {\n      \"name\": \"string.quoted.single.elm\",\n      \"begin\": \"'\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.char.begin.elm\"\n        }\n      },\n      \"end\": \"'\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.char.end.elm\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"match\": \"\\\\\\\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\\\\\\\\\\\\\"'\\\\&]|x[0-9a-fA-F]{1,5})\",\n          \"name\": \"constant.character.escape.elm\"\n        },\n        {\n          \"match\": \"\\\\^[A-Z@\\\\[\\\\]\\\\\\\\\\\\^_]\",\n          \"name\": \"constant.character.escape.control.elm\"\n        }\n      ]\n    },\n    \"debug\": {\n      \"match\": \"\\\\b(Debug)\\\\b\",\n      \"name\": \"invalid.illegal.debug.elm\"\n    },\n    \"module-exports\": {\n      \"begin\": \"(\\\\()\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"punctuation.parens.module-export.elm\"\n        }\n      },\n      \"end\": \"(\\\\))\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"punctuation.parens.module-export.elm\"\n        }\n      },\n      \"name\": \"meta.declaration.exports.elm\",\n      \"patterns\": [\n        {\n          \"match\": \"\\\\b[a-z][a-zA-Z_'0-9]*\",\n          \"name\": \"entity.name.function.elm\"\n        },\n        {\n          \"match\": \"\\\\b[A-Z][A-Za-z_'0-9]*\",\n          \"name\": \"storage.type.elm\"\n        },\n        {\n          \"match\": \",\",\n          \"name\": \"punctuation.separator.comma.elm\"\n        },\n        {\n          \"match\": \"\\\\s+\",\n          \"name\": \"punctuation.spaces.elm\"\n        },\n        {\n          \"include\": \"#comma\"\n        },\n        {\n          \"match\": \"\\\\(\\\\.\\\\.\\\\)\",\n          \"name\": \"punctuation.parens.ellipses.elm\"\n        },\n        {\n          \"match\": \"\\\\.\\\\.\",\n          \"name\": \"punctuation.parens.ellipses.elm\"\n        },\n        {\n          \"include\": \"#infix_op\"\n        },\n        {\n          \"comment\": \"So named because I don't know what to call this.\",\n          \"match\": \"\\\\(.*?\\\\)\",\n          \"name\": \"meta.other.unknown.elm\"\n        }\n      ]\n    },\n    \"module_chunk\": {\n      \"match\": \"[A-Z][a-zA-Z0-9_]*\",\n      \"name\": \"support.module.elm\"\n    },\n    \"period\": {\n      \"match\": \"[.]\",\n      \"name\": \"keyword.other.period.elm\"\n    },\n    \"square_brackets\": {\n      \"match\": \"[\\\\[\\\\]]\",\n      \"name\": \"punctuation.definition.list.elm\"\n    },\n    \"record-prefix\": {\n      \"match\": \"([a-z][a-zA-Z0-9_]*)(\\\\.)([a-z][a-zA-Z0-9_]*)\",\n      \"name\": \"record.accessor.elm\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"record.name.elm\"\n        },\n        \"2\": {\n          \"name\": \"keyword.other.period.elm\"\n        },\n        \"3\": {\n          \"name\": \"entity.name.record.field.accessor.elm\"\n        }\n      }\n    },\n    \"module-prefix\": {\n      \"match\": \"([A-Z][a-zA-Z0-9_]*)(\\\\.)\",\n      \"name\": \"meta.module.name.elm\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"support.module.elm\"\n        },\n        \"2\": {\n          \"name\": \"keyword.other.period.elm\"\n        }\n      }\n    },\n    \"constructor\": {\n      \"match\": \"\\\\b[A-Z][a-zA-Z0-9_]*\\\\b\",\n      \"name\": \"constant.type-constructor.elm\"\n    },\n    \"value\": {\n      \"match\": \"\\\\b[a-z][a-zA-Z0-9_]*\\\\b\",\n      \"name\": \"meta.value.elm\"\n    },\n    \"unit\": {\n      \"match\": \"\\\\(\\\\)\",\n      \"name\": \"constant.unit.elm\"\n    },\n    \"top_level_value\": {\n      \"match\": \"^[a-z][a-zA-Z0-9_]*\\\\b\",\n      \"name\": \"entity.name.function.top_level.elm\"\n    },\n    \"record-accessor\": {\n      \"match\": \"(\\\\.)([a-z][a-zA-Z0-9_]*)\",\n      \"name\": \"meta.record.accessor\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"keyword.other.period.elm\"\n        },\n        \"2\": {\n          \"name\": \"entity.name.record.field.accessor.elm\"\n        }\n      }\n    },\n    \"infix_op\": {\n      \"match\": \"(</>|<\\\\?>|<\\\\||<=|\\\\|\\\\||&&|>=|\\\\|>|\\\\|=|\\\\|\\\\.|\\\\+\\\\+|::|/=|==|//|>>|<<|<|>|\\\\^|\\\\+|-|/|\\\\*)\",\n      \"name\": \"keyword.operator.elm\"\n    },\n    \"type-declaration\": {\n      \"begin\": \"^(type\\\\s+)([A-Z][a-zA-Z0-9_']*)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.type.elm\"\n        },\n        \"2\": {\n          \"name\": \"storage.type.elm\"\n        }\n      },\n      \"end\": \"^(?=\\\\S)\",\n      \"name\": \"meta.function.type-declaration.elm\",\n      \"patterns\": [\n        {\n          \"name\": \"meta.record.field.elm\",\n          \"match\": \"^\\\\s*([A-Z][a-zA-Z0-9_]*)\\\\b\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"constant.type-constructor.elm\"\n            }\n          }\n        },\n        {\n          \"match\": \"\\\\s+\",\n          \"name\": \"punctuation.spaces.elm\"\n        },\n        {\n          \"name\": \"meta.record.field.elm\",\n          \"match\": \"(\\\\=|\\\\|)\\\\s+([A-Z][a-zA-Z0-9_]*)\\\\b\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.operator.assignment.elm\"\n            },\n            \"2\": {\n              \"name\": \"constant.type-constructor.elm\"\n            }\n          }\n        },\n        {\n          \"match\": \"\\\\=\",\n          \"name\": \"keyword.operator.assignment.elm\"\n        },\n        {\n          \"match\": \"\\\\-\\\\>\",\n          \"name\": \"keyword.operator.arrow.elm\"\n        },\n        {\n          \"include\": \"#module-prefix\"\n        },\n        {\n          \"match\": \"\\\\b[a-z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"variable.type.elm\"\n        },\n        {\n          \"match\": \"\\\\b[A-Z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"storage.type.elm\"\n        },\n        {\n          \"include\": \"#comments\"\n        },\n        {\n          \"include\": \"#type-record\"\n        }\n      ]\n    },\n    \"type-alias-declaration\": {\n      \"begin\": \"^(type\\\\s+)(alias\\\\s+)([A-Z][a-zA-Z0-9_']*)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.type.elm\"\n        },\n        \"2\": {\n          \"name\": \"keyword.type-alias.elm\"\n        },\n        \"3\": {\n          \"name\": \"storage.type.elm\"\n        }\n      },\n      \"end\": \"^(?=\\\\S)\",\n      \"name\": \"meta.function.type-declaration.elm\",\n      \"patterns\": [\n        {\n          \"match\": \"\\\\n\\\\s+\",\n          \"name\": \"punctuation.spaces.elm\"\n        },\n        {\n          \"match\": \"\\\\=\",\n          \"name\": \"keyword.operator.assignment.elm\"\n        },\n        {\n          \"include\": \"#module-prefix\"\n        },\n        {\n          \"match\": \"\\\\b[A-Z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"storage.type.elm\"\n        },\n        {\n          \"match\": \"\\\\b[a-z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"variable.type.elm\"\n        },\n        {\n          \"include\": \"#comments\"\n        },\n        {\n          \"include\": \"#type-record\"\n        }\n      ]\n    },\n    \"type-record\": {\n      \"begin\": \"(\\\\{)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"punctuation.section.braces.begin\"\n        }\n      },\n      \"end\": \"(\\\\})\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"punctuation.section.braces.end\"\n        }\n      },\n      \"name\": \"meta.function.type-record.elm\",\n      \"patterns\": [\n        {\n          \"match\": \"\\\\s+\",\n          \"name\": \"punctuation.spaces.elm\"\n        },\n        {\n          \"match\": \"->\",\n          \"name\": \"keyword.operator.arrow.elm\"\n        },\n        {\n          \"name\": \"meta.record.field.elm\",\n          \"match\": \"([a-z][a-zA-Z0-9_]*)\\\\s+(\\\\:)\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"entity.name.record.field.elm\"\n            },\n            \"2\": {\n              \"name\": \"keyword.other.elm\"\n            }\n          }\n        },\n        {\n          \"match\": \"\\\\,\",\n          \"name\": \"punctuation.separator.comma.elm\"\n        },\n        {\n          \"include\": \"#module-prefix\"\n        },\n        {\n          \"match\": \"\\\\b[a-z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"variable.type.elm\"\n        },\n        {\n          \"match\": \"\\\\b[A-Z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"storage.type.elm\"\n        },\n        {\n          \"include\": \"#comments\"\n        },\n        {\n          \"include\": \"#type-record\"\n        }\n      ]\n    },\n    \"type-signature\": {\n      \"begin\": \"^(port\\\\s+)?([a-z_][a-zA-Z0-9_']*)\\\\s+(\\\\:)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.port.elm\"\n        },\n        \"2\": {\n          \"name\": \"entity.name.function.elm\"\n        },\n        \"3\": {\n          \"name\": \"keyword.other.colon.elm\"\n        }\n      },\n      \"end\": \"((^(?=[a-z]))|^$)\",\n      \"name\": \"meta.function.type-declaration.elm\",\n      \"patterns\": [\n        {\n          \"include\": \"#type-signature-chunk\"\n        }\n      ]\n    },\n    \"type-signature-chunk\": {\n      \"patterns\": [\n        {\n          \"match\": \"->\",\n          \"name\": \"keyword.operator.arrow.elm\"\n        },\n        {\n          \"match\": \"\\\\s+\",\n          \"name\": \"punctuation.spaces.elm\"\n        },\n        {\n          \"include\": \"#module-prefix\"\n        },\n        {\n          \"match\": \"\\\\b[a-z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"variable.type.elm\"\n        },\n        {\n          \"match\": \"\\\\b[A-Z][a-zA-Z0-9_]*\\\\b\",\n          \"name\": \"storage.type.elm\"\n        },\n        {\n          \"match\": \"\\\\(\\\\)\",\n          \"name\": \"constant.unit.elm\"\n        },\n        {\n          \"include\": \"#comma\"\n        },\n        {\n          \"include\": \"#parens\"\n        },\n        {\n          \"include\": \"#comments\"\n        },\n        {\n          \"include\": \"#type-record\"\n        }\n      ]\n    },\n    \"glsl\": {\n      \"begin\": \"(\\\\[)(glsl)(\\\\|)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"entity.glsl.bracket.elm\"\n        },\n        \"2\": {\n          \"name\": \"entity.glsl.name.elm\"\n        },\n        \"3\": {\n          \"name\": \"entity.glsl.bracket.elm\"\n        }\n      },\n      \"end\": \"(\\\\|\\\\])\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"entity.glsl.bracket.elm\"\n        }\n      },\n      \"name\": \"meta.embedded.block.glsl\",\n      \"patterns\": [\n        {\n          \"include\": \"source.glsl\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/github1s/assets/pages/components.css",
    "content": ".vscode-button {\n  border: none;\n  display: inline-block;\n  padding: 0 10px;\n  height: 26px;\n  line-height: 26px;\n  font-size: 14px;\n  outline: 1px solid transparent;\n  outline-offset: 2px !important;\n  color: var(--vscode-button-foreground);\n  background: var(--vscode-button-background);\n  cursor: pointer;\n}\n\n.vscode-button.loading {\n  opacity: .5;\n}\n\n.vscode-button.size-mini {\n  padding: 0 8px;\n  height: 22px;\n  line-height: 22px;\n  font-size: 12px;\n}\n\n.vscode-button.size-middle {\n  padding: 0 12px;\n  height: 30px;\n  line-height: 30px;\n  font-size: 14px;\n}\n\n.vscode-button.size-large {\n  padding: 0 14px;\n  height: 34px;\n  line-height: 34px;\n  font-size: 18px;\n}\n\n.vscode-button:not([disabled]):hover {\n  background: var(--vscode-button-hoverBackground);\n}\n\n.vscode-button:not([disabled]):focus {\n  outline-color: var(--vscode-focusBorder);\n}\n\n.vscode-input {\n  border: none;\n  display: inline-block;\n  padding: 0 4px;\n  height: 26px;\n  line-height: 26px;\n  font-size: 13px;\n  outline: 1px solid transparent;\n  font-family: var(--vscode-font-family);\n  color: var(--vscode-input-foreground);\n  border: 1px solid var(--vscode-input-border, var(--vscode-widget-border));\n  background-color: var(--vscode-input-background);\n}\n\n.vscode-input.size-mini {\n  padding: 0 2px;\n  height: 22px;\n  line-height: 22px;\n  font-size: 12px;\n}\n\n.vscode-input.size-middle {\n  padding: 0 4px;\n  height: 30px;\n  line-height: 30px;\n  font-size: 13px;\n}\n\n.vscode-input.size-large {\n  padding: 0 6px;\n  height: 34px;\n  line-height: 34px;\n  font-size: 18px;\n}\n\n.vscode-input:not([disabled]):focus {\n  outline-color: var(--vscode-focusBorder);\n  outline: 1px solid -webkit-focus-ring-color;\n  outline-offset: -1px;\n}\n\n.vscode-textarea {\n  border: none;\n  display: inline-block;\n  outline: 1px solid transparent;\n  font-family: var(--vscode-font-family);\n  color: var(--vscode-input-foreground);\n  border: 1px solid var(--vscode-input-background);\n  background-color: var(--vscode-input-background);\n}\n\n.vscode-textarea:not([disabled]):focus {\n  outline-color: var(--vscode-focusBorder);\n  outline: 1px solid -webkit-focus-ring-color;\n  outline-offset: -1px;\n}\n\n.vscode-loading {\n  width: 100%;\n  text-align: center;\n  height: 26px;\n}\n\n.vscode-loading.align-left {\n  text-align: left;\n}\n\n.vscode-loading.align-right {\n  text-align: right;\n}\n\n.vscode-loading > span {\n  height: 100%;\n  width: 5px;\n  display: inline-block;\n  margin-right: 4px;\n  background: var(--vscode-button-background);\n  animation: vscodeLoading 1.2s infinite ease-in-out;\n}\n\n.vscode-loading > span:nth-child(2) {\n  animation-delay: -1s;\n}\n\n.vscode-loading > span:nth-child(3) {\n  animation-delay: -0.9s;\n}\n\n.vscode-loading > span:nth-child(4) {\n  animation-delay: -0.8s;\n}\n\n.vscode-loading > span:nth-child(5) {\n  animation-delay: -0.7s;\n}\n\n.vscode-loading > span:nth-child(6) {\n  animation-delay: -0.6s;\n}\n\n.vscode-loading > span:nth-child(7) {\n  animation-delay: -0.5s;\n}\n\n.vscode-loading > span:nth-child(8) {\n  animation-delay: -0.4s;\n}\n\n.vscode-loading > span:nth-child(9) {\n  animation-delay: -0.3s;\n}\n\n.vscode-loading > span:last-child {\n  margin-right: 0 !important;\n}\n\n@keyframes vscodeLoading {\n  0% {\n    transform: scaleY(0.4);\n  }\n  25% {\n    transform: scaleY(1);\n  }\n  50% {\n    transform: scaleY(0.4);\n  }\n  75% {\n    transform: scaleY(0.4);\n  }\n  100% {\n    transform: scaleY(0.4);\n  }\n}\n\n.vscode-link {\n  cursor: pointer;\n  color: var(--vscode-textLink-foreground);\n  text-decoration: underline;\n}\n\n.vscode-link:hover {\n  color: var(--vscode-textLink-activeForeground);\n}\n\n.success-text {\n  color: #89d185;\n}\n\n.warning-text {\n  color: #cca700;\n}\n\n.error-text {\n  color: #f48771;\n}\n"
  },
  {
    "path": "extensions/github1s/assets/pages/components.js",
    "content": "import { h } from './libraries/preact.module.js';\nimport htm from './libraries/htm.module.js';\n\nexport const html = htm.bind(h);\n\nexport const VscodeButton = ({ size, loading, ...props }) => {\n\tconst sizeClass = `size-${size || 'small'}`;\n\tconst loadingClass = loading ? 'loading' : '';\n\tconst classes = `vscode-button ${sizeClass} ${loadingClass}`;\n\n\treturn html`<button class=${classes} disabled=${loading} ...${props} />`;\n};\n\nexport const VscodeInput = ({ size, ...props }) => {\n\tconst classes = `vscode-input size-${size || 'small'}`;\n\n\treturn html`<input class=${classes} ...${props} />`;\n};\n\nexport const VscodeTextarea = (props) => {\n\treturn html` <textarea class=\"vscode-textarea\" ...${props} /> `;\n};\n\nexport const VscodeLoading = ({ blockWidth, blockSpacing, dots = 5, align = 'center', ...props }) => {\n\tconst _blockWidth = blockWidth || '5px';\n\tconst _blockSpacing = blockSpacing || '4px';\n\tconst styleStr = `width: ${_blockWidth}; margin-right: ${_blockSpacing}`;\n\tconst blocks = Array.from({ length: dots }).map(() => html`<span style=${styleStr} />`);\n\tconst classes = 'vscode-loading' + (align !== 'center' ? ` align-${align}` : '');\n\n\treturn html`<div class=${classes} ...${props}>${blocks}</div>`;\n};\n\nexport const VscodeLink = ({ to, external, ...props }) => {\n\tconst hrefProp = to ? { href: to } : {};\n\tconst roleProp = to ? {} : { role: 'button' };\n\tconst targetProp = external ? { target: '_blank' } : {};\n\tconst combineProps = { ...hrefProp, ...roleProp, ...targetProp };\n\n\treturn html` <a class=\"vscode-link\" rel=\"noopener noreferrer\" ...${combineProps} ...${props} /> `;\n};\n\nconst postMessage = (() => {\n\tconst vscode = window.acquireVsCodeApi();\n\tconst uniqueId = (\n\t\t(id) => () =>\n\t\t\tid++\n\t)(1);\n\tconst messageMap = new Map();\n\n\twindow.addEventListener('message', ({ data }) => {\n\t\tmessageMap.has(data.id) && messageMap.get(data.id)(data.data);\n\t});\n\n\treturn (type, data) => {\n\t\tconst messageId = uniqueId();\n\t\tvscode.postMessage({ type, data, id: messageId });\n\t\treturn new Promise((resolve) => {\n\t\t\tmessageMap.set(messageId, resolve);\n\t\t});\n\t};\n})();\n\nexport const bridgeCommands = {\n\tgetToken: () => postMessage('get-token'),\n\tsetToken: (token) => postMessage('set-token', token),\n\tvalidateToken: (token) => postMessage('validate-token', token),\n\topenDetailPage: () => postMessage('open-detail-page'),\n\tOAuthAuthenticate: () => postMessage('oauth-authorizing'),\n\talertMessage: (messageArgs) => postMessage('call-vscode-message-api', messageArgs),\n\tgetPreferSgApi: () => postMessage('get-prefer-sourcegraph-api'),\n\tsetPreferSgApi: (value) => postMessage('set-prefer-sourcegraph-api', value),\n\tgetNotice: () => postMessage('get-notice'),\n};\n"
  },
  {
    "path": "extensions/github1s/assets/pages/github1s-authentication.css",
    "content": ".authentication-page {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n}\n\n.authentication-page .page-notice {\n  font-size: 16px;\n  margin-bottom: 24px;\n  font-weight: bold;\n  color: #cca700;\n  max-width: 520px;\n  text-align: center;\n}\n\n.authentication-form .form-title {\n  font-size: 24px;\n  text-align: center;\n  margin-bottom: 32px;\n  color: var(--vscode-button-foreground);\n}\n\n.authentication-form .form-content {\n  width: 320px;\n}\n\n.authentication-features {\n  list-style: none;\n\tfont-size: 14px;\n\tpadding: 0;\n\tmargin: 0 0 32px;\n}\n\n.authentication-features .feature-item {\n\twhite-space: nowrap;\n\tmargin-bottom: 4px;\n}\n\n.authentication-features .feature-item:last-child {\n\tmargin-bottom: 0;\n}\n\n.authentication-features li.feature-item a {\n\tcolor: var(--vscode-foreground);\n\ttext-decoration: none;\n}\n\n.authentication-features li.feature-item a.link:hover {\n\tcolor: #40a9ff;\n}\n\n.authentication-features li.feature-item a.link:active {\n\tcolor: #096dd9;\n}\n\n.authentication-features .feature-item::before {\n\tcontent: '✓';\n\tcolor: #32d74b;\n\tmargin-right: 4px;\n}\n\n.authentication-features .feature-item {\n\twhite-space: nowrap;\n\tline-height: 20px;\n}\n\n.github1s-authorizing-dialog li.feature-item a {\n\tcolor: var(--vscode-foreground);\n\ttext-decoration: none;\n}\n\n.authentication-button {\n  width: 100%;\n  height: 40px;\n  outline: none;\n  margin: 0 auto;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background-color: #fff;\n  box-shadow: rgba(255, 255, 255, 0.2) 0px 2px 4px;\n  border: 1px solid var(--vscode-foreground);\n  border-radius: 4px;\n  font-size: 16px;\n  transition: all 0.1s;\n  cursor: pointer;\n  color: #000;\n}\n\n.authentication-button:not([disabled]):hover {\n  transform: scale(1.03);\n  box-shadow: rgba(255, 255, 255, 0.25) 0px 2px 8px;\n}\n\n.authentication-button:not([disabled]):active {\n  transform: scale(0.98);\n}\n\n.authentication-token .token-input-line {\n  display: flex;\n  margin-bottom: 6px;\n}\n\n.authentication-token .token-input-line .vscode-input {\n  flex: 1;\n  margin-right: 8px;\n}\n\n.split-line {\n  height: 0;\n  border: 1px solid var(--vscode-foreground);\n  margin: 28px 0;\n  position: relative;\n}\n\n.split-line::after {\n  content: 'OR';\n  display: block;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translateY(-50%) translateX(-50%);\n  border: 2px solid var(--vscode-foreground);\n  padding: 4px 16px;\n  border-radius: 8px;\n  background-color: var(--vscode-editor-background);\n  font-size: 12px;\n  font-weight: bold;\n}\n\n.authentication-footer {\n  margin-top: 24px;\n  color: var(--vscode-foreground);\n  width: 320px;\n}\n\n.authentication-footer > div:first-child {\n  margin-bottom: 4px;\n}\n\n.authentication-form {\n  margin: auto;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n}\n\n#app {\n  margin-top: 60px;\n}\n\n.authentication-button[disabled] .auth-button-logo {\n  opacity: .5;\n}\n\n.auth-button-logo {\n  width: 24px;\n  height: 24px;\n  display: inline-block;\n  background-size: 100% 100%;\n  background-position: 50% 50%;\n  background-repeat: no-repeat;\n  margin-right: 8px;\n}\n\n.authentication-detail {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n}\n\n.detail-title {\n  width: 320px;\n  font-size: 24px;\n  margin-bottom: 32px;\n  color: var(--vscode-button-foreground);\n}\n\n.token-status {\n  display: flex;\n  align-items: center;\n  width: 320px;\n  margin-bottom: 8px;\n}\n\n.token-status .refresh-button {\n\tcursor: pointer;\n  margin-left: 6px;\n}\n\n.token-status .refresh-button:hover {\n  color: #3794ff;\n}\n\n.token-status .refresh-button:active {\n  color: #094771;\n}\n\n.login-text > span:first-child {\n  margin-right: 4px;\n}\n\n.user-avatar {\n  display: inline-block;\n  height: 14px;\n  width: 14px;\n  margin-right: 4px;\n  vertical-align: bottom;\n  border-radius: 50%;\n  background-color: #ccc;\n}\n\n.rate-limit-info {\n  width: 320px;\n  list-style: none;\n  padding-left: 0;\n}\n\n.rate-limit-info li {\n  margin-bottom: 8px;\n}\n\n.token-text {\n  width: 320px;\n  margin-bottom: 8px;\n}\n\n.token-text.token-valid {\n  color: #73c991;\n}\n\n.token-text.token-invalid {\n  color: #f88070;\n}\n\n.token-operations {\n  width: 320px;\n  margin-top: 12px;\n}\n\n.token-operations > * {\n  width: 240px;\n}\n\n"
  },
  {
    "path": "extensions/github1s/assets/pages/github1s-authentication.js",
    "content": "import { render } from './libraries/preact.module.js';\nimport { useState, useCallback, useEffect } from './libraries/preact-hooks.module.js';\nimport { html, VscodeButton, VscodeInput, VscodeLoading, VscodeLink, bridgeCommands } from './components.js';\n\nconst pageConfig = window.pageConfig || {};\n\nconst AuthenticationFeatures = () => {\n\treturn html`\n\t\t<ul class=\"authentication-features\">\n\t\t\t${(pageConfig.authenticationFeatures || []).map(\n\t\t\t\t(feature) =>\n\t\t\t\t\thtml`<li class=\"feature-item\">\n\t\t\t\t\t\t<a class=\"link\" href=${feature.link} target=\"_blank\" rel=\"noopener noreferrer\">${feature.text}</a>\n\t\t\t\t\t</li>`,\n\t\t\t)}\n\t\t</ul>\n\t`;\n};\n\nconst AuthenticationButton = (props) => {\n\tconst [authenticating, setAuthenticating] = useState(false);\n\n\tconst handleButtonClick = useCallback(() => {\n\t\tsetAuthenticating(true);\n\t\tbridgeCommands.OAuthAuthenticate().then(() => setAuthenticating(false));\n\t}, []);\n\n\tconst buttonLogoUrl = encodeURI(`${pageConfig.extensionUri}/${pageConfig.OAuthButtonLogo}`);\n\treturn html`\n\t\t<button class=\"authentication-button\" disabled=\"${authenticating}\" onClick=${handleButtonClick} ...${props}>\n\t\t\t<span class=${'auth-button-logo'} style=${`background-image: url(\"${buttonLogoUrl}\")`}></span>\n\t\t\t<span>${pageConfig.OAuthButtonText}</span>\n\t\t</button>\n\t`;\n};\n\nconst ManualInputToken = () => {\n\tconst [inputToken, setInputToken] = useState('');\n\tconst [loading, setLoading] = useState(false);\n\tconst handleInputTokenChange = useCallback((event) => {\n\t\tsetInputToken(event.target.value);\n\t}, []);\n\n\tconst handleSubmit = useCallback(() => {\n\t\tif (inputToken) {\n\t\t\tsetLoading(true);\n\t\t\tbridgeCommands.validateToken(inputToken).then((tokenStatus) => {\n\t\t\t\tif (!tokenStatus) {\n\t\t\t\t\tconst messageArgs = { level: 'info', args: ['This AccessToken is invalid'] };\n\t\t\t\t\tbridgeCommands.alertMessage(messageArgs);\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbridgeCommands.setToken(inputToken).then(() => setLoading(false));\n\t\t\t});\n\t\t}\n\t}, [inputToken]);\n\n\treturn html`\n\t\t<div class=\"authentication-token\">\n\t\t\t<div class=\"token-input-line\">\n\t\t\t\t<${VscodeInput}\n\t\t\t\t\tautocomplete=\"off\"\n\t\t\t\t\tvalue=${inputToken}\n\t\t\t\t\tdisabled=\"${loading}\"\n\t\t\t\t\tonInput=${handleInputTokenChange}\n\t\t\t\t/>\n\t\t\t\t<${VscodeButton} loading=${loading} onClick=${handleSubmit}>Submit<//>\n\t\t\t</div>\n\t\t\t<${VscodeLink} to=\"${pageConfig.createTokenLink}\" external>Create New AccessToken<//>\n\t\t</div>\n\t`;\n};\n\nconst SplitLine = () => {\n\treturn html`<div class=\"split-line\"></div>`;\n};\n\nconst AuthenticationFooter = () => {\n\treturn html`\n\t\t<div class=\"authentication-footer\">\n\t\t\t<div>The access token will only store in your browser.</div>\n\t\t\t<div>Don't forget to clean it while you are using a device that doesn't belong to you.</div>\n\t\t</div>\n\t`;\n};\n\nconst AuthenticationForm = () => {\n\treturn html`\n\t\t<div class=\"authentication-form\">\n\t\t\t<div class=\"form-title\">${pageConfig.authenticationFormTitle}</div>\n\t\t\t<${AuthenticationFeatures} />\n\t\t\t<div class=\"form-content\">\n\t\t\t\t<${AuthenticationButton} />\n\t\t\t\t<${SplitLine} />\n\t\t\t\t<${ManualInputToken} />\n\t\t\t</div>\n\t\t\t<${AuthenticationFooter} />\n\t\t</div>\n\t`;\n};\n\nconst StatusNumberText = ({ count }) => {\n\tif (count <= 0) {\n\t\treturn html`<span class=\"error-text\">${count}</span>`;\n\t}\n\tif (count <= 99) {\n\t\treturn html`<span class=\"warning-text\">${count}</span>`;\n\t}\n\n\treturn html`<span class=\"success-text\">${count}</span>`;\n};\n\nconst RateLimitsInfo = ({ info }) => {\n\treturn html`<div>\n\t\t<ul class=\"rate-limit-info\">\n\t\t\t<li>------- Rate Limit Info -------</li>\n\t\t\t<li>X-RateLimit-Limit: <${StatusNumberText} count=${info.limit} /></li>\n\t\t\t<li>X-RateLimit-Remaining: <${StatusNumberText} count=${info.remaining} /></li>\n\t\t\t<li>X-RateLimit-Used: ${info.used}</li>\n\t\t\t<li>X-RateLimit-Reset: ${info.reset}</li>\n\t\t\t<li>------------------------------</li>\n\t\t\t<li class=\"rate-limit-description\">\n\t\t\t\t<span>Current rate limit window will reset after </span>\n\t\t\t\t<span>${Math.max(info.reset - Math.ceil(Date.now() / 1000), 0)}s</span>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<${VscodeLink} to=\"${pageConfig.rateLimitDocLink}\" external>${pageConfig.rateLimitDocLinkText}<//>\n\t\t\t</li>\n\t\t</ul>\n\t</div>`;\n};\n\nconst AuthenticationDetail = ({ accessToken }) => {\n\tconst [tokenStatus, setTokenStatus] = useState(null);\n\tconst [validating, setValidating] = useState(true);\n\n\tconst displayToken = accessToken.slice(0, 7) + '*********************************';\n\tconst tokenClasses = `token-text ${validating ? '' : tokenStatus ? 'token-valid' : 'token-invalid'}`;\n\n\tconst handleRefreshTokenStatus = useCallback(() => {\n\t\tsetValidating(true);\n\t\tbridgeCommands\n\t\t\t.validateToken(accessToken)\n\t\t\t.then((tokenStatus) => setTokenStatus(tokenStatus))\n\t\t\t.finally(() => setValidating(false));\n\t}, [accessToken]);\n\n\tconst handleClearToken = useCallback(() => {\n\t\tconst messageArgs = {\n\t\t\tlevel: 'warning',\n\t\t\targs: ['Would you want to clear the saved this AccessToken?', { modal: true }, 'Confirm'],\n\t\t};\n\t\tbridgeCommands.alertMessage(messageArgs).then((choose) => choose === 'Confirm' && bridgeCommands.setToken(''));\n\t}, []);\n\n\tuseEffect(() => {\n\t\thandleRefreshTokenStatus();\n\t}, [handleRefreshTokenStatus]);\n\n\tif (validating) {\n\t\treturn html`<${VscodeLoading} />`;\n\t}\n\n\treturn html`\n\t\t<div class=\"authentication-detail\">\n\t\t\t<div class=\"detail-title\">Authorization Detail</div>\n\t\t\t<div class=\"token-status\">\n\t\t\t\t${tokenStatus\n\t\t\t\t\t? html`<div class=\"login-text\">\n\t\t\t\t\t\t\t<span>Logged in as</span>\n\t\t\t\t\t\t\t<${VscodeLink} to=${tokenStatus.profile_url} external>\n\t\t\t\t\t\t\t\t<img class=\"user-avatar\" src=${tokenStatus.avatar_url} />${tokenStatus.username}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t  </div>`\n\t\t\t\t\t: html`<div>Current AccessToken is <span class=\"error-text\">INVALID</span>.</div>`}\n\t\t\t\t<span class=\"refresh-button\" onClick=${handleRefreshTokenStatus}>↻</span>\n\t\t\t</div>\n\t\t\t<div class=${tokenClasses}>${displayToken}</div>\n\t\t\t${tokenStatus && tokenStatus.rateLimits ? html`<${RateLimitsInfo} info=${tokenStatus.rateLimits} />` : null}\n\t\t\t<div class=\"token-operations\">\n\t\t\t\t<${VscodeButton} size=\"middle\" onClick=${handleClearToken}>Clear Access Token<//>\n\t\t\t</div>\n\t\t\t<${AuthenticationFooter} />\n\t\t</div>\n\t`;\n};\n\nconst App = () => {\n\tconst [loading, setLoading] = useState(true);\n\tconst [accessToken, setAccessToken] = useState('');\n\tconst [notice, setNotice] = useState('');\n\n\tuseEffect(() => {\n\t\tbridgeCommands.getToken().then((token) => {\n\t\t\tsetAccessToken(token);\n\t\t\tsetLoading(false);\n\t\t});\n\t\tbridgeCommands.getNotice().then((notice) => setNotice(notice));\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst handler = ({ data }) => {\n\t\t\tif (data.type === 'token-changed') {\n\t\t\t\tsetAccessToken(data.token);\n\t\t\t\tbridgeCommands.getNotice().then((notice) => setNotice(notice));\n\t\t\t}\n\t\t};\n\t\twindow.addEventListener('message', handler);\n\t\treturn () => window.removeEventListener('message', handler);\n\t}, [setAccessToken]);\n\n\tif (loading) {\n\t\treturn html`<${VscodeLoading} />`;\n\t}\n\n\treturn html`\n\t\t<div class=\"authentication-page\">\n\t\t\t${notice ? html`<div class=\"page-notice\">${notice}</div>` : null}\n\t\t\t<${accessToken ? AuthenticationDetail : AuthenticationForm} accessToken=${accessToken} />\n\t\t</div>\n\t`;\n};\n\nconst loadingElement = document.getElementById('page-loading');\nloadingElement.parentNode.removeChild(loadingElement);\nrender(html`<${App} />`, document.getElementById('app'));\n"
  },
  {
    "path": "extensions/github1s/assets/pages/github1s-settings.css",
    "content": ".vscode-input {\n  margin-bottom: 10px;\n}\n\n.vscode-button {\n  margin-bottom: 10px;\n}\n\n#app {\n  padding: 10px;\n}\n\n.flex-line {\n  display: flex;\n}\n\n.flex-line > * {\n  flex: 1;\n}\n\n.page-title {\n\tfont-size: 16px;\n\tfont-weight: bold;\n\tmargin-bottom: 10px;\n}\n\n.page-description {\n  font-size: 12px;\n\tmargin-bottom: 12px;\n}\n\n.description div:last-child {\n\tmargin-bottom: 0;\n}\n\n.content-block {\n  margin-bottom: 8px;\n}\n\n.content-block-title {\n  font-weight: normal;\n\tmargin-bottom: 8px;\n}\n\n.input-token-block {\n\tmargin-bottom: 8px;\n}\n\n.input-token-block-title {\n  font-weight: normal;\n\tmargin-bottom: 8px;\n}\n\n.create-token-link {\n\tmargin-bottom: 10px;\n}\n\n.page-footer {\n  display: flex;\n  align-items: center;\n  margin-top: 12px;\n}\n\n.page-footer input {\n margin-right: 4px;\n margin-left: 0;\n}\n\n.login-text > span:first-child {\n  margin-right: 4px;\n}\n\n.user-avatar {\n  display: inline-block;\n  height: 14px;\n  width: 14px;\n  margin-right: 4px;\n  vertical-align: bottom;\n  border-radius: 50%;\n  background-color: #ccc;\n}\n\n"
  },
  {
    "path": "extensions/github1s/assets/pages/github1s-settings.js",
    "content": "import { render } from './libraries/preact.module.js';\nimport { useState, useCallback, useEffect } from './libraries/preact-hooks.module.js';\nimport { html, VscodeButton, VscodeInput, VscodeLink, VscodeLoading, bridgeCommands } from './components.js';\n\nconst pageConfig = window.pageConfig || {};\n\nexport const PageHeader = ({ title, children, ...props }) => {\n\treturn html`<div ...${props}>\n\t\t<div class=\"page-title\">${title}</div>\n\t\t<div class=\"page-description\">${children}</div>\n\t</div>`;\n};\n\nexport const OAuthBlock = ({ buttonText, command, ...props }) => {\n\tconst [loading, setLoading] = useState(false);\n\tconst handleButtonClick = useCallback(() => {\n\t\tsetLoading(true);\n\t\tbridgeCommands.OAuthAuthenticate().then(() => setLoading(false));\n\t}, []);\n\n\treturn html`\n\t\t<div class=\"content-block\" ...${props}>\n\t\t\t<h3 class=\"content-block-title\">Authenticating OAuth App</h3>\n\t\t\t<div class=\"flex-line\">\n\t\t\t\t<${VscodeButton} loading=${loading} onClick=${handleButtonClick}>${buttonText}<//>\n\t\t\t</div>\n\t\t</div>\n\t`;\n};\n\nexport const InputTokenBlock = ({ createLink, isEditing, onCancel, ...props }) => {\n\tconst [inputToken, setInputToken] = useState('');\n\tconst [loading, setLoading] = useState(false);\n\tconst handleInputTokenChange = useCallback((event) => {\n\t\tsetInputToken(event.target.value);\n\t}, []);\n\n\tconst handleSubmit = useCallback(() => {\n\t\tif (inputToken) {\n\t\t\tsetLoading(true);\n\t\t\tbridgeCommands.validateToken(inputToken).then((tokenStatus) => {\n\t\t\t\tif (!tokenStatus) {\n\t\t\t\t\tconst messageArgs = { level: 'info', args: ['This AccessToken is invalid'] };\n\t\t\t\t\tbridgeCommands.alertMessage(messageArgs);\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbridgeCommands.setToken(inputToken).then(() => setLoading(false));\n\t\t\t});\n\t\t}\n\t}, [inputToken]);\n\n\treturn html`\n\t\t<div class=\"input-token-block\" ...${props}>\n\t\t\t<h3 class=\"input-token-block-title\">Manual Input AccessToken</h3>\n\t\t\t<div class=\"create-token-link\">\n\t\t\t\t<${VscodeLink} to=${createLink} external>Create New AccessToken <//>\n\t\t\t</div>\n\t\t\t<div class=\"flex-line\">\n\t\t\t\t<${VscodeInput}\n\t\t\t\t\tautocomplete=\"off\"\n\t\t\t\t\tvalue=${inputToken}\n\t\t\t\t\tdisabled=\"${loading}\"\n\t\t\t\t\tonInput=${handleInputTokenChange}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div class=\"flex-line\">\n\t\t\t\t<${VscodeButton} loading=${loading} onClick=${handleSubmit}>Submit<//>\n\t\t\t</div>\n\t\t\t${isEditing\n\t\t\t\t? html`<div class=\"flex-line\">\n\t\t\t\t\t\t<${VscodeButton} onClick=${onCancel}>Cancel<//>\n\t\t\t\t\t</div>`\n\t\t\t\t: null}\n\t\t</div>\n\t`;\n};\n\nexport const TokenDetailBlock = ({ token, validating, onEditClick, validateToken, ...props }) => {\n\tconst handleValidateClick = useCallback(() => {\n\t\tvalidateToken(token).then((tokenStatus) => {\n\t\t\tconst statusMessage = `Current AccessToken is ${tokenStatus ? 'VALID' : 'INVALID'}`;\n\t\t\tconst messageArgs = { level: 'info', args: [statusMessage] };\n\t\t\tbridgeCommands.alertMessage(messageArgs);\n\t\t});\n\t}, [validateToken, token]);\n\n\tconst handleClearClick = useCallback(() => {\n\t\tconst messageArgs = {\n\t\t\tlevel: 'warning',\n\t\t\targs: ['Would you want to clear the saved this AccessToken?', { modal: true }, 'Confirm'],\n\t\t};\n\t\tbridgeCommands.alertMessage(messageArgs).then((choose) => choose === 'Confirm' && bridgeCommands.setToken(''));\n\t}, []);\n\n\treturn html`\n\t\t<div class=\"token-detail-block\" ${props}>\n\t\t\t<div class=\"flex-line\"><${VscodeButton} onClick=${bridgeCommands.openDetailPage}>Detail<//></div>\n\t\t\t<div class=\"flex-line\"><${VscodeButton} loading=${validating} onClick=${handleValidateClick}>Validate<//></div>\n\t\t\t<div class=\"flex-line\"><${VscodeButton} onClick=${onEditClick}>Edit<//></div>\n\t\t\t<div class=\"flex-line\"><${VscodeButton} onClick=${handleClearClick}>Clear<//></div>\n\t\t</div>\n\t`;\n};\n\nconst PageFooter = () => {\n\tconst [preferSgApi, setPreferSgApi] = useState(false);\n\n\tconst updatePreferSgApi = useCallback(() => {\n\t\tbridgeCommands.getPreferSgApi().then((value) => {\n\t\t\tsetPreferSgApi(value);\n\t\t});\n\t}, []);\n\n\tconst handleCheckboxChange = useCallback(\n\t\t(event) => {\n\t\t\tbridgeCommands.setPreferSgApi(event.target.checked).then(() => {\n\t\t\t\tupdatePreferSgApi();\n\t\t\t});\n\t\t},\n\t\t[updatePreferSgApi],\n\t);\n\n\tuseEffect(() => {\n\t\tconst handler = ({ data }) => {\n\t\t\tif (data.type === 'prefer-sourcegraph-api-changed') {\n\t\t\t\tupdatePreferSgApi();\n\t\t\t}\n\t\t};\n\t\twindow.addEventListener('message', handler);\n\t\treturn () => window.removeEventListener('message', handler);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tupdatePreferSgApi();\n\t}, [updatePreferSgApi]);\n\n\treturn html`\n\t\t<div class=\"page-footer\">\n\t\t\t<input type=\"checkbox\" checked=${preferSgApi} onChange=${handleCheckboxChange} />\n\t\t\t<span>Prefer to use Sourcegraph API</span>\n\t\t</div>\n\t`;\n};\n\nconst TokenEditPage = ({ token, onCancel, ...props }) => {\n\tconst pageDescription = (pageConfig.pageDescriptionLines || []).map((line) => html`<div>${line}</div>`);\n\n\treturn html`\n\t\t<div class=\"token-edit-page\" ...${props}>\n\t\t\t<${PageHeader} title=\"Set AccessToken\">${pageDescription}<//>\n\t\t\t<${OAuthBlock} buttonText=${pageConfig.OAuthButtonText} command=${pageConfig.OAuthCommand} />\n\t\t\t<${InputTokenBlock} createLink=${pageConfig.createTokenLink} isEditing=${!!token} onCancel=${onCancel} />\n\t\t</div>\n\t`;\n};\n\nconst TokenDetailPage = ({ token, onEditClick, ...props }) => {\n\tconst [tokenStatus, setTokenStatus] = useState(null);\n\tconst [validating, setValidating] = useState(true);\n\n\tconst validateToken = useCallback((token) => {\n\t\tsetValidating(true);\n\t\treturn bridgeCommands.validateToken(token).then((tokenStatus) => {\n\t\t\tsetValidating(false);\n\t\t\tsetTokenStatus(tokenStatus);\n\t\t\treturn tokenStatus;\n\t\t});\n\t}, []);\n\n\tconst validateResult = tokenStatus\n\t\t? html`<div class=\"login-text\">\n\t\t\t\t<span>Logged in as</span>\n\t\t\t\t<a href=${tokenStatus.profile_url} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t<img class=\"user-avatar\" src=${tokenStatus.avatar_url} />${tokenStatus.username}\n\t\t\t\t</a>\n\t\t\t</div>`\n\t\t: html`<div>Current AccessToken is <span class=\"error-text\">INVALID</span>.</div>`;\n\n\tuseEffect(() => {\n\t\ttoken && validateToken(token);\n\t}, [token, validateToken]);\n\n\treturn html`\n\t\t<div class=\"token-detail-page\" ...${props}>\n\t\t\t<${PageHeader} title=\"You have authenticated\">\n\t\t\t\t${validating ? html`<${VscodeLoading} dots=${8} align=\"left\" style=\"height: 14px\" />` : validateResult}\n\t\t\t<//>\n\t\t\t<${TokenDetailBlock}\n\t\t\t\ttoken=${token}\n\t\t\t\tvalidating=${validating}\n\t\t\t\tonEditClick=${onEditClick}\n\t\t\t\tvalidateToken=${validateToken}\n\t\t\t/>\n\t\t</div>\n\t`;\n};\n\nconst App = () => {\n\tconst [loading, setLoading] = useState(true);\n\tconst [pageType, setPageType] = useState('EDIT');\n\tconst [token, setToken] = useState('');\n\n\tconst switchToEdit = useCallback(() => setPageType('EDIT'), []);\n\tconst switchToDetail = useCallback(() => setPageType('DETAIL'), []);\n\n\tuseEffect(() => {\n\t\tbridgeCommands.getToken().then((token) => {\n\t\t\tsetToken(token);\n\t\t\tsetLoading(false);\n\t\t\tsetPageType(token ? 'DETAIL' : 'EDIT');\n\t\t});\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst handler = ({ data }) => {\n\t\t\tif (data.type === 'token-changed') {\n\t\t\t\tsetToken(data.token);\n\t\t\t\tsetPageType(data.token ? 'DETAIL' : 'EDIT');\n\t\t\t}\n\t\t};\n\t\twindow.addEventListener('message', handler);\n\t\treturn () => window.removeEventListener('message', handler);\n\t}, []);\n\n\tif (loading) {\n\t\treturn html`<${VscodeLoading} />`;\n\t}\n\n\treturn html`\n\t\t<div>\n\t\t\t${pageType === 'DETAIL'\n\t\t\t\t? html`<${TokenDetailPage} token=${token} onEditClick=${switchToEdit} />`\n\t\t\t\t: html`<${TokenEditPage} token=${token} onCancel=${switchToDetail} />`}\n\t\t\t<${PageFooter} />\n\t\t</div>\n\t`;\n};\n\nconst loadingElement = document.getElementById('page-loading');\nloadingElement.parentNode.removeChild(loadingElement);\nrender(html`<${App} />`, document.getElementById('app'));\n"
  },
  {
    "path": "extensions/github1s/assets/pages/libraries/htm.module.js",
    "content": "// https://github.com/developit/htm, download from https://unpkg.com/htm@3.1.0/dist/htm.module.js\nvar n=function(t,s,r,e){var u;s[0]=0;for(var h=1;h<s.length;h++){var p=s[h++],a=s[h]?(s[0]|=p?1:2,r[s[h++]]):s[++h];3===p?e[0]=a:4===p?e[1]=Object.assign(e[1]||{},a):5===p?(e[1]=e[1]||{})[s[++h]]=a:6===p?e[1][s[++h]]+=a+\"\":p?(u=t.apply(a,n(t,a,r,[\"\",null])),e.push(u),a[0]?s[0]|=2:(s[h-2]=0,s[h]=u)):e.push(a)}return e},t=new Map;export default function(s){var r=t.get(this);return r||(r=new Map,t.set(this,r)),(r=n(this,r.get(s)||(r.set(s,r=function(n){for(var t,s,r=1,e=\"\",u=\"\",h=[0],p=function(n){1===r&&(n||(e=e.replace(/^\\s*\\n\\s*|\\s*\\n\\s*$/g,\"\")))?h.push(0,n,e):3===r&&(n||e)?(h.push(3,n,e),r=2):2===r&&\"...\"===e&&n?h.push(4,n,0):2===r&&e&&!n?h.push(5,0,!0,e):r>=5&&((e||!n&&5===r)&&(h.push(r,0,e,s),r=6),n&&(h.push(r,n,0,s),r=6)),e=\"\"},a=0;a<n.length;a++){a&&(1===r&&p(),p(a));for(var l=0;l<n[a].length;l++)t=n[a][l],1===r?\"<\"===t?(p(),h=[h],r=3):e+=t:4===r?\"--\"===e&&\">\"===t?(r=1,e=\"\"):e=t+e[0]:u?t===u?u=\"\":e+=t:'\"'===t||\"'\"===t?u=t:\">\"===t?(p(),r=1):r&&(\"=\"===t?(r=5,s=e,e=\"\"):\"/\"===t&&(r<5||\">\"===n[a][l+1])?(p(),3===r&&(h=h[0]),r=h,(h=h[0]).push(2,0,r),r=0):\" \"===t||\"\\t\"===t||\"\\n\"===t||\"\\r\"===t?(p(),r=2):e+=t),3===r&&\"!--\"===e&&(r=4,h=h[0])}return p(),h}(s)),r),arguments,[])).length>1?r:r[0]}"
  },
  {
    "path": "extensions/github1s/assets/pages/libraries/preact-hooks.module.js",
    "content": "// https://github.com/preactjs/preact, download from https://unpkg.com/preact@10.7.1/hooks/dist/hooks.module.js\nimport{options as n}from\"./preact.module.js\";var t,u,r,o=0,i=[],c=n.__b,f=n.__r,e=n.diffed,a=n.__c,v=n.unmount;function l(t,r){n.__h&&n.__h(u,t,o||r),o=0;var i=u.__H||(u.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({}),i.__[t]}function m(n){return o=1,p(w,n)}function p(n,r,o){var i=l(t++,2);return i.t=n,i.__c||(i.__=[o?o(r):w(void 0,r),function(n){var t=i.t(i.__[0],n);i.__[0]!==t&&(i.__=[t,i.__[1]],i.__c.setState({}))}],i.__c=u),i.__}function y(r,o){var i=l(t++,3);!n.__s&&k(i.__H,o)&&(i.__=r,i.__H=o,u.__H.__h.push(i))}function d(r,o){var i=l(t++,4);!n.__s&&k(i.__H,o)&&(i.__=r,i.__H=o,u.__h.push(i))}function h(n){return o=5,_(function(){return{current:n}},[])}function s(n,t,u){o=6,d(function(){return\"function\"==typeof n?(n(t()),function(){return n(null)}):n?(n.current=t(),function(){return n.current=null}):void 0},null==u?u:u.concat(n))}function _(n,u){var r=l(t++,7);return k(r.__H,u)&&(r.__=n(),r.__H=u,r.__h=n),r.__}function A(n,t){return o=8,_(function(){return n},t)}function F(n){var r=u.context[n.__c],o=l(t++,9);return o.c=n,r?(null==o.__&&(o.__=!0,r.sub(u)),r.props.value):n.__}function T(t,u){n.useDebugValue&&n.useDebugValue(u?u(t):t)}function q(n){var r=l(t++,10),o=m();return r.__=n,u.componentDidCatch||(u.componentDidCatch=function(n){r.__&&r.__(n),o[1](n)}),[o[0],function(){o[1](void 0)}]}function x(){for(var t;t=i.shift();)if(t.__P)try{t.__H.__h.forEach(g),t.__H.__h.forEach(j),t.__H.__h=[]}catch(u){t.__H.__h=[],n.__e(u,t.__v)}}n.__b=function(n){u=null,c&&c(n)},n.__r=function(n){f&&f(n),t=0;var r=(u=n.__c).__H;r&&(r.__h.forEach(g),r.__h.forEach(j),r.__h=[])},n.diffed=function(t){e&&e(t);var o=t.__c;o&&o.__H&&o.__H.__h.length&&(1!==i.push(o)&&r===n.requestAnimationFrame||((r=n.requestAnimationFrame)||function(n){var t,u=function(){clearTimeout(r),b&&cancelAnimationFrame(t),setTimeout(n)},r=setTimeout(u,100);b&&(t=requestAnimationFrame(u))})(x)),u=null},n.__c=function(t,u){u.some(function(t){try{t.__h.forEach(g),t.__h=t.__h.filter(function(n){return!n.__||j(n)})}catch(r){u.some(function(n){n.__h&&(n.__h=[])}),u=[],n.__e(r,t.__v)}}),a&&a(t,u)},n.unmount=function(t){v&&v(t);var u,r=t.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{g(n)}catch(n){u=n}}),u&&n.__e(u,r.__v))};var b=\"function\"==typeof requestAnimationFrame;function g(n){var t=u,r=n.__c;\"function\"==typeof r&&(n.__c=void 0,r()),u=t}function j(n){var t=u;n.__c=n.__(),u=t}function k(n,t){return!n||n.length!==t.length||t.some(function(t,u){return t!==n[u]})}function w(n,t){return\"function\"==typeof t?t(n):t}export{m as useState,p as useReducer,y as useEffect,d as useLayoutEffect,h as useRef,s as useImperativeHandle,_ as useMemo,A as useCallback,F as useContext,T as useDebugValue,q as useErrorBoundary};"
  },
  {
    "path": "extensions/github1s/assets/pages/libraries/preact.module.js",
    "content": "// https://github.com/preactjs/preact, download from https://unpkg.com/preact@10.7.1/dist/preact.module.js\nvar n,l,u,i,t,o,r,f,e={},c=[],s=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function a(n,l){for(var u in l)n[u]=l[u];return n}function h(n){var l=n.parentNode;l&&l.removeChild(n)}function v(l,u,i){var t,o,r,f={};for(r in u)\"key\"==r?t=u[r]:\"ref\"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),\"function\"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return y(l,f,t,o,null)}function y(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u:r};return null==r&&null!=l.vnode&&l.vnode(f),f}function p(){return{current:null}}function d(n){return n.children}function _(n,l){this.props=n,this.context=l}function k(n,l){if(null==l)return n.__?k(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return\"function\"==typeof n.type?k(n):null}function b(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return b(n)}}function m(n){(!n.__d&&(n.__d=!0)&&t.push(n)&&!g.__r++||r!==l.debounceRendering)&&((r=l.debounceRendering)||o)(g)}function g(){for(var n;g.__r=t.length;)n=t.sort(function(n,l){return n.__v.__b-l.__v.__b}),t=[],n.some(function(n){var l,u,i,t,o,r;n.__d&&(o=(t=(l=n).__v).__e,(r=l.__P)&&(u=[],(i=a({},t)).__v=t.__v+1,j(r,t,i,l.__n,void 0!==r.ownerSVGElement,null!=t.__h?[o]:null,u,null==o?k(t):o,t.__h),z(u,t),t.__e!=o&&b(t)))})}function w(n,l,u,i,t,o,r,f,s,a){var h,v,p,_,b,m,g,w=i&&i.__k||c,A=w.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(_=u.__k[h]=null==(_=l[h])||\"boolean\"==typeof _?null:\"string\"==typeof _||\"number\"==typeof _||\"bigint\"==typeof _?y(null,_,null,null,_):Array.isArray(_)?y(d,{children:_},null,null,null):_.__b>0?y(_.type,_.props,_.key,null,_.__v):_)){if(_.__=u,_.__b=u.__b+1,null===(p=w[h])||p&&_.key==p.key&&_.type===p.type)w[h]=void 0;else for(v=0;v<A;v++){if((p=w[v])&&_.key==p.key&&_.type===p.type){w[v]=void 0;break}p=null}j(n,_,p=p||e,t,o,r,f,s,a),b=_.__e,(v=_.ref)&&p.ref!=v&&(g||(g=[]),p.ref&&g.push(p.ref,null,_),g.push(v,_.__c||b,_)),null!=b?(null==m&&(m=b),\"function\"==typeof _.type&&_.__k===p.__k?_.__d=s=x(_,s,n):s=P(n,_,p,w,b,s),\"function\"==typeof u.type&&(u.__d=s)):s&&p.__e==s&&s.parentNode!=n&&(s=k(p))}for(u.__e=m,h=A;h--;)null!=w[h]&&(\"function\"==typeof u.type&&null!=w[h].__e&&w[h].__e==u.__d&&(u.__d=k(i,h+1)),N(w[h],w[h]));if(g)for(h=0;h<g.length;h++)M(g[h],g[++h],g[++h])}function x(n,l,u){for(var i,t=n.__k,o=0;t&&o<t.length;o++)(i=t[o])&&(i.__=n,l=\"function\"==typeof i.type?x(i,l,u):P(u,i,i,t,i.__e,l));return l}function A(n,l){return l=l||[],null==n||\"boolean\"==typeof n||(Array.isArray(n)?n.some(function(n){A(n,l)}):l.push(n)),l}function P(n,l,u,i,t,o){var r,f,e;if(void 0!==l.__d)r=l.__d,l.__d=void 0;else if(null==u||t!=o||null==t.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(t),r=null;else{for(f=o,e=0;(f=f.nextSibling)&&e<i.length;e+=2)if(f==t)break n;n.insertBefore(t,o),r=o}return void 0!==r?r:t.nextSibling}function C(n,l,u,i,t){var o;for(o in u)\"children\"===o||\"key\"===o||o in l||H(n,o,null,u[o],i);for(o in l)t&&\"function\"!=typeof l[o]||\"children\"===o||\"key\"===o||\"value\"===o||\"checked\"===o||u[o]===l[o]||H(n,o,l[o],u[o],i)}function $(n,l,u){\"-\"===l[0]?n.setProperty(l,u):n[l]=null==u?\"\":\"number\"!=typeof u||s.test(l)?u:u+\"px\"}function H(n,l,u,i,t){var o;n:if(\"style\"===l)if(\"string\"==typeof u)n.style.cssText=u;else{if(\"string\"==typeof i&&(n.style.cssText=i=\"\"),i)for(l in i)u&&l in u||$(n.style,l,\"\");if(u)for(l in u)i&&u[l]===i[l]||$(n.style,l,u[l])}else if(\"o\"===l[0]&&\"n\"===l[1])o=l!==(l=l.replace(/Capture$/,\"\")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?i||n.addEventListener(l,o?T:I,o):n.removeEventListener(l,o?T:I,o);else if(\"dangerouslySetInnerHTML\"!==l){if(t)l=l.replace(/xlink(H|:h)/,\"h\").replace(/sName$/,\"s\");else if(\"href\"!==l&&\"list\"!==l&&\"form\"!==l&&\"tabIndex\"!==l&&\"download\"!==l&&l in n)try{n[l]=null==u?\"\":u;break n}catch(n){}\"function\"==typeof u||(null!=u&&(!1!==u||\"a\"===l[0]&&\"r\"===l[1])?n.setAttribute(l,u):n.removeAttribute(l))}}function I(n){this.l[n.type+!1](l.event?l.event(n):n)}function T(n){this.l[n.type+!0](l.event?l.event(n):n)}function j(n,u,i,t,o,r,f,e,c){var s,h,v,y,p,k,b,m,g,x,A,P=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,r=[e]),(s=l.__b)&&s(u);try{n:if(\"function\"==typeof P){if(m=u.props,g=(s=P.contextType)&&t[s.__c],x=s?g?g.props.value:s.__:t,i.__c?b=(h=u.__c=i.__c).__=h.__E:(\"prototype\"in P&&P.prototype.render?u.__c=h=new P(m,x):(u.__c=h=new _(m,x),h.constructor=P,h.render=O),g&&g.sub(h),h.props=m,h.state||(h.state={}),h.context=x,h.__n=t,v=h.__d=!0,h.__h=[]),null==h.__s&&(h.__s=h.state),null!=P.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=a({},h.__s)),a(h.__s,P.getDerivedStateFromProps(m,h.__s))),y=h.props,p=h.state,v)null==P.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else{if(null==P.getDerivedStateFromProps&&m!==y&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(m,x),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(m,h.__s,x)||u.__v===i.__v){h.props=m,h.state=h.__s,u.__v!==i.__v&&(h.__d=!1),h.__v=u,u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u)}),h.__h.length&&f.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(m,h.__s,x),null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(y,p,k)})}h.context=x,h.props=m,h.state=h.__s,(s=l.__r)&&s(u),h.__d=!1,h.__v=u,h.__P=n,s=h.render(h.props,h.state,h.context),h.state=h.__s,null!=h.getChildContext&&(t=a(a({},t),h.getChildContext())),v||null==h.getSnapshotBeforeUpdate||(k=h.getSnapshotBeforeUpdate(y,p)),A=null!=s&&s.type===d&&null==s.key?s.props.children:s,w(n,Array.isArray(A)?A:[A],u,i,t,o,r,f,e,c),h.base=u.__e,u.__h=null,h.__h.length&&f.push(h),b&&(h.__E=h.__=null),h.__e=!1}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=L(i.__e,u,i,t,o,r,f,c);(s=l.diffed)&&s(u)}catch(n){u.__v=null,(c||null!=r)&&(u.__e=e,u.__h=!!c,r[r.indexOf(e)]=null),l.__e(n,u,i)}}function z(n,u){l.__c&&l.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u)})}catch(n){l.__e(n,u.__v)}})}function L(l,u,i,t,o,r,f,c){var s,a,v,y=i.props,p=u.props,d=u.type,_=0;if(\"svg\"===d&&(o=!0),null!=r)for(;_<r.length;_++)if((s=r[_])&&\"setAttribute\"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,r[_]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=o?document.createElementNS(\"http://www.w3.org/2000/svg\",d):document.createElement(d,p.is&&p),r=null,c=!1}if(null===d)y===p||c&&l.data===p||(l.data=p);else{if(r=r&&n.call(l.childNodes),a=(y=i.props||e).dangerouslySetInnerHTML,v=p.dangerouslySetInnerHTML,!c){if(null!=r)for(y={},_=0;_<l.attributes.length;_++)y[l.attributes[_].name]=l.attributes[_].value;(v||a)&&(v&&(a&&v.__html==a.__html||v.__html===l.innerHTML)||(l.innerHTML=v&&v.__html||\"\"))}if(C(l,p,y,o,c),v)u.__k=[];else if(_=u.props.children,w(l,Array.isArray(_)?_:[_],u,i,t,o&&\"foreignObject\"!==d,r,f,r?r[0]:i.__k&&k(i,0),c),null!=r)for(_=r.length;_--;)null!=r[_]&&h(r[_]);c||(\"value\"in p&&void 0!==(_=p.value)&&(_!==l.value||\"progress\"===d&&!_||\"option\"===d&&_!==y.value)&&H(l,\"value\",_,y.value,!1),\"checked\"in p&&void 0!==(_=p.checked)&&_!==l.checked&&H(l,\"checked\",_,y.checked,!1))}return l}function M(n,u,i){try{\"function\"==typeof n?n(u):n.current=u}catch(n){l.__e(n,i)}}function N(n,u,i){var t,o;if(l.unmount&&l.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||M(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount()}catch(n){l.__e(n,u)}t.base=t.__P=null}if(t=n.__k)for(o=0;o<t.length;o++)t[o]&&N(t[o],u,\"function\"!=typeof n.type);i||null==n.__e||h(n.__e),n.__e=n.__d=void 0}function O(n,l,u){return this.constructor(n,u)}function S(u,i,t){var o,r,f;l.__&&l.__(u,i),r=(o=\"function\"==typeof t)?null:t&&t.__k||i.__k,f=[],j(i,u=(!o&&t||i).__k=v(d,null,[u]),r||e,e,void 0!==i.ownerSVGElement,!o&&t?[t]:r?null:i.firstChild?n.call(i.childNodes):null,f,!o&&t?t:r?r.__e:i.firstChild,o),z(f,u)}function q(n,l){S(n,l,q)}function B(l,u,i){var t,o,r,f=a({},l.props);for(r in u)\"key\"==r?t=u[r]:\"ref\"==r?o=u[r]:f[r]=u[r];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),y(l.type,f,t||l.key,o||l.ref,null)}function D(n,l){var u={__c:l=\"__cC\"+f++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,i;return this.getChildContext||(u=[],(i={})[l]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(m)},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n)}}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=c.slice,l={__e:function(n,l,u,i){for(var t,o,r;l=l.__;)if((t=l.__c)&&!t.__)try{if((o=t.constructor)&&null!=o.getDerivedStateFromError&&(t.setState(o.getDerivedStateFromError(n)),r=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),r=t.__d),r)return t.__E=t}catch(l){n=l}throw n}},u=0,i=function(n){return null!=n&&void 0===n.constructor},_.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=a({},this.state),\"function\"==typeof n&&(n=n(a({},u),this.props)),n&&a(u,n),null!=n&&this.__v&&(l&&this.__h.push(l),m(this))},_.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),m(this))},_.prototype.render=d,t=[],o=\"function\"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,g.__r=0,f=0;export{S as render,q as hydrate,v as createElement,v as h,d as Fragment,p as createRef,i as isValidElement,_ as Component,B as cloneElement,D as createContext,A as toChildArray,l as options};"
  },
  {
    "path": "extensions/github1s/package.json",
    "content": "{\n  \"name\": \"github1s\",\n  \"version\": \"0.0.0\",\n  \"publisher\": \"github1s\",\n  \"description\": \"\",\n  \"private\": true,\n  \"enabledApiProposals\": [\n    \"fileSearchProvider\",\n    \"textSearchProvider\",\n    \"resolvers\"\n  ],\n  \"directories\": {\n    \"lib\": \"lib\"\n  },\n  \"activationEvents\": [\n    \"onStartupFinished\",\n    \"onFileSystem:github1s\",\n    \"onFileSystem:gitlab1s\",\n    \"onFileSystem:bitbucket1s\",\n    \"onFileSystem:npmjs1s\",\n    \"onFileSystem:ossinsight\",\n    \"onCommand:remoteHub.openRepository\"\n  ],\n  \"browser\": \"./dist/extension\",\n  \"engines\": {\n    \"vscode\": \"^1.48.0\"\n  },\n  \"contributes\": {\n    \"viewsContainers\": {\n      \"activitybar\": [\n        {\n          \"id\": \"settings\",\n          \"title\": \"Settings\",\n          \"icon\": \"assets/settings.svg\"\n        }\n      ]\n    },\n    \"views\": {\n      \"settings\": [\n        {\n          \"id\": \"github1s.views.settings\",\n          \"name\": \"Settings\",\n          \"type\": \"webview\",\n          \"when\": \"github1s:views:settings:visible == true\"\n        }\n      ],\n      \"scm\": [\n        {\n          \"id\": \"github1s.views.fileHistory\",\n          \"name\": \"File History\",\n          \"when\": \"github1s:views:fileHistory:visible == true\"\n        },\n        {\n          \"id\": \"github1s.views.commitList\",\n          \"name\": \"Commits\",\n          \"when\": \"github1s:views:commitList:visible == true\"\n        },\n        {\n          \"id\": \"github1s.views.codeReviewList\",\n          \"name\": \"Code Reviews\",\n          \"when\": \"github1s:views:codeReviewList:visible == true\"\n        }\n      ]\n    },\n    \"commands\": [\n      {\n        \"command\": \"github1s.commands.openRepository\",\n        \"title\": \"Open Repository...\",\n        \"category\": \"GitHub1s\"\n      },\n      {\n        \"command\": \"github1s.commands.openOnlineEditor\",\n        \"title\": \"Open Online Editor...\",\n        \"category\": \"GitHub1s\"\n      },\n      {\n        \"command\": \"github1s.commands.checkoutTo\",\n        \"title\": \"Checkout to...\",\n        \"category\": \"GitHub1s\"\n      },\n      {\n        \"command\": \"github1s.commands.refreshCodeReviewList\",\n        \"title\": \"Refresh\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(refresh)\"\n      },\n      {\n        \"command\": \"github1s.commands.searchCodeReview\",\n        \"title\": \"Search\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(search)\"\n      },\n      {\n        \"command\": \"github1s.commands.switchToPullRequest\",\n        \"title\": \"Switch to Pull Request\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(log-in)\",\n        \"enablement\": \"github1s:adapters:default:codeReviewType == 'PullRequest'\"\n      },\n      {\n        \"command\": \"github1s.commands.switchToMergeRequest\",\n        \"title\": \"Switch to Merge Request\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(log-in)\",\n        \"enablement\": \"github1s:adapters:default:codeReviewType == 'MergeRequest'\"\n      },\n      {\n        \"command\": \"github1s.commands.switchToChangeRequest\",\n        \"title\": \"Switch to Change Request\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(log-in)\",\n        \"enablement\": \"github1s:adapters:default:codeReviewType == 'ChangeRequest'\"\n      },\n      {\n        \"command\": \"github1s.commands.switchToCodeReview\",\n        \"title\": \"Switch to Code Review\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(log-in)\",\n        \"enablement\": \"github1s:adapters:default:codeReviewType != 'PullRequest' && github1s:adapters:default:codeReviewType != 'MergeRequest' && github1s:adapters:default:codeReviewType != 'ChangeRequest'\"\n      },\n      {\n        \"command\": \"github1s.commands.openCodeReviewOnGitHub\",\n        \"title\": \"Open on GitHub\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'GitHub'\"\n      },\n      {\n        \"command\": \"github1s.commands.openCodeReviewOnGitLab\",\n        \"title\": \"Open on GitLab\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'GitLab'\"\n      },\n      {\n        \"command\": \"github1s.commands.openCodeReviewOnBitbucket\",\n        \"title\": \"Open on Bitbucket\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'Bitbucket'\"\n      },\n      {\n        \"command\": \"github1s.commands.openCodeReviewOnOfficialPage\",\n        \"title\": \"Open on Official Page\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket'\"\n      },\n      {\n        \"command\": \"github1s.commands.refreshFileHistoryCommitList\",\n        \"title\": \"Refresh\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(refresh)\"\n      },\n      {\n        \"command\": \"github1s.commands.refreshCommitList\",\n        \"title\": \"Refresh\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(refresh)\"\n      },\n      {\n        \"command\": \"github1s.commands.searchCommit\",\n        \"title\": \"Search\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(search)\"\n      },\n      {\n        \"command\": \"github1s.commands.switchToCommit\",\n        \"title\": \"Switch to Commit\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(log-in)\"\n      },\n      {\n        \"command\": \"github1s.commands.diffCommitFile\",\n        \"title\": \"Diff File\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(diff)\"\n      },\n      {\n        \"command\": \"github1s.commands.openCommitOnGitHub\",\n        \"title\": \"Open on GitHub\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'GitHub'\"\n      },\n      {\n        \"command\": \"github1s.commands.openCommitOnGitLab\",\n        \"title\": \"Open on GitLab\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'GitLab'\"\n      },\n      {\n        \"command\": \"github1s.commands.openCommitOnBitbucket\",\n        \"title\": \"Open on Bitbucket\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'Bitbucket'\"\n      },\n      {\n        \"command\": \"github1s.commands.openCommitOnOfficialPage\",\n        \"title\": \"Open on Official Page\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket'\"\n      },\n      {\n        \"command\": \"github1s.commands.diffChangedFile\",\n        \"title\": \"Open Changes\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(compare-changes)\"\n      },\n      {\n        \"command\": \"github1s.commands.diffViewOpenLeftFile\",\n        \"title\": \"Open Left File\",\n        \"category\": \"GitHub1s\",\n        \"icon\": {\n          \"dark\": \"assets/icons/dark/open-left-file.svg\",\n          \"light\": \"assets/icons/light/open-left-file.svg\"\n        },\n        \"enablement\": \"isInDiffEditor && resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/ && resource =~ /^(?![^?]*\\\\?[^#]*(%26|\\\\b)base(=|%3D|%3d)github1s-empty-file)/\"\n      },\n      {\n        \"command\": \"github1s.commands.diffViewOpenRightFile\",\n        \"title\": \"Open Right File\",\n        \"category\": \"GitHub1s\",\n        \"icon\": {\n          \"dark\": \"assets/icons/dark/open-right-file.svg\",\n          \"light\": \"assets/icons/light/open-right-file.svg\"\n        },\n        \"enablement\": \"isInDiffEditor && resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/ && resource =~ /^(?![^?]*\\\\?[^#]*(%26|\\\\b)head(=|%3D|%3d)github1s-empty-file)/\"\n      },\n      {\n        \"command\": \"github1s.commands.openFilePreviousRevision\",\n        \"title\": \"Open Previous Revision\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(arrow-left)\",\n        \"enablement\": \"resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)$/ && resource =~ /^(?![^?]*\\\\?[^#]*(%26|\\\\b)base(=|%3D|%3d)github1s-empty-file)/\"\n      },\n      {\n        \"command\": \"github1s.commands.openFileNextRevision\",\n        \"title\": \"Open Next Revision\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(arrow-right)\",\n        \"enablement\": \"resource =~ /^[^?]*\\\\?[^#]*(%26|\\\\b)hasNextRevision(=|%3D|%3d)true/\"\n      },\n      {\n        \"command\": \"github1s.commands.toggleEditorGutterBlame\",\n        \"title\": \"Toggle File Blame\",\n        \"category\": \"GitHub1s\",\n        \"enablement\": \"!isInDiffEditor\"\n      },\n      {\n        \"command\": \"github1s.commands.openEditorGutterBlame\",\n        \"title\": \"Toggle File Blame\",\n        \"category\": \"GitHub1s\",\n        \"icon\": {\n          \"dark\": \"assets/icons/dark/open-blame.svg\",\n          \"light\": \"assets/icons/light/open-blame.svg\"\n        },\n        \"enablement\": \"!isInDiffEditor\"\n      },\n      {\n        \"command\": \"github1s.commands.closeEditorGutterBlame\",\n        \"title\": \"Toggle File Blame\",\n        \"category\": \"GitHub1s\",\n        \"icon\": {\n          \"dark\": \"assets/icons/dark/close-blame.svg\",\n          \"light\": \"assets/icons/light/close-blame.svg\"\n        },\n        \"enablement\": \"!isInDiffEditor\"\n      },\n      {\n        \"command\": \"github1s.commands.openOnGitHub\",\n        \"title\": \"Open on GitHub\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'GitHub'\"\n      },\n      {\n        \"command\": \"github1s.commands.openOnGitLab\",\n        \"title\": \"Open on GitLab\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'GitLab'\"\n      },\n      {\n        \"command\": \"github1s.commands.openOnBitbucket\",\n        \"title\": \"Open on Bitbucket\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'Bitbucket'\"\n      },\n      {\n        \"command\": \"github1s.commands.openOnNpm\",\n        \"title\": \"Open on npm\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName == 'npm'\"\n      },\n      {\n        \"command\": \"github1s.commands.openOnOfficialPage\",\n        \"title\": \"Open on Official Page\",\n        \"category\": \"GitHub1s\",\n        \"icon\": \"$(globe)\",\n        \"enablement\": \"github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket' && github1s:adapters:default:platformName != 'npm'\"\n      }\n    ],\n    \"colors\": [\n      {\n        \"id\": \"github1s.colors.addedResourceForeground\",\n        \"description\": \"%colors.added%\",\n        \"defaults\": {\n          \"light\": \"#587c0c\",\n          \"dark\": \"#81b88b\",\n          \"highContrast\": \"#1b5225\"\n        }\n      },\n      {\n        \"id\": \"github1s.colors.deletedResourceForeground\",\n        \"description\": \"%colors.deleted%\",\n        \"defaults\": {\n          \"light\": \"#ad0707\",\n          \"dark\": \"#c74e39\",\n          \"highContrast\": \"#c74e39\"\n        }\n      },\n      {\n        \"id\": \"github1s.colors.modifiedResourceForeground\",\n        \"description\": \"%colors.modified%\",\n        \"defaults\": {\n          \"light\": \"#895503\",\n          \"dark\": \"#E2C08D\",\n          \"highContrast\": \"#E2C08D\"\n        }\n      },\n      {\n        \"id\": \"github1s.colors.submoduleResourceForeground\",\n        \"description\": \"%colors.submodule%\",\n        \"defaults\": {\n          \"light\": \"#1258a7\",\n          \"dark\": \"#8db9e2\",\n          \"highContrast\": \"#8db9e2\"\n        }\n      },\n      {\n        \"id\": \"github1s.colors.selectedViewItem\",\n        \"description\": \"selected view item color\",\n        \"defaults\": {\n          \"light\": \"#1890ff\",\n          \"dark\": \"#1890ff\",\n          \"highContrast\": \"#1890ff\"\n        }\n      },\n      {\n        \"id\": \"github1s.colors.gutterBlameBackground\",\n        \"description\": \"gutter blame background color\",\n        \"defaults\": {\n          \"light\": \"#00000013\",\n          \"dark\": \"#ffffff13\",\n          \"highContrast\": \"#ffffff13\"\n        }\n      },\n      {\n        \"id\": \"github1s.colors.highlightGutterBlameBackground\",\n        \"description\": \"highlight gutter blame background color\",\n        \"defaults\": {\n          \"light\": \"#00bcf233\",\n          \"dark\": \"#00bce233\",\n          \"highContrast\": \"#00bce233\"\n        }\n      }\n    ],\n    \"menus\": {\n      \"commandPalette\": [\n        {\n          \"command\": \"github1s.commands.refreshCodeReviewList\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.searchCodeReview\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnGitHub\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnGitLab\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnBitbucket\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnOfficialPage\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.refreshCommitList\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.searchCommit\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnGitHub\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnGitLab\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnBitbucket\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnOfficialPage\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.diffChangedFile\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.diffViewOpenLeftFile\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.diffViewOpenRightFile\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openFilePreviousRevision\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openFileNextRevision\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.openEditorGutterBlame\",\n          \"when\": \"false\"\n        },\n        {\n          \"command\": \"github1s.commands.closeEditorGutterBlame\",\n          \"when\": \"false\"\n        }\n      ],\n      \"view/title\": [\n        {\n          \"command\": \"github1s.commands.refreshCodeReviewList\",\n          \"when\": \"view == 'github1s.views.codeReviewList'\",\n          \"group\": \"navigation@1\"\n        },\n        {\n          \"command\": \"github1s.commands.searchCodeReview\",\n          \"when\": \"view == 'github1s.views.codeReviewList'\",\n          \"group\": \"navigation@2\"\n        },\n        {\n          \"command\": \"github1s.commands.refreshFileHistoryCommitList\",\n          \"when\": \"view == 'github1s.views.fileHistory'\",\n          \"group\": \"navigation@1\"\n        },\n        {\n          \"command\": \"github1s.commands.searchCommit\",\n          \"when\": \"view == 'github1s.views.fileHistory'\",\n          \"group\": \"navigation@2\"\n        },\n        {\n          \"command\": \"github1s.commands.refreshCommitList\",\n          \"when\": \"view == 'github1s.views.commitList'\",\n          \"group\": \"navigation@1\"\n        },\n        {\n          \"command\": \"github1s.commands.searchCommit\",\n          \"when\": \"view == 'github1s.views.commitList'\",\n          \"group\": \"navigation@2\"\n        }\n      ],\n      \"view/item/context\": [\n        {\n          \"command\": \"github1s.commands.switchToPullRequest\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:codeReviewType == 'PullRequest'\",\n          \"group\": \"inline@1\"\n        },\n        {\n          \"command\": \"github1s.commands.switchToMergeRequest\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:codeReviewType == 'MergeRequest'\",\n          \"group\": \"inline@1\"\n        },\n        {\n          \"command\": \"github1s.commands.switchToChangeRequest\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:codeReviewType == 'ChangeRequest'\",\n          \"group\": \"inline@1\"\n        },\n        {\n          \"command\": \"github1s.commands.switchToCodeReview\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:codeReviewType != 'PullRequest' && github1s:adapters:default:codeReviewType != 'MergeRequest' && github1s:adapters:default:codeReviewType != 'ChangeRequest'\",\n          \"group\": \"inline@1\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnGitHub\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:platformName == 'GitHub'\",\n          \"group\": \"inline@2\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnGitLab\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:platformName == 'GitLab'\",\n          \"group\": \"inline@2\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnBitbucket\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:platformName == 'Bitbucket'\",\n          \"group\": \"inline@2\"\n        },\n        {\n          \"command\": \"github1s.commands.openCodeReviewOnOfficialPage\",\n          \"when\": \"viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket' && github1s:adapters:default:platformName != 'npm'\",\n          \"group\": \"inline@2\"\n        },\n        {\n          \"command\": \"github1s.commands.switchToCommit\",\n          \"when\": \"viewItem == 'github1s:viewItems:commitListItem'\",\n          \"group\": \"inline@1\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnGitHub\",\n          \"when\": \"viewItem == 'github1s:viewItems:commitListItem' && github1s:adapters:default:platformName == 'GitHub'\",\n          \"group\": \"inline@2\"\n        },\n        {\n          \"command\": \"github1s.commands.diffCommitFile\",\n          \"when\": \"viewItem == 'github1s:viewItems:commitListItem' && view == 'github1s.views.fileHistory'\",\n          \"group\": \"inline@3\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnGitLab\",\n          \"when\": \"viewItem == 'github1s:viewItems:commitListItem' && github1s:adapters:default:platformName == 'GitLab'\",\n          \"group\": \"inline@2\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnBitbucket\",\n          \"when\": \"viewItem == 'github1s:viewItems:commitListItem' && github1s:adapters:default:platformName == 'Bitbucket'\",\n          \"group\": \"inline@2\"\n        },\n        {\n          \"command\": \"github1s.commands.openCommitOnOfficialPage\",\n          \"when\": \"viewItem == 'github1s:viewItems:commitListItem' && github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket' && github1s:adapters:default:platformName != 'npm'\",\n          \"group\": \"inline@2\"\n        }\n      ],\n      \"editor/title\": [\n        {\n          \"command\": \"github1s.commands.diffChangedFile\",\n          \"when\": \"!isInDiffEditor && github1s:editors:showDiffChangedFile\",\n          \"group\": \"navigation@1\"\n        },\n        {\n          \"command\": \"github1s.commands.diffViewOpenLeftFile\",\n          \"when\": \"isInDiffEditor\",\n          \"group\": \"navigation@2\"\n        },\n        {\n          \"command\": \"github1s.commands.diffViewOpenRightFile\",\n          \"when\": \"isInDiffEditor\",\n          \"group\": \"navigation@3\"\n        },\n        {\n          \"command\": \"github1s.commands.openFilePreviousRevision\",\n          \"when\": \"resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/\",\n          \"group\": \"navigation@4\"\n        },\n        {\n          \"command\": \"github1s.commands.openFileNextRevision\",\n          \"when\": \"resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/\",\n          \"group\": \"navigation@5\"\n        },\n        {\n          \"command\": \"github1s.commands.openEditorGutterBlame\",\n          \"when\": \"!isInDiffEditor && github1s:features:gutterBlame:enabled && !github1s:features:gutterBlame:open\",\n          \"group\": \"navigation@6\"\n        },\n        {\n          \"command\": \"github1s.commands.closeEditorGutterBlame\",\n          \"when\": \"!isInDiffEditor && github1s:features:gutterBlame:enabled && github1s:features:gutterBlame:open\",\n          \"group\": \"navigation@6\"\n        }\n      ]\n    }\n  },\n  \"scripts\": {\n    \"clean\": \"rm -rf dist out\",\n    \"watch\": \"webpack --config webpack.config.js --watch\",\n    \"compile\": \"webpack --config webpack.config.js --mode production\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@apollo/client\": \"^3.12.5\",\n    \"@octokit/core\": \"^6.1.4\",\n    \"dayjs\": \"^1.11.1\",\n    \"graphql\": \"^16.8.1\",\n    \"history\": \"^5.3.0\",\n    \"js-base64\": \"^3.7.2\",\n    \"json-stable-stringify\": \"^1.0.1\",\n    \"match-sorter\": \"^6.3.1\",\n    \"p-finally\": \"^3.0.0\",\n    \"process\": \"^0.11.10\",\n    \"query-string\": \"^7.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/vscode\": \"^1.96.0\",\n    \"node-polyfill-webpack-plugin\": \"^1.1.4\",\n    \"ts-loader\": \"^9.2.8\",\n    \"typescript\": \"^5.7.3\",\n    \"webpack\": \"^5.105.0\",\n    \"webpack-cli\": \"^4.9.2\"\n  }\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/bitbucket1s/index.ts",
    "content": "/**\n * @file Bitbucket adapter\n * @author netcon\n */\n\nimport { BitbucketRouterParser } from './router-parser';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\nimport { Adapter, CodeReviewType, PlatformName } from '../types';\nimport { setVSCodeContext } from '@/helpers/vscode';\n\nexport class BitbucketAdapter implements Adapter {\n\tpublic scheme: string = 'bitbucket1s';\n\tpublic platformName = PlatformName.Bitbucket;\n\tpublic codeReviewType = CodeReviewType.PullRequest;\n\n\tresolveDataSource() {\n\t\treturn Promise.resolve(SourcegraphDataSource.getInstance('bitbucket'));\n\t}\n\n\tresolveRouterParser() {\n\t\treturn Promise.resolve(BitbucketRouterParser.getInstance());\n\t}\n\n\tactivateAsDefault() {\n\t\tsetVSCodeContext('github1s:views:commitList:visible', true);\n\t\tsetVSCodeContext('github1s:views:fileHistory:visible', true);\n\t\tsetVSCodeContext('github1s:features:gutterBlame:enabled', true);\n\t}\n\n\tdeactivateAsDefault() {\n\t\tsetVSCodeContext('github1s:views:commitList:visible', false);\n\t\tsetVSCodeContext('github1s:views:fileHistory:visible', false);\n\t\tsetVSCodeContext('github1s:features:gutterBlame:enabled', false);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/bitbucket1s/parse-path.ts",
    "content": "/**\n * @file parse bitbucket path\n * @author netcon\n */\n\nimport { parsePath } from 'history';\nimport { FileType, PageType, RouterState } from '@/adapters/types';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\n\nconst parseTreeOrBlobUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType, ...restParts] = pathParts;\n\tconst repoFullName = `${owner}/${repo}`;\n\tconst dataSource = SourcegraphDataSource.getInstance('bitbucket');\n\tconst { ref, path: filePath } = await dataSource.extractRefPath(repoFullName, restParts.join('/'));\n\tconst fileType = await dataSource.detectPathFileType(repo, ref, filePath);\n\n\treturn { pageType: fileType === FileType.Directory ? PageType.Tree : PageType.Blob, repo, ref, filePath };\n};\n\nconst parseCommitsUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType, ...refParts] = pathParts;\n\n\treturn {\n\t\trepo: `${owner}/${repo}`,\n\t\tpageType: PageType.CommitList,\n\t\tref: refParts.length ? refParts.join('/') : 'HEAD',\n\t};\n};\n\nconst parseCommitUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType, ...refParts] = pathParts;\n\tconst commitSha = refParts.join('/');\n\n\treturn { repo: `${owner}/${repo}`, pageType: PageType.Commit, ref: commitSha, commitSha };\n};\n\nconst PAGE_TYPE_MAP = {\n\tsrc: PageType.Tree,\n\tcommit: PageType.Commit,\n\tcommits: PageType.CommitList,\n};\n\nexport const parseBitbucketPath = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname?.split('/').filter(Boolean) || [];\n\t// detect concrete PageType the *third part* in url.path\n\tconst pageType = pathParts[2] ? PAGE_TYPE_MAP[pathParts[2]] || PageType.Unknown : PageType.Tree;\n\n\tif (pathParts.length >= 2) {\n\t\tswitch (pageType) {\n\t\t\tcase PageType.Tree:\n\t\t\t\treturn parseTreeOrBlobUrl(path);\n\t\t\tcase PageType.Commit:\n\t\t\t\treturn parseCommitUrl(path);\n\t\t\tcase PageType.CommitList:\n\t\t\t\treturn parseCommitsUrl(path);\n\t\t}\n\t}\n\n\t// fallback to default\n\treturn {\n\t\trepo: 'atlassian/clover',\n\t\tref: 'HEAD',\n\t\tpageType: PageType.Tree,\n\t\tfilePath: '',\n\t};\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/bitbucket1s/router-parser.ts",
    "content": "/**\n * @file router parser\n * @author netcon\n */\n\nimport * as adapterTypes from '../types';\nimport { parseBitbucketPath } from './parse-path';\n\nexport class BitbucketRouterParser extends adapterTypes.RouterParser {\n\tprivate static instance: BitbucketRouterParser | null = null;\n\n\tpublic static getInstance(): BitbucketRouterParser {\n\t\tif (BitbucketRouterParser.instance) {\n\t\t\treturn BitbucketRouterParser.instance;\n\t\t}\n\t\treturn (BitbucketRouterParser.instance = new BitbucketRouterParser());\n\t}\n\n\tparsePath(path: string): Promise<adapterTypes.RouterState> {\n\t\treturn parseBitbucketPath(path);\n\t}\n\n\tbuildTreePath(repo: string, ref?: string, filePath?: string): string {\n\t\treturn ref ? (filePath ? `/${repo}/src/${ref}/${filePath}` : `/${repo}/src/${ref}`) : `/${repo}`;\n\t}\n\n\tbuildBlobPath(repo: string, ref: string, filePath: string, startLine?: number, endLine?: number): string {\n\t\tconst hash = startLine ? (endLine ? `#L${startLine}-L${endLine}` : `#L${startLine}`) : '';\n\t\treturn `/${repo}/src/${ref}/${filePath}${hash}`;\n\t}\n\n\tbuildCommitListPath(repo: string): string {\n\t\treturn `/${repo}/commits`;\n\t}\n\n\tbuildCommitPath(repo: string, commitSha: string): string {\n\t\treturn `/${repo}/commits/${commitSha}`;\n\t}\n\n\tbuildCodeReviewListPath(repo: string): string {\n\t\treturn `/${repo}/pull-requests`;\n\t}\n\n\tbuildCodeReviewPath(repo: string, codeReviewId: string): string {\n\t\treturn `/${repo}/pull-requests/${codeReviewId}`;\n\t}\n\n\tbuildExternalLink(path: string): string {\n\t\treturn 'https://bitbucket.org' + (path.startsWith('/') ? path : `/${path}`);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/authentication.ts",
    "content": "/**\n * @file github authentication page\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { Barrier } from '@/helpers/async';\nimport { getExtensionContext } from '@/helpers/context';\nimport { createPageHtml, getWebviewOptions } from '@/helpers/page';\nimport { GitHubTokenManager } from './token';\nimport { messageApiMap } from './settings';\n\nexport class GitHub1sAuthenticationView {\n\tprotected static instance: GitHub1sAuthenticationView | null = null;\n\tpublic static viewType = 'github1s.views.github1s-authentication';\n\tprotected tokenManager = GitHubTokenManager.getInstance();\n\tprivate webviewPanel: vscode.WebviewPanel | null = null;\n\t// using for waiting token\n\tprivate tokenBarrier: Barrier | null = null;\n\t// using for displaying open page reason\n\tprivate notice: string = '';\n\n\tprotected pageTitle = 'Authenticating to GitHub';\n\tprotected OAuthCommand = 'github1s.commands.vscode.connectToGitHub';\n\tprotected pageConfig: Record<string, unknown> = {\n\t\tauthenticationFormTitle: 'Authenticating to GitHub',\n\t\tOAuthButtonText: 'Connect to GitHub',\n\t\tOAuthButtonLogo: 'assets/pages/assets/github.svg',\n\t\tcreateTokenLink: `${GITHUB_ORIGIN}/settings/tokens/new?scopes=repo&description=GitHub1s`,\n\t\trateLimitDocLink: 'https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting',\n\t\trateLimitDocLinkText: 'GitHub Rate limiting Documentation',\n\t\tauthenticationFeatures: [\n\t\t\t{\n\t\t\t\ttext: 'Access GitHub personal repository',\n\t\t\t\tlink: 'https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-user-account/managing-access-to-your-personal-repositories',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttext: 'Higher rate limit for GitHub official API',\n\t\t\t\tlink: 'https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttext: 'Support for GitHub GraphQL API',\n\t\t\t\tlink: 'https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#authenticating-with-graphql',\n\t\t\t},\n\t\t],\n\t};\n\n\tprotected constructor() {}\n\n\tpublic static getInstance(): GitHub1sAuthenticationView {\n\t\tif (GitHub1sAuthenticationView.instance) {\n\t\t\treturn GitHub1sAuthenticationView.instance;\n\t\t}\n\t\treturn (GitHub1sAuthenticationView.instance = new this());\n\t}\n\n\tprivate registerListeners() {\n\t\tif (!this.webviewPanel) {\n\t\t\tthrow new Error('webview is not init yet');\n\t\t}\n\n\t\tthis.webviewPanel.webview.onDidReceiveMessage((message) => {\n\t\t\tconst commonResponse = { id: message.id, type: message.type };\n\t\t\tconst postMessage = (data?: unknown) => this.webviewPanel!.webview.postMessage({ ...commonResponse, data });\n\n\t\t\tswitch (message.type) {\n\t\t\t\tcase 'get-notice':\n\t\t\t\t\tpostMessage(this.notice);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'get-token':\n\t\t\t\t\tpostMessage(this.tokenManager.getToken());\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'set-token':\n\t\t\t\t\tmessage.data && (this.notice = '');\n\t\t\t\t\tthis.tokenManager.setToken(message.data || '').then(() => postMessage());\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'validate-token':\n\t\t\t\t\tthis.tokenManager.validateToken(message.data).then((tokenStatus) => postMessage(tokenStatus));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'oauth-authorizing':\n\t\t\t\t\tvscode.commands.executeCommand(this.OAuthCommand).then((data: any) => {\n\t\t\t\t\t\tif (data && data.error_description) {\n\t\t\t\t\t\t\tvscode.window.showErrorMessage(data.error_description);\n\t\t\t\t\t\t} else if (data && data.access_token) {\n\t\t\t\t\t\t\tthis.tokenManager.setToken(data.access_token || '').then(() => postMessage());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpostMessage();\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'call-vscode-message-api':\n\t\t\t\t\tconst messageApi = messageApiMap[message.data?.level];\n\t\t\t\t\tmessageApi && messageApi(...message.data?.args).then((response) => postMessage(response));\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\n\t\tthis.tokenManager.onDidChangeToken((token) => {\n\t\t\tthis.tokenBarrier && this.tokenBarrier.open();\n\t\t\tthis.tokenBarrier && (this.tokenBarrier = null);\n\t\t\tthis.webviewPanel?.webview.postMessage({ type: 'token-changed', token });\n\t\t});\n\t}\n\n\tpublic open(notice: string = '', withBarrier = false) {\n\t\tconst extensionContext = getExtensionContext();\n\n\t\tthis.notice = notice;\n\t\twithBarrier && !this.tokenBarrier && (this.tokenBarrier = new Barrier(600 * 1000));\n\n\t\tif (!this.webviewPanel) {\n\t\t\tthis.webviewPanel = vscode.window.createWebviewPanel(\n\t\t\t\tGitHub1sAuthenticationView.viewType,\n\t\t\t\tthis.pageTitle,\n\t\t\t\tvscode.ViewColumn.One,\n\t\t\t\tgetWebviewOptions(extensionContext.extensionUri),\n\t\t\t);\n\t\t\tthis.registerListeners();\n\t\t\tthis.webviewPanel.onDidDispose(() => (this.webviewPanel = null));\n\t\t}\n\n\t\tconst styles = [\n\t\t\tvscode.Uri.joinPath(extensionContext.extensionUri, 'assets/pages/components.css').toString(),\n\t\t\tvscode.Uri.joinPath(extensionContext.extensionUri, 'assets/pages/github1s-authentication.css').toString(),\n\t\t];\n\t\tconst globalPageConfig = { ...this.pageConfig, extensionUri: extensionContext.extensionUri.toString() };\n\t\tconst scripts = [\n\t\t\t'data:text/javascript;base64,' +\n\t\t\t\tBuffer.from(`window.pageConfig=${JSON.stringify(globalPageConfig)};`).toString('base64'),\n\t\t\tvscode.Uri.joinPath(extensionContext.extensionUri, 'assets/pages/github1s-authentication.js').toString(),\n\t\t];\n\n\t\tconst webview = this.webviewPanel.webview;\n\t\twebview.html = createPageHtml(this.pageTitle, styles, scripts);\n\t\treturn withBarrier ? this.tokenBarrier!.wait() : Promise.resolve();\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/data-source.ts",
    "content": "/**\n * @file github1s data-source-provider\n * @author netcon\n */\n\nimport {\n\tBranch,\n\tCodeReview,\n\tCodeReviewState,\n\tTextSearchOptions,\n\tCommit,\n\tCommonQueryOptions,\n\tDataSource,\n\tDirectory,\n\tDirectoryEntry,\n\tFile,\n\tBlameRange,\n\tFileType,\n\tTag,\n\tTextSearchResults,\n\tTextSearchQuery,\n\tSymbolDefinitions,\n\tSymbolReferences,\n\tFileChangeStatus,\n\tChangedFile,\n\tSymbolHover,\n\tCommitsQueryOptions,\n\tCodeReviewsQueryOptions,\n} from '../types';\nimport { toUint8Array } from 'js-base64';\nimport { matchSorter } from 'match-sorter';\nimport { FILE_BLAME_QUERY } from './graphql';\nimport { GitHubFetcher } from './fetcher';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\nimport { decorate, memorize } from '@/helpers/func';\n\nconst parseRepoFullName = (repoFullName: string) => {\n\tconst [owner, repo] = repoFullName.split('/');\n\treturn { owner, repo };\n};\n\nconst encodeFilePath = (filePath: string): string => {\n\tconst pathParts = filePath.split('/').filter(Boolean);\n\treturn pathParts.map((segment) => encodeURIComponent(segment)).join('/');\n};\n\nconst FileTypeMap = {\n\tblob: FileType.File,\n\ttree: FileType.Directory,\n\tcommit: FileType.Submodule,\n};\n\nconst getPullState = (pull: { state: string; merged_at: string | null }): CodeReviewState => {\n\t// current pull request is open\n\tif (pull.state === 'open') {\n\t\treturn CodeReviewState.Open;\n\t}\n\t// current pull request is merged\n\tif (pull.state === 'closed' && pull.merged_at) {\n\t\treturn CodeReviewState.Merged;\n\t}\n\t// current pull is closed\n\treturn CodeReviewState.Closed;\n};\n\nconst sourcegraphDataSource = SourcegraphDataSource.getInstance('github');\nconst trySourcegraphApiFirst = (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => {\n\tconst originalMethod = descriptor.value;\n\n\tdescriptor.value = async function <T extends (...args) => Promise<any>>(...args: Parameters<T>) {\n\t\tconst githubFetcher = GitHubFetcher.getInstance();\n\t\tif (await githubFetcher.getPreferSourcegraphApi(args[0])) {\n\t\t\ttry {\n\t\t\t\treturn await sourcegraphDataSource[propertyKey](...args);\n\t\t\t} catch (e) {}\n\t\t}\n\t\treturn originalMethod.apply(this, args);\n\t};\n};\n\nexport class GitHub1sDataSource extends DataSource {\n\tprivate static instance: GitHub1sDataSource | null = null;\n\tprivate branchesPromiseMap: Map<string, Promise<Branch[]>> = new Map();\n\tprivate tagsPromiseMap: Map<string, Promise<Tag[]>> = new Map();\n\tprivate refPathPromiseMap: Map<string, Promise<{ ref: string; path: string }>> = new Map();\n\tprivate matchedRefsMap = new Map<string, string[]>();\n\n\tpublic static getInstance(): GitHub1sDataSource {\n\t\tif (GitHub1sDataSource.instance) {\n\t\t\treturn GitHub1sDataSource.instance;\n\t\t}\n\t\treturn (GitHub1sDataSource.instance = new GitHub1sDataSource());\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideRepository(repoFullName: string): Promise<{ private: boolean; defaultBranch: string } | null> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst requestParams = { owner, repo };\n\t\tconst response = await fetcher.request('GET /repos/{owner}/{repo}', requestParams).catch(() => null);\n\t\treturn response?.data ? { private: response.data.private, defaultBranch: response.data.default_branch } : null;\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideDirectory(repoFullName: string, ref: string, path: string, recursive = false): Promise<Directory> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst encodedPath = encodeFilePath(path);\n\t\t// github api will return all files if `recursive` exists, even the value if false\n\t\tconst recursiveParams = recursive ? { recursive } : {};\n\t\tconst requestParams = { ref, path: encodedPath, ...parseRepoFullName(repoFullName), ...recursiveParams };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/git/trees/{ref}:{path}', requestParams);\n\t\tconst parseTreeItem = (treeItem): DirectoryEntry => ({\n\t\t\tpath: treeItem.path,\n\t\t\ttype: FileTypeMap[treeItem.type] || FileType.File,\n\t\t\tcommitSha: FileTypeMap[treeItem.type] === FileType.Submodule ? treeItem.sha || 'HEAD' : undefined,\n\t\t\tsize: treeItem.size,\n\t\t});\n\n\t\treturn {\n\t\t\tentries: (data.tree || []).map(parseTreeItem),\n\t\t\ttruncated: !!data.truncated,\n\t\t};\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideFile(repoFullName: string, ref: string, path: string): Promise<File> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst requestParams = { owner, repo, ref, path };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/contents/{path}', requestParams);\n\t\treturn { content: toUint8Array((data as any).content) };\n\t}\n\n\tasync getMatchingRefs(repoFullName: string, ref: 'heads' | 'tags'): Promise<Branch[] | Tag[]> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst requestParams = { owner, repo, ref };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/git/matching-refs/{ref}', requestParams);\n\t\treturn data.map((item) => ({\n\t\t\tname: item.ref.slice(ref === 'heads' ? 11 : 10),\n\t\t\tcommitSha: item.object.sha,\n\t\t\tdescription: `${ref === 'heads' ? 'Branch' : 'Tag'} at ${item.object.sha.slice(0, 8)}`,\n\t\t}));\n\t}\n\n\t@decorate(memorize)\n\tasync getDefaultBranch(repoFullName: string) {\n\t\treturn (await this.provideRepository(repoFullName))?.defaultBranch || 'HEAD';\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync extractRefPath(repoFullName: string, refAndPath: string): Promise<{ ref: string; path: string }> {\n\t\tif (!this.matchedRefsMap.has(repoFullName)) {\n\t\t\tthis.matchedRefsMap.set(repoFullName, []);\n\t\t}\n\t\tconst matchPathRef = (ref) => refAndPath.startsWith(`${ref}/`) || refAndPath === ref;\n\t\tconst matchedRef = this.matchedRefsMap.get(repoFullName)?.find(matchPathRef);\n\t\tif (matchedRef) {\n\t\t\treturn { ref: matchedRef, path: refAndPath.slice(matchedRef.length + 1) };\n\t\t}\n\t\tconst mapKey = `${repoFullName} ${refAndPath}`;\n\t\tif (!this.refPathPromiseMap.has(mapKey)) {\n\t\t\tconst refPathPromise = new Promise<{ ref: string; path: string }>(async (resolve, reject) => {\n\t\t\t\tif (!refAndPath) {\n\t\t\t\t\treturn resolve({ ref: await this.getDefaultBranch(repoFullName), path: '' });\n\t\t\t\t}\n\t\t\t\tif (refAndPath.match(/^HEAD(\\/.*)?$/i)) {\n\t\t\t\t\treturn resolve({ ref: 'HEAD', path: refAndPath.slice(5) });\n\t\t\t\t}\n\n\t\t\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\t\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\t\t\tconst requestParams = { owner, repo, refAndPath };\n\t\t\t\tconst requestUrl = `GET /repos/{owner}/{repo}/git/extract-ref/{refAndPath}`;\n\t\t\t\tconst response = await fetcher.request(requestUrl, requestParams).catch(reject);\n\t\t\t\tresponse?.data?.ref && this.matchedRefsMap.get(repoFullName)?.push(response.data.ref);\n\t\t\t\treturn resolve(response?.data || { ref: 'HEAD', path: '' });\n\t\t\t});\n\t\t\tthis.refPathPromiseMap.set(mapKey, refPathPromise);\n\t\t}\n\t\treturn this.refPathPromiseMap.get(mapKey)!;\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideBranches(repoFullName: string, options?: CommonQueryOptions): Promise<Branch[]> {\n\t\tif (!this.branchesPromiseMap.has(repoFullName)) {\n\t\t\tthis.branchesPromiseMap.set(repoFullName, this.getMatchingRefs(repoFullName, 'heads'));\n\t\t}\n\t\treturn this.branchesPromiseMap.get(repoFullName)!.then((branches) => {\n\t\t\tconst matchOptions = { keys: ['name'] };\n\t\t\tconst matchedBranches = options?.query ? matchSorter(branches, options.query, matchOptions) : branches;\n\t\t\tif (options?.pageSize) {\n\t\t\t\tconst page = options.page || 1;\n\t\t\t\tconst pageSize = options.pageSize;\n\t\t\t\treturn matchedBranches.slice(pageSize * (page - 1), pageSize * page);\n\t\t\t}\n\t\t\treturn matchedBranches;\n\t\t});\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideBranch(repoFullName: string, branchName: string): Promise<Branch | null> {\n\t\tconst branches = await this.provideBranches(repoFullName);\n\t\treturn branches.find((item) => item.name === branchName) || null;\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideTags(repoFullName: string, options?: CommonQueryOptions): Promise<Tag[]> {\n\t\tif (!this.tagsPromiseMap.has(repoFullName)) {\n\t\t\tthis.tagsPromiseMap.set(repoFullName, this.getMatchingRefs(repoFullName, 'tags'));\n\t\t}\n\t\treturn this.tagsPromiseMap.get(repoFullName)!.then((tags) => {\n\t\t\tconst matchOptions = { keys: ['name'] };\n\t\t\tconst matchedTags = options?.query ? matchSorter(tags, options.query, matchOptions) : tags;\n\t\t\tif (options?.pageSize) {\n\t\t\t\tconst page = options.page || 1;\n\t\t\t\tconst pageSize = options.pageSize;\n\t\t\t\treturn matchedTags.slice(pageSize * (page - 1), pageSize * page);\n\t\t\t}\n\t\t\treturn matchedTags;\n\t\t});\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideTag(repoFullName: string, tagName: string): Promise<Tag | null> {\n\t\tconst tags = await this.provideTags(repoFullName);\n\t\treturn tags.find((item) => item.name === tagName) || null;\n\t}\n\n\tasync provideTextSearchResults(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tquery: TextSearchQuery,\n\t\toptions: TextSearchOptions,\n\t): Promise<TextSearchResults> {\n\t\treturn sourcegraphDataSource.provideTextSearchResults(repoFullName, ref, query, options);\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideCommits(\n\t\trepoFullName: string,\n\t\toptions?: CommitsQueryOptions,\n\t): Promise<(Commit & { files?: ChangedFile[] })[]> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst queryParams = {\n\t\t\tpage: options?.page,\n\t\t\tper_page: options?.pageSize,\n\t\t\tsha: options?.from,\n\t\t\tpath: options?.path,\n\t\t\tauthor: options?.author,\n\t\t};\n\t\tconst requestParams = { owner, repo, ...queryParams };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/commits', requestParams);\n\t\treturn data.map((item) => ({\n\t\t\tsha: item.sha,\n\t\t\tauthor: item.commit.author?.name,\n\t\t\temail: item.commit.author?.email,\n\t\t\tmessage: item.commit.message,\n\t\t\tcommitter: item.commit.committer?.name,\n\t\t\tcreateTime: item.commit.author?.date ? new Date(item.commit.author.date) : undefined,\n\t\t\tparents: item.parents.map((parent) => parent.sha) || [],\n\t\t\tavatarUrl: item.author?.avatar_url,\n\t\t}));\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideCommit(repoFullName: string, ref: string): Promise<Commit & { files?: ChangedFile[] }> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst requestParams = { owner, repo, ref };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/commits/{ref}', requestParams);\n\t\treturn {\n\t\t\tsha: data.sha,\n\t\t\tauthor: data.commit.author?.name,\n\t\t\temail: data.commit.author?.email,\n\t\t\tmessage: data.commit.message,\n\t\t\tcommitter: data.commit.committer?.name,\n\t\t\tcreateTime: data.commit.author?.date ? new Date(data.commit.author.date) : undefined,\n\t\t\tparents: data.parents.map((parent) => parent.sha) || [],\n\t\t\tfiles: data.files?.map((item) => ({\n\t\t\t\tpath: item.filename || item.previous_filename!,\n\t\t\t\tpreviousPath: item.previous_filename,\n\t\t\t\tstatus: item.status as FileChangeStatus,\n\t\t\t})),\n\t\t\tavatarUrl: data.author?.avatar_url,\n\t\t};\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideCommitChangedFiles(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\t_options?: CommonQueryOptions,\n\t): Promise<ChangedFile[]> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst requestParams = { owner, repo, ref };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/commits/{ref}', requestParams);\n\t\treturn (\n\t\t\tdata.files?.map((item) => ({\n\t\t\t\tpath: item.filename || item.previous_filename!,\n\t\t\t\tpreviousPath: item.previous_filename,\n\t\t\t\tstatus: item.status as FileChangeStatus,\n\t\t\t})) || []\n\t\t);\n\t}\n\n\tasync provideCodeReviews(\n\t\trepoFullName: string,\n\t\toptions?: CodeReviewsQueryOptions,\n\t): Promise<(CodeReview & { files?: ChangedFile[] })[]> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst state = options?.state ? (options.state === CodeReviewState.Open ? 'open' : 'closed') : 'all';\n\t\tconst queryParams = { state, page: options?.page, per_page: options?.pageSize, creator: options?.creator };\n\t\tconst requestParams = { owner, repo, ...queryParams };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/pulls', requestParams as any);\n\n\t\treturn data.map((item) => ({\n\t\t\tid: `${item.number}`,\n\t\t\ttitle: item.title,\n\t\t\tstate: getPullState(item),\n\t\t\tcreator: item.user?.login,\n\t\t\tcreateTime: new Date(item.created_at),\n\t\t\tmergeTime: item.merged_at ? new Date(item.merged_at) : null,\n\t\t\tcloseTime: item.closed_at ? new Date(item.closed_at) : null,\n\t\t\tsource: item.head.label,\n\t\t\ttarget: item.base.label,\n\t\t\tsourceSha: item.head.sha,\n\t\t\ttargetSha: item.base.sha,\n\t\t\tavatarUrl: item.user?.avatar_url,\n\t\t}));\n\t}\n\n\tasync provideCodeReview(repoFullName: string, id: string) {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst pullRequestParams = { owner, repo, pull_number: Number(id) };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/pulls/{pull_number}', pullRequestParams);\n\n\t\treturn {\n\t\t\tid: `${data.number}`,\n\t\t\ttitle: data.title,\n\t\t\tstate: getPullState(data),\n\t\t\tcreator: data.user?.login,\n\t\t\tcreateTime: new Date(data.created_at),\n\t\t\tmergeTime: data.merged_at ? new Date(data.merged_at) : null,\n\t\t\tcloseTime: data.closed_at ? new Date(data.closed_at) : null,\n\t\t\tsource: data.head.label,\n\t\t\ttarget: data.base.label,\n\t\t\tsourceSha: data.head.sha,\n\t\t\ttargetSha: data.base.sha,\n\t\t\tavatarUrl: data.user?.avatar_url,\n\t\t};\n\t}\n\n\tasync provideCodeReviewChangedFiles(\n\t\trepoFullName: string,\n\t\tid: string,\n\t\toptions?: CommonQueryOptions,\n\t): Promise<ChangedFile[]> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst pageParams = { per_page: options?.pageSize, page: options?.page };\n\t\tconst filesRequestParams = { owner, repo, pull_number: Number(id), ...pageParams };\n\t\tconst { data } = await fetcher.request('GET /repos/{owner}/{repo}/pulls/{pull_number}/files', filesRequestParams);\n\n\t\treturn data.map((item) => ({\n\t\t\tpath: item.filename,\n\t\t\tpreviousPath: item.previous_filename,\n\t\t\tstatus: item.status as FileChangeStatus,\n\t\t}));\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideFileBlameRanges(repoFullName: string, ref: string, path: string): Promise<BlameRange[]> {\n\t\tconst fetcher = GitHubFetcher.getInstance();\n\t\tconst { owner, repo } = parseRepoFullName(repoFullName);\n\t\tconst requestParams = { owner, repo, ref, path };\n\t\tconst data = await fetcher.graphql(FILE_BLAME_QUERY, requestParams);\n\t\tconst blameRanges = (data as any)?.repository?.object?.blame?.ranges;\n\n\t\treturn (blameRanges || []).map((item) => ({\n\t\t\tage: item.age as number,\n\t\t\tstartingLine: item.startingLine as number,\n\t\t\tendingLine: item.endingLine as number,\n\t\t\tcommit: {\n\t\t\t\tsha: item.commit?.sha as string,\n\t\t\t\tauthor: item.commit?.author?.name as string,\n\t\t\t\temail: item.commit?.author?.email as string,\n\t\t\t\tmessage: item.commit?.message as string,\n\t\t\t\tcreateTime: new Date(item.commit?.authoredDate),\n\t\t\t\tavatarUrl: item.commit?.author?.avatarUrl as string,\n\t\t\t},\n\t\t}));\n\t}\n\n\tprovideSymbolDefinitions(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promise<SymbolDefinitions> {\n\t\treturn sourcegraphDataSource.provideSymbolDefinitions(repoFullName, ref, path, line, character, symbol);\n\t}\n\n\tasync provideSymbolReferences(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promise<SymbolReferences> {\n\t\treturn sourcegraphDataSource.provideSymbolReferences(repoFullName, ref, path, line, character, symbol);\n\t}\n\n\tasync provideSymbolHover(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\t_symbol: string,\n\t): Promise<SymbolHover | null> {\n\t\treturn sourcegraphDataSource.provideSymbolHover(repoFullName, ref, path, line, character, _symbol);\n\t}\n\n\tprovideUserAvatarLink(user: string): string {\n\t\treturn `${GITHUB_ORIGIN}/${user}.png`;\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/fetcher.ts",
    "content": "/**\n * @file github api fetcher base octokit\n * @author netcon\n */\n\n(self as any).global = self;\nimport * as vscode from 'vscode';\nimport { getExtensionContext } from '@/helpers/context';\nimport { Octokit } from '@octokit/core';\nimport { GitHub1sAuthenticationView } from './authentication';\nimport { GitHubTokenManager } from './token';\nimport { isNil } from '@/helpers/util';\nimport { getCurrentRepo } from './parse-path';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\n\nexport const errorMessages = {\n\trateLimited: {\n\t\tanonymous: 'API Rate Limit Exceeded, please authenticate to github and retry',\n\t\tauthenticated: 'API Rate Limit Exceeded for this token, please try another account',\n\t},\n\tbadCredentials: {\n\t\tanonymous: 'Bad credentials, please authenticate to github and retry',\n\t\tauthenticated: 'This token is invalid, please try another one',\n\t},\n\trepoNotFound: {\n\t\tanonymous: 'Repository not found, if it is private, you can provide an AccessToken to access it',\n\t\tauthenticated: 'Repository not found, if it is private, you can try change an AccessToken to access it',\n\t},\n\tnoPermission: {\n\t\tanonymous: 'You have no permission for this operation, please authenticate to github and retry',\n\t\tauthenticated: 'You have no permission for this operation, please try another account',\n\t},\n};\n\nconst detectErrorMessage = (response: any, authenticated: boolean) => {\n\tif (response?.status === 403 && +response?.headers?.['x-ratelimit-remaining'] === 0) {\n\t\treturn errorMessages.rateLimited[authenticated ? 'authenticated' : 'anonymous'];\n\t}\n\tif (response?.status === 401 && response?.data?.message?.includes?.('Bad credentials')) {\n\t\treturn errorMessages.badCredentials[authenticated ? 'authenticated' : 'anonymous'];\n\t}\n\tif (response?.status === 404) {\n\t\treturn errorMessages.repoNotFound[authenticated ? 'authenticated' : 'anonymous'];\n\t}\n\tif (response?.status === 403) {\n\t\treturn errorMessages.noPermission[authenticated ? 'authenticated' : 'anonymous'];\n\t}\n\treturn response?.data?.message || '';\n};\n\nconst PREFER_SOURCEGRAPH_API = 'PREFER_SOURCEGRAPH_API';\n\nexport class GitHubFetcher {\n\tprivate static instance: GitHubFetcher | null = null;\n\tprivate _emitter = new vscode.EventEmitter<boolean | null | undefined>();\n\tprivate _request: Octokit['request'] | null = null;\n\tpublic onDidChangePreferSourcegraphApi = this._emitter.event;\n\tprivate _currentRepoPromise: Promise<any> | null = null;\n\tprivate _sgApiTimeout: boolean = false;\n\n\tpublic request: Octokit['request'];\n\tpublic graphql: Octokit['graphql'];\n\n\tpublic static getInstance(): GitHubFetcher {\n\t\tif (GitHubFetcher.instance) {\n\t\t\treturn GitHubFetcher.instance;\n\t\t}\n\t\treturn (GitHubFetcher.instance = new this());\n\t}\n\n\tprivate constructor() {\n\t\tthis.initFetcherMethods();\n\t\tthis.initPreferSourcegraphApi();\n\t\tGitHubTokenManager.getInstance().onDidChangeToken(() => this.initFetcherMethods());\n\t\tGitHubTokenManager.getInstance().onDidChangeToken(() => this.initPreferSourcegraphApi());\n\t}\n\n\t// initial fetcher methods in this way for correct `request/graphql` type inference\n\tinitFetcherMethods() {\n\t\tconst accessToken = GitHubTokenManager.getInstance().getToken();\n\t\tconst octokit = new Octokit({ auth: accessToken, request: { fetch }, baseUrl: GITHUB_API_PREFIX });\n\n\t\tthis._request = octokit.request;\n\t\tthis.request = Object.assign((...args: Parameters<Octokit['request']>) => {\n\t\t\treturn octokit.request(...args).catch(async (error) => {\n\t\t\t\tconst errorStatus = error?.response?.status as number | undefined;\n\t\t\t\tconst repoNotFound = errorStatus === 404 && !(await this.resolveCurrentRepo());\n\t\t\t\tif ((errorStatus && [401, 403].includes(errorStatus)) || repoNotFound) {\n\t\t\t\t\t// maybe we have to acquire github access token to continue\n\t\t\t\t\tconst message = detectErrorMessage(error?.response, !!accessToken);\n\t\t\t\t\tawait GitHub1sAuthenticationView.getInstance().open(message, true);\n\t\t\t\t\treturn this._request!(...args);\n\t\t\t\t}\n\t\t\t});\n\t\t}, this._request);\n\n\t\tthis.graphql = Object.assign(async (...args: Parameters<Octokit['graphql']>) => {\n\t\t\tif (!GitHubTokenManager.getInstance().getToken()) {\n\t\t\t\tconst message = 'GraphQL API only works for authenticated users';\n\t\t\t\tawait GitHub1sAuthenticationView.getInstance().open(message, true);\n\t\t\t}\n\t\t\treturn octokit.graphql(...args);\n\t\t}, octokit.graphql);\n\t}\n\n\tprivate resolveCurrentRepo(forceUpdate: boolean = false) {\n\t\tif (this._currentRepoPromise && !forceUpdate) {\n\t\t\treturn this._currentRepoPromise;\n\t\t}\n\t\tconst requestPattern = '/repos/{owner}/{repo}' as const;\n\t\tconst getOwnerRepo = () => getCurrentRepo().then((repo) => repo.split('/'));\n\t\treturn (this._currentRepoPromise = Promise.resolve(getOwnerRepo())\n\t\t\t.then(([owner, repo]) => this._request?.(requestPattern, { owner, repo }).then((res) => res.data))\n\t\t\t.catch(() => null));\n\t}\n\n\tprivate async initPreferSourcegraphApi() {\n\t\tif (await this.getPreferSourcegraphApi()) {\n\t\t\tconst sgDataSource = SourcegraphDataSource.getInstance('github');\n\t\t\ttry {\n\t\t\t\tif (!(await sgDataSource.provideRepository(await getCurrentRepo()))) {\n\t\t\t\t\tthis.resolveCurrentRepo(true).then((repo) => {\n\t\t\t\t\t\trepo?.private && this.setPreferSourcegraphApi(false);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tif (e.message && e.message.includes('signal is aborted')) {\n\t\t\t\t\tthis._sgApiTimeout = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async getPreferSourcegraphApi(repo?: string): Promise<boolean> {\n\t\tconst targetRepo = repo || (await getCurrentRepo());\n\t\tconst globalState = getExtensionContext().globalState;\n\t\tconst cachedData: Record<string, boolean> | undefined = globalState.get(PREFER_SOURCEGRAPH_API);\n\t\treturn !isNil(cachedData?.[targetRepo]) ? !!cachedData?.[targetRepo] : this._sgApiTimeout ? false : true;\n\t}\n\n\tpublic async setPreferSourcegraphApi(value: boolean, repo?: string) {\n\t\tconst targetRepo = repo || (await getCurrentRepo());\n\t\tconst globalState = getExtensionContext().globalState;\n\t\tconst cachedData: Record<string, boolean> | undefined = globalState.get(PREFER_SOURCEGRAPH_API);\n\t\tawait globalState.update(PREFER_SOURCEGRAPH_API, { ...cachedData, [targetRepo]: value });\n\t\tthis._emitter.fire(value);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/graphql.ts",
    "content": "/**\n * @file github graphql queries\n * @author netcon\n */\n\nexport const FILE_BLAME_QUERY = `\nquery fileBlameQuery($owner: String!, $repo: String!, $ref: String!, $path: String!) {\n\trepository(owner: $owner, name: $repo) {\n\t\tobject(expression: $ref) {\n\t\t\t... on Commit {\n\t\t\t\tblame(path: $path) {\n\t\t\t\t\tranges {\n\t\t\t\t\t\tage\n\t\t\t\t\t\tstartingLine\n\t\t\t\t\t\tendingLine\n\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\tsha: oid\n\t\t\t\t\t\t\tmessage\n\t\t\t\t\t\t\tauthoredDate\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tavatarUrl\n\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n`;\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/index.ts",
    "content": "/**\n * @file GitHub1s adapter\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { setVSCodeContext } from '@/helpers/vscode';\nimport { GitHub1sDataSource } from './data-source';\nimport { GitHub1sRouterParser } from './router-parser';\nimport { GitHub1sSettingsViewProvider } from './settings';\nimport { GitHub1sAuthenticationView } from './authentication';\nimport { Adapter, CodeReviewType, PlatformName } from '../types';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\nimport { getCurrentRepo } from './parse-path';\n\nexport class GitHub1sAdapter implements Adapter {\n\tpublic scheme: string = 'github1s';\n\tpublic platformName = PlatformName.GitHub;\n\tpublic codeReviewType = CodeReviewType.PullRequest;\n\n\tresolveDataSource() {\n\t\treturn Promise.resolve(GitHub1sDataSource.getInstance());\n\t}\n\n\tresolveRouterParser() {\n\t\treturn Promise.resolve(GitHub1sRouterParser.getInstance());\n\t}\n\n\tactivateAsDefault() {\n\t\t// register settings view and show it in activity bar\n\t\tsetVSCodeContext('github1s:views:settings:visible', true);\n\t\tsetVSCodeContext('github1s:views:codeReviewList:visible', true);\n\t\tsetVSCodeContext('github1s:views:commitList:visible', true);\n\t\tsetVSCodeContext('github1s:views:fileHistory:visible', true);\n\t\tsetVSCodeContext('github1s:features:gutterBlame:enabled', true);\n\n\t\tvscode.window.registerWebviewViewProvider(\n\t\t\tGitHub1sSettingsViewProvider.viewType,\n\t\t\tnew GitHub1sSettingsViewProvider(),\n\t\t);\n\t\tvscode.commands.registerCommand('github1s.commands.openGitHub1sAuthPage', () => {\n\t\t\treturn GitHub1sAuthenticationView.getInstance().open();\n\t\t});\n\t\tvscode.commands.registerCommand('github1s.commands.syncSourcegraphRepository', async () => {\n\t\t\tconst dataSource = SourcegraphDataSource.getInstance('github');\n\t\t\tconst randomRef = (Math.random() + 1).toString(36).slice(2);\n\t\t\treturn dataSource.provideCommit(await getCurrentRepo(), randomRef).then(() => {\n\t\t\t\treturn vscode.commands.executeCommand('workbench.action.reloadWindow');\n\t\t\t});\n\t\t});\n\t}\n\n\tdeactivateAsDefault() {\n\t\tsetVSCodeContext('github1s:views:settings:visible', false);\n\t\tsetVSCodeContext('github1s:views:codeReviewList:visible', false);\n\t\tsetVSCodeContext('github1s:views:commitList:visible', false);\n\t\tsetVSCodeContext('github1s:views:fileHistory:visible', false);\n\t\tsetVSCodeContext('github1s:features:gutterBlame:enabled', false);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/parse-path.ts",
    "content": "/**\n * @file parse github path\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { parsePath } from 'history';\nimport { PageType, RouterState } from '@/adapters/types';\nimport { GitHub1sDataSource } from './data-source';\nimport * as queryString from 'query-string';\nimport { memorize } from '@/helpers/func';\nimport { getBrowserUrl } from '@/helpers/context';\n\nexport const DEFAULT_REPO = 'conwnet/github1s';\n\nexport const getCurrentRepo = memorize(() => {\n\treturn getBrowserUrl().then((browserUrl: string) => {\n\t\tconst pathParts = vscode.Uri.parse(browserUrl).path.split('/').filter(Boolean);\n\t\treturn pathParts.length >= 2 ? (pathParts.slice(0, 2) as [string, string]).join('/') : DEFAULT_REPO;\n\t});\n});\n\nexport const getDefaultBranch = async (repo: string): Promise<string> => {\n\tconst dataSource = GitHub1sDataSource.getInstance();\n\treturn dataSource.getDefaultBranch(repo);\n};\n\nconst parseTreeUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType, ...restParts] = pathParts;\n\tconst repoFullName = `${owner}/${repo}`;\n\tconst dataSource = GitHub1sDataSource.getInstance();\n\tconst { ref, path: filePath } = await dataSource.extractRefPath(repoFullName, restParts.join('/'));\n\n\treturn { pageType: PageType.Tree, repo: repoFullName, ref, filePath };\n};\n\nconst parseBlobUrl = async (path: string): Promise<RouterState> => {\n\tconst routerState = (await parseTreeUrl(path)) as any;\n\tconst { hash: routerHash } = parsePath(path);\n\n\tif (!routerHash) {\n\t\treturn { ...routerState, pageType: PageType.Blob };\n\t}\n\n\t// get selected line number range from path which looks like:\n\t// `/conwnet/github1s/blob/master/package.json#L10-L20`\n\tconst matches = routerHash.match(/^#L(\\d+)(?:-L(\\d+))?/);\n\tconst [_, startLineNumber = '0', endLineNumber] = matches ? matches : [];\n\n\treturn {\n\t\t...routerState,\n\t\tpageType: PageType.Blob,\n\t\tstartLine: parseInt(startLineNumber, 10),\n\t\tendLine: parseInt(endLineNumber || startLineNumber, 10),\n\t};\n};\n\nconst parseCommitsUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType, ...refParts] = pathParts;\n\n\treturn {\n\t\trepo: `${owner}/${repo}`,\n\t\tpageType: PageType.CommitList,\n\t\tref: refParts.length ? refParts.join('/') : await getDefaultBranch(`${owner}/${repo}`),\n\t};\n};\n\nconst parseCommitUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType, ...refParts] = pathParts;\n\tconst commitSha = refParts.join('/');\n\n\treturn { repo: `${owner}/${repo}`, pageType: PageType.Commit, ref: commitSha, commitSha };\n};\n\nconst parsePullsUrl = async (path: string): Promise<RouterState> => {\n\tconst [owner, repo] = parsePath(path).pathname!.split('/').filter(Boolean);\n\n\treturn {\n\t\trepo: `${owner}/${repo}`,\n\t\tref: await getDefaultBranch(`${owner}/${repo}`),\n\t\tpageType: PageType.CodeReviewList,\n\t};\n};\n\nconst parsePullUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType, codeReviewId] = pathParts;\n\tconst repoFullName = `${owner}/${repo}`;\n\tconst codeReview = await GitHub1sDataSource.getInstance().provideCodeReview(repoFullName, codeReviewId);\n\n\treturn {\n\t\trepo: `${owner}/${repo}`,\n\t\tpageType: PageType.CodeReview,\n\t\tref: codeReview.targetSha,\n\t\tcodeReviewId,\n\t};\n};\n\nconst parseSearchUrl = async (path: string): Promise<RouterState> => {\n\tconst { pathname, search } = parsePath(path);\n\tconst pathParts = pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, _pageType] = pathParts;\n\tconst queryOptions = queryString.parse(search || '');\n\tconst query = typeof queryOptions.q === 'string' ? queryOptions.q : '';\n\tconst isRegex = queryOptions.regex === 'yes';\n\tconst isCaseSensitive = queryOptions.case === 'yes';\n\tconst matchWholeWord = queryOptions.whole === 'yes';\n\tconst filesToInclude = typeof queryOptions['files-to-include'] === 'string' ? queryOptions['files-to-include'] : '';\n\tconst filesToExclude = typeof queryOptions['files-to-exclude'] === 'string' ? queryOptions['files-to-exclude'] : '';\n\n\treturn {\n\t\trepo: `${owner}/${repo}`,\n\t\tpageType: PageType.Search,\n\t\tref: await getDefaultBranch(`${owner}/${repo}`),\n\t\tquery,\n\t\tisRegex,\n\t\tisCaseSensitive,\n\t\tmatchWholeWord,\n\t\tfilesToInclude,\n\t\tfilesToExclude,\n\t};\n};\n\nconst PAGE_TYPE_MAP = {\n\ttree: PageType.Tree,\n\tblob: PageType.Blob,\n\tpulls: PageType.CodeReviewList,\n\tpull: PageType.CodeReview,\n\tcommit: PageType.Commit,\n\tcommits: PageType.CommitList,\n\tsearch: PageType.Search,\n};\n\nexport const parseGitHubPath = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname?.split('/').filter(Boolean) || [];\n\t// detect concrete PageType the *third part* in url.path\n\tconst pageType = pathParts[2] ? PAGE_TYPE_MAP[pathParts[2]] || PageType.Unknown : PageType.Tree;\n\n\tif (pathParts.length >= 2) {\n\t\tswitch (pageType) {\n\t\t\tcase PageType.Tree:\n\t\t\tcase PageType.Unknown:\n\t\t\t\treturn parseTreeUrl(path);\n\t\t\tcase PageType.Blob:\n\t\t\t\treturn parseBlobUrl(path);\n\t\t\tcase PageType.CodeReview:\n\t\t\t\treturn parsePullUrl(path);\n\t\t\tcase PageType.CodeReviewList:\n\t\t\t\treturn parsePullsUrl(path);\n\t\t\tcase PageType.Commit:\n\t\t\t\treturn parseCommitUrl(path);\n\t\t\tcase PageType.CommitList:\n\t\t\t\treturn parseCommitsUrl(path);\n\t\t\tcase PageType.Search:\n\t\t\t\treturn parseSearchUrl(path);\n\t\t}\n\t}\n\n\t// fallback to default\n\treturn {\n\t\trepo: DEFAULT_REPO,\n\t\tref: await getDefaultBranch(DEFAULT_REPO),\n\t\tpageType: PageType.Tree,\n\t\tfilePath: '',\n\t};\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/router-parser.ts",
    "content": "/**\n * @file router parser\n * @author netcon\n */\n\nimport { joinPath } from '@/helpers/util';\nimport * as adapterTypes from '../types';\nimport { parseGitHubPath } from './parse-path';\n\nexport class GitHub1sRouterParser extends adapterTypes.RouterParser {\n\tprotected static instance: GitHub1sRouterParser | null = null;\n\n\tpublic static getInstance(): GitHub1sRouterParser {\n\t\tif (GitHub1sRouterParser.instance) {\n\t\t\treturn GitHub1sRouterParser.instance;\n\t\t}\n\t\treturn (GitHub1sRouterParser.instance = new GitHub1sRouterParser());\n\t}\n\n\tparsePath(path: string): Promise<adapterTypes.RouterState> {\n\t\treturn parseGitHubPath(path);\n\t}\n\n\tbuildTreePath(repo: string, ref?: string, filePath?: string): string {\n\t\treturn ref ? (filePath ? `/${repo}/tree/${ref}/${filePath}` : `/${repo}/tree/${ref}`) : `/${repo}`;\n\t}\n\n\tbuildBlobPath(repo: string, ref: string, filePath: string, startLine?: number, endLine?: number): string {\n\t\tconst hash = startLine ? (endLine ? `#L${startLine}-L${endLine}` : `#L${startLine}`) : '';\n\t\treturn `/${repo}/blob/${ref}/${filePath}${hash}`;\n\t}\n\n\tbuildCommitListPath(repo: string): string {\n\t\treturn `/${repo}/commits`;\n\t}\n\n\tbuildCommitPath(repo: string, commitSha: string): string {\n\t\treturn `/${repo}/commit/${commitSha}`;\n\t}\n\n\tbuildCodeReviewListPath(repo: string): string {\n\t\treturn `/${repo}/pulls`;\n\t}\n\n\tbuildCodeReviewPath(repo: string, codeReviewId: string): string {\n\t\treturn `/${repo}/pull/${codeReviewId}`;\n\t}\n\n\tbuildExternalLink(path: string): string {\n\t\treturn joinPath(GITHUB_ORIGIN, path);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/settings.ts",
    "content": "/**\n * @file GitHub1s Settings Webview Provider\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { getExtensionContext } from '@/helpers/context';\nimport { createPageHtml, getWebviewOptions } from '@/helpers/page';\nimport { GitHubTokenManager } from './token';\nimport { GitHubFetcher } from './fetcher';\n\nexport const messageApiMap = {\n\tinfo: vscode.window.showInformationMessage,\n\twarning: vscode.window.showWarningMessage,\n\terror: vscode.window.showErrorMessage,\n};\n\nexport class GitHub1sSettingsViewProvider implements vscode.WebviewViewProvider {\n\tpublic static readonly viewType = 'github1s.views.settings';\n\n\tprotected tokenManager = GitHubTokenManager.getInstance();\n\tprotected apiFetcher: Pick<\n\t\tGitHubFetcher,\n\t\t'getPreferSourcegraphApi' | 'setPreferSourcegraphApi' | 'onDidChangePreferSourcegraphApi'\n\t> = GitHubFetcher.getInstance();\n\n\tprotected pageTitle = 'GitHub1s Settings';\n\tprotected OAuthCommand = 'github1s.commands.vscode.connectToGitHub';\n\tprotected detailPageCommand = 'github1s.commands.openGitHub1sAuthPage';\n\tprotected pageConfig = {\n\t\tpageDescriptionLines: [\n\t\t\t'For unauthenticated requests, the rate limit of GitHub allows for up to 60 requests per hour.',\n\t\t\t'For API requests using Authentication, you can make up to 5,000 requests per hour.',\n\t\t],\n\t\tOAuthButtonText: 'Connect to GitHub',\n\t\tcreateTokenLink: `${GITHUB_ORIGIN}/settings/tokens/new?scopes=repo&description=GitHub1s`,\n\t};\n\n\tpublic registerListeners(webviewView: vscode.WebviewView) {\n\t\twebviewView.webview.onDidReceiveMessage((message) => {\n\t\t\tconst commonResponse = { id: message.id, type: message.type };\n\t\t\tconst postMessage = (data?: unknown) => webviewView.webview.postMessage({ ...commonResponse, data });\n\n\t\t\tswitch (message.type) {\n\t\t\t\tcase 'get-token':\n\t\t\t\t\tpostMessage(this.tokenManager.getToken());\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'set-token':\n\t\t\t\t\tthis.tokenManager.setToken(message.data || '').then(() => postMessage());\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'validate-token':\n\t\t\t\t\tthis.tokenManager.validateToken(message.data).then((tokenStatus) => postMessage(tokenStatus));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'open-detail-page':\n\t\t\t\t\tvscode.commands.executeCommand(this.detailPageCommand).then(() => postMessage());\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'oauth-authorizing':\n\t\t\t\t\tvscode.commands.executeCommand(this.OAuthCommand).then((data: any) => {\n\t\t\t\t\t\tif (data && data.error_description) {\n\t\t\t\t\t\t\tvscode.window.showErrorMessage(data.error_description);\n\t\t\t\t\t\t} else if (data && data.access_token) {\n\t\t\t\t\t\t\tthis.tokenManager.setToken(data.access_token || '');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpostMessage();\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'call-vscode-message-api':\n\t\t\t\t\tconst messageApi = messageApiMap[message.data?.level];\n\t\t\t\t\tmessageApi && messageApi(...message.data?.args).then((response) => postMessage(response));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'get-prefer-sourcegraph-api':\n\t\t\t\t\tthis.apiFetcher.getPreferSourcegraphApi().then((value) => postMessage(value));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'set-prefer-sourcegraph-api':\n\t\t\t\t\tthis.apiFetcher.setPreferSourcegraphApi(message.data);\n\t\t\t\t\tpostMessage(message.data);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\n\t\tthis.tokenManager.onDidChangeToken((token) => {\n\t\t\twebviewView.webview.postMessage({ type: 'token-changed', token });\n\t\t});\n\t\tthis.apiFetcher.onDidChangePreferSourcegraphApi((value) => {\n\t\t\twebviewView.webview.postMessage({ type: 'prefer-sourcegraph-api-changed', value });\n\t\t});\n\t}\n\n\tpublic resolveWebviewView(webviewView: vscode.WebviewView): void | Thenable<void> {\n\t\tconst extensionContext = getExtensionContext();\n\n\t\tthis.registerListeners(webviewView);\n\t\twebviewView.webview.options = getWebviewOptions(extensionContext.extensionUri);\n\n\t\tconst styles = [\n\t\t\tvscode.Uri.joinPath(extensionContext.extensionUri, 'assets/pages/components.css').toString(),\n\t\t\tvscode.Uri.joinPath(extensionContext.extensionUri, 'assets/pages/github1s-settings.css').toString(),\n\t\t];\n\t\tconst globalPageConfig = { ...this.pageConfig, extensionUri: extensionContext.extensionUri.toString() };\n\t\tconst scripts = [\n\t\t\t'data:text/javascript;base64,' +\n\t\t\t\tBuffer.from(`window.pageConfig=${JSON.stringify(globalPageConfig)};`).toString('base64'),\n\t\t\tvscode.Uri.joinPath(extensionContext.extensionUri, 'assets/pages/github1s-settings.js').toString(),\n\t\t];\n\t\twebviewView.webview.html = createPageHtml(this.pageTitle, styles, scripts);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/github1s/token.ts",
    "content": "/**\n * @file github api auth token manager\n */\n\nimport * as vscode from 'vscode';\nimport { getExtensionContext } from '@/helpers/context';\n\nexport interface ValidateResult {\n\tusername: string;\n\tavatar_url: string;\n\tprofile_url: string;\n\tratelimits?: {\n\t\tlimit?: number;\n\t\tremaining?: number;\n\t\treset?: number;\n\t\tresource?: number;\n\t\tused?: number;\n\t};\n}\n\nexport class GitHubTokenManager {\n\tprotected static instance: GitHubTokenManager | null = null;\n\tprivate _emitter = new vscode.EventEmitter<string>();\n\tpublic onDidChangeToken = this._emitter.event;\n\tpublic tokenStateKey = 'github-oauth-token';\n\n\tprotected constructor() {}\n\tpublic static getInstance(): GitHubTokenManager {\n\t\tif (GitHubTokenManager.instance) {\n\t\t\treturn GitHubTokenManager.instance;\n\t\t}\n\t\treturn (GitHubTokenManager.instance = new this());\n\t}\n\n\tpublic getToken(): string {\n\t\treturn getExtensionContext().globalState.get(this.tokenStateKey) || '';\n\t}\n\n\tpublic async setToken(token: string) {\n\t\tconst isTokenChanged = this.getToken() !== token;\n\t\treturn getExtensionContext()\n\t\t\t.globalState.update(this.tokenStateKey, token)\n\t\t\t.then(() => isTokenChanged && this._emitter.fire(token));\n\t}\n\n\tpublic async validateToken(token?: string): Promise<ValidateResult | null> {\n\t\tconst accessToken = token === undefined ? this.getToken() : token;\n\t\tif (!accessToken) {\n\t\t\treturn Promise.resolve(null);\n\t\t}\n\t\tconst fetchOptions = accessToken ? { headers: { Authorization: `token ${accessToken}` } } : {};\n\t\treturn fetch(`${GITHUB_API_PREFIX}/user`, fetchOptions)\n\t\t\t.then((response) => {\n\t\t\t\tif (response.status === 401) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn response.json().then((data) => ({\n\t\t\t\t\tusername: data.login,\n\t\t\t\t\tavatar_url: data.avatar_url,\n\t\t\t\t\tprofile_url: data.html_url,\n\t\t\t\t\trateLimits: {\n\t\t\t\t\t\tlimit: +response.headers.get('x-ratelimit-limit')! || 0,\n\t\t\t\t\t\tremaining: +response.headers.get('x-ratelimit-remaining')! || 0,\n\t\t\t\t\t\treset: +response.headers.get('x-ratelimit-reset')! || 0,\n\t\t\t\t\t\tresource: +response.headers.get('ratelimit-resource')! || 0,\n\t\t\t\t\t\tused: +response.headers.get('x-ratelimit-used')! || 0,\n\t\t\t\t\t},\n\t\t\t\t}));\n\t\t\t})\n\t\t\t.catch(() => null);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/authentication.ts",
    "content": "/**\n * @file gitlab authentication page\n * @author netcon\n */\n\nimport { GitHub1sAuthenticationView } from '../github1s/authentication';\nimport { GitLabTokenManager } from './token';\n\nexport class GitLab1sAuthenticationView extends GitHub1sAuthenticationView {\n\tprotected tokenManager = GitLabTokenManager.getInstance();\n\tprotected pageTitle = 'Authenticating to GitLab';\n\tprotected OAuthCommand = 'github1s.commands.vscode.connectToGitLab';\n\tprotected pageConfig = {\n\t\tauthenticationFormTitle: 'Authenticating to GitLab',\n\t\tOAuthButtonText: 'Connect to GitLab',\n\t\tOAuthButtonLogo: 'assets/pages/assets/gitlab.svg',\n\t\tcreateTokenLink: `${GITLAB_ORIGIN}/-/profile/personal_access_tokens?scopes=read_api&name=GitLab1s`,\n\t\tauthenticationFeatures: [\n\t\t\t{\n\t\t\t\ttext: 'Access GitLab personal repository',\n\t\t\t\tlink: 'https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttext: 'Higher rate limit for GitLab official API',\n\t\t\t\tlink: 'https://docs.gitlab.com/ee/security/rate_limits.html',\n\t\t\t},\n\t\t],\n\t};\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/data-source.ts",
    "content": "/**\n * @file gitlab1s data-source-provider\n * @author netcon\n */\n\nimport {\n\tBranch,\n\tCodeReview,\n\tCodeReviewState,\n\tTextSearchOptions,\n\tCommit,\n\tCommonQueryOptions,\n\tDataSource,\n\tDirectory,\n\tDirectoryEntry,\n\tFile,\n\tBlameRange,\n\tFileType,\n\tTag,\n\tTextSearchResults,\n\tTextSearchQuery,\n\tSymbolDefinitions,\n\tSymbolReferences,\n\tFileChangeStatus,\n\tChangedFile,\n\tSymbolHover,\n\tCommitsQueryOptions,\n\tCodeReviewsQueryOptions,\n} from '../types';\nimport { toUint8Array } from 'js-base64';\nimport { matchSorter } from 'match-sorter';\nimport { GitLabFetcher } from './fetcher';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\nimport { decorate, memorize } from '@/helpers/func';\n\nconst FileTypeMap = {\n\tblob: FileType.File,\n\ttree: FileType.Directory,\n\tcommit: FileType.Submodule,\n};\n\nconst getMergeRequestState = (mergeRequest: { state: string; merged_at: string | null }): CodeReviewState => {\n\t// current merge request is open\n\tif (mergeRequest.state === 'opened') {\n\t\treturn CodeReviewState.Open;\n\t}\n\t// current merge request is merged\n\tif (mergeRequest.state === 'closed' && mergeRequest.merged_at) {\n\t\treturn CodeReviewState.Merged;\n\t}\n\t// current merge is closed\n\treturn CodeReviewState.Closed;\n};\n\nconst resolveComputeAge = (timestamps: number[], ageLimit = 10) => {\n\tconst maxTimestamp = Math.max(...timestamps);\n\tconst minTimestamp = Math.min(...timestamps);\n\tconst step = (maxTimestamp - minTimestamp) / ageLimit;\n\treturn (timestamp: number) => {\n\t\tconst age = Math.floor((timestamp - minTimestamp) / (step || 1));\n\t\treturn (((Math.max(age, ageLimit - 1) % ageLimit) + ageLimit) % ageLimit) + 1;\n\t};\n};\n\nconst sourcegraphDataSource = SourcegraphDataSource.getInstance('gitlab');\nconst trySourcegraphApiFirst = (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => {\n\tconst originalMethod = descriptor.value;\n\n\tdescriptor.value = async function <T extends (...args) => Promise<any>>(...args: Parameters<T>) {\n\t\tconst gitlabFetcher = GitLabFetcher.getInstance();\n\t\tif (await gitlabFetcher.getPreferSourcegraphApi(args[0])) {\n\t\t\ttry {\n\t\t\t\treturn await sourcegraphDataSource[propertyKey](...args);\n\t\t\t} catch (e) {}\n\t\t}\n\t\treturn originalMethod.apply(this, args);\n\t};\n};\n\nexport class GitLab1sDataSource extends DataSource {\n\tprivate static instance: GitLab1sDataSource | null = null;\n\tprivate branchesPromiseMap: Map<string, Promise<Branch[]>> = new Map();\n\tprivate tagsPromiseMap: Map<string, Promise<Tag[]>> = new Map();\n\tprivate matchedRefsMap = new Map<string, string[]>();\n\n\tpublic static getInstance(): GitLab1sDataSource {\n\t\tif (GitLab1sDataSource.instance) {\n\t\t\treturn GitLab1sDataSource.instance;\n\t\t}\n\t\treturn (GitLab1sDataSource.instance = new GitLab1sDataSource());\n\t}\n\n\tasync provideRepository(repo: string) {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst { data } = await fetcher.request('GET /projects/{repo}', { repo });\n\t\treturn { private: data.visibility === 'private', defaultBranch: data.default_branch };\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideDirectory(repo: string, ref: string, path: string, recursive = false): Promise<Directory> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tlet page = 1;\n\t\tlet files = [];\n\t\tconst parseTreeItem = (treeItem): DirectoryEntry => ({\n\t\t\tpath: treeItem.path.slice(path.length),\n\t\t\ttype: FileTypeMap[treeItem.type] || FileType.File,\n\t\t\tcommitSha: FileTypeMap[treeItem.id] === FileType.Submodule ? treeItem.sha || 'HEAD' : undefined,\n\t\t\tsize: treeItem.size,\n\t\t});\n\t\twhile (page > 0) {\n\t\t\tconst requestParams = { ref, page, path, repo, recursive };\n\t\t\tconst { data, headers } = await fetcher.request(\n\t\t\t\t'GET /projects/{repo}/repository/tree?recursive={recursive}&per_page=100&page={page}&ref={ref}&path={path}',\n\t\t\t\trequestParams,\n\t\t\t);\n\t\t\tfiles = files.concat(data);\n\t\t\tconst nextPage = Number(headers!.get('x-next-page'));\n\t\t\tpage = nextPage > page ? nextPage : 0;\n\t\t}\n\n\t\treturn {\n\t\t\tentries: files.map(parseTreeItem),\n\t\t\ttruncated: false,\n\t\t};\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideFile(repo: string, ref: string, path: string): Promise<File> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst requestParams = { ref, path, repo };\n\t\tconst { data } = await fetcher.request('GET /projects/{repo}/repository/files/{path}?ref={ref}', requestParams);\n\t\treturn { content: toUint8Array((data as any).content) };\n\t}\n\n\t@decorate(memorize)\n\tasync getBranches(repo: string, ref: 'heads' | 'tags'): Promise<Branch[] | Tag[]> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst requestParams = { repo, ref };\n\t\tconst { data } = await fetcher.request('GET /projects/{repo}/repository/branches', requestParams);\n\t\treturn data.map((item) => ({\n\t\t\tname: item.name,\n\t\t\tcommitSha: item.commit.id,\n\t\t\tdescription: `${ref === 'heads' ? 'Branch' : 'Tag'} at ${item.commit.short_id}`,\n\t\t}));\n\t}\n\n\t@decorate(memorize)\n\tasync getTags(repo: string, ref: 'heads' | 'tags'): Promise<Branch[] | Tag[]> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst requestParams = { repo, ref };\n\t\tconst { data } = await fetcher.request('GET /projects/{repo}/repository/tags', requestParams);\n\t\treturn data.map((item) => ({\n\t\t\tname: item.name,\n\t\t\tcommitSha: item.commit.id,\n\t\t\tdescription: `${ref === 'heads' ? 'Branch' : 'Tag'} at ${item.commit.short_id}`,\n\t\t}));\n\t}\n\n\t@decorate(memorize)\n\tasync getDefaultBranch(repo: string) {\n\t\treturn (await this.provideRepository(repo))?.defaultBranch || 'HEAD';\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync extractRefPath(repo: string, refAndPath: string): Promise<{ ref: string; path: string }> {\n\t\tif (!refAndPath) {\n\t\t\treturn { ref: await this.getDefaultBranch(repo), path: '' };\n\t\t}\n\t\tif (refAndPath.match(/^HEAD(\\/.*)?$/i)) {\n\t\t\treturn { ref: 'HEAD', path: refAndPath.slice(5) };\n\t\t}\n\t\tif (!this.matchedRefsMap.has(repo)) {\n\t\t\tthis.matchedRefsMap.set(repo, []);\n\t\t}\n\t\tconst matchPathRef = (ref) => refAndPath.startsWith(`${ref}/`) || refAndPath === ref;\n\t\tconst pathRef = this.matchedRefsMap.get(repo)?.find(matchPathRef);\n\t\tif (pathRef) {\n\t\t\treturn { ref: pathRef, path: refAndPath.slice(pathRef.length + 1) };\n\t\t}\n\t\tconst [branches, tags] = await this.prepareAllRefs(repo);\n\t\tconst exactRef = [...branches, ...tags].map((item) => item.name).find(matchPathRef);\n\t\tconst ref = exactRef || refAndPath.split('/')[0] || 'HEAD';\n\t\texactRef && this.matchedRefsMap.get(repo)?.push(ref);\n\t\treturn { ref, path: refAndPath.slice(ref.length + 1) };\n\t}\n\n\tasync prepareAllRefs(repo: string) {\n\t\treturn Promise.all([this.provideBranches(repo), this.provideTags(repo)]);\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideBranches(repo: string, options?: CommonQueryOptions): Promise<Branch[]> {\n\t\tif (!this.branchesPromiseMap.has(repo)) {\n\t\t\tthis.branchesPromiseMap.set(repo, this.getBranches(repo, 'heads'));\n\t\t}\n\t\treturn this.branchesPromiseMap.get(repo)!.then((branches) => {\n\t\t\tconst matchOptions = { keys: ['name'] };\n\t\t\tconst matchedBranches = options?.query ? matchSorter(branches, options.query, matchOptions) : branches;\n\t\t\tif (options?.pageSize) {\n\t\t\t\tconst page = options.page || 1;\n\t\t\t\tconst pageSize = options.pageSize;\n\t\t\t\treturn matchedBranches.slice(pageSize * (page - 1), pageSize * page);\n\t\t\t}\n\t\t\treturn matchedBranches;\n\t\t});\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideBranch(repo: string, branchName: string): Promise<Branch | null> {\n\t\tconst branches = await this.provideBranches(repo);\n\t\treturn branches.find((item) => item.name === branchName) || null;\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideTags(repoFullName: string, options?: CommonQueryOptions): Promise<Tag[]> {\n\t\tif (!this.tagsPromiseMap.has(repoFullName)) {\n\t\t\tthis.tagsPromiseMap.set(repoFullName, this.getTags(repoFullName, 'tags'));\n\t\t}\n\t\treturn this.tagsPromiseMap.get(repoFullName)!.then((tags) => {\n\t\t\tconst matchOptions = { keys: ['name'] };\n\t\t\tconst matchedTags = options?.query ? matchSorter(tags, options.query, matchOptions) : tags;\n\t\t\tif (options?.pageSize) {\n\t\t\t\tconst page = options.page || 1;\n\t\t\t\tconst pageSize = options.pageSize;\n\t\t\t\treturn matchedTags.slice(pageSize * (page - 1), pageSize * page);\n\t\t\t}\n\t\t\treturn matchedTags;\n\t\t});\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideTag(repoFullName: string, tagName: string): Promise<Tag | null> {\n\t\tconst tags = await this.provideTags(repoFullName);\n\t\treturn tags.find((item) => item.name === tagName) || null;\n\t}\n\n\tasync provideTextSearchResults(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tquery: TextSearchQuery,\n\t\toptions: TextSearchOptions,\n\t): Promise<TextSearchResults> {\n\t\treturn sourcegraphDataSource.provideTextSearchResults(repoFullName, ref, query, options);\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideCommits(repo: string, options?: CommitsQueryOptions): Promise<(Commit & { files?: ChangedFile[] })[]> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst queryParams = {\n\t\t\tpage: options?.page,\n\t\t\tper_page: options?.pageSize,\n\t\t\tsha: options?.from,\n\t\t\tpath: options?.path,\n\t\t\tauthor: options?.author,\n\t\t};\n\t\tconst requestParams = { repo, ...queryParams };\n\t\tconst { data } = await fetcher.request(\n\t\t\t'GET /projects/{repo}/repository/commits?per_page={per_page}&page={page}&path={path}&ref_name={sha}',\n\t\t\trequestParams,\n\t\t);\n\t\treturn Promise.all(\n\t\t\tdata.map(async (item) => ({\n\t\t\t\tsha: item.id,\n\t\t\t\tauthor: item.author_name,\n\t\t\t\temail: item.author_email,\n\t\t\t\tmessage: item.message,\n\t\t\t\tcommitter: item.committer_name,\n\t\t\t\tcreateTime: item.created_at ? new Date(item.created_at) : undefined,\n\t\t\t\tparents: item.parent_ids.map((parent) => parent) || [],\n\t\t\t\tavatarUrl: item.author?.avatar_url || (await this.provideUserAvatarLink(item.author_name)),\n\t\t\t})),\n\t\t);\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideCommit(repo: string, ref: string): Promise<Commit & { files?: ChangedFile[] }> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst requestParams = { repo, ref };\n\t\tconst { data } = await fetcher.request('GET /projects/{repo}/repository/commits/{ref}', requestParams);\n\t\treturn {\n\t\t\tsha: data.id,\n\t\t\tauthor: data.author_name,\n\t\t\temail: data.author_email,\n\t\t\tmessage: data.message,\n\t\t\tcommitter: data.committer_name,\n\t\t\tcreateTime: data.created_at ? new Date(data.created_at) : undefined,\n\t\t\tparents: data.parent_ids || [],\n\t\t\tfiles: data.files?.map((item) => ({\n\t\t\t\tpath: item.filename || item.previous_filename!,\n\t\t\t\tpreviousPath: item.previous_filename,\n\t\t\t\tstatus: item.status as FileChangeStatus,\n\t\t\t})),\n\t\t\tavatarUrl: data?.avatar_url,\n\t\t};\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideCommitChangedFiles(repo: string, ref: string, _options?: CommonQueryOptions): Promise<ChangedFile[]> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst requestParams = { repo, ref };\n\t\tconst { data } = await fetcher.request('GET /projects/{repo}/repository/commits/{ref}/diff', requestParams);\n\t\treturn (\n\t\t\tdata?.map((item) => ({\n\t\t\t\tpath: item.new_path || item.old_path!,\n\t\t\t\tpreviousPath: item.old_path,\n\t\t\t\tstatus: item.new_file\n\t\t\t\t\t? FileChangeStatus.Added\n\t\t\t\t\t: item.deleted_file\n\t\t\t\t\t\t? FileChangeStatus.Removed\n\t\t\t\t\t\t: item.renamed_file\n\t\t\t\t\t\t\t? FileChangeStatus.Renamed\n\t\t\t\t\t\t\t: FileChangeStatus.Modified,\n\t\t\t})) || []\n\t\t);\n\t}\n\n\tasync provideCodeReviews(\n\t\trepo: string,\n\t\toptions?: CodeReviewsQueryOptions,\n\t): Promise<(CodeReview & { files?: ChangedFile[] })[]> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst state = options?.state ? (options.state === CodeReviewState.Open ? 'open' : 'closed') : 'all';\n\t\t// per_page=100&page={page}\n\t\tconst queryParams = { state, page: options?.page, per_page: options?.pageSize, creator: options?.creator };\n\t\tconst requestParams = { repo, ...queryParams };\n\t\tconst { data } = await fetcher.request(\n\t\t\t'GET /projects/{repo}/merge_requests?per_page={per_page}&page={page}',\n\t\t\trequestParams as any,\n\t\t);\n\n\t\treturn data.map((item) => ({\n\t\t\tid: `${item.iid}`,\n\t\t\ttitle: item.title,\n\t\t\tstate: getMergeRequestState(item),\n\t\t\tcreator: item.author?.name || item.author?.username,\n\t\t\tcreateTime: new Date(item.created_at),\n\t\t\tmergeTime: item.merged_at ? new Date(item.merged_at) : null,\n\t\t\tcloseTime: item.closed_at ? new Date(item.closed_at) : null,\n\t\t\tsource: item.source_branch,\n\t\t\ttarget: item.target_branch,\n\t\t\tavatarUrl: item.author?.avatar_url,\n\t\t}));\n\t}\n\n\tasync provideCodeReview(repo: string, id: string) {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst requestParams = { repo, id };\n\t\tconst { data } = await fetcher.request('GET /projects/{repo}/merge_requests/{id}', requestParams);\n\n\t\treturn {\n\t\t\tid: `${data.iid}`,\n\t\t\ttitle: data.title,\n\t\t\tstate: getMergeRequestState(data),\n\t\t\tcreator: data.author?.name || data.author?.username,\n\t\t\tcreateTime: new Date(data.created_at),\n\t\t\tmergeTime: data.merged_at ? new Date(data.merged_at) : null,\n\t\t\tcloseTime: data.closed_at ? new Date(data.closed_at) : null,\n\t\t\tsource: data.source_branch,\n\t\t\ttarget: data.target_branch,\n\t\t\tsourceSha: data.diff_refs.head_sha,\n\t\t\ttargetSha: data.diff_refs.base_sha,\n\t\t\tavatarUrl: data.author?.avatar_url,\n\t\t};\n\t}\n\n\tasync provideCodeReviewChangedFiles(repo: string, id: string, options?: CommonQueryOptions): Promise<ChangedFile[]> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst pageParams = { per_page: options?.pageSize, page: options?.page };\n\t\tconst filesRequestParams = { repo, id, ...pageParams };\n\t\tconst { data } = await fetcher.request(\n\t\t\t'GET /projects/{repo}/merge_requests/{id}/changes?per_page={per_page}&page={page}',\n\t\t\tfilesRequestParams,\n\t\t);\n\n\t\treturn data.changes.map((item) => ({\n\t\t\tpath: item.new_path,\n\t\t\tpreviousPath: item.old_path,\n\t\t\tstatus: item.new_file\n\t\t\t\t? FileChangeStatus.Added\n\t\t\t\t: item.deleted_file\n\t\t\t\t\t? FileChangeStatus.Removed\n\t\t\t\t\t: item.renamed_file\n\t\t\t\t\t\t? FileChangeStatus.Renamed\n\t\t\t\t\t\t: FileChangeStatus.Modified,\n\t\t}));\n\t}\n\n\t@trySourcegraphApiFirst\n\tasync provideFileBlameRanges(repo: string, ref: string, path: string): Promise<BlameRange[]> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst requestParams = { repo, ref, path };\n\t\tconst { data } = await fetcher.request(\n\t\t\t'GET /projects/{repo}/repository/files/{path}/blame?ref={ref}',\n\t\t\trequestParams,\n\t\t);\n\t\tlet startLine = 1;\n\t\tconst timestamps = data.map(({ commit }) => +new Date(commit.authored_date) || 0);\n\t\tconst computeAge = resolveComputeAge(timestamps);\n\t\treturn (data || []).map(({ commit, lines }) => {\n\t\t\tconst startingLine = startLine;\n\t\t\tconst endingLine = startingLine + lines.length;\n\t\t\tstartLine = endingLine + 1;\n\t\t\treturn {\n\t\t\t\tage: computeAge(+new Date(commit?.authored_date) || 0),\n\t\t\t\tstartingLine,\n\t\t\t\tendingLine,\n\t\t\t\tcommit: {\n\t\t\t\t\tsha: commit?.id as string,\n\t\t\t\t\tauthor: commit?.author_name as string,\n\t\t\t\t\temail: commit?.author_email as string,\n\t\t\t\t\tmessage: commit?.message as string,\n\t\t\t\t\tcreateTime: new Date(commit?.authored_date),\n\t\t\t\t\tavatarUrl: this.provideUserAvatarLink(encodeURIComponent(commit?.author?.name)),\n\t\t\t\t},\n\t\t\t};\n\t\t});\n\t}\n\n\tasync getAvatar(email): Promise<string> {\n\t\tconst fetcher = GitLabFetcher.getInstance();\n\t\tconst { data } = await fetcher.request('GET /avatar?email={email}', { email });\n\t\treturn data.avatar_url;\n\t}\n\n\tprovideSymbolDefinitions(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promise<SymbolDefinitions> {\n\t\treturn sourcegraphDataSource.provideSymbolDefinitions(repoFullName, ref, path, line, character, symbol);\n\t}\n\n\tasync provideSymbolReferences(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promise<SymbolReferences> {\n\t\treturn sourcegraphDataSource.provideSymbolReferences(repoFullName, ref, path, line, character, symbol);\n\t}\n\n\tasync provideSymbolHover(\n\t\trepoFullName: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\t_symbol: string,\n\t): Promise<SymbolHover | null> {\n\t\treturn sourcegraphDataSource.provideSymbolHover(repoFullName, ref, path, line, character, _symbol);\n\t}\n\n\tprovideUserAvatarLink(user: string): string {\n\t\treturn `https://www.gravatar.com/avatar/${user}?d=identicon`;\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/fetcher.ts",
    "content": "/**\n * @file gitlab api fetcher\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { getExtensionContext } from '@/helpers/context';\nimport { GitLab1sAuthenticationView } from './authentication';\nimport { GitLabTokenManager } from './token';\nimport { isNil } from '@/helpers/util';\nimport { reuseable } from '@/helpers/func';\nimport { getCurrentRepo } from './parse-path';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\n\nexport const errorMessages = {\n\tbadCredentials: {\n\t\tanonymous: 'Bad credentials, please authenticate to gitlab and retry',\n\t\tauthenticated: 'This token is invalid, please try another one',\n\t},\n\trepoNotFound: {\n\t\tanonymous: 'Repository not found, if it is private, you can provide an AccessToken to access it',\n\t\tauthenticated: 'Repository not found, if it is private, you can try change an AccessToken to access it',\n\t},\n\tnoPermission: {\n\t\tanonymous: 'You have no permission for this operation, please authenticate to gitlab and retry',\n\t\tauthenticated: 'You have no permission for this operation, please try another account',\n\t},\n};\n\nconst detectErrorMessage = (response: any, authenticated: boolean) => {\n\tif (response?.status === 401 && response?.data?.message?.includes?.('Unauthorized')) {\n\t\treturn errorMessages.badCredentials[authenticated ? 'authenticated' : 'anonymous'];\n\t}\n\tif (response?.status === 404) {\n\t\treturn errorMessages.repoNotFound[authenticated ? 'authenticated' : 'anonymous'];\n\t}\n\tif (response?.status === 403) {\n\t\treturn errorMessages.noPermission[authenticated ? 'authenticated' : 'anonymous'];\n\t}\n\treturn response?.data?.message || response?.data?.error || '';\n};\n\nconst PREFER_SOURCEGRAPH_API = 'PREFER_SOURCEGRAPH_API';\n\nexport class GitLabFetcher {\n\tprivate static instance: GitLabFetcher | null = null;\n\tprivate _emitter = new vscode.EventEmitter<boolean | null | undefined>();\n\tpublic onDidChangePreferSourcegraphApi = this._emitter.event;\n\tprivate _currentRepoPromise: Promise<any> | null = null;\n\n\tpublic static getInstance(): GitLabFetcher {\n\t\tif (GitLabFetcher.instance) {\n\t\t\treturn GitLabFetcher.instance;\n\t\t}\n\t\treturn (GitLabFetcher.instance = new GitLabFetcher());\n\t}\n\n\tprivate constructor() {\n\t\tthis.initPreferSourcegraphApi();\n\t\tGitLabTokenManager.getInstance().onDidChangeToken(() => this.initPreferSourcegraphApi());\n\t}\n\n\tprivate _request = reuseable(\n\t\t(\n\t\t\tcommand: string,\n\t\t\tparams: Record<string, string | number | boolean | undefined>,\n\t\t): Promise<{ status: number; data: any; headers: Headers }> => {\n\t\t\t// eslint-disable-next-line prefer-const\n\t\t\tlet [method, path] = command.split(/\\s+/).filter(Boolean);\n\t\t\tObject.keys(params).forEach((el) => {\n\t\t\t\tpath = path.replace(`{${el}}`, `${encodeURIComponent(params[el] || '')}`);\n\t\t\t});\n\t\t\tconst accessToken = GitLabTokenManager.getInstance().getToken();\n\t\t\tconst fetchOptions: { headers: Record<string, string> } =\n\t\t\t\taccessToken?.length < 60\n\t\t\t\t\t? { headers: { 'PRIVATE-TOKEN': `${accessToken}` } }\n\t\t\t\t\t: { headers: { Authorization: `Bearer ${accessToken}` } };\n\t\t\treturn fetch(GITLAB_API_PREFIX + path, {\n\t\t\t\t...fetchOptions,\n\t\t\t\tmethod,\n\t\t\t}).then(async (response: Response & { data: any }) => {\n\t\t\t\tresponse.data = await response.json();\n\t\t\t\treturn response.ok ? response : Promise.reject({ response });\n\t\t\t});\n\t\t},\n\t);\n\n\tpublic request = (command: string, params: Record<string, string | number | boolean | undefined>) => {\n\t\treturn this._request(command, params).catch(async (error: { response: any }) => {\n\t\t\tconst errorStatus = error?.response?.status as number | undefined;\n\t\t\tconst repoNotFound = errorStatus === 404 && !(await this.resolveCurrentRepo());\n\t\t\tif ((errorStatus && [401, 403].includes(errorStatus)) || repoNotFound) {\n\t\t\t\t// maybe we have to acquire github access token to continue\n\t\t\t\tconst accessToken = GitLabTokenManager.getInstance().getToken();\n\t\t\t\tconst message = detectErrorMessage(error?.response, !!accessToken);\n\t\t\t\tawait GitLab1sAuthenticationView.getInstance().open(message, true);\n\t\t\t\treturn this._request(command, params);\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t};\n\n\tprivate resolveCurrentRepo(forceUpdate: boolean = false) {\n\t\tif (this._currentRepoPromise && !forceUpdate) {\n\t\t\treturn this._currentRepoPromise;\n\t\t}\n\t\treturn (this._currentRepoPromise = Promise.resolve(getCurrentRepo())\n\t\t\t.then(async (repo) => this._request('GET /projects/{repo}', { repo }).then((res) => res.data))\n\t\t\t.catch(() => null));\n\t}\n\n\tprivate async initPreferSourcegraphApi() {\n\t\tif (await this.getPreferSourcegraphApi()) {\n\t\t\tconst sgDataSource = SourcegraphDataSource.getInstance('github');\n\t\t\tif (!(await sgDataSource.provideRepository(await getCurrentRepo()))) {\n\t\t\t\tthis.resolveCurrentRepo(true).then((repo) => {\n\t\t\t\t\trepo?.visibility === 'private' && this.setPreferSourcegraphApi(false);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async getPreferSourcegraphApi(repo?: string): Promise<boolean> {\n\t\tconst targetRepo = repo || (await getCurrentRepo());\n\t\tconst globalState = getExtensionContext().globalState;\n\t\tconst cachedData: Record<string, boolean> | undefined = globalState.get(PREFER_SOURCEGRAPH_API);\n\t\treturn !isNil(cachedData?.[targetRepo]) ? !!cachedData?.[targetRepo] : true;\n\t}\n\n\tpublic async setPreferSourcegraphApi(value: boolean, repo?: string) {\n\t\tconst targetRepo = repo || (await getCurrentRepo());\n\t\tconst globalState = getExtensionContext().globalState;\n\t\tconst cachedData: Record<string, boolean> | undefined = globalState.get(PREFER_SOURCEGRAPH_API);\n\t\tawait globalState.update(PREFER_SOURCEGRAPH_API, { ...cachedData, [targetRepo]: value });\n\t\tthis._emitter.fire(value);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/index.ts",
    "content": "/**\n * @file GitLab1s adapter\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { GitLab1sRouterParser } from './router-parser';\nimport { GitLab1sDataSource } from './data-source';\nimport { SourcegraphDataSource } from '../sourcegraph/data-source';\nimport { Adapter, CodeReviewType, PlatformName } from '../types';\nimport { GitLab1sSettingsViewProvider } from './settings';\nimport { GitLab1sAuthenticationView } from './authentication';\nimport { setVSCodeContext } from '@/helpers/vscode';\nimport { getCurrentRepo } from './parse-path';\n\nexport class GitLab1sAdapter implements Adapter {\n\tpublic scheme: string = 'gitlab1s';\n\tpublic platformName = PlatformName.GitLab;\n\tpublic codeReviewType = CodeReviewType.MergeRequest;\n\n\tresolveDataSource() {\n\t\treturn Promise.resolve(GitLab1sDataSource.getInstance());\n\t}\n\n\tresolveRouterParser() {\n\t\treturn Promise.resolve(GitLab1sRouterParser.getInstance());\n\t}\n\n\tactivateAsDefault() {\n\t\t// register settings view and show it in activity bar\n\t\tsetVSCodeContext('github1s:views:settings:visible', true);\n\t\tsetVSCodeContext('github1s:views:codeReviewList:visible', true);\n\t\tsetVSCodeContext('github1s:views:commitList:visible', true);\n\t\tsetVSCodeContext('github1s:views:fileHistory:visible', true);\n\t\tsetVSCodeContext('github1s:features:gutterBlame:enabled', true);\n\n\t\tvscode.window.registerWebviewViewProvider(\n\t\t\tGitLab1sSettingsViewProvider.viewType,\n\t\t\tnew GitLab1sSettingsViewProvider(),\n\t\t);\n\t\tvscode.commands.registerCommand('github1s.commands.openGitLab1sAuthPage', () => {\n\t\t\treturn GitLab1sAuthenticationView.getInstance().open();\n\t\t});\n\t\tvscode.commands.registerCommand('github1s.commands.syncSourcegraphRepository', async () => {\n\t\t\tconst dataSource = SourcegraphDataSource.getInstance('gitlab');\n\t\t\tconst randomRef = (Math.random() + 1).toString(36).slice(2);\n\t\t\treturn dataSource.provideCommit(await getCurrentRepo(), randomRef);\n\t\t});\n\t}\n\n\tdeactivateAsDefault() {\n\t\tsetVSCodeContext('github1s:views:settings:visible', false);\n\t\tsetVSCodeContext('github1s:views:codeReviewList:visible', false);\n\t\tsetVSCodeContext('github1s:views:commitList:visible', false);\n\t\tsetVSCodeContext('github1s:views:fileHistory:visible', false);\n\t\tsetVSCodeContext('github1s:features:gutterBlame:enabled', false);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/parse-path.ts",
    "content": "/**\n * @file parse gitlab path\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { parsePath } from 'history';\nimport { PageType, RouterState } from '../types';\nimport { GitLab1sDataSource } from './data-source';\nimport { memorize } from '@/helpers/func';\nimport { getBrowserUrl } from '@/helpers/context';\n\nexport const DEFAULT_REPO = 'gitlab-org/gitlab-docs';\n\nexport const getCurrentRepo = memorize(() => {\n\treturn getBrowserUrl().then((browserUrl: string) => {\n\t\tconst pathParts = vscode.Uri.parse(browserUrl).path.split('/').filter(Boolean);\n\t\tconst dashIndex = pathParts.indexOf('-');\n\t\treturn (dashIndex < 0 ? pathParts : pathParts.slice(0, dashIndex)).join('/') || DEFAULT_REPO;\n\t});\n});\n\nconst getDefaultBranch = async (repo: string): Promise<string> => {\n\tconst dataSource = GitLab1sDataSource.getInstance();\n\treturn dataSource.getDefaultBranch(repo);\n};\n\nconst parseTreeUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst dashIndex = pathParts.indexOf('-');\n\tconst repo = (dashIndex < 0 ? pathParts : pathParts.slice(0, dashIndex)).join('/');\n\tconst restParts = dashIndex < 0 ? [] : pathParts.slice(dashIndex + 2);\n\tconst dataSource = GitLab1sDataSource.getInstance();\n\tconst { ref, path: filePath } = await dataSource.extractRefPath(repo, restParts.join('/'));\n\n\treturn { pageType: PageType.Tree, repo, ref, filePath };\n};\n\nconst parseBlobUrl = async (path: string): Promise<RouterState> => {\n\tconst routerState = (await parseTreeUrl(path)) as any;\n\tconst { hash: routerHash } = parsePath(path);\n\n\tif (!routerHash) {\n\t\treturn { ...routerState, pageType: PageType.Blob };\n\t}\n\n\t// get selected line number range from path which looks like:\n\t// `/gitlab-org/gitlab/-/blob/main/package.json#L10-L20`\n\tconst matches = routerHash.match(/^#L(\\d+)(?:-L(\\d+))?/);\n\tconst [_, startLineNumber = '0', endLineNumber] = matches ? matches : [];\n\n\treturn {\n\t\t...routerState,\n\t\tpageType: PageType.Blob,\n\t\tstartLine: parseInt(startLineNumber, 10),\n\t\tendLine: parseInt(endLineNumber || startLineNumber, 10),\n\t};\n};\n\nconst parseCommitsUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst dashIndex = pathParts.indexOf('-');\n\tconst repo = (dashIndex < 0 ? pathParts : pathParts.slice(0, dashIndex)).join('/');\n\tconst ref = dashIndex < 0 ? await getDefaultBranch(repo) : pathParts.slice(dashIndex + 2).join('/');\n\n\treturn { repo, pageType: PageType.CommitList, ref };\n};\n\nconst parseCommitUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst dashIndex = pathParts.indexOf('-');\n\tconst repo = (dashIndex < 0 ? pathParts : pathParts.slice(0, dashIndex)).join('/');\n\tconst commitSha = dashIndex < 0 ? await getDefaultBranch(repo) : pathParts.slice(dashIndex + 2).join('/');\n\n\treturn { repo, pageType: PageType.Commit, ref: commitSha, commitSha };\n};\n\nconst parseMergeRequestsUrl = async (path: string): Promise<RouterState> => {\n\tconst [owner, repo] = parsePath(path).pathname!.split('/').filter(Boolean);\n\n\treturn {\n\t\trepo: `${owner}/${repo}`,\n\t\tref: await getDefaultBranch(`${owner}/${repo}`),\n\t\tpageType: PageType.CodeReviewList,\n\t};\n};\n\nconst parseMergeRequestUrl = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname!.split('/').filter(Boolean);\n\tconst [owner, repo, , _pageType, codeReviewId] = pathParts;\n\tconst repoFullName = `${owner}/${repo}`;\n\tconst codeReview = await GitLab1sDataSource.getInstance().provideCodeReview(repoFullName, codeReviewId);\n\n\treturn {\n\t\trepo: `${owner}/${repo}`,\n\t\tpageType: PageType.CodeReview,\n\t\tref: codeReview.targetSha,\n\t\tcodeReviewId,\n\t};\n};\n\n// const parseSearchUrl = async (path: string): Promise<RouterState> => {\n// \tconst { pathname, search } = parsePath(path);\n// \tconst pathParts = pathname!.split('/').filter(Boolean);\n// \tconst [owner, repo, _pageType] = pathParts;\n// \tconst queryOptions = queryString.parse(search || '');\n// \tconst query = typeof queryOptions.q === 'string' ? queryOptions.q : '';\n// \tconst isRegex = queryOptions.regex === 'yes';\n// \tconst isCaseSensitive = queryOptions.case === 'yes';\n// \tconst matchWholeWord = queryOptions.whole === 'yes';\n// \tconst filesToInclude = typeof queryOptions['files-to-include'] === 'string' ? queryOptions['files-to-include'] : '';\n// \tconst filesToExclude = typeof queryOptions['files-to-exclude'] === 'string' ? queryOptions['files-to-exclude'] : '';\n\n// \treturn {\n// \t\trepo: `${owner}/${repo}`,\n// \t\tpageType: PageType.Search,\n// \t\tref: 'HEAD',\n// \t\tquery,\n// \t\tisRegex,\n// \t\tisCaseSensitive,\n// \t\tmatchWholeWord,\n// \t\tfilesToInclude,\n// \t\tfilesToExclude,\n// \t};\n// };\n\nconst PAGE_TYPE_MAP = {\n\ttree: PageType.Tree,\n\tblob: PageType.Blob,\n\tmerge_requests: PageType.CodeReview,\n\tcommit: PageType.Commit,\n\tcommits: PageType.CommitList,\n};\n\nexport const parseGitLabPath = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname?.split('/').filter(Boolean) || [];\n\tconst dashIndex = pathParts.indexOf('-');\n\tconst typeSegment = dashIndex < 0 ? '' : pathParts[dashIndex + 1];\n\tconst pageType = typeSegment ? PAGE_TYPE_MAP[typeSegment] || PageType.Unknown : PageType.Tree;\n\n\tif (pathParts.length) {\n\t\tswitch (pageType) {\n\t\t\tcase PageType.Tree:\n\t\t\tcase PageType.Unknown:\n\t\t\t\treturn parseTreeUrl(path);\n\t\t\tcase PageType.Blob:\n\t\t\t\treturn parseBlobUrl(path);\n\t\t\tcase PageType.CodeReview:\n\t\t\t\tif (pathParts.length > dashIndex + 2) {\n\t\t\t\t\treturn parseMergeRequestUrl(path);\n\t\t\t\t}\n\t\t\t\treturn parseMergeRequestsUrl(path);\n\t\t\tcase PageType.CodeReviewList:\n\t\t\t\treturn parseMergeRequestsUrl(path);\n\t\t\tcase PageType.Commit:\n\t\t\t\treturn parseCommitUrl(path);\n\t\t\tcase PageType.CommitList:\n\t\t\t\treturn parseCommitsUrl(path);\n\t\t}\n\t}\n\n\t// fallback to default\n\treturn {\n\t\trepo: DEFAULT_REPO,\n\t\tref: await getDefaultBranch(DEFAULT_REPO),\n\t\tpageType: PageType.Tree,\n\t\tfilePath: '',\n\t};\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/router-parser.ts",
    "content": "/**\n * @file router parser\n * @author netcon\n */\n\nimport { joinPath } from '@/helpers/util';\nimport * as adapterTypes from '../types';\nimport { parseGitLabPath } from './parse-path';\n\nexport class GitLab1sRouterParser extends adapterTypes.RouterParser {\n\tprivate static instance: GitLab1sRouterParser | null = null;\n\n\tpublic static getInstance(): GitLab1sRouterParser {\n\t\tif (GitLab1sRouterParser.instance) {\n\t\t\treturn GitLab1sRouterParser.instance;\n\t\t}\n\t\treturn (GitLab1sRouterParser.instance = new GitLab1sRouterParser());\n\t}\n\n\tparsePath(path: string): Promise<adapterTypes.RouterState> {\n\t\treturn parseGitLabPath(path);\n\t}\n\n\tbuildTreePath(repo: string, ref?: string, filePath?: string): string {\n\t\treturn ref ? (filePath ? `/${repo}/-/tree/${ref}/${filePath}` : `/${repo}/-/tree/${ref}`) : `/${repo}`;\n\t}\n\n\tbuildBlobPath(repo: string, ref: string, filePath: string, startLine?: number, endLine?: number): string {\n\t\tconst hash = startLine ? (endLine ? `#L${startLine}-L${endLine}` : `#L${startLine}`) : '';\n\t\treturn `/${repo}/-/blob/${ref}/${filePath}${hash}`;\n\t}\n\n\tbuildCommitListPath(repo: string): string {\n\t\treturn `/${repo}/-/commits`;\n\t}\n\n\tbuildCommitPath(repo: string, commitSha: string): string {\n\t\treturn `/${repo}/-/commit/${commitSha}`;\n\t}\n\n\tbuildCodeReviewListPath(repo: string): string {\n\t\treturn `/${repo}/-/merge_requests`;\n\t}\n\n\tbuildCodeReviewPath(repo: string, codeReviewId: string): string {\n\t\treturn `/${repo}/-/merge_requests/${codeReviewId}`;\n\t}\n\n\tbuildExternalLink(path: string): string {\n\t\treturn joinPath(GITLAB_ORIGIN, path);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/settings.ts",
    "content": "/**\n * @file GitLab1s Settings Webview Provider\n * @author netcon\n */\n\nimport { GitLabTokenManager } from './token';\nimport { GitLabFetcher } from './fetcher';\nimport { GitHub1sSettingsViewProvider } from '../github1s/settings';\n\nexport class GitLab1sSettingsViewProvider extends GitHub1sSettingsViewProvider {\n\tprotected tokenManager = GitLabTokenManager.getInstance();\n\tprotected apiFetcher = GitLabFetcher.getInstance();\n\n\tprotected OAuthCommand = 'github1s.commands.vscode.connectToGitLab';\n\tprotected detailPageCommand = 'github1s.commands.openGitLab1sAuthPage';\n\tprotected pageConfig = {\n\t\tpageDescriptionLines: [\n\t\t\t'You can provide a Personal Access Token or an OAuth token to access private repositories or to increase rate limits.',\n\t\t\t\"Your token will only be stored locally in your browser. Don't forget to clean it while you are using a public device.\",\n\t\t],\n\t\tOAuthButtonText: 'Connect to GitLab',\n\t\tcreateTokenLink: `${GITLAB_ORIGIN}/-/profile/personal_access_tokens?scopes=read_api&name=GitLab1s`,\n\t};\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/gitlab1s/token.ts",
    "content": "/**\n * @file gitlab api auth token manager\n */\n\nimport { GitHubTokenManager, ValidateResult } from '../github1s/token';\n\nexport class GitLabTokenManager extends GitHubTokenManager {\n\tprotected static instance: GitLabTokenManager | null = null;\n\tpublic tokenStateKey = 'gitlab-oauth-token';\n\n\tpublic static getInstance(): GitLabTokenManager {\n\t\tif (GitLabTokenManager.instance) {\n\t\t\treturn GitLabTokenManager.instance;\n\t\t}\n\t\treturn (GitLabTokenManager.instance = new GitLabTokenManager());\n\t}\n\n\tpublic async validateToken(token?: string): Promise<ValidateResult | null> {\n\t\tconst accessToken = token === undefined ? this.getToken() : token;\n\t\tif (!accessToken) {\n\t\t\treturn Promise.resolve(null);\n\t\t}\n\t\tconst fetchOptions: { headers: Record<string, string> } =\n\t\t\taccessToken?.length < 60\n\t\t\t\t? { headers: { 'PRIVATE-TOKEN': `${accessToken}` } }\n\t\t\t\t: { headers: { Authorization: `Bearer ${accessToken}` } };\n\t\treturn fetch(`${GITLAB_API_PREFIX}/user`, fetchOptions)\n\t\t\t.then((response) => {\n\t\t\t\tif (response.status === 401) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn response.json().then((data) => ({\n\t\t\t\t\tusername: data.username,\n\t\t\t\t\tavatar_url: data.avatar_url,\n\t\t\t\t\tprofile_url: data.web_url,\n\t\t\t\t}));\n\t\t\t})\n\t\t\t.catch(() => null);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/index.ts",
    "content": "/**\n * @file register the adapters\n * @author netcon\n */\n\nimport adapterManager from './manager';\nimport { GitHub1sAdapter } from './github1s';\nimport { GitLab1sAdapter } from './gitlab1s';\nimport { BitbucketAdapter } from './bitbucket1s';\nimport { Npmjs1sAdapter } from './npmjs1s';\nimport { OSSInsightAdapter } from './ossinsight';\nimport { DataSource, PlatformName, RouterParser } from './types';\n\nconst emptyAdapter = {\n\tscheme: 'empty',\n\tplatformName: PlatformName.GitHub,\n\tresolveDataSource: () => new DataSource(),\n\tresolveRouterParser: () => new RouterParser(),\n};\n\nexport const registerAdapters = async (): Promise<void> => {\n\tawait Promise.all([\n\t\tadapterManager.registerAdapter(emptyAdapter),\n\t\tadapterManager.registerAdapter(new GitHub1sAdapter()),\n\t\tadapterManager.registerAdapter(new GitLab1sAdapter()),\n\t\tadapterManager.registerAdapter(new BitbucketAdapter()),\n\t\tadapterManager.registerAdapter(new Npmjs1sAdapter()),\n\t\tadapterManager.registerAdapter(new OSSInsightAdapter()),\n\t]);\n};\n\nexport { adapterManager };\n"
  },
  {
    "path": "extensions/github1s/src/adapters/manager.ts",
    "content": "/**\n * @file Manages the adapters.\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { setVSCodeContext } from '@/helpers/vscode';\nimport { Adapter, Promisable } from './types';\n\nexport class AdapterManager {\n\tprivate static instance: AdapterManager | null = null;\n\tprivate adaptersMap: Map<string, Adapter> = new Map();\n\tprivate defaultAdapter: Adapter | null = null;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): AdapterManager {\n\t\tif (AdapterManager.instance) {\n\t\t\treturn AdapterManager.instance;\n\t\t}\n\t\treturn (AdapterManager.instance = new AdapterManager());\n\t}\n\n\tpublic registerAdapter(adapter: Adapter): Promisable<void> {\n\t\tif (this.adaptersMap.has(adapter.scheme)) {\n\t\t\tthrow new Error(`Adapter scheme '${adapter.scheme}' is already registered.`);\n\t\t}\n\t\tif (this.defaultAdapter && this.defaultAdapter.deactivateAsDefault) {\n\t\t\tthis.defaultAdapter.deactivateAsDefault();\n\t\t}\n\t\tthis.adaptersMap.set(adapter.scheme, adapter);\n\t\tif (this.getCurrentScheme() === adapter.scheme) {\n\t\t\tsetVSCodeContext('github1s:adapters:default:platformName', adapter.platformName);\n\t\t\tsetVSCodeContext('github1s:adapters:default:codeReviewType', adapter.codeReviewType);\n\t\t\treturn adapter.activateAsDefault && adapter.activateAsDefault();\n\t\t}\n\t}\n\n\tpublic getAllAdapters(): Adapter[] {\n\t\treturn Array.from(this.adaptersMap.values());\n\t}\n\n\tpublic getAdapter(scheme: string): Adapter {\n\t\tif (!this.adaptersMap.has(scheme)) {\n\t\t\tthrow new Error(`Adapter with scheme '${scheme}' can not found.`);\n\t\t}\n\t\treturn this.adaptersMap.get(scheme)!;\n\t}\n\n\tpublic getCurrentScheme(): string {\n\t\treturn vscode.workspace.workspaceFolders?.[0]?.uri?.scheme || 'empty';\n\t}\n\n\tpublic getCurrentAdapter(): Adapter {\n\t\tconst scheme = this.getCurrentScheme();\n\t\treturn this.getAdapter(scheme);\n\t}\n}\n\nexport default AdapterManager.getInstance();\n"
  },
  {
    "path": "extensions/github1s/src/adapters/npmjs1s/data-source.ts",
    "content": "/**\n * @file npm data-source-provider\n * @author netcon\n */\n\nimport { CommonQueryOptions, DataSource, Directory, DirectoryEntry, File, FileType, Tag } from '../types';\nimport { matchSorter } from 'match-sorter';\nimport * as dayjs from 'dayjs';\n\ntype PackageFile = {\n\tpath: string;\n\tsize: number;\n\ttype: 'file';\n};\n\ntype PackageDirectory = {\n\tfiles: PackageEntry[];\n\ttype: 'directory';\n\tpath: string;\n};\n\ntype PackageEntry = PackageFile | PackageDirectory;\n\ntype PackageVersion = { name: string; tag?: string; time?: Date };\n\nconst retrieveFiles = (files: PackageEntry[], pathDeep: number, recursive: boolean) => {\n\tconst entries: DirectoryEntry[] = [];\n\tfor (const item of files) {\n\t\tconst fileType = item.type === 'directory' ? FileType.Directory : FileType.File;\n\t\tconst filePath = item.path.split(/\\/+/).filter(Boolean).slice(pathDeep).join('/');\n\t\tentries.push({ type: fileType, path: filePath });\n\t\tif (recursive && item.type === 'directory' && item.files?.length) {\n\t\t\tentries.push(...retrieveFiles(item.files, pathDeep, recursive));\n\t\t}\n\t}\n\treturn entries;\n};\n\nexport class Npmjs1sDataSource extends DataSource {\n\tprivate static instance: Npmjs1sDataSource | null = null;\n\tprivate _filesPromiseMap: Map<string, Promise<PackageEntry[]>> = new Map();\n\tprivate _versionsPromiseMap: Map<string, Promise<PackageVersion[]>> = new Map();\n\n\tpublic static getInstance(): Npmjs1sDataSource {\n\t\tif (Npmjs1sDataSource.instance) {\n\t\t\treturn Npmjs1sDataSource.instance;\n\t\t}\n\t\treturn (Npmjs1sDataSource.instance = new Npmjs1sDataSource());\n\t}\n\n\tgetPackageFiles(packageName: string, version: string): Promise<PackageEntry[]> {\n\t\tconst mapKey = `${packageName} ${version}`;\n\t\tif (!this._filesPromiseMap.has(mapKey)) {\n\t\t\tconst requestUrl = `https://unpkg.com/${packageName}@${version}/?meta`;\n\t\t\tconst filesPromise = fetch(requestUrl)\n\t\t\t\t.then((response) => response.json())\n\t\t\t\t.then((data) => data?.files || []);\n\t\t\tthis._filesPromiseMap.set(mapKey, filesPromise);\n\t\t}\n\t\treturn this._filesPromiseMap.get(mapKey)!;\n\t}\n\n\tasync provideDirectory(packageName: string, version: string, path: string, recursive = false): Promise<Directory> {\n\t\tconst pathParts = path.split(/\\/+/).filter(Boolean);\n\t\tconst parentFiles = pathParts.reduce(\n\t\t\t(prevFiles, _, index) => {\n\t\t\t\tconst currentPath = `/${pathParts.slice(0, index + 1).join('/')}`;\n\t\t\t\tconst fileNode = prevFiles?.find((item) => item.path === currentPath);\n\t\t\t\treturn fileNode?.type === 'directory' ? fileNode.files : null;\n\t\t\t},\n\t\t\tawait this.getPackageFiles(packageName, version),\n\t\t);\n\t\tconst entries = parentFiles ? retrieveFiles(parentFiles, pathParts.length, recursive) : [];\n\t\treturn { entries, truncated: false };\n\t}\n\n\tasync provideFile(packageName: string, version: string, path: string): Promise<File> {\n\t\tconst response = await fetch(`https://unpkg.com/${packageName}@${version}/${path}`);\n\t\treturn { content: new Uint8Array(await response.arrayBuffer()) };\n\t}\n\n\tgetPackageVersions(packageName: string): Promise<PackageVersion[]> {\n\t\tif (!this._versionsPromiseMap.has(packageName)) {\n\t\t\tconst versionsPromise = new Promise<PackageVersion[]>(async (resolve, reject) => {\n\t\t\t\tconst requestUrl = `https://registry.npmjs.org/${packageName}`;\n\t\t\t\tconst data = await fetch(requestUrl).then((response) => response.json(), reject);\n\t\t\t\tconst tagEntries = Object.entries(data?.['dist-tags'] || {}) as [string, string][];\n\t\t\t\tconst versionTag = tagEntries.reduce((prevVersionTag, [tag, version]) => {\n\t\t\t\t\tprevVersionTag[version] = tag;\n\t\t\t\t\treturn prevVersionTag;\n\t\t\t\t}, {}) as Record<string, string>;\n\t\t\t\tconst packageVersions = Object.keys(data?.versions || {}).map((version) => {\n\t\t\t\t\tconst releaseTime = data?.time?.[version] ? new Date(data.time[version]) : undefined;\n\t\t\t\t\treturn { name: version, tag: versionTag[version], time: releaseTime };\n\t\t\t\t});\n\t\t\t\tconst sortByTimeDesc = (versionA, versionB) => {\n\t\t\t\t\tif (+!versionA.tag ^ +!versionB.tag) {\n\t\t\t\t\t\treturn versionA.tag ? -1 : 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn versionB.time?.getTime() - versionA.time?.getTime();\n\t\t\t\t};\n\t\t\t\treturn resolve(packageVersions.sort(sortByTimeDesc));\n\t\t\t});\n\t\t\tthis._versionsPromiseMap.set(packageName, versionsPromise);\n\t\t}\n\t\treturn this._versionsPromiseMap.get(packageName)!;\n\t}\n\n\ttransformVersionToTag(version: PackageVersion) {\n\t\tconst tagPart = version.tag ? `${version.tag}, ` : '';\n\t\tconst timePart = version.time ? `published at ${dayjs(version.time).format('YYYY-MM-DD HH:mm:ss')}` : '';\n\t\treturn { name: version.name, description: `${tagPart}${timePart}` };\n\t}\n\n\tasync provideTags(packageName: string, options?: CommonQueryOptions): Promise<Tag[]> {\n\t\tconst versions = await this.getPackageVersions(packageName);\n\t\tconst allTags = versions.map((version) => this.transformVersionToTag(version));\n\t\tconst matchedTags = options?.query ? matchSorter(allTags, options.query, { keys: ['name'] }) : allTags;\n\t\tif (options?.pageSize) {\n\t\t\tconst page = options.page || 1;\n\t\t\tconst pageSize = options.pageSize;\n\t\t\treturn matchedTags.slice(pageSize * (page - 1), pageSize * page);\n\t\t}\n\t\treturn matchedTags;\n\t}\n\n\tasync provideTag(packageName: string, tagName: string): Promise<Tag | null> {\n\t\tconst versions = await this.getPackageVersions(packageName);\n\t\tconst matchedVersion = versions.find((tag) => tag.name === tagName);\n\t\treturn matchedVersion ? this.transformVersionToTag(matchedVersion) : null;\n\t}\n\n\tprovideUserAvatarLink(user: string): string {\n\t\treturn `https://www.gravatar.com/avatar/${user}?d=identicon`;\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/npmjs1s/index.ts",
    "content": "/**\n * @file Npmjs1s adapter\n * @author netcon\n */\n\nimport { Npmjs1sDataSource } from './data-source';\nimport { Npmjs1sRouterParser } from './router-parser';\nimport { Adapter, PlatformName } from '../types';\n\nexport class Npmjs1sAdapter implements Adapter {\n\tpublic scheme: string = 'npmjs1s';\n\tpublic platformName = PlatformName.npm;\n\n\tresolveDataSource() {\n\t\treturn Npmjs1sDataSource.getInstance();\n\t}\n\n\tresolveRouterParser() {\n\t\treturn Npmjs1sRouterParser.getInstance();\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/npmjs1s/router-parser.ts",
    "content": "/**\n * @file router parser\n * @author netcon\n */\n\nimport { parsePath } from 'history';\nimport { PageType, RouterParser, RouterState } from '../types';\n\nexport const parseNpmPath = async (path: string): Promise<RouterState> => {\n\tconst pathParts = parsePath(path).pathname?.split('/').filter(Boolean) || [];\n\n\tif (!pathParts.length) {\n\t\treturn { pageType: PageType.Tree, repo: 'lodash', ref: 'latest', filePath: '' };\n\t}\n\n\tconst trimedParts = pathParts[0] === 'package' ? pathParts.slice(1) : pathParts;\n\tconst packagePartsLength = trimedParts[0] && trimedParts[0][0] === '@' ? 2 : 1;\n\tconst packageParts = trimedParts.slice(0, packagePartsLength);\n\tconst packageName = packageParts.join('/') || 'package';\n\tconst packageVersion =\n\t\ttrimedParts[packagePartsLength] === 'v' ? trimedParts[packagePartsLength + 1] || 'latest' : 'latest';\n\n\treturn { pageType: PageType.Tree as const, repo: packageName, ref: packageVersion, filePath: '' };\n};\n\nexport class Npmjs1sRouterParser extends RouterParser {\n\tprivate static instance: Npmjs1sRouterParser | null = null;\n\n\tpublic static getInstance(): Npmjs1sRouterParser {\n\t\tif (Npmjs1sRouterParser.instance) {\n\t\t\treturn Npmjs1sRouterParser.instance;\n\t\t}\n\t\treturn (Npmjs1sRouterParser.instance = new Npmjs1sRouterParser());\n\t}\n\n\tparsePath(path: string): Promise<RouterState> {\n\t\treturn parseNpmPath(path);\n\t}\n\n\tbuildTreePath(packageName: string, version: string): string {\n\t\treturn `/package/${packageName}${version === 'latest' ? '' : `/v/${version}`}`;\n\t}\n\n\tbuildBlobPath(packageName: string, version: string): string {\n\t\treturn `/package/${packageName}${version === 'latest' ? '' : `/v/${version}`}`;\n\t}\n\n\tbuildCommitListPath(packageName: string): string {\n\t\treturn `/package/${packageName}`;\n\t}\n\n\tbuildCommitPath(packageName: string): string {\n\t\treturn `/package/${packageName}`;\n\t}\n\n\tbuildCodeReviewListPath(packageName: string): string {\n\t\treturn `/package/${packageName}`;\n\t}\n\n\tbuildCodeReviewPath(packageName: string): string {\n\t\treturn `/package/${packageName}`;\n\t}\n\n\tbuildExternalLink(path: string): string {\n\t\treturn 'https://npmjs.com' + (path.startsWith('/') ? path : `/${path}`);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/ossinsight/constants.ts",
    "content": "/**\n * @file trending constants\n * @author netcon\n */\n\nexport enum RankingPeriod {\n\tToday = 'Today',\n\tThisWeek = 'ThisWeek',\n\tThisMonth = 'ThisMonth',\n}\n\nexport const RankingLanguages = [\n\t'JavaScript',\n\t'Java',\n\t'Python',\n\t'PHP',\n\t'C++',\n\t'C#',\n\t'TypeScript',\n\t'Shell',\n\t'C',\n\t'Ruby',\n\t'Rust',\n\t'Go',\n\t'Kotlin',\n\t'HCL',\n\t'PowerShell',\n\t'CMake',\n\t'Groovy',\n\t'PLpgSQL',\n\t'TSQL',\n\t'Dart',\n\t'Swift',\n\t'HTML',\n\t'CSS',\n\t'Elixir',\n\t'Haskell',\n\t'Solidity',\n\t'Assembly',\n\t'R',\n\t'Scala',\n\t'Julia',\n\t'Lua',\n\t'Clojure',\n\t'Erlang',\n\t'Common Lisp',\n\t'Emacs Lisp',\n\t'OCaml',\n\t'MATLAB',\n\t'Objective-C',\n\t'Perl',\n\t'Fortran',\n];\n"
  },
  {
    "path": "extensions/github1s/src/adapters/ossinsight/data-source.ts",
    "content": "/**\n * @file trending page data source\n * @author netcon\n */\n\nimport { joinPath } from '@/helpers/util';\nimport { getCollections } from './interfaces';\nimport { RankingLanguages, RankingPeriod } from './constants';\nimport { DataSource, Directory, File, FileType, Promisable } from '../types';\nimport {\n\tcreateCollectionPageMarkdown,\n\tcreateCollectionsListPageMarkdown,\n\tcreateLanguageListPageMarkdown,\n\tcreateRankingPageMarkdown,\n} from './templates';\n\ntype StructureItem =\n\t| {\n\t\t\ttype: FileType.Directory;\n\t\t\tname: string;\n\t\t\tchildren: StructureItem[] | (() => Promisable<StructureItem[]>);\n\t  }\n\t| {\n\t\t\ttype: FileType.File;\n\t\t\tname: string;\n\t\t\tcontent?: string | (() => Promisable<string>);\n\t  };\n\nexport class OSSInsightDataSource extends DataSource {\n\tprivate static instance: OSSInsightDataSource | null = null;\n\tprivate textEncodder = new TextEncoder();\n\tprivate rootStructure: StructureItem = {\n\t\ttype: FileType.Directory,\n\t\tname: '',\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: FileType.Directory,\n\t\t\t\tname: 'collections',\n\t\t\t\tchildren: () =>\n\t\t\t\t\tgetCollections().then((collections) => {\n\t\t\t\t\t\tconst collectionsSet = new Set(collections.map((collection) => collection.name));\n\t\t\t\t\t\treturn Array.from(collectionsSet).map((collection) => ({\n\t\t\t\t\t\t\ttype: FileType.File,\n\t\t\t\t\t\t\tname: `${collection}.md`,\n\t\t\t\t\t\t\tcontent: () => createCollectionPageMarkdown(collection),\n\t\t\t\t\t\t}));\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: FileType.Directory,\n\t\t\t\tname: 'languages',\n\t\t\t\tchildren: () =>\n\t\t\t\t\tRankingLanguages.map((language) => {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: FileType.Directory,\n\t\t\t\t\t\t\tname: language,\n\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: FileType.File,\n\t\t\t\t\t\t\t\t\tname: `${language}_Today.md`,\n\t\t\t\t\t\t\t\t\tcontent: () => createRankingPageMarkdown(RankingPeriod.Today, language),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: FileType.File,\n\t\t\t\t\t\t\t\t\tname: `${language}_ThisWeek.md`,\n\t\t\t\t\t\t\t\t\tcontent: () => createRankingPageMarkdown(RankingPeriod.ThisWeek, language),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: FileType.File,\n\t\t\t\t\t\t\t\t\tname: `${language}_ThisMonth.md`,\n\t\t\t\t\t\t\t\t\tcontent: () => createRankingPageMarkdown(RankingPeriod.ThisMonth, language),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: FileType.File,\n\t\t\t\tname: 'Collections.md',\n\t\t\t\tcontent: () => createCollectionsListPageMarkdown(),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: FileType.File,\n\t\t\t\tname: 'Languages.md',\n\t\t\t\tcontent: () => createLanguageListPageMarkdown(),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: FileType.File,\n\t\t\t\tname: 'README.md',\n\t\t\t\tcontent: () => createRankingPageMarkdown(RankingPeriod.Today),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: FileType.File,\n\t\t\t\tname: 'ThisMonth.md',\n\t\t\t\tcontent: () => createRankingPageMarkdown(RankingPeriod.ThisMonth),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: FileType.File,\n\t\t\t\tname: 'ThisWeek.md',\n\t\t\t\tcontent: () => createRankingPageMarkdown(RankingPeriod.ThisWeek),\n\t\t\t},\n\t\t],\n\t};\n\n\tpublic static getInstance(): OSSInsightDataSource {\n\t\tif (OSSInsightDataSource.instance) {\n\t\t\treturn OSSInsightDataSource.instance;\n\t\t}\n\t\treturn (OSSInsightDataSource.instance = new OSSInsightDataSource());\n\t}\n\n\tasync getStructureItemChildren(item?: StructureItem) {\n\t\tif (item?.type !== FileType.Directory) {\n\t\t\tthrow new Error('Not a directory');\n\t\t}\n\t\tif (typeof item.children === 'function') {\n\t\t\titem.children = await item.children();\n\t\t}\n\t\treturn item.children;\n\t}\n\n\tasync resolveStructureItem(path: string) {\n\t\tlet structureItem: StructureItem | undefined = this.rootStructure;\n\t\tfor (const pathPart of path.split('/').filter(Boolean)) {\n\t\t\tconst children = await this.getStructureItemChildren(structureItem);\n\t\t\tstructureItem = children.find((child) => child.name === pathPart);\n\t\t}\n\t\treturn structureItem;\n\t}\n\n\tasync provideDirectory(repo: string, ref: string, path: string, recursive?: boolean): Promise<Directory> {\n\t\tconst walk = async (item: StructureItem | undefined, recursive = false, basePath = '') => {\n\t\t\tconst directoryEntires: Directory['entries'] = [];\n\t\t\tfor (const child of await this.getStructureItemChildren(item)) {\n\t\t\t\tconst currentPath = joinPath(basePath, child.name);\n\t\t\t\tdirectoryEntires.push({ type: child.type, path: currentPath });\n\t\t\t\tif (recursive && child.type === FileType.Directory) {\n\t\t\t\t\tdirectoryEntires.push(...(await walk(child, recursive, currentPath)));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn directoryEntires;\n\t\t};\n\n\t\treturn {\n\t\t\ttruncated: false,\n\t\t\tentries: await walk(await this.resolveStructureItem(path), recursive),\n\t\t};\n\t}\n\n\tasync provideFile(repo: string, ref: string, path: string): Promise<File> {\n\t\tconst structureItem = await this.resolveStructureItem(path);\n\t\tif (structureItem?.type !== FileType.File) {\n\t\t\tthrow new Error('Not a file');\n\t\t}\n\t\tif (typeof structureItem.content === 'function') {\n\t\t\tstructureItem.content = await structureItem.content();\n\t\t}\n\t\treturn {\n\t\t\tcontent: this.textEncodder.encode(structureItem.content) || '',\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/ossinsight/index.ts",
    "content": "/**\n * @file OSSInsight adapter\n * @author netcon\n */\n\nimport { OSSInsightDataSource } from './data-source';\nimport { OSSInsightRouterParser } from './router-parser';\nimport { Adapter, PlatformName } from '../types';\n\nexport class OSSInsightAdapter implements Adapter {\n\tpublic scheme: string = 'ossinsight';\n\tpublic platformName = PlatformName.GitHub;\n\n\tasync resolveDataSource() {\n\t\treturn OSSInsightDataSource.getInstance();\n\t}\n\n\tasync resolveRouterParser() {\n\t\treturn OSSInsightRouterParser.getInstance();\n\t}\n\n\tactivateAsDefault() {}\n\n\tdeactivateAsDefault() {}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/ossinsight/interfaces.ts",
    "content": "/**\n * @file trending interfaces\n * @author netcon\n */\n\nimport { memorize } from '@/helpers/func';\nimport { RankingPeriod } from './constants';\n\nconst OSSInsightEndpoint = `https://api.ossinsight.io`;\n\nconst resolveDataFromResponse = (response: Response) => {\n\tif (response.status < 200 || response.status >= 300) {\n\t\treturn [];\n\t}\n\treturn response.json().then((body) => body?.data?.rows || []);\n};\n\nexport type RepoItem = {\n\tcollection_names?: string;\n\tcontributor_logins?: string;\n\tdescription?: string;\n\tforks: string;\n\tlanguage?: string;\n\trepo_name: string;\n\tstars: string;\n\ttotal_score: string;\n};\n\nexport const getTrendingRepos = (period: RankingPeriod, language: string): Promise<RepoItem[]> => {\n\tconst encodedLanguage = encodeURIComponent(language) || 'All';\n\tconst periodValue =\n\t\tperiod === RankingPeriod.Today ? 'past_24_hours' : RankingPeriod.ThisWeek ? 'past_week' : 'past_month';\n\tconst requestUrl = `${OSSInsightEndpoint}/v1/trends/repos/?language=${encodedLanguage}&period=${periodValue}`;\n\treturn fetch(requestUrl).then(resolveDataFromResponse);\n};\n\nexport type RecentHotCollectionItem = {\n\tid: string;\n\tname: string;\n\trepos: string;\n\trepo_id: string;\n\trepo_name: string;\n\trepo_rank_changes: string;\n\trepo_past_period_rank: string;\n\trepo_current_period_rank: string;\n};\n\nexport const getRecentHotCollections = (): Promise<RecentHotCollectionItem[]> => {\n\tconst requestUrl = `${OSSInsightEndpoint}/v1/collections/hot/`;\n\treturn fetch(requestUrl).then(resolveDataFromResponse);\n};\n\nexport type CollectionItem = {\n\tid: string;\n\tname: string;\n};\n\nexport const getCollections = memorize((): Promise<CollectionItem[]> => {\n\tconst requestUrl = `${OSSInsightEndpoint}/v1/collections/`;\n\treturn fetch(requestUrl).then(resolveDataFromResponse);\n});\n\nexport const getCollectionIdByName = async (collectionName: string): Promise<string | null> => {\n\tconst collections = await getCollections();\n\treturn collections.find((item) => item.name === collectionName)?.id || null;\n};\n\nexport type Last28DaysRankItem = {\n\trepo_id: string;\n\trepo_name: string;\n\tcurrent_period_growth: string;\n\tpast_period_growth: string;\n\tgrowth_pop: string;\n\trank_pop: string;\n\ttotal: string;\n\tcurrent_period_rank: string;\n\tpast_period_rank: string;\n};\n\nexport const getCollectionStarsLast28DaysRank = (collectionId: string): Promise<Last28DaysRankItem[]> => {\n\tconst requestUrl = `${OSSInsightEndpoint}/v1/collections/${collectionId}/ranking_by_stars/`;\n\treturn fetch(requestUrl).then(resolveDataFromResponse);\n};\n\nexport const getCollectionPullRequestsLast28DaysRank = (collectionId: string): Promise<Last28DaysRankItem[]> => {\n\tconst requestUrl = `${OSSInsightEndpoint}/v1/collections/${collectionId}/ranking_by_issues/`;\n\treturn fetch(requestUrl).then(resolveDataFromResponse);\n};\n\nexport const getCollectionIssuesLast28DaysRank = (collectionId: string): Promise<Last28DaysRankItem[]> => {\n\tconst requestUrl = `${OSSInsightEndpoint}/v1/collections/${collectionId}/ranking_by_prs/`;\n\treturn fetch(requestUrl).then(resolveDataFromResponse);\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/ossinsight/router-parser.ts",
    "content": "/**\n * @file router parser\n * @author netcon\n */\n\nimport { parsePath } from 'history';\nimport * as queryString from 'query-string';\nimport * as adapterTypes from '../types';\nimport { GitHub1sRouterParser } from '../github1s/router-parser';\n\nexport class OSSInsightRouterParser extends GitHub1sRouterParser {\n\tprotected static instance: OSSInsightRouterParser | null = null;\n\n\tpublic static getInstance(): OSSInsightRouterParser {\n\t\tif (OSSInsightRouterParser.instance) {\n\t\t\treturn OSSInsightRouterParser.instance;\n\t\t}\n\t\treturn (OSSInsightRouterParser.instance = new OSSInsightRouterParser());\n\t}\n\n\tasync parsePath(path: string): Promise<adapterTypes.RouterState> {\n\t\tconst { path: pathsOrNull } = queryString.parse((parsePath(path).search || '').slice(1));\n\t\tconst filePath = (Array.isArray(pathsOrNull) ? pathsOrNull[0] : pathsOrNull) || '';\n\t\tconst pageType = filePath.endsWith('.md') ? adapterTypes.PageType.Blob : adapterTypes.PageType.Tree;\n\t\treturn { pageType, repo: '', ref: '', filePath };\n\t}\n\n\tbuildTreePath(repo: string, ref?: string, filePath?: string) {\n\t\treturn repo ? super.buildTreePath(repo, ref, filePath) : '/';\n\t}\n\n\tbuildBlobPath(repo: string, ref: string, filePath: string, startLine?: number, endLine?: number) {\n\t\treturn repo ? super.buildBlobPath(repo, ref, filePath, startLine, endLine) : '/';\n\t}\n\n\tbuildCommitListPath(repo: string) {\n\t\treturn repo ? super.buildCommitListPath(repo) : '/';\n\t}\n\n\tbuildCommitPath(repo: string, commitSha: string) {\n\t\treturn repo ? super.buildCommitPath(repo, commitSha) : '/';\n\t}\n\n\tbuildCodeReviewListPath(repo: string) {\n\t\treturn repo ? super.buildCodeReviewListPath(repo) : '/';\n\t}\n\n\tbuildCodeReviewPath(repo: string, codeReviewId: string) {\n\t\treturn repo ? super.buildCodeReviewPath(repo, codeReviewId) : '/';\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/ossinsight/templates.ts",
    "content": "/**\n * @file Trending page\n * @author netcon\n */\n\nimport { trimEnd } from '@/helpers/util';\nimport { RankingLanguages, RankingPeriod } from './constants';\nimport {\n\tgetCollections,\n\tgetCollectionIdByName,\n\tgetCollectionIssuesLast28DaysRank,\n\tgetCollectionPullRequestsLast28DaysRank,\n\tgetCollectionStarsLast28DaysRank,\n\tgetRecentHotCollections,\n\tgetTrendingRepos,\n\tRepoItem,\n} from './interfaces';\n\nconst buildRepoLink = (repo: string) => `https://github1s.com/${repo}`;\n\nconst dataSourceMarkdown = ` (Data source: [👁️ OSS Insight](https://ossinsight.io/?utm_source=github1s&utm_medium=github&utm_campaign=ghtrending))`;\n\nconst createRepoItemMarkdown = (repo: RepoItem, period: RankingPeriod) => {\n\tconst contributorAvatars = (repo.contributor_logins?.split(',') || []).map((username) => {\n\t\t// too many avatars may trigger github rate limits\n\t\t// return `[<img class=\"avatar\" src=\"https://github.com/${username}.png\" alt=\"${username}\" width=\"18\" style=\"border-radius: 50%; vertical-align: middle;\">](https://github.com/${username})`;\n\t\treturn `[${username}](https://github.com/${username})`;\n\t});\n\tconst repoBadges = [\n\t\t`[![Language](https://img.shields.io/github/languages/top/${repo.repo_name})](https://github.com/${repo.repo_name})`,\n\t\t`[![Watch](https://img.shields.io/github/watchers/${repo.repo_name}?label=Watch)](https://github.com/${repo.repo_name}/watchers)`,\n\t\t`[![Fork](https://img.shields.io/github/forks/${repo.repo_name}?label=Fork)](https://github.com/${repo.repo_name}/forks)`,\n\t\t`[![Star](https://img.shields.io/github/stars/${repo.repo_name}?label=Star)](https://github.com/${repo.repo_name}/stargazers)`,\n\t\t`[![LastCommit](https://img.shields.io/github/last-commit/${repo.repo_name})](https://github.com/${repo.repo_name}/commits)`,\n\t];\n\n\tconst increaseStarsText = (+repo.stars || 0) >= 0 ? `+${repo.stars || 0}` : `-${repo.stars}`;\n\tconst increaseForksText = (+repo.forks || 0) >= 0 ? `+${repo.forks || 0}` : `-${repo.forks}`;\n\tconst contributorsMarkdown = contributorAvatars.length\n\t\t? ' &nbsp;&nbsp; Built by &nbsp;' + contributorAvatars.join('&nbsp;&nbsp;')\n\t\t: '';\n\tconst collectionMarkdown = repo.collection_names ? ` &nbsp;&nbsp; <i>${repo.collection_names}</i>` : '';\n\tconst fireThreshold = period === RankingPeriod.ThisWeek ? 5000 : period === RankingPeriod.ThisMonth ? 12000 : 1000;\n\n\treturn `\n## ${(+repo.total_score || 0) >= fireThreshold ? '🔥' : '🚀'} [${repo.repo_name}](${buildRepoLink(repo.repo_name)})\n\n${repo.description || ''}\n\n⭐️ ${increaseStarsText} &nbsp;&nbsp; 🔗 ${increaseForksText} ${contributorsMarkdown}${collectionMarkdown}\n\n${repoBadges.join('&nbsp;')}\n`;\n};\n\nexport type PageType = RankingPeriod | 'Languages' | 'Collections' | '';\nconst createRankingsLinksMarkdown = (page: PageType) => {\n\tconst rankingLinks = [\n\t\tpage !== RankingPeriod.Today ? `[Today](/README.md)` : 'Today',\n\t\tpage !== RankingPeriod.ThisWeek ? `[This Week](/ThisWeek.md)` : 'This Week',\n\t\tpage !== RankingPeriod.ThisMonth ? `[This Month](/ThisMonth.md)` : 'This Month',\n\t\tpage !== 'Languages' ? `[Languages](/Languages.md)` : 'Languages',\n\t\tpage !== 'Collections' ? `[Collections](/Collections.md)` : 'Collections',\n\t\t`[GitHub Trending](https://github.com/trending)`,\n\t];\n\treturn rankingLinks.join(' &nbsp;&nbsp; ');\n};\n\nexport const createRankingPageMarkdown = async (period: RankingPeriod, language = '', collection = '') => {\n\tconst periodTextInTitle =\n\t\tperiod === RankingPeriod.ThisWeek ? 'This Week' : period === RankingPeriod.ThisMonth ? 'This Month' : 'Today';\n\tconst periodTextInContent =\n\t\tperiod === RankingPeriod.ThisWeek ? 'this week' : period === RankingPeriod.ThisMonth ? 'this month' : 'today';\n\n\tconst repoItems = (await getTrendingRepos(period, language)).slice(0, 30);\n\tconst repoItemsMarkdown = repoItems.map((repo) => createRepoItemMarkdown(repo, period));\n\tconst currentPage = language || collection ? '' : period;\n\n\treturn `\n# Trending Repos ${periodTextInTitle}${language ? ` (${language})` : ''}\n\nSee what the GitHub community is most excited about ${periodTextInContent}.${dataSourceMarkdown}\n\nOther Rankings: &nbsp; ${createRankingsLinksMarkdown(currentPage)}\n\n***\n\n${repoItemsMarkdown.join('\\n\\n***\\n\\n')}\n\n***\n`;\n};\n\nexport const createLanguageListPageMarkdown = () => {\n\tconst languageListMarkdown = RankingLanguages.map((language) => {\n\t\tconst todayLink = encodeURIComponent(`./languages/${language}/${language}_Today.md`);\n\t\tconst thisWeekLink = encodeURIComponent(`./languages/${language}/${language}_ThisWeek.md`);\n\t\tconst thisMonthLink = encodeURIComponent(`./languages/${language}/${language}_ThisMonth.md`);\n\t\treturn `${language} | [Today](${todayLink}) | [This Week](${thisWeekLink}) | [This Month](${thisMonthLink})`;\n\t});\n\n\treturn `\n# Trending Repos by Languages\n\nSee what the GitHub community is most excited by languages.${dataSourceMarkdown}  \n\nOther Rankings: &nbsp; ${createRankingsLinksMarkdown('Languages')}\n\n***\n\n| Language | Today | This Week | This Month |\n| -- | -- | -- | -- |\n${languageListMarkdown.join('\\n')}\n\n***\n`;\n};\n\nconst getPopCountText = (pop_count: number, percentage = false) => {\n\tconst absValue = Math.abs(pop_count);\n\tconst valueText = percentage ? `${trimEnd(absValue.toFixed(1), '0.')}%` : absValue;\n\treturn pop_count > 0\n\t\t? ` <span style=\"color: #30d158\">(+${valueText})</span>`\n\t\t: pop_count < 0\n\t\t\t? ` <span style=\"color: #ff453a\">(-${valueText})</span>`\n\t\t\t: '';\n};\n\nconst getRankChangeText = (rank_change: number) => {\n\tconst absValue = Math.abs(rank_change);\n\treturn rank_change > 0\n\t\t? ` <span style=\"color: #ff453a\">(↓${absValue})</span>`\n\t\t: rank_change < 0\n\t\t\t? ` <span style=\"color: #30d158\">(↑${absValue})</span>`\n\t\t\t: '';\n};\n\nexport const createCollectionsListPageMarkdown = async () => {\n\tconst collectionReposMap = new Map<string, [string, string][]>();\n\tconst [hotCollections, allCollections] = await Promise.all([getRecentHotCollections(), getCollections()]);\n\tconst sortedCollections = hotCollections.sort(\n\t\t(itemA, itemB) => +itemA.repo_current_period_rank - +itemB.repo_current_period_rank,\n\t);\n\tconst uniqueCollections = sortedCollections.filter((collection) => {\n\t\tconst relativeRankText = getRankChangeText(+collection.repo_rank_changes);\n\t\tif (!collectionReposMap.has(collection.name)) {\n\t\t\tcollectionReposMap.set(collection.name, [[collection.repo_name, relativeRankText]]);\n\t\t\treturn true;\n\t\t}\n\t\tcollectionReposMap.get(collection.name)?.push([collection.repo_name, relativeRankText]);\n\t\treturn false;\n\t});\n\n\tconst hotCollectionsMarkdown = uniqueCollections.map((collection) => {\n\t\tconst collectionMarkdown = ` [${collection.name}](/collections/${encodeURIComponent(collection.name)}.md)`;\n\t\tconst repos = [...(collectionReposMap.get(collection.name) || [])];\n\t\tconst firstRepo = repos[0] ? `[${repos[0][0]}](${buildRepoLink(repos[0][0])})${repos[0][1]} ` : '';\n\t\tconst secondRepo = repos[1] ? `[${repos[1][0]}](${buildRepoLink(repos[1][0])})${repos[1][1]} ` : '';\n\t\tconst thirdRepo = repos[2] ? `[${repos[2][0]}](${buildRepoLink(repos[2][0])})${repos[2][1]} ` : '';\n\t\tconst hotReposMarkdown = ` ${firstRepo}| ${secondRepo}| ${thirdRepo}|`;\n\t\treturn `|${collectionMarkdown} | ${collection.repos} |${hotReposMarkdown} |`;\n\t});\n\n\tconst allCollectionsMarkdown = allCollections.map((collection) => {\n\t\treturn `[${collection.name}](/collections/${encodeURIComponent(collection.name)}.md)`;\n\t});\n\n\treturn `\n# Trending Repos by Collections\n\nInsights about the monthly and historical rankings and trends in technical fields with curated repository lists.${dataSourceMarkdown}\n\nOther Rankings: &nbsp; ${createRankingsLinksMarkdown('Collections')}\n\n***\n\n## Recent Hot Collections\n\n| Collection | Repos | 1st repo | 2nd repo | 3rd repo |\n| -- | -- | -- | -- | -- |\n${hotCollectionsMarkdown.join('\\n')}\n\n***\n\n## All Collections\n\n${allCollectionsMarkdown.join(' &nbsp; | &nbsp; ')}\n\n***\n\n`;\n};\n\nexport const createCollectionPageMarkdown = async (collectionName: string) => {\n\tconst collectionId = await getCollectionIdByName(collectionName);\n\tif (!collectionId) {\n\t\tthrow new Error('Unable to find ranking data for ' + collectionName);\n\t}\n\tconst [starsData, pullsData, issuesData] = await Promise.all([\n\t\tgetCollectionStarsLast28DaysRank(collectionId),\n\t\tgetCollectionPullRequestsLast28DaysRank(collectionId),\n\t\tgetCollectionIssuesLast28DaysRank(collectionId),\n\t]);\n\n\tconst starRankListMarkdown = starsData.map((item) => {\n\t\tconst rankMarkdown = ` ${item.current_period_rank}${getRankChangeText(+item.rank_pop)}`;\n\t\tconst repoMarkdown = ` [${item.repo_name}](${buildRepoLink(item.repo_name)})`;\n\t\tconst starsMarkdown = ` ${item.current_period_growth}${getPopCountText(+item.growth_pop, true)}`;\n\t\treturn `|${rankMarkdown} |${repoMarkdown} |${starsMarkdown} | ${item.past_period_growth} | ${item.total} |`;\n\t});\n\n\tconst pullRankListMarkdown = pullsData.map((item) => {\n\t\tconst rankMarkdown = ` ${item.current_period_rank}${getRankChangeText(+item.rank_pop)}`;\n\t\tconst repoMarkdown = ` [${item.repo_name}](${buildRepoLink(item.repo_name)})`;\n\t\tconst starsMarkdown = ` ${item.current_period_growth}${getPopCountText(+item.growth_pop, true)}`;\n\t\treturn `|${rankMarkdown} |${repoMarkdown} |${starsMarkdown} | ${item.past_period_growth} | ${item.total} |`;\n\t});\n\n\tconst issuesRankListMarkdown = issuesData.map((item) => {\n\t\tconst rankMarkdown = ` ${item.current_period_rank}${getRankChangeText(+item.rank_pop)}`;\n\t\tconst repoMarkdown = ` [${item.repo_name}](${buildRepoLink(item.repo_name)})`;\n\t\tconst starsMarkdown = ` ${item.current_period_growth}${getPopCountText(+item.growth_pop, true)}`;\n\t\treturn `|${rankMarkdown} |${repoMarkdown} |${starsMarkdown} | ${item.past_period_growth} | ${item.total} |`;\n\t});\n\n\treturn `\n# ${collectionName} - Ranking\n\nLast 28 days ranking of repos in this collection by stars, pull requests, issues. Historical Ranking by Popularity.${dataSourceMarkdown}\n\nOther Rankings: &nbsp; ${createRankingsLinksMarkdown('')}\n\n***\n\n## Last 28 days Ranking - Stars\n\n| Rank | Repo | Last 28 Days | Last 56 Days | Total |\n| -- | -- | -- | -- | -- |\n${starRankListMarkdown.join('\\n')}\n\n***\n\n## Last 28 days Ranking - Pull Requests\n\n| Rank | Repo |  Last 28 Days | Last 56 Days | Total |\n| -- | -- | -- | -- | -- |\n${pullRankListMarkdown.join('\\n')}\n\n***\n\n## Last 28 days Ranking - Issues\n\n| Rank | Repo |  Last 28 Days | Last 56 Days | Total |\n| -- | -- | -- | -- | -- |\n${issuesRankListMarkdown.join('\\n')}\n\n***\n\n`;\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/blame.ts",
    "content": "/**\n * @file sourcegraph blame api\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { BlameRange } from '../types';\nimport { querySourcegraphRepository } from './common';\n\nconst BlameRangesQuery = gql`\n\tquery ($repository: String!, $ref: String!, $path: String!) {\n\t\trepository(name: $repository) {\n\t\t\tcommit(rev: $ref) {\n\t\t\t\tblob(path: $path) {\n\t\t\t\t\tblame(startLine: 1, endLine: 99999) {\n\t\t\t\t\t\tstartLine\n\t\t\t\t\t\tendLine\n\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tperson {\n\t\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t\tavatarURL\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdate\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcommitter {\n\t\t\t\t\t\t\t\tperson {\n\t\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmessage\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\nconst computeBlameRangeAge = (time: number, oldestTime: number, newestTime: number) => {\n\tconst blockWidth = (newestTime - oldestTime) / 10;\n\treturn 10 - Math.floor((time - oldestTime) / blockWidth);\n};\n\nexport const getFileBlameRanges = async (repository: string, ref: string, path: string): Promise<BlameRange[]> => {\n\tconst repositoryData = await querySourcegraphRepository({\n\t\tquery: BlameRangesQuery,\n\t\tvariables: { repository, ref, path },\n\t});\n\n\tconst blames = repositoryData.commit?.blob?.blame || [];\n\tconst commitTimes = blames.map((blame) => new Date(blame?.commit?.author?.date).getTime()).sort();\n\tconst oldestTime = commitTimes[0];\n\tconst newestTime = commitTimes[commitTimes.length - 1];\n\treturn blames.map((blame) => ({\n\t\tage: computeBlameRangeAge(new Date(blame.commit?.author?.date).getTime(), oldestTime, newestTime),\n\t\tstartingLine: blame.startLine,\n\t\tendingLine: blame.endLine - 1,\n\t\tcommit: {\n\t\t\tsha: blame.commit?.oid,\n\t\t\tauthor: blame.commit?.author?.person?.name,\n\t\t\temail: blame.commit?.committer?.person?.email,\n\t\t\tmessage: blame.commit?.message,\n\t\t\tcommitter: blame.commit?.commiter?.person?.name,\n\t\t\tcreateTime: new Date(blame.commit?.author?.date),\n\t\t\tavatarUrl: blame.commit?.author?.person?.avatarURL,\n\t\t},\n\t}));\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/commit.ts",
    "content": "/**\n * @file Sourcegraph commits api (tree/blob)\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { Commit } from '../types';\nimport { querySourcegraphRepository } from './common';\n\nconst CommitDetail = `\n\toid\n\tauthor {\n\t\tperson {\n\t\t\tname\n\t\t\tavatarURL\n\t\t}\n\t\tdate\n\t}\n\tcommitter {\n\t\tperson {\n\t\t\temail\n      name\n\t\t}\n\t}\n\tmessage\n\tparents {\n\t\toid\n\t}\n`;\n\nconst CommitsQuery = gql`\n\tquery($repository: String!, $ref: String!, $path: String!, $first: Int) {\n\t\trepository(name: $repository) {\n\t\t\tcommit(rev: $ref) {\n\t\t\t\t${CommitDetail}\n\t\t\t\tancestors(path: $path, first: $first) {\n\t\t\t\t\tnodes {\n\t\t\t\t\t\t${CommitDetail}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\nconst getUserAvatarUrl = (username: string, isGitHub: boolean) => {\n\tif (isGitHub && !username.includes(' ')) {\n\t\treturn `https://github.com/${username.slice(-5) === '[bot]' ? username.slice(0, -5) : username}.png`;\n\t}\n\treturn `https://www.gravatar.com/avatar/${username}?d=identicon`;\n};\n\nconst formatCommit = (commit: any, isGitHub: boolean) => {\n\tif (!commit) {\n\t\treturn null;\n\t}\n\tconst authorName = commit?.author?.person?.name;\n\treturn {\n\t\tsha: commit?.oid,\n\t\tauthor: authorName,\n\t\temail: commit?.committer?.person?.email,\n\t\tmessage: commit?.message,\n\t\tcommitter: commit?.commiter?.person?.name,\n\t\tcreateTime: new Date(commit?.author?.date),\n\t\tparents: commit?.parents?.map?.((item) => item?.oid) || [],\n\t\tavatarUrl: commit?.author?.person?.avatarURL || getUserAvatarUrl(authorName, isGitHub),\n\t};\n};\n\nexport const getCommits = async (repository: string, ref: string, path?: string, limit?: number): Promise<Commit[]> => {\n\tconst repositoryData = await querySourcegraphRepository({\n\t\tquery: CommitsQuery,\n\t\tvariables: { repository, ref, path: path || '', first: limit ? limit : undefined },\n\t});\n\n\tconst firstCommit = repositoryData.commit;\n\tconst isGitHub = repository.startsWith('github.com/');\n\tconst restCommits = firstCommit?.ancestors?.nodes?.map?.((item) => formatCommit(item, isGitHub)) || [];\n\tif (firstCommit.oid === restCommits[0]?.sha) {\n\t\treturn restCommits.filter(Boolean);\n\t}\n\treturn [formatCommit(firstCommit, isGitHub), ...restCommits].slice(0, limit).filter(Boolean);\n};\n\nconst CommitQuery = gql`\nquery($repository: String!, $ref: String!) {\n  repository(name: $repository) {\n    commit(rev: $ref) {\n      ${CommitDetail}\n    }\n  }\n}\n`;\n\nexport const getCommit = async (repository: string, ref: string): Promise<Commit | null> => {\n\tconst repositoryData = await querySourcegraphRepository({\n\t\tquery: CommitQuery,\n\t\tvariables: { repository, ref },\n\t});\n\tconst isGitHub = repository.startsWith('github.com/');\n\treturn formatCommit(repositoryData.commit, isGitHub);\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/common.ts",
    "content": "/**\n * @file Sourcegraph api common utils\n * @author netcon\n */\n\nimport { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core';\nimport { isNil, trimEnd, trimStart } from '@/helpers/util';\n\nconst createFetchWithTimeout = (timeout: number): typeof fetch => {\n\treturn (uri, opts) => {\n\t\tconst ctrl = new AbortController();\n\t\tconst timeoutId = setTimeout(() => ctrl.abort(), timeout);\n\t\treturn fetch(uri, { ...opts, signal: ctrl.signal }).finally(() => {\n\t\t\tclearTimeout(timeoutId);\n\t\t});\n\t};\n};\n\nconst sourcegraphLink = createHttpLink({\n\turi: 'https://sourcegraph.com/.api/graphql',\n\tfetch: createFetchWithTimeout(3000),\n});\n\nexport const sourcegraphClient = new ApolloClient({\n\tlink: sourcegraphLink,\n\tcache: new InMemoryCache(),\n});\n\nexport const querySourcegraphRepository = async (\n\t...args: Parameters<typeof sourcegraphClient.query>\n): Promise<Record<string, any>> => {\n\tconst response = await sourcegraphClient.query(...args);\n\tif (isNil((response.data as any).repository)) {\n\t\tconst error = new Error('repository is not found');\n\t\t(error as any).repositoryNotFound = true;\n\t\tthrow error;\n\t}\n\treturn (response.data as any).repository;\n};\n\nexport const canBeConvertToRegExp = (str: string) => {\n\ttry {\n\t\tnew RegExp(str);\n\t\treturn true;\n\t} catch (e) {\n\t\treturn false;\n\t}\n};\n\nexport const combineGlobsToRegExp = (globs: string[]) => {\n\t// only support very simple globs convert now\n\tconst result = Array.from(\n\t\tnew Set(globs.map((glob: string) => trimEnd(trimStart(glob, '*/'), '*/').replace(/^\\./, '\\\\.'))),\n\t)\n\t\t// if the glob still not can be convert to a regexp, just ignore it\n\t\t.filter((item) => canBeConvertToRegExp(item))\n\t\t.join('|');\n\t// ensure the result can be convert to a regexp\n\treturn canBeConvertToRegExp(result) ? result : '';\n};\n\nexport const escapeRegexp = (text: string): string => text.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n\nexport const buildRepoPattern = (repo: string) => {\n\treturn `^${escapeRegexp(repo)}$`;\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/comparison.ts",
    "content": "/**\n * @file sourcegraph comparison api\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { ChangedFile, FileChangeStatus } from '../types';\nimport { querySourcegraphRepository } from './common';\n\nconst ComparisonQuery = gql`\n\tquery ($repository: String!, $base: String!, $head: String!) {\n\t\trepository(name: $repository) {\n\t\t\tcomparison(base: $base, head: $head) {\n\t\t\t\tfileDiffs {\n\t\t\t\t\tnodes {\n\t\t\t\t\t\tnewPath\n\t\t\t\t\t\toldPath\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\nconst getFileChangeStatus = (oldPath: string | null, newPath: string | null): FileChangeStatus => {\n\tif (!oldPath) {\n\t\treturn FileChangeStatus.Added;\n\t}\n\tif (!newPath) {\n\t\treturn FileChangeStatus.Removed;\n\t}\n\tif (oldPath !== newPath) {\n\t\treturn FileChangeStatus.Renamed;\n\t}\n\treturn FileChangeStatus.Modified;\n};\n\nexport const compareCommits = async (repository: string, base: string, head: string): Promise<ChangedFile[]> => {\n\tconst repositoryData = await querySourcegraphRepository({\n\t\tquery: ComparisonQuery,\n\t\tvariables: { repository, base, head },\n\t});\n\tconst diffFiles = repositoryData.comparison?.fileDiffs?.nodes || [];\n\n\treturn diffFiles\n\t\t.filter((file) => file.oldPath || file.newPath)\n\t\t.map((file) => {\n\t\t\tconst status = getFileChangeStatus(file.oldPath, file.newPath);\n\n\t\t\treturn {\n\t\t\t\tstatus,\n\t\t\t\tpath: file.newPath || file.oldPath,\n\t\t\t\tpreviousPath: status === FileChangeStatus.Renamed ? file.oldPath : undefined,\n\t\t\t};\n\t\t});\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/data-source.ts",
    "content": "/**\n * @file sourcegraph data-source-provider\n * @author netcon\n */\n\nimport { joinPath } from '@/helpers/util';\nimport { matchSorter } from 'match-sorter';\nimport {\n\tBranch,\n\tTextSearchOptions,\n\tCommit,\n\tCommonQueryOptions,\n\tDataSource,\n\tDirectory,\n\tFile,\n\tBlameRange,\n\tTag,\n\tTextSearchResults,\n\tTextSearchQuery,\n\tChangedFile,\n\tSymbolHover,\n\tSymbolReferences,\n\tSymbolDefinitions,\n\tCommitsQueryOptions,\n\tFileType,\n} from '../types';\nimport { getFileBlameRanges } from './blame';\nimport { getCommit, getCommits } from './commit';\nimport { compareCommits } from './comparison';\nimport { getSymbolDefinitions } from './definition';\nimport { readDirectory, readFile } from './file';\nimport { getSymbolHover } from './hover';\nimport { getAllRefs } from './ref';\nimport { getSymbolReferences } from './reference';\nimport { getRepository } from './repository';\nimport { getTextSearchResults } from './search';\nimport { decorate, memorize } from '@/helpers/func';\n\ntype SupportedPlatform = 'github' | 'gitlab' | 'bitbucket';\n\nexport class SourcegraphDataSource extends DataSource {\n\tprivate static instanceMap: Map<SupportedPlatform, SourcegraphDataSource> = new Map();\n\tprivate refsPromiseMap: Map<string, Promise<{ branches: Branch[]; tags: Tag[] }>> = new Map();\n\tprivate repositoryPromiseMap: Map<string, Promise<{ private: boolean; defaultBranch: string } | null>> = new Map();\n\tprivate fileTypeMap: Map<string, FileType> = new Map(); // cache if path is a directory\n\tprivate matchedRefsMap: Map<string, string[]> = new Map();\n\tprivate textEncoder = new TextEncoder();\n\n\tpublic static getInstance(platform: SupportedPlatform): SourcegraphDataSource {\n\t\tif (!SourcegraphDataSource.instanceMap.has(platform)) {\n\t\t\tSourcegraphDataSource.instanceMap.set(platform, new SourcegraphDataSource(platform));\n\t\t}\n\t\treturn SourcegraphDataSource.instanceMap.get(platform)!;\n\t}\n\n\tprivate constructor(private platform: SupportedPlatform) {\n\t\tsuper();\n\t}\n\n\tbuildRepository(repo: string) {\n\t\tif (this.platform === 'github') {\n\t\t\treturn `github.com/${repo}`;\n\t\t}\n\t\tif (this.platform === 'gitlab') {\n\t\t\treturn `gitlab.com/${repo}`;\n\t\t}\n\t\tif (this.platform === 'bitbucket') {\n\t\t\treturn `bitbucket.org/${repo}`;\n\t\t}\n\t\treturn repo;\n\t}\n\n\tasync provideDirectory(repo: string, ref: string, path: string, recursive = false): Promise<Directory> {\n\t\tconst directories = await readDirectory(this.buildRepository(repo), ref, path, recursive);\n\t\tdirectories.entries.forEach((entry) => {\n\t\t\tconst mapKey = `${repo} ${ref} ${joinPath(path, entry.path)}`;\n\t\t\tthis.fileTypeMap.set(mapKey, entry.type);\n\t\t});\n\t\treturn directories;\n\t}\n\n\tasync detectPathFileType(repo: string, ref: string, path: string) {\n\t\tconst pathParts = path.split('/').filter(Boolean);\n\t\tconst trimmedPath = pathParts.join('/');\n\t\tif (!trimmedPath) {\n\t\t\treturn FileType.Directory;\n\t\t}\n\t\tconst mapKey = `${repo} ${ref} ${trimmedPath}`;\n\t\tif (this.fileTypeMap.has(mapKey)) {\n\t\t\treturn this.fileTypeMap.get(mapKey)!;\n\t\t}\n\t\tawait this.provideDirectory(repo, ref, pathParts.slice(0, -1).join('/'), false);\n\t\treturn this.fileTypeMap.get(trimmedPath) || FileType.File;\n\t}\n\n\tasync provideRepository(repo: string) {\n\t\tif (!this.repositoryPromiseMap.has(repo)) {\n\t\t\tthis.repositoryPromiseMap.set(repo, getRepository(this.buildRepository(repo)));\n\t\t}\n\t\treturn this.repositoryPromiseMap.get(repo);\n\t}\n\n\tasync provideFile(repo: string, ref: string, path: string): Promise<File> {\n\t\t// sourcegraph api break binary files and text coding, so we use github api first here\n\t\tif (this.platform === 'github') {\n\t\t\t// For GitHub repositories, request GitHub User Content API first (it seems no Rate Limit),\n\t\t\t// because Sourcegraph API returns binary data such as pictures in error. If the GitHub User\n\t\t\t// Content API goes wrong, then try Sourcegraph API. Use `try catch` because if fallback to\n\t\t\t// GitHub REST API may trigger a pop-up window to request authentication for anonymous users.\n\t\t\ttry {\n\t\t\t\treturn fetch(encodeURI(`https://raw.githubusercontent.com/${repo}/${ref}/${path}`))\n\t\t\t\t\t.then((response) => (response.ok ? response.arrayBuffer() : Promise.reject({ response })))\n\t\t\t\t\t.then((buffer) => ({ content: new Uint8Array(buffer) }));\n\t\t\t} catch {}\n\t\t}\n\t\t// TODO: support binary files for other platforms\n\t\tconst { content } = await readFile(this.buildRepository(repo), ref, path);\n\t\treturn { content: this.textEncoder.encode(content) };\n\t}\n\n\tasync prepareAllRefs(repo: string) {\n\t\tif (!this.refsPromiseMap.has(repo)) {\n\t\t\tthis.refsPromiseMap.set(repo, getAllRefs(this.buildRepository(repo)));\n\t\t}\n\t\treturn this.refsPromiseMap.get(repo)!;\n\t}\n\n\t@decorate(memorize)\n\tprivate async getDefaultBranch(repo: string) {\n\t\treturn (await this.provideRepository(repo))?.defaultBranch || 'HEAD';\n\t}\n\n\tasync extractRefPath(repo: string, refAndPath: string): Promise<{ ref: string; path: string }> {\n\t\tif (!refAndPath) {\n\t\t\treturn { ref: await this.getDefaultBranch(repo), path: '' };\n\t\t}\n\t\tif (refAndPath.match(/^HEAD(\\/.*)?$/i)) {\n\t\t\treturn { ref: 'HEAD', path: refAndPath.slice(5) };\n\t\t}\n\t\tif (!this.matchedRefsMap.has(repo)) {\n\t\t\tthis.matchedRefsMap.set(repo, []);\n\t\t}\n\t\tconst matchPathRef = (ref) => refAndPath.startsWith(`${ref}/`) || refAndPath === ref;\n\t\tconst pathRef = this.matchedRefsMap.get(repo)?.find(matchPathRef);\n\t\tif (pathRef) {\n\t\t\treturn { ref: pathRef, path: refAndPath.slice(pathRef.length + 1) };\n\t\t}\n\t\tconst { branches, tags } = await this.prepareAllRefs(repo);\n\t\tconst exactRef = [...branches, ...tags].map((item) => item.name).find(matchPathRef);\n\t\tconst ref = exactRef || refAndPath.split('/')[0] || 'HEAD';\n\t\texactRef && this.matchedRefsMap.get(repo)?.push(ref);\n\t\treturn { ref, path: refAndPath.slice(ref.length + 1) };\n\t}\n\n\tasync provideBranches(repo: string, options?: CommonQueryOptions): Promise<Branch[]> {\n\t\tconst cachedRefs = await this.prepareAllRefs(repo);\n\t\tconst matchedBranches = options?.query\n\t\t\t? matchSorter(cachedRefs?.branches || [], options.query, { keys: ['name'] })\n\t\t\t: cachedRefs?.branches || [];\n\t\tif (options?.pageSize) {\n\t\t\tconst page = options.page || 1;\n\t\t\tconst pageSize = options.pageSize;\n\t\t\treturn matchedBranches.slice(pageSize * (page - 1), pageSize * page);\n\t\t}\n\t\treturn matchedBranches;\n\t}\n\n\tasync provideTags(repo: string, options?: CommonQueryOptions): Promise<Tag[]> {\n\t\tconst cachedRefs = await this.prepareAllRefs(repo);\n\t\tconst matchedTags = options?.query\n\t\t\t? matchSorter(cachedRefs?.tags || [], options.query, { keys: ['name'] })\n\t\t\t: cachedRefs?.tags || [];\n\t\tif (options?.pageSize) {\n\t\t\tconst page = options.page || 1;\n\t\t\tconst pageSize = options.pageSize;\n\t\t\treturn matchedTags.slice(pageSize * (page - 1), pageSize * page);\n\t\t}\n\t\treturn matchedTags;\n\t}\n\n\tasync provideTextSearchResults(\n\t\trepo: string,\n\t\tref: string,\n\t\tquery: TextSearchQuery,\n\t\toptions: TextSearchOptions,\n\t): Promise<TextSearchResults> {\n\t\treturn getTextSearchResults(this.buildRepository(repo), ref, query, options);\n\t}\n\n\tasync provideCommits(repo: string, options?: CommitsQueryOptions): Promise<(Commit & { files?: ChangedFile[] })[]> {\n\t\tlet commits = await getCommits(\n\t\t\tthis.buildRepository(repo),\n\t\t\toptions?.from || 'HEAD',\n\t\t\toptions?.path,\n\t\t\toptions?.pageSize ? options.pageSize * (options.page || 1) : undefined,\n\t\t);\n\t\tif (options?.path && commits.length) {\n\t\t\t// find the latested that related the `options.path` file\n\t\t\tconst changedFiles = await this.provideCommitChangedFiles(repo, commits[0].sha);\n\t\t\tcommits = changedFiles.find((file) => file.path === options.path) ? commits : commits.slice(1);\n\t\t}\n\t\treturn options?.pageSize ? commits.slice(options.pageSize * ((options.page || 1) - 1)) : commits;\n\t}\n\n\tasync provideCommit(repo: string, ref: string): Promise<Commit | null> {\n\t\treturn getCommit(this.buildRepository(repo), ref);\n\t}\n\n\tasync provideCommitChangedFiles(repo: string, ref: string, _options?: CommonQueryOptions): Promise<ChangedFile[]> {\n\t\treturn compareCommits(this.buildRepository(repo), `${ref}~`, ref);\n\t}\n\n\tasync provideFileBlameRanges(repo: string, ref: string, path: string): Promise<BlameRange[]> {\n\t\treturn getFileBlameRanges(this.buildRepository(repo), ref, path);\n\t}\n\n\tasync provideSymbolDefinitions(\n\t\trepo: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promise<SymbolDefinitions> {\n\t\treturn getSymbolDefinitions(this.buildRepository(repo), ref, path, line, character, symbol);\n\t}\n\n\tasync provideSymbolReferences(\n\t\trepo: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promise<SymbolReferences> {\n\t\treturn getSymbolReferences(this.buildRepository(repo), ref, path, line, character, symbol);\n\t}\n\n\tasync provideSymbolHover(\n\t\trepo: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\t_symbol: string,\n\t): Promise<SymbolHover | null> {\n\t\treturn getSymbolHover(this.buildRepository(repo), ref, path, line, character);\n\t}\n\n\tprovideUserAvatarLink(user: string): string {\n\t\tif (this.platform === 'github') {\n\t\t\treturn `https://github.com/${user}.png`;\n\t\t}\n\t\treturn `https://www.gravatar.com/avatar/${user}?d=identicon`;\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/definition.ts",
    "content": "/**\n * @file Sourcegraph definition api\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { sourcegraphClient } from './common';\nimport { getSymbolPositions } from './position';\nimport { SymbolDefinitions } from '../types';\n\nconst LSIFDefinitionsQuery = gql`\n\tquery ($repository: String!, $ref: String!, $path: String!, $line: Int!, $character: Int!) {\n\t\trepository(name: $repository) {\n\t\t\tcommit(rev: $ref) {\n\t\t\t\tblob(path: $path) {\n\t\t\t\t\tlsif {\n\t\t\t\t\t\tdefinitions(line: $line, character: $character) {\n\t\t\t\t\t\t\tnodes {\n\t\t\t\t\t\t\t\tresource {\n\t\t\t\t\t\t\t\t\tpath\n\t\t\t\t\t\t\t\t\trepository {\n\t\t\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trange {\n\t\t\t\t\t\t\t\t\tstart {\n\t\t\t\t\t\t\t\t\t\tline\n\t\t\t\t\t\t\t\t\t\tcharacter\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tend {\n\t\t\t\t\t\t\t\t\t\tline\n\t\t\t\t\t\t\t\t\t\tcharacter\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\n// find definitions with Sourcegraph LSIF\n// https://docs.sourcegraph.com/code_intelligence/explanations/precise_code_intelligence\nconst getLSIFDefinitions = async (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\tline: number,\n\tcharacter: number,\n): Promise<SymbolDefinitions> => {\n\tconst response = await sourcegraphClient.query({\n\t\tquery: LSIFDefinitionsQuery,\n\t\tvariables: { repository, ref, path, line, character },\n\t});\n\tconst definitionNodes = response.data?.repository?.commit?.blob?.lsif?.definitions?.nodes;\n\t// TODO: cross-repository symbols\n\treturn (definitionNodes || []).map(({ resource, range }) => {\n\t\treturn { path: resource.path, range };\n\t});\n};\n\nexport const getSymbolDefinitions = (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\tline: number,\n\tcharacter: number,\n\tsymbol: string,\n): Promise<SymbolDefinitions> => {\n\t// if failed to find definitions from LSIF,\n\t// fallback to search-based definitions, using\n\t// two promise instead of `await` to request in\n\t// parallel for getting result as soon as possible\n\tconst LSIFDefinitionsPromise = getLSIFDefinitions(repository, ref, path, line, character);\n\tconst searchDefinitionsPromise = getSymbolPositions(repository, ref, symbol);\n\n\treturn LSIFDefinitionsPromise.then((LSIFResults) => {\n\t\tif (LSIFResults.length) {\n\t\t\treturn LSIFResults;\n\t\t}\n\t\treturn searchDefinitionsPromise;\n\t});\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/file.ts",
    "content": "/**\n * @file Sourcegraph file api (tree/blob)\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { querySourcegraphRepository } from './common';\nimport { Directory, FileType } from '../types';\n\nconst FILE_COUNT_LIMIT = 50000;\n\nconst DirectoryQuery = gql`\n\tquery($repository: String!, $ref: String!, $path: String!, $recursive: Boolean = false) {\n\t\trepository(name: $repository) {\n\t\t\tcommit(rev: $ref) {\n\t\t\t\ttree(path: $path) {\n\t\t\t\t\tentries(first: ${FILE_COUNT_LIMIT}, recursive: $recursive) {\n\t\t\t\t\t\tpath\n\t\t\t\t\t\tisDirectory\n\t\t\t\t\t\t# TODO submodule don't work now\n\t\t\t\t\t\tsubmodule {\n\t\t\t\t\t\t\tcommit\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\nexport const readDirectory = async (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\trecursive = false,\n): Promise<Directory> => {\n\tconst repositoryData = await querySourcegraphRepository({\n\t\tquery: DirectoryQuery,\n\t\tvariables: { repository, ref, path, recursive },\n\t});\n\tconst files = repositoryData.commit?.tree?.entries || [];\n\tconst pathParts = path.split('/').filter(Boolean);\n\treturn {\n\t\tentries: files.map((file) => ({\n\t\t\tpath: file.path.split('/').filter(Boolean).slice(pathParts.length).join('/'),\n\t\t\ttype: file.isDirectory ? FileType.Directory : file.submodule ? FileType.Submodule : FileType.File,\n\t\t\tcommitSha: file.submodule?.sha,\n\t\t})),\n\t\ttruncated: files.length >= FILE_COUNT_LIMIT,\n\t};\n};\n\nconst FileQuery = gql`\n\tquery ($repository: String!, $ref: String!, $path: String!) {\n\t\trepository(name: $repository) {\n\t\t\tcommit(rev: $ref) {\n\t\t\t\tblob(path: $path) {\n\t\t\t\t\tcontent\n\t\t\t\t\tbinary\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\nexport const readFile = async (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\trecursive = false,\n): Promise<{ content: string; binary: boolean }> => {\n\tconst repositoryData = await querySourcegraphRepository({\n\t\tquery: FileQuery,\n\t\tvariables: { repository, ref, path, recursive },\n\t});\n\tconst blob = repositoryData.commit?.blob;\n\treturn { content: blob?.content || '', binary: blob?.binary || false };\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/hover.ts",
    "content": "/**\n * @file Sourcegraph hover api\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { SymbolHover } from '../types';\nimport { sourcegraphClient } from './common';\n\nconst LSIFHoverQuery = gql`\n\tquery ($repository: String!, $ref: String!, $path: String!, $line: Int!, $character: Int!) {\n\t\trepository(name: $repository) {\n\t\t\tcommit(rev: $ref) {\n\t\t\t\tblob(path: $path) {\n\t\t\t\t\tlsif {\n\t\t\t\t\t\thover(line: $line, character: $character) {\n\t\t\t\t\t\t\tmarkdown {\n\t\t\t\t\t\t\t\ttext\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\n// find Hover with Sourcegraph LSIF\n// https://docs.sourcegraph.com/code_intelligence/explanations/precise_code_intelligence\nconst getLSIFHover = async (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\tline: number,\n\tcharacter: number,\n): Promise<SymbolHover | null> => {\n\tconst response = await sourcegraphClient.query({\n\t\tquery: LSIFHoverQuery,\n\t\tvariables: {\n\t\t\trepository,\n\t\t\tref,\n\t\t\tpath: path.slice(1),\n\t\t\tline,\n\t\t\tcharacter,\n\t\t},\n\t});\n\tconst markdown = response.data?.repository?.commit?.blob?.lsif?.hover?.markdown?.text;\n\n\tif (!markdown) {\n\t\treturn null;\n\t}\n\n\treturn { markdown };\n};\n\nexport const getSymbolHover = (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\tline: number,\n\tcharacter: number,\n): Promise<SymbolHover | null> => {\n\treturn getLSIFHover(repository, ref, path, line, character);\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/position.ts",
    "content": "/**\n * @file Sourcegraph api for searching symbol positions\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { buildRepoPattern, escapeRegexp, sourcegraphClient } from './common';\nimport { CodeLocation } from '../types';\n\nconst searchPositionsQuery = gql`\n\tquery ($query: String!) {\n\t\tsearch(query: $query) {\n\t\t\tresults {\n\t\t\t\tresults {\n\t\t\t\t\t... on FileMatch {\n\t\t\t\t\t\tsymbols {\n\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\tkind\n\t\t\t\t\t\t\tlocation {\n\t\t\t\t\t\t\t\tresource {\n\t\t\t\t\t\t\t\t\tpath\n\t\t\t\t\t\t\t\t\trepository {\n\t\t\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trange {\n\t\t\t\t\t\t\t\t\tstart {\n\t\t\t\t\t\t\t\t\t\tline\n\t\t\t\t\t\t\t\t\t\tcharacter\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tend {\n\t\t\t\t\t\t\t\t\t\tline\n\t\t\t\t\t\t\t\t\t\tcharacter\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\n// get symbol position information base on search,\n// used by definition, reference and hover\nexport const getSymbolPositions = async (repository: string, ref: string, symbol: string): Promise<CodeLocation[]> => {\n\tconst repoPattern = buildRepoPattern(repository);\n\tconst repoRefString = ref.toUpperCase() === 'HEAD' ? `repo:${repoPattern}` : `repo:${repoPattern}@${ref}`;\n\tconst optionsString = ['context:global', 'type:symbol', 'patternType:regexp', 'case:yes'].join(' ');\n\tconst patternString = `^${escapeRegexp(symbol)}$`;\n\tconst query = [repoRefString, optionsString, patternString].join(' ');\n\tconst response = await sourcegraphClient.query({\n\t\tquery: searchPositionsQuery,\n\t\tvariables: { query },\n\t});\n\n\tconst resultSymbols = response?.data?.search?.results?.results?.flatMap((item) => item.symbols) || [];\n\treturn resultSymbols\n\t\t.map((symbol) => {\n\t\t\tconst { resource, range } = symbol.location;\n\t\t\t// TODO: cross-repository symbols\n\t\t\treturn {\n\t\t\t\tpath: resource.path,\n\t\t\t\trange,\n\t\t\t};\n\t\t})\n\t\t.filter(Boolean);\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/ref.ts",
    "content": "/**\n * @file Sourcegraph git ref api (branch/tag)\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { querySourcegraphRepository } from './common';\nimport { Branch, Tag } from '../types';\n\nconst BranchTagQuery = gql`\n\tquery ($repository: String!) {\n\t\trepository(name: $repository) {\n\t\t\tbranches {\n\t\t\t\tnodes {\n\t\t\t\t\tdisplayName\n\t\t\t\t\ttarget {\n\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tdate\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttags {\n\t\t\t\tnodes {\n\t\t\t\t\tdisplayName\n\t\t\t\t\ttarget {\n\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tdate\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\nexport const getAllRefs = async (repository: string): Promise<{ branches: Branch[]; tags: Tag[] }> => {\n\tconst repositoryData = await querySourcegraphRepository({\n\t\tquery: BranchTagQuery,\n\t\tvariables: { repository },\n\t});\n\n\tconst sortByTimeDesc = (branchA, branchB) => {\n\t\treturn branchA.target?.commit?.author?.date > branchB.target?.commit?.author?.date ? -1 : 1;\n\t};\n\tconst branches = (repositoryData.branches?.nodes || [])\n\t\t?.filter(Boolean)\n\t\t?.sort(sortByTimeDesc)\n\t\t?.map?.((branch) => ({\n\t\t\tname: branch.displayName,\n\t\t\tcommitSha: branch.target?.commit?.oid,\n\t\t\tdescription: `Branch at ${branch.target?.commit?.oid?.slice(0, 8)}`,\n\t\t}));\n\tconst tags = (repositoryData.tags?.nodes || [])\n\t\t?.filter(Boolean)\n\t\t?.sort(sortByTimeDesc)\n\t\t?.map?.((tag) => ({\n\t\t\tname: tag?.displayName,\n\t\t\tcommitSha: tag?.target?.commit?.oid,\n\t\t\tdescription: `Tag at ${tag?.target?.commit?.oid?.slice(0, 8)}`,\n\t\t}));\n\treturn { branches, tags };\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/reference.ts",
    "content": "/**\n * @file Sourcegraph reference api\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { sourcegraphClient } from './common';\nimport { getSymbolPositions } from './position';\nimport { SymbolReferences } from '../types';\n\nconst LSIFReferencesQuery = gql`\n\tquery ($repository: String!, $ref: String!, $path: String!, $line: Int!, $character: Int!) {\n\t\trepository(name: $repository) {\n\t\t\tcommit(rev: $ref) {\n\t\t\t\tblob(path: $path) {\n\t\t\t\t\tlsif {\n\t\t\t\t\t\treferences(line: $line, character: $character) {\n\t\t\t\t\t\t\tnodes {\n\t\t\t\t\t\t\t\tresource {\n\t\t\t\t\t\t\t\t\tpath\n\t\t\t\t\t\t\t\t\trepository {\n\t\t\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trange {\n\t\t\t\t\t\t\t\t\tstart {\n\t\t\t\t\t\t\t\t\t\tline\n\t\t\t\t\t\t\t\t\t\tcharacter\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tend {\n\t\t\t\t\t\t\t\t\t\tline\n\t\t\t\t\t\t\t\t\t\tcharacter\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\n// find references with Sourcegraph LSIF\n// https://docs.sourcegraph.com/code_intelligence/explanations/precise_code_intelligence\nconst getLSIFReferences = async (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\tline: number,\n\tcharacter: number,\n): Promise<SymbolReferences> => {\n\tconst response = await sourcegraphClient.query({\n\t\tquery: LSIFReferencesQuery,\n\t\tvariables: { repository, ref, path, line, character },\n\t});\n\tconst referenceNodes = response.data?.repository?.commit?.blob?.lsif?.references?.nodes;\n\t// TODO: cross-repository symbols\n\treturn (referenceNodes || []).map(({ resource, range }) => {\n\t\treturn { path: resource.path, range };\n\t});\n};\n\nexport const getSymbolReferences = (\n\trepository: string,\n\tref: string,\n\tpath: string,\n\tline: number,\n\tcharacter: number,\n\tsymbol: string,\n): Promise<SymbolReferences> => {\n\t// if failed to find references from LSIF,\n\t// fallback to search-based references, using\n\t// two promise instead of `await` to request in\n\t// parallel for getting result as soon as possible\n\tconst LSIFReferencesPromise = getLSIFReferences(repository, ref, path, line, character);\n\tconst searchReferencesPromise = getSymbolPositions(repository, ref, symbol);\n\n\treturn LSIFReferencesPromise.then((LSIFReferences) => {\n\t\tif (LSIFReferences.length) {\n\t\t\treturn LSIFReferences;\n\t\t}\n\t\treturn searchReferencesPromise;\n\t});\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/repository.ts",
    "content": "/**\n * @file Sourcegraph file api (tree/blob)\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { sourcegraphClient } from './common';\n\nconst RepositoryQuery = gql`\n\tquery ($repository: String!) {\n\t\trepository(name: $repository) {\n\t\t\tname\n\t\t\tisPrivate\n\t\t\tdefaultBranch {\n\t\t\t\tdisplayName\n\t\t\t}\n\t\t}\n\t}\n`;\n\nexport const getRepository = async (\n\trepository: string,\n): Promise<{ private: boolean; defaultBranch: string } | null> => {\n\tconst response = await sourcegraphClient.query({\n\t\tquery: RepositoryQuery,\n\t\tvariables: { repository },\n\t});\n\tconst repositoryData = response.data?.repository;\n\treturn repositoryData\n\t\t? { private: repositoryData.isPrivate, defaultBranch: repositoryData.defaultBranch?.displayName }\n\t\t: null;\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/sourcegraph/search.ts",
    "content": "/**\n * @file Sourcegraph search api\n * @author netcon\n */\n\nimport { gql } from '@apollo/client/core';\nimport { TextSearchOptions, TextSearchQuery, TextSearchResults } from '../types';\nimport { escapeRegexp, sourcegraphClient, combineGlobsToRegExp, buildRepoPattern } from './common';\n\n// build text search query for sourcegraph graphql request\nexport const buildTextSearchQueryString = (\n\trepository: string,\n\tref: string,\n\tquery: TextSearchQuery,\n\toptions: TextSearchOptions,\n): string => {\n\tconst repoPattern = buildRepoPattern(repository);\n\tconst countString = `count:${options.pageSize ? (options.page || 1) * options.pageSize : 100}`;\n\tconst repoRefString = ref.toUpperCase() === 'HEAD' ? `repo:${repoPattern}` : `repo:${repoPattern}@${ref}`;\n\t// the string may looks like `case:yse file:src -file:node_modules`\n\tconst optionsString = [\n\t\tquery.isCaseSensitive ? `case:yes` : '',\n\t\toptions.includes?.length ? `file:${combineGlobsToRegExp(options.includes)}` : '',\n\t\toptions.excludes?.length ? `-file:${combineGlobsToRegExp(options.excludes)}` : '',\n\t]\n\t\t.filter(Boolean)\n\t\t.join(' ');\n\t// convert the pattern to adapt the sourcegraph API\n\tlet patternString = query.pattern;\n\n\tif (!query.isRegExp && !query.isWordMatch) {\n\t\tpatternString = `\"${patternString}\"`;\n\t} else if (!query.isRegExp && query.isWordMatch) {\n\t\tpatternString = `/\\\\b${escapeRegexp(patternString)}\\\\b/`;\n\t} else if (query.isRegExp && !query.isWordMatch) {\n\t\tpatternString = `/${patternString}/`;\n\t} else if (query.isRegExp && query.isWordMatch) {\n\t\treturn `/\\b${patternString}\\b/`;\n\t}\n\n\treturn [repoRefString, optionsString, patternString, countString].filter(Boolean).join(' ');\n};\n\nconst textSearchQuery = gql`\n\tquery ($query: String!) {\n\t\tsearch(query: $query) {\n\t\t\tresults {\n\t\t\t\t__typename\n\t\t\t\tlimitHit\n\t\t\t\tmatchCount\n\t\t\t\tapproximateResultCount\n\t\t\t\tmissing {\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcloning {\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\ttimedout {\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tindexUnavailable\n\t\t\t\tresults {\n\t\t\t\t\t... on FileMatch {\n\t\t\t\t\t\t__typename\n\t\t\t\t\t\tfile {\n\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\tpath\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlineMatches {\n\t\t\t\t\t\t\tpreview\n\t\t\t\t\t\t\tlineNumber\n\t\t\t\t\t\t\toffsetAndLengths\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`;\n\nconst formatTextSearchResults = (searchResults, offset: number, limit: number) => {\n\tconst truncated = !!searchResults?.limitHit;\n\tconst results = (searchResults?.results || []).slice(offset, limit).flatMap((fileMatch) => {\n\t\tconst path = fileMatch?.file?.path;\n\n\t\treturn (fileMatch?.lineMatches || []).map((lineMatch) => {\n\t\t\tconst lineNumber = lineMatch?.lineNumber;\n\t\t\tconst ranges = (lineMatch?.offsetAndLengths || []).map((segment) => ({\n\t\t\t\tstart: { line: lineNumber, character: segment[0] },\n\t\t\t\tend: { line: lineNumber, character: segment[0] + segment[1] },\n\t\t\t}));\n\t\t\tconst previewMatches = (lineMatch?.offsetAndLengths || []).map((segment) => ({\n\t\t\t\tstart: { line: 0, character: segment[0] },\n\t\t\t\tend: { line: 0, character: segment[0] + segment[1] },\n\t\t\t}));\n\t\t\tconst preview = { text: lineMatch.preview, matches: previewMatches };\n\n\t\t\treturn { path, ranges, preview };\n\t\t});\n\t});\n\n\treturn { results, truncated };\n};\n\nexport const getTextSearchResults = (\n\trepository: string,\n\tref: string,\n\tquery: TextSearchQuery,\n\toptions: TextSearchOptions,\n): Promise<TextSearchResults> => {\n\tconst offset = options.pageSize ? ((options.page || 1) - 1) * options.pageSize : 0;\n\tconst limit = options.pageSize ? options.pageSize : 100;\n\n\treturn sourcegraphClient\n\t\t.query({\n\t\t\tquery: textSearchQuery,\n\t\t\tvariables: { query: buildTextSearchQueryString(repository, ref, query, options) },\n\t\t})\n\t\t.then((response) => formatTextSearchResults(response?.data?.search?.results, offset, limit));\n};\n"
  },
  {
    "path": "extensions/github1s/src/adapters/types.ts",
    "content": "/**\n * @file GitHub1s Type Definitions\n * @author netcon\n */\n\nexport type Promisable<T> = PromiseLike<T> | T;\n\nexport enum FileType {\n\tDirectory = 'Directory',\n\tFile = 'File',\n\tLink = 'Link',\n\tSubmodule = 'Submodule',\n}\n\n// `page` starts from 1\ntype PaginationOptions = { page: number; pageSize: number } | { page?: number; pageSize?: number };\nexport type CommonQueryOptions = { query?: string } & PaginationOptions;\n\nexport type DirectoryEntry =\n\t| { type: FileType.Directory; path: string } // for director or link\n\t| { type: FileType.File; path: string; size?: number } // for a file\n\t| { type: FileType.Submodule; path: string; commitSha?: string }; // for a submodule\n\nexport interface Directory {\n\tentries: DirectoryEntry[];\n\t// entries doesn't contains all results if `truncated` is true\n\ttruncated: boolean;\n}\n\nexport interface File {\n\tcontent: Uint8Array;\n}\n\nexport interface Submodule {\n\t// which commit the submodule repository point to\n\tref: string;\n}\n\nexport interface SymbolicLink {\n\tpath: string;\n}\n\nexport interface Branch {\n\tname: string;\n\tcommitSha?: string;\n\tdescription?: string;\n}\n\nexport interface Tag {\n\tname: string;\n\tcommitSha?: string;\n\tdescription?: string;\n}\n\nexport type CommitsQueryOptions = { from?: string; author?: string; path?: string } & CommonQueryOptions;\n\nexport interface Commit {\n\tsha: string;\n\tauthor?: string; // original commit author\n\temail?: string;\n\tmessage: string;\n\tcommitter?: string;\n\tcreateTime?: Date;\n\tparents: string[]; // empty array for first commit\n\tavatarUrl?: string;\n}\n\nexport interface TextSearchQuery {\n\tpattern: string;\n\tisMultiline?: boolean;\n\tisRegExp?: boolean;\n\tisCaseSensitive?: boolean;\n\tisWordMatch?: boolean;\n}\n\n// `includes` and `excludes` both are glob strings\nexport type TextSearchOptions = { includes?: string[]; excludes?: string[] } & PaginationOptions;\n\nexport interface TextSearchResults {\n\tresults: {\n\t\tscope?: ResourceScope;\n\t\tpath: string;\n\t\tranges: Range | Range[];\n\t\tpreview: {\n\t\t\ttext: string;\n\t\t\tmatches: Range | Range[];\n\t\t};\n\t}[];\n\ttruncated: boolean;\n}\n\nexport interface Position {\n\tline: number;\n\tcharacter: number;\n}\n\nexport interface Range {\n\tstart: Position;\n\tend: Position;\n}\n\n// for cross-repository data,\n// reference to another repository\nexport interface ResourceScope {\n\tscheme: string; // github / github / bitbucket...\n\trepo: string;\n\tref: string;\n}\n\nexport enum CodeReviewState {\n\tOpen = 'Open', // icon: 🟢\n\tMerged = 'Merged', // icon: 🟣\n\tClosed = 'Closed', // icon: 🔴\n}\n\nexport type CodeReviewsQueryOptions = { state?: CodeReviewState; creator?: string } & CommonQueryOptions;\n\n// may be a Pull Request for GitHub,\n// or a Merge Request for GitLab,\n// or a Change Request for Gerrit\nexport interface CodeReview {\n\tid: string;\n\ttitle: string;\n\tstate: CodeReviewState;\n\tcreator?: string;\n\tcreateTime: Date;\n\tmergeTime: Date | null;\n\tcloseTime: Date | null;\n\tsource: string;\n\ttarget: string;\n\tsourceSha?: string;\n\ttargetSha?: string;\n\tavatarUrl?: string;\n}\n\nexport enum FileChangeStatus {\n\tAdded = 'added',\n\tRemoved = 'removed',\n\tModified = 'modified',\n\tRenamed = 'renamed',\n}\n\nexport interface ChangedFile {\n\tscope?: ResourceScope;\n\tstatus: FileChangeStatus;\n\tpath: string;\n\t// only exists for renamed file\n\tpreviousPath?: string;\n}\n\nexport interface BlameRange {\n\tage: number;\n\tstartingLine: number; // starts from 1\n\tendingLine: number;\n\tcommit: Commit & { parents?: string[] };\n}\n\nexport interface CodeLocation {\n\t// we can set `scope` to marked that current\n\t// result is referenced to another repository\n\tscope?: ResourceScope;\n\tpath: string;\n\trange: Range;\n}\n\nexport type SymbolDefinitions = CodeLocation[];\n\nexport type SymbolReferences = CodeLocation[];\n\nexport type SymbolHover = { markdown: string };\n\nexport class DataSource {\n\t// if `recursive` is true, it should try to return all subtrees\n\t// the returned Directory.entries.path is relative the `path` in arguments,\n\t// so if `recursive` is false, the returned path should be the file name\n\tprovideDirectory(repo: string, ref: string, path: string, recursive = false): Promisable<Directory | null> {\n\t\treturn null;\n\t}\n\n\t// the ref here may be a commitSha, branch, tag, or 'HEAD'\n\tprovideFile(repo: string, ref: string, path: string): Promisable<File | null> {\n\t\treturn null;\n\t}\n\n\tprovideBranches(repo: string, options?: CommonQueryOptions): Promisable<Branch[]> {\n\t\treturn [];\n\t}\n\n\tprovideBranch(repo: string, branchName: string): Promisable<Branch | null> {\n\t\treturn null;\n\t}\n\n\tprovideTags(repo: string, options?: CommonQueryOptions): Promisable<Tag[]> {\n\t\treturn [];\n\t}\n\n\tprovideTag(repo: string, tagName: string): Promisable<Tag | null> {\n\t\treturn null;\n\t}\n\n\t// use `report` to populate search results gradually\n\tprovideTextSearchResults(\n\t\trepo: string,\n\t\tref: string,\n\t\tquery: TextSearchQuery,\n\t\toptions?: TextSearchOptions,\n\t): Promisable<TextSearchResults> {\n\t\treturn { results: [], truncated: false };\n\t}\n\n\t// optionally return changed files (if `files` exists can reduce api calls)\n\t// commits should be returned by the order of `new to old`, if `options.path` is not empty,\n\t// the first commit should be the latest commit that related the `options.path` file (maybe not `ref`)\n\tprovideCommits(repo: string, options?: CommitsQueryOptions): Promisable<(Commit & { files?: ChangedFile[] })[]> {\n\t\treturn [];\n\t}\n\n\t// the ref here may be a commitSha, branch, tag, or 'HEAD'\n\t// optionally return changed files (if `files` exists can reduce api calls)\n\tprovideCommit(repo: string, ref: string): Promisable<(Commit & { files?: ChangedFile[] }) | null> {\n\t\treturn null;\n\t}\n\n\tprovideCommitChangedFiles(repo: string, ref: string, options?: CommonQueryOptions): Promisable<ChangedFile[]> {\n\t\treturn [];\n\t}\n\n\t// optionally return changed files (if `files` exists can reduce api calls)\n\tprovideCodeReviews(\n\t\trepo: string,\n\t\toptions?: CodeReviewsQueryOptions,\n\t): Promisable<(CodeReview & { files?: ChangedFile[] })[]> {\n\t\treturn [];\n\t}\n\n\t// optionally return changed files (if `files` exists can reduce api calls)\n\tprovideCodeReview(\n\t\trepo: string,\n\t\tid: string,\n\t): Promisable<(CodeReview & { sourceSha: string; targetSha: string; files?: ChangedFile[] }) | null> {\n\t\treturn null;\n\t}\n\n\tprovideCodeReviewChangedFiles(repo: string, id: string, options?: CommonQueryOptions): Promisable<ChangedFile[]> {\n\t\treturn [];\n\t}\n\n\tprovideFileBlameRanges(repo: string, ref: string, path: string): Promisable<BlameRange[]> {\n\t\treturn [];\n\t}\n\n\tprovideSymbolDefinitions(\n\t\trepo: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promisable<SymbolDefinitions> {\n\t\treturn [];\n\t}\n\n\tprovideSymbolReferences(\n\t\trepo: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promisable<SymbolReferences> {\n\t\treturn [];\n\t}\n\n\tprovideSymbolHover(\n\t\trepo: string,\n\t\tref: string,\n\t\tpath: string,\n\t\tline: number,\n\t\tcharacter: number,\n\t\tsymbol: string,\n\t): Promisable<SymbolHover | null> {\n\t\treturn null;\n\t}\n\n\tprovideUserAvatarLink(user: string): string {\n\t\treturn '';\n\t}\n}\n\nexport enum PageType {\n\t// show the structure of a dictionary\n\t// e.g. https://github.com/conwnet/github1s/tree/master/src/vs\n\tTree = 'Tree',\n\n\t// show the content for a file\n\t// e.g. https://github.com/conwnet/github1s/blob/master/extensions/github1s/src/extension.ts\n\tBlob = 'Blob',\n\n\t// show the commit list of a repository\n\t// e.g. https://github.com/conwnet/github1s/commits/master\n\tCommitList = 'CommitList',\n\n\t// show the detail of a commit\n\t// e.g. https://github.com/conwnet/github1s/commit/c1264f7338833c7aa3a502c4629df8aa6b7d6ccf\n\tCommit = 'Commit',\n\n\t// show the pull request (or merge request) list of a repository\n\t// e.g. https://github.com/conwnet/github1s/pulls\n\tCodeReviewList = 'CodeReviewList',\n\n\t// show the detail of a pull request (or merge request)\n\t// e.g. https://github.com/conwnet/github1s/pull/81\n\tCodeReview = 'CodeReview',\n\n\t// show the file blame\n\t// e.g. https://github.com/conwnet/github1s/blame/master/.gitignore\n\tFileBlame = 'FileBlame',\n\n\t// show search result\n\tSearch = 'Search',\n\n\t// branches, tags, wiki, gist should be on the way\n\tUnknown = 'Unknown',\n}\n\nexport type RouterState = { repo: string; ref: string } & (\n\t| { pageType: PageType.Tree; filePath: string } // for tree page\n\t| { pageType: PageType.Blob; filePath: string; startLine?: number; endLine?: number } // for blob page\n\t| { pageType: PageType.CommitList } // for commit list page\n\t| { pageType: PageType.Commit; commitSha: string } // for commit detail page\n\t| { pageType: PageType.CodeReviewList } // for code review list page\n\t| { pageType: PageType.CodeReview; codeReviewId: string }\n\t| {\n\t\t\tpageType: PageType.Search;\n\t\t\tquery?: string;\n\t\t\tisRegex?: boolean;\n\t\t\tisCaseSensitive?: boolean;\n\t\t\tmatchWholeWord?: boolean;\n\t\t\tfilesToInclude?: string;\n\t\t\tfilesToExclude?: string;\n\t  }\n);\n\nexport class RouterParser {\n\t// parse giving path (starts with '/', may includes search and hash) to Router state,\n\tparsePath(path: string): Promisable<RouterState> {\n\t\treturn { repo: '', ref: 'HEAD', pageType: PageType.Tree, filePath: '' };\n\t}\n\n\t// build the tree page path\n\tbuildTreePath(repo: string, ref?: string, filePath?: string): Promisable<string> {\n\t\treturn '/' + repo;\n\t}\n\n\t// build the blob page path\n\t// startLine/endLine begins from 1\n\n\tbuildBlobPath(repo: string, ref: string, filePath: string, startLine?: number, endLine?: number): Promisable<string> {\n\t\treturn '/' + repo;\n\t}\n\t// build the commit list page path\n\tbuildCommitListPath(repo: string): Promisable<string> {\n\t\treturn '/' + repo;\n\t}\n\n\t// build the commit page path\n\tbuildCommitPath(repo: string, commitSha: string): Promisable<string> {\n\t\treturn '/' + repo;\n\t}\n\n\t// build the code review list page path\n\tbuildCodeReviewListPath(repo: string): Promisable<string> {\n\t\treturn '/' + repo;\n\t}\n\n\t// build the code review page path\n\tbuildCodeReviewPath(repo: string, codeReviewId: string): Promisable<string> {\n\t\treturn '/' + repo;\n\t}\n\n\t// convert giving path to the external link (using for jumping back to origin platform)\n\tbuildExternalLink(path: string): Promisable<string> {\n\t\treturn path;\n\t}\n}\n\nexport enum CodeReviewType {\n\tPullRequest = 'PullRequest',\n\tMergeRequest = 'MergeRequest',\n\tChangeRequest = 'ChangeRequest',\n\tCodeReview = 'CodeReview', // as fallback\n}\n\nexport enum PlatformName {\n\tGitHub = 'GitHub',\n\tGitLab = 'GitLab',\n\tBitbucket = 'Bitbucket',\n\tnpm = 'npm',\n\tOfficialPage = 'OfficialPage', // as fallback\n}\n\nexport interface Adapter {\n\t// specify which scheme of workspace should current adapter should work with\n\treadonly scheme: string;\n\t// platform name, using for displaying text such as: `open on **GitHub**`\n\treadonly platformName: PlatformName;\n\t// the code review type\n\treadonly codeReviewType?: CodeReviewType;\n\n\tresolveDataSource(): Promisable<DataSource>;\n\tresolveRouterParser(): Promisable<RouterParser>;\n\tactivateAsDefault?(): Promisable<void>;\n\tdeactivateAsDefault?(): Promisable<void>;\n}\n"
  },
  {
    "path": "extensions/github1s/src/changes/files.ts",
    "content": "/**\n * @file source control change file list\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport * as queryString from 'query-string';\nimport * as adapterTypes from '@/adapters/types';\nimport adapterManager from '@/adapters/manager';\nimport router from '@/router';\nimport { basename } from '@/helpers/util';\nimport { emptyFileUri } from '@/providers';\nimport { Repository } from '@/repository';\n\ninterface VSCodeChangedFile {\n\tbaseFileUri: vscode.Uri;\n\theadFileUri: vscode.Uri;\n\tstatus: adapterTypes.FileChangeStatus;\n}\n\n// get the change files of a codeReview\nexport const getCodeReviewChangedFiles = async (\n\tcodeReview: adapterTypes.CodeReview & { sourceSha: string; targetSha: string },\n) => {\n\tconst scheme = adapterManager.getCurrentScheme();\n\tconst { repo } = await router.getState();\n\tconst baseRootUri = vscode.Uri.parse('').with({\n\t\tscheme: scheme,\n\t\tauthority: `${repo}+${codeReview.targetSha}`,\n\t\tpath: '/',\n\t});\n\tconst headRootUri = baseRootUri.with({\n\t\tauthority: `${repo}+${codeReview.sourceSha}`,\n\t});\n\n\tconst repository = Repository.getInstance(scheme, repo);\n\tconst changedFiles = await repository.getCodeReviewChangedFiles(codeReview.id);\n\n\treturn changedFiles.map((changedFile) => {\n\t\t// the `previous_filename` field only exists in `RENAMED` file,\n\t\t// fallback to `filename` otherwise\n\t\tconst baseFilePath = changedFile.previousPath || changedFile.path;\n\t\tconst headFilePath = changedFile.path;\n\t\treturn {\n\t\t\tbaseFileUri: vscode.Uri.joinPath(baseRootUri, baseFilePath),\n\t\t\theadFileUri: vscode.Uri.joinPath(headRootUri, headFilePath),\n\t\t\tstatus: changedFile.status,\n\t\t};\n\t});\n};\n\nexport const getCommitChangedFiles = async (commit: adapterTypes.Commit) => {\n\tconst currentAdapter = adapterManager.getCurrentAdapter();\n\tconst scheme = currentAdapter.scheme;\n\tconst { repo } = await router.getState();\n\t// if the commit.parents is more than one element\n\t// the parents[1].sha should be the merge source commitSha\n\t// so we use the parents[0].sha as the parent commitSha\n\tconst baseRef = commit?.parents?.[0];\n\tconst baseRootUri = vscode.Uri.parse('').with({\n\t\tscheme: currentAdapter.scheme,\n\t\tauthority: `${repo}+${baseRef || 'HEAD'}`,\n\t\tpath: '/',\n\t});\n\tconst headRootUri = baseRootUri.with({\n\t\tauthority: `${repo}+${commit.sha || 'HEAD'}`,\n\t});\n\tconst repository = Repository.getInstance(scheme, repo);\n\tconst changedFiles = await repository.getCommitChangedFiles(commit.sha);\n\n\treturn changedFiles.map((commitFile) => {\n\t\t// the `previous_filename` field only exists in `RENAMED` file,\n\t\t// fallback to `filename` otherwise\n\t\tconst baseFilePath = commitFile.previousPath || commitFile.path;\n\t\tconst headFilePath = commitFile.path;\n\t\treturn {\n\t\t\tbaseFileUri: vscode.Uri.joinPath(baseRootUri, baseFilePath),\n\t\t\theadFileUri: vscode.Uri.joinPath(headRootUri, headFilePath),\n\t\t\tstatus: commitFile.status,\n\t\t};\n\t});\n};\n\nexport const getChangedFiles = async (): Promise<VSCodeChangedFile[]> => {\n\tconst routerState = await router.getState();\n\tconst scheme = adapterManager.getCurrentScheme();\n\n\t// code review page\n\tif (routerState.pageType === adapterTypes.PageType.CodeReview) {\n\t\tconst repository = Repository.getInstance(scheme, routerState.repo);\n\t\tconst codeReview = await repository.getCodeReviewItem(routerState.codeReviewId);\n\t\treturn codeReview ? getCodeReviewChangedFiles(codeReview) : [];\n\t}\n\t// commit page\n\telse if (routerState.pageType === adapterTypes.PageType.Commit) {\n\t\tconst repository = Repository.getInstance(scheme, routerState.repo);\n\t\tconst commit = await repository.getCommitItem(routerState.commitSha);\n\t\treturn commit ? getCommitChangedFiles(commit) : [];\n\t}\n\treturn [];\n};\n\n// get the title of the diff editor\nexport const getChangedFileDiffTitle = (\n\tbaseFileUri: vscode.Uri,\n\theadFileUri: vscode.Uri,\n\tstatus: adapterTypes.FileChangeStatus,\n) => {\n\tconst baseFileName = basename(baseFileUri.path);\n\tconst headFileName = basename(headFileUri.path);\n\tconst [_repo, baseCommitSha] = baseFileUri.authority.split('+');\n\tconst [__repo, headCommitSha] = headFileUri.authority.split('+');\n\tconst baseFileLabel = `${baseFileName} (${baseCommitSha?.slice(0, 7)})`;\n\tconst headFileLabel = `${headFileName} (${headCommitSha?.slice(0, 7)})`;\n\n\tif (status === adapterTypes.FileChangeStatus.Added) {\n\t\treturn `${headFileName} (added in ${headCommitSha?.slice(0, 7)})`;\n\t}\n\n\tif (status === adapterTypes.FileChangeStatus.Removed) {\n\t\treturn `${baseFileName} (deleted from ${baseCommitSha?.slice(0, 7)})`;\n\t}\n\n\treturn `${baseFileLabel} ⟷ ${headFileLabel}`;\n};\n\nexport const getChangedFileDiffCommand = (changedFile: VSCodeChangedFile): vscode.Command => {\n\tlet baseFileUri = changedFile.baseFileUri;\n\tlet headFileUri = changedFile.headFileUri;\n\tconst status = changedFile.status;\n\n\tif (status === adapterTypes.FileChangeStatus.Added) {\n\t\tbaseFileUri = emptyFileUri;\n\t}\n\n\tif (status === adapterTypes.FileChangeStatus.Removed) {\n\t\theadFileUri = emptyFileUri;\n\t}\n\n\tconst title = getChangedFileDiffTitle(baseFileUri, headFileUri, status);\n\tconst query = queryString.stringify({\n\t\tstatus,\n\t\tbase: baseFileUri.with({ query: '' }).toString(),\n\t\thead: headFileUri.with({ query: '' }).toString(),\n\t});\n\n\treturn {\n\t\ttitle: 'Diff',\n\t\tcommand: 'vscode.diff',\n\t\targuments: [baseFileUri.with({ query }), headFileUri.with({ query }), title],\n\t};\n};\n"
  },
  {
    "path": "extensions/github1s/src/changes/index.ts",
    "content": "/**\n * @file Source Control Changed Files\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport * as adapterTypes from '@/adapters/types';\nimport { GitHub1sQuickDiffProvider } from './quick-diff';\nimport { getChangedFileDiffCommand, getChangedFiles } from './files';\nimport adapterManager from '@/adapters/manager';\n\nexport const updateSourceControlChanges = (() => {\n\tconst rootUri = vscode.Uri.parse('').with({ scheme: adapterManager.getCurrentScheme() });\n\tconst sourceControl = vscode.scm.createSourceControl('github1s', 'GitHub1s', rootUri);\n\tconst changesGroup = sourceControl.createResourceGroup('changes', 'Changes');\n\tsourceControl.quickDiffProvider = new GitHub1sQuickDiffProvider();\n\n\treturn async () => {\n\t\tconst changedFiles = await getChangedFiles();\n\n\t\tchangesGroup.resourceStates = changedFiles.map((changedFile) => {\n\t\t\treturn {\n\t\t\t\tresourceUri: changedFile.headFileUri,\n\t\t\t\tdecorations: {\n\t\t\t\t\tstrikeThrough: changedFile.status === adapterTypes.FileChangeStatus.Removed,\n\t\t\t\t\ttooltip: changedFile.status,\n\t\t\t\t},\n\t\t\t\tcommand: getChangedFileDiffCommand(changedFile),\n\t\t\t};\n\t\t});\n\t};\n})();\n"
  },
  {
    "path": "extensions/github1s/src/changes/quick-diff.ts",
    "content": "/**\n * @file GitHub1s quickDiffProvider for pull/commit change files\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { Repository } from '@/repository';\nimport { emptyFileUri } from '@/providers';\nimport adapterManager from '@/adapters/manager';\nimport * as adapterTypes from '@/adapters/types';\n\n// get the original source uri when the `routerState.pageType` is `PageType.PULL`\nconst getOriginalResourceForPull = async (uri: vscode.Uri, codeReviewId: string): Promise<vscode.Uri | null> => {\n\tconst routeState = await router.getState();\n\tconst currentScheme = adapterManager.getCurrentScheme();\n\tconst repository = Repository.getInstance(currentScheme, routeState.repo);\n\tconst codeReviewFiles = await repository.getCodeReviewChangedFiles(codeReviewId);\n\tconst changedFile = codeReviewFiles?.find((changedFile) => changedFile.path === uri.path.slice(1));\n\n\tif (\n\t\t!changedFile ||\n\t\tchangedFile.status === adapterTypes.FileChangeStatus.Added ||\n\t\tchangedFile.status === adapterTypes.FileChangeStatus.Removed\n\t) {\n\t\treturn null;\n\t}\n\n\tconst codeReview = await repository.getCodeReviewItem(codeReviewId);\n\tif (!codeReview?.targetSha) {\n\t\treturn null;\n\t}\n\n\tconst originalAuthority = `${routeState.repo}+${codeReview!.targetSha}`;\n\tconst originalPath = changedFile.previousPath ? `/${changedFile.previousPath}` : uri.path;\n\n\treturn uri.with({ authority: originalAuthority, path: originalPath });\n};\n\n// get the original source uri when the `routerState.pageType` is `PageType.COMMIT`\nconst getOriginalResourceForCommit = async (uri: vscode.Uri, commitSha: string) => {\n\tconst routeState = await router.getState();\n\tconst currentScheme = adapterManager.getCurrentScheme();\n\tconst repository = Repository.getInstance(currentScheme, routeState.repo);\n\tconst commitFiles = await repository.getCommitChangedFiles(commitSha);\n\tconst changedFile = commitFiles?.find((changedFile) => changedFile.path === uri.path.slice(1));\n\n\tif (\n\t\t!changedFile ||\n\t\tchangedFile.status === adapterTypes.FileChangeStatus.Added ||\n\t\tchangedFile.status === adapterTypes.FileChangeStatus.Removed\n\t) {\n\t\treturn null;\n\t}\n\n\tconst commit = await repository.getCommitItem(commitSha);\n\tconst parentCommitSha = commit?.parents?.[0];\n\tif (!parentCommitSha) {\n\t\treturn emptyFileUri;\n\t}\n\n\tconst originalAuthority = `${routeState.repo}+${parentCommitSha}`;\n\tconst originalPath = changedFile.previousPath ? `/${changedFile.previousPath}` : uri.path;\n\n\treturn uri.with({ authority: originalAuthority, path: originalPath });\n};\n\nexport class GitHub1sQuickDiffProvider implements vscode.QuickDiffProvider {\n\tprovideOriginalResource(uri: vscode.Uri, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.Uri> {\n\t\tif (uri.scheme !== adapterManager.getCurrentScheme()) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn router.getState().then(async (routerState) => {\n\t\t\t// only the file belong to current authority could be provided a quick diff\n\t\t\tif (uri.authority && uri.authority !== (await router.getAuthority())) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (routerState.pageType === adapterTypes.PageType.CodeReview) {\n\t\t\t\treturn getOriginalResourceForPull(uri, routerState.codeReviewId);\n\t\t\t}\n\n\t\t\tif (routerState.pageType === adapterTypes.PageType.Commit) {\n\t\t\t\treturn getOriginalResourceForCommit(uri, routerState.commitSha);\n\t\t\t}\n\n\t\t\treturn null;\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/commands/blame.ts",
    "content": "/**\n * @file GitHub1s Blame Related Commands\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { relativeTimeTo } from '@/helpers/date';\nimport { last } from '@/helpers/util';\nimport { setVSCodeContext } from '@/helpers/vscode';\nimport router from '@/router';\nimport { Repository } from '@/repository';\nimport { BlameRange, PlatformName } from '@/adapters/types';\nimport { adapterManager } from '@/adapters';\n\nconst ageColors = [\n\t'#f66a0a',\n\t'#ef6939',\n\t'#e26862',\n\t'#d3677e',\n\t'#c46696',\n\t'#b365a9',\n\t'#a064bb',\n\t'#8a63cc',\n\t'#7162db',\n\t'#5061e9',\n\t'#0a60f6',\n];\n\nconst openOnOfficialPageCommand = {\n\t[PlatformName.GitHub]: {\n\t\tcommand: 'github1s.commands.openCommitOnGitHub',\n\t\ttitle: 'Open on GitHub',\n\t},\n\t[PlatformName.GitLab]: {\n\t\tcommand: 'github1s.commands.openCommitOnGitLab',\n\t\ttitle: 'Open on GitLab',\n\t},\n\t[PlatformName.Bitbucket]: {\n\t\tcommand: 'github1s.commands.openCommitOnBitbucket',\n\t\ttitle: 'Open on Bitbucket',\n\t},\n\t[PlatformName.OfficialPage]: {\n\t\tcommand: 'github1s.commands.openCommitOnOfficialPage',\n\t\ttitle: 'Open on Official Page',\n\t},\n};\n\nconst createCommitMessagePreviewMarkdown = (blameRange: BlameRange, platformName: PlatformName) => {\n\tconst commit = blameRange.commit;\n\tconst messageTextLines: string[] = [];\n\n\tmessageTextLines.push(\n\t\t`![avatar](${commit.avatarUrl}|width=16px,height=16px) [${commit.author}](mailto:${commit.email}), ${relativeTimeTo(commit.createTime)} (*${commit.createTime}*)`, // prettier-ignore\n\t);\n\tmessageTextLines.push(`Commit ID: ${commit.sha}`);\n\n\tmessageTextLines.push('---');\n\tmessageTextLines.push(`~~~\\n${commit.message}\\n~~~`);\n\tmessageTextLines.push('---');\n\n\tconst commandConfig = openOnOfficialPageCommand[platformName];\n\tconst switchToCommitCommandText = `command:github1s.commands.switchToCommit?${encodeURIComponent(JSON.stringify([commit.sha]))}`; // prettier-ignore\n\tconst openOnGitHubCommandText = `command:${commandConfig.command}?${encodeURIComponent(JSON.stringify([commit.sha]))}`; // prettier-ignore\n\tmessageTextLines.push(\n\t\t`[$(log-in) Switch to Commit](${switchToCommitCommandText}) | [$(globe) ${commandConfig.title}](${openOnGitHubCommandText})`,\n\t);\n\n\tconst markdownString = new vscode.MarkdownString(messageTextLines.join('\\n\\n'), true);\n\tmarkdownString.isTrusted = true;\n\treturn markdownString;\n};\n\nconst commonLineDecorationTypeOptions = {\n\tbefore: {\n\t\twidth: '460px',\n\t\theight: '100%',\n\t\tcontentText: '.',\n\t\tcolor: 'rgba(0, 0, 0, 0)',\n\t\tmargin: '0 20px 0 0',\n\t\tborderStyle: 'none',\n\t\ttextDecoration: `none;\n\t\t\tbox-sizing: border-box;\n\t\t\tpadding-right: 110px;\n\t\t\tborder-right-width: 2px;\n\t\t\tborder-right-style: solid`,\n\t},\n\tafter: {\n\t\twidth: '460px',\n\t\theight: '100%',\n\t\tcontentText: '.',\n\t\tcolor: 'rgba(0, 0, 0, 0)',\n\t\ttextDecoration: `none;\n\t\t\tbox-sizing: border-box;\n\t\t\tposition: absolute;\n\t\t\tleft: 0;\n\t\t\tz-index: -1;\n\t\t\ttext-align: right;\n\t\t\tpadding-right: 6px`,\n\t\tbackgroundColor: new vscode.ThemeColor('github1s.colors.gutterBlameBackground'),\n\t},\n};\n\n// the decoration type for the all lines that belong\n// to the commit which user are focusing to\nconst createSelectedLineDecorationType = () =>\n\tvscode.window.createTextEditorDecorationType({\n\t\tisWholeLine: true,\n\t\toverviewRulerColor: new vscode.ThemeColor('github1s.colors.highlightGutterBlameBackground'),\n\t\tbackgroundColor: new vscode.ThemeColor('github1s.colors.highlightGutterBlameBackground'),\n\t});\n\n// the decoration type for the first line of **a blame block**\nconst createFirstLineDecorationType = (blameRange: BlameRange) => {\n\t// put the avatar of commit author to the beginning of the line\n\tconst firstLineBeforeTextDecorationCss =\n\t\tcommonLineDecorationTypeOptions.before.textDecoration +\n\t\t`; white-space: nowrap;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t\tvertical-align: bottom;\n\t\ttext-indent: 2em;\n\t\tbackground-image: url(${encodeURI(blameRange.commit?.avatarUrl || '')});\n\t\tbackground-size: auto 95%;\n\t\tbackground-position: 0 50%;\n\t\tbackground-repeat: no-repeat`;\n\t// set the split line with other blame blocks\n\tconst firstLineAfterTextDecorationCss =\n\t\tcommonLineDecorationTypeOptions.after.textDecoration + `; box-shadow: 0 -1px 0 rgba(0, 0, 0, .3)`;\n\n\treturn vscode.window.createTextEditorDecorationType({\n\t\t...commonLineDecorationTypeOptions,\n\t\tbefore: {\n\t\t\t...commonLineDecorationTypeOptions.before,\n\t\t\tcontentText: blameRange.commit.message,\n\t\t\tcolor: new vscode.ThemeColor('foreground'),\n\t\t\ttextDecoration: firstLineBeforeTextDecorationCss,\n\t\t\tborderColor: ageColors[blameRange.age % 11 || 10],\n\t\t},\n\t\tafter: {\n\t\t\t...commonLineDecorationTypeOptions.after,\n\t\t\tcontentText: relativeTimeTo(blameRange.commit.createTime),\n\t\t\tcolor: new vscode.ThemeColor('descriptionForeground'),\n\t\t\ttextDecoration: firstLineAfterTextDecorationCss,\n\t\t},\n\t});\n};\n\n// the decoration type for the rest lines (not the first line) of a blame block\nconst createRestLinesDecorationType = (blameRange: BlameRange) => {\n\treturn vscode.window.createTextEditorDecorationType({\n\t\t...commonLineDecorationTypeOptions,\n\t\tbefore: {\n\t\t\t...commonLineDecorationTypeOptions.before,\n\t\t\tborderColor: ageColors[blameRange.age % 11 || 10],\n\t\t},\n\t});\n};\n\n// create decoration option for each line of a blame block\nconst createLineDecorationOptions = (\n\tblameRange: BlameRange,\n\thoverMessage?: vscode.MarkdownString | string,\n): vscode.DecorationOptions[] => {\n\tconst decorationOptions: vscode.DecorationOptions[] = [];\n\tconst { startingLine, endingLine } = blameRange;\n\n\tfor (let lineIndex = startingLine - 1; lineIndex < endingLine; lineIndex++) {\n\t\tdecorationOptions.push({\n\t\t\trange: new vscode.Range(new vscode.Position(lineIndex, 0), new vscode.Position(lineIndex, 0)),\n\t\t\thoverMessage,\n\t\t});\n\t}\n\treturn decorationOptions;\n};\n\nclass EditorGitBlame {\n\tprivate static instanceMap = new WeakMap<vscode.TextEditor, EditorGitBlame>();\n\tprivate opening: boolean = false; // if the editor blame is showing now\n\tprivate refreshDisposables: vscode.Disposable[] = [];\n\tprivate selectionDisposables: vscode.Disposable[] = [];\n\n\tprivate constructor(private editor: vscode.TextEditor) {\n\t\tvscode.window.onDidChangeTextEditorSelection((event) => {\n\t\t\tif (this.opening && event.selections.length) {\n\t\t\t\tthis.selection(last(event.selections).active.line);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic static getInstance(editor: vscode.TextEditor) {\n\t\tif (!EditorGitBlame.instanceMap.has(editor)) {\n\t\t\tEditorGitBlame.instanceMap.set(editor, new EditorGitBlame(editor));\n\t\t}\n\t\treturn EditorGitBlame.instanceMap.get(editor)!;\n\t}\n\n\tasync getBlameRanges(): Promise<BlameRange[]> {\n\t\tconst filePath = this.editor.document?.uri.path;\n\t\tconst fileAuthority = this.editor.document?.uri.authority || (await router.getAuthority());\n\t\tconst [repo, ref] = fileAuthority.split('+').filter(Boolean);\n\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\tconst repository = Repository.getInstance(scheme, repo);\n\t\treturn filePath ? repository.getFileBlameRanges(ref, filePath.slice(1)) : [];\n\t}\n\n\tasync open() {\n\t\tthis.refreshDisposables.forEach((disposable) => disposable.dispose());\n\t\tsetVSCodeContext('github1s:features:gutterBlame:open', true);\n\t\tconst { platformName } = adapterManager.getCurrentAdapter();\n\n\t\t(await this.getBlameRanges()).forEach((blameRange) => {\n\t\t\tconst hoverMessage = createCommitMessagePreviewMarkdown(blameRange, platformName);\n\t\t\tconst firstLineDecorationType = createFirstLineDecorationType(blameRange);\n\t\t\tconst lineDecorationOptions = createLineDecorationOptions(blameRange, hoverMessage);\n\n\t\t\tthis.refreshDisposables.push(firstLineDecorationType);\n\t\t\tthis.editor.setDecorations(firstLineDecorationType, [lineDecorationOptions[0]]);\n\n\t\t\tif (lineDecorationOptions.length > 1) {\n\t\t\t\tconst restLinesDecorationType = createRestLinesDecorationType(blameRange);\n\n\t\t\t\tthis.refreshDisposables.push(restLinesDecorationType);\n\t\t\t\tthis.editor.setDecorations(restLinesDecorationType, lineDecorationOptions.slice(1));\n\t\t\t}\n\t\t});\n\t\tthis.opening = true;\n\t}\n\n\tasync selection(lineIndex: number) {\n\t\tthis.selectionDisposables.forEach((disposable) => disposable.dispose());\n\n\t\tconst blameRanges = await this.getBlameRanges();\n\t\tconst selectedCommitSha = blameRanges.find(\n\t\t\t(blameRange) => blameRange.startingLine - 1 <= lineIndex && blameRange.endingLine - 1 >= lineIndex,\n\t\t)?.commit.sha;\n\t\tconst selectedBlameRanges = blameRanges.filter((blameRange) => blameRange.commit.sha === selectedCommitSha);\n\t\tconst decorationType = createSelectedLineDecorationType();\n\t\tconst decorationOptions: vscode.DecorationOptions[] = [];\n\n\t\tthis.selectionDisposables.push(decorationType);\n\t\tselectedBlameRanges.forEach((blameRange) => {\n\t\t\tdecorationOptions.push(...createLineDecorationOptions(blameRange));\n\t\t});\n\t\tthis.editor.setDecorations(decorationType, decorationOptions);\n\t}\n\n\tclose() {\n\t\tsetVSCodeContext('github1s:features:gutterBlame:open', false);\n\t\tthis.refreshDisposables.forEach((disposable) => disposable.dispose());\n\t\tthis.selectionDisposables.forEach((disposable) => disposable.dispose());\n\t\tthis.opening = false;\n\t}\n\n\ttoggle() {\n\t\treturn this.opening ? this.close() : this.open();\n\t}\n}\n\nconst commandToggleEditorGutterBlame = () => {\n\tif (vscode.window.activeTextEditor) {\n\t\treturn EditorGitBlame.getInstance(vscode.window.activeTextEditor).toggle();\n\t}\n};\n\nconst commandOpenEditorGutterBlame = () => {\n\tif (vscode.window.activeTextEditor) {\n\t\treturn EditorGitBlame.getInstance(vscode.window.activeTextEditor).open();\n\t}\n};\n\nconst commandCloseEditorGutterBlame = () => {\n\tif (vscode.window.activeTextEditor) {\n\t\treturn EditorGitBlame.getInstance(vscode.window.activeTextEditor).close();\n\t}\n};\n\nexport const registerBlameCommands = (context: vscode.ExtensionContext) => {\n\treturn context.subscriptions.push(\n\t\tvscode.commands.registerCommand('github1s.commands.toggleEditorGutterBlame', commandToggleEditorGutterBlame),\n\t\tvscode.commands.registerCommand('github1s.commands.openEditorGutterBlame', commandOpenEditorGutterBlame),\n\t\tvscode.commands.registerCommand('github1s.commands.closeEditorGutterBlame', commandCloseEditorGutterBlame),\n\t);\n};\n"
  },
  {
    "path": "extensions/github1s/src/commands/code-review.ts",
    "content": "/**\n * @file GitHub1s Code Review Related Commands\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport {\n\tCodeReviewTreeItem,\n\tgetCodeReviewTreeItemLabel,\n\tgetCodeReviewTreeItemDescription,\n} from '@/views/code-review-list';\nimport { codeReviewRequestTreeDataProvider } from '@/views';\nimport { CodeReviewType } from '@/adapters/types';\nimport { adapterManager } from '@/adapters';\nimport { Repository } from '@/repository';\n\nconst CodeReviewTypeName = {\n\t[CodeReviewType.PullRequest]: 'pull request',\n\t[CodeReviewType.MergeRequest]: 'merge request',\n\t[CodeReviewType.ChangeRequest]: 'change request',\n\t[CodeReviewType.CodeReview]: 'code review',\n};\n\nconst checkCodeReviewExists = async (repo: string, codeReviewId: string) => {\n\tconst adapter = adapterManager.getCurrentAdapter();\n\tconst dataSoruce = await adapter.resolveDataSource();\n\ttry {\n\t\treturn !!(await dataSoruce.provideCodeReview(repo, codeReviewId));\n\t} catch (error) {\n\t\tconst typeName = CodeReviewTypeName[adapter.codeReviewType || CodeReviewType.CodeReview];\n\t\tconst errorMessage =\n\t\t\t(error as any)?.response?.status === 404\n\t\t\t\t? `No ${typeName} found for id: ${codeReviewId}`\n\t\t\t\t: error?.response?.data?.message;\n\t\tvscode.window.showErrorMessage(errorMessage || `Get ${typeName} ${codeReviewId} error`);\n\t\treturn false;\n\t}\n};\n\nconst commandSwitchToCodeReview = async (codeReviewItemOrId?: string | CodeReviewTreeItem) => {\n\tlet codeReviewId: string | undefined = codeReviewItemOrId\n\t\t? typeof codeReviewItemOrId === 'string'\n\t\t\t? codeReviewItemOrId\n\t\t\t: codeReviewItemOrId.codeReview.id\n\t\t: '';\n\tconst adapter = adapterManager.getCurrentAdapter();\n\tconst { repo } = await router.getState();\n\tconst typeName = CodeReviewTypeName[adapter.codeReviewType || CodeReviewType.CodeReview];\n\tconst repository = Repository.getInstance(adapter.scheme, repo);\n\n\t// if the a codeReviewId isn't provided, use quickInput\n\tif (!codeReviewId) {\n\t\t// manual input a codeReviewId\n\t\tconst inputCodeReviewIdItem: vscode.QuickPickItem = {\n\t\t\tlabel: `$(git-pull-request) Manual input the ${typeName} id`,\n\t\t\talwaysShow: true,\n\t\t};\n\t\t// use the code review list as the candidates\n\t\tconst codeReviews = await repository.getCodeReviewList();\n\t\tconst codeReviewItems: vscode.QuickPickItem[] = codeReviews.map((codeReview) => ({\n\t\t\tcodeReviewId: codeReview.id,\n\t\t\tlabel: getCodeReviewTreeItemLabel(codeReview),\n\t\t\tdescription: getCodeReviewTreeItemDescription(codeReview),\n\t\t}));\n\n\t\tconst quickPick = vscode.window.createQuickPick<vscode.QuickPickItem>();\n\t\tquickPick.matchOnDescription = true;\n\t\tquickPick.items = [inputCodeReviewIdItem, ...codeReviewItems];\n\t\tquickPick.show();\n\n\t\tconst choice = (await new Promise<vscode.QuickPickItem | undefined>((resolve) =>\n\t\t\tquickPick.onDidAccept(() => resolve(quickPick.activeItems[0])),\n\t\t)) as vscode.QuickPickItem & { codeReviewId?: string };\n\t\tquickPick.hide();\n\n\t\t// select nothing\n\t\tif (!choice) {\n\t\t\treturn;\n\t\t}\n\n\t\t// select `manual input the code review id`\n\t\tif (choice === inputCodeReviewIdItem) {\n\t\t\tcodeReviewId = await vscode.window.showInputBox({\n\t\t\t\tplaceHolder: `Please input the ${typeName} id`,\n\t\t\t});\n\t\t} else {\n\t\t\t// select a code review item\n\t\t\tcodeReviewId = choice.codeReviewId;\n\t\t}\n\t}\n\n\tconst routerParser = await router.resolveParser();\n\t(await checkCodeReviewExists(repo, codeReviewId!)) &&\n\t\trouter.replace(await routerParser.buildCodeReviewPath(repo, codeReviewId!));\n};\n\n// this command is used in `source control code review view`\nconst commandOpenCodeReviewOnOfficialPage = async (codeReviewItemOrId?: string | CodeReviewTreeItem) => {\n\tconst codeReviewId: string | undefined = codeReviewItemOrId\n\t\t? typeof codeReviewItemOrId === 'string'\n\t\t\t? codeReviewItemOrId\n\t\t\t: codeReviewItemOrId.codeReview.id\n\t\t: '';\n\tif (codeReviewId) {\n\t\tconst { repo } = await router.getState();\n\t\tconst routerParser = await router.resolveParser();\n\t\tconst codeReviewPath = await routerParser.buildCodeReviewPath(repo, codeReviewId);\n\t\tconst codeReviewLink = await routerParser.buildExternalLink(codeReviewPath);\n\t\treturn vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(codeReviewLink));\n\t}\n};\n\nconst commandRefreshCodeReviewList = (forceUpdate = true) => {\n\treturn codeReviewRequestTreeDataProvider.updateTree(forceUpdate);\n};\n\nconst commandLoadMoreCodeReviews = async () => {\n\treturn codeReviewRequestTreeDataProvider.loadMoreCodeReviews();\n};\n\nconst commandLoadMoreCodeReviewChangedFiles = async (codeReviewId: string) => {\n\treturn codeReviewRequestTreeDataProvider.loadMoreChangedFiles(codeReviewId);\n};\n\nexport const registerCodeReviewCommands = (context: vscode.ExtensionContext) => {\n\treturn context.subscriptions.push(\n\t\tvscode.commands.registerCommand('github1s.commands.refreshCodeReviewList', commandRefreshCodeReviewList),\n\t\tvscode.commands.registerCommand('github1s.commands.searchCodeReview', commandSwitchToCodeReview),\n\t\tvscode.commands.registerCommand('github1s.commands.switchToPullRequest', commandSwitchToCodeReview),\n\t\tvscode.commands.registerCommand('github1s.commands.switchToMergeRequest', commandSwitchToCodeReview),\n\t\tvscode.commands.registerCommand('github1s.commands.switchToChangeRequest', commandSwitchToCodeReview),\n\t\tvscode.commands.registerCommand('github1s.commands.switchToCodeReview', commandSwitchToCodeReview),\n\t\tvscode.commands.registerCommand('github1s.commands.openCodeReviewOnGitHub', commandOpenCodeReviewOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openCodeReviewOnGitLab', commandOpenCodeReviewOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openCodeReviewOnBitbucket', commandOpenCodeReviewOnOfficialPage),\n\t\tvscode.commands.registerCommand(\n\t\t\t'github1s.commands.openCodeReviewOnOfficialPage',\n\t\t\tcommandOpenCodeReviewOnOfficialPage,\n\t\t),\n\t\tvscode.commands.registerCommand('github1s.commands.load-more-code-reviews', commandLoadMoreCodeReviews),\n\t\tvscode.commands.registerCommand(\n\t\t\t'github1s.commands.load-more-code-review-changed-files',\n\t\t\tcommandLoadMoreCodeReviewChangedFiles,\n\t\t),\n\t);\n};\n"
  },
  {
    "path": "extensions/github1s/src/commands/commit.ts",
    "content": "/**\n * @file GitHub1s Commit Related Commands\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { CommitTreeItem, getCommitTreeItemDescription } from '@/views/commit-list';\nimport { commitTreeDataProvider, fileHistoryTreeDataProvider } from '@/views';\nimport { adapterManager } from '@/adapters';\nimport { Repository } from '@/repository';\n\nexport const checkCommitExists = async (repo: string, commitSha: string) => {\n\tconst adapter = adapterManager.getCurrentAdapter();\n\tconst dataSoruce = await adapter.resolveDataSource();\n\ttry {\n\t\treturn !!(await dataSoruce.provideCommit(repo, commitSha));\n\t} catch (error) {\n\t\tconst errorMessage =\n\t\t\t(error as any)?.response?.status === 404\n\t\t\t\t? `No commit found for commitSha: ${commitSha}`\n\t\t\t\t: error?.response?.data?.message;\n\t\tvscode.window.showErrorMessage(errorMessage || `Get commit ${commitSha}} error`);\n\t\treturn false;\n\t}\n};\n\nconst commandSwitchToCommit = async (commitItemOrSha?: string | CommitTreeItem) => {\n\tlet commitSha: string | undefined = commitItemOrSha\n\t\t? typeof commitItemOrSha === 'string'\n\t\t\t? commitItemOrSha\n\t\t\t: commitItemOrSha.commit.sha\n\t\t: '';\n\tconst adapter = adapterManager.getCurrentAdapter();\n\tconst { repo } = await router.getState();\n\tconst repository = Repository.getInstance(adapter.scheme, repo);\n\n\t// if the a commitSha isn't provided, use quickInput\n\tif (!commitSha) {\n\t\t// manual input a commit sha\n\t\tconst inputCommitShaItem: vscode.QuickPickItem = {\n\t\t\tlabel: '$(git-commit) Manual input the commit sha',\n\t\t\talwaysShow: true,\n\t\t};\n\t\t// use the commit list as the candidates\n\t\tconst commits = await repository.getCommitList();\n\t\tconst commitItems: vscode.QuickPickItem[] = commits.map((commit) => ({\n\t\t\tcommitSha: commit.sha,\n\t\t\tlabel: commit.message,\n\t\t\tdescription: getCommitTreeItemDescription(commit),\n\t\t}));\n\n\t\tconst quickPick = vscode.window.createQuickPick<vscode.QuickPickItem>();\n\t\tquickPick.matchOnDescription = true;\n\t\tquickPick.items = [inputCommitShaItem, ...commitItems];\n\t\tquickPick.show();\n\n\t\tconst choice = (await new Promise<vscode.QuickPickItem | undefined>((resolve) =>\n\t\t\tquickPick.onDidAccept(() => resolve(quickPick.activeItems[0])),\n\t\t)) as vscode.QuickPickItem & { commitSha?: string };\n\t\tquickPick.hide();\n\n\t\t// select nothing\n\t\tif (!choice) {\n\t\t\treturn;\n\t\t}\n\n\t\t// select `manual input the commit sha`\n\t\tif (choice === inputCommitShaItem) {\n\t\t\tcommitSha = await vscode.window.showInputBox({\n\t\t\t\tplaceHolder: 'Please input the commit sha',\n\t\t\t});\n\t\t} else {\n\t\t\t// select a commit sha\n\t\t\tcommitSha = choice.commitSha;\n\t\t}\n\t}\n\n\tconst routerParser = await router.resolveParser();\n\tif (await checkCommitExists(repo, commitSha!)) {\n\t\trouter.replace(await routerParser.buildCommitPath(repo, commitSha!));\n\t}\n};\n\nconst commandDiffCommitFile = async (commitItem: CommitTreeItem) => {\n\tconst commitSha = commitItem.commit.sha;\n\tif (!commitSha) {\n\t\treturn;\n\t}\n\tconst { repo } = await router.getState();\n\tconst activeDocumentUri = vscode.window.activeTextEditor?.document?.uri;\n\tconst fileUri = activeDocumentUri?.with({\n\t\tauthority: `${repo}+${commitSha}`,\n\t\tquery: '',\n\t});\n\treturn vscode.commands.executeCommand('github1s.commands.openFilePreviousRevision', fileUri);\n};\n\n// this command is used in `source control commit list view`\nconst commandOpenCommitOnOfficialPage = async (commitItemOrSha?: string | CommitTreeItem) => {\n\tconst commitSha = commitItemOrSha\n\t\t? typeof commitItemOrSha === 'string'\n\t\t\t? commitItemOrSha\n\t\t\t: commitItemOrSha.commit.sha\n\t\t: '';\n\tif (commitSha) {\n\t\tconst { repo } = await router.getState();\n\t\tconst routerParser = await router.resolveParser();\n\t\tconst commitPath = await routerParser.buildCommitPath(repo, commitSha);\n\t\tconst commitLink = await routerParser.buildExternalLink(commitPath);\n\t\treturn vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(commitLink));\n\t}\n};\n\nconst commandRefreshCommitList = (forceUpdate = true) => {\n\treturn commitTreeDataProvider.updateTree(forceUpdate);\n};\n\nconst commandLoadMoreCommits = async () => {\n\treturn commitTreeDataProvider.loadMoreCommits();\n};\n\nconst commandLoadMoreCommitChangedFiles = async (commitSha: string) => {\n\treturn commitTreeDataProvider.loadMoreChangedFiles(commitSha);\n};\n\nconst commandRefreshFileHistoryCommitList = (forceUpdate = true) => {\n\treturn fileHistoryTreeDataProvider.updateTree(forceUpdate);\n};\n\nconst commandLoadMoreFileHistoryCommits = async () => {\n\treturn fileHistoryTreeDataProvider.loadMoreCommits();\n};\n\nconst commandLoadMoreFileHistoryCommitChangedFiles = async (commitSha: string) => {\n\treturn fileHistoryTreeDataProvider.loadMoreChangedFiles(commitSha);\n};\n\nexport const registerCommitCommands = (context: vscode.ExtensionContext) => {\n\treturn context.subscriptions.push(\n\t\tvscode.commands.registerCommand('github1s.commands.refreshCommitList', commandRefreshCommitList),\n\t\tvscode.commands.registerCommand('github1s.commands.searchCommit', commandSwitchToCommit),\n\t\tvscode.commands.registerCommand('github1s.commands.switchToCommit', commandSwitchToCommit),\n\t\tvscode.commands.registerCommand('github1s.commands.diffCommitFile', commandDiffCommitFile),\n\t\tvscode.commands.registerCommand('github1s.commands.openCommitOnGitHub', commandOpenCommitOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openCommitOnGitLab', commandOpenCommitOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openCommitOnBitbucket', commandOpenCommitOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openCommitOnOfficialPage', commandOpenCommitOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.loadMoreCommits', commandLoadMoreCommits),\n\t\tvscode.commands.registerCommand('github1s.commands.loadMoreCommitChangedFiles', commandLoadMoreCommitChangedFiles),\n\t\tvscode.commands.registerCommand('github1s.commands.loadMoreFileHistoryCommits', commandLoadMoreFileHistoryCommits),\n\t\tvscode.commands.registerCommand(\n\t\t\t'github1s.commands.loadMoreFileHistoryCommitChangedFiles',\n\t\t\tcommandLoadMoreFileHistoryCommitChangedFiles,\n\t\t),\n\t\tvscode.commands.registerCommand(\n\t\t\t'github1s.commands.refreshFileHistoryCommitList',\n\t\t\tcommandRefreshFileHistoryCommitList,\n\t\t),\n\t);\n};\n"
  },
  {
    "path": "extensions/github1s/src/commands/editor.ts",
    "content": "/**\n * @file Editor Related Commands\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport * as queryString from 'query-string';\nimport router from '@/router';\nimport { emptyFileUri } from '@/providers';\nimport { basename } from '@/helpers/util';\nimport { FileChangeStatus } from '@/adapters/types';\nimport { Repository } from '@/repository';\nimport { getChangedFiles, getChangedFileDiffCommand, getChangedFileDiffTitle } from '@/changes/files';\n\nexport const getChangedFileFromSourceControl = async (fileUri: vscode.Uri) => {\n\t// the file should belong to current workspace\n\tif (fileUri.authority) {\n\t\treturn;\n\t}\n\n\treturn (await getChangedFiles()).find((changedFile) => {\n\t\treturn changedFile.headFileUri.path === fileUri.path;\n\t});\n};\n\n// open the diff editor of a file, such as click it in source-control-panel,\n// only work when we can found the corresponding file in source-control-panel\nconst commandDiffChangedFile = async (fileUri: vscode.Uri) => {\n\tconst changedFile = await getChangedFileFromSourceControl(fileUri);\n\n\tif (!changedFile) {\n\t\treturn;\n\t}\n\n\tconst command = await getChangedFileDiffCommand(changedFile);\n\tvscode.commands.executeCommand(command.command, ...(command.arguments || []));\n};\n\nconst openFileToEditor = async (fileUri) => {\n\tconst isCurrentAuthority = fileUri.authority === (await router.getAuthority());\n\n\t// In order to make the file explorer focus corresponding file when\n\t// the `fileUri.authority` equals `current authority`, set the\n\t// `fileUri.authority` to '' in this case\n\tconst targetFileUri = isCurrentAuthority ? fileUri.with({ authority: '' }) : fileUri;\n\n\tlet editorLabel: string | undefined = undefined;\n\tif (!isCurrentAuthority) {\n\t\t// the authority here should be `{repo}+{commitSha}`\n\t\tconst [_repo, commitSha] = targetFileUri.authority.split('+');\n\t\teditorLabel = `${basename(targetFileUri.path)} (${commitSha.slice(0, 7)})`;\n\t}\n\n\treturn vscode.commands.executeCommand('vscode.open', targetFileUri, { preview: false }, editorLabel);\n};\n\n// open the left file in the diff editor title\nconst commandDiffViewOpenLeftFile = async (fileUri: vscode.Uri) => {\n\tconst query = queryString.parse(fileUri?.query || '');\n\treturn query.base ? openFileToEditor(vscode.Uri.parse(query.base as string)) : null;\n};\n\n// open the right file in the diff editor title\nconst commandDiffViewOpenRightFile = async (fileUri: vscode.Uri) => {\n\tconst query = queryString.parse(fileUri?.query || '');\n\treturn query.head ? openFileToEditor(vscode.Uri.parse(query.head as string)) : null;\n};\n\n// get the file uri with the concrete commit sha, the `ref` in\n// `fileUri.authority` maybe newer but not related this file\nconst getConcreteFileUri = async (fileUri: vscode.Uri) => {\n\t// the `fileUri.authority` maybe empty, fallback to router.getAuthority() in this case\n\tconst fileAuthority = fileUri.authority || (await router.getAuthority());\n\tconst [repo, ref] = fileAuthority.split('+').filter(Boolean);\n\tconst repository = Repository.getInstance(fileUri.scheme, repo);\n\tconst commit = await repository.getFileLatestCommit(ref, fileUri.path.slice(1));\n\tconst latestCommitSha = commit?.sha || (await repository.getCommitItem(ref))?.sha || 'HEAD';\n\n\treturn fileUri.with({ authority: `${repo}+${latestCommitSha}` });\n};\n\n// show the file's diff between current commit and previous commit\nconst commandOpenFilePreviousRevision = async (fileUri: vscode.Uri) => {\n\tconst queryBaseUriStr = queryString.parse(fileUri.query).base;\n\tconst rightFileUri = await getConcreteFileUri(\n\t\t// if the `queryBaseUriStr` is empty, which means this command is called from\n\t\t// a normal file editor (not a diff editor), just use `fileUri` in this case\n\t\tqueryBaseUriStr ? vscode.Uri.parse(queryBaseUriStr as string) : fileUri,\n\t);\n\tconst [repo, rightCommitSha] = rightFileUri.authority.split('+').filter(Boolean);\n\n\tconst repository = Repository.getInstance(fileUri.scheme, repo);\n\tconst leftCommit = await repository.getPreviousCommit(rightCommitSha, fileUri.path.slice(1));\n\t// if we can't find previous commit, use the `emptyFileUri` as the leftFileUri\n\tconst leftFileUri = leftCommit ? rightFileUri.with({ authority: `${repo}+${leftCommit.sha}` }) : emptyFileUri;\n\n\tconst changedStatus = leftCommit ? FileChangeStatus.Modified : FileChangeStatus.Added;\n\tconst hasNextRevision = !!(await repository.getNextCommit(rightCommitSha, rightFileUri.path.slice(1)));\n\n\tconst query = queryString.stringify({\n\t\tbase: leftFileUri.with({ query: '' }).toString(),\n\t\thead: rightFileUri.with({ query: '' }).toString(),\n\t\tstatus: changedStatus,\n\t\t// if we can't find a newer commit for this file,\n\t\t// the `Show Next Commit` Button would be disabled.\n\t\thasNextRevision,\n\t});\n\n\treturn vscode.commands.executeCommand(\n\t\t'vscode.diff',\n\t\tleftFileUri.with({ query }),\n\t\trightFileUri.with({ query }),\n\t\tgetChangedFileDiffTitle(leftFileUri, rightFileUri, changedStatus),\n\t);\n};\n\n// show the file's diff between current commit and next commit\nconst commandOpenFileNextRevision = async (fileUri: vscode.Uri) => {\n\tconst leftFileUri = await getConcreteFileUri(fileUri);\n\n\tconst [repo, leftCommitSha] = leftFileUri.authority.split('+').filter(Boolean);\n\tconst repository = Repository.getInstance(fileUri.scheme, repo);\n\tconst rightCommit = await repository.getNextCommit(leftCommitSha, fileUri.path.slice(1));\n\n\tif (!rightCommit) {\n\t\treturn vscode.window.showInformationMessage('There is no next commit found.');\n\t}\n\n\tconst rightFileUri = leftFileUri.with({ authority: `${repo}+${rightCommit.sha}` });\n\tconst hasNextRevision = !!(await repository.getNextCommit(rightCommit.sha, rightFileUri.path.slice(1)));\n\n\tconst query = queryString.stringify({\n\t\tbase: leftFileUri.with({ query: '' }).toString(),\n\t\thead: rightFileUri.with({ query: '' }).toString(),\n\t\tstatus: FileChangeStatus.Modified,\n\t\thasNextRevision,\n\t});\n\n\treturn vscode.commands.executeCommand(\n\t\t'vscode.diff',\n\t\tleftFileUri.with({ query }),\n\t\trightFileUri.with({ query }),\n\t\tgetChangedFileDiffTitle(leftFileUri, rightFileUri, FileChangeStatus.Modified),\n\t);\n};\n\nexport const registerEditorCommands = (context: vscode.ExtensionContext) => {\n\treturn context.subscriptions.push(\n\t\tvscode.commands.registerCommand('github1s.commands.diffChangedFile', commandDiffChangedFile),\n\t\tvscode.commands.registerCommand('github1s.commands.diffViewOpenLeftFile', commandDiffViewOpenLeftFile),\n\t\tvscode.commands.registerCommand('github1s.commands.diffViewOpenRightFile', commandDiffViewOpenRightFile),\n\t\tvscode.commands.registerCommand('github1s.commands.openFilePreviousRevision', commandOpenFilePreviousRevision),\n\t\tvscode.commands.registerCommand('github1s.commands.openFileNextRevision', commandOpenFileNextRevision),\n\t);\n};\n"
  },
  {
    "path": "extensions/github1s/src/commands/global.ts",
    "content": "/**\n * @file GitHub1s Ref Related Commands\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { relativeTimeTo } from '@/helpers/date';\nimport { getRecentRepositories, removeRecentRepository } from '@/helpers/context';\nimport { adapterManager } from '@/adapters';\n\nexport const commandOpenOnOfficialPage = async () => {\n\tconst location = (await router.getHistory()).location;\n\tconst routerParser = await router.resolveParser();\n\tconst fullPath = `${location.pathname}${location.search}${location.hash}`;\n\tconst externalLink = await routerParser.buildExternalLink(fullPath);\n\n\treturn vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(externalLink));\n};\n\nconst repoPickItemButtons = [{ iconPath: new vscode.ThemeIcon('close') }];\n\nconst getRecentRepoPickItems = () =>\n\tgetRecentRepositories().map((record) => ({\n\t\tlabel: record.name,\n\t\tdescription: relativeTimeTo(record.timestamp),\n\t\tbuttons: repoPickItemButtons,\n\t}));\n\nexport const commandOpenRepository = async () => {\n\tconst quickPick = vscode.window.createQuickPick();\n\tconst manualInputItem = { label: '' };\n\tlet recentRepoPickItems = getRecentRepoPickItems();\n\n\tconst updatePickerItems = () => {\n\t\tif (manualInputItem.label) {\n\t\t\treturn (quickPick.items = [...recentRepoPickItems, manualInputItem]);\n\t\t}\n\t\treturn (quickPick.items = recentRepoPickItems);\n\t};\n\n\tquickPick.placeholder = 'Select to open...';\n\tupdatePickerItems();\n\n\tquickPick.show();\n\tquickPick.onDidTriggerItemButton(async (event) => {\n\t\tif (event.button === repoPickItemButtons[0]) {\n\t\t\tawait removeRecentRepository(event.item.label);\n\t\t\trecentRepoPickItems = getRecentRepoPickItems();\n\t\t\tupdatePickerItems();\n\t\t}\n\t});\n\n\tquickPick.onDidChangeValue((value) => {\n\t\tmanualInputItem.label = value ? `Open ${value}...` : '';\n\t\tupdatePickerItems();\n\t});\n\n\tquickPick.onDidAccept(async () => {\n\t\tconst choice = quickPick.activeItems[0];\n\t\tconst repository = choice === manualInputItem ? quickPick.value : choice.label;\n\t\tconst targetLink = vscode.Uri.parse((await router.href()) || '').with({\n\t\t\tpath: await (await router.resolveParser()).buildTreePath(repository),\n\t\t});\n\t\tvscode.commands.executeCommand('vscode.open', targetLink);\n\t\tquickPick.hide();\n\t});\n};\n\nconst commandOpenOnlineEditor = async () => {\n\tconst currentScheme = adapterManager.getCurrentScheme();\n\tconst onlineEditorPath = ['github1s', 'ossinsight'].includes(currentScheme) ? '/editor' : '/';\n\tconst targetLink = vscode.Uri.parse((await router.href()) || '').with({ path: onlineEditorPath });\n\treturn vscode.commands.executeCommand('vscode.open', targetLink);\n};\n\nconst commandRefreshRepository = async () => {\n\tif (['github1s', 'gitlab1s'].includes(adapterManager.getCurrentScheme())) {\n\t\tawait vscode.commands.executeCommand('github1s.commands.syncSourcegraphRepository');\n\t}\n\tvscode.commands.executeCommand('workbench.action.reloadWindow');\n};\n\nexport const registerGlobalCommands = (context: vscode.ExtensionContext) => {\n\treturn context.subscriptions.push(\n\t\tvscode.commands.registerCommand('github1s.commands.openOnGitHub', commandOpenOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openOnGitLab', commandOpenOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openOnBitbucket', commandOpenOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openOnNpm', commandOpenOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openOnOfficialPage', commandOpenOnOfficialPage),\n\t\tvscode.commands.registerCommand('github1s.commands.openRepository', commandOpenRepository),\n\t\tvscode.commands.registerCommand('github1s.commands.openOnlineEditor', commandOpenOnlineEditor),\n\t\tvscode.commands.registerCommand('github1s.commands.refreshRepository', commandRefreshRepository),\n\t\tvscode.commands.registerCommand('remoteHub.openRepository', commandOpenRepository),\n\t);\n};\n"
  },
  {
    "path": "extensions/github1s/src/commands/index.ts",
    "content": "/**\n * @file github1s commands\n * @author netcon\n */\n\nimport { getExtensionContext } from '@/helpers/context';\nimport { registerRefCommands } from './ref';\nimport { registerCodeReviewCommands } from './code-review';\nimport { registerCommitCommands } from './commit';\nimport { registerEditorCommands } from './editor';\nimport { registerBlameCommands } from './blame';\nimport { registerGlobalCommands } from './global';\n\nexport const registerGitHub1sCommands = () => {\n\tconst context = getExtensionContext();\n\n\tregisterRefCommands(context);\n\tregisterEditorCommands(context);\n\tregisterCodeReviewCommands(context);\n\tregisterCommitCommands(context);\n\tregisterBlameCommands(context);\n\tregisterGlobalCommands(context);\n};\n"
  },
  {
    "path": "extensions/github1s/src/commands/ref.ts",
    "content": "/**\n * @file GitHub1s Ref Related Commands\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { adapterManager } from '@/adapters';\nimport { Repository } from '@/repository';\n\nconst loadMorePickerItem: vscode.QuickPickItem = {\n\tlabel: '$(more) Load More',\n\talwaysShow: true,\n};\n\nconst checkoutToItem: vscode.QuickPickItem = {\n\tlabel: '$(debug-disconnect) Checkout detached',\n\talwaysShow: true,\n};\n\n// check out to branch/tag/commit\nconst commandCheckoutTo = async () => {\n\tconst routerParser = await router.resolveParser();\n\tconst routeState = await router.getState();\n\tconst quickPick = vscode.window.createQuickPick();\n\n\tconst loadMoreRefPickerItems = async () => {\n\t\tquickPick.busy = true;\n\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\tconst repository = Repository.getInstance(scheme, routeState.repo);\n\t\tawait Promise.all([repository.loadMoreBranches(), repository.loadMoreTags()]);\n\t\tconst [branchRefs, tagRefs] = await Promise.all([repository.getBranchList(), repository.getTagList()]);\n\t\tconst refPickerItems = [...branchRefs, ...tagRefs].map((ref) => ({\n\t\t\tlabel: ref.name,\n\t\t\tdescription: ref.description,\n\t\t}));\n\t\tconst hasMore = (await Promise.all([repository.hasMoreBranches(), repository.hasMoreTags()])).some(Boolean);\n\t\tquickPick.items = [...refPickerItems, hasMore ? loadMorePickerItem : null!, checkoutToItem].filter(Boolean);\n\t\tquickPick.busy = false;\n\t};\n\n\tquickPick.placeholder = 'Input a ref to checkout';\n\tquickPick.items = [checkoutToItem];\n\tloadMoreRefPickerItems();\n\tquickPick.show();\n\n\tquickPick.onDidAccept(async () => {\n\t\tconst choice = quickPick.activeItems[0];\n\t\tif (choice === loadMorePickerItem) {\n\t\t\treturn loadMoreRefPickerItems();\n\t\t}\n\t\tconst selectedRef = choice === checkoutToItem ? quickPick.value : choice?.label;\n\t\tconst targetRef = selectedRef.toUpperCase() !== 'HEAD' ? selectedRef : undefined;\n\t\trouter.push(await routerParser.buildTreePath(routeState.repo, targetRef));\n\t\tquickPick.hide();\n\t});\n};\n\nexport const registerRefCommands = (context: vscode.ExtensionContext) => {\n\treturn context.subscriptions.push(vscode.commands.registerCommand('github1s.commands.checkoutTo', commandCheckoutTo));\n};\n"
  },
  {
    "path": "extensions/github1s/src/extension.ts",
    "content": "/**\n * @file extension entry\n * @author netcon\n */\n\nimport router from '@/router';\nimport * as vscode from 'vscode';\nimport { PageType } from './adapters/types';\nimport { registerCustomViews } from '@/views';\nimport { decorateStatusBar } from '@/statusbar';\nimport { registerEventListeners } from '@/listeners';\nimport { registerVSCodeProviders } from '@/providers';\nimport { registerGitHub1sCommands } from '@/commands';\nimport { updateSourceControlChanges } from '@/changes';\nimport { adapterManager, registerAdapters } from '@/adapters';\nimport { addRecentRepositories, setExtensionContext } from '@/helpers/context';\n\nconst browserUrlManager = {\n\thref: () => vscode.commands.executeCommand('github1s.commands.vscode.getBrowserUrl') as Promise<string>,\n\tpush: (url: string) =>\n\t\tvscode.commands.executeCommand('github1s.commands.vscode.pushBrowserUrl', url) as Promise<void>,\n\treplace: (url: string) =>\n\t\tvscode.commands.executeCommand('github1s.commands.vscode.replaceBrowserUrl', url) as Promise<void>,\n};\n\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport async function activate(context: vscode.ExtensionContext) {\n\t// set the global context for convenient\n\tsetExtensionContext(context);\n\n\t// register platform adapters\n\tawait registerAdapters();\n\n\t// Ensure the router has been initialized\n\tawait router.initialize(browserUrlManager);\n\n\t// do follow-up works in parallel\n\tawait Promise.all([\n\t\tregisterVSCodeProviders(),\n\t\tregisterEventListeners(),\n\t\tregisterGitHub1sCommands(),\n\t\tregisterCustomViews(),\n\t\tupdateSourceControlChanges(),\n\t\tdecorateStatusBar(),\n\t]);\n\n\tinitialVSCodeState();\n}\n\n// initialize the VSCode's state according to the router url\nconst initialVSCodeState = async () => {\n\tconst routerState = await router.getState();\n\tconst scheme = adapterManager.getCurrentScheme();\n\n\tif (routerState.pageType === PageType.Tree && routerState.filePath) {\n\t\tvscode.commands.executeCommand(\n\t\t\t'revealInExplorer',\n\t\t\tvscode.Uri.parse('').with({ scheme, path: `/${routerState.filePath}` }),\n\t\t);\n\t} else if (routerState.pageType === PageType.Blob && routerState.filePath) {\n\t\tconst { startLine, endLine } = routerState;\n\t\tlet documentShowOptions: vscode.TextDocumentShowOptions = {};\n\t\tif (startLine || endLine) {\n\t\t\tconst startPosition = new vscode.Position((startLine || endLine)! - 1, 0);\n\t\t\tconst endPosition = new vscode.Position((endLine || startLine)! - 1, 1 << 20);\n\t\t\tdocumentShowOptions = { selection: new vscode.Range(startPosition, endPosition) };\n\t\t}\n\t\tvscode.window.showTextDocument(\n\t\t\tvscode.Uri.parse('').with({ scheme, path: `/${routerState.filePath}` }),\n\t\t\tdocumentShowOptions,\n\t\t);\n\t} else if (routerState.pageType === PageType.CodeReviewList) {\n\t\tvscode.commands.executeCommand('github1s.views.codeReviewList.focus');\n\t} else if (routerState.pageType === PageType.CommitList) {\n\t\tvscode.commands.executeCommand('github1s.views.commitList.focus');\n\t} else if ([PageType.CodeReview, PageType.Commit].includes(routerState.pageType)) {\n\t\tvscode.commands.executeCommand('workbench.scm.focus');\n\t} else if (routerState.pageType === PageType.Search) {\n\t\tvscode.commands.executeCommand('workbench.action.findInFiles', routerState);\n\t}\n\trouterState.repo && addRecentRepositories(routerState.repo);\n};\n"
  },
  {
    "path": "extensions/github1s/src/global.d.ts",
    "content": "declare const GITHUB_ORIGIN: string;\ndeclare const GITHUB_API_PREFIX: string;\ndeclare const GITLAB_ORIGIN: string;\ndeclare const GITLAB_API_PREFIX: string;\n"
  },
  {
    "path": "extensions/github1s/src/helpers/async.ts",
    "content": "/**\n * @file async related helpers\n */\n\n// below code is comes from:\n// https://github.com/microsoft/vscode/blob/a3415e669a8f3879c290af5616a8ed45dd0534af/src/vs/base/common/async.ts#L344\nexport class Barrier {\n\tprivate _isOpen: boolean;\n\tprivate _promise: Promise<boolean>;\n\tprivate _completePromise!: (v: boolean) => void;\n\n\tconstructor(timeout = 0) {\n\t\tthis._isOpen = false;\n\t\tthis._promise = new Promise<boolean>((c, e) => {\n\t\t\tthis._completePromise = c;\n\t\t});\n\t\ttimeout && setTimeout(() => this.open(), timeout);\n\t}\n\n\tisOpen(): boolean {\n\t\treturn this._isOpen;\n\t}\n\n\topen(): void {\n\t\tthis._isOpen = true;\n\t\tthis._completePromise(true);\n\t}\n\n\twait(): Promise<boolean> {\n\t\treturn this._promise;\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/helpers/context.ts",
    "content": "/**\n * @file extension context\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\n\nlet extensionContext: vscode.ExtensionContext | null = null;\n\nexport const setExtensionContext = (_extensionContext: vscode.ExtensionContext) => {\n\textensionContext = _extensionContext;\n};\n\nexport const getExtensionContext = (): vscode.ExtensionContext => {\n\tif (!extensionContext) {\n\t\tthrow new Error('extension context initialize failed!');\n\t}\n\n\treturn extensionContext;\n};\n\nconst RECENT_REPOSITORIES = 'github1s-recent-repositories';\nexport const getRecentRepositories = (): { name: string; timestamp: number }[] => {\n\treturn getExtensionContext().globalState.get(RECENT_REPOSITORIES) || [];\n};\n\nexport const addRecentRepositories = (name: string, timestamp = 0) => {\n\tconst currentRecord = { name, timestamp: timestamp || Date.now() };\n\tconst restRecords = getRecentRepositories().filter((record) => record.name !== name);\n\tconst newRecords = [currentRecord, ...restRecords.slice(0, 49)]; // max to 50 records\n\treturn getExtensionContext().globalState.update(RECENT_REPOSITORIES, newRecords);\n};\n\nexport const removeRecentRepository = (name: string) => {\n\tconst newRecords = getRecentRepositories().filter((record) => record.name !== name);\n\treturn getExtensionContext().globalState.update(RECENT_REPOSITORIES, newRecords);\n};\n\nexport const getBrowserUrl = () => {\n\treturn vscode.commands.executeCommand('github1s.commands.vscode.getBrowserUrl');\n};\n"
  },
  {
    "path": "extensions/github1s/src/helpers/date.ts",
    "content": "/**\n * @file date util\n * @author netcon\n */\n\nimport * as dayjs from 'dayjs';\nimport * as relativeTimePlugin from 'dayjs/plugin/relativeTime';\n\ndayjs.extend(relativeTimePlugin);\n\nexport const relativeTimeTo = (date: dayjs.ConfigType) => dayjs().to(dayjs(date));\n\nexport const toISOString = (date: dayjs.ConfigType) => dayjs(date).toISOString();\n"
  },
  {
    "path": "extensions/github1s/src/helpers/func.ts",
    "content": "/**\n * @file function utils\n * @author netcon\n */\n\nimport * as jsonStableStringify from 'json-stable-stringify';\nimport pFinally from 'p-finally';\n\nconst defaultComputeCacheKey = (...args) => jsonStableStringify([...args]);\n\n// reuse previous promise when a request call\n// and previous request not completed\nexport const reuseable = <T extends (...args: any[]) => Promise<any>>(\n\tfunc: T,\n\tcomputeCacheKey: (...args: Parameters<T>) => string = defaultComputeCacheKey,\n) => {\n\tconst cache = new Map<string, ReturnType<T>>();\n\n\treturn function (...args: Parameters<T>): ReturnType<T> {\n\t\tconst key = computeCacheKey(...args);\n\t\tif (cache.has(key)) {\n\t\t\treturn cache.get(key)!;\n\t\t}\n\n\t\tconst promise = func.call(this, ...args);\n\t\tcache.set(key, promise);\n\t\treturn pFinally(promise, () => cache.delete(key));\n\t};\n};\n\nexport const throttle = <T extends (...args: any[]) => any>(func: T, interval: number) => {\n\tlet timer: ReturnType<typeof setTimeout> | null = null;\n\treturn function (...args: Parameters<T>): ReturnType<T> | undefined {\n\t\tif (timer) {\n\t\t\treturn;\n\t\t}\n\t\tfunc.call(this, ...args);\n\t\ttimer = setTimeout(() => (timer = null), interval);\n\t};\n};\n\nexport const debounce = <T extends (...args: any[]) => any>(func: T, wait: number) => {\n\tlet timer: ReturnType<typeof setTimeout> | null = null;\n\treturn function (...args: Parameters<T>): void {\n\t\ttimer && clearTimeout(timer);\n\t\ttimer = setTimeout(() => func.call(this, ...args), wait);\n\t};\n};\n\n// debounce an async func. once an async func canceled, it throws a exception\nexport const debounceAsyncFunc = <T extends (...args: any[]) => Promise<any>>(func: T, wait: number) => {\n\tlet timer: ReturnType<typeof setTimeout> | null = null;\n\tlet previousReject: (() => any) | null = null;\n\treturn function (...args: Parameters<T>): ReturnType<T> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttimer && clearTimeout(timer);\n\t\t\tpreviousReject && previousReject();\n\t\t\ttimer = setTimeout(() => resolve(func.call(this, ...args)), wait);\n\t\t\tpreviousReject = reject;\n\t\t}) as ReturnType<T>;\n\t};\n};\n\n// memorize function result, beware of memory leaks!\nexport const memorize = <T extends (...args: any[]) => any>(\n\tfunc: T,\n\tcomputeCacheKey: (...args: Parameters<T>) => string = defaultComputeCacheKey,\n) => {\n\tconst cache = new Map<string, ReturnType<T>>();\n\n\treturn function (...args: Parameters<T>): ReturnType<T> {\n\t\tconst key = computeCacheKey(...args);\n\t\tif (cache.has(key)) {\n\t\t\treturn cache.get(key)!;\n\t\t}\n\n\t\tconst result = func.call(this, ...args);\n\t\tcache.set(key, result);\n\t\treturn result;\n\t};\n};\n\nexport const decorate = <F extends (...args: unknown[]) => unknown>(transformer: (func: F) => F) => {\n\treturn <T>(_target: T, _propertyKey: string, descriptor: PropertyDescriptor) => {\n\t\tconst originalMethod = descriptor.value;\n\t\tdescriptor.value = transformer(originalMethod as F);\n\t};\n};\n"
  },
  {
    "path": "extensions/github1s/src/helpers/page.ts",
    "content": "/**\n * @file page html helpers\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\n\nexport const getNonce = (): string => {\n\tlet text: string = '';\n\tconst possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\tfor (let i = 0; i < 32; i++) {\n\t\ttext += possible.charAt(Math.floor(Math.random() * possible.length));\n\t}\n\treturn text;\n};\n\nexport const getWebviewOptions = (extensionUri: vscode.Uri): vscode.WebviewOptions => {\n\treturn {\n\t\t// Enable javascript in the webview\n\t\tenableScripts: true,\n\t\t// And restrict the webview to only loading content from our extension's `assets` directory.\n\t\tlocalResourceRoots: [vscode.Uri.joinPath(extensionUri, 'assets')],\n\t};\n};\n\nexport const createPageHtml = (title: string, styles: string[] = [], scripts: string[] = []) => {\n\tconst nonce = getNonce();\n\treturn `\n\t\t<!DOCTYPE html>\n\t\t<html lang=\"en\">\n\t\t<head>\n\t\t\t<meta charset=\"UTF-8\">\n\t\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t\t<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; style-src 'nonce-${nonce}'; script-src 'nonce-${nonce}'; img-src *;\">\n\t\t\t<title>${title}</title>\n\t\t\t${styles.map((style) => `<link rel=\"stylesheet\" nonce=\"${nonce}\" href=\"${style}\" />`).join('')}\n\t\t\t<style nonce=\"${nonce}\">\n\t\t\tbody{margin:0;padding:0;background-color:transparent}\n\t\t\t#page-loading{width:100%;text-align:center;height:40px;margin-top:60px}\n\t\t\t#page-loading>span{height:100%;width:8px;display:inline-block;margin-right:6px;background:var(--vscode-button-background);animation:pageLoading 1.2s infinite ease-in-out}\n\t\t\t#page-loading>span:nth-child(2){animation-delay:-1s}#page-loading>span:nth-child(3){animation-delay:-.9s}#page-loading>span:nth-child(4){animation-delay:-.8s}#page-loading>span:nth-child(5){margin-right:0!important;animation-delay:-.7s}\n\t\t\t@keyframes pageLoading{0%{transform:scaleY(.4)}25%{transform:scaleY(1)}50%{transform:scaleY(.4)}75%{transform:scaleY(.4)}100%{transform:scaleY(.4)}}\n\t\t\t</style>\n\t\t</head>\n\t\t<body>\n\t\t\t<div id=\"page-loading\">\n\t\t\t\t<span></span><span></span><span></span><span></span><span></span>\n\t\t\t</div>\n\t\t  <div id=\"app\"></div>\n\t\t  ${scripts.map((script) => `<script type=\"module\" nonce=\"${nonce}\" src=\"${script}\"></script>`).join('')}\n\t\t</body>\n\t\t</html>\n\t `;\n};\n"
  },
  {
    "path": "extensions/github1s/src/helpers/submodule.ts",
    "content": "/**\n * @file git submodule util\n * @author netcon\n */\n\nimport { FileSystemError, Uri } from 'vscode';\n\n// the code below is come from https://github.com/microsoft/vscode/blob/1.52.1/extensions/git/src/git.ts#L661\nexport interface Submodule {\n\tname: string;\n\tpath: string;\n\turl: string;\n}\n\n// the code below is come from https://github.com/microsoft/vscode/blob/1.52.1/extensions/git/src/git.ts#L667\nexport const parseGitmodules = (raw: string): Submodule[] => {\n\tconst regex = /\\r?\\n/g;\n\tlet position = 0;\n\tlet match: RegExpExecArray | null = null;\n\n\tconst result: Submodule[] = [];\n\tlet submodule: Partial<Submodule> = {};\n\n\tconst parseLine = (line: string): void => {\n\t\tconst sectionMatch = /^\\s*\\[submodule \"([^\"]+)\"\\]\\s*$/.exec(line);\n\n\t\tif (sectionMatch) {\n\t\t\tif (submodule.name && submodule.path && submodule.url) {\n\t\t\t\tresult.push(submodule as Submodule);\n\t\t\t}\n\n\t\t\tconst name = sectionMatch[1];\n\n\t\t\tif (name) {\n\t\t\t\tsubmodule = { name };\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (!submodule) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst propertyMatch = /^\\s*(\\w+)\\s*=\\s*(.*)$/.exec(line);\n\n\t\tif (!propertyMatch) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst [, key, value] = propertyMatch;\n\n\t\tswitch (key) {\n\t\t\tcase 'path':\n\t\t\t\tsubmodule.path = value;\n\t\t\t\tbreak;\n\t\t\tcase 'url':\n\t\t\t\tsubmodule.url = value;\n\t\t\t\tbreak;\n\t\t}\n\t};\n\n\twhile ((match = regex.exec(raw))) {\n\t\tparseLine(raw.substring(position, match.index));\n\t\tposition = match.index + match[0].length;\n\t}\n\n\tparseLine(raw.substring(position));\n\n\tif (submodule.name && submodule.path && submodule.url) {\n\t\tresult.push(submodule as Submodule);\n\t}\n\n\treturn result;\n};\n\nexport const parseSubmoduleUrl = (url: string) => {\n\ttry {\n\t\tlet host = '';\n\t\tlet path = '';\n\t\t// the url is looks like git@github.com:xcv58/rc_config_files.git\n\t\tif (url.startsWith('git@')) {\n\t\t\tconst colonIndex = url.indexOf(':');\n\t\t\thost = url.slice(0, colonIndex);\n\t\t\tpath = url.slice(colonIndex + 1);\n\t\t} else {\n\t\t\tconst submoduleUri = Uri.parse(url);\n\t\t\thost = submoduleUri.authority;\n\t\t\tpath = submoduleUri.path;\n\t\t}\n\t\tlet submoduleScheme = 'github1s';\n\t\tif (/\\bgithub\\.com/i.test(host)) {\n\t\t\tsubmoduleScheme = 'github1s';\n\t\t} else if (/\\bgitlab\\.com/i.test(host)) {\n\t\t\tsubmoduleScheme = 'gitlab1s';\n\t\t} else if (/\\bbitbucket\\.org/i.test(host)) {\n\t\t\tsubmoduleScheme = 'bitbucket1s';\n\t\t} else {\n\t\t\tthrow FileSystemError.Unavailable('only github submodules are supported now');\n\t\t}\n\t\tconst [submoduleOwner, submoduleRepoPart] = path.split('/').filter(Boolean);\n\t\t// if there are a repo which the name endsWith '.git' (likes conwnet/demo.git), this ambiguity may cause a problem\n\t\tconst submoduleRepo = submoduleRepoPart.endsWith('.git') ? submoduleRepoPart.slice(0, -4) : submoduleRepoPart;\n\t\treturn [submoduleScheme, `${submoduleOwner}/${submoduleRepo}`];\n\t} catch (e) {\n\t\tthrow FileSystemError.Unavailable('Can not found valid submodule declare');\n\t}\n};\n"
  },
  {
    "path": "extensions/github1s/src/helpers/urls.ts",
    "content": "/**\n * @file extension url helpers\n * @author netcon\n */\n\nexport const getSourcegraphUrl = (repo: string, ref: string, path: string, line: number, character: number): string => {\n\tconst repoUrl = `https://sourcegraph.com/github.com/${repo}@${ref}`;\n\treturn `${repoUrl}/-/blob${path}#L${line + 1}:${character + 1}`;\n};\n"
  },
  {
    "path": "extensions/github1s/src/helpers/util.ts",
    "content": "/**\n * @file common util\n * @author netcon\n */\n\nexport const noop = () => {};\nexport const isNil = (value: any) => value === undefined || value === null;\n\nexport const trimStart = (str: string, chars: string = ' '): string => {\n\tlet index = 0;\n\twhile (chars.indexOf(str[index]) !== -1) {\n\t\tindex++;\n\t}\n\treturn str.slice(index);\n};\n\nexport const trimEnd = (str: string, chars: string = ' '): string => {\n\tlet length = str.length;\n\twhile (length && chars.indexOf(str[length - 1]) !== -1) {\n\t\tlength--;\n\t}\n\treturn str.slice(0, length);\n};\n\nexport const joinPath = (...segments: string[]): string => {\n\tconst validSegments = segments.filter(Boolean);\n\tif (!validSegments.length) {\n\t\treturn '';\n\t}\n\treturn validSegments.reduce((prev, segment) => {\n\t\treturn trimEnd(prev, '/') + '/' + trimStart(segment, '/');\n\t});\n};\n\nexport const dirname = (path: string): string => {\n\tconst trimmedPath = trimEnd(path, '/');\n\treturn trimmedPath.substr(0, trimmedPath.lastIndexOf('/')) || '';\n};\n\nexport const basename = (path: string): string => {\n\tconst trimmedPath = trimEnd(path, '/');\n\treturn trimmedPath.substr(trimmedPath.lastIndexOf('/') + 1) || '';\n};\n\nexport const uniqueId = (\n\t(id) => () =>\n\t\tid++\n)(1);\n\nexport const prop = (obj: object, path: (string | number)[] = []): any => {\n\tlet cur = obj;\n\tpath.forEach((key) => (cur = cur ? cur[key] : undefined));\n\treturn cur;\n};\n\nexport const last = <T>(array: readonly T[]): T => {\n\treturn array[array.length - 1];\n};\n\nexport const encodeFilePath = (filePath: string): string => {\n\treturn filePath\n\t\t.split('/')\n\t\t.map((segment) => encodeURIComponent(segment))\n\t\t.join('/');\n};\n"
  },
  {
    "path": "extensions/github1s/src/helpers/vscode.ts",
    "content": "/**\n * @file helper functions about vscode\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\n\nexport const setVSCodeContext = (key, value) => vscode.commands.executeCommand('setContext', key, value);\n"
  },
  {
    "path": "extensions/github1s/src/listeners/index.ts",
    "content": "/**\n * @file register event listeners\n * @author netcon\n */\n\nimport { registerVSCodeEventListeners } from './vscode';\nimport { registerRouterEventListeners } from './router';\n\nexport const registerEventListeners = () => {\n\tregisterVSCodeEventListeners();\n\tregisterRouterEventListeners();\n};\n"
  },
  {
    "path": "extensions/github1s/src/listeners/router/changes.ts",
    "content": "/**\n * @file url listener for file SourceControl\n * @author netcon\n */\n\nimport { RouterState } from '@/adapters/types';\nimport { updateCheckoutTo } from '@/statusbar/checkout';\nimport { updateSourceControlChanges } from '@/changes';\nimport { commitTreeDataProvider } from '@/views';\n\ntype NewType = RouterState;\n\nexport const sourceControlRouterListener = (currentState: NewType, previousState: RouterState) => {\n\tif (currentState.ref !== previousState.ref) {\n\t\tupdateCheckoutTo();\n\t\tcommitTreeDataProvider.updateTree();\n\t}\n\n\tif ((currentState as any).codeReviewId !== (previousState as any).codeReviewId) {\n\t\tupdateSourceControlChanges();\n\t}\n\n\tif ((currentState as any).commitSha !== (previousState as any).commitSha) {\n\t\tupdateSourceControlChanges();\n\t}\n};\n"
  },
  {
    "path": "extensions/github1s/src/listeners/router/explorer.ts",
    "content": "/**\n * @file url listener for file Explorer\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { PageType, RouterState } from '@/adapters/types';\nimport { GitHub1sFileSearchProvider } from '@/providers/file-search';\nimport { GitHub1sSubmoduleDecorationProvider } from '@/providers/decorations/submodule';\nimport { GitHub1sChangedFileDecorationProvider } from '@/providers/decorations/changed-file';\nimport { GitHub1sSourceControlDecorationProvider } from '@/providers/decorations/source-control';\n\nconst sortedEqual = (source: any[], target: any[]) => {\n\tconst sortedSource = source.sort();\n\tconst sortedTarget = target.sort();\n\treturn sortedSource.every((item, index) => item === sortedTarget[index]);\n};\n\nconst shouldRefreshExplorerState = (currentState: RouterState, previousState: RouterState) => {\n\tif (['repo', 'ref'].find((key) => currentState[key] !== previousState[key])) {\n\t\treturn true;\n\t}\n\n\tif (\n\t\tcurrentState.pageType !== previousState.pageType &&\n\t\t// when the pageType transform to each other between Tree and Blob,\n\t\t// don't refresh the explorer state\n\t\t!sortedEqual([currentState.pageType, previousState.pageType], [PageType.Tree, PageType.Blob])\n\t) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nexport const explorerRouterListener = (currentState: RouterState, previousState: RouterState) => {\n\tif (shouldRefreshExplorerState(currentState, previousState)) {\n\t\tvscode.commands.executeCommand('workbench.files.action.refreshFilesExplorer');\n\t\t// TODO: maybe we should update the editors but not close it\n\t\tvscode.commands.executeCommand('workbench.action.closeAllGroups');\n\n\t\tGitHub1sChangedFileDecorationProvider.getInstance().updateDecorations();\n\t\tGitHub1sSubmoduleDecorationProvider.getInstance().updateDecorations();\n\t\tGitHub1sSourceControlDecorationProvider.getInstance().updateDecorations();\n\t\tGitHub1sFileSearchProvider.getInstance().loadFilesForCurrentAuthority();\n\t}\n};\n"
  },
  {
    "path": "extensions/github1s/src/listeners/router/index.ts",
    "content": "/**\n * @file listeners for router event\n * @author netcon\n */\n\nimport router from '@/router';\nimport { explorerRouterListener } from './explorer';\nimport { sourceControlRouterListener } from './changes';\n\nexport const registerRouterEventListeners = () => {\n\trouter.addListener(explorerRouterListener);\n\trouter.addListener(sourceControlRouterListener);\n};\n"
  },
  {
    "path": "extensions/github1s/src/listeners/vscode.ts",
    "content": "/**\n * @file listeners for vscode event\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { setVSCodeContext } from '@/helpers/vscode';\nimport { getChangedFileFromSourceControl } from '@/commands/editor';\nimport { debounce } from '@/helpers/func';\nimport { PageType } from '@/adapters/types';\nimport { adapterManager } from '@/adapters';\n\nconst handleRouterOnActiveEditorChange = async (editor: vscode.TextEditor | undefined) => {\n\t// replace current url when user change active editor\n\tconst { repo, ref, pageType } = await router.getState();\n\tconst activeFileUri = editor?.document.uri;\n\tconst routerParser = await router.resolveParser();\n\n\t// only `tree/blob` page will replace url with the active editor change\n\tif (![PageType.Tree, PageType.Blob].includes(pageType)) {\n\t\treturn;\n\t}\n\n\t// if the file which not belong to current workspace is opened, or no file\n\t// is opened, only retain `repo` (and `ref` if need) in browser url\n\tif (!activeFileUri || activeFileUri?.authority || activeFileUri?.scheme !== adapterManager.getCurrentScheme()) {\n\t\tconst browserPath = await (ref.toUpperCase() === 'HEAD'\n\t\t\t? routerParser.buildTreePath(repo)\n\t\t\t: routerParser.buildTreePath(repo, ref));\n\t\trouter.replace(browserPath);\n\t\treturn;\n\t}\n\n\tconst browserPath = await routerParser.buildBlobPath(repo, ref, activeFileUri.path.slice(1));\n\trouter.replace(browserPath);\n};\n\n// if the `Open Changes` Button should show in editor title\nconst handleOpenChangesContextOnActiveEditorChange = async (editor: vscode.TextEditor | undefined) => {\n\tconst changedFile = editor?.document.uri ? await getChangedFileFromSourceControl(editor.document.uri) : undefined;\n\n\treturn setVSCodeContext('github1s:editors:showDiffChangedFile', !!changedFile);\n};\n\n// set the `gutterBlameOpen` to false when the active editor changed\nconst handlegutterBlameOpenContextOnActiveEditorChange = async () => {\n\treturn setVSCodeContext('github1s:features:gutterBlame:open', false);\n};\n\n// add the line number anchor when user selection lines in a editor\nconst handleRouterOnTextEditorSelectionChange = async (editor: vscode.TextEditor) => {\n\tconst { repo, ref, pageType } = await router.getState();\n\tconst routerParser = await router.resolveParser();\n\n\t// only add the line number anchor when pageType is PageType.Blob\n\tif (pageType !== PageType.Blob || !editor?.selection) {\n\t\treturn;\n\t}\n\n\tconst activeFileUri = editor?.document.uri;\n\tconst browserPath = await routerParser.buildBlobPath(\n\t\trepo,\n\t\tref,\n\t\tactiveFileUri.path.slice(1),\n\t\t!editor.selection.isEmpty ? editor.selection.start.line + 1 : undefined,\n\t\teditor.selection.end.line !== editor.selection.start.line ? editor.selection.end.line + 1 : undefined,\n\t);\n\n\tbrowserPath !== (await router.getPath()) && router.replace(browserPath);\n};\n\n// refresh file history view if active editor changed\nconst handleRefreshFileHistoryView = () => {\n\tvscode.commands.executeCommand('github1s.commands.refreshFileHistoryCommitList', false);\n};\n\nexport const registerVSCodeEventListeners = () => {\n\tvscode.window.onDidChangeActiveTextEditor((editor) => {\n\t\thandleRouterOnActiveEditorChange(editor);\n\t\thandleOpenChangesContextOnActiveEditorChange(editor);\n\t\thandlegutterBlameOpenContextOnActiveEditorChange();\n\t\thandleRefreshFileHistoryView();\n\t});\n\n\t// debounce to update the browser url\n\tconst debouncedSelectionChangeRouterHandler = debounce(handleRouterOnTextEditorSelectionChange, 100);\n\tvscode.window.onDidChangeTextEditorSelection((event) => {\n\t\tdebouncedSelectionChangeRouterHandler(event.textEditor);\n\t});\n};\n"
  },
  {
    "path": "extensions/github1s/src/messages.ts",
    "content": "/**\n * @file vscode messages\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { getSourcegraphUrl } from '@/helpers/urls';\n\nexport const showSourcegraphSearchMessage = (() => {\n\tlet alreadyShown = false;\n\n\treturn async () => {\n\t\tif (alreadyShown) {\n\t\t\treturn;\n\t\t}\n\t\talreadyShown = true;\n\t\tconst { repo, ref } = await router.getState();\n\t\tconst url = `https://sourcegraph.com/github.com/${repo}@${ref}`;\n\t\tvscode.window.showInformationMessage(`The code search ability is powered by [Sourcegraph](${url})`);\n\t};\n})();\n\nexport const showSourcegraphSymbolMessage = (() => {\n\tlet alreadyShown = false;\n\treturn async (repo: string, ref: string, path: string, line: number, character: number) => {\n\t\tif (alreadyShown) {\n\t\t\treturn;\n\t\t}\n\t\talreadyShown = true;\n\t\tconst url = getSourcegraphUrl(repo, ref, path, line, character);\n\t\tvscode.window.showInformationMessage(`The results are provided by [Sourcegraph](${url})`);\n\t};\n})();\n\nexport const showFileBlameAuthorizedRequiredMessage = async () => {\n\tconst selectedValue = await vscode.window.showInformationMessage(\n\t\t'The file blame feature only works for authorized users due to the limit of [GitHub GraphQL API](https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#authenticating-with-graphql), please provide an AccessToken to enable it.',\n\t\t'Set AccessToken',\n\t);\n\tif (selectedValue === 'Set AccessToken') {\n\t\tvscode.commands.executeCommand('github1s.views.settings.focus');\n\t}\n};\n"
  },
  {
    "path": "extensions/github1s/src/providers/decorations/changed-file.ts",
    "content": "/**\n * @file GitHub1s ChangedFile FileDecorationProvider,\n * @author netcon\n * Decorate the file/directory that has changes\n */\n\nimport {\n\tCancellationToken,\n\tDisposable,\n\tEventEmitter,\n\tFileDecoration,\n\tFileDecorationProvider,\n\tProviderResult,\n\tUri,\n\tThemeColor,\n} from 'vscode';\nimport router from '@/router';\nimport { ChangedFile, FileChangeStatus, PageType } from '@/adapters/types';\nimport { adapterManager } from '@/adapters';\nimport { Repository } from '@/repository';\n\nexport const changedFileDecorationDataMap: { [key: string]: FileDecoration } = {\n\t[FileChangeStatus.Added]: {\n\t\ttooltip: 'Added',\n\t\tbadge: 'A',\n\t\tcolor: new ThemeColor('github1s.colors.addedResourceForeground'),\n\t},\n\t[FileChangeStatus.Removed]: {\n\t\ttooltip: 'Deleted',\n\t\tbadge: 'D',\n\t\tcolor: new ThemeColor('github1s.colors.deletedResourceForeground'),\n\t},\n\t[FileChangeStatus.Modified]: {\n\t\ttooltip: 'Modified',\n\t\tbadge: 'M',\n\t\tcolor: new ThemeColor('github1s.colors.modifiedResourceForeground'),\n\t},\n\t[FileChangeStatus.Renamed]: {\n\t\ttooltip: 'Renamed',\n\t\tbadge: 'R',\n\t\tcolor: new ThemeColor('github1s.colors.modifiedResourceForeground'),\n\t},\n};\n\nconst getFileDecorationFromChangeFiles = (uri: Uri, changedFiles: ChangedFile[]): FileDecoration | null => {\n\tconst changedFile = changedFiles.find((changedFile) => changedFile.path === uri.path.slice(1));\n\n\tif (changedFile) {\n\t\treturn changedFileDecorationDataMap[changedFile.status];\n\t}\n\t// we have to determine the changed folder manually rather then use\n\t// the `propagate` property of FileDecoration, because the file tree\n\t// in the file explorer is lazy load\n\tconst folderPath = `${uri.path.slice(1)}/`;\n\tconst includeChangedFile = changedFiles.find((changedFile) => changedFile.path.startsWith(folderPath));\n\tif (includeChangedFile) {\n\t\treturn {\n\t\t\t...changedFileDecorationDataMap[includeChangedFile.status],\n\t\t\tbadge: '\\u29bf',\n\t\t};\n\t}\n\treturn null;\n};\n\nconst getFileDecorationForCodeReview = async (uri: Uri, codeReviewId: string): Promise<FileDecoration | null> => {\n\tconst [repo] = (uri.authority || (await router.getAuthority()))?.split('+') || [];\n\tconst repository = Repository.getInstance(uri.scheme, repo);\n\tconst changedFiles = await repository.getCodeReviewChangedFiles(codeReviewId);\n\treturn getFileDecorationFromChangeFiles(uri, changedFiles);\n};\n\nconst getFileDecorationForCommit = async (uri: Uri, commitSha: string): Promise<FileDecoration | null> => {\n\tconst [repo] = (uri.authority || (await router.getAuthority()))?.split('+') || [];\n\tconst repository = Repository.getInstance(uri.scheme, repo);\n\tconst changedFiles = await repository.getCommitChangedFiles(commitSha);\n\treturn getFileDecorationFromChangeFiles(uri, changedFiles);\n};\n\nexport class GitHub1sChangedFileDecorationProvider implements FileDecorationProvider, Disposable {\n\tprivate static instance: GitHub1sChangedFileDecorationProvider | null = null;\n\tprivate readonly disposable: Disposable;\n\n\tprivate _onDidChangeFileDecorations = new EventEmitter<undefined>();\n\treadonly onDidChangeFileDecorations = this._onDidChangeFileDecorations.event;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sChangedFileDecorationProvider {\n\t\tif (GitHub1sChangedFileDecorationProvider.instance) {\n\t\t\treturn GitHub1sChangedFileDecorationProvider.instance;\n\t\t}\n\t\treturn (GitHub1sChangedFileDecorationProvider.instance = new GitHub1sChangedFileDecorationProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\tupdateDecorations() {\n\t\tthis._onDidChangeFileDecorations.fire(undefined);\n\t}\n\n\tprovideFileDecoration(uri: Uri, _token: CancellationToken): ProviderResult<FileDecoration> {\n\t\tif (uri.scheme !== adapterManager.getCurrentScheme()) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn router.getState().then((routerState) => {\n\t\t\tif (routerState.pageType === PageType.CodeReview) {\n\t\t\t\treturn getFileDecorationForCodeReview(uri, routerState.codeReviewId);\n\t\t\t}\n\t\t\tif (routerState.pageType === PageType.Commit) {\n\t\t\t\treturn getFileDecorationForCommit(uri, routerState.commitSha);\n\t\t\t}\n\t\t\treturn null;\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/decorations/source-control.ts",
    "content": "/**\n * @file GitHub1s File Decoration for the view in SourceControl Panel\n * @author netcon\n */\n\nimport {\n\tCancellationToken,\n\tDisposable,\n\tEventEmitter,\n\tFileDecoration,\n\tFileDecorationProvider,\n\tProviderResult,\n\tThemeColor,\n\tUri,\n} from 'vscode';\nimport router from '@/router';\nimport * as queryString from 'query-string';\nimport { changedFileDecorationDataMap } from './changed-file';\n\nconst selectedViewItemDecoration: FileDecoration = {\n\tcolor: new ThemeColor('github1s.colors.selectedViewItem'),\n\tbadge: '✔',\n\ttooltip: 'Selected',\n};\n\nexport class GitHub1sSourceControlDecorationProvider implements FileDecorationProvider, Disposable {\n\tpublic static codeReviewSchema: string = 'github1s-source-control-code-review';\n\tpublic static commitSchema: string = 'github1s-source-control-commit';\n\tprivate static instance: GitHub1sSourceControlDecorationProvider | null = null;\n\n\tprivate readonly disposable: Disposable;\n\tprivate _onDidChangeFileDecorations = new EventEmitter<undefined>();\n\treadonly onDidChangeFileDecorations = this._onDidChangeFileDecorations.event;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sSourceControlDecorationProvider {\n\t\tif (GitHub1sSourceControlDecorationProvider.instance) {\n\t\t\treturn GitHub1sSourceControlDecorationProvider.instance;\n\t\t}\n\t\treturn (GitHub1sSourceControlDecorationProvider.instance = new GitHub1sSourceControlDecorationProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\tupdateDecorations() {\n\t\tthis._onDidChangeFileDecorations.fire(undefined);\n\t}\n\n\tprovideFileDecoration(uri: Uri, _token: CancellationToken): ProviderResult<FileDecoration> {\n\t\tif (uri.query.includes('changeStatus')) {\n\t\t\tconst query = queryString.parse(uri.query);\n\t\t\treturn changedFileDecorationDataMap[query.changeStatus as string];\n\t\t}\n\n\t\tif (uri.scheme === GitHub1sSourceControlDecorationProvider.codeReviewSchema) {\n\t\t\treturn router.getState().then((routerState) => {\n\t\t\t\tconst query = queryString.parse(uri.query);\n\t\t\t\treturn +(routerState as any).codeReviewId === +query.id! ? selectedViewItemDecoration : null;\n\t\t\t});\n\t\t}\n\n\t\tif (uri.scheme === GitHub1sSourceControlDecorationProvider.commitSchema) {\n\t\t\treturn router.getState().then((routerState) => {\n\t\t\t\tconst query = queryString.parse(uri.query);\n\t\t\t\treturn (routerState as any).commitSha === query.sha ? selectedViewItemDecoration : null;\n\t\t\t});\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/decorations/submodule.ts",
    "content": "/**\n * @file GitHub1s Submodule FileDecorationProvider,\n * @author netcon\n * Decorate the directory which is a submodule in the file tree\n */\n\nimport {\n\tCancellationToken,\n\tDisposable,\n\tEventEmitter,\n\tFileDecoration,\n\tFileDecorationProvider,\n\tProviderResult,\n\tThemeColor,\n\tUri,\n} from 'vscode';\nimport { GitHub1sFileSystemProvider } from '../file-system';\nimport { Directory } from '../file-system/types';\n\nexport class GitHub1sSubmoduleDecorationProvider implements FileDecorationProvider, Disposable {\n\tprivate static instance: GitHub1sSubmoduleDecorationProvider | null = null;\n\tprivate readonly disposable: Disposable;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sSubmoduleDecorationProvider {\n\t\tif (GitHub1sSubmoduleDecorationProvider.instance) {\n\t\t\treturn GitHub1sSubmoduleDecorationProvider.instance;\n\t\t}\n\t\treturn (GitHub1sSubmoduleDecorationProvider.instance = new GitHub1sSubmoduleDecorationProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\t// the directory which is submodule will be decorated with this\n\tprivate static submoduleDecorationData: FileDecoration = {\n\t\ttooltip: 'Submodule',\n\t\tbadge: 'S',\n\t\tcolor: new ThemeColor('github1s.colors.submoduleResourceForeground'),\n\t};\n\n\tprivate _onDidChangeFileDecorations = new EventEmitter<undefined>();\n\treadonly onDidChangeFileDecorations = this._onDidChangeFileDecorations.event;\n\n\tupdateDecorations() {\n\t\tthis._onDidChangeFileDecorations.fire(undefined);\n\t}\n\n\tprovideFileDecoration(uri: Uri, _token: CancellationToken): ProviderResult<FileDecoration> {\n\t\treturn GitHub1sFileSystemProvider.getInstance()\n\t\t\t.lookup(uri, false)\n\t\t\t.then((entry) => {\n\t\t\t\tif (entry instanceof Directory && entry.isSubmodule === true) {\n\t\t\t\t\treturn GitHub1sSubmoduleDecorationProvider.submoduleDecorationData;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/definition.ts",
    "content": "/**\n * @file DefinitionProvider\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { showSourcegraphSymbolMessage } from '@/messages';\nimport adapterManager from '@/adapters/manager';\n\nexport class GitHub1sDefinitionProvider implements vscode.DefinitionProvider, vscode.Disposable {\n\tprivate static instance: GitHub1sDefinitionProvider | null = null;\n\tprivate readonly disposable: vscode.Disposable;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sDefinitionProvider {\n\t\tif (GitHub1sDefinitionProvider.instance) {\n\t\t\treturn GitHub1sDefinitionProvider.instance;\n\t\t}\n\t\treturn (GitHub1sDefinitionProvider.instance = new GitHub1sDefinitionProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\tasync provideDefinition(\n\t\tdocument: vscode.TextDocument,\n\t\tposition: vscode.Position,\n\t\t_token: vscode.CancellationToken,\n\t): Promise<vscode.Definition | vscode.LocationLink[]> {\n\t\tconst symbolRange = document.getWordRangeAtPosition(position);\n\t\tconst symbol = symbolRange ? document.getText(symbolRange) : '';\n\n\t\tif (!symbol) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst authority = document.uri.authority || (await router.getAuthority());\n\t\tconst [repo, ref] = authority.split('+').filter(Boolean);\n\t\tconst { scheme, path } = document.uri;\n\t\tconst { line, character } = position;\n\n\t\tconst dataSource = await adapterManager.getCurrentAdapter().resolveDataSource();\n\t\tconst symbolDefinitions = await dataSource.provideSymbolDefinitions(repo, ref, path, line, character, symbol);\n\n\t\tif (symbolDefinitions.length) {\n\t\t\tshowSourcegraphSymbolMessage(repo, ref, path, line, character);\n\t\t}\n\n\t\treturn symbolDefinitions.map(({ scope, path, range }) => {\n\t\t\tconst isSameRepo = !scope || (scope.scheme === scheme && scope.repo === repo);\n\t\t\t// if the definition target and the searched symbol is in the same\n\t\t\t// repository, just replace the `document.uri.path` with targetPath\n\t\t\t// (so that the target file will open with expanding the file explorer)\n\t\t\tconst uri = isSameRepo\n\t\t\t\t? document.uri.with({ path: `/${path}` })\n\t\t\t\t: vscode.Uri.parse('').with({\n\t\t\t\t\t\tscheme: scope!.scheme,\n\t\t\t\t\t\tauthority: `${scope!.repo}+${scope!.ref}`,\n\t\t\t\t\t\tpath: `/${path}`,\n\t\t\t\t\t});\n\t\t\tconst { start, end } = range;\n\t\t\treturn {\n\t\t\t\turi,\n\t\t\t\trange: new vscode.Range(\n\t\t\t\t\tnew vscode.Position(start.line, start.character),\n\t\t\t\t\tnew vscode.Position(end.line, end.character),\n\t\t\t\t),\n\t\t\t};\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/file-search.ts",
    "content": "/**\n * @file GitHub1s FileSearchProvider (ctrl/cmd + p)\n * @author netcon\n */\n\nimport {\n\tCancellationToken,\n\tDisposable,\n\tFileSearchProvider,\n\tFileSearchQuery,\n\tFileSearchOptions,\n\tProviderResult,\n\tUri,\n\twindow,\n} from 'vscode';\nimport { matchSorter } from 'match-sorter';\nimport { reuseable } from '@/helpers/func';\nimport router from '@/router';\nimport * as adapterTypes from '@/adapters/types';\nimport { GitHub1sFileSystemProvider } from './file-system';\nimport adapterManager from '@/adapters/manager';\n\nexport class GitHub1sFileSearchProvider implements FileSearchProvider, Disposable {\n\tprivate static instance: GitHub1sFileSearchProvider | null = null;\n\tprivate readonly disposable: Disposable;\n\tprivate fileUrisMap: Map<string, Uri[]> = new Map();\n\n\tprivate constructor() {\n\t\t// Preload the files for better `ctrl/command + p` experience.\n\t\t// Once we have loaded the files, it will also populate the files into\n\t\t// fileSystemProvider's cache. So after that, we don't have to send\n\t\t// a request when you open the new directory in explorer late\n\t\tthis.loadFilesForCurrentAuthority();\n\t}\n\n\tpublic static getInstance(): GitHub1sFileSearchProvider {\n\t\tif (GitHub1sFileSearchProvider.instance) {\n\t\t\treturn GitHub1sFileSearchProvider.instance;\n\t\t}\n\t\treturn (GitHub1sFileSearchProvider.instance = new GitHub1sFileSearchProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\t// load the files for current authority\n\tasync loadFilesForCurrentAuthority() {\n\t\treturn this.getFileUris(await router.getAuthority());\n\t}\n\n\t/**\n\t * Get all files for the repo with specified by `authority`.\n\t * The response of corresponding API maybe truncated, if so,\n\t * we should not insert the response to the fileSystemProvider's\n\t * cache, and the fuzzy search maybe not work fine\n\t */\n\tgetFileUris = reuseable(async (authority: string): Promise<Uri[]> => {\n\t\tif (this.fileUrisMap.has(authority)) {\n\t\t\treturn this.fileUrisMap.get(authority)!;\n\t\t}\n\n\t\tconst [repo, ref] = authority.split('+');\n\t\tconst currentAdapter = adapterManager.getCurrentAdapter();\n\t\tconst dataSource = await currentAdapter.resolveDataSource();\n\t\tconst rootDirectoryData = await dataSource.provideDirectory(repo, ref, '', true);\n\t\tconst rootDirectoryUri = Uri.parse('').with({ scheme: currentAdapter.scheme, authority, path: '/' });\n\n\t\t// the number of items in the tree array maybe exceeded maximum limit, only\n\t\t// insert the data to fileSystemProvider's cache if `treeData.truncated` is false\n\t\tif (!rootDirectoryData?.truncated) {\n\t\t\tconst fsProvider = GitHub1sFileSystemProvider.getInstance();\n\t\t\tfsProvider.populateWithDirectoryEntities(rootDirectoryUri, rootDirectoryData?.entries || []);\n\t\t} else {\n\t\t\twindow.showWarningMessage('Too many files in this repository, file search feature may be limited.');\n\t\t}\n\n\t\tconst fileUris = (rootDirectoryData?.entries || [])\n\t\t\t.filter((item) => item.type === adapterTypes.FileType.File)\n\t\t\t.map((item) => Uri.joinPath(rootDirectoryUri, item.path));\n\t\tthis.fileUrisMap.set(authority, fileUris);\n\t\treturn fileUris;\n\t});\n\n\tprovideFileSearchResults(\n\t\tquery: FileSearchQuery,\n\t\t_options: FileSearchOptions,\n\t\t_token: CancellationToken,\n\t): ProviderResult<Uri[]> {\n\t\treturn router.getAuthority().then(async (authority) => {\n\t\t\treturn matchSorter(await this.getFileUris(authority), query.pattern);\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/file-system/index.ts",
    "content": "/**\n * @file GitHub1s FileSystemProvider\n * @author netcon\n */\n\nimport {\n\tDisposable,\n\tEvent,\n\tEventEmitter,\n\tFileSystemProvider,\n\tFileSystemError,\n\tFileChangeEvent,\n\tFileStat,\n\tFileType,\n\tUri,\n\tworkspace,\n} from 'vscode';\nimport adapterManager from '@/adapters/manager';\nimport * as adapterTypes from '@/adapters/types';\nimport router from '@/router';\nimport { noop, trimStart, basename, dirname, joinPath } from '@/helpers/util';\nimport { parseGitmodules, parseSubmoduleUrl } from '@/helpers/submodule';\nimport { reuseable } from '@/helpers/func';\nimport { File, Directory, Entry } from './types';\n\nconst textDecoder = new TextDecoder();\n\nconst createEntry = (type: adapterTypes.FileType, uri: Uri, name: string, options?: any) => {\n\tswitch (type) {\n\t\tcase adapterTypes.FileType.Directory:\n\t\t\treturn new Directory(uri, name, options);\n\t\tcase adapterTypes.FileType.Submodule:\n\t\t\treturn new Directory(uri, name, { ...options, isSubmodule: true });\n\t\tdefault:\n\t\t\treturn new File(uri, name, options);\n\t}\n};\n\nexport class GitHub1sFileSystemProvider implements FileSystemProvider, Disposable {\n\tprivate static instance: GitHub1sFileSystemProvider | null = null;\n\tprivate readonly disposable: Disposable;\n\tprivate _emitter = new EventEmitter<FileChangeEvent[]>();\n\tprivate root: Map<string, Directory | File> = new Map();\n\tprivate contentCache: Map<string, Uint8Array> = new Map();\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sFileSystemProvider {\n\t\tif (GitHub1sFileSystemProvider.instance) {\n\t\t\treturn GitHub1sFileSystemProvider.instance;\n\t\t}\n\t\treturn (GitHub1sFileSystemProvider.instance = new GitHub1sFileSystemProvider());\n\t}\n\n\tonDidChangeFile: Event<FileChangeEvent[]> = this._emitter.event;\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\tprivate async _resolveDataSource(scheme: string) {\n\t\treturn adapterManager.getAdapter(scheme).resolveDataSource();\n\t}\n\n\t// insert DirectoryEntry into the cache `this.root`\n\tpublic async populateWithDirectoryEntities(base: Uri, entries: adapterTypes.DirectoryEntry[]) {\n\t\tconst baseDirectory = await this.lookupAsDirectory(base, true);\n\t\tif (!baseDirectory) {\n\t\t\treturn;\n\t\t}\n\t\treturn entries.forEach((entry) => {\n\t\t\tlet current = baseDirectory;\n\t\t\tconst pathParts = dirname(entry.path).split('/').filter(Boolean);\n\t\t\tpathParts.forEach((part) => {\n\t\t\t\tif (!(current.entries || (current.entries = new Map<string, Entry>())).has(part)) {\n\t\t\t\t\tcurrent.entries.set(part, createEntry(adapterTypes.FileType.Directory, current.uri, current.name));\n\t\t\t\t}\n\t\t\t\tcurrent = current.entries.get(part) as Directory;\n\t\t\t});\n\t\t\tconst fileName = basename(entry.path);\n\t\t\tif (!(current.entries || (current.entries = new Map<string, Entry>())).has(fileName)) {\n\t\t\t\tconst entryUri = Uri.joinPath(current.uri, current.name);\n\t\t\t\tcurrent.entries.set(fileName, createEntry(entry.type, entryUri, fileName));\n\t\t\t}\n\t\t});\n\t}\n\n\t// --- lookup\n\t// ensure the authority field in `the uri of returned entry` is exists\n\tpublic async lookup(uri: Uri, silent: false): Promise<Entry>;\n\tpublic async lookup(uri: Uri, silent: boolean): Promise<Entry | null>;\n\tpublic async lookup(uri: Uri, silent: boolean): Promise<Entry | null> {\n\t\tconst parts = uri.path.split('/').filter(Boolean);\n\t\t// if the authority of uri is empty, we should use `current authority`\n\t\tconst authority = uri.authority || (await router.getAuthority());\n\t\tif (!this.root.has(authority)) {\n\t\t\tthis.root.set(authority, createEntry(adapterTypes.FileType.Directory, uri.with({ authority, path: '/' }), ''));\n\t\t}\n\t\tlet entry = this.root.get(authority);\n\t\tfor (const part of parts) {\n\t\t\tlet child: Entry | undefined;\n\t\t\tif (entry instanceof Directory) {\n\t\t\t\tif (entry.entries === null) {\n\t\t\t\t\tawait this.readDirectory(Uri.joinPath(entry.uri, entry.name));\n\t\t\t\t}\n\t\t\t\tchild = entry.entries?.get(part);\n\t\t\t}\n\t\t\tif (!child) {\n\t\t\t\tif (!silent) {\n\t\t\t\t\tthrow FileSystemError.FileNotFound(uri);\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tentry = child;\n\t\t}\n\t\treturn entry || null;\n\t}\n\n\tpublic async lookupAsDirectory(uri: Uri, silent: boolean): Promise<Directory | null> {\n\t\tconst entry = await this.lookup(uri, silent);\n\t\tif (entry instanceof Directory) {\n\t\t\treturn entry;\n\t\t}\n\t\tif (!silent) {\n\t\t\tthrow FileSystemError.FileNotADirectory(uri);\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic async lookupAsFile(uri: Uri, silent: boolean): Promise<File | null> {\n\t\tconst entry = await this.lookup(uri, silent);\n\t\tif (entry instanceof File) {\n\t\t\treturn entry;\n\t\t}\n\t\tif (!silent) {\n\t\t\tthrow FileSystemError.FileIsADirectory(uri);\n\t\t}\n\t\treturn null;\n\t}\n\n\twatch(uri: Uri, options: { recursive: boolean; excludes: string[] }): Disposable {\n\t\treturn new Disposable(noop);\n\t}\n\n\tstat(uri: Uri): FileStat | Thenable<FileStat> {\n\t\treturn this.lookup(uri, false);\n\t}\n\n\t// it used by `@/src/providers/fileDecorationProvider.ts`\n\t// update the uri of a git submodule as directory, which the type of corresponding githubEntry should be `commit`.\n\t// the `directory.uri.authority` and the `directory.uri.path` must belong to the `parent repository` before called.\n\t// and the `directory.name` is the corresponding `directory name` in `parent repository` before called.\n\t// once the function is called successful, the `directory.uri.authority` field, the `directory.uri.path`,\n\t// and the `directory.uri.name` field would be changed to the `submodule repository's`.\n\t//\n\t// so this function could be called only once for a submodule directory, for example:\n\t// - the directory argument before called may looks like:\n\t// {\n\t//     uri: {\n\t//         scheme: 'github1s',\n\t//         authority: 'conwnet+github1s+master', // this is the authority of `parent repository`\n\t//         path: '/some/submodule/path' // the corresponding path in `parent repository`\n\t//     },\n\t//     name: 'vscode', // the name is the `directory name` of `parent repository` before called\n\t//     entries: null, // the entries should be null to indicated we haven't call this for `parent`\n\t//     isSubmodule: true, // this Directory must be a submodule\n\t//     ...otherFields\n\t// }\n\t// - and the directory argument after called may looks like:\n\t// {\n\t//     uri: {\n\t//         scheme: 'github1s',\n\t//         authority: 'microsoft+vscode+master', // this is the authority of `submodule repository`\n\t//         path: '/' // the `path` filed should be '/' to indicated to the root directory of `submodule repository`\n\t//     },\n\t//     name: '', // the name is the '' to indicated it is a root directory of `submodule repository`\n\t//     entries: Map<string, Entry> {...}, // the entries contains the files of `submodule repository`\n\t//     isSubmodule: true, // this Directory must be a submodule\n\t//     ...otherFields\n\t// }\n\tprivate _updateSubmoduleDirectory = reuseable(async (directory: Directory): Promise<[string, FileType][]> => {\n\t\t// if the directory is not submodule, or it has be called already\n\t\tif (!directory.isSubmodule || directory.entries) {\n\t\t\treturn directory.getNameTypePairs() || [];\n\t\t}\n\t\tconst parentRepositoryRoot = await this.lookupAsDirectory(directory.uri.with({ path: '/' }), false);\n\t\tif (!parentRepositoryRoot?.entries || !parentRepositoryRoot.entries.has('.gitmodules')) {\n\t\t\tthrow FileSystemError.FileNotFound('.gitmodules can not be found');\n\t\t}\n\t\tconst submodulesFileContent = textDecoder.decode(\n\t\t\tawait this.readFile(Uri.joinPath(parentRepositoryRoot.uri, '.gitmodules')),\n\t\t);\n\t\t// the path should declared in .gitmodules file\n\t\tconst submodulePath = trimStart(Uri.joinPath(directory.uri, directory.name).path, '/');\n\t\tconst gitmoduleData = parseGitmodules(submodulesFileContent).find((item) => item.path === submodulePath);\n\t\tif (!gitmoduleData) {\n\t\t\tthrow FileSystemError.FileNotFound(`can't found corresponding declare in .gitmodules`);\n\t\t}\n\t\tconst [submoduleScheme, submoduleRepo] = parseSubmoduleUrl(gitmoduleData.url);\n\t\tconst submoduleAuthority = `${submoduleRepo}+${directory.sha || 'HEAD'}`;\n\t\tdirectory.name = ''; // update the name field to '' to indicated it is an root directory\n\t\t// update the uri field to indicated it is belong the `submodule repository`\n\t\tdirectory.uri = Uri.parse('').with({\n\t\t\tscheme: submoduleScheme,\n\t\t\tauthority: submoduleAuthority,\n\t\t\tpath: '/',\n\t\t});\n\t\t// insert the directory in to this.root map because it indicated another repository\n\t\tthis.root.set(submoduleAuthority, directory);\n\t\treturn [];\n\t});\n\n\treadDirectory = reuseable(\n\t\tasync (uri: Uri): Promise<[string, FileType][]> => {\n\t\t\tconst parent = await this.lookupAsDirectory(uri, false);\n\t\t\tif (!parent) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tif (parent.entries !== null) {\n\t\t\t\treturn parent.getNameTypePairs();\n\t\t\t}\n\t\t\tif (parent.isSubmodule) {\n\t\t\t\tawait this._updateSubmoduleDirectory(parent);\n\t\t\t}\n\t\t\tconst [repo, ref] = parent.uri.authority.split('+');\n\t\t\tconst path = Uri.joinPath(parent.uri, parent.name).path.slice(1); // delete leading '/'\n\t\t\tconst dataSource = await this._resolveDataSource(uri.scheme);\n\t\t\tconst data = await dataSource.provideDirectory(repo, ref, path, false);\n\t\t\tdata?.entries && (await this.populateWithDirectoryEntities(uri, data.entries));\n\t\t\treturn parent.getNameTypePairs();\n\t\t},\n\t\t(uri) => uri.toString(),\n\t);\n\n\treadFile = reuseable(\n\t\tasync (uri: Uri): Promise<Uint8Array> => {\n\t\t\tlet { scheme, authority, path } = uri;\n\t\t\t// if `authority` is same with current, try to find it with `this.lookupAsFile`,\n\t\t\t// we can't use `router.getAuthority()` directly because this file may be in submodule\n\t\t\tif (authority === workspace.workspaceFolders?.[0].uri.authority) {\n\t\t\t\tconst file = (await this.lookupAsFile(uri, false))!;\n\t\t\t\tscheme = file.uri.scheme;\n\t\t\t\tauthority = file.uri.authority;\n\t\t\t\tpath = joinPath(file.uri.path, file.name);\n\t\t\t}\n\t\t\tconst cacheKey = `${scheme} ${authority} ${path}`;\n\t\t\tif (!this.contentCache.has(cacheKey)) {\n\t\t\t\tconst [repo, ref] = authority.split('+');\n\t\t\t\tconst dataSource = await this._resolveDataSource(scheme);\n\t\t\t\tconst data = await dataSource.provideFile(repo, ref, path.slice(1));\n\t\t\t\tdata && this.contentCache.set(cacheKey, data.content);\n\t\t\t}\n\t\t\treturn this.contentCache.get(cacheKey) || new Uint8Array();\n\t\t},\n\t\t(uri) => uri.toString(),\n\t);\n\n\tasync createDirectory(uri: Uri): Promise<void> {\n\t\treturn;\n\t}\n\n\tasync writeFile(uri: Uri, content: Uint8Array, options: { create: boolean; overwrite: boolean }): Promise<void> {\n\t\treturn;\n\t}\n\n\tasync delete(uri: Uri, options: { recursive: boolean }): Promise<void> {\n\t\treturn;\n\t}\n\n\tasync rename(oldUri: Uri, newUri: Uri, options: { overwrite: boolean }): Promise<void> {\n\t\treturn;\n\t}\n\n\tasync copy?(source: Uri, destination: Uri, options: { overwrite: boolean }): Promise<void> {\n\t\treturn;\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/file-system/types.ts",
    "content": "/**\n * @file GitHub1s FileSystemProvider Types\n * @author netcon\n */\n\nimport { FileStat, FileType, Uri } from 'vscode';\n\nexport class File implements FileStat {\n\ttype: FileType;\n\tctime: number;\n\tmtime: number;\n\tsize: number;\n\tname: string;\n\tsha: string;\n\tcontent: Uint8Array;\n\n\tconstructor(\n\t\tpublic uri: Uri,\n\t\tname: string,\n\t\toptions?: any,\n\t) {\n\t\tthis.type = FileType.File;\n\t\tthis.ctime = Date.now();\n\t\tthis.mtime = Date.now();\n\t\tthis.name = name;\n\t\tthis.sha = options && 'sha' in options ? options.sha : '';\n\t\tthis.size = options && 'size' in options ? options.size : 0;\n\t}\n}\n\nexport class Directory implements FileStat {\n\ttype: FileType;\n\tctime: number;\n\tmtime: number;\n\tsize: number;\n\tsha: string;\n\tname: string;\n\tentries: Map<string, File | Directory> | null;\n\tisSubmodule: boolean;\n\n\tconstructor(\n\t\tpublic uri: Uri,\n\t\tname: string,\n\t\toptions?: any,\n\t) {\n\t\tthis.type = FileType.Directory;\n\t\tthis.ctime = Date.now();\n\t\tthis.mtime = Date.now();\n\t\tthis.size = 0;\n\t\tthis.name = name;\n\t\tthis.entries = null;\n\t\tthis.sha = options && 'sha' in options ? options.sha : '';\n\t\tthis.size = options && 'size' in options ? options.size : 0;\n\t\tthis.isSubmodule = options && 'isSubmodule' in options ? options.isSubmodule : false;\n\t}\n\n\tgetNameTypePairs(): [string, FileType][] {\n\t\treturn Array.from(this.entries?.entries() || []).map(([name, item]: [string, Entry]) => [\n\t\t\tname,\n\t\t\titem instanceof Directory ? FileType.Directory : FileType.File,\n\t\t]);\n\t}\n}\n\nexport type Entry = File | Directory;\n\n// TODO: rename\nexport interface GitHubRESTEntry {\n\tpath: string;\n\ttype: 'tree' | 'blob' | 'commit';\n\tsha: string;\n\tsize?: number;\n}\n\nexport interface GitHubGraphQLEntry {\n\tname: string;\n\toid: string;\n\tpath: string;\n\ttype: 'tree' | 'blob' | 'commit';\n\tobject?: any;\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/hover.ts",
    "content": "/**\n * @file HoverProvider\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { getSourcegraphUrl } from '@/helpers/urls';\nimport { adapterManager } from '@/adapters';\n\nconst getSemanticMarkdownSuffix = (sourcegraphUrl: string) => `\n\n---\n\n[Semantic](https://docs.sourcegraph.com/code_intelligence/explanations/precise_code_intelligence) result provided by [Sourcegraph](${sourcegraphUrl})\n`;\n\nconst getSearchBasedMarkdownSuffix = (sourcegraphUrl: string) => `\n\n---\n\n[Search-based](https://docs.sourcegraph.com/code_intelligence/explanations/precise_code_intelligence) result provided by [Sourcegraph](${sourcegraphUrl})\n`;\n\nexport class GitHub1sHoverProvider implements vscode.HoverProvider, vscode.Disposable {\n\tprivate static instance: GitHub1sHoverProvider | null = null;\n\tprivate readonly disposable: vscode.Disposable;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sHoverProvider {\n\t\tif (GitHub1sHoverProvider.instance) {\n\t\t\treturn GitHub1sHoverProvider.instance;\n\t\t}\n\t\treturn (GitHub1sHoverProvider.instance = new GitHub1sHoverProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\tasync getSearchBasedHover(\n\t\tdocument: vscode.TextDocument,\n\t\tposition: vscode.Position,\n\t\tsymbol: string,\n\t): Promise<string | null> {\n\t\tconst { line, character } = position;\n\t\tconst authority = document.uri.authority || (await router.getAuthority());\n\t\tconst [repo, ref] = authority.split('+').filter(Boolean);\n\t\tconst dataSource = await adapterManager.getCurrentAdapter().resolveDataSource();\n\n\t\tconst requestParams = [repo, ref, document.uri.path, line, character, symbol] as const;\n\t\tconst definitions = await dataSource.provideSymbolDefinitions(...requestParams);\n\n\t\tif (!definitions.length) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// use the information of first definition as hover context\n\t\tconst target = definitions[0];\n\t\tconst isSameRepo = !target.scope || (target.scope.scheme === document.uri.scheme && target.scope.repo === repo);\n\t\t// if the definition target and the searched symbol is in the same\n\t\t// repository, just replace the `document.uri.path` with targetPath\n\t\tconst targetFileUri = isSameRepo\n\t\t\t? document.uri.with({ path: `/${target.path}` })\n\t\t\t: vscode.Uri.parse('').with({\n\t\t\t\t\tscheme: target.scope?.scheme,\n\t\t\t\t\tauthority: `${target.scope?.repo}+${target.scope?.ref}`,\n\t\t\t\t\tpath: `/${target.path}`,\n\t\t\t\t});\n\t\t// open corresponding file with target\n\t\tconst textDocument = await vscode.workspace.openTextDocument(targetFileUri);\n\t\t// get the content in `[range.start.line - 2, range.end.line + 2]` lines\n\t\tconst startPosition = new vscode.Position(Math.max(0, target.range.start.line - 2), 0);\n\n\t\tconst endPosition = textDocument.lineAt(Math.min(textDocument.lineCount - 1, target.range.end.line + 2)).range.end;\n\t\tconst codeText = textDocument.getText(new vscode.Range(startPosition, endPosition));\n\n\t\treturn `\\`\\`\\`${textDocument.languageId}\\n${codeText}\\n\\`\\`\\``;\n\t}\n\n\tasync provideHover(\n\t\tdocument: vscode.TextDocument,\n\t\tposition: vscode.Position,\n\t\t_token: vscode.CancellationToken,\n\t): Promise<vscode.Hover | null> {\n\t\tconst symbolRange = document.getWordRangeAtPosition(position);\n\t\tconst symbol = symbolRange ? document.getText(symbolRange) : '';\n\n\t\tif (!symbol) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst authority = document.uri.authority || (await router.getAuthority());\n\t\tconst [repo, ref] = authority.split('+').filter(Boolean);\n\t\tconst path = document.uri.path;\n\t\tconst { line, character } = position;\n\n\t\t// get the sourcegraph url for current symbol\n\t\tconst sourcegraphUrl = getSourcegraphUrl(repo, ref, path, line, character);\n\t\tconst requestParams = [repo, ref, path, line, character, symbol] as const;\n\n\t\t// get the hover result based on search\n\t\tconst searchBasedMardownPromise = this.getSearchBasedHover(document, position, symbol);\n\n\t\t// get the hover result based on sourcegraph lsif\n\t\tconst dataSource = await adapterManager.getCurrentAdapter().resolveDataSource();\n\t\tconst symbolHover = await dataSource.provideSymbolHover(...requestParams);\n\n\t\tconst markdown = symbolHover ? symbolHover.markdown : await searchBasedMardownPromise;\n\n\t\tif (!markdown) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst suffixMarkdown = symbolHover\n\t\t\t? getSemanticMarkdownSuffix(sourcegraphUrl)\n\t\t\t: getSearchBasedMarkdownSuffix(sourcegraphUrl);\n\n\t\treturn new vscode.Hover(markdown + suffixMarkdown);\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/index.ts",
    "content": "/**\n * @file register VS Code providers\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport adapterManager from '@/adapters/manager';\nimport { getExtensionContext } from '@/helpers/context';\nimport { GitHub1sFileSystemProvider } from './file-system';\nimport { GitHub1sFileSearchProvider } from './file-search';\nimport { GitHub1sTextSearchProvider } from './text-search';\nimport { GitHub1sSubmoduleDecorationProvider } from './decorations/submodule';\nimport { GitHub1sChangedFileDecorationProvider } from './decorations/changed-file';\nimport { GitHub1sSourceControlDecorationProvider } from './decorations/source-control';\nimport { GitHub1sDefinitionProvider } from './definition';\nimport { GitHub1sReferenceProvider } from './reference';\nimport { GitHub1sHoverProvider } from './hover';\n\nexport const EMPTY_FILE_SCHEME = 'github1s-empty-file';\nexport const emptyFileUri = vscode.Uri.parse('').with({\n\tscheme: EMPTY_FILE_SCHEME,\n});\n\nexport const registerVSCodeProviders = () => {\n\tconst context = getExtensionContext();\n\n\tconst allSchemes = adapterManager.getAllAdapters().map((item) => item.scheme);\n\n\tallSchemes.forEach((scheme) => {\n\t\tcontext.subscriptions.push(\n\t\t\tvscode.workspace.registerFileSystemProvider(scheme, GitHub1sFileSystemProvider.getInstance(), {\n\t\t\t\tisCaseSensitive: true,\n\t\t\t\tisReadonly: true,\n\t\t\t}),\n\t\t\tvscode.workspace.registerFileSearchProvider(scheme, GitHub1sFileSearchProvider.getInstance()),\n\t\t\tvscode.workspace.registerTextSearchProvider(scheme, GitHub1sTextSearchProvider.getInstance()),\n\t\t\tvscode.languages.registerDefinitionProvider({ scheme }, GitHub1sDefinitionProvider.getInstance()),\n\t\t\tvscode.languages.registerReferenceProvider({ scheme }, GitHub1sReferenceProvider.getInstance()),\n\t\t\tvscode.languages.registerHoverProvider({ scheme }, GitHub1sHoverProvider.getInstance()),\n\t\t);\n\t});\n\n\tcontext.subscriptions.push(\n\t\tvscode.window.registerFileDecorationProvider(GitHub1sSubmoduleDecorationProvider.getInstance()),\n\t\tvscode.window.registerFileDecorationProvider(GitHub1sChangedFileDecorationProvider.getInstance()),\n\t\tvscode.window.registerFileDecorationProvider(GitHub1sSourceControlDecorationProvider.getInstance()),\n\t\t// provider a readonly empty file for diff\n\t\tvscode.workspace.registerTextDocumentContentProvider(EMPTY_FILE_SCHEME, {\n\t\t\tprovideTextDocumentContent: () => '',\n\t\t}),\n\t);\n};\n"
  },
  {
    "path": "extensions/github1s/src/providers/reference.ts",
    "content": "/**\n * @file ReferenceProvider\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { showSourcegraphSymbolMessage } from '@/messages';\nimport adapterManager from '@/adapters/manager';\n\nexport class GitHub1sReferenceProvider implements vscode.ReferenceProvider, vscode.Disposable {\n\tprivate static instance: GitHub1sReferenceProvider | null = null;\n\tprivate readonly disposable: vscode.Disposable;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sReferenceProvider {\n\t\tif (GitHub1sReferenceProvider.instance) {\n\t\t\treturn GitHub1sReferenceProvider.instance;\n\t\t}\n\t\treturn (GitHub1sReferenceProvider.instance = new GitHub1sReferenceProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\tasync provideReferences(\n\t\tdocument: vscode.TextDocument,\n\t\tposition: vscode.Position,\n\t\t_context: vscode.ReferenceContext,\n\t\t_token: vscode.CancellationToken,\n\t): Promise<vscode.Location[]> {\n\t\tconst symbolRange = document.getWordRangeAtPosition(position);\n\t\tconst symbol = symbolRange ? document.getText(symbolRange) : '';\n\n\t\tif (!symbol) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst authority = document.uri.authority || (await router.getAuthority());\n\t\tconst [repo, ref] = authority.split('+').filter(Boolean);\n\t\tconst { scheme, path } = document.uri;\n\t\tconst { line, character } = position;\n\n\t\tconst dataSource = await adapterManager.getCurrentAdapter().resolveDataSource();\n\t\tconst symbolReferences = await dataSource.provideSymbolReferences(repo, ref, path, line, character, symbol);\n\n\t\tif (symbolReferences.length) {\n\t\t\tshowSourcegraphSymbolMessage(repo, ref, path, line, character);\n\t\t}\n\n\t\treturn symbolReferences.map(({ scope, path, range }) => {\n\t\t\tconst isSameRepo = !scope || (scope.scheme === scheme && scope.repo === repo);\n\t\t\t// if the reference target and the searched symbol is in the same\n\t\t\t// repository, just replace the `document.uri.path` with targetPath\n\t\t\t// (so that the target file will open with expanding the file explorer)\n\t\t\tconst uri = isSameRepo\n\t\t\t\t? document.uri.with({ path: `/${path}` })\n\t\t\t\t: vscode.Uri.parse('').with({\n\t\t\t\t\t\tscheme: scope!.scheme,\n\t\t\t\t\t\tauthority: `${scope!.repo}+${scope!.ref}`,\n\t\t\t\t\t\tpath: `/${path}`,\n\t\t\t\t\t});\n\t\t\tconst { start, end } = range;\n\t\t\treturn {\n\t\t\t\turi,\n\t\t\t\trange: new vscode.Range(\n\t\t\t\t\tnew vscode.Position(start.line, start.character),\n\t\t\t\t\tnew vscode.Position(end.line, end.character),\n\t\t\t\t),\n\t\t\t};\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/providers/text-search.ts",
    "content": "/**\n * @file GitHub1s TextSearchProvider (ctrl/cmd + shift + f)\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport adapterManager from '@/adapters/manager';\nimport { showSourcegraphSearchMessage } from '@/messages';\nimport * as adapterTypes from '@/adapters/types';\n\nconst ensureArray = <T>(arrayOrItem: T | T[]): T[] => (Array.isArray(arrayOrItem) ? arrayOrItem : [arrayOrItem]);\nconst createVscodeRange = (range: adapterTypes.Range) =>\n\tnew vscode.Range(range.start.line, range.start.character, range.end.line, range.end.character);\n\nexport class GitHub1sTextSearchProvider implements vscode.TextSearchProvider, vscode.Disposable {\n\tprivate static instance: GitHub1sTextSearchProvider | null = null;\n\tprivate readonly disposable: vscode.Disposable;\n\n\tprivate constructor() {}\n\n\tpublic static getInstance(): GitHub1sTextSearchProvider {\n\t\tif (GitHub1sTextSearchProvider.instance) {\n\t\t\treturn GitHub1sTextSearchProvider.instance;\n\t\t}\n\t\treturn (GitHub1sTextSearchProvider.instance = new GitHub1sTextSearchProvider());\n\t}\n\n\tdispose() {\n\t\tthis.disposable?.dispose();\n\t}\n\n\tprovideTextSearchResults(\n\t\tquery: vscode.TextSearchQuery,\n\t\toptions: vscode.TextSearchOptions,\n\t\tprogress: vscode.Progress<vscode.TextSearchResult>,\n\t\t_token: vscode.CancellationToken,\n\t) {\n\t\treturn router.getAuthority().then(async (authority) => {\n\t\t\tconst [repo, ref] = authority.split('+');\n\t\t\tconst dataSource = await adapterManager.getCurrentAdapter().resolveDataSource();\n\t\t\tconst searchOptions = { page: 1, pageSize: 100, includes: options.includes, excludes: options.excludes };\n\t\t\tconst searchResults = await dataSource.provideTextSearchResults(repo, ref, query, searchOptions);\n\t\t\tconst currentScheme = adapterManager.getCurrentScheme();\n\n\t\t\t(searchResults.results || []).forEach((item) => {\n\t\t\t\t// because we set the authority of workspace as '' (on application start)\n\t\t\t\t// at src/vs/code/browser/workbench/workbench.ts\n\t\t\t\t// so don't specified authority here, or the VS Code won't use the results\n\t\t\t\tconst fileUri = vscode.Uri.parse('').with({ scheme: currentScheme, path: `/${item.path}` });\n\t\t\t\tconst ranges = ensureArray(item.ranges).map((range) => createVscodeRange(range));\n\t\t\t\tconst previewMatches = ensureArray(item.preview.matches).map((match) => createVscodeRange(match));\n\t\t\t\tconst preview = { text: item.preview.text, matches: previewMatches };\n\n\t\t\t\tprogress.report({ uri: fileUri, ranges, preview });\n\t\t\t});\n\n\t\t\tshowSourcegraphSearchMessage();\n\t\t\treturn { limitHit: searchResults.truncated };\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/repository/branch-tag-manager.ts",
    "content": "/**\n * @file Branch/Tag Manager\n * @author netcon\n */\n\nimport { reuseable } from '@/helpers/func';\nimport { Branch, Tag } from '@/adapters/types';\nimport { adapterManager } from '@/adapters';\n\nexport class BranchTagManager {\n\tprivate static instancesMap = new Map<string, BranchTagManager>();\n\n\tprivate _branchMap = new Map<string, Branch>(); // branchName -> Branch\n\tprivate _branchList: Branch[] | null = null;\n\tprivate _branchPageSize = 1000;\n\tprivate _branchCurrentPage = 1; // page number is begin from 1\n\tprivate _branchHasMore = true;\n\n\tprivate _tagMap = new Map<string, Tag>(); // tagName -> Tag\n\tprivate _tagList: Tag[] | null = null;\n\tprivate _tagPageSize = 1000;\n\tprivate _tagCurrentPage = 1; // page number is begin from 1\n\tprivate _tagHasMore = true;\n\n\tpublic static getInstance(scheme: string, repo: string) {\n\t\tconst mapKey = `${scheme} ${repo}`;\n\t\tif (!BranchTagManager.instancesMap.has(mapKey)) {\n\t\t\tBranchTagManager.instancesMap.set(mapKey, new BranchTagManager(scheme, repo));\n\t\t}\n\t\treturn BranchTagManager.instancesMap.get(mapKey)!;\n\t}\n\n\tprivate constructor(\n\t\tprivate _scheme: string,\n\t\tprivate _repo: string,\n\t) {}\n\n\tgetBranchList = reuseable(async (forceUpdate: boolean = false): Promise<Branch[]> => {\n\t\tif (forceUpdate || !this._branchList) {\n\t\t\tthis._branchList = [];\n\t\t\tthis._branchCurrentPage = 1;\n\t\t\tawait this.loadMoreBranches();\n\t\t}\n\t\treturn this._branchList;\n\t});\n\n\tgetBranchItem = reuseable(async (branchName: string, forceUpdate = false): Promise<Branch | null> => {\n\t\tif (forceUpdate || !this._branchMap.has(branchName)) {\n\t\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\t\tconst branch = await dataSource.provideBranch(this._repo, branchName);\n\t\t\tbranch && this._branchMap.set(branchName, branch);\n\t\t}\n\t\treturn this._branchMap.get(branchName) || null;\n\t});\n\n\tloadMoreBranches = reuseable(async (): Promise<Branch[]> => {\n\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\tconst queryOptions = { pageSize: this._branchPageSize, page: this._branchCurrentPage };\n\t\tconst branches = await dataSource.provideBranches(this._repo, queryOptions);\n\n\t\tbranches.forEach((branch) => this._branchMap.set(branch.name, branch));\n\t\tthis._branchCurrentPage += 1;\n\t\tthis._branchHasMore = branches.length === this._branchPageSize;\n\t\t(this._branchList || (this._branchList = [])).push(...branches);\n\n\t\treturn branches;\n\t});\n\n\thasMoreBranches = reuseable(async () => {\n\t\treturn this._branchHasMore;\n\t});\n\n\tgetTagList = reuseable(async (forceUpdate: boolean = false): Promise<Tag[]> => {\n\t\tif (forceUpdate || !this._tagList) {\n\t\t\tthis._tagList = [];\n\t\t\tthis._tagCurrentPage = 1;\n\t\t\tawait this.loadMoreTags();\n\t\t}\n\t\treturn this._tagList;\n\t});\n\n\tgetTagItem = reuseable(async (tagName: string, forceUpdate = false): Promise<Tag | null> => {\n\t\tif (forceUpdate || !this._tagMap.has(tagName)) {\n\t\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\t\tconst tag = await dataSource.provideTag(this._repo, tagName);\n\t\t\ttag && this._tagMap.set(tagName, tag);\n\t\t}\n\t\treturn this._tagMap.get(tagName) || null;\n\t});\n\n\tloadMoreTags = reuseable(async (): Promise<Tag[]> => {\n\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\tconst queryOptions = { pageSize: this._tagPageSize, page: this._tagCurrentPage };\n\t\tconst tags = await dataSource.provideTags(this._repo, queryOptions);\n\n\t\ttags.forEach((tag) => this._tagMap.set(tag.name, tag));\n\t\tthis._tagCurrentPage += 1;\n\t\tthis._tagHasMore = tags.length === this._tagPageSize;\n\t\t(this._tagList || (this._tagList = [])).push(...tags);\n\n\t\treturn tags;\n\t});\n\n\thasMoreTags = reuseable(async () => {\n\t\treturn this._tagHasMore;\n\t});\n}\n"
  },
  {
    "path": "extensions/github1s/src/repository/code-review-manager.ts",
    "content": "/**\n * @file Code Review Manager\n * @author netcon\n */\n\nimport { reuseable } from '@/helpers/func';\nimport { ChangedFile, CodeReview } from '@/adapters/types';\nimport { adapterManager } from '@/adapters';\n\n// manage changed files for a code review\nclass CodeReviewChangedFilesManager {\n\tprivate static instancesMap = new Map<string, CodeReviewChangedFilesManager>();\n\n\tprivate _pageSize = 100;\n\tprivate _currentPage = 1; // page is begin from 1\n\tprivate _hasMore = true;\n\tprivate _changedFilesList: ChangedFile[] | null = null;\n\n\tpublic static getInstance(scheme: string, repo: string, codeReviewId: string) {\n\t\tconst mapKey = `${scheme} ${repo} ${codeReviewId}`;\n\t\tif (!CodeReviewChangedFilesManager.instancesMap.has(mapKey)) {\n\t\t\tconst manager = new CodeReviewChangedFilesManager(scheme, repo, codeReviewId);\n\t\t\tCodeReviewChangedFilesManager.instancesMap.set(mapKey, manager);\n\t\t}\n\t\treturn CodeReviewChangedFilesManager.instancesMap.get(mapKey)!;\n\t}\n\n\tconstructor(\n\t\tprivate _scheme: string,\n\t\tprivate _repo: string,\n\t\tprivate _codeReviewId: string,\n\t) {}\n\n\tgetList = reuseable(async (forceUpdate: boolean = false): Promise<ChangedFile[]> => {\n\t\tif (forceUpdate || !this._changedFilesList) {\n\t\t\tthis._currentPage = 1;\n\t\t\tthis._changedFilesList = [];\n\t\t\tawait this.loadMore();\n\t\t}\n\t\treturn this._changedFilesList;\n\t});\n\n\tloadMore = reuseable(async (): Promise<ChangedFile[]> => {\n\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\tconst changedFiles = await dataSource.provideCodeReviewChangedFiles(this._repo, this._codeReviewId, {\n\t\t\tpageSize: this._pageSize,\n\t\t\tpage: this._currentPage,\n\t\t});\n\n\t\tthis._currentPage += 1;\n\t\tthis._hasMore = changedFiles.length === this._pageSize;\n\t\t(this._changedFilesList || (this._changedFilesList = [])).push(...changedFiles);\n\n\t\treturn changedFiles;\n\t});\n\n\thasMore = reuseable(async () => {\n\t\treturn this._hasMore;\n\t});\n\n\tasync setChangedFiles(files: ChangedFile[]) {\n\t\tthis._changedFilesList = files;\n\t\tthis._hasMore = false;\n\t}\n}\n\nexport class CodeReviewManager {\n\tprivate static instancesMap = new Map<string, CodeReviewManager>();\n\n\tprivate _codeReviewMap = new Map<string, CodeReview>(); // codeReviewId -> CodeReview\n\tprivate _codeReviewList: CodeReview[] | null = null;\n\tprivate _pageSize = 100;\n\tprivate _currentPage = 1; // page number is begin from 1\n\tprivate _hasMore = true;\n\n\tpublic static getInstance(scheme: string, repo: string) {\n\t\tconst mapKey = `${scheme} ${repo}`;\n\t\tif (!CodeReviewManager.instancesMap.has(mapKey)) {\n\t\t\tCodeReviewManager.instancesMap.set(mapKey, new CodeReviewManager(scheme, repo));\n\t\t}\n\t\treturn CodeReviewManager.instancesMap.get(mapKey)!;\n\t}\n\n\tprivate constructor(\n\t\tprivate _scheme: string,\n\t\tprivate _repo: string,\n\t) {}\n\n\tgetList = reuseable(async (forceUpdate: boolean = false): Promise<CodeReview[]> => {\n\t\tif (forceUpdate || !this._codeReviewList) {\n\t\t\tthis._currentPage = 1;\n\t\t\tthis._codeReviewList = [];\n\t\t\tawait this.loadMore();\n\t\t}\n\t\treturn this._codeReviewList;\n\t});\n\n\tgetItem = reuseable(\n\t\tasync (\n\t\t\tcodeReviewId: string,\n\t\t\tforceUpdate = false,\n\t\t): Promise<(CodeReview & { sourceSha: string; targetSha: string }) | null> => {\n\t\t\tconst isShaExists = (codeReview: CodeReview) => codeReview.sourceSha && codeReview.targetSha;\n\t\t\tif (\n\t\t\t\tforceUpdate ||\n\t\t\t\t!this._codeReviewMap.has(codeReviewId) ||\n\t\t\t\t!isShaExists(this._codeReviewMap.get(codeReviewId)!)\n\t\t\t) {\n\t\t\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\t\t\tconst codeReview = await dataSource.provideCodeReview(this._repo, codeReviewId);\n\t\t\t\tcodeReview && this._codeReviewMap.set(codeReviewId, codeReview);\n\t\t\t\tif (codeReview?.files) {\n\t\t\t\t\tconst manager = CodeReviewChangedFilesManager.getInstance(this._scheme, this._repo, codeReviewId);\n\t\t\t\t\tmanager.setChangedFiles(codeReview.files);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn (this._codeReviewMap.get(codeReviewId) || null) as\n\t\t\t\t| (CodeReview & { sourceSha: string; targetSha: string })\n\t\t\t\t| null;\n\t\t},\n\t);\n\n\tloadMore = reuseable(async (): Promise<CodeReview[]> => {\n\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\tconst queryOptions = { pageSize: this._pageSize, page: this._currentPage };\n\t\tconst codeReviews = await dataSource.provideCodeReviews(this._repo, queryOptions);\n\n\t\tcodeReviews.forEach((codeReview) => {\n\t\t\tthis._codeReviewMap.set(codeReview.id, codeReview);\n\t\t\t// directly set changed files if they are in response\n\t\t\tif (codeReview.files) {\n\t\t\t\tconst manager = CodeReviewChangedFilesManager.getInstance(this._scheme, this._repo, codeReview.id);\n\t\t\t\tmanager.setChangedFiles(codeReview.files);\n\t\t\t}\n\t\t});\n\t\tthis._currentPage += 1;\n\t\tthis._hasMore = codeReviews.length === this._pageSize;\n\t\t(this._codeReviewList || (this._codeReviewList = [])).push(...codeReviews);\n\n\t\treturn codeReviews;\n\t});\n\n\thasMore = reuseable(async () => {\n\t\treturn this._hasMore;\n\t});\n\n\tpublic getChangedFiles = reuseable(\n\t\tasync (codeReviewId: string, forceUpdate: boolean = false): Promise<ChangedFile[]> => {\n\t\t\tconst manager = CodeReviewChangedFilesManager.getInstance(this._scheme, this._repo, codeReviewId);\n\t\t\treturn manager.getList(forceUpdate);\n\t\t},\n\t);\n\n\tpublic loadMoreChangedFiles = reuseable(async (codeReviewId: string) => {\n\t\tconst manager = CodeReviewChangedFilesManager.getInstance(this._scheme, this._repo, codeReviewId);\n\t\treturn manager.loadMore();\n\t});\n\n\tpublic hasMoreChangedFiles = reuseable((codeReviewId: string) => {\n\t\tconst manager = CodeReviewChangedFilesManager.getInstance(this._scheme, this._repo, codeReviewId);\n\t\treturn manager.hasMore();\n\t});\n}\n"
  },
  {
    "path": "extensions/github1s/src/repository/commit-manager.ts",
    "content": "/**\n * @file Commit Manager\n * @author netcon\n */\n\nimport { reuseable } from '@/helpers/func';\nimport { ChangedFile, Commit } from '@/adapters/types';\nimport { adapterManager } from '@/adapters';\n\n// manage changed files for a commit\nclass CommitChangedFilesManager {\n\tprivate static instancesMap = new Map<string, CommitChangedFilesManager>();\n\n\tprivate _pageSize = 100;\n\tprivate _currentPage = 1; // page is begin from 1\n\tprivate _hasMore = true;\n\tprivate _changedFilesList: ChangedFile[] | null = null;\n\n\tpublic static getInstance(scheme: string, repo: string, commitSha: string) {\n\t\tconst mapKey = `${scheme} ${repo} ${commitSha}`;\n\t\tif (!CommitChangedFilesManager.instancesMap.has(mapKey)) {\n\t\t\tconst manager = new CommitChangedFilesManager(scheme, repo, commitSha);\n\t\t\tCommitChangedFilesManager.instancesMap.set(mapKey, manager);\n\t\t}\n\t\treturn CommitChangedFilesManager.instancesMap.get(mapKey)!;\n\t}\n\n\tconstructor(\n\t\tprivate _scheme: string,\n\t\tprivate _repo: string,\n\t\tprivate _commitSha: string,\n\t) {}\n\n\tgetList = reuseable(async (forceUpdate: boolean = false): Promise<ChangedFile[]> => {\n\t\tif (forceUpdate || !this._changedFilesList) {\n\t\t\tthis._currentPage = 1;\n\t\t\tthis._changedFilesList = [];\n\t\t\tawait this.loadMore();\n\t\t}\n\t\treturn this._changedFilesList;\n\t});\n\n\tloadMore = reuseable(async (): Promise<ChangedFile[]> => {\n\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\tconst changedFiles = await dataSource.provideCommitChangedFiles(this._repo, this._commitSha, {\n\t\t\tpageSize: this._pageSize,\n\t\t\tpage: this._currentPage,\n\t\t});\n\n\t\tthis._currentPage += 1;\n\t\tthis._hasMore = changedFiles.length === this._pageSize;\n\t\t(this._changedFilesList || (this._changedFilesList = [])).push(...changedFiles);\n\n\t\treturn changedFiles;\n\t});\n\n\thasMore = reuseable(async () => {\n\t\treturn this._hasMore;\n\t});\n\n\tasync setChangedFiles(files: ChangedFile[]) {\n\t\tthis._changedFilesList = files;\n\t\tthis._hasMore = false;\n\t}\n}\n\nexport class CommitManager {\n\tprivate static instancesMap = new Map<string, CommitManager>();\n\tprivate static _commitMap = new Map<string, Commit>(); // commitSha -> CommitWithDirection\n\t// if `previous` or `next` is null, it means this is an end node\n\tprivate static _relationMap = new Map<string, Map<string, { previous?: string | null; next?: string | null }>>();\n\n\tprivate _latestCommitSha: string | null = null;\n\tprivate _currentPage = 1;\n\tprivate _pageSize = 100;\n\n\tpublic static getInstance(scheme: string, repo: string, from: string, filePath: string) {\n\t\tconst mapKey = `${scheme} ${repo} ${from} ${filePath}`;\n\t\tif (!CommitManager.instancesMap.has(mapKey)) {\n\t\t\tCommitManager.instancesMap.set(mapKey, new CommitManager(scheme, repo, from, filePath));\n\t\t}\n\t\treturn CommitManager.instancesMap.get(mapKey)!;\n\t}\n\n\tprivate constructor(\n\t\tprivate _scheme: string,\n\t\tprivate _repo: string,\n\t\tprivate _from: string,\n\t\tprivate _filePath: string,\n\t) {}\n\n\t// link two commitSha\n\tprivate linkCommitShas(previousCommitSha: string | null, nextCommitSha: string | null) {\n\t\tif (!CommitManager._relationMap.has(this._filePath)) {\n\t\t\tCommitManager._relationMap.set(this._filePath, new Map());\n\t\t}\n\t\tconst relation = CommitManager._relationMap.get(this._filePath)!;\n\t\tif (previousCommitSha) {\n\t\t\t!relation.has(previousCommitSha) && relation.set(previousCommitSha, {});\n\t\t\trelation.get(previousCommitSha)!.next = nextCommitSha;\n\t\t}\n\t\tif (nextCommitSha) {\n\t\t\t!relation.has(nextCommitSha) && relation.set(nextCommitSha, {});\n\t\t\trelation.get(nextCommitSha)!.previous = previousCommitSha;\n\t\t}\n\t}\n\n\t// construct commit list with commit relations\n\tprivate resolveCommitList() {\n\t\tconst commitList: Commit[] = [];\n\t\tconst relation = CommitManager._relationMap.get(this._filePath);\n\t\tlet currentCommitSha: string | undefined | null = this._latestCommitSha;\n\t\twhile (currentCommitSha && CommitManager._commitMap.has(currentCommitSha)) {\n\t\t\tconst commit = CommitManager._commitMap.get(currentCommitSha)!;\n\t\t\tcommitList.push(commit);\n\t\t\tcurrentCommitSha = relation?.get(commit.sha)?.previous;\n\t\t}\n\t\treturn commitList;\n\t}\n\n\tgetList = reuseable(async (forceUpdate: boolean = false): Promise<Commit[]> => {\n\t\tconst hasMore = await this.hasMore();\n\t\tconst commitList = this.resolveCommitList();\n\t\tconst shouldLoadMore = hasMore && commitList.length < this._pageSize;\n\n\t\tif (forceUpdate || shouldLoadMore) {\n\t\t\tthis._currentPage = 1;\n\t\t\tthis._latestCommitSha = null;\n\t\t\tCommitManager._relationMap.set(this._filePath, new Map());\n\t\t\tawait this.loadMore();\n\t\t}\n\t\treturn this.resolveCommitList();\n\t});\n\n\tgetItem = reuseable(async (forceUpdate: boolean = false): Promise<Commit | null> => {\n\t\tif (forceUpdate || !CommitManager._commitMap.has(this._from)) {\n\t\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\t\tconst commit = await dataSource.provideCommit(this._repo, this._from);\n\n\t\t\tcommit && CommitManager._commitMap.set(this._from, commit);\n\t\t\tcommit && CommitManager._commitMap.set(commit.sha, commit);\n\t\t\tif (commit?.files) {\n\t\t\t\tconst manager = CommitChangedFilesManager.getInstance(this._scheme, this._repo, commit.sha);\n\t\t\t\tmanager.setChangedFiles(commit.files);\n\t\t\t}\n\t\t}\n\t\treturn CommitManager._commitMap.get(this._from)!;\n\t});\n\n\tloadMore = reuseable(async (): Promise<Commit[]> => {\n\t\tconst commitList = this.resolveCommitList();\n\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\tconst queryOptions = {\n\t\t\tpage: this._currentPage,\n\t\t\tpageSize: this._pageSize,\n\t\t\tfrom: this._from,\n\t\t\tpath: this._filePath,\n\t\t};\n\t\tconst commits = await dataSource.provideCommits(this._repo, queryOptions);\n\n\t\tif (this._currentPage === 1 && commits.length) {\n\t\t\tthis._latestCommitSha = commits[0].sha;\n\t\t\t// also map `this._from` to the first commit if currentPage is 1 and filePath is empty\n\t\t\t!this._filePath && CommitManager._commitMap.set(this._from, commits[0]);\n\t\t}\n\t\tcommits.forEach((commit) => {\n\t\t\tCommitManager._commitMap.set(commit.sha, commit);\n\t\t\t// directly set changed files if they are in response\n\t\t\tif (commit?.files) {\n\t\t\t\tconst manager = CommitChangedFilesManager.getInstance(this._scheme, this._repo, commit.sha);\n\t\t\t\tmanager.setChangedFiles(commit.files);\n\t\t\t}\n\t\t});\n\t\tif (this._currentPage > 1 && commitList.length && commits.length) {\n\t\t\tthis.linkCommitShas(commits[0].sha, commitList[commitList.length - 1].sha);\n\t\t}\n\t\tfor (let i = 1, len = commits.length; i < len; i++) {\n\t\t\tconst previousCommitSha = commits[i].sha;\n\t\t\tconst nextCommitSha = commits[i - 1].sha;\n\t\t\tthis.linkCommitShas(previousCommitSha, nextCommitSha);\n\t\t}\n\t\t// if has more commits\n\t\tconst hasMore = commits.length === this._pageSize;\n\t\tif (!hasMore) {\n\t\t\tconst latestCommit = commits.length ? commits[commits.length - 1] : commitList[commitList.length - 1];\n\t\t\tthis.linkCommitShas(null, latestCommit.sha);\n\t\t}\n\t\tthis._currentPage += 1;\n\t\treturn commits;\n\t});\n\n\thasMore = reuseable(async (): Promise<boolean> => {\n\t\tconst commitList = this.resolveCommitList();\n\t\tconst relation = CommitManager._relationMap.get(this._filePath);\n\t\tconst commitRelation = commitList.length ? relation?.get(commitList[commitList.length - 1].sha) : null;\n\t\treturn !commitRelation || commitRelation.previous !== null;\n\t});\n\n\tpublic getChangedFiles = reuseable(async (forceUpdate: boolean = false): Promise<ChangedFile[]> => {\n\t\tconst commit = await this.getItem();\n\t\tconst manager = commit ? CommitChangedFilesManager.getInstance(this._scheme, this._repo, commit.sha) : null;\n\t\treturn manager ? manager.getList(forceUpdate) : [];\n\t});\n\n\tpublic loadMoreChangedFiles = reuseable(async (): Promise<ChangedFile[]> => {\n\t\tconst commit = await this.getItem();\n\t\tconst manager = commit ? CommitChangedFilesManager.getInstance(this._scheme, this._repo, commit.sha) : null;\n\t\treturn manager ? manager.loadMore() : [];\n\t});\n\n\tpublic hasMoreChangedFiles = reuseable(async (): Promise<boolean> => {\n\t\tconst commit = await this.getItem();\n\t\tconst manager = commit ? CommitChangedFilesManager.getInstance(this._scheme, this._repo, commit.sha) : null;\n\t\treturn manager ? manager.hasMore() : false;\n\t});\n\n\t// get the lastest commit of `file with modifications`,\n\t// the commit of `this._from` could be newer than result\n\tpublic getLatestCommit = reuseable(async (): Promise<Commit | null> => {\n\t\tconst commit = this._latestCommitSha ? CommitManager._commitMap.get(this._latestCommitSha) : null;\n\t\treturn commit || (await this.loadMore())[0] || null;\n\t});\n\n\tpublic getPreviousCommit = reuseable(async (): Promise<Commit | null> => {\n\t\tconst commit = await this.getItem();\n\t\tconst commitRelation = commit ? CommitManager._relationMap.get(this._filePath)?.get(commit.sha) : null;\n\t\tif (!commitRelation || commitRelation.previous === undefined) {\n\t\t\treturn (await this.loadMore())[0] || null;\n\t\t}\n\t\treturn (commitRelation.previous ? CommitManager._commitMap.get(commitRelation.previous) : null) || null;\n\t});\n\n\tpublic getNextCommit = reuseable(async (): Promise<Commit | null> => {\n\t\tconst commit = await this.getItem();\n\t\tconst commitRelation = commit ? CommitManager._relationMap.get(this._filePath)?.get(commit.sha) : null;\n\t\tconst nextCommitSha = commitRelation ? commitRelation.next : null;\n\t\treturn (nextCommitSha ? CommitManager._commitMap.get(nextCommitSha) : null) || null;\n\t});\n}\n"
  },
  {
    "path": "extensions/github1s/src/repository/index.ts",
    "content": "/**\n * @file Current GitHub Repository\n * @author netcon\n */\n\nimport { adapterManager } from '@/adapters';\nimport { CommitManager } from './commit-manager';\nimport { CodeReviewManager } from './code-review-manager';\nimport { BranchTagManager } from './branch-tag-manager';\nimport { BlameRange } from '@/adapters/types';\n\nexport class Repository {\n\tprivate static instanceMap = new Map<string, Repository>();\n\n\tprivate _branchTagManager: BranchTagManager;\n\tprivate _codeReviewManager: CodeReviewManager;\n\tprivate _blameRangesCache: Map<string, BlameRange[]>;\n\n\tpublic static getInstance(scheme: string, repo: string) {\n\t\tconst mapKey = `${scheme} ${repo}`;\n\t\tif (!Repository.instanceMap.has(mapKey)) {\n\t\t\tRepository.instanceMap.set(mapKey, new Repository(scheme, repo));\n\t\t}\n\t\treturn Repository.instanceMap.get(mapKey)!;\n\t}\n\n\tprivate constructor(\n\t\tprivate _scheme: string,\n\t\tprivate _repo: string,\n\t) {\n\t\tthis._branchTagManager = BranchTagManager.getInstance(_scheme, _repo);\n\t\tthis._codeReviewManager = CodeReviewManager.getInstance(_scheme, _repo);\n\t\tthis._blameRangesCache = new Map<string, BlameRange[]>();\n\t}\n\n\tgetBranchList(...args: Parameters<BranchTagManager['getBranchList']>) {\n\t\treturn this._branchTagManager.getBranchList(...args);\n\t}\n\n\tgetBranchItem(...args: Parameters<BranchTagManager['getBranchItem']>) {\n\t\treturn this._branchTagManager.getBranchItem(...args);\n\t}\n\n\tloadMoreBranches(...args: Parameters<BranchTagManager['loadMoreBranches']>) {\n\t\treturn this._branchTagManager.loadMoreBranches(...args);\n\t}\n\n\thasMoreBranches(...args: Parameters<BranchTagManager['hasMoreBranches']>) {\n\t\treturn this._branchTagManager.hasMoreBranches(...args);\n\t}\n\n\tgetTagList(...args: Parameters<BranchTagManager['getTagList']>) {\n\t\treturn this._branchTagManager.getTagList(...args);\n\t}\n\n\tgetTagItem(...args: Parameters<BranchTagManager['getTagItem']>) {\n\t\treturn this._branchTagManager.getTagItem(...args);\n\t}\n\n\tloadMoreTags(...args: Parameters<BranchTagManager['loadMoreTags']>) {\n\t\treturn this._branchTagManager.loadMoreTags(...args);\n\t}\n\n\thasMoreTags(...args: Parameters<BranchTagManager['hasMoreTags']>) {\n\t\treturn this._branchTagManager.hasMoreTags(...args);\n\t}\n\n\tgetCommitList(ref: string = 'HEAD', filePath: string = '', forceUpdate: boolean = false) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, filePath).getList(forceUpdate);\n\t}\n\n\tgetCommitItem(ref: string, forceUpdate: boolean = false) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, '').getItem(forceUpdate);\n\t}\n\n\tloadMoreCommits(ref: string = 'HEAD', filePath: string = '') {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, filePath).loadMore();\n\t}\n\n\thasMoreCommits(ref: string = 'HEAD', filePath: string = '') {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, filePath).hasMore();\n\t}\n\n\tgetCommitChangedFiles(ref: string, forceUpdate: boolean = false) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, '').getChangedFiles(forceUpdate);\n\t}\n\n\tloadMoreCommitChangedFiles(ref: string) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, '').loadMoreChangedFiles();\n\t}\n\n\thasMoreCommitChangedFiles(ref: string) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, '').hasMoreChangedFiles();\n\t}\n\n\tgetFileLatestCommit(ref: string, filePath: string) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, filePath).getLatestCommit();\n\t}\n\n\tgetPreviousCommit(ref: string, filePath: string) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, filePath).getPreviousCommit();\n\t}\n\n\tgetNextCommit(ref: string, filePath: string) {\n\t\treturn CommitManager.getInstance(this._scheme, this._repo, ref, filePath).getNextCommit();\n\t}\n\n\tgetCodeReviewList(...args: Parameters<CodeReviewManager['getList']>) {\n\t\treturn this._codeReviewManager.getList(...args);\n\t}\n\n\tgetCodeReviewItem(...args: Parameters<CodeReviewManager['getItem']>) {\n\t\treturn this._codeReviewManager.getItem(...args);\n\t}\n\n\tloadMoreCodeReviews(...args: Parameters<CodeReviewManager['loadMore']>) {\n\t\treturn this._codeReviewManager.loadMore(...args);\n\t}\n\n\thasMoreCodeReviews(...args: Parameters<CodeReviewManager['hasMore']>) {\n\t\treturn this._codeReviewManager.hasMore(...args);\n\t}\n\n\tgetCodeReviewChangedFiles(...args: Parameters<CodeReviewManager['getChangedFiles']>) {\n\t\treturn this._codeReviewManager.getChangedFiles(...args);\n\t}\n\n\tloadMoreCodeReviewChangedFiles(...args: Parameters<CodeReviewManager['loadMoreChangedFiles']>) {\n\t\treturn this._codeReviewManager.loadMoreChangedFiles(...args);\n\t}\n\n\thasMoreCodeReviewChangedFiles(...args: Parameters<CodeReviewManager['hasMoreChangedFiles']>) {\n\t\treturn this._codeReviewManager.hasMoreChangedFiles(...args);\n\t}\n\n\tasync getFileBlameRanges(ref: string, path: string) {\n\t\tconst cacheKey = `${ref} ${path}`;\n\t\tif (!this._blameRangesCache.has(cacheKey)) {\n\t\t\tconst dataSource = await adapterManager.getAdapter(this._scheme).resolveDataSource();\n\t\t\tconst blameRanges = await dataSource.provideFileBlameRanges(this._repo, ref, path);\n\t\t\tthis._blameRangesCache.set(cacheKey, blameRanges);\n\t\t}\n\t\treturn this._blameRangesCache.get(cacheKey) || [];\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/router/events.ts",
    "content": "/**\n * @file Observable\n * @author netcon\n */\n\nexport class EventEmitter<T> {\n\tprivate _listeners: ((...args: T[]) => any)[] = [];\n\n\tpublic addListener(listener) {\n\t\tthis._listeners.push(listener);\n\t\treturn () => this.removeListener(listener);\n\t}\n\n\tpublic removeListener(listener) {\n\t\tconst index = this._listeners.indexOf(listener);\n\t\treturn index >= 0 && this._listeners.splice(index, 1);\n\t}\n\n\tpublic notifyListeners(...args) {\n\t\tthis._listeners.forEach((listener) => listener(...args));\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/router/index.ts",
    "content": "/**\n * @file GitHub url router (just like react-router)\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport { History, createMemoryHistory, parsePath, Action } from 'history';\nimport { RouterParser, RouterState } from '@/adapters/types';\nimport { Barrier } from '@/helpers/async';\nimport adapterManager from '@/adapters/manager';\nimport { EventEmitter } from './events';\n\nexport interface UrlManager {\n\thref: () => string | Promise<string>; // get href\n\tpush: (url: string) => void | Promise<void>;\n\treplace: (url: string) => void | Promise<void>;\n}\n\nexport class Router extends EventEmitter<RouterState> {\n\tprivate static instance: Router;\n\n\tprivate _state: RouterState | null = null;\n\tprivate _history: History | null = null;\n\tprivate _parser: RouterParser | null = null;\n\t// ensure router has been initialized\n\tprivate _barrier: Barrier = new Barrier();\n\tprivate _manager: UrlManager | null = null;\n\n\tpublic static getInstance() {\n\t\tif (Router.instance) {\n\t\t\treturn Router.instance;\n\t\t}\n\t\treturn (Router.instance = new Router());\n\t}\n\n\t// initialize the router with current url in browser\n\tasync initialize(urlManager: UrlManager) {\n\t\tthis._manager = urlManager;\n\t\tthis._parser = await adapterManager.getCurrentAdapter().resolveRouterParser();\n\t\tconst { path: pathname, query, fragment } = vscode.Uri.parse(await this._manager.href());\n\t\tconst path = pathname + (query ? `?${query}` : '') + (fragment ? `#${fragment}` : '');\n\n\t\tthis._state = await this._parser.parsePath(path);\n\t\tthis._history = createMemoryHistory({ initialEntries: [path] });\n\n\t\tthis._history.listen(async ({ action, location }) => {\n\t\t\tconst prevState = this._state;\n\t\t\tconst targetPath = `${location.pathname}${location.search}${location.hash}`;\n\t\t\tconst routerParser = await adapterManager.getCurrentAdapter().resolveRouterParser();\n\n\t\t\tthis._manager?.[action === Action.Push ? 'push' : 'replace'](targetPath);\n\t\t\tthis._state = await routerParser.parsePath(targetPath);\n\t\t\tsuper.notifyListeners(this._state, prevState);\n\t\t});\n\t\tthis._barrier.open();\n\t}\n\n\t// get the routerState for current url\n\tpublic async getState(): Promise<RouterState> {\n\t\tawait this._barrier.wait();\n\t\treturn this._state!;\n\t}\n\n\t// compute the file URI authority of current routerState\n\tpublic async getAuthority(): Promise<string> {\n\t\tconst state = await this.getState();\n\t\treturn `${state.repo}+${state.ref}`;\n\t}\n\n\tpublic async getHistory() {\n\t\tawait this._barrier.wait();\n\t\treturn this._history!;\n\t}\n\n\tpublic async getPath() {\n\t\tawait this._barrier.wait();\n\t\tconst { pathname, search, hash } = this._history!.location;\n\t\treturn `${pathname}${search}${hash}`;\n\t}\n\n\t// push the url with current history\n\tpublic async push(path: string) {\n\t\tawait this._barrier.wait();\n\t\tconst emptyState = { pathname: '', search: '', hash: '' };\n\t\treturn this._history!.push({ ...emptyState, ...parsePath(encodeURI(path)) });\n\t}\n\n\t// replace the url with current history\n\tpublic async replace(path: string) {\n\t\tawait this._barrier.wait();\n\t\tconst emptyState = { pathname: '', search: '', hash: '' };\n\t\treturn this._history!.replace({ ...emptyState, ...parsePath(encodeURI(path)) });\n\t}\n\n\tpublic async resolveParser(): Promise<RouterParser> {\n\t\tawait this._barrier.wait();\n\t\treturn this._parser!;\n\t}\n\n\tpublic async href(): Promise<string | undefined> {\n\t\treturn this._manager?.href();\n\t}\n}\n\nexport default Router.getInstance();\n"
  },
  {
    "path": "extensions/github1s/src/statusbar/checkout.ts",
    "content": "/**\n * @file checkout to another ref in status bar\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\n\nexport const updateCheckoutTo = (() => {\n\tconst checkoutItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);\n\tconst refreshItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 90);\n\treturn async () => {\n\t\tconst { repo, ref } = await router.getState();\n\n\t\tcheckoutItem.text = `$(git-branch) ${ref}`;\n\t\tcheckoutItem.tooltip = 'Checkout branch/tag/commit...';\n\t\tcheckoutItem.command = 'github1s.commands.checkoutTo';\n\t\trepo && checkoutItem.show();\n\n\t\trefreshItem.text = `$(refresh)`;\n\t\trefreshItem.tooltip = 'Refresh Repository';\n\t\trefreshItem.command = 'github1s.commands.refreshRepository';\n\t\trepo && refreshItem.show();\n\t};\n})();\n"
  },
  {
    "path": "extensions/github1s/src/statusbar/index.ts",
    "content": "/**\n * @file decorate footer\n * @author netcon\n */\n\nimport { updateCheckoutTo } from './checkout';\nimport { showSponsors } from './sponsors';\n\nexport const decorateStatusBar = () => {\n\tupdateCheckoutTo();\n\tshowSponsors();\n};\n"
  },
  {
    "path": "extensions/github1s/src/statusbar/sponsors.ts",
    "content": "/**\n * @file Show Sponsors In Status Bar\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { adapterManager } from '@/adapters';\nimport { PlatformName } from '@/adapters/types';\n\nconst resolveSourcegraphLink = async () => {\n\tconst { repo, ref } = await router.getState();\n\tswitch (adapterManager.getCurrentAdapter().platformName) {\n\t\tcase PlatformName.GitHub:\n\t\t\treturn `https://sourcegraph.com/github.com/${repo}@${ref}`;\n\t\tcase PlatformName.GitLab:\n\t\t\treturn `https://sourcegraph.com/gitlab.com/${repo}@${ref}`;\n\t\tcase PlatformName.Bitbucket:\n\t\t\treturn `https://sourcegraph.com/bitbucket.org/${repo}@${ref}`;\n\t\tdefault:\n\t\t\treturn 'https://sourcegraph.com';\n\t}\n};\n\nconst resolveSponsors = async () => {\n\treturn [\n\t\t{\n\t\t\tname: 'Sourcegraph',\n\t\t\tlink: await resolveSourcegraphLink(),\n\t\t\tdescription: 'Universal code search',\n\t\t},\n\t];\n};\n\nexport const showSponsors = async () => {\n\tconst titleItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);\n\ttitleItem.text = '  $(heart) Sponsors:';\n\ttitleItem.show();\n\n\t(await resolveSponsors()).forEach((sponsor) => {\n\t\tconst sponsorItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);\n\t\tsponsorItem.text = sponsor.name;\n\t\tsponsorItem.tooltip = sponsor.description;\n\t\tsponsorItem.command = {\n\t\t\ttitle: `Visit ${sponsor.name}`,\n\t\t\tcommand: 'vscode.open',\n\t\t\targuments: [vscode.Uri.parse(sponsor.link)],\n\t\t};\n\t\tsponsorItem.show();\n\t});\n};\n"
  },
  {
    "path": "extensions/github1s/src/views/code-review-list.ts",
    "content": "/**\n * @file Code Review List View\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport * as queryString from 'query-string';\nimport router from '@/router';\nimport { Barrier } from '@/helpers/async';\nimport { Repository } from '@/repository';\nimport { relativeTimeTo, toISOString } from '@/helpers/date';\nimport adapterManager from '@/adapters/manager';\nimport * as adapterTypes from '@/adapters/types';\nimport { getChangedFileDiffCommand, getCodeReviewChangedFiles } from '@/changes/files';\nimport { GitHub1sSourceControlDecorationProvider } from '@/providers/decorations/source-control';\n\nenum CodeReviewState {\n\tOPEN = 'open',\n\tCLOSED = 'closed',\n\tMERGED = 'merged',\n}\n\nconst getCodeReviewStatus = (codeReview: adapterTypes.CodeReview): CodeReviewState => {\n\t// current codeReview request is open\n\tif (codeReview.state === adapterTypes.CodeReviewState.Open) {\n\t\treturn CodeReviewState.OPEN;\n\t}\n\n\t// current codeReview request is merged\n\tif (codeReview.state === adapterTypes.CodeReviewState.Merged) {\n\t\treturn CodeReviewState.MERGED;\n\t}\n\n\t// current codeReview is closed\n\treturn CodeReviewState.CLOSED;\n};\n\nconst statusIconMap = {\n\t[CodeReviewState.OPEN]: '🟢',\n\t[CodeReviewState.CLOSED]: '🔴',\n\t[CodeReviewState.MERGED]: '🟣',\n};\n\nexport const getCodeReviewTreeItemLabel = (codeReview: adapterTypes.CodeReview) => {\n\tconst statusIcon = statusIconMap[getCodeReviewStatus(codeReview)];\n\treturn `${statusIcon} #${codeReview.id} ${codeReview.title.split(/[\\r\\n]/)[0]}`;\n};\n\nexport const getCodeReviewTreeItemDescription = (codeReview: adapterTypes.CodeReview) => {\n\tconst codeReviewStatus = getCodeReviewStatus(codeReview);\n\n\t// current codeReview request is open\n\tif (codeReviewStatus === CodeReviewState.OPEN) {\n\t\treturn `opened ${relativeTimeTo(codeReview.createTime)} by ${codeReview.creator}`;\n\t}\n\n\t// current codeReview request is merged\n\tif (codeReviewStatus === CodeReviewState.MERGED) {\n\t\treturn `by ${codeReview.creator} was merged ${relativeTimeTo(codeReview.mergeTime!)}`;\n\t}\n\n\t// current codeReview is closed\n\treturn `by ${codeReview.creator} was closed ${relativeTimeTo(codeReview.closeTime!)}`;\n};\n\nexport const getCodeReviewTreeItemTooltip = (codeReview: adapterTypes.CodeReview): string => {\n\tconst titleText = `#${codeReview.id} ${codeReview.title.split(/[\\r\\n]/)[0]}`;\n\tconst ISOTimeStr = codeReview.createTime ? toISOString(codeReview.createTime) : null;\n\tconst directionText = `${codeReview.target} ← ${codeReview.source}`;\n\tconst infoText = [codeReview.state, directionText].filter(Boolean).join(', ');\n\tconst detailText = [codeReview.creator, ISOTimeStr].filter(Boolean).join(', ');\n\treturn `${titleText}\\n(${infoText})\\n(${detailText})`;\n};\n\nexport interface CodeReviewTreeItem extends vscode.TreeItem {\n\tcodeReview: adapterTypes.CodeReview;\n}\n\nconst loadMoreCodeReviewsItem: vscode.TreeItem = {\n\tlabel: 'Load more',\n\ttooltip: 'Load more code reviews',\n\tcommand: {\n\t\ttitle: 'Load more code reviews',\n\t\tcommand: 'github1s.commands.load-more-code-reviews',\n\t\ttooltip: 'Load more code reviews',\n\t},\n};\n\nconst createLoadMoreChangedFilesItem = (codeReviewId: string): vscode.TreeItem => ({\n\tlabel: 'Load more',\n\ttooltip: 'Load more changed files',\n\tcommand: {\n\t\ttitle: 'Load more changed files',\n\t\tcommand: 'github1s.commands.load-more-code-review-changed-files',\n\t\ttooltip: 'Load more changed files',\n\t\targuments: [codeReviewId],\n\t},\n});\n\nexport class CodeReviewTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {\n\tpublic static viewType = 'github1s.views.codeReviewList';\n\n\tprivate _forceUpdate = false;\n\tprivate _loadingBarrier: Barrier | null = null;\n\tprivate _onDidChangeTreeData = new vscode.EventEmitter<void>();\n\treadonly onDidChangeTreeData = this._onDidChangeTreeData.event;\n\n\tpublic updateTree(forceUpdate = true) {\n\t\tthis._forceUpdate = forceUpdate;\n\t\tthis._onDidChangeTreeData.fire();\n\t}\n\n\tpublic async loadMoreCodeReviews() {\n\t\tif (!this._loadingBarrier || this._loadingBarrier.isOpen()) {\n\t\t\tthis._loadingBarrier = new Barrier(5000);\n\t\t\tthis.updateTree(false);\n\t\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\t\tconst { repo } = await router.getState();\n\t\t\tawait Repository.getInstance(scheme, repo).loadMoreCodeReviews();\n\t\t\tthis._loadingBarrier.open();\n\t\t}\n\t}\n\n\tpublic async loadMoreChangedFiles(codeReviewId: string) {\n\t\tif (!this._loadingBarrier || this._loadingBarrier.isOpen()) {\n\t\t\tthis._loadingBarrier = new Barrier(5000);\n\t\t\tthis.updateTree(false);\n\t\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\t\tconst { repo } = await router.getState();\n\t\t\tawait Repository.getInstance(scheme, repo).loadMoreCodeReviewChangedFiles(codeReviewId);\n\t\t\tthis._loadingBarrier.open();\n\t\t}\n\t}\n\n\tasync getCodeReviewItems(): Promise<vscode.TreeItem[]> {\n\t\tthis._loadingBarrier && (await this._loadingBarrier.wait());\n\t\tconst currentScheme = adapterManager.getCurrentScheme();\n\t\tconst { repo } = await router.getState();\n\t\tconst repository = Repository.getInstance(currentScheme, repo);\n\t\tconst codeReviews = await repository.getCodeReviewList(this._forceUpdate);\n\t\tconst codeReviewTreeItems = codeReviews.map((codeReview) => {\n\t\t\tconst label = getCodeReviewTreeItemLabel(codeReview);\n\t\t\tconst description = getCodeReviewTreeItemDescription(codeReview);\n\t\t\tconst tooltip = getCodeReviewTreeItemTooltip(codeReview);\n\t\t\tconst iconPath = vscode.Uri.parse(codeReview?.avatarUrl || '');\n\t\t\tconst contextValue = 'github1s:viewItems:codeReviewListItem';\n\n\t\t\treturn {\n\t\t\t\tcodeReview,\n\t\t\t\tlabel,\n\t\t\t\ticonPath,\n\t\t\t\tdescription,\n\t\t\t\ttooltip,\n\t\t\t\tcontextValue,\n\t\t\t\tresourceUri: vscode.Uri.parse('').with({\n\t\t\t\t\tscheme: GitHub1sSourceControlDecorationProvider.codeReviewSchema,\n\t\t\t\t\tquery: queryString.stringify({ id: codeReview.id }),\n\t\t\t\t}),\n\t\t\t\tcollapsibleState: vscode.TreeItemCollapsibleState.Collapsed,\n\t\t\t};\n\t\t});\n\t\tthis._forceUpdate = false;\n\t\tconst hasMore = await repository.hasMoreCodeReviews();\n\t\treturn hasMore ? [...codeReviewTreeItems, loadMoreCodeReviewsItem] : codeReviewTreeItems;\n\t}\n\n\tasync getCodeReviewFileItems(codeReview: adapterTypes.CodeReview): Promise<vscode.TreeItem[]> {\n\t\tthis._loadingBarrier && (await this._loadingBarrier.wait());\n\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\tconst { repo } = await router.getState();\n\t\tconst repository = Repository.getInstance(scheme, repo);\n\t\tconst _codeReview = await repository.getCodeReviewItem(codeReview.id);\n\t\tconst changedFiles = _codeReview ? await getCodeReviewChangedFiles(_codeReview) : [];\n\t\tconst changedFileItems = changedFiles.map((changedFile) => {\n\t\t\tconst filePath = changedFile.headFileUri.path;\n\t\t\tconst id = `${codeReview.id} ${filePath}`;\n\t\t\tconst command = getChangedFileDiffCommand(changedFile);\n\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tcommand,\n\t\t\t\tdescription: true,\n\t\t\t\tresourceUri: changedFile.headFileUri.with({\n\t\t\t\t\tquery: queryString.stringify({ changeStatus: changedFile.status }),\n\t\t\t\t}),\n\t\t\t\tcollapsibleState: vscode.TreeItemCollapsibleState.None,\n\t\t\t};\n\t\t});\n\n\t\tconst hasMore = await repository.hasMoreCodeReviewChangedFiles(codeReview.id);\n\t\tconst loadMoreChangedFilesItem = createLoadMoreChangedFilesItem(codeReview.id);\n\t\treturn hasMore ? [...changedFileItems, loadMoreChangedFilesItem] : changedFileItems;\n\t}\n\n\tgetTreeItem(element: vscode.TreeItem): vscode.TreeItem | Thenable<vscode.TreeItem> {\n\t\treturn element;\n\t}\n\n\tgetChildren(element?: vscode.TreeItem): vscode.ProviderResult<vscode.TreeItem[]> {\n\t\tif (!element) {\n\t\t\treturn this.getCodeReviewItems();\n\t\t}\n\t\tconst codeReview = (element as CodeReviewTreeItem)?.codeReview;\n\t\treturn codeReview ? this.getCodeReviewFileItems(codeReview) : [];\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/views/commit-list.ts",
    "content": "/**\n * @file GitHub Commit List View\n * @author netcon\n */\n\nimport * as vscode from 'vscode';\nimport router from '@/router';\nimport { Barrier } from '@/helpers/async';\nimport { Repository } from '@/repository';\nimport * as queryString from 'query-string';\nimport { relativeTimeTo, toISOString } from '@/helpers/date';\nimport adapterManager from '@/adapters/manager';\nimport * as adapterTypes from '@/adapters/types';\nimport { getChangedFileDiffCommand, getCommitChangedFiles } from '@/changes/files';\nimport { GitHub1sSourceControlDecorationProvider } from '@/providers/decorations/source-control';\n\nexport const getCommitTreeItemDescription = (commit: adapterTypes.Commit): string => {\n\tconst shortCommitSha = commit.sha.slice(0, 7);\n\tconst relativeTimeStr = commit.createTime ? relativeTimeTo(commit.createTime) : null;\n\treturn [shortCommitSha, commit.author, relativeTimeStr].filter(Boolean).join(', ');\n};\n\nexport const getCommitTreeItemTooltip = (commit: adapterTypes.Commit): string => {\n\tconst shortCommitSha = commit.sha.slice(0, 7);\n\tconst ISOTimeStr = commit.createTime ? toISOString(commit.createTime) : null;\n\tconst detailText = [shortCommitSha, commit.author, ISOTimeStr].filter(Boolean).join(', ');\n\treturn `${commit.message}\\n(${detailText})`;\n};\n\nexport interface CommitTreeItem extends vscode.TreeItem {\n\tcommit: adapterTypes.Commit;\n}\n\nexport class CommitTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {\n\tpublic static viewType = 'github1s.views.commitList';\n\n\tprotected _forceUpdate = false;\n\tprotected _loadingBarrier: Barrier | null = null;\n\tprotected _onDidChangeTreeData = new vscode.EventEmitter<void>();\n\treadonly onDidChangeTreeData = this._onDidChangeTreeData.event;\n\n\tprotected loadMoreCommitItem: vscode.TreeItem = {\n\t\tlabel: 'Load more',\n\t\ttooltip: 'Load more commits',\n\t\tcommand: {\n\t\t\ttitle: 'Load more commits',\n\t\t\tcommand: 'github1s.commands.loadMoreCommits',\n\t\t\ttooltip: 'Load more commits',\n\t\t},\n\t};\n\n\tprotected createLoadMoreChangedFilesItem = (commitSha: string): vscode.TreeItem => ({\n\t\tlabel: 'Load more',\n\t\ttooltip: 'Load more changed files',\n\t\tcommand: {\n\t\t\ttitle: 'Load more changed files',\n\t\t\tcommand: 'github1s.commands.loadMoreCommitChangedFiles',\n\t\t\ttooltip: 'Load more changed files',\n\t\t\targuments: [commitSha],\n\t\t},\n\t});\n\n\tasync resolveFilePath() {\n\t\treturn '';\n\t}\n\n\tpublic updateTree(forceUpdate = true) {\n\t\tthis._forceUpdate = forceUpdate;\n\t\tthis._onDidChangeTreeData.fire();\n\t}\n\n\tpublic async loadMoreCommits() {\n\t\tif (!this._loadingBarrier || this._loadingBarrier.isOpen()) {\n\t\t\tthis._loadingBarrier = new Barrier(5000);\n\t\t\tthis.updateTree(false);\n\t\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\t\tconst { repo, ref } = await router.getState();\n\t\t\tconst repository = Repository.getInstance(scheme, repo);\n\t\t\tawait repository.loadMoreCommits(ref, await this.resolveFilePath());\n\t\t\tthis._loadingBarrier.open();\n\t\t}\n\t}\n\n\tpublic async loadMoreChangedFiles(commitSha: string) {\n\t\tif (!this._loadingBarrier || this._loadingBarrier.isOpen()) {\n\t\t\tthis._loadingBarrier = new Barrier(5000);\n\t\t\tthis.updateTree(false);\n\t\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\t\tconst { repo } = await router.getState();\n\t\t\tawait Repository.getInstance(scheme, repo).loadMoreCommitChangedFiles(commitSha);\n\t\t\tthis._loadingBarrier.open();\n\t\t}\n\t}\n\n\tasync getCommitItems(): Promise<vscode.TreeItem[]> {\n\t\tthis._loadingBarrier && (await this._loadingBarrier.wait());\n\t\tconst filePath = await this.resolveFilePath();\n\t\tconst currentAdapter = adapterManager.getCurrentAdapter();\n\t\tconst { repo, ref } = await router.getState();\n\t\tconst repository = Repository.getInstance(currentAdapter.scheme, repo);\n\t\tconst repositoryCommits = await repository.getCommitList(ref, filePath, this._forceUpdate);\n\t\tconst commitTreeItems = repositoryCommits.map((commit) => {\n\t\t\tconst label = commit.message.split(/[\\r\\n]/)[0];\n\t\t\tconst description = getCommitTreeItemDescription(commit);\n\t\t\tconst tooltip = getCommitTreeItemTooltip(commit);\n\t\t\tconst iconPath = vscode.Uri.parse(commit.avatarUrl || '');\n\t\t\tconst contextValue = 'github1s:viewItems:commitListItem';\n\n\t\t\treturn {\n\t\t\t\tcommit,\n\t\t\t\tlabel,\n\t\t\t\ticonPath,\n\t\t\t\tdescription,\n\t\t\t\ttooltip,\n\t\t\t\tcontextValue,\n\t\t\t\tresourceUri: vscode.Uri.parse('').with({\n\t\t\t\t\tscheme: GitHub1sSourceControlDecorationProvider.commitSchema,\n\t\t\t\t\tquery: queryString.stringify({ sha: commit.sha }),\n\t\t\t\t}),\n\t\t\t\tcollapsibleState: vscode.TreeItemCollapsibleState.Collapsed,\n\t\t\t};\n\t\t});\n\t\tthis._forceUpdate = false;\n\t\tconst hasMore = await repository.hasMoreCommits(ref, filePath);\n\t\treturn hasMore ? [...commitTreeItems, this.loadMoreCommitItem] : commitTreeItems;\n\t}\n\n\tasync getCommitFileItems(commit: adapterTypes.Commit): Promise<vscode.TreeItem[]> {\n\t\tconst changedFiles = await getCommitChangedFiles(commit);\n\t\tconst changedFileItems = changedFiles.map((changedFile) => {\n\t\t\tconst filePath = changedFile.headFileUri.path;\n\t\t\tconst id = `${commit.sha} ${filePath}`;\n\t\t\tconst command = getChangedFileDiffCommand(changedFile);\n\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tcommand,\n\t\t\t\tdescription: true,\n\t\t\t\tresourceUri: changedFile.headFileUri.with({\n\t\t\t\t\tquery: queryString.stringify({ changeStatus: changedFile.status }),\n\t\t\t\t}),\n\t\t\t\tcollapsibleState: vscode.TreeItemCollapsibleState.None,\n\t\t\t};\n\t\t});\n\t\tconst scheme = adapterManager.getCurrentScheme();\n\t\tconst { repo } = await router.getState();\n\t\tconst repository = Repository.getInstance(scheme, repo);\n\t\tconst hasMore = await repository.hasMoreCommitChangedFiles(commit.sha);\n\t\tconst loadMoreChangedFilesItem = this.createLoadMoreChangedFilesItem(commit.sha);\n\t\treturn hasMore ? [...changedFileItems, loadMoreChangedFilesItem] : changedFileItems;\n\t}\n\n\tgetTreeItem(element: vscode.TreeItem): vscode.TreeItem | Thenable<vscode.TreeItem> {\n\t\treturn element;\n\t}\n\n\tgetChildren(element?: vscode.TreeItem): vscode.ProviderResult<vscode.TreeItem[]> {\n\t\tif (!element) {\n\t\t\treturn this.getCommitItems();\n\t\t}\n\t\tconst commit = (element as CommitTreeItem)?.commit;\n\t\treturn commit ? this.getCommitFileItems(commit) : [];\n\t}\n}\n\nexport class FileHistoryTreeDataProvider extends CommitTreeDataProvider {\n\tpublic static viewType = 'github1s.views.fileHistory';\n\n\tprotected loadMoreCommitItem: vscode.TreeItem = {\n\t\tlabel: 'Load more',\n\t\ttooltip: 'Load more commits',\n\t\tcommand: {\n\t\t\ttitle: 'Load more commits',\n\t\t\tcommand: 'github1s.commands.loadMoreFileHistoryCommits',\n\t\t\ttooltip: 'Load more commits',\n\t\t},\n\t};\n\n\tprotected createLoadMoreChangedFilesItem = (commitSha: string): vscode.TreeItem => ({\n\t\tlabel: 'Load more',\n\t\ttooltip: 'Load more changed files',\n\t\tcommand: {\n\t\t\ttitle: 'Load more changed files',\n\t\t\tcommand: 'github1s.commands.loadMoreFileHistoryCommitChangedFiles',\n\t\t\ttooltip: 'Load more changed files',\n\t\t\targuments: [commitSha],\n\t\t},\n\t});\n\n\tasync resolveFilePath() {\n\t\tconst activeDocumentUri = vscode.window.activeTextEditor?.document?.uri;\n\t\tconst currentScheme = adapterManager.getCurrentScheme();\n\t\treturn activeDocumentUri?.scheme === currentScheme ? activeDocumentUri.path.slice(1) : '';\n\t}\n\n\tasync getCommitItems() {\n\t\tif (!(await this.resolveFilePath())) {\n\t\t\treturn [];\n\t\t}\n\t\treturn super.getCommitItems();\n\t}\n}\n"
  },
  {
    "path": "extensions/github1s/src/views/index.ts",
    "content": "/**\n * @file register views\n */\n\nimport * as vscode from 'vscode';\nimport { adapterManager } from '@/adapters';\nimport { CodeReviewType } from '@/adapters/types';\nimport { getExtensionContext } from '@/helpers/context';\nimport { CodeReviewTreeDataProvider } from './code-review-list';\nimport { CommitTreeDataProvider, FileHistoryTreeDataProvider } from './commit-list';\n\nexport const fileHistoryTreeDataProvider = new FileHistoryTreeDataProvider();\nexport const commitTreeDataProvider = new CommitTreeDataProvider();\nexport const codeReviewRequestTreeDataProvider = new CodeReviewTreeDataProvider();\n\nexport const codeReviewViewTitle = {\n\t[CodeReviewType.PullRequest]: 'Pull Requests',\n\t[CodeReviewType.MergeRequest]: 'Merge Requests',\n\t[CodeReviewType.ChangeRequest]: 'Change Requests',\n\t[CodeReviewType.CodeReview]: 'Code Reviews',\n};\n\nexport const registerCustomViews = () => {\n\tconst context = getExtensionContext();\n\n\t// register code review view which is in source control panel\n\tconst codeReviewTreeView = vscode.window.createTreeView(CodeReviewTreeDataProvider.viewType, {\n\t\ttreeDataProvider: codeReviewRequestTreeDataProvider,\n\t});\n\t// set code view list view title according code review type\n\tconst codeReviewType = adapterManager.getCurrentAdapter().codeReviewType || CodeReviewType.CodeReview;\n\tcodeReviewTreeView.title = codeReviewViewTitle[codeReviewType];\n\n\tcontext.subscriptions.push(\n\t\t// register commit view which is in source control panel\n\t\tvscode.window.registerTreeDataProvider(FileHistoryTreeDataProvider.viewType, fileHistoryTreeDataProvider),\n\t\tvscode.window.registerTreeDataProvider(CommitTreeDataProvider.viewType, commitTreeDataProvider),\n\t);\n};\n"
  },
  {
    "path": "extensions/github1s/src/vscode.proposed.d.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/**\n * This is the place for API experiments and proposals.\n * These API are NOT stable and subject to change. They are only available in the Insiders\n * distribution and CANNOT be used in published extensions.\n *\n * To test these API in local environment:\n * - Use Insiders release of VS Code.\n * - Add `\"enableProposedApi\": true` to your package.json.\n * - Copy this file to your project.\n */\n\ndeclare module 'vscode' {\n\t// #region auth provider: https://github.com/microsoft/vscode/issues/88309\n\n\t/**\n\t * An [event](#Event) which fires when an [AuthenticationProvider](#AuthenticationProvider) is added or removed.\n\t */\n\texport interface AuthenticationProvidersChangeEvent {\n\t\t/**\n\t\t * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been added.\n\t\t */\n\t\treadonly added: ReadonlyArray<AuthenticationProviderInformation>;\n\n\t\t/**\n\t\t * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been removed.\n\t\t */\n\t\treadonly removed: ReadonlyArray<AuthenticationProviderInformation>;\n\t}\n\n\t/**\n\t * An [event](#Event) which fires when an [AuthenticationSession](#AuthenticationSession) is added, removed, or changed.\n\t */\n\texport interface AuthenticationProviderAuthenticationSessionsChangeEvent {\n\t\t/**\n\t\t * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been added.\n\t\t */\n\t\treadonly added: ReadonlyArray<string>;\n\n\t\t/**\n\t\t * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been removed.\n\t\t */\n\t\treadonly removed: ReadonlyArray<string>;\n\n\t\t/**\n\t\t * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been changed.\n\t\t */\n\t\treadonly changed: ReadonlyArray<string>;\n\t}\n\n\t/**\n\t * **WARNING** When writing an AuthenticationProvider, `id` should be treated as part of your extension's\n\t * API, changing it is a breaking change for all extensions relying on the provider. The id is\n\t * treated case-sensitively.\n\t */\n\texport interface AuthenticationProvider {\n\t\t/**\n\t\t * Used as an identifier for extensions trying to work with a particular\n\t\t * provider: 'microsoft', 'github', etc. id must be unique, registering\n\t\t * another provider with the same id will fail.\n\t\t */\n\t\treadonly id: string;\n\n\t\t/**\n\t\t * The human-readable name of the provider.\n\t\t */\n\t\treadonly label: string;\n\n\t\t/**\n\t\t * Whether it is possible to be signed into multiple accounts at once with this provider\n\t\t */\n\t\treadonly supportsMultipleAccounts: boolean;\n\n\t\t/**\n\t\t * An [event](#Event) which fires when the array of sessions has changed, or data\n\t\t * within a session has changed.\n\t\t */\n\t\treadonly onDidChangeSessions: Event<AuthenticationProviderAuthenticationSessionsChangeEvent>;\n\n\t\t/**\n\t\t * Returns an array of current sessions.\n\t\t */\n\t\tgetSessions(): Thenable<ReadonlyArray<AuthenticationSession>>;\n\n\t\t/**\n\t\t * Prompts a user to login.\n\t\t */\n\t\tlogin(scopes: string[]): Thenable<AuthenticationSession>;\n\n\t\t/**\n\t\t * Removes the session corresponding to session id.\n\t\t * @param sessionId The session id to log out of\n\t\t */\n\t\tlogout(sessionId: string): Thenable<void>;\n\t}\n\n\texport namespace authentication {\n\t\t/**\n\t\t * Register an authentication provider.\n\t\t *\n\t\t * There can only be one provider per id and an error is being thrown when an id\n\t\t * has already been used by another provider.\n\t\t *\n\t\t * @param provider The authentication provider provider.\n\t\t * @return A [disposable](#Disposable) that unregisters this provider when being disposed.\n\t\t */\n\t\texport function registerAuthenticationProvider(provider: AuthenticationProvider): Disposable;\n\n\t\t/**\n\t\t * @deprecated - getSession should now trigger extension activation.\n\t\t * Fires with the provider id that was registered or unregistered.\n\t\t */\n\t\texport const onDidChangeAuthenticationProviders: Event<AuthenticationProvidersChangeEvent>;\n\n\t\t/**\n\t\t * @deprecated\n\t\t * The ids of the currently registered authentication providers.\n\t\t * @returns An array of the ids of authentication providers that are currently registered.\n\t\t */\n\t\texport function getProviderIds(): Thenable<ReadonlyArray<string>>;\n\n\t\t/**\n\t\t * @deprecated\n\t\t * An array of the ids of authentication providers that are currently registered.\n\t\t */\n\t\texport const providerIds: ReadonlyArray<string>;\n\n\t\t/**\n\t\t * An array of the information of authentication providers that are currently registered.\n\t\t */\n\t\texport const providers: ReadonlyArray<AuthenticationProviderInformation>;\n\n\t\t/**\n\t\t * @deprecated\n\t\t * Logout of a specific session.\n\t\t * @param providerId The id of the provider to use\n\t\t * @param sessionId The session id to remove\n\t\t * provider\n\t\t */\n\t\texport function logout(providerId: string, sessionId: string): Thenable<void>;\n\n\t\t/**\n\t\t * Retrieve a password that was stored with key. Returns undefined if there\n\t\t * is no password matching that key.\n\t\t * @param key The key the password was stored under.\n\t\t */\n\t\texport function getPassword(key: string): Thenable<string | undefined>;\n\n\t\t/**\n\t\t * Store a password under a given key.\n\t\t * @param key The key to store the password under\n\t\t * @param value The password\n\t\t */\n\t\texport function setPassword(key: string, value: string): Thenable<void>;\n\n\t\t/**\n\t\t * Remove a password from storage.\n\t\t * @param key The key the password was stored under.\n\t\t */\n\t\texport function deletePassword(key: string): Thenable<void>;\n\n\t\t/**\n\t\t * Fires when a password is set or deleted.\n\t\t */\n\t\texport const onDidChangePassword: Event<void>;\n\t}\n\n\t//#endregion\n\n\t//#region @alexdima - resolvers\n\n\texport interface RemoteAuthorityResolverContext {\n\t\tresolveAttempt: number;\n\t}\n\n\texport class ResolvedAuthority {\n\t\treadonly host: string;\n\t\treadonly port: number;\n\t\treadonly connectionToken: string | undefined;\n\n\t\tconstructor(host: string, port: number, connectionToken?: string);\n\t}\n\n\texport interface ResolvedOptions {\n\t\textensionHostEnv?: { [key: string]: string | null };\n\t}\n\n\texport interface TunnelOptions {\n\t\tremoteAddress: { port: number; host: string };\n\t\t// The desired local port. If this port can't be used, then another will be chosen.\n\t\tlocalAddressPort?: number;\n\t\tlabel?: string;\n\t}\n\n\texport interface TunnelDescription {\n\t\tremoteAddress: { port: number; host: string };\n\t\t//The complete local address(ex. localhost:1234)\n\t\tlocalAddress: { port: number; host: string } | string;\n\t}\n\n\texport interface Tunnel extends TunnelDescription {\n\t\t// Implementers of Tunnel should fire onDidDispose when dispose is called.\n\t\tonDidDispose: Event<void>;\n\t\tdispose(): void;\n\t}\n\n\t/**\n\t * Used as part of the ResolverResult if the extension has any candidate,\n\t * published, or forwarded ports.\n\t */\n\texport interface TunnelInformation {\n\t\t/**\n\t\t * Tunnels that are detected by the extension. The remotePort is used for display purposes.\n\t\t * The localAddress should be the complete local address (ex. localhost:1234) for connecting to the port. Tunnels provided through\n\t\t * detected are read-only from the forwarded ports UI.\n\t\t */\n\t\tenvironmentTunnels?: TunnelDescription[];\n\t}\n\n\texport interface TunnelCreationOptions {\n\t\t/**\n\t\t * True when the local operating system will require elevation to use the requested local port.\n\t\t */\n\t\televationRequired?: boolean;\n\t}\n\n\texport type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation;\n\n\texport class RemoteAuthorityResolverError extends Error {\n\t\tstatic NotAvailable(message?: string, handled?: boolean): RemoteAuthorityResolverError;\n\t\tstatic TemporarilyNotAvailable(message?: string): RemoteAuthorityResolverError;\n\n\t\tconstructor(message?: string);\n\t}\n\n\texport interface RemoteAuthorityResolver {\n\t\tresolve(authority: string, context: RemoteAuthorityResolverContext): ResolverResult | Thenable<ResolverResult>;\n\t\t/**\n\t\t * Can be optionally implemented if the extension can forward ports better than the core.\n\t\t * When not implemented, the core will use its default forwarding logic.\n\t\t * When implemented, the core will use this to forward ports.\n\t\t *\n\t\t * To enable the \"Change Local Port\" action on forwarded ports, make sure to set the `localAddress` of\n\t\t * the returned `Tunnel` to a `{ port: number, host: string; }` and not a string.\n\t\t */\n\t\ttunnelFactory?: (\n\t\t\ttunnelOptions: TunnelOptions,\n\t\t\ttunnelCreationOptions: TunnelCreationOptions\n\t\t) => Thenable<Tunnel> | undefined;\n\n\t\t/**\n\t\t * Provides filtering for candidate ports.\n\t\t */\n\t\tshowCandidatePort?: (host: string, port: number, detail: string) => Thenable<boolean>;\n\t}\n\n\texport namespace workspace {\n\t\t/**\n\t\t * Forwards a port. If the current resolver implements RemoteAuthorityResolver:forwardPort then that will be used to make the tunnel.\n\t\t * By default, openTunnel only support localhost; however, RemoteAuthorityResolver:tunnelFactory can be used to support other ips.\n\t\t *\n\t\t * @throws When run in an environment without a remote.\n\t\t *\n\t\t * @param tunnelOptions The `localPort` is a suggestion only. If that port is not available another will be chosen.\n\t\t */\n\t\texport function openTunnel(tunnelOptions: TunnelOptions): Thenable<Tunnel>;\n\n\t\t/**\n\t\t * Gets an array of the currently available tunnels. This does not include environment tunnels, only tunnels that have been created by the user.\n\t\t * Note that these are of type TunnelDescription and cannot be disposed.\n\t\t */\n\t\texport let tunnels: Thenable<TunnelDescription[]>;\n\n\t\t/**\n\t\t * Fired when the list of tunnels has changed.\n\t\t */\n\t\texport const onDidChangeTunnels: Event<void>;\n\t}\n\n\texport interface ResourceLabelFormatter {\n\t\tscheme: string;\n\t\tauthority?: string;\n\t\tformatting: ResourceLabelFormatting;\n\t}\n\n\texport interface ResourceLabelFormatting {\n\t\tlabel: string; // myLabel:/${path}\n\t\t// For historic reasons we use an or string here. Once we finalize this API we should start using enums instead and adopt it in extensions.\n\t\t//// eslint-disable-next-line vscode-dts-literal-or-types\n\t\tseparator: '/' | '\\\\' | '';\n\t\ttildify?: boolean;\n\t\tnormalizeDriveLetter?: boolean;\n\t\tworkspaceSuffix?: string;\n\t\tauthorityPrefix?: string;\n\t\tstripPathStartingSeparator?: boolean;\n\t}\n\n\texport namespace workspace {\n\t\texport function registerRemoteAuthorityResolver(\n\t\t\tauthorityPrefix: string,\n\t\t\tresolver: RemoteAuthorityResolver\n\t\t): Disposable;\n\t\texport function registerResourceLabelFormatter(formatter: ResourceLabelFormatter): Disposable;\n\t}\n\n\t//#endregion\n\n\t//#region editor insets: https://github.com/microsoft/vscode/issues/85682\n\n\texport interface WebviewEditorInset {\n\t\treadonly editor: TextEditor;\n\t\treadonly line: number;\n\t\treadonly height: number;\n\t\treadonly webview: Webview;\n\t\treadonly onDidDispose: Event<void>;\n\t\tdispose(): void;\n\t}\n\n\texport namespace window {\n\t\texport function createWebviewTextEditorInset(\n\t\t\teditor: TextEditor,\n\t\t\tline: number,\n\t\t\theight: number,\n\t\t\toptions?: WebviewOptions\n\t\t): WebviewEditorInset;\n\t}\n\n\t//#endregion\n\n\t//#region read/write in chunks: https://github.com/microsoft/vscode/issues/84515\n\n\texport interface FileSystemProvider {\n\t\topen?(resource: Uri, options: { create: boolean }): number | Thenable<number>;\n\t\tclose?(fd: number): void | Thenable<void>;\n\t\tread?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable<number>;\n\t\twrite?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable<number>;\n\t}\n\n\t//#endregion\n\n\t//#region TextSearchProvider: https://github.com/microsoft/vscode/issues/59921\n\n\t/**\n\t * The parameters of a query for text search.\n\t */\n\texport interface TextSearchQuery {\n\t\t/**\n\t\t * The text pattern to search for.\n\t\t */\n\t\tpattern: string;\n\n\t\t/**\n\t\t * Whether or not `pattern` should match multiple lines of text.\n\t\t */\n\t\tisMultiline?: boolean;\n\n\t\t/**\n\t\t * Whether or not `pattern` should be interpreted as a regular expression.\n\t\t */\n\t\tisRegExp?: boolean;\n\n\t\t/**\n\t\t * Whether or not the search should be case-sensitive.\n\t\t */\n\t\tisCaseSensitive?: boolean;\n\n\t\t/**\n\t\t * Whether or not to search for whole word matches only.\n\t\t */\n\t\tisWordMatch?: boolean;\n\t}\n\n\t/**\n\t * A file glob pattern to match file paths against.\n\t * TODO@roblourens merge this with the GlobPattern docs/definition in vscode.d.ts.\n\t * @see [GlobPattern](#GlobPattern)\n\t */\n\texport type GlobString = string;\n\n\t/**\n\t * Options common to file and text search\n\t */\n\texport interface SearchOptions {\n\t\t/**\n\t\t * The root folder to search within.\n\t\t */\n\t\tfolder: Uri;\n\n\t\t/**\n\t\t * Files that match an `includes` glob pattern should be included in the search.\n\t\t */\n\t\tincludes: GlobString[];\n\n\t\t/**\n\t\t * Files that match an `excludes` glob pattern should be excluded from the search.\n\t\t */\n\t\texcludes: GlobString[];\n\n\t\t/**\n\t\t * Whether external files that exclude files, like .gitignore, should be respected.\n\t\t * See the vscode setting `\"search.useIgnoreFiles\"`.\n\t\t */\n\t\tuseIgnoreFiles: boolean;\n\n\t\t/**\n\t\t * Whether symlinks should be followed while searching.\n\t\t * See the vscode setting `\"search.followSymlinks\"`.\n\t\t */\n\t\tfollowSymlinks: boolean;\n\n\t\t/**\n\t\t * Whether global files that exclude files, like .gitignore, should be respected.\n\t\t * See the vscode setting `\"search.useGlobalIgnoreFiles\"`.\n\t\t */\n\t\tuseGlobalIgnoreFiles: boolean;\n\t}\n\n\t/**\n\t * Options to specify the size of the result text preview.\n\t * These options don't affect the size of the match itself, just the amount of preview text.\n\t */\n\texport interface TextSearchPreviewOptions {\n\t\t/**\n\t\t * The maximum number of lines in the preview.\n\t\t * Only search providers that support multiline search will ever return more than one line in the match.\n\t\t */\n\t\tmatchLines: number;\n\n\t\t/**\n\t\t * The maximum number of characters included per line.\n\t\t */\n\t\tcharsPerLine: number;\n\t}\n\n\t/**\n\t * Options that apply to text search.\n\t */\n\texport interface TextSearchOptions extends SearchOptions {\n\t\t/**\n\t\t * The maximum number of results to be returned.\n\t\t */\n\t\tmaxResults: number;\n\n\t\t/**\n\t\t * Options to specify the size of the result text preview.\n\t\t */\n\t\tpreviewOptions?: TextSearchPreviewOptions;\n\n\t\t/**\n\t\t * Exclude files larger than `maxFileSize` in bytes.\n\t\t */\n\t\tmaxFileSize?: number;\n\n\t\t/**\n\t\t * Interpret files using this encoding.\n\t\t * See the vscode setting `\"files.encoding\"`\n\t\t */\n\t\tencoding?: string;\n\n\t\t/**\n\t\t * Number of lines of context to include before each match.\n\t\t */\n\t\tbeforeContext?: number;\n\n\t\t/**\n\t\t * Number of lines of context to include after each match.\n\t\t */\n\t\tafterContext?: number;\n\t}\n\n\t/**\n\t * Information collected when text search is complete.\n\t */\n\texport interface TextSearchComplete {\n\t\t/**\n\t\t * Whether the search hit the limit on the maximum number of search results.\n\t\t * `maxResults` on [`TextSearchOptions`](#TextSearchOptions) specifies the max number of results.\n\t\t * - If exactly that number of matches exist, this should be false.\n\t\t * - If `maxResults` matches are returned and more exist, this should be true.\n\t\t * - If search hits an internal limit which is less than `maxResults`, this should be true.\n\t\t */\n\t\tlimitHit?: boolean;\n\t}\n\n\t/**\n\t * A preview of the text result.\n\t */\n\texport interface TextSearchMatchPreview {\n\t\t/**\n\t\t * The matching lines of text, or a portion of the matching line that contains the match.\n\t\t */\n\t\ttext: string;\n\n\t\t/**\n\t\t * The Range within `text` corresponding to the text of the match.\n\t\t * The number of matches must match the TextSearchMatch's range property.\n\t\t */\n\t\tmatches: Range | Range[];\n\t}\n\n\t/**\n\t * A match from a text search\n\t */\n\texport interface TextSearchMatch {\n\t\t/**\n\t\t * The uri for the matching document.\n\t\t */\n\t\turi: Uri;\n\n\t\t/**\n\t\t * The range of the match within the document, or multiple ranges for multiple matches.\n\t\t */\n\t\tranges: Range | Range[];\n\n\t\t/**\n\t\t * A preview of the text match.\n\t\t */\n\t\tpreview: TextSearchMatchPreview;\n\t}\n\n\t/**\n\t * A line of context surrounding a TextSearchMatch.\n\t */\n\texport interface TextSearchContext {\n\t\t/**\n\t\t * The uri for the matching document.\n\t\t */\n\t\turi: Uri;\n\n\t\t/**\n\t\t * One line of text.\n\t\t * previewOptions.charsPerLine applies to this\n\t\t */\n\t\ttext: string;\n\n\t\t/**\n\t\t * The line number of this line of context.\n\t\t */\n\t\tlineNumber: number;\n\t}\n\n\texport type TextSearchResult = TextSearchMatch | TextSearchContext;\n\n\t/**\n\t * A TextSearchProvider provides search results for text results inside files in the workspace.\n\t */\n\texport interface TextSearchProvider {\n\t\t/**\n\t\t * Provide results that match the given text pattern.\n\t\t * @param query The parameters for this query.\n\t\t * @param options A set of options to consider while searching.\n\t\t * @param progress A progress callback that must be invoked for all results.\n\t\t * @param token A cancellation token.\n\t\t */\n\t\tprovideTextSearchResults(\n\t\t\tquery: TextSearchQuery,\n\t\t\toptions: TextSearchOptions,\n\t\t\tprogress: Progress<TextSearchResult>,\n\t\t\ttoken: CancellationToken\n\t\t): ProviderResult<TextSearchComplete>;\n\t}\n\n\t//#endregion\n\n\t//#region FileSearchProvider: https://github.com/microsoft/vscode/issues/73524\n\n\t/**\n\t * The parameters of a query for file search.\n\t */\n\texport interface FileSearchQuery {\n\t\t/**\n\t\t * The search pattern to match against file paths.\n\t\t */\n\t\tpattern: string;\n\t}\n\n\t/**\n\t * Options that apply to file search.\n\t */\n\texport interface FileSearchOptions extends SearchOptions {\n\t\t/**\n\t\t * The maximum number of results to be returned.\n\t\t */\n\t\tmaxResults?: number;\n\n\t\t/**\n\t\t * A CancellationToken that represents the session for this search query. If the provider chooses to, this object can be used as the key for a cache,\n\t\t * and searches with the same session object can search the same cache. When the token is cancelled, the session is complete and the cache can be cleared.\n\t\t */\n\t\tsession?: CancellationToken;\n\t}\n\n\t/**\n\t * A FileSearchProvider provides search results for files in the given folder that match a query string. It can be invoked by quickopen or other extensions.\n\t *\n\t * A FileSearchProvider is the more powerful of two ways to implement file search in VS Code. Use a FileSearchProvider if you wish to search within a folder for\n\t * all files that match the user's query.\n\t *\n\t * The FileSearchProvider will be invoked on every keypress in quickopen. When `workspace.findFiles` is called, it will be invoked with an empty query string,\n\t * and in that case, every file in the folder should be returned.\n\t */\n\texport interface FileSearchProvider {\n\t\t/**\n\t\t * Provide the set of files that match a certain file path pattern.\n\t\t * @param query The parameters for this query.\n\t\t * @param options A set of options to consider while searching files.\n\t\t * @param token A cancellation token.\n\t\t */\n\t\tprovideFileSearchResults(\n\t\t\tquery: FileSearchQuery,\n\t\t\toptions: FileSearchOptions,\n\t\t\ttoken: CancellationToken\n\t\t): ProviderResult<Uri[]>;\n\t}\n\n\texport namespace workspace {\n\t\t/**\n\t\t * Register a search provider.\n\t\t *\n\t\t * Only one provider can be registered per scheme.\n\t\t *\n\t\t * @param scheme The provider will be invoked for workspace folders that have this file scheme.\n\t\t * @param provider The provider.\n\t\t * @return A [disposable](#Disposable) that unregisters this provider when being disposed.\n\t\t */\n\t\texport function registerFileSearchProvider(scheme: string, provider: FileSearchProvider): Disposable;\n\n\t\t/**\n\t\t * Register a text search provider.\n\t\t *\n\t\t * Only one provider can be registered per scheme.\n\t\t *\n\t\t * @param scheme The provider will be invoked for workspace folders that have this file scheme.\n\t\t * @param provider The provider.\n\t\t * @return A [disposable](#Disposable) that unregisters this provider when being disposed.\n\t\t */\n\t\texport function registerTextSearchProvider(scheme: string, provider: TextSearchProvider): Disposable;\n\t}\n\n\t//#endregion\n\n\t//#region findTextInFiles: https://github.com/microsoft/vscode/issues/59924\n\n\t/**\n\t * Options that can be set on a findTextInFiles search.\n\t */\n\texport interface FindTextInFilesOptions {\n\t\t/**\n\t\t * A [glob pattern](#GlobPattern) that defines the files to search for. The glob pattern\n\t\t * will be matched against the file paths of files relative to their workspace. Use a [relative pattern](#RelativePattern)\n\t\t * to restrict the search results to a [workspace folder](#WorkspaceFolder).\n\t\t */\n\t\tinclude?: GlobPattern;\n\n\t\t/**\n\t\t * A [glob pattern](#GlobPattern) that defines files and folders to exclude. The glob pattern\n\t\t * will be matched against the file paths of resulting matches relative to their workspace. When `undefined`, default excludes will\n\t\t * apply.\n\t\t */\n\t\texclude?: GlobPattern;\n\n\t\t/**\n\t\t * Whether to use the default and user-configured excludes. Defaults to true.\n\t\t */\n\t\tuseDefaultExcludes?: boolean;\n\n\t\t/**\n\t\t * The maximum number of results to search for\n\t\t */\n\t\tmaxResults?: number;\n\n\t\t/**\n\t\t * Whether external files that exclude files, like .gitignore, should be respected.\n\t\t * See the vscode setting `\"search.useIgnoreFiles\"`.\n\t\t */\n\t\tuseIgnoreFiles?: boolean;\n\n\t\t/**\n\t\t * Whether global files that exclude files, like .gitignore, should be respected.\n\t\t * See the vscode setting `\"search.useGlobalIgnoreFiles\"`.\n\t\t */\n\t\tuseGlobalIgnoreFiles?: boolean;\n\n\t\t/**\n\t\t * Whether symlinks should be followed while searching.\n\t\t * See the vscode setting `\"search.followSymlinks\"`.\n\t\t */\n\t\tfollowSymlinks?: boolean;\n\n\t\t/**\n\t\t * Interpret files using this encoding.\n\t\t * See the vscode setting `\"files.encoding\"`\n\t\t */\n\t\tencoding?: string;\n\n\t\t/**\n\t\t * Options to specify the size of the result text preview.\n\t\t */\n\t\tpreviewOptions?: TextSearchPreviewOptions;\n\n\t\t/**\n\t\t * Number of lines of context to include before each match.\n\t\t */\n\t\tbeforeContext?: number;\n\n\t\t/**\n\t\t * Number of lines of context to include after each match.\n\t\t */\n\t\tafterContext?: number;\n\t}\n\n\texport namespace workspace {\n\t\t/**\n\t\t * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace.\n\t\t * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words.\n\t\t * @param callback A callback, called for each result\n\t\t * @param token A token that can be used to signal cancellation to the underlying search engine.\n\t\t * @return A thenable that resolves when the search is complete.\n\t\t */\n\t\texport function findTextInFiles(\n\t\t\tquery: TextSearchQuery,\n\t\t\tcallback: (result: TextSearchResult) => void,\n\t\t\ttoken?: CancellationToken\n\t\t): Thenable<TextSearchComplete>;\n\n\t\t/**\n\t\t * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace.\n\t\t * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words.\n\t\t * @param options An optional set of query options. Include and exclude patterns, maxResults, etc.\n\t\t * @param callback A callback, called for each result\n\t\t * @param token A token that can be used to signal cancellation to the underlying search engine.\n\t\t * @return A thenable that resolves when the search is complete.\n\t\t */\n\t\texport function findTextInFiles(\n\t\t\tquery: TextSearchQuery,\n\t\t\toptions: FindTextInFilesOptions,\n\t\t\tcallback: (result: TextSearchResult) => void,\n\t\t\ttoken?: CancellationToken\n\t\t): Thenable<TextSearchComplete>;\n\t}\n\n\t//#endregion\n\n\t//#region diff command: https://github.com/microsoft/vscode/issues/84899\n\n\t/**\n\t * The contiguous set of modified lines in a diff.\n\t */\n\texport interface LineChange {\n\t\treadonly originalStartLineNumber: number;\n\t\treadonly originalEndLineNumber: number;\n\t\treadonly modifiedStartLineNumber: number;\n\t\treadonly modifiedEndLineNumber: number;\n\t}\n\n\texport namespace commands {\n\t\t/**\n\t\t * Registers a diff information command that can be invoked via a keyboard shortcut,\n\t\t * a menu item, an action, or directly.\n\t\t *\n\t\t * Diff information commands are different from ordinary [commands](#commands.registerCommand) as\n\t\t * they only execute when there is an active diff editor when the command is called, and the diff\n\t\t * information has been computed. Also, the command handler of an editor command has access to\n\t\t * the diff information.\n\t\t *\n\t\t * @param command A unique identifier for the command.\n\t\t * @param callback A command handler function with access to the [diff information](#LineChange).\n\t\t * @param thisArg The `this` context used when invoking the handler function.\n\t\t * @return Disposable which unregisters this command on disposal.\n\t\t */\n\t\texport function registerDiffInformationCommand(\n\t\t\tcommand: string,\n\t\t\tcallback: (diff: LineChange[], ...args: any[]) => any,\n\t\t\tthisArg?: any\n\t\t): Disposable;\n\t}\n\n\t//#endregion\n\n\t//#region debug\n\n\t/**\n\t * A DebugProtocolVariableContainer is an opaque stand-in type for the intersection of the Scope and Variable types defined in the Debug Adapter Protocol.\n\t * See https://microsoft.github.io/debug-adapter-protocol/specification#Types_Scope and https://microsoft.github.io/debug-adapter-protocol/specification#Types_Variable.\n\t */\n\texport interface DebugProtocolVariableContainer {\n\t\t// Properties: the intersection of DAP's Scope and Variable types.\n\t}\n\n\t/**\n\t * A DebugProtocolVariable is an opaque stand-in type for the Variable type defined in the Debug Adapter Protocol.\n\t * See https://microsoft.github.io/debug-adapter-protocol/specification#Types_Variable.\n\t */\n\texport interface DebugProtocolVariable {\n\t\t// Properties: see details [here](https://microsoft.github.io/debug-adapter-protocol/specification#Base_Protocol_Variable).\n\t}\n\n\t//#endregion\n\n\t//#region @joaomoreno: SCM validation\n\n\t/**\n\t * Represents the validation type of the Source Control input.\n\t */\n\texport enum SourceControlInputBoxValidationType {\n\t\t/**\n\t\t * Something not allowed by the rules of a language or other means.\n\t\t */\n\t\tError = 0,\n\n\t\t/**\n\t\t * Something suspicious but allowed.\n\t\t */\n\t\tWarning = 1,\n\n\t\t/**\n\t\t * Something to inform about but not a problem.\n\t\t */\n\t\tInformation = 2,\n\t}\n\n\texport interface SourceControlInputBoxValidation {\n\t\t/**\n\t\t * The validation message to display.\n\t\t */\n\t\treadonly message: string;\n\n\t\t/**\n\t\t * The validation type.\n\t\t */\n\t\treadonly type: SourceControlInputBoxValidationType;\n\t}\n\n\t/**\n\t * Represents the input box in the Source Control viewlet.\n\t */\n\texport interface SourceControlInputBox {\n\t\t/**\n\t\t * A validation function for the input box. It's possible to change\n\t\t * the validation provider simply by setting this property to a different function.\n\t\t */\n\t\tvalidateInput?(\n\t\t\tvalue: string,\n\t\t\tcursorPosition: number\n\t\t): ProviderResult<SourceControlInputBoxValidation | undefined | null>;\n\t}\n\n\t//#endregion\n\n\t//#region @joaomoreno: SCM selected provider\n\n\texport interface SourceControl {\n\t\t/**\n\t\t * Whether the source control is selected.\n\t\t */\n\t\treadonly selected: boolean;\n\n\t\t/**\n\t\t * An event signaling when the selection state changes.\n\t\t */\n\t\treadonly onDidChangeSelection: Event<boolean>;\n\t}\n\n\t//#endregion\n\n\t//#region Terminal data write event https://github.com/microsoft/vscode/issues/78502\n\n\texport interface TerminalDataWriteEvent {\n\t\t/**\n\t\t * The [terminal](#Terminal) for which the data was written.\n\t\t */\n\t\treadonly terminal: Terminal;\n\t\t/**\n\t\t * The data being written.\n\t\t */\n\t\treadonly data: string;\n\t}\n\n\tnamespace window {\n\t\t/**\n\t\t * An event which fires when the terminal's child pseudo-device is written to (the shell).\n\t\t * In other words, this provides access to the raw data stream from the process running\n\t\t * within the terminal, including VT sequences.\n\t\t */\n\t\texport const onDidWriteTerminalData: Event<TerminalDataWriteEvent>;\n\t}\n\n\t//#endregion\n\n\t//#region Terminal dimensions property and change event https://github.com/microsoft/vscode/issues/55718\n\n\t/**\n\t * An [event](#Event) which fires when a [Terminal](#Terminal)'s dimensions change.\n\t */\n\texport interface TerminalDimensionsChangeEvent {\n\t\t/**\n\t\t * The [terminal](#Terminal) for which the dimensions have changed.\n\t\t */\n\t\treadonly terminal: Terminal;\n\t\t/**\n\t\t * The new value for the [terminal's dimensions](#Terminal.dimensions).\n\t\t */\n\t\treadonly dimensions: TerminalDimensions;\n\t}\n\n\texport namespace window {\n\t\t/**\n\t\t * An event which fires when the [dimensions](#Terminal.dimensions) of the terminal change.\n\t\t */\n\t\texport const onDidChangeTerminalDimensions: Event<TerminalDimensionsChangeEvent>;\n\t}\n\n\texport interface Terminal {\n\t\t/**\n\t\t * The current dimensions of the terminal. This will be `undefined` immediately after the\n\t\t * terminal is created as the dimensions are not known until shortly after the terminal is\n\t\t * created.\n\t\t */\n\t\treadonly dimensions: TerminalDimensions | undefined;\n\t}\n\n\t//#endregion\n\n\t//#region @jrieken -> exclusive document filters\n\n\texport interface DocumentFilter {\n\t\treadonly exclusive?: boolean;\n\t}\n\n\t//#endregion\n\n\t//#region @alexdima - OnEnter enhancement\n\texport interface OnEnterRule {\n\t\t/**\n\t\t * This rule will only execute if the text above the this line matches this regular expression.\n\t\t */\n\t\toneLineAboveText?: RegExp;\n\t}\n\t//#endregion\n\n\t//#region Tree View: https://github.com/microsoft/vscode/issues/61313\n\texport interface TreeView<T> extends Disposable {\n\t\treveal(\n\t\t\telement: T | undefined,\n\t\t\toptions?: { select?: boolean; focus?: boolean; expand?: boolean | number }\n\t\t): Thenable<void>;\n\t}\n\t//#endregion\n\n\t//#region Task presentation group: https://github.com/microsoft/vscode/issues/47265\n\texport interface TaskPresentationOptions {\n\t\t/**\n\t\t * Controls whether the task is executed in a specific terminal group using split panes.\n\t\t */\n\t\tgroup?: string;\n\t}\n\t//#endregion\n\n\t//#region Status bar item with ID and Name: https://github.com/microsoft/vscode/issues/74972\n\n\texport namespace window {\n\t\t/**\n\t\t * Options to configure the status bar item.\n\t\t */\n\t\texport interface StatusBarItemOptions {\n\t\t\t/**\n\t\t\t * A unique identifier of the status bar item. The identifier\n\t\t\t * is for example used to allow a user to show or hide the\n\t\t\t * status bar item in the UI.\n\t\t\t */\n\t\t\tid: string;\n\n\t\t\t/**\n\t\t\t * A human readable name of the status bar item. The name is\n\t\t\t * for example used as a label in the UI to show or hide the\n\t\t\t * status bar item.\n\t\t\t */\n\t\t\tname: string;\n\n\t\t\t/**\n\t\t\t * Accessibility information used when screen reader interacts with this status bar item.\n\t\t\t */\n\t\t\taccessibilityInformation?: AccessibilityInformation;\n\n\t\t\t/**\n\t\t\t * The alignment of the status bar item.\n\t\t\t */\n\t\t\talignment?: StatusBarAlignment;\n\n\t\t\t/**\n\t\t\t * The priority of the status bar item. Higher value means the item should\n\t\t\t * be shown more to the left.\n\t\t\t */\n\t\t\tpriority?: number;\n\t\t}\n\n\t\t/**\n\t\t * Creates a status bar [item](#StatusBarItem).\n\t\t *\n\t\t * @param options The options of the item. If not provided, some default values\n\t\t * will be assumed. For example, the `StatusBarItemOptions.id` will be the id\n\t\t * of the extension and the `StatusBarItemOptions.name` will be the extension name.\n\t\t * @return A new status bar item.\n\t\t */\n\t\texport function createStatusBarItem(options?: StatusBarItemOptions): StatusBarItem;\n\t}\n\n\t//#endregion\n\n\t//#region Custom editor move https://github.com/microsoft/vscode/issues/86146\n\n\t// TODO: Also for custom editor\n\n\texport interface CustomTextEditorProvider {\n\t\t/**\n\t\t * Handle when the underlying resource for a custom editor is renamed.\n\t\t *\n\t\t * This allows the webview for the editor be preserved throughout the rename. If this method is not implemented,\n\t\t * VS Code will destroy the previous custom editor and create a replacement one.\n\t\t *\n\t\t * @param newDocument New text document to use for the custom editor.\n\t\t * @param existingWebviewPanel Webview panel for the custom editor.\n\t\t * @param token A cancellation token that indicates the result is no longer needed.\n\t\t *\n\t\t * @return Thenable indicating that the webview editor has been moved.\n\t\t */\n\t\tmoveCustomTextEditor?(\n\t\t\tnewDocument: TextDocument,\n\t\t\texistingWebviewPanel: WebviewPanel,\n\t\t\ttoken: CancellationToken\n\t\t): Thenable<void>;\n\t}\n\n\t//#endregion\n\n\t//#region allow QuickPicks to skip sorting: https://github.com/microsoft/vscode/issues/73904\n\n\texport interface QuickPick<T extends QuickPickItem> extends QuickInput {\n\t\t/**\n\t\t * An optional flag to sort the final results by index of first query match in label. Defaults to true.\n\t\t */\n\t\tsortByLabel: boolean;\n\t}\n\n\t//#endregion\n\n\t//#region @rebornix: Notebook\n\n\texport enum CellKind {\n\t\tMarkdown = 1,\n\t\tCode = 2,\n\t}\n\n\texport enum CellOutputKind {\n\t\tText = 1,\n\t\tError = 2,\n\t\tRich = 3,\n\t}\n\n\texport interface CellStreamOutput {\n\t\toutputKind: CellOutputKind.Text;\n\t\ttext: string;\n\t}\n\n\texport interface CellErrorOutput {\n\t\toutputKind: CellOutputKind.Error;\n\t\t/**\n\t\t * Exception Name\n\t\t */\n\t\tename: string;\n\t\t/**\n\t\t * Exception Value\n\t\t */\n\t\tevalue: string;\n\t\t/**\n\t\t * Exception call stack\n\t\t */\n\t\ttraceback: string[];\n\t}\n\n\texport interface NotebookCellOutputMetadata {\n\t\t/**\n\t\t * Additional attributes of a cell metadata.\n\t\t */\n\t\tcustom?: { [key: string]: any };\n\t}\n\n\texport interface CellDisplayOutput {\n\t\toutputKind: CellOutputKind.Rich;\n\t\t/**\n\t\t * { mime_type: value }\n\t\t *\n\t\t * Example:\n\t\t * ```json\n\t\t * {\n\t\t *   \"outputKind\": vscode.CellOutputKind.Rich,\n\t\t *   \"data\": {\n\t\t *      \"text/html\": [\n\t\t *          \"<h1>Hello</h1>\"\n\t\t *       ],\n\t\t *      \"text/plain\": [\n\t\t *        \"<IPython.lib.display.IFrame at 0x11dee3e80>\"\n\t\t *      ]\n\t\t *   }\n\t\t * }\n\t\t */\n\t\tdata: { [key: string]: any };\n\n\t\treadonly metadata?: NotebookCellOutputMetadata;\n\t}\n\n\texport type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput;\n\n\texport class NotebookCellOutputItem {\n\t\treadonly mime: string;\n\t\treadonly value: unknown;\n\t\treadonly metadata?: Record<string, string | number | boolean>;\n\n\t\tconstructor(mime: string, value: unknown, metadata?: Record<string, string | number | boolean>);\n\t}\n\n\t//TODO@jrieken add id?\n\texport class NotebookCellOutput {\n\t\treadonly outputs: NotebookCellOutputItem[];\n\t\treadonly metadata?: Record<string, string | number | boolean>;\n\n\t\tconstructor(outputs: NotebookCellOutputItem[], metadata?: Record<string, string | number | boolean>);\n\n\t\t//TODO@jrieken HACK to workaround dependency issues...\n\t\ttoJSON(): any;\n\t}\n\n\texport enum NotebookCellRunState {\n\t\tRunning = 1,\n\t\tIdle = 2,\n\t\tSuccess = 3,\n\t\tError = 4,\n\t}\n\n\texport enum NotebookRunState {\n\t\tRunning = 1,\n\t\tIdle = 2,\n\t}\n\n\texport interface NotebookCellMetadata {\n\t\t/**\n\t\t * Controls whether a cell's editor is editable/readonly.\n\t\t */\n\t\teditable?: boolean;\n\n\t\t/**\n\t\t * Controls if the cell is executable.\n\t\t * This metadata is ignored for markdown cell.\n\t\t */\n\t\trunnable?: boolean;\n\n\t\t/**\n\t\t * Controls if the cell has a margin to support the breakpoint UI.\n\t\t * This metadata is ignored for markdown cell.\n\t\t */\n\t\tbreakpointMargin?: boolean;\n\n\t\t/**\n\t\t * Whether the [execution order](#NotebookCellMetadata.executionOrder) indicator will be displayed.\n\t\t * Defaults to true.\n\t\t */\n\t\thasExecutionOrder?: boolean;\n\n\t\t/**\n\t\t * The order in which this cell was executed.\n\t\t */\n\t\texecutionOrder?: number;\n\n\t\t/**\n\t\t * A status message to be shown in the cell's status bar\n\t\t */\n\t\tstatusMessage?: string;\n\n\t\t/**\n\t\t * The cell's current run state\n\t\t */\n\t\trunState?: NotebookCellRunState;\n\n\t\t/**\n\t\t * If the cell is running, the time at which the cell started running\n\t\t */\n\t\trunStartTime?: number;\n\n\t\t/**\n\t\t * The total duration of the cell's last run\n\t\t */\n\t\tlastRunDuration?: number;\n\n\t\t/**\n\t\t * Whether a code cell's editor is collapsed\n\t\t */\n\t\tinputCollapsed?: boolean;\n\n\t\t/**\n\t\t * Whether a code cell's outputs are collapsed\n\t\t */\n\t\toutputCollapsed?: boolean;\n\n\t\t/**\n\t\t * Additional attributes of a cell metadata.\n\t\t */\n\t\tcustom?: { [key: string]: any };\n\t}\n\n\texport interface NotebookCell {\n\t\treadonly index: number;\n\t\treadonly notebook: NotebookDocument;\n\t\treadonly uri: Uri;\n\t\treadonly cellKind: CellKind;\n\t\treadonly document: TextDocument;\n\t\treadonly language: string;\n\t\toutputs: CellOutput[];\n\t\tmetadata: NotebookCellMetadata;\n\t}\n\n\texport interface NotebookDocumentMetadata {\n\t\t/**\n\t\t * Controls if users can add or delete cells\n\t\t * Defaults to true\n\t\t */\n\t\teditable?: boolean;\n\n\t\t/**\n\t\t * Controls whether the full notebook can be run at once.\n\t\t * Defaults to true\n\t\t */\n\t\trunnable?: boolean;\n\n\t\t/**\n\t\t * Default value for [cell editable metadata](#NotebookCellMetadata.editable).\n\t\t * Defaults to true.\n\t\t */\n\t\tcellEditable?: boolean;\n\n\t\t/**\n\t\t * Default value for [cell runnable metadata](#NotebookCellMetadata.runnable).\n\t\t * Defaults to true.\n\t\t */\n\t\tcellRunnable?: boolean;\n\n\t\t/**\n\t\t * Default value for [cell hasExecutionOrder metadata](#NotebookCellMetadata.hasExecutionOrder).\n\t\t * Defaults to true.\n\t\t */\n\t\tcellHasExecutionOrder?: boolean;\n\n\t\tdisplayOrder?: GlobPattern[];\n\n\t\t/**\n\t\t * Additional attributes of the document metadata.\n\t\t */\n\t\tcustom?: { [key: string]: any };\n\n\t\t/**\n\t\t * The document's current run state\n\t\t */\n\t\trunState?: NotebookRunState;\n\n\t\t/**\n\t\t * Whether the document is trusted, default to true\n\t\t * When false, insecure outputs like HTML, JavaScript, SVG will not be rendered.\n\t\t */\n\t\ttrusted?: boolean;\n\t}\n\n\texport interface NotebookDocumentContentOptions {\n\t\t/**\n\t\t * Controls if outputs change will trigger notebook document content change and if it will be used in the diff editor\n\t\t * Default to false. If the content provider doesn't persist the outputs in the file document, this should be set to true.\n\t\t */\n\t\ttransientOutputs: boolean;\n\n\t\t/**\n\t\t * Controls if a metadata property change will trigger notebook document content change and if it will be used in the diff editor\n\t\t * Default to false. If the content provider doesn't persist a metadata property in the file document, it should be set to true.\n\t\t */\n\t\ttransientMetadata: { [K in keyof NotebookCellMetadata]?: boolean };\n\t}\n\n\texport interface NotebookDocument {\n\t\treadonly uri: Uri;\n\t\treadonly version: number;\n\t\treadonly fileName: string;\n\t\treadonly viewType: string;\n\t\treadonly isDirty: boolean;\n\t\treadonly isUntitled: boolean;\n\t\treadonly cells: ReadonlyArray<NotebookCell>;\n\t\treadonly contentOptions: NotebookDocumentContentOptions;\n\t\tlanguages: string[];\n\t\tmetadata: NotebookDocumentMetadata;\n\t}\n\n\texport interface NotebookConcatTextDocument {\n\t\turi: Uri;\n\t\tisClosed: boolean;\n\t\tdispose(): void;\n\t\tonDidChange: Event<void>;\n\t\tversion: number;\n\t\tgetText(): string;\n\t\tgetText(range: Range): string;\n\n\t\toffsetAt(position: Position): number;\n\t\tpositionAt(offset: number): Position;\n\t\tvalidateRange(range: Range): Range;\n\t\tvalidatePosition(position: Position): Position;\n\n\t\tlocationAt(positionOrRange: Position | Range): Location;\n\t\tpositionAt(location: Location): Position;\n\t\tcontains(uri: Uri): boolean;\n\t}\n\n\texport interface WorkspaceEdit {\n\t\treplaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void;\n\t\treplaceNotebookCells(\n\t\t\turi: Uri,\n\t\t\tstart: number,\n\t\t\tend: number,\n\t\t\tcells: NotebookCellData[],\n\t\t\tmetadata?: WorkspaceEditEntryMetadata\n\t\t): void;\n\t\treplaceNotebookCellOutput(\n\t\t\turi: Uri,\n\t\t\tindex: number,\n\t\t\toutputs: (NotebookCellOutput | CellOutput)[],\n\t\t\tmetadata?: WorkspaceEditEntryMetadata\n\t\t): void;\n\t\treplaceNotebookCellMetadata(\n\t\t\turi: Uri,\n\t\t\tindex: number,\n\t\t\tcellMetadata: NotebookCellMetadata,\n\t\t\tmetadata?: WorkspaceEditEntryMetadata\n\t\t): void;\n\t}\n\n\texport interface NotebookEditorEdit {\n\t\treplaceMetadata(value: NotebookDocumentMetadata): void;\n\t\treplaceCells(start: number, end: number, cells: NotebookCellData[]): void;\n\t\treplaceCellOutput(index: number, outputs: (NotebookCellOutput | CellOutput)[]): void;\n\t\treplaceCellMetadata(index: number, metadata: NotebookCellMetadata): void;\n\t}\n\n\texport interface NotebookCellRange {\n\t\treadonly start: number;\n\t\t/**\n\t\t * exclusive\n\t\t */\n\t\treadonly end: number;\n\t}\n\n\texport enum NotebookEditorRevealType {\n\t\t/**\n\t\t * The range will be revealed with as little scrolling as possible.\n\t\t */\n\t\tDefault = 0,\n\t\t/**\n\t\t * The range will always be revealed in the center of the viewport.\n\t\t */\n\t\tInCenter = 1,\n\t\t/**\n\t\t * If the range is outside the viewport, it will be revealed in the center of the viewport.\n\t\t * Otherwise, it will be revealed with as little scrolling as possible.\n\t\t */\n\t\tInCenterIfOutsideViewport = 2,\n\t}\n\n\texport interface NotebookEditor {\n\t\t/**\n\t\t * The document associated with this notebook editor.\n\t\t */\n\t\treadonly document: NotebookDocument;\n\n\t\t/**\n\t\t * The primary selected cell on this notebook editor.\n\t\t */\n\t\treadonly selection?: NotebookCell;\n\n\t\t/**\n\t\t * The current visible ranges in the editor (vertically).\n\t\t */\n\t\treadonly visibleRanges: NotebookCellRange[];\n\n\t\t/**\n\t\t * The column in which this editor shows.\n\t\t */\n\t\treadonly viewColumn?: ViewColumn;\n\n\t\t/**\n\t\t * Fired when the panel is disposed.\n\t\t */\n\t\treadonly onDidDispose: Event<void>;\n\n\t\t/**\n\t\t * Active kernel used in the editor\n\t\t */\n\t\treadonly kernel?: NotebookKernel;\n\n\t\t/**\n\t\t * Fired when the output hosting webview posts a message.\n\t\t */\n\t\treadonly onDidReceiveMessage: Event<any>;\n\t\t/**\n\t\t * Post a message to the output hosting webview.\n\t\t *\n\t\t * Messages are only delivered if the editor is live.\n\t\t *\n\t\t * @param message Body of the message. This must be a string or other json serializable object.\n\t\t */\n\t\tpostMessage(message: any): Thenable<boolean>;\n\n\t\t/**\n\t\t * Convert a uri for the local file system to one that can be used inside outputs webview.\n\t\t */\n\t\tasWebviewUri(localResource: Uri): Uri;\n\n\t\t/**\n\t\t * Perform an edit on the notebook associated with this notebook editor.\n\t\t *\n\t\t * The given callback-function is invoked with an [edit-builder](#NotebookEditorEdit) which must\n\t\t * be used to make edits. Note that the edit-builder is only valid while the\n\t\t * callback executes.\n\t\t *\n\t\t * @param callback A function which can create edits using an [edit-builder](#NotebookEditorEdit).\n\t\t * @return A promise that resolves with a value indicating if the edits could be applied.\n\t\t */\n\t\tedit(callback: (editBuilder: NotebookEditorEdit) => void): Thenable<boolean>;\n\n\t\tsetDecorations(decorationType: NotebookEditorDecorationType, range: NotebookCellRange): void;\n\n\t\trevealRange(range: NotebookCellRange, revealType?: NotebookEditorRevealType): void;\n\t}\n\n\texport interface NotebookOutputSelector {\n\t\tmimeTypes?: string[];\n\t}\n\n\texport interface NotebookRenderRequest {\n\t\toutput: CellDisplayOutput;\n\t\tmimeType: string;\n\t\toutputId: string;\n\t}\n\n\texport interface NotebookDocumentMetadataChangeEvent {\n\t\treadonly document: NotebookDocument;\n\t}\n\n\texport interface NotebookCellsChangeData {\n\t\treadonly start: number;\n\t\treadonly deletedCount: number;\n\t\treadonly deletedItems: NotebookCell[];\n\t\treadonly items: NotebookCell[];\n\t}\n\n\texport interface NotebookCellsChangeEvent {\n\t\t/**\n\t\t * The affected document.\n\t\t */\n\t\treadonly document: NotebookDocument;\n\t\treadonly changes: ReadonlyArray<NotebookCellsChangeData>;\n\t}\n\n\texport interface NotebookCellMoveEvent {\n\t\t/**\n\t\t * The affected document.\n\t\t */\n\t\treadonly document: NotebookDocument;\n\t\treadonly index: number;\n\t\treadonly newIndex: number;\n\t}\n\n\texport interface NotebookCellOutputsChangeEvent {\n\t\t/**\n\t\t * The affected document.\n\t\t */\n\t\treadonly document: NotebookDocument;\n\t\treadonly cells: NotebookCell[];\n\t}\n\n\texport interface NotebookCellLanguageChangeEvent {\n\t\t/**\n\t\t * The affected document.\n\t\t */\n\t\treadonly document: NotebookDocument;\n\t\treadonly cell: NotebookCell;\n\t\treadonly language: string;\n\t}\n\n\texport interface NotebookCellMetadataChangeEvent {\n\t\treadonly document: NotebookDocument;\n\t\treadonly cell: NotebookCell;\n\t}\n\n\texport interface NotebookEditorSelectionChangeEvent {\n\t\treadonly notebookEditor: NotebookEditor;\n\t\treadonly selection?: NotebookCell;\n\t}\n\n\texport interface NotebookEditorVisibleRangesChangeEvent {\n\t\treadonly notebookEditor: NotebookEditor;\n\t\treadonly visibleRanges: ReadonlyArray<NotebookCellRange>;\n\t}\n\n\texport interface NotebookCellData {\n\t\treadonly cellKind: CellKind;\n\t\treadonly source: string;\n\t\treadonly language: string;\n\t\treadonly outputs: CellOutput[];\n\t\treadonly metadata: NotebookCellMetadata | undefined;\n\t}\n\n\texport interface NotebookData {\n\t\treadonly cells: NotebookCellData[];\n\t\treadonly languages: string[];\n\t\treadonly metadata: NotebookDocumentMetadata;\n\t}\n\n\tinterface NotebookDocumentContentChangeEvent {\n\t\t/**\n\t\t * The document that the edit is for.\n\t\t */\n\t\treadonly document: NotebookDocument;\n\t}\n\n\tinterface NotebookDocumentEditEvent {\n\t\t/**\n\t\t * The document that the edit is for.\n\t\t */\n\t\treadonly document: NotebookDocument;\n\n\t\t/**\n\t\t * Undo the edit operation.\n\t\t *\n\t\t * This is invoked by VS Code when the user undoes this edit. To implement `undo`, your\n\t\t * extension should restore the document and editor to the state they were in just before this\n\t\t * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`.\n\t\t */\n\t\tundo(): Thenable<void> | void;\n\n\t\t/**\n\t\t * Redo the edit operation.\n\t\t *\n\t\t * This is invoked by VS Code when the user redoes this edit. To implement `redo`, your\n\t\t * extension should restore the document and editor to the state they were in just after this\n\t\t * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`.\n\t\t */\n\t\tredo(): Thenable<void> | void;\n\n\t\t/**\n\t\t * Display name describing the edit.\n\t\t *\n\t\t * This will be shown to users in the UI for undo/redo operations.\n\t\t */\n\t\treadonly label?: string;\n\t}\n\n\tinterface NotebookDocumentBackup {\n\t\t/**\n\t\t * Unique identifier for the backup.\n\t\t *\n\t\t * This id is passed back to your extension in `openNotebook` when opening a notebook editor from a backup.\n\t\t */\n\t\treadonly id: string;\n\n\t\t/**\n\t\t * Delete the current backup.\n\t\t *\n\t\t * This is called by VS Code when it is clear the current backup is no longer needed, such as when a new backup\n\t\t * is made or when the file is saved.\n\t\t */\n\t\tdelete(): void;\n\t}\n\n\tinterface NotebookDocumentBackupContext {\n\t\treadonly destination: Uri;\n\t}\n\n\tinterface NotebookDocumentOpenContext {\n\t\treadonly backupId?: string;\n\t}\n\n\t/**\n\t * Communication object passed to the {@link NotebookContentProvider} and\n\t * {@link NotebookOutputRenderer} to communicate with the webview.\n\t */\n\texport interface NotebookCommunication {\n\t\t/**\n\t\t * ID of the editor this object communicates with. A single notebook\n\t\t * document can have multiple attached webviews and editors, when the\n\t\t * notebook is split for instance. The editor ID lets you differentiate\n\t\t * between them.\n\t\t */\n\t\treadonly editorId: string;\n\n\t\t/**\n\t\t * Fired when the output hosting webview posts a message.\n\t\t */\n\t\treadonly onDidReceiveMessage: Event<any>;\n\t\t/**\n\t\t * Post a message to the output hosting webview.\n\t\t *\n\t\t * Messages are only delivered if the editor is live.\n\t\t *\n\t\t * @param message Body of the message. This must be a string or other json serializable object.\n\t\t */\n\t\tpostMessage(message: any): Thenable<boolean>;\n\n\t\t/**\n\t\t * Convert a uri for the local file system to one that can be used inside outputs webview.\n\t\t */\n\t\tasWebviewUri(localResource: Uri): Uri;\n\t}\n\n\texport interface NotebookContentProvider {\n\t\treadonly options?: NotebookDocumentContentOptions;\n\t\treadonly onDidChangeNotebookContentOptions?: Event<NotebookDocumentContentOptions>;\n\t\treadonly onDidChangeNotebook: Event<NotebookDocumentContentChangeEvent | NotebookDocumentEditEvent>;\n\n\t\t/**\n\t\t * Content providers should always use [file system providers](#FileSystemProvider) to\n\t\t * resolve the raw content for `uri` as the resource is not necessarily a file on disk.\n\t\t */\n\t\topenNotebook(uri: Uri, openContext: NotebookDocumentOpenContext): NotebookData | Promise<NotebookData>;\n\t\tresolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Promise<void>;\n\t\tsaveNotebook(document: NotebookDocument, cancellation: CancellationToken): Promise<void>;\n\t\tsaveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise<void>;\n\t\tbackupNotebook(\n\t\t\tdocument: NotebookDocument,\n\t\t\tcontext: NotebookDocumentBackupContext,\n\t\t\tcancellation: CancellationToken\n\t\t): Promise<NotebookDocumentBackup>;\n\t}\n\n\texport interface NotebookKernel {\n\t\treadonly id?: string;\n\t\tlabel: string;\n\t\tdescription?: string;\n\t\tdetail?: string;\n\t\tisPreferred?: boolean;\n\t\tpreloads?: Uri[];\n\t\texecuteCell(document: NotebookDocument, cell: NotebookCell): void;\n\t\tcancelCellExecution(document: NotebookDocument, cell: NotebookCell): void;\n\t\texecuteAllCells(document: NotebookDocument): void;\n\t\tcancelAllCellsExecution(document: NotebookDocument): void;\n\t}\n\n\texport type NotebookFilenamePattern = GlobPattern | { include: GlobPattern; exclude: GlobPattern };\n\n\texport interface NotebookDocumentFilter {\n\t\tviewType?: string | string[];\n\t\tfilenamePattern?: NotebookFilenamePattern;\n\t}\n\n\texport interface NotebookKernelProvider<T extends NotebookKernel = NotebookKernel> {\n\t\tonDidChangeKernels?: Event<NotebookDocument | undefined>;\n\t\tprovideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult<T[]>;\n\t\tresolveKernel?(\n\t\t\tkernel: T,\n\t\t\tdocument: NotebookDocument,\n\t\t\twebview: NotebookCommunication,\n\t\t\ttoken: CancellationToken\n\t\t): ProviderResult<void>;\n\t}\n\n\t/**\n\t * Represents the alignment of status bar items.\n\t */\n\texport enum NotebookCellStatusBarAlignment {\n\t\t/**\n\t\t * Aligned to the left side.\n\t\t */\n\t\tLeft = 1,\n\n\t\t/**\n\t\t * Aligned to the right side.\n\t\t */\n\t\tRight = 2,\n\t}\n\n\texport interface NotebookCellStatusBarItem {\n\t\treadonly cell: NotebookCell;\n\t\treadonly alignment: NotebookCellStatusBarAlignment;\n\t\treadonly priority?: number;\n\t\ttext: string;\n\t\ttooltip: string | undefined;\n\t\tcommand: string | Command | undefined;\n\t\taccessibilityInformation?: AccessibilityInformation;\n\t\tshow(): void;\n\t\thide(): void;\n\t\tdispose(): void;\n\t}\n\n\texport interface NotebookDecorationRenderOptions {\n\t\tbackgroundColor?: string | ThemeColor;\n\t\tborderColor?: string | ThemeColor;\n\t\ttop: ThemableDecorationAttachmentRenderOptions;\n\t}\n\n\texport interface NotebookEditorDecorationType {\n\t\treadonly key: string;\n\t\tdispose(): void;\n\t}\n\n\texport interface NotebookDocumentShowOptions {\n\t\tviewColumn?: ViewColumn;\n\t\tpreserveFocus?: boolean;\n\t\tpreview?: boolean;\n\t\tselection?: NotebookCellRange;\n\t}\n\n\texport namespace notebook {\n\t\texport function registerNotebookContentProvider(\n\t\t\tnotebookType: string,\n\t\t\tprovider: NotebookContentProvider,\n\t\t\toptions?: NotebookDocumentContentOptions & {\n\t\t\t\t/**\n\t\t\t\t * Not ready for production or development use yet.\n\t\t\t\t */\n\t\t\t\tviewOptions?: {\n\t\t\t\t\tdisplayName: string;\n\t\t\t\t\tfilenamePattern: NotebookFilenamePattern[];\n\t\t\t\t\texclusive?: boolean;\n\t\t\t\t};\n\t\t\t}\n\t\t): Disposable;\n\n\t\texport function registerNotebookKernelProvider(\n\t\t\tselector: NotebookDocumentFilter,\n\t\t\tprovider: NotebookKernelProvider\n\t\t): Disposable;\n\n\t\texport function createNotebookEditorDecorationType(\n\t\t\toptions: NotebookDecorationRenderOptions\n\t\t): NotebookEditorDecorationType;\n\t\texport function openNotebookDocument(uri: Uri, viewType?: string): Promise<NotebookDocument>;\n\t\texport const onDidOpenNotebookDocument: Event<NotebookDocument>;\n\t\texport const onDidCloseNotebookDocument: Event<NotebookDocument>;\n\t\texport const onDidSaveNotebookDocument: Event<NotebookDocument>;\n\n\t\t/**\n\t\t * All currently known notebook documents.\n\t\t */\n\t\texport const notebookDocuments: ReadonlyArray<NotebookDocument>;\n\t\texport const onDidChangeNotebookDocumentMetadata: Event<NotebookDocumentMetadataChangeEvent>;\n\t\texport const onDidChangeNotebookCells: Event<NotebookCellsChangeEvent>;\n\t\texport const onDidChangeCellOutputs: Event<NotebookCellOutputsChangeEvent>;\n\t\texport const onDidChangeCellLanguage: Event<NotebookCellLanguageChangeEvent>;\n\t\texport const onDidChangeCellMetadata: Event<NotebookCellMetadataChangeEvent>;\n\t\t/**\n\t\t * Create a document that is the concatenation of all  notebook cells. By default all code-cells are included\n\t\t * but a selector can be provided to narrow to down the set of cells.\n\t\t *\n\t\t * @param notebook\n\t\t * @param selector\n\t\t */\n\t\texport function createConcatTextDocument(\n\t\t\tnotebook: NotebookDocument,\n\t\t\tselector?: DocumentSelector\n\t\t): NotebookConcatTextDocument;\n\n\t\texport const onDidChangeActiveNotebookKernel: Event<{\n\t\t\tdocument: NotebookDocument;\n\t\t\tkernel: NotebookKernel | undefined;\n\t\t}>;\n\n\t\t/**\n\t\t * Creates a notebook cell status bar [item](#NotebookCellStatusBarItem).\n\t\t * It will be disposed automatically when the notebook document is closed or the cell is deleted.\n\t\t *\n\t\t * @param cell The cell on which this item should be shown.\n\t\t * @param alignment The alignment of the item.\n\t\t * @param priority The priority of the item. Higher values mean the item should be shown more to the left.\n\t\t * @return A new status bar item.\n\t\t */\n\t\texport function createCellStatusBarItem(\n\t\t\tcell: NotebookCell,\n\t\t\talignment?: NotebookCellStatusBarAlignment,\n\t\t\tpriority?: number\n\t\t): NotebookCellStatusBarItem;\n\t}\n\n\texport namespace window {\n\t\texport const visibleNotebookEditors: NotebookEditor[];\n\t\texport const onDidChangeVisibleNotebookEditors: Event<NotebookEditor[]>;\n\t\texport const activeNotebookEditor: NotebookEditor | undefined;\n\t\texport const onDidChangeActiveNotebookEditor: Event<NotebookEditor | undefined>;\n\t\texport const onDidChangeNotebookEditorSelection: Event<NotebookEditorSelectionChangeEvent>;\n\t\texport const onDidChangeNotebookEditorVisibleRanges: Event<NotebookEditorVisibleRangesChangeEvent>;\n\t\texport function showNotebookDocument(\n\t\t\tdocument: NotebookDocument,\n\t\t\toptions?: NotebookDocumentShowOptions\n\t\t): Promise<NotebookEditor>;\n\t}\n\n\t//#endregion\n\n\t//#region https://github.com/microsoft/vscode/issues/39441\n\n\texport interface CompletionItem {\n\t\t/**\n\t\t * Will be merged into CompletionItem#label\n\t\t */\n\t\tlabel2?: CompletionItemLabel;\n\t}\n\n\texport interface CompletionItemLabel {\n\t\t/**\n\t\t * The function or variable. Rendered leftmost.\n\t\t */\n\t\tname: string;\n\n\t\t/**\n\t\t * The parameters without the return type. Render after `name`.\n\t\t */\n\t\tparameters?: string;\n\n\t\t/**\n\t\t * The fully qualified name, like package name or file path. Rendered after `signature`.\n\t\t */\n\t\tqualifier?: string;\n\n\t\t/**\n\t\t * The return-type of a function or type of a property/variable. Rendered rightmost.\n\t\t */\n\t\ttype?: string;\n\t}\n\n\t//#endregion\n\n\t//#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297\n\n\texport class TimelineItem {\n\t\t/**\n\t\t * A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred.\n\t\t */\n\t\ttimestamp: number;\n\n\t\t/**\n\t\t * A human-readable string describing the timeline item.\n\t\t */\n\t\tlabel: string;\n\n\t\t/**\n\t\t * Optional id for the timeline item. It must be unique across all the timeline items provided by this source.\n\t\t *\n\t\t * If not provided, an id is generated using the timeline item's timestamp.\n\t\t */\n\t\tid?: string;\n\n\t\t/**\n\t\t * The icon path or [ThemeIcon](#ThemeIcon) for the timeline item.\n\t\t */\n\t\ticonPath?: Uri | { light: Uri; dark: Uri } | ThemeIcon;\n\n\t\t/**\n\t\t * A human readable string describing less prominent details of the timeline item.\n\t\t */\n\t\tdescription?: string;\n\n\t\t/**\n\t\t * The tooltip text when you hover over the timeline item.\n\t\t */\n\t\tdetail?: string;\n\n\t\t/**\n\t\t * The [command](#Command) that should be executed when the timeline item is selected.\n\t\t */\n\t\tcommand?: Command;\n\n\t\t/**\n\t\t * Context value of the timeline item. This can be used to contribute specific actions to the item.\n\t\t * For example, a timeline item is given a context value as `commit`. When contributing actions to `timeline/item/context`\n\t\t * using `menus` extension point, you can specify context value for key `timelineItem` in `when` expression like `timelineItem == commit`.\n\t\t * ```\n\t\t *\t\"contributes\": {\n\t\t *\t\t\"menus\": {\n\t\t *\t\t\t\"timeline/item/context\": [\n\t\t *\t\t\t\t{\n\t\t *\t\t\t\t\t\"command\": \"extension.copyCommitId\",\n\t\t *\t\t\t\t\t\"when\": \"timelineItem == commit\"\n\t\t *\t\t\t\t}\n\t\t *\t\t\t]\n\t\t *\t\t}\n\t\t *\t}\n\t\t * ```\n\t\t * This will show the `extension.copyCommitId` action only for items where `contextValue` is `commit`.\n\t\t */\n\t\tcontextValue?: string;\n\n\t\t/**\n\t\t * Accessibility information used when screen reader interacts with this timeline item.\n\t\t */\n\t\taccessibilityInformation?: AccessibilityInformation;\n\n\t\t/**\n\t\t * @param label A human-readable string describing the timeline item\n\t\t * @param timestamp A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred\n\t\t */\n\t\tconstructor(label: string, timestamp: number);\n\t}\n\n\texport interface TimelineChangeEvent {\n\t\t/**\n\t\t * The [uri](#Uri) of the resource for which the timeline changed.\n\t\t */\n\t\turi: Uri;\n\n\t\t/**\n\t\t * A flag which indicates whether the entire timeline should be reset.\n\t\t */\n\t\treset?: boolean;\n\t}\n\n\texport interface Timeline {\n\t\treadonly paging?: {\n\t\t\t/**\n\t\t\t * A provider-defined cursor specifying the starting point of timeline items which are after the ones returned.\n\t\t\t * Use `undefined` to signal that there are no more items to be returned.\n\t\t\t */\n\t\t\treadonly cursor: string | undefined;\n\t\t};\n\n\t\t/**\n\t\t * An array of [timeline items](#TimelineItem).\n\t\t */\n\t\treadonly items: readonly TimelineItem[];\n\t}\n\n\texport interface TimelineOptions {\n\t\t/**\n\t\t * A provider-defined cursor specifying the starting point of the timeline items that should be returned.\n\t\t */\n\t\tcursor?: string;\n\n\t\t/**\n\t\t * An optional maximum number timeline items or the all timeline items newer (inclusive) than the timestamp or id that should be returned.\n\t\t * If `undefined` all timeline items should be returned.\n\t\t */\n\t\tlimit?: number | { timestamp: number; id?: string };\n\t}\n\n\texport interface TimelineProvider {\n\t\t/**\n\t\t * An optional event to signal that the timeline for a source has changed.\n\t\t * To signal that the timeline for all resources (uris) has changed, do not pass any argument or pass `undefined`.\n\t\t */\n\t\tonDidChange?: Event<TimelineChangeEvent | undefined>;\n\n\t\t/**\n\t\t * An identifier of the source of the timeline items. This can be used to filter sources.\n\t\t */\n\t\treadonly id: string;\n\n\t\t/**\n\t\t * A human-readable string describing the source of the timeline items. This can be used as the display label when filtering sources.\n\t\t */\n\t\treadonly label: string;\n\n\t\t/**\n\t\t * Provide [timeline items](#TimelineItem) for a [Uri](#Uri).\n\t\t *\n\t\t * @param uri The [uri](#Uri) of the file to provide the timeline for.\n\t\t * @param options A set of options to determine how results should be returned.\n\t\t * @param token A cancellation token.\n\t\t * @return The [timeline result](#TimelineResult) or a thenable that resolves to such. The lack of a result\n\t\t * can be signaled by returning `undefined`, `null`, or an empty array.\n\t\t */\n\t\tprovideTimeline(uri: Uri, options: TimelineOptions, token: CancellationToken): ProviderResult<Timeline>;\n\t}\n\n\texport namespace workspace {\n\t\t/**\n\t\t * Register a timeline provider.\n\t\t *\n\t\t * Multiple providers can be registered. In that case, providers are asked in\n\t\t * parallel and the results are merged. A failing provider (rejected promise or exception) will\n\t\t * not cause a failure of the whole operation.\n\t\t *\n\t\t * @param scheme A scheme or schemes that defines which documents this provider is applicable to. Can be `*` to target all documents.\n\t\t * @param provider A timeline provider.\n\t\t * @return A [disposable](#Disposable) that unregisters this provider when being disposed.\n\t\t */\n\t\texport function registerTimelineProvider(scheme: string | string[], provider: TimelineProvider): Disposable;\n\t}\n\n\t//#endregion\n\n\t//#region https://github.com/microsoft/vscode/issues/91555\n\n\texport enum StandardTokenType {\n\t\tOther = 0,\n\t\tComment = 1,\n\t\tString = 2,\n\t\tRegEx = 4,\n\t}\n\n\texport interface TokenInformation {\n\t\ttype: StandardTokenType;\n\t\trange: Range;\n\t}\n\n\texport namespace languages {\n\t\texport function getTokenInformationAtPosition(\n\t\t\tdocument: TextDocument,\n\t\t\tposition: Position\n\t\t): Promise<TokenInformation>;\n\t}\n\n\t//#endregion\n\n\t//#region https://github.com/microsoft/vscode/issues/104436\n\n\texport enum ExtensionRuntime {\n\t\t/**\n\t\t * The extension is running in a NodeJS extension host. Runtime access to NodeJS APIs is available.\n\t\t */\n\t\tNode = 1,\n\t\t/**\n\t\t * The extension is running in a Webworker extension host. Runtime access is limited to Webworker APIs.\n\t\t */\n\t\tWebworker = 2,\n\t}\n\n\texport interface ExtensionContext {\n\t\treadonly extensionRuntime: ExtensionRuntime;\n\t}\n\n\t//#endregion\n\n\t//#region https://github.com/microsoft/vscode/issues/102091\n\n\texport interface TextDocument {\n\t\t/**\n\t\t * The [notebook](#NotebookDocument) that contains this document as a notebook cell or `undefined` when\n\t\t * the document is not contained by a notebook (this should be the more frequent case).\n\t\t */\n\t\tnotebook: NotebookDocument | undefined;\n\t}\n\t//#endregion\n\n\t//#region https://github.com/microsoft/vscode/issues/107467\n\t/*\n\t\tGeneral activation events:\n\t\t\t- `onLanguage:*` most test extensions will want to activate when their\n\t\t\t\tlanguage is opened to provide code lenses.\n\t\t\t- `onTests:*` new activation event very similar to `workspaceContains`,\n\t\t\t\tbut only fired when the user wants to run tests or opens the test explorer.\n\t*/\n\texport namespace test {\n\t\t/**\n\t\t * Registers a provider that discovers tests for the given document\n\t\t * selectors. It is activated when either tests need to be enumerated, or\n\t\t * a document matching the selector is opened.\n\t\t */\n\t\texport function registerTestProvider<T extends TestItem>(testProvider: TestProvider<T>): Disposable;\n\n\t\t/**\n\t\t * Runs tests with the given options. If no options are given, then\n\t\t * all tests are run. Returns the resulting test run.\n\t\t */\n\t\texport function runTests<T extends TestItem>(options: TestRunOptions<T>): Thenable<void>;\n\n\t\t/**\n\t\t * Returns an observer that retrieves tests in the given workspace folder.\n\t\t */\n\t\texport function createWorkspaceTestObserver(workspaceFolder: WorkspaceFolder): TestObserver;\n\n\t\t/**\n\t\t * Returns an observer that retrieves tests in the given text document.\n\t\t */\n\t\texport function createDocumentTestObserver(document: TextDocument): TestObserver;\n\t}\n\n\texport interface TestObserver {\n\t\t/**\n\t\t * List of tests returned by test provider for files in the workspace.\n\t\t */\n\t\treadonly tests: ReadonlyArray<TestItem>;\n\n\t\t/**\n\t\t * An event that fires when an existing test in the collection changes, or\n\t\t * null if a top-level test was added or removed. When fired, the consumer\n\t\t * should check the test item and all its children for changes.\n\t\t */\n\t\treadonly onDidChangeTest: Event<TestChangeEvent>;\n\n\t\t/**\n\t\t * An event the fires when all test providers have signalled that the tests\n\t\t * the observer references have been discovered. Providers may continue to\n\t\t * watch for changes and cause {@link onDidChangeTest} to fire as files\n\t\t * change, until the observer is disposed.\n\t\t *\n\t\t * @todo as below\n\t\t */\n\t\treadonly onDidDiscoverInitialTests: Event<void>;\n\n\t\t/**\n\t\t * Dispose of the observer, allowing VS Code to eventually tell test\n\t\t * providers that they no longer need to update tests.\n\t\t */\n\t\tdispose(): void;\n\t}\n\n\texport interface TestChangeEvent {\n\t\t/**\n\t\t * List of all tests that are newly added.\n\t\t */\n\t\treadonly added: ReadonlyArray<TestItem>;\n\n\t\t/**\n\t\t * List of existing tests that have updated.\n\t\t */\n\t\treadonly updated: ReadonlyArray<TestItem>;\n\n\t\t/**\n\t\t * List of existing tests that have been removed.\n\t\t */\n\t\treadonly removed: ReadonlyArray<TestItem>;\n\n\t\t/**\n\t\t * Highest node in the test tree under which changes were made. This can\n\t\t * be easily plugged into events like the TreeDataProvider update event.\n\t\t */\n\t\treadonly commonChangeAncestor: TestItem | null;\n\t}\n\n\t/**\n\t * Tree of tests returned from the provide methods in the {@link TestProvider}.\n\t */\n\texport interface TestHierarchy<T extends TestItem> {\n\t\t/**\n\t\t * Root node for tests. The `testRoot` instance must not be replaced over\n\t\t * the lifespan of the TestHierarchy, since you will need to reference it\n\t\t * in `onDidChangeTest` when a test is added or removed.\n\t\t */\n\t\treadonly root: T;\n\n\t\t/**\n\t\t * An event that fires when an existing test under the `root` changes.\n\t\t * This can be a result of a state change in a test run, a property update,\n\t\t * or an update to its children. Changes made to tests will not be visible\n\t\t * to {@link TestObserver} instances until this event is fired.\n\t\t *\n\t\t * This will signal a change recursively to all children of the given node.\n\t\t * For example, firing the event with the {@link testRoot} will refresh\n\t\t * all tests.\n\t\t */\n\t\treadonly onDidChangeTest: Event<T>;\n\n\t\t/**\n\t\t * An event that should be fired when all tests that are currently defined\n\t\t * have been discovered. The provider should continue to watch for changes\n\t\t * and fire `onDidChangeTest` until the hierarchy is disposed.\n\t\t *\n\t\t * @todo can this be covered by existing progress apis? Or return a promise\n\t\t */\n\t\treadonly onDidDiscoverInitialTests: Event<void>;\n\n\t\t/**\n\t\t * Dispose will be called when there are no longer observers interested\n\t\t * in the hierarchy.\n\t\t */\n\t\tdispose(): void;\n\t}\n\n\t/**\n\t * Discovers and provides tests. It's expected that the TestProvider will\n\t * ambiently listen to {@link vscode.window.onDidChangeVisibleTextEditors} to\n\t * provide test information about the open files for use in code lenses and\n\t * other file-specific UI.\n\t *\n\t * Additionally, the UI may request it to discover tests for the workspace\n\t * via `addWorkspaceTests`.\n\t *\n\t * @todo rename from provider\n\t */\n\texport interface TestProvider<T extends TestItem = TestItem> {\n\t\t/**\n\t\t * Requests that tests be provided for the given workspace. This will\n\t\t * generally be called when tests need to be enumerated for the\n\t\t * workspace.\n\t\t *\n\t\t * It's guaranteed that this method will not be called again while\n\t\t * there is a previous undisposed watcher for the given workspace folder.\n\t\t */\n\t\tcreateWorkspaceTestHierarchy?(workspace: WorkspaceFolder): TestHierarchy<T>;\n\n\t\t/**\n\t\t * Requests that tests be provided for the given document. This will\n\t\t * be called when tests need to be enumerated for a single open file,\n\t\t * for instance by code lens UI.\n\t\t */\n\t\tcreateDocumentTestHierarchy?(document: TextDocument): TestHierarchy<T>;\n\n\t\t/**\n\t\t * Starts a test run. This should cause {@link onDidChangeTest} to\n\t\t * fire with update test states during the run.\n\t\t * @todo this will eventually need to be able to return a summary report, coverage for example.\n\t\t */\n\t\trunTests?(options: TestRunOptions<T>, cancellationToken: CancellationToken): ProviderResult<void>;\n\t}\n\n\t/**\n\t * Options given to `TestProvider.runTests`\n\t */\n\texport interface TestRunOptions<T extends TestItem = TestItem> {\n\t\t/**\n\t\t * Array of specific tests to run. The {@link TestProvider.testRoot} may\n\t\t * be provided as an indication to run all tests.\n\t\t */\n\t\ttests: T[];\n\n\t\t/**\n\t\t * Whether or not tests in this run should be debugged.\n\t\t */\n\t\tdebug: boolean;\n\t}\n\n\t/**\n\t * A test item is an item shown in the \"test explorer\" view. It encompasses\n\t * both a suite and a test, since they have almost or identical capabilities.\n\t */\n\texport interface TestItem {\n\t\t/**\n\t\t * Display name describing the test case.\n\t\t */\n\t\tlabel: string;\n\n\t\t/**\n\t\t * Optional description that appears next to the label.\n\t\t */\n\t\tdescription?: string;\n\n\t\t/**\n\t\t * Whether this test item can be run individually, defaults to `true`\n\t\t * if not provided.\n\t\t *\n\t\t * In some cases, like Go's tests, test can have children but these\n\t\t * children cannot be run independently.\n\t\t */\n\t\trunnable?: boolean;\n\n\t\t/**\n\t\t * Whether this test item can be debugged. Defaults to `false` if not provided.\n\t\t */\n\t\tdebuggable?: boolean;\n\n\t\t/**\n\t\t * VS Code location.\n\t\t */\n\t\tlocation?: Location;\n\n\t\t/**\n\t\t * Optional list of nested tests for this item.\n\t\t */\n\t\tchildren?: TestItem[];\n\n\t\t/**\n\t\t * Test run state. Will generally be {@link TestRunState.Unset} by\n\t\t * default.\n\t\t */\n\t\tstate: TestState;\n\t}\n\n\texport enum TestRunState {\n\t\t// Initial state\n\t\tUnset = 0,\n\t\t// Test is currently running\n\t\tRunning = 1,\n\t\t// Test run has passed\n\t\tPassed = 2,\n\t\t// Test run has failed (on an assertion)\n\t\tFailed = 3,\n\t\t// Test run has been skipped\n\t\tSkipped = 4,\n\t\t// Test run failed for some other reason (compilation error, timeout, etc)\n\t\tErrored = 5,\n\t}\n\n\t/**\n\t * TestState includes a test and its run state. This is included in the\n\t * {@link TestItem} and is immutable; it should be replaced in th TestItem\n\t * in order to update it. This allows consumers to quickly and easily check\n\t * for changes via object identity.\n\t */\n\texport class TestState {\n\t\t/**\n\t\t * Current state of the test.\n\t\t */\n\t\treadonly runState: TestRunState;\n\n\t\t/**\n\t\t * Optional duration of the test run, in milliseconds.\n\t\t */\n\t\treadonly duration?: number;\n\n\t\t/**\n\t\t * Associated test run message. Can, for example, contain assertion\n\t\t * failure information if the test fails.\n\t\t */\n\t\treadonly messages: ReadonlyArray<Readonly<TestMessage>>;\n\n\t\t/**\n\t\t * @param state Run state to hold in the test state\n\t\t * @param messages List of associated messages for the test\n\t\t * @param duration Length of time the test run took, if appropriate.\n\t\t */\n\t\tconstructor(runState: TestRunState, messages?: TestMessage[], duration?: number);\n\t}\n\n\t/**\n\t * Represents the severity of test messages.\n\t */\n\texport enum TestMessageSeverity {\n\t\tError = 0,\n\t\tWarning = 1,\n\t\tInformation = 2,\n\t\tHint = 3,\n\t}\n\n\t/**\n\t * Message associated with the test state. Can be linked to a specific\n\t * source range -- useful for assertion failures, for example.\n\t */\n\texport interface TestMessage {\n\t\t/**\n\t\t * Human-readable message text to display.\n\t\t */\n\t\tmessage: string | MarkdownString;\n\n\t\t/**\n\t\t * Message severity. Defaults to \"Error\", if not provided.\n\t\t */\n\t\tseverity?: TestMessageSeverity;\n\n\t\t/**\n\t\t * Expected test output. If given with `actual`, a diff view will be shown.\n\t\t */\n\t\texpectedOutput?: string;\n\n\t\t/**\n\t\t * Actual test output. If given with `actual`, a diff view will be shown.\n\t\t */\n\t\tactualOutput?: string;\n\n\t\t/**\n\t\t * Associated file location.\n\t\t */\n\t\tlocation?: Location;\n\t}\n\t//#endregion\n\n\t//#region Statusbar Item Background Color (https://github.com/microsoft/vscode/issues/110214)\n\n\t/**\n\t * A status bar item is a status bar contribution that can\n\t * show text and icons and run a command on click.\n\t */\n\texport interface StatusBarItem {\n\t\t/**\n\t\t * The background color for this entry.\n\t\t *\n\t\t * Note: only `new ThemeColor('statusBarItem.errorBackground')` is\n\t\t * supported for now. More background colors may be supported in the\n\t\t * future.\n\t\t *\n\t\t * Note: when a background color is set, the statusbar may override\n\t\t * the `color` choice to ensure the entry is readable in all themes.\n\t\t */\n\t\tbackgroundColor: ThemeColor | undefined;\n\t}\n\n\t//#endregion\n}\n"
  },
  {
    "path": "extensions/github1s/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"strictNullChecks\": true,\n    \"experimentalDecorators\": true,\n    \"outDir\": \"out\",\n    \"lib\": [\"WebWorker\", \"es2016\"],\n    \"sourceMap\": true,\n    \"baseUrl\": \"src\",\n    \"paths\": {\n      \"@/*\": [\"*\"]\n    }\n  },\n  \"include\": [\n    \"src\"\n  ]\n}"
  },
  {
    "path": "extensions/github1s/webpack.config.js",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n//@ts-check\n'use strict';\n\n//@ts-check\n/** WebpackConfig */\n/* eslint-disable @typescript-eslint/no-require-imports */\nconst webpack = require('webpack');\nconst path = require('path');\nconst NodePolyfillPlugin = require('node-polyfill-webpack-plugin');\n\nmodule.exports = {\n\tcontext: __dirname,\n\tmode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')\n\ttarget: 'webworker', // extensions run in a webworker context\n\tentry: {\n\t\textension: './src/extension.ts',\n\t},\n\tresolve: {\n\t\tmainFields: ['module', 'main'],\n\t\textensions: ['.ts', '.js'], // support ts-files and js-files\n\t\talias: {\n\t\t\t'@': path.resolve(__dirname, 'src'),\n\t\t},\n\t},\n\tmodule: {\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: /\\.ts$/,\n\t\t\t\texclude: /node_modules/,\n\t\t\t\tuse: [\n\t\t\t\t\t{\n\t\t\t\t\t\t// configure TypeScript loader:\n\t\t\t\t\t\t// * enable sources maps for end-to-end source maps\n\t\t\t\t\t\tloader: 'ts-loader',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tcompilerOptions: {\n\t\t\t\t\t\t\t\tsourceMap: true,\n\t\t\t\t\t\t\t\tdeclaration: false,\n\t\t\t\t\t\t\t\texperimentalDecorators: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t},\n\texternals: {\n\t\tvscode: 'commonjs vscode', // ignored because it doesn't exist\n\t},\n\tperformance: {\n\t\thints: false,\n\t},\n\toutput: {\n\t\tfilename: 'extension.js',\n\t\tpath: path.join(__dirname, 'dist'),\n\t\tlibraryTarget: 'commonjs',\n\t},\n\tdevtool: 'source-map',\n\tplugins: [\n\t\tnew webpack.DefinePlugin({\n\t\t\tGITHUB_ORIGIN: JSON.stringify(process.env.GITHUB_DOMAIN || 'https://github.com'),\n\t\t\tGITHUB_API_PREFIX: JSON.stringify(process.env.GITHUB_API_PREFIX || 'https://api.github.com'),\n\t\t\tGITLAB_ORIGIN: JSON.stringify(process.env.GITLAB_DOMAIN || 'https://gitlab.com'),\n\t\t\tGITLAB_API_PREFIX: JSON.stringify(process.env.GITLAB_API_PREFIX || 'https://gitlab.com/api/v4'),\n\t\t}),\n\t\tnew webpack.ProvidePlugin({\n\t\t\tprocess: 'process/browser.js',\n\t\t}),\n\t\tnew NodePolyfillPlugin(),\n\t],\n};\n"
  },
  {
    "path": "extensions/nim-web/LICENSE",
    "content": "vscode-nim\n\nThe MIT License (MIT)\n\nCopyright (c) Xored Software Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to deal in the Software without restriction, \nincluding without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, \nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT \nNOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. \nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH \nTHE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "extensions/nim-web/README.md",
    "content": "# This extension is a fork from [vscode-nim](https://github.com/saem/vscode-nim) for github1s\n\n# At present only languages features is reserved\n\n# I have deleted some files and only reserved the necessary code\n\n# Nim Extension\n\nVisual Studio:\n[![Version](https://vsmarketplacebadge.apphb.com/version/nimsaem.nimvscode.svg)](https://marketplace.visualstudio.com/items?itemName=nimsaem.nimvscode)\n[![Ratings](https://vsmarketplacebadge.apphb.com/rating/nimsaem.nimvscode.svg)](https://vsmarketplacebadge.apphb.com/rating/nimsaem.nimvscode.svg)\n\nOpen-VSX:\n[![Version](https://img.shields.io/open-vsx/v/nimsaem/nimvscode)](https://open-vsx.org/extension/nimsaem/nimvscode)\n[![Installs](https://img.shields.io/open-vsx/dt/nimsaem/nimvscode)](https://open-vsx.org/extension/nimsaem/nimvscode)\n[![Ratings](https://img.shields.io/open-vsx/rating/nimsaem/nimvscode)](https://open-vsx.org/extension/nimsaem/nimvscode)\n\nThis extension adds language support for the Nim language to VS Code, including:\n\n- Syntax Highlight (nim, nimble, nim.cfg)\n"
  },
  {
    "path": "extensions/nim-web/nimcfg.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"#\",\n    \"blockComment\": [\"#[\", \"]#\"]\n  },\n  \"brackets\": [\n    [\"[\", \"]\"],\n    [\"(\", \")\"]\n  ],\n  \"autoClosingPairs\": [\n    [\"#[\", \"]#\"],\n    { \"open\": \"[\", \"close\": \"]\", \"notIn\": [\"comment\"] },\n    [\"(\", \")\"],\n    { \"open\": \"\\\"\", \"close\": \"\\\"\", \"notIn\": [\"string\", \"comment\"] }\n  ],\n  \"surroundingPairs\": [\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"'\", \"'\"],\n    [\"\\\"\", \"\\\"\"]\n  ],\n  \"folding\": {\n    \"offSide\": true,\n    \"markers\": {\n      \"start\": \"^\\\\s*#region\",\n      \"end\": \"^\\\\s*#endregion\"\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/nim-web/package.json",
    "content": "{\n  \"name\": \"nimvscode\",\n  \"displayName\": \"Nim\",\n  \"description\": \"Nim language support for Visual Studio Code written in Nim\",\n  \"version\": \"0.1.17\",\n  \"publisher\": \"nimsaem\",\n  \"author\": {\n    \"name\": \"Saem\"\n  },\n  \"license\": \"MIT\",\n  \"icon\": \"images/nim_icon.png\",\n  \"homepage\": \"https://github.com/saem/vscode-nim/blob/main/README.md\",\n  \"categories\": [\n    \"Programming Languages\",\n    \"Linters\"\n  ],\n  \"galleryBanner\": {\n    \"color\": \"#2C2A35\",\n    \"theme\": \"dark\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/saem/vscode-nim.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/saem/vscode-nim/issues\"\n  },\n  \"scripts\": {\n    \"vscode:prepublish\": \"nimble release\",\n    \"compile\": \"echo done\",\n    \"watch\": \"echo done\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {},\n  \"engines\": {\n    \"vscode\": \"^1.27.0\"\n  },\n  \"activationEvents\": [\n    \"onLanguage:nim\",\n    \"onLanguage:nimcfg\",\n    \"onLanguage:nimble\",\n    \"onCommand:nim.build\",\n    \"onCommand:nim.run\",\n    \"onCommand:nim.runTest\",\n    \"onCommand:nim.execSelectionInTerminal\"\n  ],\n  \"main\": \"./out/nimvscode.js\",\n  \"contributes\": {\n    \"languages\": [\n      {\n        \"id\": \"nim\",\n        \"aliases\": [\n          \"Nim\",\n          \"nim\"\n        ],\n        \"extensions\": [\n          \".nim\",\n          \".nims\",\n          \"nim.cfg\",\n          \".nim.cfg\"\n        ],\n        \"configuration\": \"./nimcfg.json\"\n      },\n      {\n        \"id\": \"nimble\",\n        \"aliases\": [\n          \"Nimble\",\n          \"nimble\"\n        ],\n        \"extensions\": [\n          \".nimble\"\n        ],\n        \"configuration\": \"./nimcfg.json\"\n      }\n    ],\n    \"grammars\": [\n      {\n        \"language\": \"nim\",\n        \"scopeName\": \"source.nim\",\n        \"path\": \"./syntaxes/nim.json\"\n      },\n      {\n        \"language\": \"nimble\",\n        \"scopeName\": \"source.nimble\",\n        \"path\": \"./syntaxes/nimble.json\"\n      }\n    ],\n    \"problemMatchers\": [\n      {\n        \"name\": \"nim\",\n        \"owner\": \"nim\",\n        \"fileLocation\": \"absolute\",\n        \"severity\": \"error\",\n        \"pattern\": {\n          \"regexp\": \"(?!^(\\\\.+|Hint|\\\\s+$))(.*)\\\\((\\\\d+),\\\\s(\\\\d+)\\\\)\\\\s+((Error|Warning|Hint):\\\\s(.*)|(template/generic instantiation from here.*))(\\\\s\\\\[.*\\\\])?\",\n          \"file\": 2,\n          \"line\": 3,\n          \"column\": 4,\n          \"severity\": 6,\n          \"message\": 7\n        }\n      },\n      {\n        \"name\": \"nim test\",\n        \"owner\": \"nim\",\n        \"fileLocation\": \"absolute\",\n        \"pattern\": [\n          {\n            \"regexp\": \"  \\\\[(OK|FAILED|SKIPPED)\\\\] (.*)\",\n            \"severity\": 1,\n            \"code\": 2\n          },\n          {\n            \"regexp\": \"    (.*)\\\\((\\\\d+), (\\\\d+)\\\\): (.*)\",\n            \"file\": 1,\n            \"line\": 2,\n            \"column\": 3,\n            \"message\": 4,\n            \"loop\": true\n          }\n        ]\n      }\n    ],\n    \"commands\": [\n      {\n        \"command\": \"nim.run.file\",\n        \"title\": \"Run selected Nim file\",\n        \"category\": \"Nim\"\n      },\n      {\n        \"command\": \"nim.check\",\n        \"title\": \"Check Nim project\",\n        \"category\": \"Nim\"\n      },\n      {\n        \"command\": \"nim.execSelectionInTerminal\",\n        \"title\": \"Run Selection/Line in Nim Terminal\",\n        \"category\": \"Nim\"\n      },\n      {\n        \"command\": \"nim.clearCaches\",\n        \"title\": \"Clear internal caches\",\n        \"category\": \"Nim\"\n      },\n      {\n        \"command\": \"nim.listCandidateProjects\",\n        \"title\": \"List candidate nim projects\",\n        \"category\": \"Nim\"\n      }\n    ],\n    \"menus\": {\n      \"editor/context\": [\n        {\n          \"when\": \"editorLangId == 'nim'\",\n          \"command\": \"nim.run.file\",\n          \"group\": \"run@1\"\n        }\n      ]\n    },\n    \"keybindings\": [\n      {\n        \"key\": \"F6\",\n        \"command\": \"nim.run.file\",\n        \"when\": \"editorLangId == 'nim'\"\n      },\n      {\n        \"key\": \"ctrl+alt+b\",\n        \"command\": \"nim.check\",\n        \"when\": \"editorLangId == 'nim'\"\n      },\n      {\n        \"key\": \"shift+enter\",\n        \"command\": \"nim.execSelectionInTerminal\",\n        \"when\": \"editorFocus && editorLangId == nim && !findInputFocussed && !replaceInputFocussed\"\n      }\n    ],\n    \"configuration\": {\n      \"type\": \"object\",\n      \"title\": \"Nim configuration\",\n      \"properties\": {\n        \"nim.project\": {\n          \"type\": \"array\",\n          \"default\": [],\n          \"description\": \"Nim project file, if empty use current selected.\"\n        },\n        \"nim.projectMapping\": {\n          \"type\": \"object\",\n          \"default\": {},\n          \"description\": \"For non project mode list of per file project mapping using regex, for example ```{\\\"(.*).inim\\\": \\\"$1.nim\\\"}```\"\n        },\n        \"nim.test-project\": {\n          \"type\": \"string\",\n          \"default\": \"\",\n          \"description\": \"Optional test project.\"\n        },\n        \"nim.buildOnSave\": {\n          \"type\": \"boolean\",\n          \"default\": false,\n          \"description\": \"Execute build task from tasks.json file on save.\"\n        },\n        \"nim.buildCommand\": {\n          \"type\": \"string\",\n          \"default\": \"c\",\n          \"description\": \"Nim build command (c, cpp, doc, etc)\"\n        },\n        \"nim.runOutputDirectory\": {\n          \"type\": \"string\",\n          \"default\": \"\",\n          \"description\": \"Output directory for run selected file command. The directory is relative to the workspace root.\"\n        },\n        \"nim.lintOnSave\": {\n          \"type\": \"boolean\",\n          \"default\": true,\n          \"description\": \"Check code by using 'nim check' on save.\"\n        },\n        \"nim.enableNimsuggest\": {\n          \"type\": \"boolean\",\n          \"default\": true,\n          \"description\": \"Enable calling nimsuggest process to provide completion suggestions, hover suggestions, etc.\\nThis option requires restart to take effect.\"\n        },\n        \"nim.useNimsuggestCheck\": {\n          \"type\": \"boolean\",\n          \"default\": false,\n          \"description\": \"Use nimsuggest in order to run check, instead of the nim compiler.\"\n        },\n        \"nim.logNimsuggest\": {\n          \"type\": \"boolean\",\n          \"default\": false,\n          \"description\": \"Enable verbose logging of nimsuggest to use profile directory.\"\n        },\n        \"nim.licenseString\": {\n          \"type\": \"string\",\n          \"default\": \"\",\n          \"description\": \"Optional license text that will be inserted on nim file creation.\"\n        },\n        \"nim.nimsuggestRestartTimeout\": {\n          \"type\": \"integer\",\n          \"default\": 60,\n          \"description\": \"Nimsuggest will be restarted after this timeout in minutes, if 0 then restart disabled.\\nThis option requires restart to take effect.\"\n        },\n        \"nim.nimprettyIndent\": {\n          \"type\": \"integer\",\n          \"default\": 0,\n          \"description\": \"Nimpretty: set the number of spaces that is used for indentation\\n--indent:0 means autodetection (default behaviour).\"\n        },\n        \"nim.nimprettyMaxLineLen\": {\n          \"type\": \"integer\",\n          \"default\": 80,\n          \"description\": \"Nimpretty: set the desired maximum line length (default: 80).\"\n        }\n      }\n    },\n    \"breakpoints\": [\n      {\n        \"language\": \"nim\"\n      }\n    ],\n    \"snippets\": [\n      {\n        \"language\": \"nim\",\n        \"path\": \"./snippets/nim.json\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "extensions/nim-web/snippets/nim.json",
    "content": "{\n  \".source.nim\": {\n    \"procedure\": {\n      \"prefix\": \"proc\",\n      \"body\": \"proc ${1:name}(${2:arguments}): ${3:return type} =\\n\\t$0\"\n    },\n    \"function\": {\n      \"prefix\": \"func\",\n      \"body\": \"func ${1:name}(${2:arguments}): ${3:return type} =\\n\\t$0\"\n    },\n    \"method\": {\n      \"prefix\": \"method\",\n      \"body\": \"method ${1:name}(${2:arguments}): ${3:return type} =\\n\\t$0\"\n    },\n    \"iterator\": {\n      \"prefix\": \"iterator\",\n      \"body\": \"iterator ${1:name}(${2:arguments}): ${3:return type}$0\"\n    },\n    \"array\": {\n      \"prefix\": \"array\",\n      \"body\": \"array[${1:length}, ${2:type}]$0\"\n    },\n    \"sequence\": {\n      \"prefix\": \"seq\",\n      \"body\": \"seq[${1:type}]$0\"\n    },\n    \"if\": {\n      \"prefix\": \"if\",\n      \"body\": \"if ${1:expression}:\\n\\t$0\"\n    },\n    \"for\": {\n      \"prefix\": \"for\",\n      \"body\": \"for ${1:index} in ${2:sequence}:\\n\\t$0\"\n    },\n    \"while\": {\n      \"prefix\": \"while\",\n      \"body\": \"while ${1:expression}:\\n\\t$0\"\n    },\n    \"block\": {\n      \"prefix\": \"block\",\n      \"body\": \"block ${1:name}:\\n\\t$0\"\n    },\n    \"case\": {\n      \"prefix\": \"case\",\n      \"body\": \"case ${1:value}\\n$0\"\n    },\n    \"of\": {\n      \"prefix\": \"of\",\n      \"body\": \"of ${1:value}:\\n\\t$0\"\n    },\n    \"import from\": {\n      \"prefix\": \"from\",\n      \"body\": \"from ${1:module} import ${2:field}\"\n    },\n    \"import\": {\n      \"prefix\": \"import\",\n      \"body\": \"import ${1:module}\"\n    },\n    \"try-except\": {\n      \"prefix\": \"try\",\n      \"body\": \"try:\\n\\t$0\\nexcept ${1:exception}:\\n\\t\"\n    },\n    \"template\": {\n      \"prefix\": \"template\",\n      \"body\": \"template ${1:name}(${2:arguments}): ${3:return type} =\\n\\t$0\"\n    },\n    \"macro\": {\n      \"prefix\": \"macro\",\n      \"body\": \"macro ${1:name}(${2:arguments}): ${3:return type} =\\n\\t$0\"\n    },\n    \"pragma\": {\n      \"prefix\": \"pr\",\n      \"body\": \"{.${1:name}.}\"\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/nim-web/syntaxes/nim.json",
    "content": "{\n  \"fileTypes\": [\"nim\"],\n  \"keyEquivalent\": \"^~N\",\n  \"name\": \"Nim\",\n  \"patterns\": [\n    {\n      \"begin\": \"[ \\\\t]*##\\\\[\",\n      \"contentName\": \"comment.block.doc-comment.content.nim\",\n      \"end\": \"\\\\]##\",\n      \"name\": \"comment.block.doc-comment.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#multilinedoccomment\",\n          \"name\": \"comment.block.doc-comment.nested.nim\"\n        }\n      ]\n    },\n    {\n      \"begin\": \"[ \\\\t]*#\\\\[\",\n      \"contentName\": \"comment.block.content.nim\",\n      \"end\": \"\\\\]#\",\n      \"name\": \"comment.block.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#multilinecomment\",\n          \"name\": \"comment.block.nested.nim\"\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^[ \\\\t]+)?(?=##)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"punctuation.whitespace.comment.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)\",\n      \"patterns\": [\n        {\n          \"begin\": \"##\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.comment.nim\"\n            }\n          },\n          \"end\": \"\\\\n\",\n          \"name\": \"comment.line.number-sign.doc-comment.nim\"\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^[ \\\\t]+)?(?=#[^\\\\[])\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"punctuation.whitespace.comment.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)\",\n      \"patterns\": [\n        {\n          \"begin\": \"#\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.comment.nim\"\n            }\n          },\n          \"end\": \"\\\\n\",\n          \"name\": \"comment.line.number-sign.nim\"\n        }\n      ]\n    },\n    {\n      \"comment\": \"A nim procedure or method\",\n      \"name\": \"meta.proc.nim\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(proc|method|template|macro|iterator|converter|func)\\\\s+\\\\`?([^\\\\:\\\\{\\\\s\\\\`\\\\*\\\\(]*)\\\\`?(\\\\s*\\\\*)?\\\\s*(?=\\\\(|\\\\=|:|\\\\[|\\\\n|\\\\{)\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other\"\n            },\n            \"2\": {\n              \"name\": \"entity.name.function.nim\"\n            },\n            \"3\": {\n              \"name\": \"keyword.control.export\"\n            }\n          },\n          \"end\": \"\\\\)\",\n          \"patterns\": [\n            {\n              \"include\": \"source.nim\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"begin\": \"discard \\\"\\\"\\\"\",\n      \"comment\": \"A discarded triple string literal comment\",\n      \"end\": \"\\\"\\\"\\\"(?!\\\")\",\n      \"name\": \"comment.line.discarded.nim\"\n    },\n    {\n      \"include\": \"#float_literal\"\n    },\n    {\n      \"include\": \"#integer_literal\"\n    },\n    {\n      \"comment\": \"Operator as function name\",\n      \"match\": \"(?<=\\\\`)[^\\\\` ]+(?=\\\\`)\",\n      \"name\": \"entity.name.function.nim\"\n    },\n    {\n      \"captures\": {\n        \"1\": {\n          \"name\": \"keyword.control.export\"\n        }\n      },\n      \"comment\": \"Export qualifier.\",\n      \"match\": \"\\\\b\\\\s*(\\\\*)(?:\\\\s*(?=[,:])|\\\\s+(?=[=]))\"\n    },\n    {\n      \"comment\": \"Export qualifier following a type def.\",\n      \"match\": \"\\\\b([A-Z]\\\\w+)(\\\\*)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"support.type.nim\"\n        },\n        \"2\": {\n          \"name\": \"keyword.control.export\"\n        }\n      }\n    },\n    {\n      \"include\": \"#string_literal\"\n    },\n    {\n      \"comment\": \"Language Constants.\",\n      \"match\": \"\\\\b(true|false|Inf|NegInf|NaN|nil)\\\\b\",\n      \"name\": \"constant.language.nim\"\n    },\n    {\n      \"comment\": \"Keywords that affect program control flow or scope.\",\n      \"match\": \"\\\\b(block|break|case|continue|do|elif|else|end|except|finally|for|if|raise|return|try|when|while|yield)\\\\b\",\n      \"name\": \"keyword.control.nim\"\n    },\n    {\n      \"comment\": \"Keyword boolean operators for expressions.\",\n      \"match\": \"(\\\\b(and|in|is|isnot|not|notin|or|xor)\\\\b)\",\n      \"name\": \"keyword.boolean.nim\"\n    },\n    {\n      \"comment\": \"Generic operators for expressions.\",\n      \"match\": \"(=|\\\\+|-|\\\\*|/|<|>|@|\\\\$|~|&|%|!|\\\\?|\\\\^|\\\\.|:|\\\\\\\\)+\",\n      \"name\": \"keyword.operator.nim\"\n    },\n    {\n      \"comment\": \"Other keywords.\",\n      \"match\": \"(\\\\b(addr|as|asm|atomic|bind|cast|const|converter|concept|defer|discard|distinct|div|enum|export|from|import|include|let|mod|mixin|object|of|ptr|ref|shl|shr|static|type|using|var|tuple|iterator|macro|func|method|proc|template)\\\\b)\",\n      \"name\": \"keyword.other.nim\"\n    },\n    {\n      \"comment\": \"Invalid and unused keywords.\",\n      \"match\": \"(\\\\b(generic|interface|lambda|out|shared)\\\\b)\",\n      \"name\": \"invalid.illegal.invalid-keyword.nim\"\n    },\n    {\n      \"comment\": \"Common functions\",\n      \"match\": \"\\\\b(new|await|assert|echo|defined|declared|newException|countup|countdown|high|low)\\\\b\",\n      \"name\": \"keyword.other.common.function.nim\"\n    },\n    {\n      \"comment\": \"Built-in, concrete types.\",\n      \"match\": \"\\\\b(((uint|int)(8|16|32|64)?)|cint|float(32|64)?|bool|string|auto|cstring|char|byte|tobject|typedesc|stmt|expr|any|untyped|typed)\\\\b\",\n      \"name\": \"storage.type.concrete.nim\"\n    },\n    {\n      \"comment\": \"Built-in, generic types.\",\n      \"match\": \"\\\\b(range|array|seq|set|pointer)\\\\b\",\n      \"name\": \"storage.type.generic.nim\"\n    },\n    {\n      \"comment\": \"Special types.\",\n      \"match\": \"\\\\b(openArray|varargs|void)\\\\b\",\n      \"name\": \"storage.type.generic.nim\"\n    },\n    {\n      \"comment\": \"Other constants.\",\n      \"match\": \"\\\\b[A-Z][A-Z0-9_]+\\\\b\",\n      \"name\": \"support.constant.nim\"\n    },\n    {\n      \"comment\": \"Other types.\",\n      \"match\": \"\\\\b[A-Z]\\\\w+\\\\b\",\n      \"name\": \"support.type.nim\"\n    },\n    {\n      \"comment\": \"Function call.\",\n      \"match\": \"\\\\b\\\\w+\\\\b(?=(\\\\[([a-zA-Z0-9_,]|\\\\s)+\\\\])?\\\\()\",\n      \"name\": \"support.function.any-method.nim\"\n    },\n    {\n      \"comment\": \"Function call (no parenthesis).\",\n      \"match\": \"(?!(openArray|varargs|void|range|array|seq|set|pointer|new|await|assert|echo|defined|declared|newException|countup|countdown|high|low|((uint|int)(8|16|32|64)?)|float(32|64)?|bool|string|auto|cstring|char|byte|tobject|typedesc|stmt|expr|any|untyped|typed|addr|as|asm|atomic|bind|cast|const|converter|concept|defer|discard|distinct|div|enum|export|from|import|include|let|mod|mixin|object|of|ptr|ref|shl|shr|static|type|using|var|tuple|iterator|macro|func|method|proc|template|and|in|is|isnot|not|notin|or|xor|proc|method|template|macro|iterator|converter|func|true|false|Inf|NegInf|NaN|nil|block|break|case|continue|do|elif|else|end|except|finally|for|if|raise|return|try|when|while|yield)\\\\b)\\\\w+\\\\s+(?!(and|in|is|isnot|not|notin|or|xor|[^a-zA-Z0-9_\\\"'`(-+]+)\\\\b)(?=[a-zA-Z0-9_\\\"'`(-+])\",\n      \"name\": \"support.function.any-method.nim\"\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=\\\\{\\\\.emit: ?\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\{\\\\.(emit:) ?(\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"source.c\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")(\\\\.{0,1}\\\\})?\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"source.c\"\n            }\n          },\n          \"name\": \"meta.embedded.block.c\",\n          \"patterns\": [\n            {\n              \"begin\": \"\\\\`\",\n              \"end\": \"\\\\`\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"source.c\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"begin\": \"\\\\{\\\\.\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.pragma.start.nim\"\n        }\n      },\n      \"end\": \"\\\\.?\\\\}\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.pragma.end.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b([[:alpha:]]\\\\w*)(?:\\\\s|\\\\s*:)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"meta.preprocessor.pragma.nim\"\n            }\n          },\n          \"end\": \"(?=\\\\.?\\\\}|,)\",\n          \"patterns\": [\n            {\n              \"include\": \"source.nim\"\n            }\n          ]\n        },\n        {\n          \"begin\": \"\\\\b([[:alpha:]]\\\\w*)\\\\(\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"meta.preprocessor.pragma.nim\"\n            }\n          },\n          \"end\": \"\\\\)\",\n          \"patterns\": [\n            {\n              \"include\": \"source.nim\"\n            }\n          ]\n        },\n        {\n          \"match\": \"\\\\b([[:alpha:]]\\\\w*)(?=\\\\.?\\\\}|,)\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"meta.preprocessor.pragma.nim\"\n            }\n          }\n        },\n        {\n          \"begin\": \"\\\\b([[:alpha:]]\\\\w*)(\\\"\\\"\\\")\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"meta.preprocessor.pragma.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.definition.string.begin.nim\"\n            }\n          },\n          \"end\": \"\\\"\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.end.nim\"\n            }\n          },\n          \"name\": \"string.quoted.triple.raw.nim\"\n        },\n        {\n          \"begin\": \"\\\\b([[:alpha:]]\\\\w*)(\\\")\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"meta.preprocessor.pragma.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.definition.string.begin.nim\"\n            }\n          },\n          \"end\": \"\\\"\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.end.nim\"\n            }\n          },\n          \"name\": \"string.quoted.double.raw.nim\"\n        },\n        {\n          \"begin\": \"\\\\b(hint\\\\[\\\\w+\\\\]):\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"meta.preprocessor.pragma.nim\"\n            }\n          },\n          \"end\": \"(?=\\\\.?\\\\}|,)\",\n          \"patterns\": [\n            {\n              \"include\": \"source.nim\"\n            }\n          ]\n        },\n        {\n          \"match\": \",\",\n          \"name\": \"punctuation.separator.comma.nim\"\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=asm \\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(asm) (\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"source.asm\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"source.asm\"\n            }\n          },\n          \"name\": \"meta.embedded.block.asm\",\n          \"patterns\": [\n            {\n              \"begin\": \"\\\\`\",\n              \"end\": \"\\\\`\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"source.asm\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"captures\": {\n        \"1\": {\n          \"name\": \"storage.type.function.nim\"\n        },\n        \"2\": {\n          \"name\": \"keyword.operator.nim\"\n        }\n      },\n      \"comment\": \"tmpl specifier\",\n      \"match\": \"(tmpl(i)?)(?=( (html|xml|js|css|glsl|md))?\\\"\\\"\\\")\"\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=html\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(html)(\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"text.html\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"text.html\"\n            }\n          },\n          \"name\": \"meta.embedded.block.html\",\n          \"patterns\": [\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\(\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\)\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\{\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\}\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)(for|while|case|of|when|if|else|elif)( )\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"(\\\\{|\\\\n)\",\n              \"endCaptures\": {\n                \"1\": {\n                  \"name\": \"plain\"\n                }\n              },\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"match\": \"(?<!\\\\$)(\\\\$\\\\w+)\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"text.html.basic\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=xml\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(xml)(\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"text.xml\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"text.xml\"\n            }\n          },\n          \"name\": \"meta.embedded.block.xml\",\n          \"patterns\": [\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\(\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\)\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\{\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\}\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)(for|while|case|of|when|if|else|elif)( )\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"(\\\\{|\\\\n)\",\n              \"endCaptures\": {\n                \"1\": {\n                  \"name\": \"plain\"\n                }\n              },\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"match\": \"(?<!\\\\$)(\\\\$\\\\w+)\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"text.xml\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=js\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(js)(\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"source.js\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"source.js\"\n            }\n          },\n          \"name\": \"meta.embedded.block.js\",\n          \"patterns\": [\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\(\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\)\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\{\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\}\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)(for|while|case|of|when|if|else|elif)( )\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"(\\\\{|\\\\n)\",\n              \"endCaptures\": {\n                \"1\": {\n                  \"name\": \"plain\"\n                }\n              },\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"match\": \"(?<!\\\\$)(\\\\$\\\\w+)\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"source.js\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=css\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(css)(\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"source.css\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"source.css\"\n            }\n          },\n          \"name\": \"meta.embedded.block.css\",\n          \"patterns\": [\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\(\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\)\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\{\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\}\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)(for|while|case|of|when|if|else|elif)( )\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"(\\\\{|\\\\n)\",\n              \"endCaptures\": {\n                \"1\": {\n                  \"name\": \"plain\"\n                }\n              },\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"match\": \"(?<!\\\\$)(\\\\$\\\\w+)\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"source.css\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=glsl\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(glsl)(\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"source.glsl\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"source.glsl\"\n            }\n          },\n          \"name\": \"meta.embedded.block.glsl\",\n          \"patterns\": [\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\(\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\)\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\{\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\}\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)(for|while|case|of|when|if|else|elif)( )\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"(\\\\{|\\\\n)\",\n              \"endCaptures\": {\n                \"1\": {\n                  \"name\": \"plain\"\n                }\n              },\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"match\": \"(?<!\\\\$)(\\\\$\\\\w+)\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"source.glsl\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"begin\": \"(^\\\\s*)?(?=md\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.leading.nim\"\n        }\n      },\n      \"end\": \"(?!\\\\G)(\\\\s*$\\\\n?)?\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.whitespace.embedded.trailing.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(md)(\\\"\\\"\\\")\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.nim\"\n            },\n            \"2\": {\n              \"name\": \"punctuation.section.embedded.begin.nim\"\n            }\n          },\n          \"contentName\": \"text.html.markdown\",\n          \"end\": \"(\\\")\\\"\\\"(?!\\\")\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.section.embedded.end.nim\"\n            },\n            \"1\": {\n              \"name\": \"text.html.markdown\"\n            }\n          },\n          \"name\": \"meta.embedded.block.html.markdown\",\n          \"patterns\": [\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\(\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\)\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)\\\\{\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"\\\\}\",\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(?<!\\\\$)(\\\\$)(for|while|case|of|when|if|else|elif)( )\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"keyword.operator.nim\"\n                },\n                \"2\": {\n                  \"name\": \"keyword.operator.nim\"\n                }\n              },\n              \"end\": \"(\\\\{|\\\\n)\",\n              \"endCaptures\": {\n                \"1\": {\n                  \"name\": \"plain\"\n                }\n              },\n              \"patterns\": [\n                {\n                  \"include\": \"source.nim\"\n                }\n              ]\n            },\n            {\n              \"match\": \"(?<!\\\\$)(\\\\$\\\\w+)\",\n              \"name\": \"keyword.operator.nim\"\n            },\n            {\n              \"include\": \"text.html.markdown\"\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"repository\": {\n    \"multilinecomment\": {\n      \"begin\": \"#\\\\[\",\n      \"end\": \"\\\\]#\",\n      \"patterns\": [\n        {\n          \"include\": \"#multilinecomment\"\n        }\n      ]\n    },\n    \"multilinedoccomment\": {\n      \"begin\": \"##\\\\[\",\n      \"end\": \"\\\\]##\",\n      \"patterns\": [\n        {\n          \"include\": \"#multilinedoccomment\"\n        }\n      ]\n    },\n    \"char_escapes\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\\\\\[cC]|\\\\\\\\[rR]\",\n          \"name\": \"constant.character.escape.carriagereturn.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[lL]|\\\\\\\\[nN]\",\n          \"name\": \"constant.character.escape.linefeed.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[fF]\",\n          \"name\": \"constant.character.escape.formfeed.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[tT]\",\n          \"name\": \"constant.character.escape.tabulator.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[vV]\",\n          \"name\": \"constant.character.escape.verticaltabulator.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\\\\\\\\"\",\n          \"name\": \"constant.character.escape.double-quote.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\'\",\n          \"name\": \"constant.character.escape.single-quote.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[0-9]+\",\n          \"name\": \"constant.character.escape.chardecimalvalue.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[aA]\",\n          \"name\": \"constant.character.escape.alert.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[bB]\",\n          \"name\": \"constant.character.escape.backspace.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[eE]\",\n          \"name\": \"constant.character.escape.escape.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[xX]\\\\h\\\\h\",\n          \"name\": \"constant.character.escape.hex.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\\\\\\\\\\",\n          \"name\": \"constant.character.escape.backslash.nim\"\n        }\n      ]\n    },\n    \"string_escapes\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\\\\\[pP]\",\n          \"name\": \"constant.character.escape.newline.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[uU]\\\\h\\\\h\\\\h\\\\h\",\n          \"name\": \"constant.character.escape.hex.nim\"\n        },\n        {\n          \"match\": \"\\\\\\\\[uU]\\\\{\\\\h+\\\\}\",\n          \"name\": \"constant.character.escape.hex.nim\"\n        },\n        {\n          \"include\": \"#char_escapes\"\n        }\n      ]\n    },\n    \"raw_string_escapes\": {\n      \"match\": \"[^\\\"](\\\"\\\")\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"constant.character.escape.double-quote.nim\"\n        }\n      }\n    },\n    \"fmt_interpolation\": {\n      \"begin\": \"\\\\{\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.template-expression.begin.nim\"\n        }\n      },\n      \"end\": \"\\\\}\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.template-expression.end.nim\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \":\",\n          \"end\": \"(?=\\\\})\",\n          \"name\": \"meta.template.format-specifier.nim\"\n        },\n        {\n          \"include\": \"source.nim\"\n        }\n      ],\n      \"name\": \"meta.template.expression.nim\"\n    },\n    \"string_literal\": {\n      \"patterns\": [\n        {\n          \"include\": \"#fmt_string_triple\"\n        },\n        {\n          \"include\": \"#fmt_string_triple_operator\"\n        },\n        {\n          \"include\": \"#extended_string_quoted_triple_raw\"\n        },\n        {\n          \"include\": \"#string_quoted_triple_raw\"\n        },\n        {\n          \"include\": \"#fmt_string_operator\"\n        },\n        {\n          \"include\": \"#fmt_string\"\n        },\n        {\n          \"include\": \"#fmt_string_call\"\n        },\n        {\n          \"include\": \"#string_quoted_double_raw\"\n        },\n        {\n          \"include\": \"#extended_string_quoted_double_raw\"\n        },\n        {\n          \"include\": \"#string_quoted_single\"\n        },\n        {\n          \"include\": \"#string_quoted_triple\"\n        },\n        {\n          \"include\": \"#string_quoted_double\"\n        }\n      ]\n    },\n    \"fmt_string\": {\n      \"begin\": \"\\\\b(fmt)(\\\")\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"support.function.any-method.nim\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"end\": \"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.double.raw.nim\",\n      \"patterns\": [\n        {\n          \"match\": \"(?<!\\\")\\\"(?!\\\")\",\n          \"name\": \"invalid.illegal.nim\"\n        },\n        {\n          \"include\": \"#raw_string_escapes\"\n        },\n        {\n          \"include\": \"#fmt_interpolation\"\n        }\n      ]\n    },\n    \"fmt_string_triple\": {\n      \"begin\": \"\\\\b(fmt)(\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"support.function.any-method.nim\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"end\": \"\\\"\\\"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.triple.raw.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#fmt_interpolation\"\n        }\n      ]\n    },\n    \"fmt_string_operator\": {\n      \"begin\": \"(&)(\\\")\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.operator.nim\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"end\": \"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.double.nim\",\n      \"patterns\": [\n        {\n          \"match\": \"\\\"\",\n          \"name\": \"invalid.illegal.nim\"\n        },\n        {\n          \"include\": \"#string_escapes\"\n        },\n        {\n          \"include\": \"#fmt_interpolation\"\n        }\n      ]\n    },\n    \"fmt_string_triple_operator\": {\n      \"begin\": \"(&)(\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.operator.nim\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"end\": \"\\\"\\\"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.triple.raw.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#fmt_interpolation\"\n        }\n      ]\n    },\n    \"fmt_string_call\": {\n      \"begin\": \"(fmt)\\\\((?=\\\")\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"support.function.any-method.nim\"\n        }\n      },\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\"\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.begin.nim\"\n            }\n          },\n          \"end\": \"\\\"(?=\\\\))\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.end.nim\"\n            }\n          },\n          \"name\": \"string.quoted.double.nim\",\n          \"patterns\": [\n            {\n              \"match\": \"\\\"\",\n              \"name\": \"invalid.illegal.nim\"\n            },\n            {\n              \"include\": \"#string_escapes\"\n            },\n            {\n              \"include\": \"#fmt_interpolation\"\n            }\n          ]\n        }\n      ]\n    },\n    \"string_quoted_double\": {\n      \"begin\": \"\\\"\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"comment\": \"Double Quoted String\",\n      \"end\": \"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.double.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#string_escapes\"\n        }\n      ]\n    },\n    \"string_quoted_double_raw\": {\n      \"begin\": \"\\\\br\\\"\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"end\": \"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.double.raw.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#raw_string_escapes\"\n        }\n      ]\n    },\n    \"extended_string_quoted_double_raw\": {\n      \"begin\": \"\\\\b(\\\\w+)(\\\")\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"support.function.any-method.nim\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"end\": \"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.double.raw.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#raw_string_escapes\"\n        }\n      ]\n    },\n    \"string_quoted_single\": {\n      \"begin\": \"'\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"comment\": \"Single quoted character literal\",\n      \"end\": \"'\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.single.nim\",\n      \"patterns\": [\n        {\n          \"include\": \"#char_escapes\"\n        },\n        {\n          \"match\": \"([^']{2,}?)\",\n          \"name\": \"invalid.illegal.character.nim\"\n        }\n      ]\n    },\n    \"string_quoted_triple\": {\n      \"begin\": \"\\\"\\\"\\\"\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"comment\": \"Triple Quoted String\",\n      \"end\": \"\\\"\\\"\\\"(?!\\\")\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.triple.nim\"\n    },\n    \"string_quoted_triple_raw\": {\n      \"begin\": \"r\\\"\\\"\\\"\",\n      \"beginCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"comment\": \"Raw Triple Quoted String\",\n      \"end\": \"\\\"\\\"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.triple.raw.nim\"\n    },\n    \"extended_string_quoted_triple_raw\": {\n      \"begin\": \"\\\\b(\\\\w+)(\\\"\\\"\\\")\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"support.function.any-method.nim\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.definition.string.begin.nim\"\n        }\n      },\n      \"end\": \"\\\"\\\"\\\"\",\n      \"endCaptures\": {\n        \"0\": {\n          \"name\": \"punctuation.definition.string.end.nim\"\n        }\n      },\n      \"name\": \"string.quoted.triple.raw.nim\"\n    },\n    \"float_literal\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\b\\\\d[_\\\\d]*((\\\\.\\\\d[_\\\\d]*([eE][\\\\+\\\\-]?\\\\d[_\\\\d]*)?)|([eE][\\\\+\\\\-]?\\\\d[_\\\\d]*))('([fF](32|64|128)|[fFdD]))?\",\n          \"name\": \"constant.numeric.float.decimal.nim\"\n        },\n        {\n          \"match\": \"\\\\b0[xX]\\\\h[_\\\\h]*'([fF](32|64|128)|[fFdD])\",\n          \"name\": \"constant.numeric.float.hexadecimal.nim\"\n        },\n        {\n          \"match\": \"\\\\b0o[0-7][_0-7]*'([fF](32|64|128)|[fFdD])\",\n          \"name\": \"constant.numeric.float.octal.nim\"\n        },\n        {\n          \"match\": \"\\\\b0(b|B)[01][_01]*'([fF](32|64|128)|[fFdD])\",\n          \"name\": \"constant.numeric.float.binary.nim\"\n        },\n        {\n          \"match\": \"\\\\b(\\\\d[_\\\\d]*)'([fF](32|64|128)|[fFdD])\",\n          \"name\": \"constant.numeric.float.decimal.nim\"\n        }\n      ]\n    },\n    \"integer_literal\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\b(0[xX]\\\\h[_\\\\h]*)('(([iIuU](8|16|32|64))|[uU]))?\",\n          \"name\": \"constant.numeric.integer.hexadecimal.nim\"\n        },\n        {\n          \"match\": \"\\\\b(0o[0-7][_0-7]*)('(([iIuU](8|16|32|64))|[uU]))?\",\n          \"name\": \"constant.numeric.integer.octal.nim\"\n        },\n        {\n          \"match\": \"\\\\b(0(b|B)[01][_01]*)('(([iIuU](8|16|32|64))|[uU]))?\",\n          \"name\": \"constant.numeric.integer.binary.nim\"\n        },\n        {\n          \"match\": \"\\\\b(\\\\d[_\\\\d]*)('(([iIuU](8|16|32|64))|[uU]))?\",\n          \"name\": \"constant.numeric.integer.decimal.nim\"\n        }\n      ]\n    }\n  },\n  \"scopeName\": \"source.nim\",\n  \"uuid\": \"6DD62CE8-B129-4554-BD8E-CE5DB490E5A4\"\n}\n"
  },
  {
    "path": "extensions/nim-web/syntaxes/nimble.json",
    "content": "{\n  \"name\": \"nimble\",\n  \"scopeName\": \"source.nimble\",\n  \"fileTypes\": [\"nimble\"],\n  \"foldingStartMarker\": \"\",\n  \"foldingStopMarker\": \"\",\n  \"patterns\": [\n    { \"include\": \"#comments\" },\n    { \"include\": \"#strings\" },\n    { \"include\": \"#category\" },\n    { \"include\": \"#keywords\" },\n    { \"include\": \"#text\" }\n  ],\n  \"repository\": {\n    \"category\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.control.nimble\",\n          \"match\": \"^\\\\[\\\\w+\\\\]$\"\n        }\n      ]\n    },\n    \"comments\": {\n      \"patterns\": [\n        {\n          \"name\": \"comment.line.nimble\",\n          \"match\": \"#.*$\"\n        }\n      ]\n    },\n    \"keywords\": {\n      \"patterns\": [\n        {\n          \"name\": \"entity.name.section.nimble\",\n          \"match\": \"author|name|version|description|license\"\n        },\n        {\n          \"name\": \"variable.nimble\",\n          \"match\": \"SkipDirs|SkipFiles|SkipExt|InstallDirs|InstallFiles|InstallExt|srcDir|binDir|bin|backend|requires\"\n        },\n        {\n          \"name\": \"meta.selector.nimble\",\n          \"match\": \"\\\\:\"\n        }\n      ]\n    },\n    \"strings\": {\n      \"patterns\": [\n        {\n          \"name\": \"string.quoted.double.nimble\",\n          \"begin\": \"(?=[^\\\\\\\\])(\\\")\",\n          \"end\": \"(\\\")\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"punctuation.definition.string.begin.nimble\"\n            }\n          },\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"punctuation.definition.string.end.nimble\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"name\": \"punctuation.separator.string.ignore-eol.nimble\",\n              \"match\": \"\\\\\\\\$[ \\\\t]*\"\n            },\n            {\n              \"name\": \"constant.character.string.escape.nimble\",\n              \"match\": \"\\\\\\\\([\\\\\\\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})\"\n            },\n            {\n              \"name\": \"invalid.illeagal.character.string.nimble\",\n              \"match\": \"\\\\\\\\(?![\\\\\\\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).\"\n            }\n          ]\n        }\n      ]\n    },\n    \"text\": {\n      \"patterns\": [\n        {\n          \"name\": \"text.nimble\",\n          \"match\": \"\\\\\\\\\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/LICENSE",
    "content": "ISC License\n\nCopyright (c) 2019 OCaml Labs\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "extensions/ocaml-web/README.md",
    "content": "# This extension is a fork from [vscode-ocaml-platform](https://github.com/ocamllabs/vscode-ocaml-platform) for github1s.\n\n# At present only languages features is reserved\n\n# I have deleted some files and only reserved the necessary code\n\n# VSCode OCaml Platform\n\n[![Main workflow](https://img.shields.io/github/workflow/status/ocamllabs/vscode-ocaml-platform/Main%20workflow?branch=master)](https://github.com/ocamllabs/vscode-ocaml-platform/actions?query=workflow%3A%22Main+workflow%22+branch%3Amaster)\n\nVisual Studio Code extension for OCaml and relevant tools.\n\n_Please report any bugs you encounter._\n\n## Features\n\n- Syntax highlighting\n  - ATD\n  - Cram tests\n  - Dune\n  - Menhir\n  - Merlin\n  - META\n  - OASIS\n  - OCaml\n  - OCamlbuild\n  - OCamlFormat\n  - OCamllex\n  - opam\n  - ReasonML\n  - Eliom\n- Indentation rules\n- Snippets\n  - Dune\n  - OCaml\n  - OCamllex\n- Task Provider\n  - Dune\n"
  },
  {
    "path": "extensions/ocaml-web/languages/META.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"#\"\n  },\n  \"brackets\": [[\"(\", \")\"]],\n  \"autoClosingPairs\": [\n    { \"open\": \"(\", \"close\": \")\" },\n    { \"open\": \"\\\"\", \"close\": \"\\\"\", \"notIn\": [\"string\"] }\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/dune.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \";\"\n  },\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"]\n  ],\n  \"autoClosingPairs\": [\n    { \"open\": \"{\", \"close\": \"}\" },\n    { \"open\": \"[\", \"close\": \"]\" },\n    { \"open\": \"(\", \"close\": \")\" },\n    { \"open\": \"\\\"\", \"close\": \"\\\"\", \"notIn\": [\"string\", \"comment\"] }\n  ],\n  \"surroundingPairs\": [\n    { \"open\": \"[\", \"close\": \"]\" },\n    { \"open\": \"(\", \"close\": \")\" },\n    { \"open\": \"\\\"\", \"close\": \"\\\"\" }\n  ],\n  \"wordPattern\": {\n    \"pattern\": \"[A-Za-z_'`][A-Za-z_'.0-9]*\"\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/menhir.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"//\",\n    \"blockComment\": [\"/*\", \"*/\"]\n  },\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"<\", \">\"],\n    [\"%{\", \"%}\"]\n  ],\n  \"autoClosingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"<\", \">\"],\n    [\"\\\"\", \"\\\"\"],\n    [\"'\", \"'\"],\n    [\"%{\", \"%}\"]\n  ],\n  \"surroundingPairs\": [\n    [\"(\", \")\"],\n    [\"<\", \">\"],\n    [\"\\\"\", \"\\\"\"]\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/oasis.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"#\"\n  },\n  \"autoClosingPairs\": [{ \"open\": \"\\\"\", \"close\": \"\\\"\", \"notIn\": [\"string\"] }]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/ocaml.json",
    "content": "{\n  \"autoClosingPairs\": [\n    { \"open\": \"{\", \"close\": \"}\" },\n    { \"open\": \"[\", \"close\": \"]\" },\n    { \"open\": \"(\", \"close\": \")\" },\n    { \"open\": \"\\\"\", \"close\": \"\\\"\", \"notIn\": [\"string\"] },\n    { \"open\": \"(*\", \"close\": \"*\", \"notIn\": [\"string\"] }\n  ],\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"[|\", \"|]\"]\n  ],\n  \"comments\": {\n    \"blockComment\": [\"(*\", \"*)\"]\n  },\n  \"surroundingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"'\", \"'\"],\n    [\"\\\"\", \"\\\"\"]\n  ],\n  \"indentationRules\": {\n    \"decreaseIndentPattern\": \"^\\\\s*(end|done|with|in|else)\\\\b|^\\\\s*;;\",\n    \"increaseIndentPattern\": \"\\\\b(begin|object)\\\\s*$|\\\\blet [a-zA-Z0-9_-]+( [^ ]+)* =\\\\s*$|method!?[ \\\\t]+.*=[ \\\\t]*$|->[ \\\\t]*$|\\\\b(for|while)(_lwt)?[ \\\\t]+.*[ \\\\t]+do[ \\\\t]*$|(\\\\btry(_lwt)?$|\\\\bif\\\\s+.*\\\\sthen$|\\\\belse|[:=]\\\\s*sig|=\\\\s*struct)\\\\s*$\",\n    \"indentNextLinePattern\": \"(?!\\\\bif.*then.*(else.*|(;|[ \\\\t]in)[ \\\\t]*$))\\\\bif|\\\\bthen[ \\\\t]*$|\\\\belse[ \\\\t]*$$\"\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/ocamlbuild.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"#\"\n  },\n  \"brackets\": [\n    [\"(\", \")\"],\n    [\"{\", \"}\"],\n    [\"<\", \">\"]\n  ],\n  \"autoClosingPairs\": [\n    { \"open\": \"(\", \"close\": \")\" },\n    { \"open\": \"{\", \"close\": \"}\" },\n    { \"open\": \"<\", \"close\": \">\" },\n    { \"open\": \"\\\"\", \"close\": \"\\\"\", \"notIn\": [\"string\"] }\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/ocamlformat.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"#\"\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/ocamllex.json",
    "content": "{\n  \"comments\": {\n    \"blockComment\": [\"(*\", \"*)\"]\n  },\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"]\n  ],\n  \"autoClosingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"\\\"\", \"\\\"\"],\n    [\"'\", \"'\"]\n  ],\n  \"surroundingPairs\": [\n    [\"(\", \")\"],\n    [\"\\\"\", \"\\\"\"]\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/opam-install.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"#\"\n  },\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"]\n  ],\n  \"autoClosingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"\\\"\", \"\\\"\"]\n  ],\n  \"surroundingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"\\\"\", \"\\\"\"]\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/opam.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"#\"\n  },\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"]\n  ],\n  \"autoClosingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"\\\"\", \"\\\"\"],\n    [\"'\", \"'\"],\n    [\"\\\"\\\"\\\"\", \"\\\"\\\"\\\"\"]\n  ],\n  \"surroundingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"\\\"\", \"\\\"\"],\n    [\"'\", \"'\"],\n    [\"\\\"\\\"\\\"\", \"\\\"\\\"\\\"\"]\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/languages/reason.json",
    "content": "{\n  \"autoClosingPairs\": [\n    { \"open\": \"{\", \"close\": \"}\" },\n    { \"open\": \"[\", \"close\": \"]\" },\n    { \"open\": \"(\", \"close\": \")\" },\n    { \"open\": \"\\\"\", \"close\": \"\\\"\", \"notIn\": [\"string\"] },\n    { \"open\": \"/**\", \"close\": \" */\", \"notIn\": [\"string\"] }\n  ],\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"]\n  ],\n  \"comments\": {\n    \"lineComment\": \"//\",\n    \"blockComment\": [\"/*\", \"*/\"]\n  },\n  \"surroundingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"'\", \"'\"],\n    [\"\\\"\", \"\\\"\"]\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/package.json",
    "content": "{\n  \"name\": \"ocaml-platform\",\n  \"displayName\": \"OCaml Platform\",\n  \"description\": \"Official OCaml Support from OCamlLabs\",\n  \"license\": \"MIT\",\n  \"version\": \"1.6.0\",\n  \"publisher\": \"ocamllabs\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/ocamllabs/vscode-ocaml-platform\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/ocamllabs/vscode-ocaml-platform/issues\"\n  },\n  \"homepage\": \"https://github.com/ocamllabs/vscode-ocaml-platform\",\n  \"engines\": {\n    \"vscode\": \"^1.53.0\"\n  },\n  \"categories\": [\n    \"Programming Languages\"\n  ],\n  \"activationEvents\": [\n    \"onLanguage:ocaml\",\n    \"onLanguage:ocaml.interface\",\n    \"onLanguage:reason\",\n    \"onLanguage:ocaml.ocamllex\",\n    \"onLanguage:ocaml.menhir\",\n    \"onLanguage:dune\",\n    \"onLanguage:dune-project\",\n    \"onLanguage:dune-workspace\"\n  ],\n  \"icon\": \"assets/logo.png\",\n  \"contributes\": {\n    \"configurationDefaults\": {\n      \"[ocaml]\": {\n        \"editor.tabSize\": 2,\n        \"editor.insertSpaces\": true\n      },\n      \"[dune]\": {\n        \"editor.tabSize\": 1,\n        \"editor.insertSpaces\": true\n      },\n      \"[dune-project]\": {\n        \"editor.tabSize\": 1,\n        \"editor.insertSpaces\": true\n      },\n      \"[dune-workspace]\": {\n        \"editor.tabSize\": 1,\n        \"editor.insertSpaces\": true\n      },\n      \"[cram]\": {\n        \"editor.tabSize\": 2,\n        \"editor.insertSpaces\": true\n      }\n    },\n    \"languages\": [\n      {\n        \"id\": \"dune\",\n        \"aliases\": [\n          \"dune\"\n        ],\n        \"extensions\": [\n          \"dune\",\n          \"jbuild\"\n        ],\n        \"configuration\": \"./languages/dune.json\"\n      },\n      {\n        \"id\": \"dune-project\",\n        \"aliases\": [\n          \"dune project\"\n        ],\n        \"extensions\": [\n          \"dune-project\"\n        ],\n        \"configuration\": \"./languages/dune.json\"\n      },\n      {\n        \"id\": \"dune-workspace\",\n        \"aliases\": [\n          \"dune workspace\"\n        ],\n        \"filenames\": [\n          \"dune-workspace\"\n        ],\n        \"filenamePatterns\": [\n          \"dune-workspace.*\"\n        ],\n        \"configuration\": \"./languages/dune.json\"\n      },\n      {\n        \"id\": \"ocaml.merlin\",\n        \"aliases\": [\n          \"Merlin\",\n          \"merlin\"\n        ],\n        \"extensions\": [\n          \".merlin\"\n        ]\n      },\n      {\n        \"id\": \"ocaml\",\n        \"aliases\": [\n          \"OCaml\",\n          \"ocaml\"\n        ],\n        \"extensions\": [\n          \".ml\",\n          \".eliom\",\n          \".ocamlinit\"\n        ],\n        \"configuration\": \"./languages/ocaml.json\"\n      },\n      {\n        \"id\": \"ocaml.interface\",\n        \"aliases\": [\n          \"OCaml Interface\",\n          \"ocaml interface\"\n        ],\n        \"extensions\": [\n          \".mli\",\n          \".eliomi\"\n        ],\n        \"configuration\": \"./languages/ocaml.json\"\n      },\n      {\n        \"id\": \"ocaml.opam\",\n        \"aliases\": [\n          \"opam\"\n        ],\n        \"filenames\": [\n          \"opam\"\n        ],\n        \"extensions\": [\n          \".opam\",\n          \".opam.locked\",\n          \".opam.template\"\n        ],\n        \"configuration\": \"./languages/opam.json\"\n      },\n      {\n        \"id\": \"ocaml.opam-install\",\n        \"aliases\": [\n          \"opam install\"\n        ],\n        \"extensions\": [\n          \".install\"\n        ],\n        \"configuration\": \"./languages/opam-install.json\"\n      },\n      {\n        \"id\": \"ocaml.META\",\n        \"aliases\": [\n          \"META\",\n          \"meta\"\n        ],\n        \"filenames\": [\n          \"META\"\n        ],\n        \"filenamePatterns\": [\n          \"META.*\"\n        ],\n        \"configuration\": \"./languages/META.json\"\n      },\n      {\n        \"id\": \"ocaml.ocamlbuild\",\n        \"aliases\": [\n          \"OCamlbuild\",\n          \"ocamlbuild\"\n        ],\n        \"extensions\": [\n          \"_tags\"\n        ],\n        \"configuration\": \"./languages/ocamlbuild.json\"\n      },\n      {\n        \"id\": \"ocaml.oasis\",\n        \"aliases\": [\n          \"OASIS\",\n          \"oasis\"\n        ],\n        \"extensions\": [\n          \"_oasis\"\n        ],\n        \"configuration\": \"./languages/oasis.json\"\n      },\n      {\n        \"id\": \"ocaml.ocamldoc\",\n        \"aliases\": [\n          \"OCamldoc\",\n          \"ocamldoc\"\n        ],\n        \"extensions\": [\n          \".mld\"\n        ]\n      },\n      {\n        \"id\": \"ocaml.ocamlformat\",\n        \"aliases\": [\n          \"OCamlFormat\",\n          \"ocamlformat\"\n        ],\n        \"extensions\": [\n          \".ocamlformat\"\n        ],\n        \"configuration\": \"./languages/ocamlformat.json\"\n      },\n      {\n        \"id\": \"ocaml.ocamllex\",\n        \"aliases\": [\n          \"OCamllex\",\n          \"ocamllex\"\n        ],\n        \"extensions\": [\n          \".mll\"\n        ],\n        \"configuration\": \"./languages/ocamllex.json\"\n      },\n      {\n        \"id\": \"ocaml.menhir\",\n        \"aliases\": [\n          \"Menhir\",\n          \"menhir\",\n          \"OCamlyacc\",\n          \"ocamlyacc\"\n        ],\n        \"extensions\": [\n          \".mly\"\n        ],\n        \"configuration\": \"./languages/menhir.json\"\n      },\n      {\n        \"id\": \"atd\",\n        \"aliases\": [\n          \"ATD\",\n          \"atd\"\n        ],\n        \"extensions\": [\n          \".atd\"\n        ],\n        \"configuration\": \"./languages/ocaml.json\"\n      },\n      {\n        \"id\": \"reason\",\n        \"aliases\": [\n          \"Reason\",\n          \"reason\"\n        ],\n        \"extensions\": [\n          \".re\",\n          \".rei\"\n        ],\n        \"configuration\": \"./languages/reason.json\"\n      },\n      {\n        \"id\": \"cram\",\n        \"aliases\": [\n          \"Cram Test\",\n          \"Cram\",\n          \"cram\"\n        ],\n        \"extensions\": [\n          \".t\"\n        ]\n      }\n    ],\n    \"grammars\": [\n      {\n        \"language\": \"dune\",\n        \"scopeName\": \"source.dune\",\n        \"path\": \"./syntaxes/dune.json\"\n      },\n      {\n        \"language\": \"dune-project\",\n        \"scopeName\": \"source.dune-project\",\n        \"path\": \"./syntaxes/dune-project.json\"\n      },\n      {\n        \"language\": \"dune-workspace\",\n        \"scopeName\": \"source.dune-workspace\",\n        \"path\": \"./syntaxes/dune-workspace.json\"\n      },\n      {\n        \"language\": \"ocaml.merlin\",\n        \"scopeName\": \"source.ocaml.merlin\",\n        \"path\": \"./syntaxes/merlin.json\"\n      },\n      {\n        \"scopeName\": \"markdown.ocaml.codeblock\",\n        \"path\": \"./syntaxes/ocaml-markdown-codeblock.json\",\n        \"injectTo\": [\n          \"text.html.markdown\"\n        ],\n        \"embeddedLanguages\": {\n          \"meta.embedded.block.ocaml\": \"ocaml\"\n        }\n      },\n      {\n        \"language\": \"ocaml\",\n        \"scopeName\": \"source.ocaml\",\n        \"path\": \"./syntaxes/ocaml.json\"\n      },\n      {\n        \"language\": \"ocaml.interface\",\n        \"scopeName\": \"source.ocaml.interface\",\n        \"path\": \"./syntaxes/ocaml.interface.json\"\n      },\n      {\n        \"language\": \"ocaml.ocamlbuild\",\n        \"scopeName\": \"source.ocaml.ocamlbuild\",\n        \"path\": \"./syntaxes/ocamlbuild.json\"\n      },\n      {\n        \"language\": \"ocaml.ocamldoc\",\n        \"scopeName\": \"source.ocaml.ocamldoc\",\n        \"path\": \"./syntaxes/ocamldoc.json\"\n      },\n      {\n        \"language\": \"ocaml.ocamlformat\",\n        \"scopeName\": \"source.ocaml.ocamlformat\",\n        \"path\": \"./syntaxes/ocamlformat.json\"\n      },\n      {\n        \"language\": \"ocaml.ocamllex\",\n        \"scopeName\": \"source.ocaml.ocamllex\",\n        \"path\": \"./syntaxes/ocamllex.json\"\n      },\n      {\n        \"scopeName\": \"source.action.menhir\",\n        \"path\": \"./syntaxes/menhir-action.json\",\n        \"injectTo\": [\n          \"source.ocaml\"\n        ]\n      },\n      {\n        \"language\": \"ocaml.menhir\",\n        \"scopeName\": \"source.ocaml.menhir\",\n        \"path\": \"./syntaxes/menhir.json\",\n        \"embeddedLanguages\": {\n          \"source.embedded-action.menhir\": \"source.action.menhir\"\n        }\n      },\n      {\n        \"language\": \"ocaml.opam\",\n        \"scopeName\": \"source.ocaml.opam\",\n        \"path\": \"./syntaxes/opam.json\"\n      },\n      {\n        \"language\": \"ocaml.opam-install\",\n        \"scopeName\": \"source.ocaml.opam-install\",\n        \"path\": \"./syntaxes/opam-install.json\"\n      },\n      {\n        \"language\": \"ocaml.META\",\n        \"scopeName\": \"source.ocaml.META\",\n        \"path\": \"./syntaxes/META.json\"\n      },\n      {\n        \"language\": \"ocaml.oasis\",\n        \"scopeName\": \"source.ocaml.oasis\",\n        \"path\": \"./syntaxes/oasis.json\"\n      },\n      {\n        \"language\": \"atd\",\n        \"scopeName\": \"source.atd\",\n        \"path\": \"./syntaxes/atd.json\"\n      },\n      {\n        \"scopeName\": \"markdown.reason.codeblock\",\n        \"path\": \"./syntaxes/reason-markdown-codeblock.json\",\n        \"injectTo\": [\n          \"text.html.markdown\"\n        ],\n        \"embeddedLanguages\": {\n          \"meta.embedded.block.reason\": \"reason\"\n        }\n      },\n      {\n        \"language\": \"reason\",\n        \"scopeName\": \"source.reason\",\n        \"path\": \"./syntaxes/reason.json\"\n      },\n      {\n        \"language\": \"cram\",\n        \"scopeName\": \"source.cram\",\n        \"path\": \"./syntaxes/cram.json\"\n      }\n    ],\n    \"snippets\": [\n      {\n        \"language\": \"dune\",\n        \"path\": \"./snippets/dune.json\"\n      },\n      {\n        \"language\": \"dune-project\",\n        \"path\": \"./snippets/dune-project.json\"\n      },\n      {\n        \"language\": \"ocaml\",\n        \"path\": \"./snippets/ocaml.json\"\n      },\n      {\n        \"language\": \"ocaml.ocamllex\",\n        \"path\": \"./snippets/ocamllex.json\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"compile\": \"echo done\",\n    \"watch\": \"echo done\"\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/snippets/dune-project.json",
    "content": "{\n  \"lang\": {\n    \"prefix\": \"lang\",\n    \"body\": [\"(lang $1 $2)\"]\n  },\n  \"name\": {\n    \"prefix\": \"name\",\n    \"body\": [\"(name $1)\"]\n  },\n  \"using\": {\n    \"prefix\": \"using\",\n    \"body\": [\"(using $1 $2)\"]\n  },\n  \"info\": {\n    \"prefix\": \"info\",\n    \"body\": [\n      \"(license $1)\\n(authors \\\"$2\\\")\\n(maintainers \\\"$3\\\")\\n(source (${4|uri,github|} $5))\\n(bug_reports \\\"$6\\\")\\n(homepage \\\"$7\\\")\\n(documentation \\\"$8\\\")\"\n    ]\n  },\n  \"package\": {\n    \"prefix\": \"package\",\n    \"body\": [\n      \"(package\\n (name $1)\\n (synopsis \\\"$2\\\")\\n (description \\\"$3\\\")\\n (depends $4))\"\n    ]\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/snippets/dune.json",
    "content": "{\n  \"env\": {\n    \"prefix\": \"env\",\n    \"body\": [\"(env\\n ($1 $2))\"]\n  },\n  \"executable\": {\n    \"prefix\": \"executable\",\n    \"body\": [\"(executable\\n (name $1)\\n (public_name $2)\\n (libraries $3))\"]\n  },\n  \"executables\": {\n    \"prefix\": \"executables\",\n    \"body\": [\"(executables\\n (names $1)\\n (public_names $2)\\n (libraries $3))\"]\n  },\n  \"install\": {\n    \"prefix\": \"install\",\n    \"body\": [\"(install\\n (section $1)\\n (files ($2.exe as $3)))\"]\n  },\n  \"library\": {\n    \"prefix\": \"library\",\n    \"body\": [\"(library\\n (name $1)\\n (public_name $2)\\n (libraries $3))\"]\n  },\n  \"rule\": {\n    \"prefix\": \"rule\",\n    \"body\": [\"(rule\\n (alias $1)\\n (deps $2)\\n (targets $3)\\n (action $4))\"]\n  },\n  \"test\": {\n    \"prefix\": \"test\",\n    \"body\": [\"(test\\n (name $1)\\n (libraries $2))\"]\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/snippets/ocaml.json",
    "content": "{\n  \"lambda\": {\n    \"prefix\": \"fun\",\n    \"body\": [\"fun (${1:pattern}) -> ${2:${1:pattern}}\"]\n  },\n  \"let .. in\": {\n    \"prefix\": \"let\",\n    \"body\": [\"let ${1:pattern} = ${2:()} in$0\"]\n  },\n  \"function\": {\n    \"prefix\": \"func\",\n    \"body\": [\"function\\n| $0\"]\n  },\n  \"variant pattern\": {\n    \"prefix\": \"|\",\n    \"body\": [\"| ${1:_} -> $0\"]\n  },\n  \"let (toplevel)\": {\n    \"prefix\": \"let\",\n    \"body\": [\"let ${1:pattern} = $0\"]\n  },\n  \"val\": {\n    \"prefix\": \"val\",\n    \"body\": [\"val ${1:name} : $0\"]\n  },\n  \"sig\": {\n    \"prefix\": \"sig\",\n    \"body\": [\"sig\\n  ${1}\\nend$0\"]\n  },\n  \"struct\": {\n    \"prefix\": \"struct\",\n    \"body\": [\"struct\\n  ${1}\\nend$0\"]\n  },\n  \"module\": {\n    \"prefix\": \"module\",\n    \"body\": [\"module ${1:M} = struct\\n  ${2}\\nend$0\"]\n  },\n  \"module signature\": {\n    \"prefix\": \"module\",\n    \"body\": [\"module ${1:M} : sig\\n  ${2}\\nend$0\"]\n  },\n  \"module type\": {\n    \"prefix\": \"module\",\n    \"body\": [\"module type ${1:M} = sig\\n  ${2}\\nend$0\"]\n  },\n  \"match\": {\n    \"prefix\": \"match\",\n    \"body\": [\"match ${1:scrutinee} with\\n| ${2:pattern} -> ${3:${2:pattern}}\"]\n  },\n  \"type declaration\": {\n    \"prefix\": \"type\",\n    \"body\": [\"type ${1:name} = $0\"]\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/snippets/ocamllex.json",
    "content": "{\n  \"rule\": {\n    \"prefix\": \"rule\",\n    \"body\": [\"rule ${1:pattern} = parse\", \"| $0\"]\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/META.json",
    "content": "{\n  \"scopeName\": \"source.ocaml.META\",\n  \"fileTypes\": [\"META\"],\n  \"patterns\": [{ \"include\": \"#comments\" }, { \"include\": \"#entries\" }],\n  \"repository\": {\n    \"comments\": {\n      \"comment\": \"line comment\",\n      \"name\": \"comment.line.META\",\n      \"begin\": \"#\",\n      \"end\": \"$\"\n    },\n    \"entries\": {\n      \"patterns\": [\n        {\n          \"comment\": \"assignment or addition\",\n          \"match\": \"\\\\b([[:word:].]+)[[:space:]]*(\\\\+?=)[[:space:]]*(\\\".*\\\")\",\n          \"captures\": {\n            \"1\": { \"name\": \"entity.name.tag.META\" },\n            \"2\": { \"name\": \"keyword.operator.META\" },\n            \"3\": { \"name\": \"string.quoted.double.META\" }\n          }\n        },\n        {\n          \"comment\": \"assignment or addition with formal predicates\",\n          \"begin\": \"\\\\b([[:word:].]+)[[:space:]]*\\\\(\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"entity.name.tag.META\" }\n          },\n          \"end\": \"\\\\)[[:space:]]*(\\\\+?=)[[:space:]]*(\\\".*\\\")\",\n          \"endCaptures\": {\n            \"1\": { \"name\": \"keyword.operator.META\" },\n            \"2\": { \"name\": \"string.quoted.double.META\" }\n          },\n          \"patterns\": [\n            { \"match\": \"-\", \"name\": \"keyword.operator.META\" },\n            {\n              \"comment\": \"standard predicates\",\n              \"match\": \"\\\\b(byte|native|toploop|mt|mt_posix|mt_vm|gprof|autolink)\\\\b\",\n              \"name\": \"constant.language.META\"\n            }\n          ]\n        },\n        {\n          \"comment\": \"subpackage\",\n          \"begin\": \"\\\\b(package)[[:space:]]*(\\\"[^.]*\\\")[[:space:]]*\\\\(\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other.META\" },\n            \"2\": { \"name\": \"string.quoted.double.META\" }\n          },\n          \"end\": \"\\\\)\",\n          \"patterns\": [{ \"include\": \"$self\" }]\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/atd.json",
    "content": "{\n  \"name\": \"ATD\",\n  \"scopeName\": \"source.atd\",\n  \"fileTypes\": [\"atd\"],\n  \"patterns\": [\n    { \"include\": \"source.ocaml#comments\" },\n    { \"include\": \"source.ocaml#strings\" },\n    { \"include\": \"#annotations\" },\n    { \"include\": \"#definitions\" },\n    { \"include\": \"#keywords\" },\n    { \"include\": \"#types\" },\n    { \"include\": \"source.ocaml#operators\" },\n    { \"include\": \"source.ocaml#identifiers\" }\n  ],\n  \"repository\": {\n    \"annotations\": {\n      \"patterns\": [\n        {\n          \"begin\": \"(<)[[:space:]]*([[:lower:]_][[:word:]']*)\",\n          \"end\": \">\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other.atd\" },\n            \"2\": { \"name\": \"keyword.other.atd\" }\n          },\n          \"endCaptures\": [{ \"name\": \"keyword.other.atd\" }],\n          \"patterns\": [{ \"include\": \"$self\" }]\n        }\n      ]\n    },\n    \"definitions\": {\n      \"match\": \"\\\\b(type)[[:space:]]+('[[:alpha:]][[:word:]']*[[:space:]]+|\\\\(.*\\\\)[[:space:]]*)?([[:lower:]_][[:word:]']*)\",\n      \"captures\": {\n        \"1\": { \"name\": \"keyword.other.atd\" },\n        \"2\": { \"patterns\": [{ \"include\": \"$self\" }] },\n        \"3\": { \"name\": \"entity.name.function.binding.atd\" }\n      }\n    },\n    \"keywords\": {\n      \"name\": \"keyword.other.atd\",\n      \"match\": \"\\\\b(type|of|inherit)\\\\b(?!')\"\n    },\n    \"types\": {\n      \"patterns\": [\n        {\n          \"comment\": \"type parameter\",\n          \"name\": \"storage.type.ocaml.atd\",\n          \"match\": \"'[[:alpha:]][[:word:]']*\\\\b\"\n        },\n        {\n          \"comment\": \"builtin type\",\n          \"name\": \"support.type.ocaml.atd\",\n          \"match\": \"\\\\b(unit|bool|int|float|string|abstract)\\\\b\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/cram.json",
    "content": "{\n  \"scopeName\": \"source.cram\",\n  \"fileTypes\": [\"t\"],\n  \"patterns\": [\n    {\n      \"comment\": \"command\",\n      \"match\": \"^  (\\\\$|>) (.*)$\",\n      \"captures\": {\n        \"1\": { \"name\": \"keyword.operator.cram\" },\n        \"2\": {\n          \"name\": \"source.cram\",\n          \"patterns\": [{ \"include\": \"#escape\" }, { \"include\": \"#strings\" }]\n        }\n      }\n    },\n    {\n      \"comment\": \"regex output\",\n      \"match\": \"^  (.*) \\\\((re)\\\\)$\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"string.other.cram\",\n          \"patterns\": [{ \"include\": \"#regex\" }]\n        },\n        \"2\": { \"name\": \"keyword.other.cram\" }\n      }\n    },\n    {\n      \"comment\": \"glob output\",\n      \"match\": \"^  (.*) \\\\((glob)\\\\)$\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"string.other.cram\",\n          \"patterns\": [{ \"include\": \"#glob\" }]\n        },\n        \"2\": { \"name\": \"keyword.other.cram\" }\n      }\n    },\n    {\n      \"comment\": \"no end-of-line output\",\n      \"match\": \"^  (.*) \\\\((no-eol)\\\\)$\",\n      \"captures\": {\n        \"1\": { \"name\": \"string.other.cram\" },\n        \"2\": { \"name\": \"keyword.other.cram\" }\n      }\n    },\n    {\n      \"comment\": \"escaped output\",\n      \"match\": \"^  (.*) \\\\((esc)\\\\)$\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"string.other.cram\",\n          \"patterns\": [{ \"include\": \"#escape\" }]\n        },\n        \"2\": { \"name\": \"keyword.other.cram\" }\n      }\n    },\n    {\n      \"comment\": \"output\",\n      \"match\": \"^  (.*)$\",\n      \"captures\": {\n        \"1\": { \"name\": \"string.other.cram\" }\n      }\n    },\n    {\n      \"comment\": \"everything else is a comment\",\n      \"name\": \"comment.line.cram\",\n      \"match\": \"^.*$\"\n    }\n  ],\n  \"repository\": {\n    \"escape\": {\n      \"patterns\": [\n        {\n          \"comment\": \"octal escape\",\n          \"name\": \"constant.character.escape.cram\",\n          \"match\": \"\\\\\\\\0[[:digit:]]+\"\n        },\n        {\n          \"comment\": \"hex escape\",\n          \"name\": \"constant.character.escape.cram\",\n          \"match\": \"\\\\\\\\x[[:xdigit:]]{2}\"\n        },\n        {\n          \"comment\": \"other escaped character\",\n          \"name\": \"constant.character.escape.cram\",\n          \"match\": \"\\\\\\\\.\"\n        }\n      ]\n    },\n    \"strings\": {\n      \"patterns\": [\n        {\n          \"name\": \"string.quoted.double.cram\",\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"|$\",\n          \"patterns\": [{ \"include\": \"#escape\" }]\n        },\n        {\n          \"name\": \"string.quoted.single.cram\",\n          \"begin\": \"'\",\n          \"end\": \"'|$\",\n          \"patterns\": [{ \"include\": \"#escape\" }]\n        }\n      ]\n    },\n    \"glob\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.other.cram\",\n          \"match\": \"[*?]\"\n        },\n        {\n          \"name\": \"keyword.other.cram\",\n          \"match\": \"\\\\\\\\[*?\\\\\\\\]\"\n        }\n      ]\n    },\n    \"regex\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.other.regex\",\n          \"match\": \"\\\\\\\\.\"\n        },\n        {\n          \"name\": \"keyword.other.regex\",\n          \"match\": \"[|^$]\"\n        },\n        {\n          \"begin\": \"\\\\[\\\\^?\",\n          \"end\": \"\\\\]\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.regex\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.other.regex\" }],\n          \"contentName\": \"source.regex\",\n          \"patterns\": [{ \"name\": \"keyword.other.regex\", \"match\": \"-\" }]\n        },\n        {\n          \"begin\": \"\\\\((\\\\?[:=!])?\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.regex\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.other.regex\" }],\n          \"contentName\": \"source.regex\",\n          \"patterns\": [{ \"include\": \"#regex\" }]\n        },\n        {\n          \"begin\": \"{\",\n          \"end\": \"}\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.regex\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.other.regex\" }],\n          \"contentName\": \"source.regex\",\n          \"patterns\": [\n            {\n              \"name\": \"constant.numeric.decimal.integer.regex\",\n              \"match\": \"[[:digit:]]+\"\n            }\n          ]\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/dune-project.json",
    "content": "{\n  \"name\": \"dune-project\",\n  \"scopeName\": \"source.dune-project\",\n  \"fileTypes\": [\"dune-project\"],\n  \"patterns\": [{ \"include\": \"#stanzas\" }, { \"include\": \"#general\" }],\n  \"repository\": {\n    \"stanzas\": {\n      \"patterns\": [\n        {\n          \"comment\": \"lang\",\n          \"begin\": \"\\\\([[:space:]]*(lang)[[:space:]]+(dune)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" },\n            \"2\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"name\",\n          \"begin\": \"\\\\([[:space:]]*(name)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"contentName\": \"variable.other.declaration.dune-project\",\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"version\",\n          \"begin\": \"\\\\([[:space:]]*(version)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"contentName\": \"constant.language.dune-project\",\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"implicit_transitive_deps\",\n          \"begin\": \"\\\\([[:space:]]*(implicit_transitive_deps)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"wrapped_executables\",\n          \"begin\": \"\\\\([[:space:]]*(wrapped_executables)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"explicit_js_mode\",\n          \"match\": \"\\\\([[:space:]]*(explicit_js_mode)[[:space:]]*\\\\)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          }\n        },\n\n        {\n          \"comment\": \"dialect\",\n          \"begin\": \"\\\\([[:space:]]*(dialect)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [\n            {\n              \"comment\": \"name\",\n              \"begin\": \"\\\\([[:space:]]*(name)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"contentName\": \"variable.other.declaration.dune-project\",\n              \"patterns\": [{ \"include\": \"#general\" }]\n            },\n\n            {\n              \"comment\": \"implementation/interface\",\n              \"begin\": \"\\\\([[:space:]]*(implementation|interface)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"patterns\": [\n                {\n                  \"comment\": \"extension/preprocess/format\",\n                  \"begin\": \"\\\\([[:space:]]*(extension|preprocess|format)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-project\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                }\n              ]\n            },\n\n            { \"include\": \"#general\" }\n          ]\n        },\n\n        {\n          \"comment\": \"formatting\",\n          \"begin\": \"\\\\([[:space:]]*(formatting)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [\n            {\n              \"name\": \"constant.language.dune-project\",\n              \"match\": \"\\\\b(disabled)\\\\b\"\n            },\n            {\n              \"begin\": \"\\\\([[:space:]]*(enabled_for)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"patterns\": [{ \"include\": \"#general\" }]\n            },\n            { \"include\": \"#general\" }\n          ]\n        },\n\n        {\n          \"comment\": \"generate_opam_files\",\n          \"begin\": \"\\\\([[:space:]]*(generate_opam_files)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"package\",\n          \"begin\": \"\\\\([[:space:]]*(package)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [\n            {\n              \"comment\": \"name\",\n              \"begin\": \"\\\\([[:space:]]*(name)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"contentName\": \"variable.other.declaration.dune-project\",\n              \"patterns\": [{ \"include\": \"#general\" }]\n            },\n\n            {\n              \"comment\": \"synopsis/description\",\n              \"begin\": \"\\\\([[:space:]]*(synopsis|description)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"patterns\": [{ \"include\": \"#general\" }]\n            },\n\n            {\n              \"comment\": \"depends/conflicts/depopts\",\n              \"begin\": \"\\\\([[:space:]]*(depends|conflicts|depopts)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"patterns\": [\n                {\n                  \"comment\": \"dependency\",\n                  \"name\": \"variable.other.declaration.dune-project\",\n                  \"match\": \"\\\\b([[:alpha:]-]+)\\\\b\"\n                },\n                {\n                  \"comment\": \"dependency constraint\",\n                  \"begin\": \"\\\\([[:space:]]*([[:alpha:]-]+)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"variable.other.declaration.dune-project\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n                { \"include\": \"#general\" }\n              ]\n            },\n\n            {\n              \"comment\": \"tags\",\n              \"begin\": \"\\\\([[:space:]]*(tags)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"contentName\": \"variable.other.declaration.dune-project\",\n              \"patterns\": [{ \"include\": \"#general\" }]\n            },\n\n            {\n              \"comment\": \"deprecated_package_names\",\n              \"begin\": \"\\\\([[:space:]]*(deprecated_package_names)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"patterns\": [{ \"include\": \"#general\" }]\n            },\n\n            { \"include\": \"#opam-metadata\" },\n            { \"include\": \"#general\" }\n          ]\n        },\n\n        {\n          \"comment\": \"using\",\n          \"begin\": \"\\\\([[:space:]]*(using)([[:space:]]+menhir)?\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" },\n            \"2\": { \"name\": \"variable.other.declaration.dune-project\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"cram\",\n          \"begin\": \"\\\\([[:space:]]*(cram)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"contentName\": \"variable.other.declaration.dune-project\",\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        { \"include\": \"#opam-metadata\" }\n      ]\n    },\n\n    \"opam-metadata\": {\n      \"patterns\": [\n        {\n          \"comment\": \"license\",\n          \"begin\": \"\\\\([[:space:]]*(license)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"contentName\": \"constant.language.dune-project\",\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"authors/maintainers\",\n          \"begin\": \"\\\\([[:space:]]*(authors|maintainers)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"source\",\n          \"begin\": \"\\\\([[:space:]]*(source)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [\n            {\n              \"comment\": \"github\",\n              \"begin\": \"\\\\([[:space:]]*(github)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"patterns\": [\n                {\n                  \"name\": \"keyword.language.dune-project\",\n                  \"match\": \"/\"\n                },\n                { \"include\": \"#general\" }\n              ],\n              \"contentName\": \"string.other.line.dune-project\"\n            },\n            {\n              \"comment\": \"uri\",\n              \"begin\": \"\\\\([[:space:]]*(uri)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-project\" }\n              },\n              \"patterns\": [{ \"include\": \"#general\" }]\n            },\n            { \"include\": \"#general\" }\n          ]\n        },\n\n        {\n          \"comment\": \"bug_reports/homepage/documentation\",\n          \"begin\": \"\\\\([[:space:]]*(bug_reports|homepage|documentation)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-project\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        }\n      ]\n    },\n\n    \"general\": {\n      \"patterns\": [\n        {\n          \"name\": \"comment.line.dune\",\n          \"begin\": \";\",\n          \"end\": \"$\"\n        },\n        {\n          \"name\": \"string.quoted.line.dune\",\n          \"begin\": \"\\\"\\\\\\\\\\\\|\",\n          \"end\": \"$\",\n          \"patterns\": [{ \"include\": \"#escape-characters\" }]\n        },\n        {\n          \"name\": \"string.quoted.line.dune\",\n          \"begin\": \"\\\"\\\\\\\\>\",\n          \"end\": \"$\"\n        },\n        {\n          \"name\": \"string.quoted.double.dune\",\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\",\n          \"patterns\": [{ \"include\": \"#escape-characters\" }]\n        },\n        {\n          \"comment\": \"symbol\",\n          \"name\": \"constant.symbol.dune\",\n          \"match\": \"(:[[:alpha:]-]+)\\\\b\"\n        },\n        {\n          \"comment\": \"number or version\",\n          \"name\": \"constant.numeric.dune\",\n          \"match\": \"\\\\b([[:digit:]](\\\\.[[:digit:]]+)+)\\\\b\"\n        },\n        {\n          \"comment\": \"true or false\",\n          \"name\": \"constant.language.dune\",\n          \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n        {\n          \"comment\": \"variable\",\n          \"begin\": \"%\\\\{\",\n          \"end\": \"\\\\}\",\n          \"beginCaptures\": [{ \"name\": \"keyword.operator.dune\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.operator.dune\" }],\n          \"patterns\": [{ \"include\": \"#variables\" }]\n        },\n        {\n          \"comment\": \"boolean/predicate language\",\n          \"begin\": \"\\\\([[:space:]]*(=|<>|>=|<=|<|>)\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": { \"1\": { \"name\": \"keyword.operator.dune\" } },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n        {\n          \"comment\": \"boolean/predicate language\",\n          \"begin\": \"\\\\([[:space:]]*(and|or|not)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": { \"1\": { \"name\": \"keyword.operator.dune\" } },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n        {\n          \"comment\": \"ordered set language\",\n          \"begin\": \"\\\\(\",\n          \"end\": \"\\\\)\",\n          \"patterns\": [\n            { \"name\": \"keyword.operator.dune\", \"match\": \"/\" },\n            { \"include\": \"#general\" }\n          ]\n        }\n      ]\n    },\n\n    \"escape-characters\": {\n      \"patterns\": [\n        {\n          \"comment\": \"escaped newline\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\$\"\n        },\n        {\n          \"comment\": \"escaped character\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\(n|r|b|t|\\\\\\\\|\\\")\"\n        },\n        {\n          \"comment\": \"character from decimal ASCII code\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\[[:digit:]]{3}\"\n        },\n        {\n          \"comment\": \"character from hexadecimal ASCII code\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\x[[:xdigit:]]{2}\"\n        },\n        {\n          \"comment\": \"escaped variable\",\n          \"begin\": \"(\\\\%\\\\{)\",\n          \"end\": \"(\\\\})\",\n          \"beginCaptures\": [{ \"name\": \"constant.character.escape.dune\" }],\n          \"endCaptures\": [{ \"name\": \"constant.character.escape.dune\" }],\n          \"patterns\": [{ \"include\": \"#variables\" }]\n        }\n      ]\n    },\n\n    \"variables\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.operator.variable.dune\",\n          \"match\": \":\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(project_root|workspace_root)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(CC|CXX)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(ocaml_bin|ocaml|ocamlc|ocamlopt|ocaml_version|ocaml_where|ocaml-config)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(profile|null|context_name|ignoring_promoted_rule)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(ext_obj|ext_asm|ext_lib|ext_dll|ext_exe|ext_plugin)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(arch_sixtyfour|architecture|os_type|model|system)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(cmo|cmi|cma|cmx|cmxa)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\^\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\b(targets|target|deps|dep|exe|bin|version)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\b(lib-available|lib-private|libexec-private|libexec|lib)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\b(read-lines|read-strings|read)\\\\b\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/dune-workspace.json",
    "content": "{\n  \"name\": \"dune-workspace\",\n  \"scopeName\": \"source.dune-workspace\",\n  \"fileTypes\": [\"dune-workspace\"],\n  \"patterns\": [{ \"include\": \"#stanzas\" }, { \"include\": \"#general\" }],\n  \"repository\": {\n    \"stanzas\": {\n      \"patterns\": [\n        {\n          \"comment\": \"lang\",\n          \"begin\": \"\\\\([[:space:]]*(lang)[[:space:]]+(dune)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-workspace\" },\n            \"2\": { \"name\": \"keyword.language.dune-workspace\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"profile\",\n          \"begin\": \"\\\\([[:space:]]*(profile)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n          },\n          \"contentName\": \"variable.other.declaration.dune-project\",\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"env\",\n          \"begin\": \"\\\\([[:space:]]*(env)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n          },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n\n        {\n          \"comment\": \"context\",\n          \"begin\": \"\\\\([[:space:]]*(context)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n          },\n          \"patterns\": [\n            {\n              \"comment\": \"default\",\n              \"name\": \"keyword.language.dune-workspace\",\n              \"match\": \"\\\\b(default)\\\\b\"\n            },\n            {\n              \"comment\": \"opam/default\",\n              \"begin\": \"\\\\([[:space:]]*(opam|default)\\\\b\",\n              \"end\": \"\\\\)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n              },\n              \"patterns\": [\n                {\n                  \"comment\": \"opam switch\",\n                  \"begin\": \"\\\\([[:space:]]*(switch)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"name\",\n                  \"begin\": \"\\\\([[:space:]]*(name)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"root\",\n                  \"begin\": \"\\\\([[:space:]]*(root)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"merlin\",\n                  \"begin\": \"\\\\([[:space:]]*(merlin)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"profile\",\n                  \"begin\": \"\\\\([[:space:]]*(profile)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"env\",\n                  \"begin\": \"\\\\([[:space:]]*(env)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"toolchain\",\n                  \"begin\": \"\\\\([[:space:]]*(toolchain)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"host\",\n                  \"begin\": \"\\\\([[:space:]]*(host)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"paths\",\n                  \"begin\": \"\\\\([[:space:]]*(paths)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"fdo\",\n                  \"begin\": \"\\\\([[:space:]]*(fdo)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"disable_dynamically_linked_foreign_archives\",\n                  \"begin\": \"\\\\([[:space:]]*(disable_dynamically_linked_foreign_archives)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                {\n                  \"comment\": \"targets\",\n                  \"begin\": \"\\\\([[:space:]]*(targets)\\\\b\",\n                  \"end\": \"\\\\)\",\n                  \"beginCaptures\": {\n                    \"1\": { \"name\": \"keyword.language.dune-workspace\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#general\" }]\n                },\n\n                { \"include\": \"#general\" }\n              ]\n            },\n            { \"include\": \"#general\" }\n          ]\n        }\n      ]\n    },\n\n    \"general\": {\n      \"patterns\": [\n        {\n          \"name\": \"comment.line.dune\",\n          \"begin\": \";\",\n          \"end\": \"$\"\n        },\n        {\n          \"name\": \"string.quoted.line.dune\",\n          \"begin\": \"\\\"\\\\\\\\\\\\|\",\n          \"end\": \"$\",\n          \"patterns\": [{ \"include\": \"#escape-characters\" }]\n        },\n        {\n          \"name\": \"string.quoted.line.dune\",\n          \"begin\": \"\\\"\\\\\\\\>\",\n          \"end\": \"$\"\n        },\n        {\n          \"name\": \"string.quoted.double.dune\",\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\",\n          \"patterns\": [{ \"include\": \"#escape-characters\" }]\n        },\n        {\n          \"comment\": \"symbol\",\n          \"name\": \"constant.symbol.dune\",\n          \"match\": \"(:[[:alpha:]-]+)\\\\b\"\n        },\n        {\n          \"comment\": \"number or version\",\n          \"name\": \"constant.numeric.dune\",\n          \"match\": \"\\\\b([[:digit:]](\\\\.[[:digit:]]+)+)\\\\b\"\n        },\n        {\n          \"comment\": \"true or false\",\n          \"name\": \"constant.language.dune\",\n          \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n        {\n          \"comment\": \"variable\",\n          \"begin\": \"%\\\\{\",\n          \"end\": \"\\\\}\",\n          \"beginCaptures\": [{ \"name\": \"keyword.operator.dune\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.operator.dune\" }],\n          \"patterns\": [{ \"include\": \"#variables\" }]\n        },\n        {\n          \"comment\": \"boolean/predicate language\",\n          \"begin\": \"\\\\([[:space:]]*(=|<>|>=|<=|<|>)\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": { \"1\": { \"name\": \"keyword.operator.dune\" } },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n        {\n          \"comment\": \"boolean/predicate language\",\n          \"begin\": \"\\\\([[:space:]]*(and|or|not)\\\\b\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": { \"1\": { \"name\": \"keyword.operator.dune\" } },\n          \"patterns\": [{ \"include\": \"#general\" }]\n        },\n        {\n          \"comment\": \"ordered set language\",\n          \"begin\": \"\\\\(\",\n          \"end\": \"\\\\)\",\n          \"patterns\": [\n            { \"name\": \"keyword.operator.dune\", \"match\": \"/\" },\n            { \"include\": \"#general\" }\n          ]\n        }\n      ]\n    },\n\n    \"escape-characters\": {\n      \"patterns\": [\n        {\n          \"comment\": \"escaped newline\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\$\"\n        },\n        {\n          \"comment\": \"escaped character\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\(n|r|b|t|\\\\\\\\|\\\")\"\n        },\n        {\n          \"comment\": \"character from decimal ASCII code\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\[[:digit:]]{3}\"\n        },\n        {\n          \"comment\": \"character from hexadecimal ASCII code\",\n          \"name\": \"constant.character.escape.dune\",\n          \"match\": \"\\\\\\\\x[[:xdigit:]]{2}\"\n        },\n        {\n          \"comment\": \"escaped variable\",\n          \"begin\": \"(\\\\%\\\\{)\",\n          \"end\": \"(\\\\})\",\n          \"beginCaptures\": [{ \"name\": \"constant.character.escape.dune\" }],\n          \"endCaptures\": [{ \"name\": \"constant.character.escape.dune\" }],\n          \"patterns\": [{ \"include\": \"#variables\" }]\n        }\n      ]\n    },\n\n    \"variables\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.operator.variable.dune\",\n          \"match\": \":\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(project_root|workspace_root)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(CC|CXX)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(ocaml_bin|ocaml|ocamlc|ocamlopt|ocaml_version|ocaml_where|ocaml-config)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(profile|null|context_name|ignoring_promoted_rule)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(ext_obj|ext_asm|ext_lib|ext_dll|ext_exe|ext_plugin)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(arch_sixtyfour|architecture|os_type|model|system)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.dune\",\n          \"match\": \"\\\\b(cmo|cmi|cma|cmx|cmxa)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\^\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\b(targets|target|deps|dep|exe|bin|version)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\b(lib-available|lib-private|libexec-private|libexec|lib)\\\\b\"\n        },\n        {\n          \"name\": \"constant.language.variable.action.dune\",\n          \"match\": \"\\\\b(read-lines|read-strings|read)\\\\b\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/dune.json",
    "content": "{\n  \"name\": \"dune\",\n  \"scopeName\": \"source.dune\",\n  \"fileTypes\": [\"dune\", \"jbuild\"],\n  \"patterns\": [\n    {\n      \"include\": \"#comments\"\n    },\n    {\n      \"name\": \"meta.stanza.dune\",\n      \"begin\": \"\\\\([[:space:]]*(library|rule|executable|executables|rule|ocamllex|ocamlyacc|menhir|install|alias|copy_files|copy_files#|jbuild_version|include)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"meta.class.stanza.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.library.field.dune\",\n      \"begin\": \"\\\\([[:space:]]*(name|public_name|synopsis|install_c_headers|ppx_runtime_libraries|c_flags|cxx_flags|c_names|cxx_names|library_flags|c_library_flags|virtual_deps|modes|kind|wrapped|optional|self_build_stubs_archive|no_dynlink|ppx\\\\.driver)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.rule.dune\",\n      \"begin\": \"\\\\([[:space:]]*(targets|deps|locks|loc|mode|action)[[:space:]]\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.mono-sexp.dune\",\n      \"match\": \"\\\\([[:space:]]*(fallback|optional)[[:space:]]*\\\\)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      }\n    },\n    {\n      \"name\": \"meta.stanza.rule.action.dune\",\n      \"begin\": \"\\\\([[:space:]]*(run|chdir|setenv|with-stdout-to|with-stderr-to|with-outputs-to|ignore-stdout|ignore-stderr|ignore-outputs|progn|echo|cat|copy|copy#|system|bash|write-file|diff|diff\\\\?)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"entity.name.function.action.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.install.dune\",\n      \"begin\": \"\\\\([[:space:]]*(section)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"name\": \"constant.language.rule.mode.dune\",\n          \"match\": \"\\\\b(lib|libexec|bin|sbin|toplevel|share|share_root|etc|doc|stublibs|man|misc)\\\\b\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.install.dune\",\n      \"begin\": \"\\\\([[:space:]]*(files)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.library.kind.dune\",\n      \"begin\": \"\\\\([[:space:]]*(normal|ppx_deriver|ppx_rewriter)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"constant.language.rule.mode.dune\"\n        }\n      }\n    },\n    {\n      \"name\": \"meta.stanza.executables.dune\",\n      \"begin\": \"\\\\([[:space:]]*(name|link_executables|link_flags|modes)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.lib-or-exec.buildable.dune\",\n      \"begin\": \"\\\\([[:space:]]*(preprocess|preprocessor_deps|lint|modules|modules_without_implementation|libraries|flags|ocamlc_flags|ocamlopt_flags|js_of_ocaml|allow_overlapping_dependencies|per_module)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.lib-or-exec.buildable.preprocess.dune\",\n      \"begin\": \"\\\\([[:space:]]*(no_preprocessing|action|pps)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.lib-or-exec.buildable.preprocess_deps.dune\",\n      \"begin\": \"\\\\([[:space:]]*(file|alias|alias_rec|glob_files|files_recursively_in)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"meta.stanza.lib-or-exec.buildable.libraries.dune\",\n      \"begin\": \"\\\\([[:space:]]*(select)[[:space:]]\",\n      \"end\": \"\\\\)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.other.dune\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"include\": \"$self\"\n        }\n      ]\n    },\n    {\n      \"name\": \"constant.numeric.dune\",\n      \"match\": \"\\\\b\\\\d+\\\\b\"\n    },\n    {\n      \"name\": \"constant.language.dune\",\n      \"match\": \"(true|false)\"\n    },\n    {\n      \"name\": \"keyword.other.dune\",\n      \"match\": \"[[:space:]](as|from|->)[[:space:]]\"\n    },\n    {\n      \"name\": \"keyword.other.dune\",\n      \"match\": \"(\\\\!)\"\n    },\n    {\n      \"name\": \"constant.language.flag.dune\",\n      \"match\": \"(:\\\\w+)\\\\b\"\n    },\n    {\n      \"name\": \"constant.language.rule.mode.dune\",\n      \"match\": \"\\\\b(standard|fallback|promote|promote-until-then)\\\\b\"\n    },\n    {\n      \"include\": \"#string\"\n    },\n    {\n      \"include\": \"#variable\"\n    },\n    {\n      \"include\": \"#list\"\n    },\n    {\n      \"include\": \"#atom\"\n    }\n  ],\n  \"repository\": {\n    \"comments\": {\n      \"patterns\": [\n        {\n          \"name\": \"comment.block.dune\",\n          \"begin\": \"#\\\\|\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.comment.begin.dune\"\n            }\n          },\n          \"end\": \"\\\\|#\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.comment.end.dune\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"include\": \"#comments\"\n            }\n          ]\n        },\n        {\n          \"name\": \"comment.sexp.dune\",\n          \"begin\": \"#;[[:space:]]*\\\\(\",\n          \"end\": \"\\\\)\",\n          \"patterns\": [\n            {\n              \"include\": \"#comment-inner\"\n            }\n          ]\n        },\n        {\n          \"name\": \"comment.line.dune\",\n          \"match\": \";.*$\"\n        }\n      ]\n    },\n    \"comment-inner\": {\n      \"patterns\": [\n        {\n          \"name\": \"comment.sexp.inner.dune\",\n          \"begin\": \"\\\\(\",\n          \"end\": \"\\\\)\",\n          \"patterns\": [\n            {\n              \"include\": \"#comment-inner\"\n            }\n          ]\n        }\n      ]\n    },\n    \"string\": {\n      \"patterns\": [\n        {\n          \"name\": \"string.quoted.double.dune\",\n          \"begin\": \"(?=[^\\\\\\\\])(\\\")\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"punctuation.definition.string.begin.dune\"\n            }\n          },\n          \"end\": \"(\\\")\",\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"punctuation.definition.string.end.dune\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"name\": \"constant.character.string.escape.dune\",\n              \"match\": \"\\\\\\\\\\\"\"\n            },\n            {\n              \"include\": \"#variable\"\n            }\n          ]\n        }\n      ]\n    },\n    \"variable\": {\n      \"patterns\": [\n        {\n          \"name\": \"variable.other.dune\",\n          \"match\": \"\\\\${[^}]*}\"\n        }\n      ]\n    },\n    \"list\": {\n      \"patterns\": [\n        {\n          \"name\": \"meta.list.dune\",\n          \"begin\": \"(\\\\()\",\n          \"end\": \"(\\\\))\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"entity.tag.list.parenthesis.dune\"\n            }\n          },\n          \"comment\": \"ok, for this one, I didn't know what to choose\",\n          \"patterns\": [\n            {\n              \"include\": \"$self\"\n            }\n          ]\n        }\n      ]\n    },\n    \"atom\": {\n      \"patterns\": [\n        {\n          \"name\": \"meta.atom.dune\",\n          \"match\": \"\\\\b[^[[:space:]]]+\\\\b\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/menhir-action.json",
    "content": "{\n  \"scopeName\": \"source.action.menhir\",\n  \"injectionSelector\": \"L:source.embedded-action.menhir\",\n  \"patterns\": [\n    {\n      \"begin\": \"(\\\\$(?:startpos|endpos|startofs|endofs|loc))[[:space:]]*\\\\(\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other.menhir\" }\n      },\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        { \"include\": \"#anon-capture\" },\n        { \"include\": \"source.ocaml.menhir#token-name\" },\n        { \"include\": \"source.ocaml.menhir#production-name\" }\n      ]\n    },\n    {\n      \"match\": \"\\\\$(?:startpos|endpos|symbolstartpos|startofs|endofs|symbolstartofs|loc|sloc)\\\\b\",\n      \"name\": \"keyword.other.menhir\"\n    },\n    { \"include\": \"#anon-capture\" }\n  ],\n  \"repository\": {\n    \"anon-capture\": {\n      \"match\": \"\\\\$[[:digit:]]+\\\\b\",\n      \"name\": \"keyword.other.menhir\"\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/menhir.json",
    "content": "{\n  \"name\": \"Menhir\",\n  \"scopeName\": \"source.ocaml.menhir\",\n  \"fileTypes\": [\"mly\"],\n  \"patterns\": [\n    { \"include\": \"#comments\" },\n    {\n      \"comment\": \"sequence of declarations\",\n      \"begin\": \"(?=%[^%])\",\n      \"end\": \"(?=%%)\",\n      \"patterns\": [{ \"include\": \"#comments\" }, { \"include\": \"#declarations\" }]\n    },\n    {\n      \"comment\": \"sequence of rules\",\n      \"begin\": \"%%\",\n      \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n      \"end\": \"%%\",\n      \"endCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n      \"patterns\": [{ \"include\": \"#comments\" }, { \"include\": \"#rules\" }]\n    },\n    { \"include\": \"source.ocaml\" }\n  ],\n  \"repository\": {\n    \"comments\": {\n      \"patterns\": [\n        { \"include\": \"source.ocaml#comments\" },\n        {\n          \"comment\": \"c-style block comment\",\n          \"name\": \"comment.block.menhir\",\n          \"begin\": \"/\\\\*\",\n          \"end\": \"\\\\*/\"\n        },\n        {\n          \"comment\": \"c-style line comment\",\n          \"name\": \"comment.line.menhir\",\n          \"begin\": \"//\",\n          \"end\": \"$\"\n        }\n      ]\n    },\n\n    \"declarations\": {\n      \"patterns\": [\n        {\n          \"comment\": \"ocaml header\",\n          \"begin\": \"%{\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \"%}\",\n          \"endCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"patterns\": [{ \"include\": \"source.ocaml\" }]\n        },\n        {\n          \"comment\": \"token declaration\",\n          \"begin\": \"%token\\\\b\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \"(?=%)\",\n          \"patterns\": [\n            { \"include\": \"#type-annotation\" },\n            { \"include\": \"#token-name\" },\n            { \"include\": \"source.ocaml#strings\" },\n            { \"include\": \"source.ocaml#attributes\" },\n            { \"include\": \"#comments\" }\n          ]\n        },\n        {\n          \"comment\": \"associativity declaration\",\n          \"begin\": \"%(?:nonassoc|left|right)\\\\b\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \"(?=%)\",\n          \"patterns\": [\n            { \"include\": \"#token-name\" },\n            { \"include\": \"#production-name\" },\n            { \"include\": \"source.ocaml#strings\" },\n            { \"include\": \"source.ocaml#attributes\" },\n            { \"include\": \"#comments\" }\n          ]\n        },\n        {\n          \"comment\": \"type/start/on_error_reduce declaration\",\n          \"begin\": \"%(?:type|start|on_error_reduce)\\\\b\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \"(?=%)\",\n          \"patterns\": [\n            { \"include\": \"#type-annotation\" },\n            { \"include\": \"#production-name\" },\n            { \"include\": \"source.ocaml#strings\" },\n            { \"include\": \"source.ocaml#attributes\" },\n            { \"include\": \"#comments\" }\n          ]\n        },\n        {\n          \"comment\": \"parameter declaration\",\n          \"name\": \"keyword.other.menhir\",\n          \"match\": \"%parameter\\\\b\"\n        },\n        {\n          \"comment\": \"attribute declaration\",\n          \"begin\": \"%(?:attribute\\\\b|(?=\\\\[))\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \"(?=%)\",\n          \"patterns\": [\n            { \"include\": \"source.ocaml#attributes\" },\n            { \"include\": \"#token-name\" },\n            { \"include\": \"#production-name\" },\n            { \"include\": \"#comments\" }\n          ]\n        },\n        { \"include\": \"#type-annotation\" },\n        { \"include\": \"source.ocaml#strings\" }\n      ],\n      \"repository\": {\n        \"type-annotation\": {\n          \"comment\": \"ocaml type annotation for token\",\n          \"begin\": \"<\",\n          \"end\": \">\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"patterns\": [{ \"include\": \"source.ocaml\" }]\n        }\n      }\n    },\n\n    \"rules\": {\n      \"patterns\": [\n        { \"include\": \"#old-rules\" },\n        { \"include\": \"#new-rules\" },\n        {\n          \"comment\": \"declaration for public or inline rule\",\n          \"name\": \"keyword.other.directive.menhir\",\n          \"match\": \"%(?:public|inline)\\\\b\"\n        },\n        {\n          \"comment\": \"reserved keywords/operators for new syntax\",\n          \"name\": \"keyword.other.menhir\",\n          \"match\": \"\\\\blet\\\\b|:=|==\"\n        }\n      ]\n    },\n    \"old-rules\": {\n      \"comment\": \"rule name with optional parameter list\",\n      \"begin\": \"([[:lower:]_][[:word:]]*)[[:space:]]*(?:\\\\(([^)]+)\\\\))?(?=[[:space:]]*:)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"comment\": \"rule name\",\n          \"name\": \"entity.name.function.rule.menhir\"\n        },\n        \"2\": {\n          \"patterns\": [\n            {\n              \"comment\": \"rule parameter\",\n              \"name\": \"variable.parameter.rule.menhir\",\n              \"match\": \"[[:alpha:]_][[:word:]]*\"\n            }\n          ]\n        }\n      },\n      \"end\": \"(?=let\\\\b|[[:lower:]_][[:word:]]*[[:space:]]*(?:\\\\([^)]+\\\\)[[:space:]]*)?:|%(?!prec\\\\b))\",\n      \"patterns\": [\n        { \"include\": \"#comments\" },\n        { \"include\": \"#old-variables\" },\n        { \"include\": \"#references\" },\n        { \"include\": \"#prec\" },\n        { \"include\": \"#operators\" },\n        { \"include\": \"source.ocaml#strings\" },\n        { \"include\": \"source.ocaml#attributes\" },\n        { \"include\": \"#old-actions\" },\n        {\n          \"comment\": \"production\",\n          \"begin\": \"[:|]\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \"(?=[{<|]|let\\\\b|[[:lower:]_][[:word:]]*[[:space:]]*(?:\\\\([^)]+\\\\)[[:space:]]*)?:|%(?!prec\\\\b))\",\n          \"patterns\": [\n            { \"include\": \"#comments\" },\n            { \"include\": \"#old-variables\" },\n            { \"include\": \"#references\" },\n            { \"include\": \"#prec\" },\n            { \"include\": \"#operators\" },\n            { \"include\": \"source.ocaml#strings\" },\n            { \"include\": \"source.ocaml#attributes\" }\n          ]\n        }\n      ]\n    },\n    \"new-rules\": {\n      \"comment\": \"new rule syntax with optional parameter list\",\n      \"begin\": \"(let)[[:space:]]+([[:lower:]_][[:word:]]*)[[:space:]]*(?:\\\\(([^)]+)\\\\)[[:space:]]*)?(:=|==)\",\n      \"end\": \"(?=let\\\\b|[[:lower:]_][[:word:]]*[[:space:]]*(?:\\\\([^)]+\\\\)[[:space:]]*)?:|%(?!prec\\\\b))\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other.menhir\" },\n        \"2\": {\n          \"comment\": \"rule name\",\n          \"name\": \"entity.name.function.rule.menhir\"\n        },\n        \"3\": {\n          \"patterns\": [\n            {\n              \"comment\": \"rule parameter\",\n              \"name\": \"variable.parameter.rule.menhir\",\n              \"match\": \"[[:alpha:]_][[:word:]]*\"\n            }\n          ]\n        },\n        \"4\": { \"name\": \"keyword.other.menhir\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#comments\" },\n        { \"include\": \"#new-variables\" },\n        { \"include\": \"#references\" },\n        { \"include\": \"#prec\" },\n        { \"include\": \"#operators\" },\n        { \"include\": \"source.ocaml#strings\" },\n        { \"include\": \"source.ocaml#attributes\" },\n        { \"include\": \"#new-actions\" },\n        {\n          \"comment\": \"production\",\n          \"begin\": \"[:|]\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \"(?=[{<|]|let\\\\b|[[:lower:]_][[:word:]]*[[:space:]]*(?:\\\\([^)]+\\\\)[[:space:]]*)?:|%(?!prec\\\\b))\",\n          \"patterns\": [\n            { \"include\": \"#comments\" },\n            { \"include\": \"#new-variables\" },\n            { \"include\": \"#references\" },\n            { \"include\": \"#prec\" },\n            { \"include\": \"#operators\" },\n            { \"include\": \"source.ocaml#strings\" },\n            { \"include\": \"source.ocaml#attributes\" }\n          ]\n        }\n      ]\n    },\n\n    \"prec\": {\n      \"match\": \"%prec\\\\b\",\n      \"name\": \"keyword.other.menhir\"\n    },\n\n    \"old-actions\": {\n      \"comment\": \"ocaml semantic action\",\n      \"contentName\": \"source.embedded-action.menhir\",\n      \"begin\": \"{\",\n      \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n      \"end\": \"}\",\n      \"endCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n      \"patterns\": [{ \"include\": \"source.ocaml\" }]\n    },\n    \"new-actions\": {\n      \"patterns\": [\n        { \"include\": \"#old-actions\" },\n        {\n          \"comment\": \"point-free ocaml semantic action\",\n          \"begin\": \"<\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"end\": \">\",\n          \"endCaptures\": [{ \"name\": \"keyword.other.menhir\" }],\n          \"patterns\": [{ \"include\": \"source.ocaml\" }]\n        }\n      ]\n    },\n\n    \"old-variables\": {\n      \"comment\": \"labeled semantic value identifier\",\n      \"match\": \"([[:lower:]_][[:word:]]*)[[:space:]]*(=)\",\n      \"captures\": {\n        \"1\": { \"name\": \"variable.parameter.value.menhir\" },\n        \"2\": { \"name\": \"keyword.other.menhir\" }\n      },\n      \"patterns\": [{ \"include\": \"#references\" }]\n    },\n    \"new-variables\": {\n      \"patterns\": [\n        { \"include\": \"#old-variables\" },\n        {\n          \"comment\": \"punned semantic value capture\",\n          \"match\": \"(~)[[:space:]]*(=)\",\n          \"captures\": {\n            \"1\": { \"name\": \"variable.parameter.value.menhir\" },\n            \"2\": { \"name\": \"keyword.other.menhir\" }\n          }\n        },\n        {\n          \"comment\": \"destructured semantic value capture\",\n          \"begin\": \"(?<![[:word:]][[:space:]]*)\\\\(\",\n          \"end\": \"\\\\)[[:space:]]*(=)\",\n          \"endCaptures\": {\n            \"1\": { \"name\": \"keyword.other.menhir\" }\n          },\n          \"patterns\": [{ \"include\": \"#pattern\" }]\n        }\n      ],\n      \"repository\": {\n        \"pattern\": {\n          \"patterns\": [\n            {\n              \"match\": \"[[:lower:]_][[:word:]]*|~\",\n              \"name\": \"variable.parameter.value.menhir\"\n            },\n            {\n              \"begin\": \"\\\\(\",\n              \"end\": \"\\\\)\",\n              \"patterns\": [{ \"include\": \"#pattern\" }]\n            }\n          ]\n        }\n      }\n    },\n\n    \"token-name\": {\n      \"comment\": \"reference to a token\",\n      \"name\": \"constant.other.token.menhir\",\n      \"match\": \"[[:upper:]][[:word:]]*\"\n    },\n    \"production-name\": {\n      \"comment\": \"reference to a production\",\n      \"name\": \"entity.name.function.rule.menhir\",\n      \"match\": \"[[:lower:]_][[:word:]]*\"\n    },\n    \"references\": {\n      \"patterns\": [\n        {\n          \"comment\": \"builtin standard library functions\",\n          \"name\": \"support.function.rule.menhir\",\n          \"match\": \"\\\\b(endrule|midrule|option|ioption|boption|loption|pair|separated_pair|preceded|terminated|delimited|list|nonempty_list|separated_list|separated_nonempty_list|rev|flatten|append)\\\\b\"\n        },\n        { \"include\": \"#token-name\" },\n        { \"include\": \"#production-name\" }\n      ]\n    },\n\n    \"operators\": {\n      \"patterns\": [\n        {\n          \"comment\": \"rule modifier (?, +, *)\",\n          \"match\": \"[?+*]\",\n          \"name\": \"keyword.operator.menhir\"\n        },\n        {\n          \"comment\": \"vertical bar\",\n          \"match\": \"\\\\|\",\n          \"name\": \"keyword.other.menhir\"\n        },\n        {\n          \"comment\": \"semicolon\",\n          \"match\": \";\",\n          \"name\": \"keyword.other.menhir punctuation.separator.terminator punctuation.separator.semicolon\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/merlin.json",
    "content": "{\n  \"scopeName\": \"source.ocaml.merlin\",\n  \"fileTypes\": [\"merlin\"],\n  \"patterns\": [\n    { \"include\": \"#comment\" },\n    { \"include\": \"#directory\" },\n    { \"include\": \"#flag\" },\n    { \"include\": \"#package\" }\n  ],\n  \"repository\": {\n    \"comment\": {\n      \"begin\": \"#\",\n      \"end\": \"$\",\n      \"name\": \"comment.line.merlin\"\n    },\n    \"directory\": {\n      \"begin\": \"\\\\b(B|S)\\\\b\",\n      \"end\": \"$\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other.merlin\" }\n      },\n      \"name\": \"string.other.merlin\",\n      \"patterns\": [\n        {\n          \"match\": \"[:./  \\\\\\\\]\",\n          \"name\": \"keyword.other.path.merlin\"\n        },\n        {\n          \"match\": \"[*?]\",\n          \"name\": \"keyword.other.glob.merlin\"\n        }\n      ]\n    },\n    \"flag\": {\n      \"begin\": \"\\\\b(FLG)\\\\b\",\n      \"end\": \"$\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other.merlin\" }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\",\n          \"name\": \"string.quoted.double.merlin\"\n        },\n        {\n          \"match\": \"([\\\\-\\\\+])\\\\b(?:([[:digit:]]+)|([[:lower:]][[:word:]]*))\\\\b\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.other.merlin\" },\n            \"2\": { \"name\": \"constant.language.merlin\" },\n            \"3\": { \"name\": \"variable.parameter.merlin\" }\n          }\n        }\n      ]\n    },\n    \"package\": {\n      \"begin\": \"\\\\b(PKG)\\\\b\",\n      \"end\": \"$\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"storage.type.merlin\" }\n      },\n      \"patterns\": [\n        {\n          \"match\": \"(?<![\\\\-\\\\+])\\\\b([[:lower:]][-[:word:]]*)\\\\b[[:space:]]*(\\\\.)?\",\n          \"captures\": {\n            \"1\": { \"name\": \"entity.name.class.merlin\" },\n            \"2\": { \"name\": \"keyword.other.merlin\" }\n          }\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/oasis.json",
    "content": "{\n  \"scopeName\": \"source.ocaml.oasis\",\n  \"fileTypes\": [\"_oasis\"],\n  \"patterns\": [\n    { \"include\": \"#comments\" },\n    { \"include\": \"#fields\" },\n    { \"include\": \"#sections\" },\n    { \"include\": \"#conditionals\" },\n    { \"include\": \"#substitution\" }\n  ],\n  \"repository\": {\n    \"comments\": {\n      \"comment\": \"line comment\",\n      \"name\": \"comment.line.oasis\",\n      \"begin\": \"#\",\n      \"end\": \"$\"\n    },\n\n    \"fields\": {\n      \"comment\": \"labeled field\",\n      \"match\": \"^[[:space:]]*([[:word:]]+)(:|\\\\+:|\\\\$:)\",\n      \"captures\": {\n        \"1\": { \"name\": \"entity.name.tag.oasis\" },\n        \"2\": { \"name\": \"keyword.operator.oasis\" }\n      }\n    },\n\n    \"sections\": {\n      \"comment\": \"labeled section\",\n      \"begin\": \"^[[:space:]]*(Flag|Library|Object|Executable|Document|Test|SourceRepository)\",\n      \"beginCaptures\": { \"1\": { \"name\": \"keyword.other.oasis\" } },\n      \"end\": \"$\",\n      \"contentName\": \"string.other.oasis\"\n    },\n\n    \"conditionals\": {\n      \"patterns\": [\n        {\n          \"comment\": \"if condition\",\n          \"name\": \"keyword.other.oasis\",\n          \"match\": \"\\\\b(if|else)\\\\b\"\n        },\n        {\n          \"comment\": \"operators\",\n          \"name\": \"keyword.operator.oasis\",\n          \"match\": \"(!|&&|\\\\|\\\\|)\"\n        },\n        {\n          \"comment\": \"boolean\",\n          \"name\": \"constant.language.oasis\",\n          \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n        {\n          \"comment\": \"tests\",\n          \"begin\": \"\\\\b(os_type|system|architecture|ccomp_type|ocaml_version|flag)\\\\(\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"entity.name.function.oasis\" }\n          }\n        }\n      ]\n    },\n\n    \"substitution\": {\n      \"match\": \"\\\\$[[:word:]]+\",\n      \"name\": \"constant.language.oasis\"\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/ocaml-markdown-codeblock.json",
    "content": "{\n  \"fileTypes\": [],\n  \"injectionSelector\": \"L:markup.fenced_code.block.markdown\",\n  \"patterns\": [{ \"include\": \"#ocaml-code-block\" }],\n  \"repository\": {\n    \"ocaml-code-block\": {\n      \"begin\": \"(ml|ocaml)(\\\\s+[^`~]*)?$\",\n      \"end\": \"(^|\\\\G)(?=\\\\s*[`~]{3,}\\\\s*$)\",\n      \"patterns\": [\n        {\n          \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n          \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n          \"contentName\": \"meta.embedded.block.ocaml\",\n          \"patterns\": [\n            {\n              \"include\": \"source.ocaml\"\n            }\n          ]\n        }\n      ]\n    }\n  },\n  \"scopeName\": \"markdown.ocaml.codeblock\"\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/ocaml.interface.json",
    "content": "{\n  \"name\": \"OCaml Interface\",\n  \"scopeName\": \"source.ocaml.interface\",\n  \"fileTypes\": [\"mli\", \"eliomi\"],\n  \"patterns\": [\n    { \"include\": \"source.ocaml#directives\" },\n    { \"include\": \"source.ocaml#comments\" },\n    { \"include\": \"source.ocaml#attributes\" },\n    { \"include\": \"source.ocaml#extensions\" },\n    { \"include\": \"#bindings\" },\n    { \"include\": \"source.ocaml#operators\" },\n    { \"include\": \"#keywords\" },\n    { \"include\": \"source.ocaml#types\" },\n    { \"include\": \"source.ocaml#identifiers\" }\n  ],\n  \"repository\": {\n    \"bindings\": {\n      \"comment\": \"bindings that are shared between .ml and .mli syntaxes\",\n      \"patterns\": [\n        {\n          \"comment\": \"optional labeled argument\",\n          \"name\": \"variable.parameter.optional.ocaml\",\n          \"match\": \"\\\\?([[:lower:]_][[:word:]']*)?\"\n        },\n        {\n          \"comment\": \"labeled argument\",\n          \"name\": \"variable.parameter.labeled.ocaml\",\n          \"match\": \"~([[:lower:]_][[:word:]']*)?\"\n        },\n        {\n          \"comment\": \"type declaration\",\n          \"match\": \"\\\\b(type)[[:space:]]+(nonrec[[:space:]]+)?(_[[:space:]]+|[+-]?'[[:alpha:]][[:word:]']*[[:space:]]+|\\\\(.*\\\\)[[:space:]]+)?([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"patterns\": [{ \"include\": \"$base\" }] },\n            \"4\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"and declaration for let bindings, type declarations, class bindings, class type definitions, or module constraints\",\n          \"match\": \"\\\\b(and)[[:space:]]+(?!(?:module|type|lazy)\\\\b(?!'))(virtual[[:space:]]+)?(_[[:space:]]+|'[[:alpha:]][[:word:]']*[[:space:]]+|\\\\(.*\\\\)[[:space:]]+)?([[:lower:]_][[:word:]']*)[[:space:]]+(?!,|::)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"patterns\": [{ \"include\": \"$base\" }] },\n            \"4\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"external declaration\",\n          \"begin\": \"\\\\b(external)[[:space:]]+([[:lower:]_][[:word:]']*)?\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          },\n          \"end\": \"(?<=]|\\\")[[:space:]]*$\",\n          \"patterns\": [\n            {\n              \"comment\": \"string literal\",\n              \"name\": \"string.quoted.double.ocaml\",\n              \"begin\": \"\\\"\",\n              \"end\": \"\\\"\"\n            },\n            { \"include\": \"$base\" }\n          ]\n        },\n        {\n          \"comment\": \"val declaration for class instance variables\",\n          \"match\": \"\\\\b(val)[[:space:]]+(virtual)[[:space:]]+(mutable)[[:space:]]+([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"keyword.ocaml\" },\n            \"4\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"val declaration for let bindings or class instance variables\",\n          \"match\": \"\\\\b(val|val!)[[:space:]]+(mutable[[:space:]]+)?(virtual[[:space:]]+)?([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"keyword.ocaml\" },\n            \"4\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"class method declaration\",\n          \"match\": \"\\\\b(method)[[:space:]]+(virtual)[[:space:]]+(private)[[:space:]]+([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"keyword.ocaml\" },\n            \"4\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"class method declaration\",\n          \"match\": \"\\\\b(method|method!)[[:space:]]+(private[[:space:]]+)?(virtual[[:space:]]+)?([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"keyword.ocaml\" },\n            \"4\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"class specification or class type definition with type parameters\",\n          \"match\": \"\\\\b(class)[[:space:]]*([[:space:]]+type)?([[:space:]]+virtual)?[[:space:]]*(\\\\[.*\\\\])[[:space:]]*([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"keyword.ocaml\" },\n            \"4\": { \"patterns\": [{ \"include\": \"$base\" }] },\n            \"5\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"class specification or class type definition\",\n          \"match\": \"\\\\b(class)[[:space:]]+(type[[:space:]]+)?(virtual[[:space:]]+)?([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"keyword.ocaml\" },\n            \"4\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"named self in object\",\n          \"match\": \"\\\\b(object)[[:space:]]*\\\\([[:space:]]*([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"module type of\",\n          \"begin\": \"\\\\b(module)[[:space:]]+(type)[[:space:]]+(of)\\\\b\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"keyword.ocaml\" }\n          },\n          \"end\": \"(?=val|external|type|exception|class|module|open|include|=)\",\n          \"patterns\": [{ \"include\": \"source.ocaml\" }]\n        }\n      ]\n    },\n\n    \"keywords\": {\n      \"patterns\": [\n        {\n          \"comment\": \"reserved ocaml keyword (in interfaces)\",\n          \"name\": \"keyword.other.ocaml.interface\",\n          \"match\": \"\\\\b(and|as|class|constraint|end|exception|external|functor|in|include|inherit|let[[:space:]]+open|method|module|mutable|nonrec|object|of|open|private|rec|sig|type|val|virtual|with)\\\\b(?!')\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/ocaml.json",
    "content": "{\n  \"name\": \"OCaml\",\n  \"scopeName\": \"source.ocaml\",\n  \"fileTypes\": [\"ml\", \"eliom\", \".ocamlinit\"],\n  \"patterns\": [\n    { \"include\": \"#directives\" },\n    { \"include\": \"#comments\" },\n    { \"include\": \"#strings\" },\n    { \"include\": \"#characters\" },\n    { \"include\": \"#attributes\" },\n    { \"include\": \"#extensions\" },\n    { \"include\": \"#modules\" },\n    { \"include\": \"#bindings\" },\n    { \"include\": \"#operators\" },\n    { \"include\": \"#keywords\" },\n    { \"include\": \"#literals\" },\n    { \"include\": \"#types\" },\n    { \"include\": \"#identifiers\" }\n  ],\n  \"repository\": {\n    \"directives\": {\n      \"patterns\": [\n        {\n          \"comment\": \"line number directive\",\n          \"begin\": \"^[[:space:]]*(#)[[:space:]]*([[:digit:]]+)\",\n          \"end\": \"$\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other.ocaml\" },\n            \"2\": { \"name\": \"constant.numeric.decimal.integer.ocaml\" }\n          },\n          \"contentName\": \"comment.line.directive.ocaml\"\n        },\n        {\n          \"comment\": \"toplevel directives\",\n          \"patterns\": [\n            {\n              \"comment\": \"general, loading codes\",\n              \"begin\": \"^[[:space:]]*(#)[[:space:]]*(help|quit|cd|directory|remove_directory|load_rec|load|use|mod_use)\",\n              \"end\": \"$\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other.ocaml\" },\n                \"2\": { \"name\": \"keyword.other.ocaml\" }\n              },\n              \"patterns\": [{ \"include\": \"#strings\" }]\n            },\n            {\n              \"comment\": \"environment queries\",\n              \"begin\": \"^[[:space:]]*(#)[[:space:]]*(show_class_type|show_class|show_exception|show_module_type|show_module|show_type|show_val|show)\",\n              \"end\": \"$\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other.ocaml\" },\n                \"2\": { \"name\": \"keyword.other.ocaml\" }\n              },\n              \"patterns\": [\n                { \"include\": \"#types\" },\n                { \"include\": \"#identifiers\" }\n              ]\n            },\n            {\n              \"comment\": \"pretty-printing, tracing\",\n              \"begin\": \"^[[:space:]]*(#)[[:space:]]*(install_printer|print_depth|print_length|remove_printer|trace|untrace_all|untrace)\",\n              \"end\": \"$\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other.ocaml\" },\n                \"2\": { \"name\": \"keyword.other.ocaml\" }\n              },\n              \"patterns\": [\n                { \"include\": \"#literals\" },\n                { \"include\": \"#identifiers\" }\n              ]\n            },\n            {\n              \"comment\": \"compiler options\",\n              \"begin\": \"^[[:space:]]*(#)[[:space:]]*(labels|ppx|principal|rectypes|warn_error|warnings)\",\n              \"end\": \"$\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other.ocaml\" },\n                \"2\": { \"name\": \"keyword.other.ocaml\" }\n              },\n              \"patterns\": [\n                { \"include\": \"#strings\" },\n                { \"include\": \"#literals\" }\n              ]\n            }\n          ]\n        },\n        {\n          \"comment\": \"topfind directives\",\n          \"begin\": \"^[[:space:]]*(#)[[:space:]]*(require|list|camlp4o|camlp4r|predicates|thread)\",\n          \"end\": \"$\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other.ocaml\" },\n            \"2\": { \"name\": \"keyword.other.ocaml\" }\n          },\n          \"patterns\": [{ \"include\": \"#strings\" }]\n        },\n        {\n          \"comment\": \"cppo directives\",\n          \"begin\": \"^[[:space:]]*(#)[[:space:]]*(define|undef|ifdef|ifndef|if|else|elif|endif|include|warning|error|ext|endext)\",\n          \"end\": \"$\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other.ocaml\" },\n            \"2\": { \"name\": \"keyword.other.ocaml\" }\n          },\n          \"patterns\": [\n            { \"name\": \"keyword.other.ocaml\", \"match\": \"\\\\b(defined)\\\\b\" },\n            { \"name\": \"keyword.other.ocaml\", \"match\": \"\\\\\\\\\" },\n            { \"include\": \"#comments\" },\n            { \"include\": \"#strings\" },\n            { \"include\": \"#characters\" },\n            { \"include\": \"#keywords\" },\n            { \"include\": \"#operators\" },\n            { \"include\": \"#literals\" },\n            { \"include\": \"#types\" },\n            { \"include\": \"#identifiers\" }\n          ]\n        }\n      ]\n    },\n\n    \"comments\": {\n      \"patterns\": [\n        {\n          \"comment\": \"empty comment\",\n          \"name\": \"comment.block.ocaml\",\n          \"match\": \"\\\\(\\\\*\\\\*\\\\)\"\n        },\n        {\n          \"comment\": \"ocamldoc comment\",\n          \"name\": \"comment.doc.ocaml\",\n          \"begin\": \"\\\\(\\\\*\\\\*\",\n          \"end\": \"\\\\*\\\\)\",\n          \"patterns\": [\n            { \"include\": \"source.ocaml.ocamldoc#markup\" },\n            { \"include\": \"#strings-in-comments\" },\n            { \"include\": \"#comments\" }\n          ]\n        },\n        {\n          \"comment\": \"block comment\",\n          \"name\": \"comment.block.ocaml\",\n          \"begin\": \"\\\\(\\\\*\",\n          \"end\": \"\\\\*\\\\)\",\n          \"patterns\": [\n            { \"include\": \"#strings-in-comments\" },\n            { \"include\": \"#comments\" }\n          ]\n        }\n      ]\n    },\n\n    \"strings-in-comments\": {\n      \"patterns\": [\n        {\n          \"comment\": \"char literal\",\n          \"match\": \"'(\\\\\\\\)?.'\"\n        },\n        {\n          \"comment\": \"string literal\",\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\",\n          \"patterns\": [{ \"match\": \"\\\\\\\\\\\\\\\\\" }, { \"match\": \"\\\\\\\\\\\"\" }]\n        },\n        {\n          \"comment\": \"quoted string literal\",\n          \"begin\": \"\\\\{[[:lower:]_]*\\\\|\",\n          \"end\": \"\\\\|[[:lower:]_]*\\\\}\"\n        }\n      ]\n    },\n\n    \"strings\": {\n      \"patterns\": [\n        {\n          \"comment\": \"quoted string literal\",\n          \"name\": \"string.quoted.braced.ocaml\",\n          \"begin\": \"\\\\{(%%?[[:alpha:]_][[:word:]']*(\\\\.[[:alpha:]_][[:word:]']*)*[[:space:]]*)?[[:lower:]_]*\\\\|\",\n          \"end\": \"\\\\|[[:lower:]_]*\\\\}\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other.extension.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"string literal\",\n          \"name\": \"string.quoted.double.ocaml\",\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\",\n          \"patterns\": [\n            {\n              \"comment\": \"escaped newline\",\n              \"name\": \"constant.character.escape.ocaml\",\n              \"match\": \"\\\\\\\\$\"\n            },\n            {\n              \"comment\": \"escaped backslash\",\n              \"name\": \"constant.character.escape.ocaml\",\n              \"match\": \"\\\\\\\\\\\\\\\\\"\n            },\n            {\n              \"comment\": \"escaped quote or whitespace\",\n              \"name\": \"constant.character.escape.ocaml\",\n              \"match\": \"\\\\\\\\[\\\"'ntbr ]\"\n            },\n            {\n              \"comment\": \"character from decimal ASCII code\",\n              \"name\": \"constant.character.escape.ocaml\",\n              \"match\": \"\\\\\\\\[[:digit:]]{3}\"\n            },\n            {\n              \"comment\": \"character from hexadecimal ASCII code\",\n              \"name\": \"constant.character.escape.ocaml\",\n              \"match\": \"\\\\\\\\x[[:xdigit:]]{2}\"\n            },\n            {\n              \"comment\": \"character from octal ASCII code\",\n              \"name\": \"constant.character.escape.ocaml\",\n              \"match\": \"\\\\\\\\o[0-3][0-7]{2}\"\n            },\n            {\n              \"comment\": \"unicode character escape sequence\",\n              \"name\": \"constant.character.escape.ocaml\",\n              \"match\": \"\\\\\\\\u\\\\{[[:xdigit:]]{1,6}\\\\}\"\n            },\n            {\n              \"comment\": \"printf format string\",\n              \"name\": \"constant.character.printf.ocaml\",\n              \"match\": \"%[-0+ #]*([[:digit:]]+|\\\\*)?(.([[:digit:]]+|\\\\*))?[lLn]?[diunlLNxXosScCfFeEgGhHBbat!%@,]\"\n            },\n            {\n              \"comment\": \"unknown escape sequence\",\n              \"name\": \"invalid.illegal.unknown-escape.ocaml\",\n              \"match\": \"\\\\\\\\.\"\n            }\n          ]\n        }\n      ]\n    },\n\n    \"characters\": {\n      \"patterns\": [\n        {\n          \"comment\": \"character literal from escaped backslash\",\n          \"name\": \"string.quoted.single.ocaml\",\n          \"match\": \"'(\\\\\\\\\\\\\\\\)'\",\n          \"captures\": { \"1\": { \"name\": \"constant.character.escape.ocaml\" } }\n        },\n        {\n          \"comment\": \"character literal from escaped quote or whitespace\",\n          \"name\": \"string.quoted.single.ocaml\",\n          \"match\": \"'(\\\\\\\\[\\\"'ntbr ])'\",\n          \"captures\": { \"1\": { \"name\": \"constant.character.escape.ocaml\" } }\n        },\n        {\n          \"comment\": \"character literal from decimal ASCII code\",\n          \"name\": \"string.quoted.single.ocaml\",\n          \"match\": \"'(\\\\\\\\[[:digit:]]{3})'\",\n          \"captures\": { \"1\": { \"name\": \"constant.character.escape.ocaml\" } }\n        },\n        {\n          \"comment\": \"character literal from hexadecimal ASCII code\",\n          \"name\": \"string.quoted.single.ocaml\",\n          \"match\": \"'(\\\\\\\\x[[:xdigit:]]{2})'\",\n          \"captures\": { \"1\": { \"name\": \"constant.character.escape.ocaml\" } }\n        },\n        {\n          \"comment\": \"character literal from octal ASCII code\",\n          \"name\": \"string.quoted.single.ocaml\",\n          \"match\": \"'(\\\\\\\\o[0-3][0-7]{2})'\",\n          \"captures\": { \"1\": { \"name\": \"constant.character.escape.ocaml\" } }\n        },\n        {\n          \"comment\": \"character literal from unknown escape sequence\",\n          \"name\": \"string.quoted.single.ocaml\",\n          \"match\": \"'(\\\\\\\\.)'\",\n          \"captures\": {\n            \"1\": { \"name\": \"invalid.illegal.unknown-escape.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"character literal\",\n          \"name\": \"string.quoted.single.ocaml\",\n          \"match\": \"'.'\"\n        }\n      ]\n    },\n\n    \"attributes\": {\n      \"begin\": \"\\\\[(@|@@|@@@)[[:space:]]*([[:alpha:]_]+(\\\\.[[:word:]']+)*)\",\n      \"end\": \"\\\\]\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.operator.attribute.ocaml\" },\n        \"2\": {\n          \"name\": \"keyword.other.attribute.ocaml\",\n          \"patterns\": [\n            {\n              \"name\": \"keyword.other.ocaml punctuation.other.period punctuation.separator.period\",\n              \"match\": \"\\\\.\"\n            }\n          ]\n        }\n      },\n      \"patterns\": [{ \"include\": \"$self\" }]\n    },\n\n    \"extensions\": {\n      \"begin\": \"\\\\[(%|%%)[[:space:]]*([[:alpha:]_]+(\\\\.[[:word:]']+)*)\",\n      \"end\": \"\\\\]\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.operator.extension.ocaml\" },\n        \"2\": {\n          \"name\": \"keyword.other.extension.ocaml\",\n          \"patterns\": [\n            {\n              \"name\": \"keyword.other.ocaml punctuation.other.period punctuation.separator.period\",\n              \"match\": \"\\\\.\"\n            }\n          ]\n        }\n      },\n      \"patterns\": [{ \"include\": \"$self\" }]\n    },\n\n    \"modules\": {\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(sig)\\\\b\",\n          \"end\": \"\\\\b(end)\\\\b\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.ocaml\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.other.ocaml\" }],\n          \"patterns\": [{ \"include\": \"source.ocaml.interface\" }]\n        },\n        {\n          \"begin\": \"\\\\b(struct)\\\\b\",\n          \"end\": \"\\\\b(end)\\\\b\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.ocaml\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.other.ocaml\" }],\n          \"patterns\": [{ \"include\": \"$self\" }]\n        }\n      ]\n    },\n\n    \"bindings\": {\n      \"patterns\": [\n        {\n          \"comment\": \"for loop\",\n          \"match\": \"\\\\b(for)[[:space:]]+([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"local open/exception/module\",\n          \"match\": \"\\\\b(let)[[:space:]]+(open|exception|module)\\\\b(?!')\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"let expression\",\n          \"match\": \"\\\\b(let)[[:space:]]+(?!lazy\\\\b(?!'))(rec[[:space:]]+)?(?!rec\\\\b(?!'))([[:lower:]_][[:word:]']*)[[:space:]]+(?!,|::)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"using binding operators\",\n          \"match\": \"\\\\b(let|and)([$&*+\\\\-/=>@^|<][!?$&*+\\\\-/=>@^|%:]*)[[:space:]]*(?!lazy\\\\b(?!'))([[:lower:]_][[:word:]']*)[[:space:]]+(?!,|::)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"first class module packing\",\n          \"match\": \"\\\\([[:space:]]*(val)[[:space:]]+([[:lower:]_][[:word:]']*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.ocaml\" },\n            \"2\": { \"patterns\": [{ \"include\": \"$self\" }] }\n          }\n        },\n        {\n          \"comment\": \"locally abstract types\",\n          \"match\": \"(?:\\\\(|(:))[[:space:]]*(type)((?:[[:space:]]+[[:lower:]_][[:word:]']*)+)\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"keyword.other.ocaml punctuation.other.colon punctuation.colon\"\n            },\n            \"2\": { \"name\": \"keyword.ocaml\" },\n            \"3\": { \"name\": \"entity.name.function.binding.ocaml\" }\n          }\n        },\n        {\n          \"comment\": \"optional labeled argument with type\",\n          \"begin\": \"(\\\\?)\\\\([[:space:]]*([[:lower:]_][[:word:]']*)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"variable.parameter.optional.ocaml\" },\n            \"2\": { \"name\": \"variable.parameter.optional.ocaml\" }\n          },\n          \"end\": \"\\\\)\",\n          \"patterns\": [{ \"include\": \"$self\" }]\n        },\n        {\n          \"comment\": \"labeled argument with type\",\n          \"begin\": \"(~)\\\\([[:space:]]*([[:lower:]_][[:word:]']*)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"variable.parameter.labeled.ocaml\" },\n            \"2\": { \"name\": \"variable.parameter.labeled.ocaml\" }\n          },\n          \"end\": \"\\\\)\",\n          \"patterns\": [{ \"include\": \"$self\" }]\n        },\n        { \"include\": \"source.ocaml.interface#bindings\" }\n      ]\n    },\n\n    \"operators\": {\n      \"patterns\": [\n        {\n          \"comment\": \"binding operator\",\n          \"name\": \"keyword.ocaml\",\n          \"match\": \"\\\\b(let|and)[$&*+\\\\-/=>@^|<][!?$&*+\\\\-/=>@^|%:]*\"\n        },\n        {\n          \"comment\": \"infix symbol\",\n          \"name\": \"keyword.operator.ocaml\",\n          \"match\": \"[$&*+\\\\-/=>@^%<][~!?$&*+\\\\-/=>@^|%<:.]*\"\n        },\n        {\n          \"comment\": \"infix symbol that begins with vertical bar\",\n          \"name\": \"keyword.operator.ocaml\",\n          \"match\": \"\\\\|[~!?$&*+\\\\-/=>@^|%<:.]+\"\n        },\n        {\n          \"comment\": \"vertical bar\",\n          \"name\": \"keyword.other.ocaml\",\n          \"match\": \"(?<!\\\\[)(\\\\|)(?!\\\\])\"\n        },\n        {\n          \"comment\": \"infix symbol\",\n          \"name\": \"keyword.operator.ocaml\",\n          \"match\": \"#[~!?$&*+\\\\-/=>@^|%<:.]+\"\n        },\n        {\n          \"comment\": \"prefix symbol\",\n          \"name\": \"keyword.operator.ocaml\",\n          \"match\": \"![~!?$&*+\\\\-/=>@^|%<:.]*\"\n        },\n        {\n          \"comment\": \"prefix symbol\",\n          \"name\": \"keyword.operator.ocaml\",\n          \"match\": \"[?~][~!?$&*+\\\\-/=>@^|%<:.]+\"\n        },\n        {\n          \"comment\": \"named operator\",\n          \"name\": \"keyword.operator.ocaml\",\n          \"match\": \"\\\\b(or|mod|land|lor|lxor|lsl|lsr|asr)\\\\b\"\n        },\n        {\n          \"comment\": \"method invocation\",\n          \"name\": \"keyword.other.ocaml\",\n          \"match\": \"#\"\n        },\n        {\n          \"comment\": \"type annotation\",\n          \"name\": \"keyword.other.ocaml punctuation.other.colon punctuation.colon\",\n          \"match\": \":\"\n        },\n        {\n          \"comment\": \"field accessor\",\n          \"name\": \"keyword.other.ocaml punctuation.other.period punctuation.separator.period\",\n          \"match\": \"\\\\.\"\n        },\n        {\n          \"comment\": \"semicolon separator\",\n          \"name\": \"keyword.other.ocaml punctuation.separator.terminator punctuation.separator.semicolon\",\n          \"match\": \";\"\n        },\n        {\n          \"comment\": \"comma separator\",\n          \"name\": \"keyword.other.ocaml punctuation.comma punctuation.separator.comma\",\n          \"match\": \",\"\n        }\n      ]\n    },\n\n    \"keywords\": {\n      \"patterns\": [\n        {\n          \"comment\": \"reserved ocaml keyword\",\n          \"name\": \"keyword.other.ocaml\",\n          \"match\": \"\\\\b(and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|virtual|when|while|with)\\\\b(?!')\"\n        }\n      ]\n    },\n\n    \"literals\": {\n      \"patterns\": [\n        {\n          \"comment\": \"boolean literal\",\n          \"name\": \"constant.language.boolean.ocaml\",\n          \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n\n        {\n          \"comment\": \"floating point decimal literal with exponent\",\n          \"name\": \"constant.numeric.decimal.float.ocaml\",\n          \"match\": \"\\\\b([[:digit:]][[:digit:]_]*(\\\\.[[:digit:]_]*)?[eE][+-]?[[:digit:]][[:digit:]_]*[g-zG-Z]?)\\\\b\"\n        },\n        {\n          \"comment\": \"floating point decimal literal\",\n          \"name\": \"constant.numeric.decimal.float.ocaml\",\n          \"match\": \"\\\\b([[:digit:]][[:digit:]_]*\\\\.[[:digit:]_]*[g-zG-Z]?)\\\\b\"\n        },\n        {\n          \"comment\": \"floating point hexadecimal literal with exponent part\",\n          \"name\": \"constant.numeric.hexadecimal.float.ocaml\",\n          \"match\": \"\\\\b((0x|0X)[[:xdigit:]][[:xdigit:]_]*(\\\\.[[:xdigit:]_]*)?[pP][+-]?[[:digit:]][[:digit:]_]*[g-zG-Z]?)\\\\b\"\n        },\n        {\n          \"comment\": \"floating point hexadecimal literal\",\n          \"name\": \"constant.numeric.hexadecimal.float.ocaml\",\n          \"match\": \"\\\\b((0x|0X)[[:xdigit:]][[:xdigit:]_]*\\\\.[[:xdigit:]_]*[g-zG-Z]?)\\\\b\"\n        },\n\n        {\n          \"comment\": \"decimal integer literal\",\n          \"name\": \"constant.numeric.decimal.integer.ocaml\",\n          \"match\": \"\\\\b([[:digit:]][[:digit:]_]*[lLng-zG-Z]?)\\\\b\"\n        },\n        {\n          \"comment\": \"hexadecimal integer literal\",\n          \"name\": \"constant.numeric.hexadecimal.integer.ocaml\",\n          \"match\": \"\\\\b((0x|0X)[[:xdigit:]][[:xdigit:]_]*[lLng-zG-Z]?)\\\\b\"\n        },\n        {\n          \"comment\": \"octal integer literal\",\n          \"name\": \"constant.numeric.octal.integer.ocaml\",\n          \"match\": \"\\\\b((0o|0O)[0-7][0-7_]*[lLng-zG-Z]?)\\\\b\"\n        },\n\n        {\n          \"comment\": \"binary integer literal\",\n          \"name\": \"constant.numeric.binary.integer.ocaml\",\n          \"match\": \"\\\\b((0b|0B)[0-1][0-1_]*[lLng-zG-Z]?)\\\\b\"\n        },\n\n        {\n          \"comment\": \"unit literal\",\n          \"name\": \"constant.language.unit.ocaml\",\n          \"match\": \"\\\\(\\\\)\"\n        },\n        {\n          \"comment\": \"parentheses\",\n          \"begin\": \"\\\\(\",\n          \"end\": \"\\\\)\",\n          \"patterns\": [{ \"include\": \"$self\" }]\n        },\n\n        {\n          \"comment\": \"empty array\",\n          \"name\": \"constant.language.array.ocaml\",\n          \"match\": \"\\\\[\\\\|\\\\|\\\\]\"\n        },\n        {\n          \"comment\": \"array\",\n          \"begin\": \"\\\\[\\\\|\",\n          \"end\": \"\\\\|\\\\]\",\n          \"patterns\": [{ \"include\": \"$self\" }]\n        },\n\n        {\n          \"comment\": \"empty list\",\n          \"name\": \"constant.language.list.ocaml\",\n          \"match\": \"\\\\[\\\\]\"\n        },\n        {\n          \"comment\": \"list\",\n          \"begin\": \"\\\\[\",\n          \"end\": \"]\",\n          \"patterns\": [{ \"include\": \"$self\" }]\n        },\n        {\n          \"comment\": \"braces\",\n          \"begin\": \"\\\\{\",\n          \"end\": \"\\\\}\",\n          \"patterns\": [{ \"include\": \"$self\" }]\n        }\n      ]\n    },\n\n    \"types\": {\n      \"patterns\": [\n        {\n          \"comment\": \"type parameter\",\n          \"name\": \"storage.type.ocaml\",\n          \"match\": \"'[[:alpha:]][[:word:]']*\\\\b|'_\\\\b\"\n        },\n        {\n          \"comment\": \"weak type parameter\",\n          \"name\": \"storage.type.weak.ocaml\",\n          \"match\": \"'_[[:alpha:]][[:word:]']*\\\\b\"\n        },\n        {\n          \"comment\": \"builtin type\",\n          \"name\": \"support.type.ocaml\",\n          \"match\": \"\\\\b(unit|bool|int|int32|int64|nativeint|float|char|bytes|string)\\\\b\"\n        }\n      ]\n    },\n\n    \"identifiers\": {\n      \"patterns\": [\n        {\n          \"comment\": \"wildcard underscore\",\n          \"name\": \"constant.language.ocaml\",\n          \"match\": \"\\\\b_\\\\b\"\n        },\n        {\n          \"comment\": \"capital identifier for constructor, exception, or module\",\n          \"name\": \"constant.language.capital-identifier.ocaml\",\n          \"match\": \"\\\\b[[:upper:]][[:word:]']*('|\\\\b)\"\n        },\n        {\n          \"comment\": \"lowercase identifier\",\n          \"name\": \"source.ocaml\",\n          \"match\": \"\\\\b[[:lower:]_][[:word:]']*('|\\\\b)\"\n        },\n        {\n          \"comment\": \"polymorphic variant tag\",\n          \"name\": \"constant.language.polymorphic-variant.ocaml\",\n          \"match\": \"\\\\`[[:alpha:]][[:word:]']*\\\\b\"\n        },\n        {\n          \"comment\": \"empty list (can be used as a constructor)\",\n          \"name\": \"constant.language.list.ocaml\",\n          \"match\": \"\\\\[\\\\]\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/ocamlbuild.json",
    "content": "{\n  \"scopeName\": \"source.ocaml.ocamlbuild\",\n  \"fileTypes\": [\"_tags\"],\n  \"patterns\": [\n    { \"include\": \"#comments\" },\n    { \"include\": \"#lines\" },\n    {\n      \"comment\": \"comma separator\",\n      \"name\": \"keyword.other.ocamlbuild punctuation.comma punctuation.separator.comma\",\n      \"match\": \",\"\n    }\n  ],\n  \"repository\": {\n    \"comments\": {\n      \"comment\": \"line comment\",\n      \"name\": \"comment.line.ocamlbuild\",\n      \"begin\": \"#\",\n      \"end\": \"$\"\n    },\n\n    \"lines\": {\n      \"begin\": \"^[[:space:]]*\",\n      \"end\": \"(:)|$\",\n      \"endCaptures\": { \"1\": { \"name\": \"keyword.operator.ocamlbuild\" } },\n      \"patterns\": [{ \"include\": \"#expressions\" }]\n    },\n\n    \"expressions\": {\n      \"comment\": \"glob expressions\",\n      \"patterns\": [\n        {\n          \"begin\": \"<\",\n          \"end\": \">\",\n          \"beginCaptures\": [{ \"name\": \"keyword.operator.ocamlbuild\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.operator.ocamlbuild\" }],\n          \"name\": \"string.quoted.double.ocamlbuild\",\n          \"patterns\": [{ \"include\": \"#patterns\" }]\n        },\n        {\n          \"comment\": \"quoted string\",\n          \"name\": \"string.quoted.double.ocamlbuild\",\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\"\n        },\n        {\n          \"comment\": \"boolean\",\n          \"name\": \"constant.language.ocamlbuild\",\n          \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n        {\n          \"comment\": \"operators\",\n          \"name\": \"keyword.operator.ocamlbuild\",\n          \"match\": \"\\\\b(or|and|not)\\\\b\"\n        },\n        { \"include\": \"#variables\" },\n        { \"include\": \"$self\" }\n      ]\n    },\n\n    \"patterns\": {\n      \"comment\": \"glob patterns\",\n      \"patterns\": [\n        { \"name\": \"keyword.operator.ocamlbuild\", \"match\": \"\\\\?\" },\n        { \"name\": \"constant.language.ocamlbuild\", \"match\": \"\\\\*\" },\n        {\n          \"begin\": \"{\",\n          \"end\": \"}\",\n          \"beginCaptures\": [{ \"name\": \"keyword.operator.ocamlbuild\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.operator.ocamlbuild\" }],\n          \"patterns\": [\n            { \"name\": \"keyword.operator.ocamlbuild\", \"match\": \",\" },\n            { \"include\": \"#patterns\" }\n          ]\n        },\n        {\n          \"begin\": \"\\\\[\\\\^?\",\n          \"end\": \"\\\\]\",\n          \"beginCaptures\": [{ \"name\": \"keyword.operator.ocamlbuild\" }],\n          \"endCaptures\": [{ \"name\": \"keyword.operator.ocamlbuild\" }]\n        }\n      ]\n    },\n\n    \"variables\": {\n      \"comment\": \"pattern variables\",\n      \"patterns\": [\n        {\n          \"match\": \"(%)\\\\([^:)]*\\\\)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.operator.ocamlbuild\" }\n          },\n          \"patterns\": [{ \"include\": \"#expressions\" }]\n        },\n        {\n          \"begin\": \"(%)\\\\([^:]*(:)\",\n          \"end\": \"\\\\)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.operator.ocamlbuild\" },\n            \"2\": { \"name\": \"keyword.operator.ocamlbuild\" }\n          },\n          \"patterns\": [{ \"include\": \"#expressions\" }]\n        },\n        {\n          \"name\": \"keyword.operator.ocamlbuild\",\n          \"match\": \"%\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/ocamldoc.json",
    "content": "{\n  \"scopeName\": \"source.ocaml.ocamldoc\",\n  \"name\": \"comment.other.ocamldoc\",\n  \"fileTypes\": [\"mld\"],\n  \"patterns\": [\n    {\n      \"name\": \"comment.other.ocamldoc\",\n      \"begin\": \"\",\n      \"end\": \"\",\n      \"patterns\": [{ \"include\": \"#markup\" }]\n    }\n  ],\n  \"repository\": {\n    \"markup\": {\n      \"patterns\": [\n        {\n          \"comment\": \"ocamldoc documentation tag\",\n          \"name\": \"keyword.doc-tag.ocamldoc\",\n          \"match\": \"\\\\@[[:lower:]]+\"\n        },\n        {\n          \"comment\": \"embedded ocaml source\",\n          \"begin\": \"\\\\[\",\n          \"end\": \"\\\\]\",\n          \"contentName\": \"source.embedded.ocamldoc\",\n          \"patterns\": [{ \"include\": \"source.ocaml\" }]\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/ocamlformat.json",
    "content": "{\n  \"name\": \"OCamlFormat\",\n  \"scopeName\": \"source.ocaml.ocamlformat\",\n  \"fileTypes\": [\".ocamlformat\"],\n  \"patterns\": [\n    {\n      \"include\": \"#comments\"\n    },\n    {\n      \"include\": \"#options\"\n    },\n    {\n      \"include\": \"#values\"\n    },\n    {\n      \"comment\": \"equals sign\",\n      \"name\": \"punctuation.separator.key-value.ocamlformat\",\n      \"match\": \"=\"\n    }\n  ],\n  \"repository\": {\n    \"comments\": {\n      \"comment\": \"line comment\",\n      \"name\": \"comment.line.ocamlformat\",\n      \"begin\": \"#\",\n      \"end\": \"$\"\n    },\n    \"options\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(align-cases|align-constructors-decl|align-variants-decl|assignment-operator)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(break-before-in|break-cases|break-collection-expressions|break-collection|break-fun-decl|break-fun-sig|break-infix-before-func|break-infix|break-separators|break-sequences|break-string-literals|break-struct)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(cases-exp-indent|cases-matching-exp-indent|comment-check)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(disable|disambiguate-non-breaking-match|doc-comments-padding|doc-comments-tag-only|doc-comments-val|doc-comments|dock-collection-brackets)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(escape-chars|escape-strings|exp-grouping|extension-indent|extension-sugar)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(field-space|function-indent-nested|function-indent)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(if-then-else|indent-after-in|indicate-multiline-delimiters|indicate-nested-or-patterns|infix-precedence)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(leading-nested-match-parens|let-and|let-binding-indent|let-binding-spacing|let-module|let-open)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(m|margin|match-indent-nested|match-indent|max-indent|module-item-spacing|max-iters)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(n|nested-match|no-align-cases|no-align-constructors-decl|no-align-variants-decl|no-break-infix-before-func|no-break-sequences|no-disable|no-disambiguate-non-breaking-match|no-dock-collection-brackets|no-leading-nested-match-parens|no-ocp-indent-compat|no-parens-ite|no-parse-docstrings|no-space-around-arrays|no-space-around-lists|no-space-around-records|no-space-around-variants|no-wrap-comments|no-wrap-fun-args)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(ocp-indent-compat)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(p|profile|parens-ite|parens-tuple-patterns|parens-tuple|parse-docstrings)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(q|quiet)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(sequence-blank-line|sequence-style|single-case|space-around-arrays|space-around-lists|space-around-records|space-around-variants|stritem-extension-indent)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(type-decl-indent|type-decl)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(version)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.other.ocamlformat\",\n          \"match\": \"\\\\b(wrap-comments|wrap-fun-args)\\\\b\"\n        }\n      ]\n    },\n    \"values\": {\n      \"patterns\": [\n        {\n          \"comment\": \"boolean literal\",\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n        {\n          \"comment\": \"numeric literal\",\n          \"name\": \"constant.numeric.decimal.ocamlformat\",\n          \"match\": \"\\\\b([[:digit:]]+(\\\\.[[:digit:]]*)*)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(after-when-possible|after|align|all|always|auto)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(before-except-val|before|begin-line)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(closing-on-separate-line|compact|conventional)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(decimal|default|double-semicolon)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(end-line)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(fit-or-vertical|fit|force)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(hexadecimal)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(indent)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(janestreet)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(k-r|keyword-first)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(long|loose)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(multi-line-only)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(natural|nested|never|no|normal)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(ocamlformat)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(parens|preserve-one|preserve)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(separator|short|smart|space|sparse)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(terminator|tight-decl|tight|toplevel)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(unsafe-no|unset)\\\\b\"\n        },\n        {\n          \"name\": \"string.other.ocamlformat\",\n          \"match\": \"\\\\b(wrap)\\\\b\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/ocamllex.json",
    "content": "{\n  \"name\": \"OCamllex\",\n  \"scopeName\": \"source.ocaml.ocamllex\",\n  \"fileTypes\": [\"mll\"],\n  \"foldingStartMarker\": \"{\",\n  \"foldingStopMarker\": \"}\",\n  \"keyEquivalent\": \"^~O\",\n  \"patterns\": [\n    {\n      \"include\": \"source.ocaml#comments\"\n    },\n    {\n      \"include\": \"source.ocaml#strings\"\n    },\n    {\n      \"include\": \"source.ocaml#characters\"\n    },\n\n    {\n      \"include\": \"#rules\"\n    },\n    {\n      \"include\": \"#keywords\"\n    },\n    {\n      \"include\": \"#actions\"\n    },\n    {\n      \"include\": \"#regex\"\n    },\n\n    {\n      \"match\": \"(’|‘|“|”)\",\n      \"name\": \"invalid.illegal.unrecognized-character.ocamllex\"\n    }\n  ],\n  \"repository\": {\n    \"rules\": {\n      \"match\": \"\\\\b(rule|and)[[:space:]]+([[:lower:]][[:word:]']*('|\\\\b))\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"keyword.other.ocamllex\"\n        },\n        \"2\": {\n          \"name\": \"entity.name.function.rule.ocamllex\"\n        }\n      }\n    },\n\n    \"keywords\": {\n      \"patterns\": [\n        {\n          \"comment\": \"ocamllex reserved keywords\",\n          \"name\": \"keyword.other.ocamllex\",\n          \"match\": \"\\\\b(let|as|rule|and|parse|shortest|refill)\\\\b(?!')\"\n        },\n        {\n          \"comment\": \"assignment operator\",\n          \"match\": \"=\",\n          \"name\": \"keyword.operator.symbol.ocamllex\"\n        }\n      ]\n    },\n\n    \"actions\": {\n      \"patterns\": [\n        {\n          \"comment\": \"embedded ocaml source\",\n          \"begin\": \"{\",\n          \"beginCaptures\": [{ \"name\": \"keyword.other.ocamllex\" }],\n          \"end\": \"}\",\n          \"endCaptures\": [{ \"name\": \"keyword.other.ocamllex\" }],\n          \"patterns\": [{ \"include\": \"source.ocaml\" }]\n        }\n      ]\n    },\n\n    \"regex\": {\n      \"patterns\": [\n        {\n          \"comment\": \"regex character set\",\n          \"name\": \"punctuation.character-set.ocamllex\",\n          \"match\": \"\\\\[|\\\\]\"\n        },\n        {\n          \"comment\": \"regex group\",\n          \"name\": \"punctuation.group.ocamllex\",\n          \"match\": \"\\\\(|\\\\)\"\n        },\n        {\n          \"comment\": \"regex operators\",\n          \"name\": \"keyword.operator.ocamllex\",\n          \"match\": \"\\\\^|#|\\\\*|\\\\+|\\\\?|\\\\||-\"\n        },\n        {\n          \"comment\": \"end-of-file token\",\n          \"name\": \"constant.language.eof.ocamllex\",\n          \"match\": \"\\\\beof\\\\b\"\n        },\n        {\n          \"comment\": \"reference to regex pattern\",\n          \"name\": \"entity.name.type.reference.ocamllex\",\n          \"match\": \"\\\\b[[:alpha:]][[:word:]']*('|\\\\b)\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/opam-install.json",
    "content": "{\n  \"scopeName\": \"source.ocaml.opam-install\",\n  \"fileTypes\": [\"install\"],\n  \"patterns\": [\n    {\n      \"name\": \"comment.line.opam-install\",\n      \"begin\": \"#\",\n      \"end\": \"$\"\n    },\n    {\n      \"match\": \"^[[:space:]]*(lib|lib_root|libexec|libexec_root|bin|sbin|toplevel|share|share_root|etc|doc|stublibs|man|misc)[[:space:]]*(:)\",\n      \"captures\": {\n        \"1\": { \"name\": \"entity.name.tag.opam-install\" },\n        \"2\": { \"name\": \"keyword.operator.opam-install\" }\n      }\n    },\n    {\n      \"name\": \"string.quoted.double.opam-install\",\n      \"begin\": \"\\\"\",\n      \"end\": \"\\\"\"\n    }\n  ]\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/opam.json",
    "content": "{\n  \"scopeName\": \"source.ocaml.opam\",\n  \"fileTypes\": [\"opam\"],\n  \"patterns\": [\n    { \"include\": \"#comments\" },\n    { \"include\": \"#fields\" },\n    { \"include\": \"#values\" }\n  ],\n  \"repository\": {\n    \"comments\": {\n      \"patterns\": [\n        {\n          \"comment\": \"block comment\",\n          \"name\": \"comment.block.opam\",\n          \"begin\": \"\\\\(\\\\*\",\n          \"end\": \"\\\\*\\\\)\"\n        },\n        {\n          \"comment\": \"line comment\",\n          \"name\": \"comment.line.opam\",\n          \"begin\": \"#\",\n          \"end\": \"$\"\n        }\n      ]\n    },\n\n    \"fields\": {\n      \"comment\": \"labeled field\",\n      \"match\": \"^([[:word:]-]*[[:alpha:]][[:word:]-]*)(:)\",\n      \"captures\": {\n        \"1\": { \"name\": \"entity.name.tag.opam\" },\n        \"2\": { \"name\": \"keyword.operator.opam\" }\n      }\n    },\n\n    \"values\": {\n      \"patterns\": [\n        {\n          \"comment\": \"boolean literal\",\n          \"name\": \"constant.language.opam\",\n          \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n        {\n          \"comment\": \"integer literal\",\n          \"name\": \"constant.numeric.decimal.opam\",\n          \"match\": \"(\\\\b|\\\\-?)[[:digit:]]+\\\\b\"\n        },\n        {\n          \"comment\": \"double-quote string literal\",\n          \"name\": \"string.quoted.double.opam\",\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\",\n          \"patterns\": [{ \"include\": \"#string-elements\" }]\n        },\n        {\n          \"comment\": \"triple-double-quote string literal\",\n          \"name\": \"string.quoted.triple-double.opam\",\n          \"begin\": \"\\\"\\\"\\\"\",\n          \"end\": \"\\\"\\\"\\\"\",\n          \"patterns\": [{ \"include\": \"#string-elements\" }]\n        },\n        {\n          \"comment\": \"operator\",\n          \"name\": \"keyword.operator.opam\",\n          \"match\": \"[!=<>\\\\|&?:]+\"\n        },\n        {\n          \"comment\": \"identifier\",\n          \"match\": \"\\\\b([[:word:]+-]+)\\\\b\",\n          \"name\": \"variable.parameter.opam\"\n        }\n      ]\n    },\n\n    \"string-elements\": {\n      \"patterns\": [\n        {\n          \"comment\": \"escaped backslash\",\n          \"name\": \"constant.character.escape.opam\",\n          \"match\": \"\\\\\\\\\\\\\\\\\"\n        },\n        {\n          \"comment\": \"escaped quote or whitespace\",\n          \"name\": \"constant.character.escape.opam\",\n          \"match\": \"\\\\\\\\[\\\"ntbr\\\\n]\"\n        },\n        {\n          \"comment\": \"character from decimal ASCII code\",\n          \"name\": \"constant.character.escape.opam\",\n          \"match\": \"\\\\\\\\[[:digit:]]{3}\"\n        },\n        {\n          \"comment\": \"character from hexadecimal ASCII code\",\n          \"name\": \"constant.character.escape.opam\",\n          \"match\": \"\\\\\\\\x[[:xdigit:]]{2}\"\n        },\n        {\n          \"comment\": \"variable interpolation\",\n          \"name\": \"constant.variable.opam\",\n          \"begin\": \"%\\\\{\",\n          \"end\": \"}\\\\%\"\n        },\n        {\n          \"comment\": \"unknown escape sequence\",\n          \"name\": \"invalid.illegal.unknown-escape.opam\",\n          \"match\": \"\\\\\\\\.\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/reason-markdown-codeblock.json",
    "content": "{\n  \"fileTypes\": [],\n  \"injectionSelector\": \"L:markup.fenced_code.block.markdown\",\n  \"patterns\": [{ \"include\": \"#reason-code-block\" }],\n  \"repository\": {\n    \"reason-code-block\": {\n      \"begin\": \"(re|reason|reasonml)(\\\\s+[^`~]*)?$\",\n      \"end\": \"(^|\\\\G)(?=\\\\s*[`~]{3,}\\\\s*$)\",\n      \"patterns\": [\n        {\n          \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n          \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n          \"contentName\": \"meta.embedded.block.reason\",\n          \"patterns\": [\n            {\n              \"include\": \"source.reason\"\n            }\n          ]\n        }\n      ]\n    }\n  },\n  \"scopeName\": \"markdown.reason.codeblock\"\n}\n"
  },
  {
    "path": "extensions/ocaml-web/syntaxes/reason.json",
    "content": "{\n  \"name\": \"Reason\",\n  \"scopeName\": \"source.reason\",\n  \"fileTypes\": [\"re\", \"rei\"],\n  \"patterns\": [\n    { \"include\": \"#structure-expression-block-item\" },\n    { \"include\": \"#value-expression\" }\n  ],\n  \"repository\": {\n    \"attribute\": {\n      \"begin\": \"(?=\\\\[(@{1,3})[[:space:]]*[[:alpha:]])\",\n      \"end\": \"\\\\]\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\[(@{1,3})\",\n          \"end\": \"(?=[^_\\\\.'[:word:]])\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [{ \"include\": \"#attribute-identifier\" }]\n        },\n        { \"include\": \"#attribute-payload\" }\n      ]\n    },\n    \"attribute-identifier\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\b([[:alpha:]][[:word:]]*)\\\\b[[:space:]]*(?:(\\\\.))\",\n          \"captures\": {\n            \"1\": { \"name\": \"support.class entity.name.class\" },\n            \"2\": { \"name\": \"keyword.control.less\" }\n          }\n        },\n        {\n          \"match\": \"\\\\b([[:alpha:]][[:word:]]*)\\\\b\",\n          \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n        }\n      ]\n    },\n    \"attribute-payload\": {\n      \"patterns\": [\n        {\n          \"begin\": \"(:)\",\n          \"end\": \"(?=\\\\])\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#structure-expression\" },\n            { \"include\": \"#module-item-type\" },\n            { \"include\": \"#type-expression\" }\n          ]\n        },\n        {\n          \"begin\": \"([\\\\?])\",\n          \"end\": \"(?=\\\\])\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#pattern-guard\" },\n            { \"include\": \"#pattern\" }\n          ]\n        },\n        { \"include\": \"#structure-expression-block-item\" },\n        { \"include\": \"#value-expression\" }\n      ]\n    },\n    \"class-item-inherit\": {\n      \"begin\": \"\\\\b(inherit)\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#value-expression\" }]\n    },\n    \"class-item-method\": {\n      \"begin\": \"\\\\b(method)\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"storage.type\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-value-bind-name-params-type-body\" }\n      ]\n    },\n    \"comment\": {\n      \"name\": \"comment\",\n      \"patterns\": [\n        { \"include\": \"#comment-line\" },\n        { \"include\": \"#comment-block-doc\" },\n        { \"include\": \"#comment-block\" }\n      ]\n    },\n    \"comment-line\": {\n      \"name\": \"comment.line\",\n      \"begin\": \"(^[ \\\\t]+)?((//))\",\n      \"end\": \"(?=^)\"\n    },\n    \"comment-block\": {\n      \"begin\": \"/\\\\*\",\n      \"end\": \"\\\\*/\",\n      \"name\": \"comment.block\",\n      \"patterns\": [\n        { \"include\": \"#comment-block-doc\" },\n        { \"include\": \"#comment-block\" }\n      ]\n    },\n    \"comment-block-doc\": {\n      \"begin\": \"/\\\\*\\\\*(?!/)\",\n      \"end\": \"\\\\*/\",\n      \"name\": \"comment.block.documentation\",\n      \"patterns\": [\n        { \"include\": \"#comment-block-doc\" },\n        { \"include\": \"#comment-block\" }\n      ]\n    },\n    \"condition-lhs\": {\n      \"begin\": \"(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])([\\\\?])(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])\",\n      \"end\": \"(?=[\\\\)])\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control message.error variable.interpolation\" }\n      },\n      \"patterns\": [\n        {\n          \"match\": \"(?:\\\\b|[[:space:]]+)([?])(?:\\\\b|[[:space:]]+)\",\n          \"name\": \"keyword.control message.error variable.interpolation\"\n        },\n        { \"include\": \"#value-expression\" }\n      ]\n    },\n    \"extension-node\": {\n      \"begin\": \"(?=\\\\[(%{1,3})[[:space:]]*[[:alpha:]])\",\n      \"end\": \"\\\\]\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\[(%{1,3})\",\n          \"end\": \"(?=[^_\\\\.'[:word:]])\\\\:?\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [{ \"include\": \"#attribute-identifier\" }]\n        },\n        { \"include\": \"#attribute-payload\" }\n      ]\n    },\n    \"jsx\": {\n      \"patterns\": [{ \"include\": \"#jsx-head\" }, { \"include\": \"#jsx-tail\" }]\n    },\n    \"jsx-attributes\": {\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b[[:space:]]*(=)\",\n          \"end\": \"(?<![=])(?=[/>[:lower:]])\",\n          \"comment\": \"meta.separator\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n            },\n            \"2\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [{ \"include\": \"#value-expression-atomic-with-paths\" }]\n        },\n        {\n          \"match\": \"(\\\\b([[:lower:]][[:word:]]*)\\\\b[[:space:]]*+)\",\n          \"captures\": {\n            \"1\": { \"comment\": \"meta.separator\" },\n            \"2\": {\n              \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n            }\n          }\n        }\n      ]\n    },\n    \"jsx-body\": {\n      \"begin\": \"((>))\",\n      \"end\": \"(?=</)\",\n      \"beginCaptures\": {\n        \"1\": { \"comment\": \"meta.separator\" },\n        \"2\": { \"name\": \"punctuation.definition.tag.end.js\" }\n      },\n      \"patterns\": [\n        {\n          \"comment\": \"FIXME: seems necessary in order to properly tokenize `[[:word:]]</` boundary\",\n          \"match\": \"[[:lower:]][[:word:]]*\"\n        },\n        { \"include\": \"#value-expression\" }\n      ]\n    },\n    \"jsx-head\": {\n      \"begin\": \"((<))(?=[_[:alpha:]])\",\n      \"end\": \"((/>))|(?=</)\",\n      \"applyEndPatternLast\": true,\n      \"beginCaptures\": {\n        \"1\": { \"comment\": \"meta.separator\" },\n        \"2\": { \"name\": \"punctuation.definition.tag.begin.js\" }\n      },\n      \"endCaptures\": {\n        \"1\": { \"comment\": \"meta.separator\" },\n        \"2\": { \"name\": \"punctuation.definition.tag.end.js\" }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\G\",\n          \"end\": \"(?=[[:space:]/>])[[:space:]]*+\",\n          \"comment\": \"meta.separator\",\n          \"patterns\": [\n            { \"include\": \"#module-path-simple\" },\n            {\n              \"match\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n              \"name\": \"entity.name.tag.inline.any.html\"\n            }\n          ]\n        },\n        { \"include\": \"#jsx-attributes\" },\n        { \"include\": \"#jsx-body\" },\n        { \"include\": \"#comment\" }\n      ]\n    },\n    \"jsx-tail\": {\n      \"begin\": \"\\\\G(/>)|(</)\",\n      \"end\": \"(>)\",\n      \"applyEndPatternLast\": true,\n      \"comment\": \"meta.separator\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"punctuation.definition.tag.end.js\" },\n        \"2\": { \"name\": \"punctuation.definition.tag.begin.js\" }\n      },\n      \"endCaptures\": {\n        \"1\": { \"name\": \"punctuation.definition.tag.end.js\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-path-simple\" },\n        {\n          \"match\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n          \"name\": \"entity.name.tag.inline.any.html\"\n        }\n      ]\n    },\n    \"module-name-extended\": {\n      \"patterns\": [\n        { \"include\": \"#module-name-simple\" },\n        {\n          \"begin\": \"([\\\\(])\",\n          \"end\": \"([\\\\)])\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          },\n          \"patterns\": [{ \"include\": \"#module-path-extended\" }]\n        }\n      ]\n    },\n    \"module-name-simple\": {\n      \"match\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n      \"name\": \"support.class entity.name.class\"\n    },\n    \"module-path-extended\": {\n      \"patterns\": [\n        { \"include\": \"#module-name-extended\" },\n        { \"include\": \"#comment\" },\n        {\n          \"comment\": \"NOTE: end early to avoid too much reparsing\",\n          \"begin\": \"([\\\\.])\",\n          \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [\n            {\n              \"begin\": \"(?<=[\\\\.])\",\n              \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n              \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-name-extended\" }\n              ]\n            }\n          ]\n        }\n      ]\n    },\n    \"module-path-extended-prefix\": {\n      \"begin\": \"(?=\\\\b[[:upper:]])\",\n      \"end\": \"([\\\\.])|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#module-path-extended\" }]\n    },\n    \"module-path-simple\": {\n      \"patterns\": [\n        { \"include\": \"#module-name-simple\" },\n        { \"include\": \"#comment\" },\n        {\n          \"comment\": \"NOTE: end early to avoid too much reparsing\",\n          \"begin\": \"([\\\\.])\",\n          \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"begin\": \"(?<=[\\\\.])\",\n              \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n              \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-name-simple\" }\n              ]\n            }\n          ]\n        }\n      ]\n    },\n    \"module-path-simple-prefix\": {\n      \"begin\": \"(?=\\\\b[[:upper:]])\",\n      \"end\": \"([\\\\.])|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#module-path-simple\" }]\n    },\n    \"module-item-class-type\": {\n      \"comment\": \"FIXME: proper parsing\",\n      \"begin\": \"\\\\b(class)\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(type)\\\\b\",\n          \"end\": \"(?==)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          },\n          \"patterns\": [{ \"include\": \"#module-item-type-bind-name-tyvars\" }]\n        },\n        {\n          \"begin\": \"(=)\",\n          \"end\": \"(?=;)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#attribute\" },\n            { \"include\": \"#comment\" },\n            { \"include\": \"#class-item-inherit\" },\n            { \"include\": \"#class-item-method\" }\n          ]\n        }\n      ]\n    },\n    \"module-item-exception\": {\n      \"begin\": \"\\\\b(exception)\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#module-item-type-bind-body-item\" }]\n    },\n    \"module-item-external\": {\n      \"begin\": \"\\\\b(external)\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"storage.type\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-value-bind-name-or-pattern\" },\n        { \"include\": \"#module-item-let-value-bind-type\" },\n        {\n          \"begin\": \"(=)\",\n          \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#attribute\" },\n            {\n              \"begin\": \"\\\"\",\n              \"end\": \"\\\"\",\n              \"name\": \"string.double string.regexp\",\n              \"patterns\": [\n                { \"include\": \"#value-literal-string-escape\" },\n                {\n                  \"match\": \"(?:(%)(.*?)|(caml.*?))(?=\\\"|(?:[^\\\\\\\\\\\\n]$))\",\n                  \"captures\": {\n                    \"1\": {\n                      \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n                    },\n                    \"2\": {\n                      \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                    },\n                    \"3\": {\n                      \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                    }\n                  }\n                }\n              ]\n            }\n          ]\n        }\n      ]\n    },\n    \"module-item-include\": {\n      \"begin\": \"\\\\b(include)\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.include\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#signature-expression\" }]\n    },\n    \"module-item-let\": {\n      \"begin\": \"\\\\b(let)((%)([[:word:]\\\\.]+))?\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"storage.type\" },\n        \"3\": { \"name\": \"keyword.control.less\" },\n        \"4\": { \"name\": \"entity.name.class\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-module\" },\n        { \"include\": \"#module-item-let-value\" }\n      ]\n    },\n    \"module-item-let-module\": {\n      \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(module)\\\\b\",\n      \"end\": \"(?=[;}]|\\\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.control storage.type message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-item-let-module-and\" },\n        { \"include\": \"#module-item-let-module-rec\" },\n        { \"include\": \"#module-item-let-module-bind-name-params-type-body\" }\n      ]\n    },\n    \"module-item-let-module-and\": {\n      \"begin\": \"\\\\b(and)\\\\b\",\n      \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"storage.type\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-module-bind-name-params-type-body\" }\n      ]\n    },\n    \"module-item-let-module-bind-body\": {\n      \"begin\": \"(=>?)\",\n      \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.less\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#structure-expression\" },\n        { \"include\": \"#extension-node\" }\n      ]\n    },\n    \"module-item-let-module-bind-name-params\": {\n      \"begin\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b\",\n      \"end\": \"(?=[;:}=]|\\\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"support.class entity.name.class\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-item-let-module-param\" }\n      ]\n    },\n    \"module-item-let-module-bind-name-params-type-body\": {\n      \"begin\": \"(?:\\\\G|^)\",\n      \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-item-let-module-bind-name-params\" },\n        { \"include\": \"#module-item-let-module-bind-type\" },\n        { \"include\": \"#module-item-let-module-bind-body\" }\n      ]\n    },\n    \"module-item-let-module-bind-type\": {\n      \"begin\": \"(:)\",\n      \"end\": \"(?=[;}=]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#signature-expression\" }]\n    },\n    \"module-item-let-module-param\": {\n      \"begin\": \"(?=\\\\()\",\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\(\",\n          \"end\": \"(?=[:])\",\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            { \"include\": \"#module-name-simple\" }\n          ]\n        },\n        {\n          \"begin\": \"(:)\",\n          \"end\": \"(?=\\\\))\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [{ \"include\": \"#signature-expression\" }]\n        }\n      ]\n    },\n    \"module-item-let-module-rec\": {\n      \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(rec)\\\\b\",\n      \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control storage.modifier.rec\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-module-bind-name-params-type-body\" }\n      ]\n    },\n    \"module-item-let-value\": {\n      \"patterns\": [\n        { \"include\": \"#module-item-let-value-and\" },\n        { \"include\": \"#module-item-let-value-rec\" },\n        { \"include\": \"#module-item-let-value-bind-name-params-type-body\" }\n      ]\n    },\n    \"module-item-let-value-and\": {\n      \"begin\": \"\\\\b(and)\\\\b\",\n      \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"storage.type\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-value-bind-name-params-type-body\" }\n      ]\n    },\n    \"module-item-let-value-bind-body\": {\n      \"begin\": \"(=>?)\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.less\" }\n      },\n      \"patterns\": [{ \"include\": \"#value-expression\" }]\n    },\n    \"module-item-let-value-bind-name-or-pattern\": {\n      \"end\": \"(?<=[^[:space:]])|(?=[[:space:]]|[;:}=]|\\\\b(and|as|class|constraint|exception|external|for|include|inherit|let|method|module|nonrec|open|private|rec|switch|try|type|val|while|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"match\": \"\\\\b(?:([_][[:word:]]+)|([[:lower:]][[:word:]]*))\\\\b\",\n          \"captures\": {\n            \"1\": { \"name\": \"comment\" },\n            \"2\": { \"name\": \"entity.name.function\" }\n          }\n        },\n        { \"include\": \"#module-item-let-value-bind-parens-params\" },\n        { \"include\": \"#pattern\" }\n      ]\n    },\n    \"module-item-let-value-bind-name-params-type-body\": {\n      \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#module-item-let-value-bind-name-or-pattern\" },\n        { \"include\": \"#module-item-let-value-bind-params-type\" },\n        { \"include\": \"#module-item-let-value-bind-type\" },\n        { \"include\": \"#module-item-let-value-bind-body\" }\n      ]\n    },\n    \"module-item-let-value-bind-params-type\": {\n      \"begin\": \"(?=[^[:space:]:=])\",\n      \"end\": \"(?=[;}=]|\\\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-item-let-value-param\" },\n        {\n          \"begin\": \"(?<![:])(:)[[:space:]]*(?![[:space:]]*[:\\\\)])\",\n          \"end\": \"(?=[;}=]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [{ \"include\": \"#type-expression-atomic\" }]\n        }\n      ]\n    },\n    \"module-item-let-value-bind-parens-params\": {\n      \"begin\": \"\\\\((?![\\\\)])\",\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        { \"include\": \"#operator\" },\n        { \"include\": \"#pattern-parens-lhs\" },\n        { \"include\": \"#type-annotation-rhs\" },\n        { \"include\": \"#pattern\" }\n      ]\n    },\n    \"module-item-let-value-bind-pattern\": {\n      \"begin\": \"(?<=[^[:word:]]and|^and|[^[:word:]]external|^external|[^[:word:]]let|^let|[^[:word:]]method|^method|[^[:word:]]rec|^rec)\",\n      \"end\": \"(?=[;:}=]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-item-let-value-bind-parens-params\" },\n        { \"include\": \"#pattern\" }\n      ]\n    },\n    \"module-item-let-value-bind-type\": {\n      \"comment\": \"FIXME: lookahead\",\n      \"begin\": \"(?<![:])(:)(?![[:space:]]*[:\\\\)])\",\n      \"end\": \"(?==[^>]|[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(type)\\\\b\",\n          \"end\": \"([\\\\.])\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          },\n          \"endCaptures\": {\n            \"1\": { \"name\": \"entity.name.function\" }\n          },\n          \"patterns\": [{ \"include\": \"#pattern-variable\" }]\n        },\n        { \"include\": \"#type-expression\" }\n      ]\n    },\n    \"module-item-let-value-param\": {\n      \"patterns\": [\n        { \"include\": \"#module-item-let-value-param-label\" },\n        { \"include\": \"#module-item-let-value-param-type\" },\n        { \"include\": \"#module-item-let-value-param-module\" },\n        { \"include\": \"#pattern\" }\n      ]\n    },\n    \"module-item-let-value-param-label\": {\n      \"patterns\": [\n        {\n          \"begin\": \"(\\\\b[[:lower:]][[:word:]]*\\\\b)?[[:space:]]*(::)\",\n          \"end\": \"(?<=[[:space:]])\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n            },\n            \"2\": { \"name\": \"keyword.control\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#pattern\" },\n            {\n              \"begin\": \"(=)\",\n              \"end\": \"(\\\\?)|(?<=[^[:space:]=][[:space:]])(?=[[:space:]]*+[^\\\\.])\",\n              \"beginCaptures\": {\n                \"1\": {\n                  \"name\": \"markup.inserted keyword.control.less message.error\"\n                }\n              },\n              \"endCaptures\": {\n                \"1\": { \"name\": \"storage.type\" }\n              },\n              \"patterns\": [{ \"include\": \"#value-expression-atomic-with-paths\" }]\n            }\n          ]\n        }\n      ]\n    },\n    \"module-item-let-value-param-module\": {\n      \"comment\": \"FIXME: merge with pattern-parens\",\n      \"begin\": \"\\\\([[:space:]]*(?=\\\\b(module)\\\\b)\",\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(module)\\\\b\",\n          \"end\": \"(?=\\\\))\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other message.error\" }\n          },\n          \"patterns\": [\n            {\n              \"match\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n              \"name\": \"support.class entity.name.class\"\n            }\n          ]\n        }\n      ]\n    },\n    \"module-item-let-value-param-type\": {\n      \"comment\": \"FIXME: merge with pattern-parens\",\n      \"begin\": \"\\\\((?=\\\\b(type)\\\\b)\",\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(type)\\\\b\",\n          \"end\": \"(?=\\\\))\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          },\n          \"patterns\": [{ \"include\": \"#pattern-variable\" }]\n        }\n      ]\n    },\n    \"module-item-let-value-rec\": {\n      \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(rec)\\\\b\",\n      \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control storage.modifier message.error\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-value-bind-name-params-type-body\" }\n      ]\n    },\n    \"module-item-module\": {\n      \"comment\": \"NOTE: this is to support the let-module case without the let prefix\",\n      \"begin\": \"\\\\b(module)\\\\b[[:space:]]*(?!\\\\b(type)\\\\b|$)\",\n      \"end\": \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"storage.type message.error\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-let-module-and\" },\n        { \"include\": \"#module-item-let-module-rec\" },\n        { \"include\": \"#module-item-let-module-bind-name-params-type-body\" }\n      ]\n    },\n    \"module-item-module-type\": {\n      \"begin\": \"\\\\b(module)\\\\b[[:space:]]*(?=\\\\b(type)\\\\b|$)\",\n      \"end\": \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control message.error\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(type)\\\\b\",\n          \"end\": \"(?==)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            {\n              \"match\": \"([[:upper:]][[:word:]]*)\",\n              \"captures\": {\n                \"1\": { \"name\": \"support.class entity.name.class\" }\n              }\n            }\n          ]\n        },\n        {\n          \"begin\": \"(=)\",\n          \"end\": \"(?=;)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            { \"include\": \"#signature-expression\" }\n          ]\n        }\n      ]\n    },\n    \"module-item-open\": {\n      \"begin\": \"\\\\b(open)\\\\b\",\n      \"end\": \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.open\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-path-simple\" }\n      ]\n    },\n    \"module-item-type\": {\n      \"comment\": \"FIXME: the semi-colon is optional so we can re-use this for hover, which does not print the trailing ;\",\n      \"begin\": \"\\\\b(type)\\\\b\",\n      \"end\": \"(;)|(?=[\\\\)}]|\\\\b(class|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other\" }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#module-item-type-and\" },\n        { \"include\": \"#module-item-type-constraint\" },\n        { \"include\": \"#module-item-type-bind\" }\n      ]\n    },\n    \"module-item-type-and\": {\n      \"comment\": \"FIXME: the optional `type` is for module constraints\",\n      \"begin\": \"\\\\b(and)\\\\b([[:space:]]*type)?\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(class|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other\" },\n        \"2\": {\n          \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#module-item-type-bind-name-tyvars-body\" }]\n    },\n    \"module-item-type-bind\": {\n      \"comment\": \"FIXME: only allow module paths before type variables\",\n      \"patterns\": [\n        { \"include\": \"#module-item-type-bind-nonrec\" },\n        { \"include\": \"#module-item-type-bind-name-tyvars-body\" }\n      ]\n    },\n    \"module-item-type-bind-body\": {\n      \"comment\": \"FIXME: parsing\",\n      \"begin\": \"(\\\\+?=)\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.less\" }\n      },\n      \"patterns\": [{ \"include\": \"#module-item-type-bind-body-item\" }]\n    },\n    \"module-item-type-bind-body-item\": {\n      \"patterns\": [\n        {\n          \"match\": \"(=)(?!>)|\\\\b(private)\\\\b\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.less\" },\n            \"2\": {\n              \"name\": \"variable.other.class.js variable.interpolation storage.modifier message.error\"\n            }\n          }\n        },\n        {\n          \"comment\": \"FIXME: specialized version of variant rule that also scans for (\",\n          \"match\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b(?![[:space:]]*[\\\\.\\\\(])\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          }\n        },\n        {\n          \"begin\": \"(\\\\.\\\\.)\",\n          \"end\": \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          }\n        },\n        {\n          \"begin\": \"(\\\\|)(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])[[:space:]]*\",\n          \"end\": \"(?=[;\\\\)}]|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#value-expression-constructor\" },\n            {\n              \"match\": \"([:])|\\\\b(of)\\\\b\",\n              \"captures\": {\n                \"1\": { \"name\": \"keyword.control.less\" },\n                \"2\": { \"name\": \"keyword.other\" }\n              }\n            },\n            { \"include\": \"#type-expression\" }\n          ]\n        },\n        {\n          \"comment\": \"FIXME: remove this once the pretty printer no longer outputs 'of'\",\n          \"match\": \"(:)|(\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|\\\\b(of)\\\\b\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            },\n            \"2\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            },\n            \"3\": { \"name\": \"keyword.other\" }\n          }\n        },\n        { \"include\": \"#type-expression\" }\n      ]\n    },\n    \"module-item-type-bind-name-tyvars\": {\n      \"begin\": \"(?<=\\\\G|^|\\\\.)[[:space:]]*\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n      \"end\": \"(?=\\\\+?=|[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"entity.name.function\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#attribute\" },\n        {\n          \"match\": \"_\",\n          \"name\": \"comment\"\n        },\n        {\n          \"comment\": \"FIXME: add separate type-variable rule\",\n          \"match\": \"([+\\\\-])?(?:(_)|(')([[:lower:]][[:word:]]*)\\\\b)(?!\\\\.[[:upper:]])\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            },\n            \"2\": { \"name\": \"comment\" },\n            \"3\": { \"name\": \"comment\" },\n            \"4\": {\n              \"name\": \"variable.parameter string.other.link variable.language\"\n            }\n          }\n        }\n      ]\n    },\n    \"module-item-type-bind-name-tyvars-body\": {\n      \"begin\": \"(?=(\\\\G|^)[[:space:]]*\\\\b[[:alpha:]])\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#module-path-simple-prefix\" },\n        { \"include\": \"#module-item-type-bind-name-tyvars\" },\n        { \"include\": \"#module-item-type-bind-body\" }\n      ]\n    },\n    \"module-item-type-bind-nonrec\": {\n      \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(nonrec)\\\\b\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control storage.modifier message.error\" }\n      },\n      \"patterns\": [{ \"include\": \"#module-item-type-bind-name-tyvars-body\" }]\n    },\n    \"module-item-type-constraint\": {\n      \"comment\": \"FIXME: proper parsing\",\n      \"begin\": \"\\\\b(constraint)\\\\b\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation storage.modifier message.error\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"comment\": \"FIXME: add separate type-variable rule\",\n          \"match\": \"([+\\\\-])?(')([_[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            },\n            \"2\": { \"name\": \"comment\" },\n            \"3\": {\n              \"name\": \"variable.parameter string.other.link variable.language\"\n            }\n          }\n        },\n        {\n          \"match\": \"=\",\n          \"name\": \"keyword.control.less\"\n        },\n        { \"include\": \"#type-expression\" }\n      ]\n    },\n    \"object-item\": {\n      \"begin\": \"\\\\G|(;)\",\n      \"end\": \"(?=[;}]|\\\\b(class|constraint|exception|external|include|let|module|nonrec|open|private|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#class-item-method\" }]\n    },\n    \"operator\": {\n      \"patterns\": [\n        { \"include\": \"#operator-infix\" },\n        { \"include\": \"#operator-prefix\" }\n      ]\n    },\n    \"operator-infix\": {\n      \"patterns\": [\n        {\n          \"match\": \";\",\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        },\n        { \"include\": \"#operator-infix-assign\" },\n        { \"include\": \"#operator-infix-builtin\" },\n        { \"include\": \"#operator-infix-custom\" },\n        { \"comment\": \"#operator-infix-custom-hash\" }\n      ]\n    },\n    \"operator-infix-assign\": {\n      \"match\": \"(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])(=)(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])\",\n      \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control.less message.error\"\n    },\n    \"operator-infix-builtin\": {\n      \"match\": \":=\",\n      \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control.less message.error\"\n    },\n    \"operator-infix-custom\": {\n      \"match\": \"(?:(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])((<>))(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|([#\\\\-@*/&%^+<=>$\\\\\\\\][#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]*|[|][#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]+)\",\n      \"captures\": {\n        \"1\": { \"comment\": \"meta.separator\" },\n        \"2\": { \"name\": \"punctuation.definition.tag.begin.js\" },\n        \"3\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      }\n    },\n    \"operator-infix-custom-hash\": {\n      \"match\": \"#[\\\\-:!?.@*/&%^+<=>|~$]+\",\n      \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n    },\n    \"operator-prefix\": {\n      \"patterns\": [\n        { \"include\": \"#operator-prefix-bang\" },\n        { \"include\": \"#operator-prefix-label-token\" }\n      ]\n    },\n    \"operator-prefix-bang\": {\n      \"match\": \"![\\\\-:!?.@*/&%^+<=>|~$]*\",\n      \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n    },\n    \"operator-prefix-label-token\": {\n      \"match\": \"[?~][\\\\-:!?.@*/&%^+<=>|~$]+\",\n      \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n    },\n    \"pattern\": {\n      \"patterns\": [\n        { \"include\": \"#attribute\" },\n        { \"include\": \"#comment\" },\n        { \"include\": \"#pattern-atomic\" },\n        {\n          \"match\": \"[[:space:]]*+(?:(\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|\\\\b(as)\\\\b|(\\\\.\\\\.\\\\.?))[[:space:]]*+\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            },\n            \"2\": { \"name\": \"keyword.other\" },\n            \"3\": { \"name\": \"keyword.control\" }\n          }\n        }\n      ]\n    },\n    \"pattern-atomic\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\b(exception)\\\\b\",\n          \"name\": \"keyword.other\"\n        },\n        { \"include\": \"#value-expression-literal\" },\n        { \"include\": \"#module-path-simple-prefix\" },\n        { \"include\": \"#pattern-list-or-array\" },\n        { \"include\": \"#pattern-record\" },\n        { \"include\": \"#pattern-variable\" },\n        { \"include\": \"#pattern-parens\" }\n      ]\n    },\n    \"pattern-guard\": {\n      \"begin\": \"\\\\b(when)\\\\b\",\n      \"end\": \"(?==>)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.other\" }\n      },\n      \"patterns\": [{ \"include\": \"#value-expression\" }]\n    },\n    \"pattern-list-or-array\": {\n      \"begin\": \"(\\\\[\\\\|?)(?![@%])\",\n      \"end\": \"(\\\\|?\\\\])\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n        }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#value-expression-literal-list-or-array-separator\" },\n        { \"include\": \"#pattern\" }\n      ]\n    },\n    \"pattern-parens\": {\n      \"begin\": \"(?=\\\\()\",\n      \"end\": \"\\\\)|(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#pattern-parens-lhs\" },\n        { \"include\": \"#type-annotation-rhs\" }\n      ]\n    },\n    \"pattern-parens-lhs\": {\n      \"begin\": \"\\\\(|(,)\",\n      \"end\": \"(?=(?:[,:\\\\)]))|(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#pattern\" }]\n    },\n    \"record-path\": {\n      \"begin\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n      \"end\": \"(?=[^[:space:]\\\\.])(?!/\\\\*)\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#record-path-suffix\" }\n      ]\n    },\n    \"record-path-suffix\": {\n      \"begin\": \"(\\\\.)\",\n      \"end\": \"(\\\\))|\\\\b([[:upper:]][[:word:]]*)\\\\b|\\\\b([[:lower:]][[:word:]]*)\\\\b|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"endCaptures\": {\n        \"1\": { \"name\": \"keyword.control\" },\n        \"2\": { \"name\": \"support.class entity.name.class\" },\n        \"3\": {\n          \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"begin\": \"([\\\\(])\",\n          \"end\": \"(?=[\\\\)])\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            {\n              \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b(?=[^\\\\)]*([\\\\.]))\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n                },\n                \"2\": { \"name\": \"keyword.other\" }\n              }\n            },\n            {\n              \"match\": \"([\\\\.])\",\n              \"name\": \"keyword.control.less\"\n            },\n            {\n              \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b[[:space:]]*\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"variable.parameter string.other.link variable.language\"\n                }\n              }\n            },\n            { \"include\": \"#value-expression\" }\n          ]\n        }\n      ]\n    },\n    \"pattern-record\": {\n      \"begin\": \"{\",\n      \"end\": \"}\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#pattern-record-item\" }\n      ]\n    },\n    \"pattern-record-field\": {\n      \"begin\": \"\\\\b([_][[:word:]]*)\\\\b|\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n      \"end\": \"(,)|(?=})\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"comment\" },\n        \"2\": {\n          \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n        }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"begin\": \"\\\\G(:)\",\n          \"end\": \"(?=[,}])\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [{ \"include\": \"#pattern\" }]\n        }\n      ]\n    },\n    \"pattern-record-item\": {\n      \"patterns\": [\n        { \"include\": \"#module-path-simple-prefix\" },\n        { \"include\": \"#pattern-record-field\" }\n      ]\n    },\n    \"pattern-variable\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\b(_(?:[[:lower:]][[:word:]]*)?)\\\\b(?!\\\\.[[:upper:]])\",\n          \"captures\": {\n            \"1\": { \"name\": \"comment\" }\n          }\n        },\n        {\n          \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n          \"captures\": {\n            \"1\": { \"name\": \"variable.language string.other.link\" }\n          }\n        }\n      ]\n    },\n    \"signature-expression\": {\n      \"patterns\": [\n        {\n          \"comment\": \"FIXME: scan for :upper: to disambiguate type/signature in hover\",\n          \"begin\": \"(?=\\\\([[:space:]]*[[:upper:]][[:word:]]*[[:space:]]*:)\",\n          \"end\": \"(?=[;])\",\n          \"patterns\": [\n            {\n              \"begin\": \"(?=\\\\()\",\n              \"end\": \"(?=[;]|=>)\",\n              \"patterns\": [{ \"include\": \"#module-item-let-module-param\" }]\n            },\n            {\n              \"begin\": \"(=>)\",\n              \"end\": \"(?=[;\\\\(])\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"markup.inserted keyword.control.less\" }\n              },\n              \"patterns\": [{ \"include\": \"#structure-expression\" }]\n            }\n          ]\n        },\n        {\n          \"begin\": \"\\\\b(module)\\\\b[[:space:]]*\\\\b(type)\\\\b([[:space:]]*\\\\b(of)\\\\b)?\",\n          \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"markup.inserted keyword.other variable.other.readwrite.instance\"\n            },\n            \"2\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            },\n            \"3\": {\n              \"name\": \"markup.inserted keyword.other variable.other.readwrite.instance\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            { \"include\": \"#module-path-simple\" },\n            {\n              \"match\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b\",\n              \"name\": \"support.class entity.name.class\"\n            }\n          ]\n        },\n        { \"include\": \"#signature-expression-constraints\" },\n        { \"include\": \"#structure-expression\" }\n      ]\n    },\n    \"signature-expression-constraints\": {\n      \"begin\": \"(?=\\\\b(with))\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val)\\\\b)\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(and|with)\\\\b\",\n          \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation storage.modifier message.error\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            {\n              \"comment\": \"FIXME: special version of #module-item-type with non-consuming `;`. Atom seems to need this to work.\",\n              \"begin\": \"\\\\b(type)\\\\b\",\n              \"end\": \"(?=[;\\\\)}]|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\\\b)\",\n              \"beginCaptures\": {\n                \"1\": {\n                  \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n                }\n              },\n              \"patterns\": [\n                { \"include\": \"#module-item-type-and\" },\n                { \"include\": \"#module-item-type-constraint\" },\n                { \"include\": \"#module-item-type-bind\" }\n              ]\n            },\n            {\n              \"begin\": \"(?=\\\\b(module)\\\\b)\",\n              \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\\\b)\",\n              \"patterns\": [\n                {\n                  \"begin\": \"\\\\b(module)\\\\b\",\n                  \"end\": \"(?=:?=|[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n                  \"beginCaptures\": {\n                    \"1\": {\n                      \"name\": \"markup.inserted keyword.control storage.type variable.other.readwrite.instance\"\n                    }\n                  },\n                  \"patterns\": [\n                    { \"include\": \"#comment\" },\n                    { \"include\": \"#module-path-simple\" },\n                    {\n                      \"match\": \"[[:upper:]][[:word:]]*\",\n                      \"name\": \"support.class entity.name.class\"\n                    }\n                  ]\n                },\n                {\n                  \"begin\": \"(:=)|(=)\",\n                  \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n                  \"beginCaptures\": {\n                    \"1\": {\n                      \"name\": \"markup.inserted keyword.control.less message.error\"\n                    },\n                    \"2\": { \"name\": \"markup.inserted keyword.control.less\" }\n                  },\n                  \"patterns\": [{ \"include\": \"#structure-expression\" }]\n                }\n              ]\n            }\n          ]\n        }\n      ]\n    },\n    \"structure-expression\": {\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"comment\": \"FIXME: scan for :upper: or `val` to disambiguate types from signatures for hover\",\n          \"begin\": \"\\\\((?=[[:space:]]*(\\\\b(val)\\\\b|[^'\\\\[<[:lower:]]))\",\n          \"end\": \"\\\\)|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|with)\\\\b)\",\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            {\n              \"comment\": \"FIXME: might need to refactor this or include more expressions\",\n              \"include\": \"#structure-expression-block\"\n            },\n            {\n              \"begin\": \"\\\\b(val)\\\\b\",\n              \"end\": \"(?=\\\\))|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n              },\n              \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                  \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n                  \"name\": \"support.class entity.name.class\"\n                }\n              ]\n            },\n            { \"include\": \"#module-path-simple\" },\n            {\n              \"begin\": \"(:)\",\n              \"end\": \"(?=[\\\\)])|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val)\\\\b)\",\n              \"beginCaptures\": {\n                \"1\": {\n                  \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                }\n              },\n              \"patterns\": [{ \"include\": \"#signature-expression\" }]\n            }\n          ]\n        },\n        { \"include\": \"#module-path-simple\" },\n        { \"include\": \"#structure-expression-block\" }\n      ]\n    },\n    \"structure-expression-block\": {\n      \"begin\": \"{\",\n      \"end\": \"}\",\n      \"patterns\": [{ \"include\": \"#structure-expression-block-item\" }]\n    },\n    \"structure-expression-block-item\": {\n      \"patterns\": [\n        { \"include\": \"#attribute\" },\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-item-exception\" },\n        { \"include\": \"#module-item-external\" },\n        { \"include\": \"#module-item-include\" },\n        { \"include\": \"#module-item-let\" },\n        { \"include\": \"#module-item-class-type\" },\n        { \"include\": \"#module-item-module-type\" },\n        { \"include\": \"#module-item-module\" },\n        { \"include\": \"#module-item-open\" },\n        { \"include\": \"#module-item-type\" }\n      ]\n    },\n    \"type-annotation-rhs\": {\n      \"begin\": \"(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])([:])(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])\",\n      \"end\": \"(?=\\\\))|(?=[,;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#type-expression\" }]\n    },\n    \"type-expression\": {\n      \"patterns\": [\n        {\n          \"match\": \"([\\\\.])\",\n          \"name\": \"entity.name.function\"\n        },\n        { \"include\": \"#type-expression-atomic\" },\n        { \"include\": \"#type-expression-arrow\" }\n      ]\n    },\n    \"type-expression-atomic\": {\n      \"patterns\": [\n        { \"include\": \"#attribute\" },\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-path-extended-prefix\" },\n        { \"include\": \"#type-expression-label\" },\n        {\n          \"match\": \"\\\\b(as)\\\\b\",\n          \"name\": \"variable.other.class.js variable.interpolation storage.modifier message.error\"\n        },\n        { \"include\": \"#type-expression-constructor\" },\n        { \"include\": \"#type-expression-object\" },\n        { \"include\": \"#type-expression-parens\" },\n        { \"include\": \"#type-expression-polymorphic-variant\" },\n        { \"include\": \"#type-expression-record\" },\n        { \"include\": \"#type-expression-variable\" }\n      ]\n    },\n    \"type-expression-arrow\": {\n      \"match\": \"=>\",\n      \"name\": \"markup.inserted keyword.control.less\"\n    },\n    \"type-expression-constructor\": {\n      \"match\": \"(_)(?![[:alnum:]])|\\\\b([_[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n      \"captures\": {\n        \"1\": { \"name\": \"comment\" },\n        \"2\": { \"name\": \"support.type string.regexp\" }\n      }\n    },\n    \"type-expression-label\": {\n      \"begin\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b(::)\",\n      \"end\": \"(?<==>)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n        },\n        \"2\": { \"name\": \"keyword.control\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#type-expression\" },\n        {\n          \"match\": \"(\\\\?)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.less\" }\n          }\n        }\n      ]\n    },\n    \"type-expression-object\": {\n      \"comment\": \"FIXME: separate sub-rules\",\n      \"begin\": \"(<)\",\n      \"end\": \"(>)\",\n      \"captures\": {\n        \"1\": { \"name\": \"entity.name.function\" }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(\\\\.\\\\.)\",\n          \"end\": \"(?=>)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          }\n        },\n        {\n          \"comment\": \"FIXME: method item\",\n          \"begin\": \"(?=[_[:lower:]])\",\n          \"end\": \"(,)|(?=>)\",\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"comment\": \"FIXME: method name\",\n              \"begin\": \"(?=[_[:lower:]])\",\n              \"end\": \"(?=:)\",\n              \"patterns\": [\n                {\n                  \"match\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b\",\n                  \"captures\": {\n                    \"1\": {\n                      \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n                    }\n                  }\n                }\n              ]\n            },\n            {\n              \"comment\": \"FIXME: method type\",\n              \"begin\": \"(:)\",\n              \"end\": \"(?=[,>])\",\n              \"beginCaptures\": {\n                \"1\": {\n                  \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                }\n              },\n              \"patterns\": [{ \"include\": \"#type-expression\" }]\n            }\n          ]\n        }\n      ]\n    },\n    \"type-expression-parens\": {\n      \"comment\": \"FIXME: proper tuple types\",\n      \"begin\": \"\\\\(\",\n      \"end\": \"\\\\)\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(module)\\\\b\",\n          \"end\": \"(?=[\\\\)])\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other message.error\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#module-path-extended\" },\n            { \"include\": \"#signature-expression-constraints\" }\n          ]\n        },\n        {\n          \"match\": \",\",\n          \"name\": \"keyword.control.less\"\n        },\n        { \"include\": \"#type-expression\" }\n      ]\n    },\n    \"type-expression-polymorphic-variant\": {\n      \"comment\": \"FIXME: proper parsing\",\n      \"begin\": \"(\\\\[)([<>])?\",\n      \"end\": \"(\\\\])\",\n      \"captures\": {\n        \"1\": { \"name\": \"entity.name.function\" },\n        \"2\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"(\\\\|)?(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])[[:space:]]*\",\n          \"end\": \"(?=[;)}\\\\]]|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#value-expression-constructor\" },\n            {\n              \"match\": \"([:])|\\\\b(of)\\\\b|([&])\",\n              \"captures\": {\n                \"1\": { \"name\": \"keyword.control.less\" },\n                \"2\": { \"name\": \"keyword.other\" },\n                \"3\": {\n                  \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                }\n              }\n            },\n            { \"include\": \"#value-expression-constructor-polymorphic\" },\n            { \"include\": \"#type-expression\" }\n          ]\n        }\n      ]\n    },\n    \"type-expression-record\": {\n      \"begin\": \"{\",\n      \"end\": \"}\",\n      \"patterns\": [{ \"include\": \"#type-expression-record-item\" }]\n    },\n    \"type-expression-record-field-sans-modifier\": {\n      \"begin\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b\",\n      \"end\": \"(,)|(?=[,}])\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n        }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"begin\": \"(:)\",\n          \"end\": \"(?=[,}])\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [{ \"include\": \"#type-expression\" }]\n        }\n      ]\n    },\n    \"type-expression-record-field\": {\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(mutable)\\\\b\",\n          \"end\": \"(?<=[,])|(?=})\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation storage.modifier message.error\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#type-expression-record-field-sans-modifier\" }\n          ]\n        },\n        { \"include\": \"#type-expression-record-field-sans-modifier\" }\n      ]\n    },\n    \"type-expression-record-item\": {\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-path-simple-prefix\" },\n        { \"include\": \"#type-expression-record-field\" }\n      ]\n    },\n    \"type-expression-variable\": {\n      \"match\": \"(')([_[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n      \"captures\": {\n        \"1\": { \"name\": \"comment\" },\n        \"2\": {\n          \"name\": \"variable.parameter string.other.link variable.language\"\n        }\n      }\n    },\n    \"value-expression\": {\n      \"patterns\": [\n        { \"include\": \"#attribute\" },\n        { \"include\": \"#comment\" },\n        { \"include\": \"#extension-node\" },\n        { \"include\": \"#jsx\" },\n        { \"include\": \"#operator\" },\n        { \"include\": \"#value-expression-builtin\" },\n        { \"include\": \"#value-expression-if-then-else\" },\n        { \"include\": \"#value-expression-atomic\" },\n        { \"include\": \"#module-path-simple-prefix\" },\n        {\n          \"match\": \"[:?]\",\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        },\n        { \"include\": \"#record-path\" }\n      ]\n    },\n    \"value-expression-atomic\": {\n      \"patterns\": [\n        { \"include\": \"#value-expression-literal\" },\n        { \"include\": \"#value-expression-literal-list-or-array\" },\n        { \"include\": \"#value-expression-for\" },\n        { \"include\": \"#value-expression-fun\" },\n        { \"include\": \"#value-expression-block-or-record-or-object\" },\n        { \"include\": \"#value-expression-label\" },\n        { \"include\": \"#value-expression-parens\" },\n        { \"include\": \"#value-expression-switch\" },\n        { \"include\": \"#value-expression-try\" },\n        { \"include\": \"#value-expression-while\" }\n      ]\n    },\n    \"value-expression-atomic-with-paths\": {\n      \"patterns\": [\n        { \"include\": \"#value-expression-atomic\" },\n        { \"include\": \"#module-path-simple-prefix\" },\n        { \"include\": \"#record-path-suffix\" }\n      ]\n    },\n    \"value-expression-block\": {\n      \"begin\": \"{\",\n      \"end\": \"}\",\n      \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n    },\n    \"value-expression-block-item\": {\n      \"patterns\": [\n        { \"include\": \"#module-item-let\" },\n        { \"include\": \"#module-item-open\" },\n        { \"include\": \"#value-expression\" }\n      ]\n    },\n    \"value-expression-block-look\": {\n      \"begin\": \"(?![[:space:]]*($|\\\\.\\\\.\\\\.|([[:upper:]][[:word:]]*\\\\.)*([[:lower:]][[:word:]]*)[[:space:]]*(?:,|:(?![=]))))\",\n      \"end\": \"(?=})\",\n      \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n    },\n    \"value-expression-block-or-record-or-object\": {\n      \"begin\": \"{\",\n      \"end\": \"}\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-path-simple-prefix\" },\n        { \"include\": \"#value-expression-object-look\" },\n        { \"include\": \"#value-expression-record-look\" },\n        { \"include\": \"#value-expression-block-look\" }\n      ]\n    },\n    \"value-expression-builtin\": {\n      \"match\": \"\\\\b(assert|decr|failwith|fprintf|ignore|incr|land|lazy|lor|lsl|lsr|lxor|mod|new|not|printf|ref)\\\\b|\\\\b(raise)\\\\b\",\n      \"captures\": {\n        \"1\": { \"name\": \"keyword.control message.error\" },\n        \"2\": { \"name\": \"keyword.control.trycatch\" }\n      }\n    },\n    \"value-expression-constructor\": {\n      \"match\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b(?![[:space:]]*[\\\\.])\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n        }\n      }\n    },\n    \"value-expression-constructor-polymorphic\": {\n      \"match\": \"(`)([[:alpha:]][[:word:]]*)\\\\b(?!\\\\.)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"constant.other.symbol keyword.control.less variable.parameter\"\n        },\n        \"2\": {\n          \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n        }\n      }\n    },\n    \"value-expression-for\": {\n      \"begin\": \"(?=\\\\b(for)\\\\b)\",\n      \"end\": \"(?<=})|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#value-expression-for-head\" },\n        { \"include\": \"#value-expression-block\" }\n      ]\n    },\n    \"value-expression-for-head\": {\n      \"begin\": \"(?=\\\\b(for)\\\\b)\",\n      \"end\": \"(?={)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(for)\\\\b\",\n          \"end\": \"(?=\\\\b(in)\\\\b)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.loop\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            { \"include\": \"#pattern-variable\" }\n          ]\n        },\n        {\n          \"begin\": \"\\\\b(in)\\\\b\",\n          \"end\": \"(?=\\\\b(to)\\\\b)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.loop\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            { \"include\": \"#value-expression-atomic-with-paths\" }\n          ]\n        },\n        {\n          \"begin\": \"\\\\b(to)\\\\b\",\n          \"end\": \"(?={)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.loop\" }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            { \"include\": \"#value-expression-atomic-with-paths\" }\n          ]\n        },\n        { \"include\": \"#value-expression-block\" }\n      ]\n    },\n    \"value-expression-fun\": {\n      \"begin\": \"\\\\b(fun)\\\\b\",\n      \"end\": \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#value-expression-fun-pattern-match-rule-lhs\" },\n        { \"include\": \"#value-expression-fun-pattern-match-rule-rhs\" }\n      ]\n    },\n    \"value-expression-fun-pattern-match-rule-lhs\": {\n      \"begin\": \"(?=\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|(?<=fun)\",\n      \"end\": \"(\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|(?==>)|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"applyEndPatternLast\": true,\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [{ \"include\": \"#module-item-let-value-param\" }]\n    },\n    \"value-expression-fun-pattern-match-rule-rhs\": {\n      \"begin\": \"(=>)\",\n      \"end\": \"(?=[;\\\\)}]|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])|\\\\b(and)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.less\" }\n      },\n      \"patterns\": [{ \"include\": \"#value-expression\" }]\n    },\n    \"value-expression-if-then-else\": {\n      \"begin\": \"\\\\b(if)\\\\b\",\n      \"end\": \"(?=[;\\\\)\\\\]}])\",\n      \"applyEndPatternLast\": true,\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.conditional\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"begin\": \"\\\\b(else)\\\\b\",\n          \"end\": \"(?=[;\\\\)\\\\]}])\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.conditional\" }\n          },\n          \"patterns\": [{ \"include\": \"#value-expression\" }]\n        },\n        { \"include\": \"#value-expression-atomic-with-paths\" }\n      ]\n    },\n    \"value-expression-lazy\": {\n      \"comment\": \"FIXME\",\n      \"match\": \"\\\\b(lazy)\\\\b\",\n      \"captures\": {\n        \"1\": { \"name\": \"keyword.other\" }\n      }\n    },\n    \"value-expression-label\": {\n      \"begin\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b[[:space:]]*(::)(\\\\?)?\",\n      \"end\": \"(?![[:space:]])\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n        },\n        \"2\": { \"name\": \"keyword.control\" },\n        \"3\": { \"name\": \"storage.type\" }\n      },\n      \"patterns\": [{ \"include\": \"#value-expression\" }]\n    },\n    \"value-expression-literal\": {\n      \"patterns\": [\n        { \"include\": \"#value-expression-literal-boolean\" },\n        { \"include\": \"#value-expression-literal-character\" },\n        { \"include\": \"#value-expression-constructor\" },\n        { \"include\": \"#value-expression-constructor-polymorphic\" },\n        { \"include\": \"#value-expression-lazy\" },\n        { \"include\": \"#value-expression-literal-numeric\" },\n        { \"include\": \"#value-expression-literal-string\" },\n        { \"include\": \"#value-expression-literal-unit\" }\n      ]\n    },\n    \"value-expression-literal-boolean\": {\n      \"match\": \"\\\\b(false|true)\\\\b\",\n      \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n    },\n    \"value-expression-literal-character\": {\n      \"match\": \"(')([[:space:]]|[[:graph:]]|\\\\\\\\[\\\\\\\\\\\"'ntbr]|\\\\\\\\[[:digit:]][[:digit:]][[:digit:]]|\\\\\\\\x[[:xdigit:]][[:xdigit:]]|\\\\\\\\o[0-3][0-7][0-7])(')\",\n      \"name\": \"constant.character\"\n    },\n    \"value-expression-literal-list-or-array\": {\n      \"begin\": \"(\\\\[\\\\|?)(?![@%])\",\n      \"end\": \"(\\\\|?\\\\])\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"constant.language.list\" }\n      },\n      \"endCaptures\": {\n        \"1\": { \"name\": \"constant.language.list\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#value-expression-literal-list-or-array-separator\" },\n        { \"include\": \"#value-expression\" },\n        { \"include\": \"#value-expression-literal-list-or-array\" }\n      ]\n    },\n    \"value-expression-literal-list-or-array-separator\": {\n      \"match\": \"(,)|(\\\\.\\\\.\\\\.)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        },\n        \"2\": { \"name\": \"keyword.control\" }\n      }\n    },\n    \"value-expression-literal-numeric\": {\n      \"patterns\": [\n        {\n          \"match\": \"([-])?([[:digit:]][_[:digit:]]*)(?:(\\\\.)([_[:digit:]]*))?(?:([eE])([\\\\-\\\\+])?([[:digit:]][_[:digit:]]*))?(?![bBoOxX])\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.less\" },\n            \"2\": { \"name\": \"constant.numeric\" },\n            \"3\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            },\n            \"4\": { \"name\": \"constant.numeric\" },\n            \"5\": { \"name\": \"keyword.control.less\" },\n            \"6\": { \"name\": \"keyword.control.less\" },\n            \"7\": { \"name\": \"constant.numeric\" }\n          }\n        },\n        {\n          \"match\": \"([-])?(0[xX])([[:xdigit:]][_[:xdigit:]]*)(?:(\\\\.)([_[:xdigit:]]*))?(?:([pP])([\\\\-\\\\+])?([[:digit:]][_[:digit:]]*))?\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.less\" },\n            \"2\": { \"name\": \"keyword.control.less\" },\n            \"3\": { \"name\": \"constant.numeric\" },\n            \"4\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            },\n            \"5\": { \"name\": \"constant.numeric\" },\n            \"6\": { \"name\": \"keyword.control.less\" },\n            \"7\": { \"name\": \"keyword.control.less\" },\n            \"8\": { \"name\": \"constant.numeric\" }\n          }\n        },\n        {\n          \"match\": \"([-])?(0[oO])([0-7][_0-7]*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.less\" },\n            \"2\": { \"name\": \"keyword.control.less\" },\n            \"3\": { \"name\": \"constant.numeric\" }\n          }\n        },\n        {\n          \"match\": \"([-])?(0[bB])([0-1][_0-1]*)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.less\" },\n            \"2\": { \"name\": \"keyword.control.less\" },\n            \"3\": { \"name\": \"constant.numeric\" }\n          }\n        }\n      ]\n    },\n    \"value-expression-literal-string\": {\n      \"patterns\": [\n        {\n          \"begin\": \"(?<![[:alpha:]])js_expr(?!=[[:word:]])\",\n          \"end\": \"(?<=\\\")|(\\\\|)([_[:lower:]]*)?(})|(?=[^[:space:]\\\"{])\",\n          \"endCaptures\": {\n            \"1\": { \"name\": \"keyword.control.flow message.error\" },\n            \"2\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            },\n            \"3\": { \"name\": \"keyword.control.flow message.error\" }\n          },\n          \"patterns\": [\n            {\n              \"begin\": \"({)([_[:lower:]]*)?(\\\\|)\",\n              \"end\": \"(?=\\\\|\\\\2})\",\n              \"comment\": \"meta.separator\",\n              \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.flow message.error\" },\n                \"2\": {\n                  \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n                },\n                \"3\": { \"name\": \"keyword.control.flow message.error\" }\n              },\n              \"patterns\": [{ \"include\": \"source.js\" }]\n            },\n            {\n              \"begin\": \"\\\"\",\n              \"end\": \"\\\"\",\n              \"comment\": \"meta.separator\",\n              \"patterns\": [{ \"include\": \"source.js\" }]\n            }\n          ]\n        },\n        {\n          \"begin\": \"({)([_[:lower:]]*)?(\\\\|)\",\n          \"end\": \"(\\\\|)(\\\\2)(})\",\n          \"name\": \"string.double string.regexp\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control.flow message.error\" },\n            \"2\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            },\n            \"3\": { \"name\": \"keyword.control.flow message.error\" }\n          },\n          \"endCaptures\": {\n            \"1\": { \"name\": \"keyword.control.flow message.error\" },\n            \"2\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            },\n            \"3\": { \"name\": \"keyword.control.flow message.error\" }\n          }\n        },\n        {\n          \"begin\": \"\\\"\",\n          \"end\": \"\\\"\",\n          \"name\": \"string.double string.regexp\",\n          \"patterns\": [{ \"include\": \"#value-expression-literal-string-escape\" }]\n        }\n      ]\n    },\n    \"value-expression-literal-string-escape\": {\n      \"patterns\": [\n        {\n          \"comment\": \"FIXME: make escapes into separate rule\",\n          \"match\": \"\\\\\\\\[\\\\\\\\\\\"'ntbr ]|\\\\\\\\[[:digit:]][[:digit:]][[:digit:]]|\\\\\\\\x[[:xdigit:]][[:xdigit:]]|\\\\\\\\o[0-3][0-7][0-7]\",\n          \"name\": \"constant.character\"\n        },\n        {\n          \"match\": \"(@)([ \\\\[\\\\],.]|\\\\\\\\n)\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.less\" },\n            \"2\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            }\n          }\n        },\n        {\n          \"comment\": \"FIXME: don't highlight in external strings\",\n          \"match\": \"(%)([ads])?\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"entity.other.attribute-name.css constant.language constant.numeric\"\n            },\n            \"2\": {\n              \"name\": \"variable.other.readwrite.instance string.other.link variable.language\"\n            }\n          }\n        }\n      ]\n    },\n    \"value-expression-literal-unit\": {\n      \"match\": \"\\\\(\\\\)\",\n      \"name\": \"constant.language.unit\"\n    },\n    \"value-expression-object-look\": {\n      \"comment\": \"FIXME: is there a better way than listing all the keywords?\",\n      \"begin\": \"(?:\\\\G|^)[[:space:]]*(?=method)\",\n      \"end\": \"(?=})\",\n      \"patterns\": [{ \"include\": \"#object-item\" }]\n    },\n    \"value-expression-parens\": {\n      \"begin\": \"(?=\\\\()\",\n      \"end\": \"(\\\\))|(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"endCaptures\": {},\n      \"patterns\": [\n        { \"include\": \"#condition-lhs\" },\n        { \"include\": \"#value-expression-parens-lhs\" },\n        { \"include\": \"#type-annotation-rhs\" }\n      ]\n    },\n    \"value-expression-parens-lhs\": {\n      \"begin\": \"(\\\\()|(,)\",\n      \"end\": \"(?=[?,:\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"2\": {\n          \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n        }\n      },\n      \"patterns\": [\n        {\n          \"begin\": \"\\\\b(module)\\\\b\",\n          \"end\": \"(?=\\\\))\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.other message.error\" }\n          },\n          \"patterns\": [{ \"include\": \"#module-path-simple\" }]\n        },\n        { \"include\": \"#value-expression\" }\n      ]\n    },\n    \"value-expression-record-field\": {\n      \"patterns\": [\n        {\n          \"begin\": \"(\\\\.\\\\.\\\\.)\",\n          \"end\": \"(,)|(?=})\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"keyword.control\" }\n          },\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#comment\" },\n            { \"include\": \"#module-path-simple-prefix\" },\n            {\n              \"begin\": \"(?=[\\\\.])\",\n              \"end\": \"(?=[:,])\",\n              \"patterns\": [\n                {\n                  \"match\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n                  \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n                }\n              ]\n            },\n            {\n              \"begin\": \"(:)\",\n              \"end\": \"(?=[,}])\",\n              \"beginCaptures\": {\n                \"1\": {\n                  \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                }\n              },\n              \"patterns\": [{ \"include\": \"#value-expression\" }]\n            }\n          ]\n        },\n        {\n          \"begin\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n          \"end\": \"(,)|(?=})\",\n          \"beginCaptures\": {\n            \"1\": { \"name\": \"support.class entity.name.class\" }\n          },\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            { \"include\": \"#module-path-simple-prefix\" },\n            {\n              \"begin\": \"(:)\",\n              \"end\": \"(?=[,}])\",\n              \"beginCaptures\": {\n                \"1\": {\n                  \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                }\n              },\n              \"patterns\": [{ \"include\": \"#value-expression\" }]\n            }\n          ]\n        },\n        {\n          \"begin\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n          \"end\": \"(,)|(?=})\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"markup.inserted constant.language support.property-value entity.name.filename\"\n            }\n          },\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"begin\": \"(:)\",\n              \"end\": \"(?=[,}])\",\n              \"beginCaptures\": {\n                \"1\": {\n                  \"name\": \"variable.other.class.js variable.interpolation keyword.operator keyword.control message.error\"\n                }\n              },\n              \"patterns\": [{ \"include\": \"#value-expression\" }]\n            }\n          ]\n        }\n      ]\n    },\n    \"value-expression-record-item\": {\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#module-path-simple-prefix\" },\n        { \"include\": \"#value-expression-record-field\" }\n      ]\n    },\n    \"value-expression-switch\": {\n      \"begin\": \"\\\\b(switch)\\\\b\",\n      \"end\": \"(?<=})\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.switch\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#value-expression-switch-head\" },\n        { \"include\": \"#value-expression-switch-body\" }\n      ]\n    },\n    \"value-expression-switch-body\": {\n      \"begin\": \"{\",\n      \"end\": \"}\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#value-expression-switch-pattern-match-rule\" }\n      ]\n    },\n    \"value-expression-switch-head\": {\n      \"begin\": \"(?<=switch)\",\n      \"end\": \"(?<!switch)(?={)|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"begin\": \"\\\\G[[:space:]]*+{\",\n          \"end\": \"}[[:space:]]*+\",\n          \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n        },\n        { \"include\": \"#value-expression-atomic-with-paths\" }\n      ]\n    },\n    \"value-expression-switch-pattern-match-rule\": {\n      \"patterns\": [\n        { \"include\": \"#value-expression-switch-pattern-match-rule-lhs\" },\n        { \"include\": \"#value-expression-switch-pattern-match-rule-rhs\" }\n      ]\n    },\n    \"value-expression-switch-pattern-match-rule-lhs\": {\n      \"begin\": \"(?=\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))\",\n      \"end\": \"(?==>|[;\\\\)}])\",\n      \"patterns\": [{ \"include\": \"#pattern-guard\" }, { \"include\": \"#pattern\" }]\n    },\n    \"value-expression-switch-pattern-match-rule-rhs\": {\n      \"begin\": \"(=>)\",\n      \"end\": \"(?=}|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.less\" }\n      },\n      \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n    },\n    \"value-expression-try\": {\n      \"begin\": \"\\\\b(try)\\\\b\",\n      \"end\": \"(?<=})|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.trycatch\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#value-expression-try-head\" },\n        { \"include\": \"#value-expression-switch-body\" }\n      ]\n    },\n    \"value-expression-try-head\": {\n      \"begin\": \"(?<=try)\",\n      \"end\": \"(?<!try)(?={)|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        {\n          \"begin\": \"\\\\G[[:space:]]*+{\",\n          \"end\": \"}[[:space:]]*+\",\n          \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n        },\n        { \"include\": \"#value-expression-atomic-with-paths\" }\n      ]\n    },\n    \"value-expression-while\": {\n      \"begin\": \"\\\\b(while)\\\\b\",\n      \"end\": \"(?<=})|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.loop\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#value-expression-while-head\" },\n        { \"include\": \"#value-expression-block\" }\n      ]\n    },\n    \"value-expression-while-head\": {\n      \"begin\": \"(?<=while)[[:space:]]*+\",\n      \"end\": \"(?={)|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n      \"patterns\": [\n        { \"include\": \"#comment\" },\n        { \"include\": \"#value-expression-atomic-with-paths\" }\n      ]\n    },\n    \"value-expression-record-look\": {\n      \"begin\": \"(?=\\\\.\\\\.\\\\.|([[:upper:]][[:word:]]*\\\\.)*([[:lower:]][[:word:]]*)[[:space:]]*[,:}])\",\n      \"end\": \"(?=})\",\n      \"patterns\": [{ \"include\": \"#value-expression-record-item\" }]\n    }\n  }\n}\n"
  },
  {
    "path": "extensions/vlang-web/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 0x9ef\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 all\ncopies 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 THE\nSOFTWARE."
  },
  {
    "path": "extensions/vlang-web/README.md",
    "content": "# This extension is a fork from [vscode-vlang](https://github.com/vlang/vscode-vlang) for github1s.\n\n# At present only languages features is reserved\n\n# I have deleted some files and only reserved the necessary code\n\n# V language support for Visual Studio Code\n\n[![Version](https://vsmarketplacebadge.apphb.com/version/vlanguage.vscode-vlang.svg)](https://marketplace.visualstudio.com/items?itemName=vlanguage.vscode-vlang)\n[![Installs](https://vsmarketplacebadge.apphb.com/installs/vlanguage.vscode-vlang.svg)](https://marketplace.visualstudio.com/items?itemName=vlanguage.vscode-vlang)\n![GitHub Workflow Status](https://img.shields.io/github/workflow/status/vlang/vscode-vlang/CI)\n\nProvides [V language](https://vlang.io) support for Visual Studio Code.\n\n## Features\n\n- Syntax Highlighting\n\n## License\n\n[MIT](./LICENSE)\n"
  },
  {
    "path": "extensions/vlang-web/language-configuration.json",
    "content": "{\n  \"comments\": {\n    \"lineComment\": \"//\",\n    \"blockComment\": [\"/*\", \"*/\"]\n  },\n  \"folding\": {\n    \"markers\": {\n      \"start\": \"^\\\\s*//\\\\s*#?region\\\\b\",\n      \"end\": \"^\\\\s*//\\\\s*#?endregion\\\\b\"\n    }\n  },\n  \"brackets\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"]\n  ],\n  \"autoClosingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"\\\"\", \"\\\"\"],\n    [\"'\", \"'\"]\n  ],\n  \"surroundingPairs\": [\n    [\"{\", \"}\"],\n    [\"[\", \"]\"],\n    [\"(\", \")\"],\n    [\"\\\"\", \"\\\"\"],\n    [\"'\", \"'\"]\n  ]\n}"
  },
  {
    "path": "extensions/vlang-web/package.json",
    "content": "{\n  \"name\": \"vscode-vlang\",\n  \"displayName\": \"V\",\n  \"description\": \"V language support (syntax highlighting, formatter, linter, snippets) for Visual Studio Code.\",\n  \"publisher\": \"vlanguage\",\n  \"icon\": \"icons/icon.png\",\n  \"version\": \"0.1.7\",\n  \"license\": \"MIT\",\n  \"private\": true,\n  \"engines\": {\n    \"vscode\": \"^1.40.0\"\n  },\n  \"homepage\": \"https://vlang.io/\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vlang/vscode-vlang/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/vlang/vscode-vlang\"\n  },\n  \"keywords\": [\n    \"V\",\n    \"v\",\n    \"v language\",\n    \"vlang\",\n    \"extension\",\n    \"autocompletion\"\n  ],\n  \"categories\": [\n    \"Snippets\",\n    \"Programming Languages\"\n  ],\n  \"contributes\": {\n    \"snippets\": [\n      {\n        \"language\": \"v\",\n        \"path\": \"snippets/snippets.json\"\n      }\n    ],\n    \"languages\": [\n      {\n        \"id\": \"v\",\n        \"aliases\": [\n          \"V\"\n        ],\n        \"extensions\": [\n          \".v\",\n          \".vh\",\n          \".vsh\"\n        ],\n        \"configuration\": \"./language-configuration.json\"\n      }\n    ],\n    \"grammars\": [\n      {\n        \"language\": \"v\",\n        \"scopeName\": \"source.v\",\n        \"path\": \"./syntaxes/v.tmLanguage.json\"\n      }\n    ],\n    \"configurationDefaults\": {\n      \"[v]\": {\n        \"editor.insertSpaces\": false\n      }\n    },\n    \"breakpoints\": [\n      {\n        \"language\": \"v\"\n      }\n    ]\n  },\n  \"activationEvents\": [\n    \"onLanguage:v\"\n  ],\n  \"scripts\": {\n    \"compile\": \"echo done\",\n    \"watch\": \"echo done\"\n  }\n}\n"
  },
  {
    "path": "extensions/vlang-web/snippets/snippets.json",
    "content": "{\n  \"snippet.assert\": {\n    \"body\": [\"assert ${1:expression}\"],\n    \"description\": \"Code snippet for testing 'assert'\",\n    \"prefix\": \"as\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.break\": {\n    \"body\": [\"break$0\"],\n    \"description\": \"Code snippet for 'break'\",\n    \"prefix\": \"br\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.const\": {\n    \"body\": [\"const ${1:name} = ${2:value}\"],\n    \"description\": \"Code snippet for 'const'\",\n    \"prefix\": \"co\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.const.multiply\": {\n    \"body\": [\"const (\", \"\\t$0\", \")\"],\n    \"description\": \"Code snippet for multiply 'const'\",\n    \"prefix\": \"cons\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.continue\": {\n    \"body\": [\"continue$0\"],\n    \"description\": \"Code snippet for 'continue'\",\n    \"prefix\": \"con\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.defer\": {\n    \"body\": [\"defer ${1:function}($0)\"],\n    \"description\": \"Code snippet for 'defer' function\",\n    \"prefix\": \"def\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.else\": {\n    \"body\": [\"else {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'else' statement\",\n    \"prefix\": \"el\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.elseif\": {\n    \"body\": [\"else if ${1:expression} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'else if' statement\",\n    \"prefix\": \"elf\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.enum\": {\n    \"body\": [\"enum ${1:name} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'enum'\",\n    \"prefix\": \"en\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.flag\": {\n    \"body\": [\"#flag ${1:-flag}\"],\n    \"description\": \"Code snippet for '#flag'\",\n    \"prefix\": \"fl\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.fn.eprint\": {\n    \"body\": [\"eprint('${1:text}')\"],\n    \"description\": \"Code snippet for standart based function 'eprint'\",\n    \"prefix\": \"epr\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.fn.eprintln\": {\n    \"body\": [\"eprintln('${1:text}')\"],\n    \"description\": \"Code snippet for standart based function 'eprintln'\",\n    \"prefix\": \"eprl\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.fn.init\": {\n    \"body\": [\"fn init() {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'init' function\",\n    \"prefix\": \"finit\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.fn.main\": {\n    \"body\": [\"fn main() {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'main' function\",\n    \"prefix\": \"fmain\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.fn.print\": {\n    \"body\": [\"print('${1:text}')\"],\n    \"description\": \"Code snippet for standart based function 'print'\",\n    \"prefix\": \"pr\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.fn.println\": {\n    \"body\": [\"println('${1:text}')\"],\n    \"description\": \"Code snippet for standart based function 'println'\",\n    \"prefix\": \"prl\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.for\": {\n    \"body\": [\"for {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for pure infinity loop 'for'\",\n    \"prefix\": \"for\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.for.index\": {\n    \"body\": [\"for ${1:i} := 0; $1 < ${3:count}; $1++ {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for index loop 'for'\",\n    \"prefix\": \"for\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.foreach\": {\n    \"body\": [\"for ${1:variable} in ${2:array} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for foreach 'for'\",\n    \"prefix\": \"fore\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.foreach.index\": {\n    \"body\": [\"for ${1:_}, ${2:variable} in ${3:array} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for index based loop 'for'\",\n    \"prefix\": \"fore\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.function\": {\n    \"body\": [\"fn ${1:name}() {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for function 'fn'\",\n    \"prefix\": \"fn\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.go\": {\n    \"body\": [\"go ${1:function}($0)\"],\n    \"description\": \"Code snippet for concurrency 'go'\",\n    \"prefix\": \"go\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.goto\": {\n    \"body\": [\"goto ${1:label}\"],\n    \"description\": \"Code snippet for 'goto' label\",\n    \"prefix\": \"got\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.if\": {\n    \"body\": [\"if ${1:expression} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'if' statement\",\n    \"prefix\": \"if\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.if.compile\": {\n    \"body\": [\"\\\\$if ${1:expression} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for compile time 'if'\",\n    \"prefix\": \"$i\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.ifelse\": {\n    \"body\": [\"if ${1:expression} {\", \"\\t$0\", \"} else {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'if-else' statement\",\n    \"prefix\": \"ie\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.import\": {\n    \"body\": [\"import ${1:module}\"],\n    \"description\": \"Code snippet for 'import' module\",\n    \"prefix\": \"imp\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.include\": {\n    \"body\": [\"#include <${1:name}>\"],\n    \"description\": \"Code snippet for C '#include'\",\n    \"prefix\": \"inc\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.interface\": {\n    \"body\": [\"interface ${1:name} {$0}\"],\n    \"description\": \"Code snippet for 'interface'\",\n    \"prefix\": \"inte\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.map\": {\n    \"body\": [\"map[${1:key}]${2:value}{$0}\"],\n    \"description\": \"Code snippet for 'map'\",\n    \"prefix\": \"map\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.match\": {\n    \"body\": [\"match ${1:expression} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'match' statement\",\n    \"prefix\": \"ma\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.module\": {\n    \"body\": [\"module ${1:name}\"],\n    \"description\": \"Code snippet for 'module'\",\n    \"prefix\": \"mod\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.public.function\": {\n    \"body\": [\"pub fn ${1:name}() {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for public function 'pub fn'\",\n    \"prefix\": \"pub\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.return\": {\n    \"body\": [\"return ${1:value}\"],\n    \"description\": \"Code snippet for 'return'\",\n    \"prefix\": \"ret\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.struct\": {\n    \"body\": [\"struct ${1:Name} {\", \"\\t$0\", \"}\"],\n    \"description\": \"Code snippet for 'struct'\",\n    \"prefix\": \"stru\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type\": {\n    \"body\": [\"type ${1:name} ${2:type}\"],\n    \"description\": \"Code snippet for 'type' definition\",\n    \"prefix\": \"ty\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.bool\": {\n    \"body\": [\"bool\"],\n    \"description\": \"Code snippet for Boolean\",\n    \"prefix\": \"bool\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.byte\": {\n    \"body\": [\"byte\"],\n    \"description\": \"Code snippet for Unsigned 8-bit Integer\",\n    \"prefix\": \"byte\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.byteptr\": {\n    \"body\": [\"byteptr\"],\n    \"description\": \"Code snippet for Byte*\",\n    \"prefix\": \"bptr\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.f32\": {\n    \"body\": [\"f32\"],\n    \"description\": \"Code snippet for 32-bit FloatingPoint\",\n    \"prefix\": \"float\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.f64\": {\n    \"body\": [\"f64\"],\n    \"description\": \"Code snippet for 64-bit FloatingPoint\",\n    \"prefix\": \"float64\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.i8\": {\n    \"body\": [\"i8\"],\n    \"description\": \"Code snippet for Signed 8-bit Integer\",\n    \"prefix\": \"int8\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.i16\": {\n    \"body\": [\"i16\"],\n    \"description\": \"Code snippet for Signed 16-bit Integer\",\n    \"prefix\": \"int16\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.i64\": {\n    \"body\": [\"i64\"],\n    \"description\": \"Code snippet for Signed 64-bit Integer\",\n    \"prefix\": \"int64\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.int\": {\n    \"body\": [\"int\"],\n    \"description\": \"Code snippet for Signed 32-bit Integer\",\n    \"prefix\": \"int\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.rune\": {\n    \"body\": [\"rune\"],\n    \"description\": \"Code snippet for Represents a Unicode CodePoint\",\n    \"prefix\": \"rune\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.string\": {\n    \"body\": [\"string\"],\n    \"description\": \"Code snippet for String\",\n    \"prefix\": \"str\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.u16\": {\n    \"body\": [\"u16\"],\n    \"description\": \"Code snippet for Unsigned 16-bit Integer\",\n    \"prefix\": \"u16\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.u32\": {\n    \"body\": [\"u32\"],\n    \"description\": \"Code snippet for Unsigned 32-bit Integer\",\n    \"prefix\": \"u32\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.u64\": {\n    \"body\": [\"u64\"],\n    \"description\": \"Code snippet for Unsigned 64-bit Integer\",\n    \"prefix\": \"u64\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.voidptr\": {\n    \"body\": [\"voidptr\"],\n    \"description\": \"Code snippet for Void*\",\n    \"prefix\": \"vptr\",\n    \"scope\": \"v,vlang\"\n  },\n  \"snippet.type.charptr\": {\n    \"body\": [\"charptr\"],\n    \"description\": \"Code snippet for char*\",\n    \"prefix\": \"cptr\",\n    \"scope\": \"v,vlang\"\n  }\n}\n"
  },
  {
    "path": "extensions/vlang-web/syntaxes/v.tmLanguage.json",
    "content": "{\n  \"name\": \"V\",\n  \"scopeName\": \"source.v\",\n  \"fileTypes\": [\".v\", \".vh\", \".vsh\", \".vv\"],\n  \"patterns\": [\n    {\n      \"include\": \"#comments\"\n    },\n    {\n      \"include\": \"#as-is\"\n    },\n    {\n      \"include\": \"#attributes\"\n    },\n    {\n      \"include\": \"#assignment\"\n    },\n    {\n      \"include\": \"#module-decl\"\n    },\n    {\n      \"include\": \"#import-decl\"\n    },\n    {\n      \"include\": \"#include-decl\"\n    },\n    {\n      \"include\": \"#flag-decl\"\n    },\n    {\n      \"include\": \"#brackets\"\n    },\n    {\n      \"include\": \"#builtin-fix\"\n    },\n    {\n      \"include\": \"#escaped-fix\"\n    },\n    {\n      \"include\": \"#operators\"\n    },\n    {\n      \"include\": \"#function-limited-overload-decl\"\n    },\n    {\n      \"include\": \"#function-extend-decl\"\n    },\n    {\n      \"include\": \"#function-decl\"\n    },\n    {\n      \"include\": \"#function-exist\"\n    },\n    {\n      \"include\": \"#generic\"\n    },\n    {\n      \"include\": \"#constants\"\n    },\n    {\n      \"include\": \"#type\"\n    },\n    {\n      \"include\": \"#enum\"\n    },\n    {\n      \"include\": \"#interface\"\n    },\n    {\n      \"include\": \"#struct\"\n    },\n    {\n      \"include\": \"#keywords\"\n    },\n    {\n      \"include\": \"#storage\"\n    },\n    {\n      \"include\": \"#numbers\"\n    },\n    {\n      \"include\": \"#strings\"\n    },\n    {\n      \"include\": \"#types\"\n    }\n  ],\n  \"repository\": {\n    \"as-is\": {\n      \"begin\": \"\\\\s+(as|is)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.$1.v\"\n        }\n      },\n      \"end\": \"([\\\\w.]*)\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"entity.name.alias.v\"\n        }\n      }\n    },\n    \"assignment\": {\n      \"name\": \"meta.definition.variable.v\",\n      \"match\": \"([\\\\w.]+)\\\\s*((?:\\\\:|\\\\+|\\\\-|\\\\*|\\\\/|\\\\%|\\\\&|\\\\||\\\\^)?=)\\\\s*(?=.+)\",\n      \"captures\": {\n        \"1\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"match\": \"\\\\w+\",\n              \"name\": \"variable.assignment.other.v\"\n            }\n          ]\n        },\n        \"2\": {\n          \"patterns\": [\n            {\n              \"include\": \"#operators\"\n            }\n          ]\n        }\n      }\n    },\n    \"attributes\": {\n      \"name\": \"meta.definition.attribute.v\",\n      \"match\": \"^\\\\s*((\\\\[)(deprecated|unsafe_fn|typedef|live|inline|flag|ref_only|windows_stdcall|direct_array_access)(\\\\]))\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"meta.function.attribute.v\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.definition.begin.bracket.square.v\"\n        },\n        \"3\": {\n          \"name\": \"storage.modifier.attribute.v\"\n        },\n        \"4\": {\n          \"name\": \"punctuation.definition.end.bracket.square.v\"\n        }\n      }\n    },\n    \"module-decl\": {\n      \"name\": \"meta.module.v\",\n      \"begin\": \"^\\\\s*(module)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.module.v\"\n        }\n      },\n      \"end\": \"([\\\\w.]+)\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"entity.name.module.v\"\n        }\n      }\n    },\n    \"import-decl\": {\n      \"name\": \"meta.import.v\",\n      \"begin\": \"^\\\\s*(import)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.import.v\"\n        }\n      },\n      \"end\": \"([\\\\w.]+)\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"entity.name.import.v\"\n        }\n      }\n    },\n    \"include-decl\": {\n      \"patterns\": [\n        {\n          \"name\": \"meta.include.v\",\n          \"begin\": \"^\\\\s*(#include)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"keyword.include.v\"\n            }\n          },\n          \"end\": \"\\\\s+([\\\\<\\\"]\\\\s*(.*)[\\\\>\\\"])\",\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"string.quoted.double.v\"\n            }\n          }\n        }\n      ]\n    },\n    \"flag-decl\": {\n      \"name\": \"meta.flag.v\",\n      \"begin\": \"^\\\\s*(#flag)\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"keyword.flag.v\"\n        }\n      },\n      \"end\": \"\\\\s+(.*?)$\",\n      \"endCaptures\": {\n        \"1\": {\n          \"name\": \"string.quoted.single.v\"\n        }\n      }\n    },\n    \"brackets\": {\n      \"patterns\": [\n        {\n          \"begin\": \"{\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.bracket.curly.begin.v\"\n            }\n          },\n          \"end\": \"}\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.bracket.curly.end.v\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"include\": \"$self\"\n            }\n          ]\n        },\n        {\n          \"begin\": \"\\\\(\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.bracket.round.begin.v\"\n            }\n          },\n          \"end\": \"\\\\)\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.bracket.round.end.v\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"include\": \"$self\"\n            }\n          ]\n        },\n        {\n          \"begin\": \"\\\\[\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.bracket.square.begin.v\"\n            }\n          },\n          \"end\": \"\\\\]\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.bracket.square.end.v\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"include\": \"$self\"\n            }\n          ]\n        }\n      ]\n    },\n    \"builtin-fix\": {\n      \"patterns\": [\n        {\n          \"patterns\": [\n            {\n              \"name\": \"storage.modifier.v\",\n              \"match\": \"(const)(?=\\\\s*\\\\()\"\n            },\n            {\n              \"name\": \"keyword.$1.v\",\n              \"match\": \"\\\\b(fn|type|enum|struct|union|interface|map|assert|sizeof)\\\\b(?=\\\\s*\\\\()\"\n            }\n          ]\n        },\n        {\n          \"patterns\": [\n            {\n              \"name\": \"keyword.control.v\",\n              \"match\": \"(\\\\$if|\\\\$else)(?=\\\\s*\\\\()\"\n            },\n            {\n              \"name\": \"keyword.control.v\",\n              \"match\": \"\\\\b(as|in|is|or|break|continue|default|unsafe|match|if|else|for|go|goto|defer|return|shared|select|rlock|lock|atomic|asm)\\\\b(?=\\\\s*\\\\()\"\n            }\n          ]\n        },\n        {\n          \"patterns\": [\n            {\n              \"match\": \"(i?(?:8|16|nt|64|128)|u?(?:16|32|64|128)|f?(?:32|64))(?=\\\\s*\\\\()\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"storage.type.numeric.v\"\n                }\n              },\n              \"name\": \"meta.expr.numeric.cast.v\"\n            },\n            {\n              \"match\": \"(bool|byte|byteptr|charptr|voidptr|string|ustring|rune)(?=\\\\s*\\\\()\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"storage.type.$1.v\"\n                }\n              },\n              \"name\": \"meta.expr.bool.cast.v\"\n            }\n          ]\n        }\n      ]\n    },\n    \"escaped-fix\": {\n      \"name\": \"meta.escaped.keyword.v\",\n      \"match\": \"((?:@)(?:mut|pub|fn|unsafe|module|import|as|const|map|assert|sizeof|type|struct|interface|enum|in|is|or|match|if|else|for|go|goto|defer|return|shared|select|rlock|lock|atomic|asm|i?(?:8|16|nt|64|128)|u?(?:16|32|64|128)|f?(?:32|64)|bool|byte|byteptr|charptr|voidptr|string|ustring|rune))\",\n      \"captures\": {\n        \"0\": {\n          \"name\": \"keyword.other.escaped.v\"\n        }\n      }\n    },\n    \"comments\": {\n      \"patterns\": [\n        {\n          \"name\": \"comment.block.documentation.v\",\n          \"begin\": \"/\\\\*\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.comment.begin.v\"\n            }\n          },\n          \"end\": \"\\\\*/\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.comment.end.v\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"include\": \"#comments\"\n            }\n          ]\n        },\n        {\n          \"name\": \"comment.line.double-slash.v\",\n          \"begin\": \"//\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.comment.begin.v\"\n            }\n          },\n          \"end\": \"$\"\n        }\n      ]\n    },\n    \"constants\": {\n      \"name\": \"constant.language.v\",\n      \"match\": \"\\\\b(true|false|none)\\\\b\"\n    },\n    \"generic\": {\n      \"patterns\": [\n        {\n          \"name\": \"meta.definition.generic.v\",\n          \"match\": \"(?<=[\\\\w\\\\s+])(\\\\<)(\\\\w+)(\\\\>)\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"punctuation.definition.bracket.angle.begin.v\"\n            },\n            \"2\": {\n              \"patterns\": [\n                {\n                  \"include\": \"#illegal-name\"\n                },\n                {\n                  \"match\": \"\\\\w+\",\n                  \"name\": \"entity.name.generic.v\"\n                }\n              ]\n            },\n            \"3\": {\n              \"name\": \"punctuation.definition.bracket.angle.end.v\"\n            }\n          }\n        }\n      ]\n    },\n    \"function-decl\": {\n      \"name\": \"meta.definition.function.v\",\n      \"begin\": \"^\\\\s*(pub)?\\\\s*(fn)\\\\s+\",\n      \"beginCaptures\": {\n        \"1\": {\n          \"name\": \"storage.modifier.v\"\n        },\n        \"2\": {\n          \"name\": \"keyword.function.v\"\n        }\n      },\n      \"end\": \"(?:(?:C\\\\.)?)(\\\\w+)\\\\s*((?<=[\\\\w\\\\s+])(\\\\<)(\\\\w+)(\\\\>))?\",\n      \"endCaptures\": {\n        \"1\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"match\": \"\\\\w+\",\n              \"name\": \"entity.name.function.v\"\n            }\n          ]\n        },\n        \"2\": {\n          \"patterns\": [\n            {\n              \"include\": \"#generic\"\n            }\n          ]\n        }\n      }\n    },\n    \"function-extend-decl\": {\n      \"name\": \"meta.definition.function.v\",\n      \"match\": \"^\\\\s*(pub)?\\\\s*(fn)\\\\s*(\\\\()([^\\\\)]*)(\\\\))\\\\s*(?:(?:C\\\\.)?)(\\\\w+)\\\\s*((?<=[\\\\w\\\\s+])(\\\\<)(\\\\w+)(\\\\>))?\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"storage.modifier.v\"\n        },\n        \"2\": {\n          \"name\": \"keyword.function.v\"\n        },\n        \"3\": {\n          \"name\": \"punctuation.definition.bracket.round.begin.v\"\n        },\n        \"4\": {\n          \"patterns\": [\n            {\n              \"include\": \"#brackets\"\n            },\n            {\n              \"include\": \"#storage\"\n            },\n            {\n              \"include\": \"#generic\"\n            },\n            {\n              \"include\": \"#types\"\n            },\n            {\n              \"include\": \"#punctuation\"\n            }\n          ]\n        },\n        \"5\": {\n          \"name\": \"punctuation.definition.bracket.round.end.v\"\n        },\n        \"6\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"match\": \"\\\\w+\",\n              \"name\": \"entity.name.function.v\"\n            }\n          ]\n        },\n        \"7\": {\n          \"patterns\": [\n            {\n              \"include\": \"#generic\"\n            }\n          ]\n        }\n      }\n    },\n    \"function-limited-overload-decl\": {\n      \"name\": \"meta.definition.function.v\",\n      \"match\": \"^\\\\s*(pub)?\\\\s*(fn)\\\\s*(\\\\()([^\\\\)]*)(\\\\))\\\\s*([\\\\+\\\\-\\\\*\\\\/])?\\\\s*(\\\\()([^\\\\)]*)(\\\\))\\\\s*(?:(?:C\\\\.)?)(\\\\w+)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"storage.modifier.v\"\n        },\n        \"2\": {\n          \"name\": \"keyword.function.v\"\n        },\n        \"3\": {\n          \"name\": \"punctuation.definition.bracket.round.begin.v\"\n        },\n        \"4\": {\n          \"patterns\": [\n            {\n              \"include\": \"#brackets\"\n            },\n            {\n              \"include\": \"#storage\"\n            },\n            {\n              \"include\": \"#generic\"\n            },\n            {\n              \"include\": \"#types\"\n            },\n            {\n              \"include\": \"#punctuation\"\n            }\n          ]\n        },\n        \"5\": {\n          \"name\": \"punctuation.definition.bracket.round.end.v\"\n        },\n        \"6\": {\n          \"patterns\": [\n            {\n              \"include\": \"#operators\"\n            }\n          ]\n        },\n        \"7\": {\n          \"name\": \"punctuation.definition.bracket.round.begin.v\"\n        },\n        \"8\": {\n          \"patterns\": [\n            {\n              \"include\": \"#brackets\"\n            },\n            {\n              \"include\": \"#storage\"\n            },\n            {\n              \"include\": \"#generic\"\n            },\n            {\n              \"include\": \"#types\"\n            },\n            {\n              \"include\": \"#punctuation\"\n            }\n          ]\n        },\n        \"9\": {\n          \"name\": \"punctuation.definition.bracket.round.end.v\"\n        },\n        \"10\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"match\": \"\\\\w+\",\n              \"name\": \"entity.name.function.v\"\n            }\n          ]\n        }\n      }\n    },\n    \"function-exist\": {\n      \"name\": \"meta.support.function.v\",\n      \"match\": \"(\\\\w+)((?<=[\\\\w\\\\s+])(\\\\<)(\\\\w+)(\\\\>))?(?=\\\\s*\\\\()\",\n      \"captures\": {\n        \"0\": {\n          \"name\": \"meta.function.call.v\"\n        },\n        \"1\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"match\": \"\\\\w+\",\n              \"name\": \"entity.name.function.v\"\n            }\n          ]\n        },\n        \"2\": {\n          \"patterns\": [\n            {\n              \"include\": \"#generic\"\n            }\n          ]\n        }\n      }\n    },\n    \"type\": {\n      \"name\": \"meta.definition.type.v\",\n      \"match\": \"^\\\\s*(?:(pub)?\\\\s+)?(type)\\\\s+(\\\\w*)\\\\s+(?:\\\\w+\\\\.+)?(\\\\w*)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"storage.modifier.$1.v\"\n        },\n        \"2\": {\n          \"name\": \"storage.type.type.v\"\n        },\n        \"3\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"include\": \"#types\"\n            },\n            {\n              \"name\": \"entity.name.type.v\",\n              \"match\": \"\\\\w+\"\n            }\n          ]\n        },\n        \"4\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"include\": \"#types\"\n            },\n            {\n              \"name\": \"entity.name.type.v\",\n              \"match\": \"\\\\w+\"\n            }\n          ]\n        }\n      }\n    },\n    \"enum\": {\n      \"name\": \"meta.definition.enum.v\",\n      \"match\": \"^\\\\s*(?:(pub)?\\\\s+)?(enum)\\\\s+(?:\\\\w+\\\\.)?(\\\\w*)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"storage.modifier.$1.v\"\n        },\n        \"2\": {\n          \"name\": \"storage.type.enum.v\"\n        },\n        \"3\": {\n          \"name\": \"entity.name.enum.v\"\n        }\n      }\n    },\n    \"interface\": {\n      \"name\": \"meta.definition.interface.v\",\n      \"match\": \"^\\\\s*(?:(pub)?\\\\s+)?(interface)\\\\s+(\\\\w*)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"storage.modifier.$1.v\"\n        },\n        \"2\": {\n          \"name\": \"keyword.interface.v\"\n        },\n        \"3\": {\n          \"patterns\": [\n            {\n              \"include\": \"#illegal-name\"\n            },\n            {\n              \"name\": \"entity.name.interface.v\",\n              \"match\": \"\\\\w+\"\n            }\n          ]\n        }\n      }\n    },\n    \"struct\": {\n      \"patterns\": [\n        {\n          \"name\": \"meta.definition.struct.v\",\n          \"begin\": \"^\\\\s*(?:(mut|pub(?:\\\\s+mut)?|__global)\\\\s+)?(struct|union)\\\\s+([\\\\w.]+)\\\\s*|({)\",\n          \"beginCaptures\": {\n            \"1\": {\n              \"name\": \"storage.modifier.$1.v\"\n            },\n            \"2\": {\n              \"name\": \"storage.type.struct.v\"\n            },\n            \"3\": {\n              \"name\": \"entity.name.struct.v\"\n            },\n            \"4\": {\n              \"name\": \"punctuation.definition.bracket.curly.begin.v\"\n            }\n          },\n          \"end\": \"\\\\s*|(})\",\n          \"endCaptures\": {\n            \"1\": {\n              \"name\": \"punctuation.definition.bracket.curly.end.v\"\n            }\n          },\n          \"patterns\": [\n            {\n              \"include\": \"#struct-access-modifier\"\n            },\n            {\n              \"match\": \"\\\\b(\\\\w+)\\\\s+([\\\\w\\\\[\\\\]\\\\*&.]+)(?:\\\\s*(=)\\\\s*((?:.(?=$|//|/\\\\*))*+))?\",\n              \"captures\": {\n                \"1\": {\n                  \"name\": \"variable.other.property.v\"\n                },\n                \"2\": {\n                  \"patterns\": [\n                    {\n                      \"include\": \"#numbers\"\n                    },\n                    {\n                      \"include\": \"#brackets\"\n                    },\n                    {\n                      \"include\": \"#types\"\n                    },\n                    {\n                      \"match\": \"\\\\w+\",\n                      \"name\": \"storage.type.other.v\"\n                    }\n                  ]\n                },\n                \"3\": {\n                  \"name\": \"keyword.operator.assignment.v\"\n                },\n                \"4\": {\n                  \"patterns\": [\n                    {\n                      \"include\": \"$self\"\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"include\": \"#types\"\n            },\n            {\n              \"include\": \"$self\"\n            }\n          ]\n        },\n        {\n          \"name\": \"meta.definition.struct.v\",\n          \"match\": \"^\\\\s*(?:(mut|pub(?:\\\\s+mut)?|__global))\\\\s+?(struct)\\\\s+(?:\\\\s+([\\\\w.]+))?\",\n          \"captures\": {\n            \"1\": {\n              \"name\": \"storage.modifier.$1.v\"\n            },\n            \"2\": {\n              \"name\": \"storage.type.struct.v\"\n            },\n            \"3\": {\n              \"name\": \"entity.name.struct.v\"\n            }\n          }\n        }\n      ]\n    },\n    \"struct-access-modifier\": {\n      \"match\": \"(?<=\\\\s|^)(mut|pub(?:\\\\s+mut)?|__global)(:|\\\\b)\",\n      \"captures\": {\n        \"1\": {\n          \"name\": \"storage.modifier.$1.v\"\n        },\n        \"2\": {\n          \"name\": \"punctuation.separator.struct.key-value.v\"\n        }\n      }\n    },\n    \"punctuation\": {\n      \"patterns\": [\n        {\n          \"name\": \"punctuation.delimiter.period.dot.v\",\n          \"match\": \"\\\\.\"\n        },\n        {\n          \"name\": \"punctuation.delimiter.comma.v\",\n          \"match\": \",\"\n        },\n        {\n          \"name\": \"punctuation.separator.key-value.colon.v\",\n          \"match\": \":\"\n        },\n        {\n          \"name\": \"punctuation.definition.other.semicolon.v\",\n          \"match\": \";\"\n        },\n        {\n          \"name\": \"punctuation.definition.other.questionmark.v\",\n          \"match\": \"\\\\?\"\n        }\n      ]\n    },\n    \"keywords\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.control.v\",\n          \"match\": \"(\\\\$if|\\\\$else)\"\n        },\n        {\n          \"name\": \"keyword.control.v\",\n          \"match\": \"\\\\b(as|it|is|in|or|break|continue|default|unsafe|match|if|else|for|go|goto|defer|return|shared|select|rlock|lock|atomic|asm)\\\\b\"\n        },\n        {\n          \"name\": \"keyword.$1.v\",\n          \"match\": \"\\\\b(fn|type|enum|struct|interface|map|assert|sizeof)\\\\b\"\n        }\n      ]\n    },\n    \"storage\": {\n      \"name\": \"storage.modifier.v\",\n      \"match\": \"\\\\b(const|mut|pub)\\\\b\"\n    },\n    \"types\": {\n      \"patterns\": [\n        {\n          \"name\": \"storage.type.numeric.v\",\n          \"match\": \"\\\\b(i(8|16|nt|64|128)|u(8|16|32|64|128)|f(32|64))\\\\b\"\n        },\n        {\n          \"name\": \"storage.type.$1.v\",\n          \"match\": \"\\\\b(bool|byte|byteptr|charptr|voidptr|string|ustring|rune)\\\\b\"\n        }\n      ]\n    },\n    \"operators\": {\n      \"patterns\": [\n        {\n          \"name\": \"keyword.operator.arithmethic.v\",\n          \"match\": \"(\\\\+|\\\\-|\\\\*|\\\\/|\\\\%|\\\\+\\\\+|\\\\-\\\\-)\"\n        },\n        {\n          \"name\": \"keyword.operator.assignment.v\",\n          \"match\": \"(\\\\:\\\\=|\\\\=|\\\\+\\\\=|\\\\-\\\\=|\\\\*\\\\=|\\\\/\\\\=|\\\\%\\\\=|\\\\&\\\\=|\\\\|\\\\=|\\\\^\\\\=|\\\\&\\\\&\\\\=|\\\\|\\\\|\\\\=|\\\\>\\\\>\\\\=|\\\\<\\\\<\\\\=)\"\n        },\n        {\n          \"name\": \"keyword.operator.bitwise.v\",\n          \"match\": \"(\\\\&|\\\\||\\\\^|<(?!<)|>(?!>))\"\n        },\n        {\n          \"name\": \"keyword.operator.logical.v\",\n          \"match\": \"(\\\\&\\\\&|\\\\|\\\\||\\\\!)\"\n        },\n        {\n          \"name\": \"keyword.operator.relation.v\",\n          \"match\": \"(\\\\=\\\\=|\\\\!\\\\=|\\\\>|\\\\<|\\\\>\\\\=|\\\\<\\\\=)\"\n        }\n      ]\n    },\n    \"numbers\": {\n      \"patterns\": [\n        {\n          \"name\": \"constant.numeric.float.v\",\n          \"match\": \"(?:(?:[-]?)(?:[0-9e]*)(?:[.]){1}(?:[0-9]+))\"\n        },\n        {\n          \"name\": \"constant.numeric.exponental.v\",\n          \"match\": \"[-+]?[0-9]*\\\\.?[0-9]+(?:[eE][-+]?[0-9]+)\"\n        },\n        {\n          \"name\": \"constant.numeric.binary.v\",\n          \"match\": \"\\\\b(?:0[b])(?:[0-1]+)\"\n        },\n        {\n          \"name\": \"constant.numeric.octal.v\",\n          \"match\": \"\\\\b(?:0[o])(?:[0-7]+)\"\n        },\n        {\n          \"name\": \"constant.numeric.hex.v\",\n          \"match\": \"\\\\b(?:0[x])(?:[0-9a-fA-F]+)\"\n        },\n        {\n          \"name\": \"constant.numeric.integer.v\",\n          \"match\": \"\\\\b(?:[-]?)(?:[0-9]+)\"\n        }\n      ]\n    },\n    \"strings\": {\n      \"patterns\": [\n        {\n          \"begin\": \"`\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.raw.begin.v\"\n            }\n          },\n          \"end\": \"`\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.raw.end.v\"\n            }\n          },\n          \"name\": \"string.quoted.raw.v\",\n          \"patterns\": [\n            {\n              \"include\": \"#string-escaped-char\"\n            },\n            {\n              \"include\": \"#string-interpolation\"\n            },\n            {\n              \"include\": \"#string-placeholder\"\n            }\n          ]\n        },\n        {\n          \"begin\": \"'\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.single.begin.v\"\n            }\n          },\n          \"end\": \"'\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.single.end.v\"\n            }\n          },\n          \"name\": \"string.quoted.single.v\",\n          \"patterns\": [\n            {\n              \"include\": \"#string-escaped-char\"\n            },\n            {\n              \"include\": \"#string-interpolation\"\n            },\n            {\n              \"include\": \"#string-placeholder\"\n            }\n          ]\n        },\n        {\n          \"begin\": \"\\\"\",\n          \"beginCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.double.begin.v\"\n            }\n          },\n          \"end\": \"\\\"\",\n          \"endCaptures\": {\n            \"0\": {\n              \"name\": \"punctuation.definition.string.double.end.v\"\n            }\n          },\n          \"name\": \"string.quoted.double.v\",\n          \"patterns\": [\n            {\n              \"include\": \"#string-escaped-char\"\n            },\n            {\n              \"include\": \"#string-interpolation\"\n            },\n            {\n              \"include\": \"#string-placeholder\"\n            }\n          ]\n        }\n      ]\n    },\n    \"string-escaped-char\": {\n      \"patterns\": [\n        {\n          \"name\": \"constant.character.escape.v\",\n          \"match\": \"\\\\\\\\([0-7]{3}|[\\\\$abfnrtv\\\\\\\\'\\\"]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})\"\n        },\n        {\n          \"name\": \"invalid.illegal.unknown-escape.v\",\n          \"match\": \"\\\\\\\\[^0-7\\\\$xuUabfnrtv\\\\'\\\"]\"\n        }\n      ]\n    },\n    \"string-interpolation\": {\n      \"name\": \"meta.string.interpolation.v\",\n      \"match\": \"(\\\\$([\\\\w.]+|\\\\{.*?\\\\}))\",\n      \"captures\": {\n        \"1\": {\n          \"patterns\": [\n            {\n              \"name\": \"invalid.illegal.v\",\n              \"match\": \"\\\\$\\\\d[\\\\.\\\\w]+\"\n            },\n            {\n              \"name\": \"variable.other.interpolated.v\",\n              \"match\": \"\\\\$([\\\\.\\\\w]+|\\\\{.*?\\\\})\"\n            }\n          ]\n        }\n      }\n    },\n    \"string-placeholder\": {\n      \"match\": \"%(\\\\[\\\\d+\\\\])?([\\\\+#\\\\-0\\\\x20]{,2}((\\\\d+|\\\\*)?(\\\\.?(\\\\d+|\\\\*|(\\\\[\\\\d+\\\\])\\\\*?)?(\\\\[\\\\d+\\\\])?)?))?[vT%tbcdoqxXUbeEfFgGsp]\",\n      \"name\": \"constant.other.placeholder.v\"\n    },\n    \"illegal-name\": {\n      \"match\": \"\\\\d\\\\w+\",\n      \"name\": \"invalid.illegal.v\"\n    }\n  }\n}\n"
  },
  {
    "path": "functions/api/github-auth-callback.ts",
    "content": "/**\n * @file github auth callback\n * @author netcon\n */\n\nconst createResponseHtml = (text: string, script: string) => `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<title>Connect to GitHub</title>\n</head>\n<body>\n\t<h1>${text}</h1>\n\t<script>${script}</script>\n</body>\n</html>\n`;\n\n// return the data to the opener window by postMessage API,\n// and close current window if successfully connected\nconst createAuthorizeResultHtml = (data: Record<any, any>, origins: string) => {\n\tconst errorText = 'Failed! You can close this window and retry.';\n\tconst successText = 'Connected! You can now close this window.';\n\tconst resultStr = `{ type: 'authorizing', payload: ${JSON.stringify(data)} }`;\n\tconst script = `\n\t'${origins}'.split(',').forEach(function(allowedOrigin) {\n\t\twindow.opener.postMessage(${resultStr}, allowedOrigin);\n\t});\n\t${data.error ? '' : 'setTimeout(() => window.close(), 50);'}`;\n\treturn createResponseHtml(data.error ? errorText : successText, script);\n};\n\nconst MISSING_CODE_ERROR = {\n\terror: 'request_invalid',\n\terror_description: 'Missing code',\n};\nconst UNKNOWN_ERROR = {\n\terror: 'internal_error',\n\terror_description: 'Unknown error',\n};\n\nexport const onRequest: PagesFunction<{\n\tGITHUB_OAUTH_ID: string;\n\tGITHUB_OAUTH_SECRET: string;\n\tGITHUB1S_ALLOWED_ORIGINS: string;\n}> = async ({ request, env }) => {\n\tconst code = new URL(request.url).searchParams.get('code');\n\n\tconst createResponse = (status, data) => {\n\t\tconst body = createAuthorizeResultHtml(data, env.GITHUB1S_ALLOWED_ORIGINS);\n\t\treturn new Response(body, { status, headers: { 'content-type': 'text/html' } });\n\t};\n\n\tif (!code) {\n\t\treturn createResponse(401, MISSING_CODE_ERROR);\n\t}\n\n\ttry {\n\t\t// https://docs.github.com/en/developers/apps/authorizing-oauth-apps#2-users-are-redirected-back-to-your-site-by-github\n\t\tconst response = await fetch('https://github.com/login/oauth/access_token', {\n\t\t\tmethod: 'POST',\n\t\t\tbody: JSON.stringify({ client_id: env.GITHUB_OAUTH_ID, client_secret: env.GITHUB_OAUTH_SECRET, code }),\n\t\t\theaders: { accept: 'application/json', 'content-type': 'application/json' },\n\t\t});\n\t\treturn response.json().then((result) => createResponse(response.status, result));\n\t} catch (e) {\n\t\treturn createResponse(500, UNKNOWN_ERROR);\n\t}\n};\n"
  },
  {
    "path": "functions/api/gitlab-auth-callback.ts",
    "content": "/**\n * @file gitlab auth callback\n * @author netcon\n */\n\nconst AUTH_REDIRECT_URI = 'https://auth.gitlab1s.com/api/gitlab-auth-callback';\n\nconst createResponseHtml = (text: string, script: string) => `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<title>Connect to GitLab</title>\n</head>\n<body>\n\t<h1>${text}</h1>\n\t<script>${script}</script>\n</body>\n</html>\n`;\n\n// return the data to the opener window by postMessage API,\n// and close current window if successfully connected\nconst createAuthorizeResultHtml = (data: Record<any, any>, origins: string) => {\n\tconst errorText = 'Failed! You can close this window and retry.';\n\tconst successText = 'Connected! You can now close this window.';\n\tconst resultStr = `{ type: 'authorizing', payload: ${JSON.stringify(data)} }`;\n\tconst script = `\n\t'${origins}'.split(',').forEach(function(allowedOrigin) {\n\t\twindow.opener.postMessage(${resultStr}, allowedOrigin);\n\t});\n\t${data.error ? '' : 'setTimeout(() => window.close(), 50);'}`;\n\treturn createResponseHtml(data.error ? errorText : successText, script);\n};\n\nconst MISSING_CODE_ERROR = {\n\terror: 'request_invalid',\n\terror_description: 'Missing code',\n};\nconst UNKNOWN_ERROR = {\n\terror: 'internal_error',\n\terror_description: 'Unknown error',\n};\n\nexport const onRequest: PagesFunction<{\n\tGITLAB_OAUTH_ID: string;\n\tGITLAB_OAUTH_SECRET: string;\n\tGITLAB1S_ALLOWED_ORIGINS: string;\n}> = async ({ request, env }) => {\n\tconst code = new URL(request.url).searchParams.get('code');\n\n\tconst createResponse = (status, data) => {\n\t\tconst body = createAuthorizeResultHtml(data, env.GITLAB1S_ALLOWED_ORIGINS);\n\t\treturn new Response(body, { status, headers: { 'content-type': 'text/html' } });\n\t};\n\n\tif (!code) {\n\t\treturn createResponse(401, MISSING_CODE_ERROR);\n\t}\n\n\ttry {\n\t\t// https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow\n\t\tconst response = await fetch('https://gitlab.com/oauth/token', {\n\t\t\tmethod: 'POST',\n\t\t\tbody: JSON.stringify({\n\t\t\t\tcode,\n\t\t\t\tclient_id: env.GITLAB_OAUTH_ID,\n\t\t\t\tclient_secret: env.GITLAB_OAUTH_SECRET,\n\t\t\t\tredirect_uri: AUTH_REDIRECT_URI,\n\t\t\t\tgrant_type: 'authorization_code',\n\t\t\t}),\n\t\t\theaders: { accept: 'application/json', 'content-type': 'application/json' },\n\t\t});\n\t\treturn response.json().then((result) => createResponse(response.status, result));\n\t} catch (e) {\n\t\treturn createResponse(500, UNKNOWN_ERROR);\n\t}\n};\n"
  },
  {
    "path": "functions/tsconfig.json",
    "content": "{\n  \"include\": [\"**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"lib\": [\"esnext\"],\n    \"types\": [\"@cloudflare/workers-types\"]\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"github1s\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"node scripts/build.js\",\n    \"watch\": \"rm -rf dist && run-p watch:*\",\n    \"watch:dev-server\": \"webpack serve --mode=development\",\n    \"watch:github1s-extension\": \"cd extensions/github1s && npm run watch\",\n    \"watch-with-vscode\": \"DEV_VSCODE=true npm run watch\",\n    \"link\": \"node scripts/link.js\",\n    \"format\": \"prettier --write .\",\n    \"eslint\": \"eslint --fix\",\n    \"test:ci\": \"start-test watch:dev-server 8080 test\",\n    \"test\": \"cd tests && npm install && npx playwright install && npm run test\",\n    \"postinstall\": \"husky install && node scripts/postinstall.js\"\n  },\n  \"lint-staged\": {\n    \"*.{js,ts}\": [\n      \"prettier --write\",\n      \"eslint --fix\"\n    ],\n    \"*.{json.css,md,yml,yaml}\": [\n      \"prettier --write\"\n    ]\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"@cloudflare/workers-types\": \"^4.20250109.0\",\n    \"@github1s/vscode-web\": \"^0.27.0\",\n    \"chokidar\": \"^4.0.3\",\n    \"clean-css\": \"^5.3.3\",\n    \"copy-webpack-plugin\": \"^12.0.2\",\n    \"css-loader\": \"^7.1.2\",\n    \"eslint\": \"^9.17.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-plugin-jsdoc\": \"^50.6.1\",\n    \"eslint-plugin-prettier\": \"^5.2.1\",\n    \"file-loader\": \"^6.2.0\",\n    \"fs-extra\": \"^11.2.0\",\n    \"glob\": \"^11.0.1\",\n    \"html-webpack-plugin\": \"^5.6.3\",\n    \"husky\": \"^9.1.7\",\n    \"lint-staged\": \"^15.3.0\",\n    \"npm-run-all\": \"^4.1.5\",\n    \"prettier\": \"^3.4.2\",\n    \"start-server-and-test\": \"^2.0.9\",\n    \"style-loader\": \"^4.0.0\",\n    \"ts-loader\": \"^9.5.1\",\n    \"typescript\": \"^5.7.3\",\n    \"typescript-eslint\": \"^8.19.1\",\n    \"uglify-js\": \"^3.19.3\",\n    \"webpack\": \"^5.97.1\",\n    \"webpack-cli\": \"^6.0.1\",\n    \"webpack-dev-server\": \"^5.2.0\"\n  }\n}\n"
  },
  {
    "path": "public/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no\" />\n\t\t<title>GitHub1s</title>\n\t\t<link rel=\"icon\" media=\"(prefers-color-scheme:light)\" href=\"/favicon-light.svg\" type=\"image/svg+xml\" />\n\t\t<link rel=\"icon\" media=\"(prefers-color-scheme:dark)\" href=\"/favicon-dark.svg\" type=\"image/svg+xml\" />\n\t\t<link rel=\"manifest\" href=\"/manifest.json\" />\n\t\t<style><%= spinnerStyle %></style>\n\t\t<script><%= pageTitleScript %></script>\n\t\t<script><%= globalScript %></script>\n\t</head>\n\t<body aria-label=\"\">\n\t\t<noscript title=\"No JavaScript Support\">\n\t\t\t<h1>You need to enable JavaScript to run this app.</h1>\n\t\t</noscript>\n\t\t<div id=\"load-spinner\" aria-label=\"loading\">\n\t\t\t<div class=\"lds-grid\">\n\t\t\t\t<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
  },
  {
    "path": "public/manifest.json",
    "content": "{\n  \"name\": \"GitHub1S\",\n  \"short_name\": \"GitHub1s\",\n  \"start_url\": \"/\",\n  \"lang\": \"en-US\",\n  \"display\": \"standalone\"\n}"
  },
  {
    "path": "public/page-title.js",
    "content": "(function () {\n\tif (window.location.hostname.match(/\\.?gitlab1s\\.com$/i)) {\n\t\twindow.document.title = 'GitLab1s';\n\t} else if (window.location.hostname.match(/\\.?bitbucket1s\\.org$/i)) {\n\t\twindow.document.title = 'Bitbucket1s';\n\t} else if (window.location.hostname.match(/\\.?npmjs1s\\.com$/i)) {\n\t\twindow.document.title = 'npm1s';\n\t}\n})();\n"
  },
  {
    "path": "public/robots.txt",
    "content": "User-agent: *\nAllow: /\n"
  },
  {
    "path": "public/spinner.css",
    "content": "#load-spinner {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  background-color: #1e1e1e\n}\n\n.lds-grid {\n  display: inline-block;\n  position: relative;\n  width: 80px;\n  height: 80px\n}\n\n.lds-grid div {\n  position: absolute;\n  width: 16px;\n  height: 16px;\n  border-radius: 50%;\n  background: #fff;\n  animation: lds-grid 1.2s linear infinite\n}\n\n.lds-grid div:nth-child(1) {\n  top: 8px;\n  left: 8px;\n  animation-delay: 0s\n}\n\n.lds-grid div:nth-child(2) {\n  top: 8px;\n  left: 32px;\n  animation-delay: -0.4s\n}\n\n.lds-grid div:nth-child(3) {\n  top: 8px;\n  left: 56px;\n  animation-delay: -0.8s\n}\n\n.lds-grid div:nth-child(4) {\n  top: 32px;\n  left: 8px;\n  animation-delay: -0.4s\n}\n\n.lds-grid div:nth-child(5) {\n  top: 32px;\n  left: 32px;\n  animation-delay: -0.8s\n}\n\n.lds-grid div:nth-child(6) {\n  top: 32px;\n  left: 56px;\n  animation-delay: -1.2s\n}\n\n.lds-grid div:nth-child(7) {\n  top: 56px;\n  left: 8px;\n  animation-delay: -0.8s\n}\n\n.lds-grid div:nth-child(8) {\n  top: 56px;\n  left: 32px;\n  animation-delay: -1.2s\n}\n\n.lds-grid div:nth-child(9) {\n  top: 56px;\n  left: 56px;\n  animation-delay: -1.6s\n}\n\n@keyframes lds-grid {\n  0%,\n  100% {\n    opacity: 1\n  }\n\n  50% {\n    opacity: 0.5\n  }\n}\n"
  },
  {
    "path": "scripts/build.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport cp from 'child_process';\nimport { executeCommand, PROJECT_ROOT } from './utils.js';\n\nconst main = () => {\n\tfor (const extension of fs.readdirSync('extensions')) {\n\t\tconst extensionPath = path.join(PROJECT_ROOT, 'extensions', extension);\n\t\tif (fs.existsSync(path.join(extensionPath, 'package.json'))) {\n\t\t\texecuteCommand('npm', ['run', 'compile'], extensionPath);\n\t\t}\n\t}\n\texecuteCommand('npx', ['webpack', '--mode=production'], PROJECT_ROOT);\n};\n\nmain();\n"
  },
  {
    "path": "scripts/link.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport { executeCommand, PROJECT_ROOT } from './utils.js';\n\nconst main = () => {\n\tconst distPath = path.join(PROJECT_ROOT, 'vscode-web/dist');\n\texecuteCommand('npm', ['link'], distPath);\n\texecuteCommand('npm', ['link', '@github1s/vscode-web'], PROJECT_ROOT);\n};\n\nmain();\n"
  },
  {
    "path": "scripts/postinstall.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { executeCommand, PROJECT_ROOT } from './utils.js';\n\nconst main = () => {\n\tconst extensions = fs.readdirSync(path.join(PROJECT_ROOT, 'extensions'));\n\tfor (const extension of extensions) {\n\t\tconst extensionPath = path.join(PROJECT_ROOT, 'extensions', extension);\n\t\texecuteCommand('npm', ['install', '--no-save'], extensionPath);\n\t}\n};\n\nmain();\n"
  },
  {
    "path": "scripts/utils.js",
    "content": "import path from 'path';\nimport cp from 'child_process';\n\nexport const PROJECT_ROOT = path.join(import.meta.dirname, '..');\n\nexport const executeCommand = (command, args, cwd) => {\n\tconst result = cp.spawnSync(command, args, { stdio: 'inherit', cwd });\n\tif (result.error) {\n\t\tthrow result.error;\n\t}\n};\n"
  },
  {
    "path": "scripts/webpack.js",
    "content": "import path from 'path';\nimport fs from 'fs-extra';\nimport { globSync } from 'glob';\n\nconst APP_ROOT = path.join(import.meta.dirname, '..');\n\nconst isWebExtension = (manifest) => {\n\tif (Boolean(manifest.browser)) {\n\t\treturn true;\n\t}\n\tif (Boolean(manifest.main)) {\n\t\treturn false;\n\t}\n\t// neither browser nor main\n\tif (typeof manifest.extensionKind !== 'undefined') {\n\t\tconst extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind];\n\t\tif (extensionKind.indexOf('web') >= 0) {\n\t\t\treturn true;\n\t\t}\n\t}\n\tif (typeof manifest.contributes !== 'undefined') {\n\t\tfor (const id of ['debuggers', 'terminal', 'typescriptServerPlugins']) {\n\t\t\tif (manifest.contributes.hasOwnProperty(id)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n};\n\nconst getExtensionData = (absolutePath) => {\n\ttry {\n\t\tconst packageJSONPath = path.join(absolutePath, 'package.json');\n\t\tif (!fs.existsSync(packageJSONPath)) {\n\t\t\treturn null;\n\t\t}\n\t\tconst packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString('utf8'));\n\t\tif (!isWebExtension(packageJSON)) {\n\t\t\treturn null;\n\t\t}\n\t\tconst children = fs.readdirSync(absolutePath);\n\t\tconst packageNLSPath = children.filter((child) => child === 'package.nls.json')[0];\n\t\tconst packageNLS = packageNLSPath\n\t\t\t? JSON.parse(fs.readFileSync(path.join(absolutePath, packageNLSPath)).toString())\n\t\t\t: undefined;\n\t\tconst readme = children.filter((child) => /^readme(\\.txt|\\.md|)$/i.test(child))[0];\n\t\tconst changelog = children.filter((child) => /^changelog(\\.txt|\\.md|)$/i.test(child))[0];\n\t\tconst extensionFolder = path.basename(absolutePath);\n\n\t\treturn {\n\t\t\textensionPath: extensionFolder,\n\t\t\tpackageJSON,\n\t\t\tpackageNLS,\n\t\t\treadmePath: readme ? path.join(extensionFolder, readme) : undefined,\n\t\t\tchangelogPath: changelog ? path.join(extensionFolder, changelog) : undefined,\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst scanVSCodeExtensions = () => {\n\tconst extensionsPath = path.join(APP_ROOT, 'vscode-web/lib/vscode/extensions');\n\tconst extensionFolders = fs.existsSync(extensionsPath) ? fs.readdirSync(extensionsPath) : [];\n\treturn extensionFolders.map((item) => getExtensionData(path.join(extensionsPath, item))).filter(Boolean);\n};\n\nconst scanGitHub1sExtensions = () => {\n\tconst extensions = fs.readdirSync(path.join(APP_ROOT, 'extensions'));\n\treturn extensions.map((item) => getExtensionData(path.join(APP_ROOT, 'extensions', item))).filter(Boolean);\n};\n\nexport const getBuiltinExtensions = (devVscode) => {\n\treturn [...(devVscode ? scanVSCodeExtensions() : []), ...scanGitHub1sExtensions()];\n};\n\nconst createImportMapScript = () => {\n\tconst cssFiles = globSync('**/*.css', { cwd: path.join(APP_ROOT, 'vscode-web/lib/vscode/out') });\n\treturn `const styleElement = document.createElement('style');\n\t\t\tstyleElement.setAttribute('type', 'text/css');\n\t\t\tstyleElement.setAttribute('media', 'screen');\n\t\t\tdocument.head.appendChild(styleElement);\n\n\t\t\tglobalThis._VSCODE_CSS_MODULES = ${JSON.stringify(cssFiles || [])};\n\t\t\tglobalThis._VSCODE_CSS_LOAD = (url) => styleElement.sheet.insertRule(\\`@import url(\\${url});\\`);\n\n\t\t\tconst importMap = { imports: {} };\n\t\t\tfor (const cssModule of globalThis._VSCODE_CSS_MODULES) {\n\t\t\t\tconst cssUrl = new URL(cssModule, globalThis._VSCODE_FILE_ROOT).href;\n\t\t\t\tconst jsSrc = \\`globalThis._VSCODE_CSS_LOAD('\\${cssUrl}');\\\\n\\`;\n\t\t\t\tconst blob = new Blob([jsSrc], { type: 'application/javascript' });\n\t\t\t\timportMap.imports[cssUrl] = URL.createObjectURL(blob);\n\t\t\t}\n\t\t\tconst importMapElement = document.createElement('script');\n\t\t\timportMapElement.type = 'importmap';\n\t\t\timportMapElement.setAttribute('nonce', '1nline-m4p');\n\t\t\timportMapElement.textContent = JSON.stringify(importMap, undefined, 2);\n\t\t\tdocument.head.appendChild(importMapElement);`;\n};\n\nexport const createGlobalScript = (staticDir, devVscode) => {\n\treturn `globalThis.dynamicImport = (url) => import(url);\n\t\t\tglobalThis._VSCODE_FILE_ROOT = new URL('/${staticDir}/vscode/', window.location.origin).toString();\n\t\t\t${devVscode ? createImportMapScript() : ''}`;\n};\n"
  },
  {
    "path": "src/config.ts",
    "content": "/**\n * @file config for different platform\n * @author netcon\n */\n\nimport githubLogoUrl from './assets/github.svg';\nimport gitlabLogoUrl from './assets/gitlab.svg';\nimport bitbucketLogoUrl from './assets/bitbucket.svg';\nimport npmLogoUrl from './assets/npm.svg';\n\nconst createFolderWorkspace = (scheme: string) => ({\n\tfolderUri: { scheme, authority: '', path: '/', query: '', fragment: '' },\n});\n\nconst openGitHub1sPage = () => {\n\treturn window.open('https://github.com/conwnet/github1s', '_blank');\n};\n\nconst openOfficialPage = (origin: string) => {\n\tconst targetPath = window.location.pathname + window.location.search + window.location.hash;\n\treturn window.open(origin + targetPath, '_blank');\n};\n\nconst createWindowIndicator = (label: string) => ({\n\ttooltip: label || '',\n\tlabel: label || '$(remote)',\n\tcommand: 'github1s.commands.openRepository',\n});\n\nconst createConfigurationDefaults = (disableSomeAnyCodeFeatures: boolean) => {\n\tconst configurationDefaults = {\n\t\t'workbench.colorTheme': 'Default Dark+',\n\t\t'telemetry.telemetryLevel': 'off',\n\t\t'workbench.startupEditor': 'readme',\n\t\t'workbench.editorAssociations': { '*.md': 'vscode.markdown.preview.editor' },\n\t\t'markdown.preview.doubleClickToSwitchToEditor': false,\n\t} as Record<string, any>;\n\n\t// disable some anycode features when we can use sourcegraph instead\n\tif (disableSomeAnyCodeFeatures) {\n\t\tconfigurationDefaults['anycode.language.features'] = {\n\t\t\tcompletions: false,\n\t\t\tdefinitions: false,\n\t\t\treferences: false,\n\t\t\thighlights: true,\n\t\t\toutline: true,\n\t\t\tworkspaceSymbols: true,\n\t\t\tfolding: false,\n\t\t\tdiagnostics: false,\n\t\t};\n\t}\n\treturn configurationDefaults;\n};\n\nexport enum Platform {\n\tGitHub = 'GitHub',\n\tGitLab = 'GitLab',\n\tBitbucket = 'Bitbucket',\n\tnpm = 'npm',\n}\n\nexport const createVSCodeWebConfig = (platform: Platform, repository: string): any => {\n\tif (platform === Platform.GitLab) {\n\t\treturn {\n\t\t\thideTextFileLabelDecorations: !!repository,\n\t\t\tworkspace: repository ? createFolderWorkspace('gitlab1s') : undefined,\n\t\t\tworkspaceId: repository ? 'gitlab1s:' + repository : '',\n\t\t\tworkspaceLabel: repository,\n\t\t\tlogo: {\n\t\t\t\ttitle: 'Open on GitLab',\n\t\t\t\ticon: gitlabLogoUrl,\n\t\t\t\tonClick: () => (repository ? openOfficialPage(GITLAB_ORIGIN) : openGitHub1sPage()),\n\t\t\t},\n\t\t};\n\t}\n\n\t// bitbucket is not available now\n\tif (platform === Platform.Bitbucket) {\n\t\treturn {\n\t\t\thideTextFileLabelDecorations: !!repository,\n\t\t\tworkspace: repository ? createFolderWorkspace('bitbucket1s') : undefined,\n\t\t\tworkspaceId: repository ? 'bitbucket1s:' + repository : '',\n\t\t\tworkspaceLabel: repository,\n\t\t\tlogo: {\n\t\t\t\ttitle: 'Open on Bitbucket',\n\t\t\t\ticon: bitbucketLogoUrl,\n\t\t\t\tonClick: () => (repository ? openOfficialPage('https://bitbucket.org') : openGitHub1sPage()),\n\t\t\t},\n\t\t};\n\t}\n\n\tif (platform === Platform.npm) {\n\t\treturn {\n\t\t\thideTextFileLabelDecorations: !!repository,\n\t\t\tworkspace: repository ? createFolderWorkspace('npmjs1s') : undefined,\n\t\t\tworkspaceId: repository ? 'npmjs1s:' + repository : '',\n\t\t\tworkspaceLabel: repository,\n\t\t\tlogo: {\n\t\t\t\ttitle: 'Open on npm',\n\t\t\t\ticon: npmLogoUrl,\n\t\t\t\tonClick: () => (repository ? openOfficialPage('https://npmjs.com') : openGitHub1sPage()),\n\t\t\t},\n\t\t};\n\t}\n\n\tconst isOnlineEditor = repository === 'editor';\n\treturn {\n\t\thideTextFileLabelDecorations: !isOnlineEditor,\n\t\tworkspace: !isOnlineEditor ? createFolderWorkspace(repository ? 'github1s' : 'ossinsight') : undefined,\n\t\tworkspaceId: !isOnlineEditor ? 'github1s:' + (repository || 'trending') : '',\n\t\tworkspaceLabel: repository || (isOnlineEditor ? '' : 'GitHub Trending'),\n\t\tlogo: {\n\t\t\ttitle: 'Open on GitHub',\n\t\t\ticon: githubLogoUrl,\n\t\t\tonClick: () => (repository ? openOfficialPage(GITHUB_ORIGIN) : openGitHub1sPage()),\n\t\t},\n\t};\n};\n\nexport const createWorkbenchOptions = (platform: Platform, repository: string): any => {\n\tif (platform === Platform.GitLab) {\n\t\treturn {\n\t\t\twindowIndicator: createWindowIndicator(repository),\n\t\t\tconfigurationDefaults: createConfigurationDefaults(!!repository),\n\t\t};\n\t}\n\n\t// bitbucket is not available now\n\tif (platform === Platform.Bitbucket) {\n\t\treturn {\n\t\t\twindowIndicator: createWindowIndicator(repository),\n\t\t\tconfigurationDefaults: createConfigurationDefaults(!!repository),\n\t\t};\n\t}\n\n\tif (platform === Platform.npm) {\n\t\treturn {\n\t\t\twindowIndicator: createWindowIndicator(repository),\n\t\t\tconfigurationDefaults: createConfigurationDefaults(false),\n\t\t};\n\t}\n\n\treturn {\n\t\twindowIndicator: createWindowIndicator(repository),\n\t\tconfigurationDefaults: createConfigurationDefaults(!!repository),\n\t};\n};\n"
  },
  {
    "path": "src/github-auth.ts",
    "content": "/**\n * @file connect to github\n * @author netcon\n */\n\nconst CLIENT_ID = 'eae6621348403ea49103';\nconst GITHUB_ORIGIN = 'https://github.com';\nconst GITHUB_AUTH_URL = `${GITHUB_ORIGIN}/login/oauth/authorize?scope=repo,user:email&client_id=${CLIENT_ID}`;\nconst OPEN_WINDOW_FEATURES =\n\t'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=800,height=520,top=150,left=150';\nconst AUTH_PAGE_ORIGIN = 'https://auth.github1s.com';\n\nexport const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nexport const ConnectToGitHub = () => {\n\tconst opener = window.open(GITHUB_AUTH_URL, '_blank', OPEN_WINDOW_FEATURES);\n\n\treturn new Promise((resolve) => {\n\t\tconst handleAuthMessage = (event: MessageEvent) => {\n\t\t\t// Note that though the browser block opening window and popup a tip,\n\t\t\t// the user can be still open it from the tip. In this case, the `opener`\n\t\t\t// is null, and we should still process the authorizing message\n\t\t\tconst isValidOpener = !!(opener && event.source === opener);\n\t\t\tconst isValidOrigin = event.origin === AUTH_PAGE_ORIGIN;\n\t\t\tconst isValidResponse = event.data ? event.data.type === 'authorizing' : false;\n\t\t\tif (!isValidOpener || !isValidOrigin || !isValidResponse) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\twindow.removeEventListener('message', handleAuthMessage);\n\t\t\tresolve(event.data?.payload);\n\t\t};\n\n\t\twindow.addEventListener('message', handleAuthMessage);\n\t\t// if there isn't any message from opener window in 300s, remove the message handler\n\t\ttimeout(300 * 1000).then(() => {\n\t\t\twindow.removeEventListener('message', handleAuthMessage);\n\t\t\tresolve({ error: 'authorizing_timeout', error_description: 'Authorizing timeout' });\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "src/gitlab-auth.ts",
    "content": "/**\n * @file connect to gitlab\n * @author netcon\n */\n\nimport { timeout } from './github-auth';\n\nconst GITLAB_ORIGIN = 'https://gitlab.com';\nconst AUTH_PAGE_ORIGIN = 'https://auth.gitlab1s.com';\nconst AUTH_REDIRECT_URI = 'https://auth.gitlab1s.com/api/gitlab-auth-callback';\nconst CLIENT_ID = '5ef142320efe9d2e8caeb0185771bb126d3035dc0a325c6ad5bab567f320d564';\nconst OPEN_WINDOW_FEATURES =\n\t'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=800,height=520,top=150,left=150';\n\nconst createRandomString = (length: number) => {\n\tconst charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n\treturn Array.from({ length }, () => charset.charAt(Math.floor(Math.random() * charset.length))).join('');\n};\n\nconst createAuthorizeUrl = (state: string) => {\n\tconst parameters = Object.entries({\n\t\tstate,\n\t\tscope: 'read_api',\n\t\tresponse_type: 'code',\n\t\tclient_id: CLIENT_ID,\n\t\tredirect_uri: AUTH_REDIRECT_URI,\n\t}).map(([key, value]) => `${key}=${encodeURIComponent(value)}`);\n\treturn `${GITLAB_ORIGIN}/oauth/authorize?${parameters.join('&')}`;\n};\n\n// https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow\nexport const ConnectToGitLab = async () => {\n\tconst STATE = createRandomString(32);\n\tconst opener = window.open(createAuthorizeUrl(STATE), '_blank', OPEN_WINDOW_FEATURES);\n\n\treturn new Promise((resolve) => {\n\t\tconst handleAuthMessage = (event: MessageEvent) => {\n\t\t\t// Note that though the browser block opening window and popup a tip,\n\t\t\t// the user can be still open it from the tip. In this case, the `opener`\n\t\t\t// is null, and we should still process the authorizing message\n\t\t\tconst isValidOpener = !!(opener && event.source === opener);\n\t\t\tconst isValidOrigin = event.origin === AUTH_PAGE_ORIGIN;\n\t\t\tconst isValidResponse = event.data ? event.data.type === 'authorizing' : false;\n\t\t\tif (!isValidOpener || !isValidOrigin || !isValidResponse) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\twindow.removeEventListener('message', handleAuthMessage);\n\t\t\tresolve(event.data?.payload);\n\t\t};\n\n\t\twindow.addEventListener('message', handleAuthMessage);\n\t\t// if there isn't any message from opener window in 300s, remove the message handler\n\t\ttimeout(300 * 1000).then(() => {\n\t\t\twindow.removeEventListener('message', handleAuthMessage);\n\t\t\tresolve({ error: 'authorizing_timeout', error_description: 'Authorizing timeout' });\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "src/global.d.ts",
    "content": "// eslint-disable-next-line @typescript-eslint/triple-slash-reference\n/// <reference path=\"../vscode-web/src/setup.d.ts\" />\n\ndeclare module '*.svg' {\n\tconst content: string;\n\texport default content;\n}\n\ndeclare const DEV_VSCODE: boolean;\ndeclare const GITHUB_ORIGIN: string;\ndeclare const GITLAB_ORIGIN: string;\ndeclare const GITHUB1S_EXTENSIONS: string;\ndeclare const AVAILABLE_LANGUAGES: string[];\n\n/* eslint-disable no-var */\ndeclare var dynamicImport: (url: string) => Promise<any>;\ndeclare var _VSCODE_FILE_ROOT: string;\n"
  },
  {
    "path": "src/index.ts",
    "content": "/**\n * @file page entry\n * @author netcon\n */\n\nimport { ConnectToGitHub } from './github-auth';\nimport { ConnectToGitLab } from './gitlab-auth';\nimport { renderNotification } from './notification';\nimport { createProductConfiguration } from './product';\nimport { createVSCodeWebConfig, createWorkbenchOptions, Platform } from './config';\n\nconst resolvePlatformState = (): [Platform, string] => {\n\tconst hostname = window.location.hostname;\n\tconst pathParts = window.location.pathname.split('/').filter(Boolean);\n\n\tif (hostname.match(/^(.*\\.)?gitlab1s\\.com$/i)) {\n\t\tconst dashIndex = pathParts.indexOf('-');\n\t\tconst repository = (dashIndex < 0 ? pathParts : pathParts.slice(0, dashIndex)).join('/');\n\t\treturn [Platform.GitLab, repository];\n\t}\n\tif (hostname.match(/^(.*\\.)?bitbucket1s\\.org$/i)) {\n\t\tconst repository = pathParts.length >= 2 ? pathParts.slice(0, 2).join('/') : '';\n\t\treturn [Platform.Bitbucket, repository];\n\t}\n\tif (hostname.match(/^(.*\\.)?npmjs1s\\.com$/i)) {\n\t\tconst trimmedParts = pathParts[0] === 'package' ? pathParts.slice(1) : pathParts;\n\t\tconst packageParts = trimmedParts.slice(0, trimmedParts[0] && trimmedParts[0][0] === '@' ? 2 : 1);\n\t\tconst repository = pathParts.length ? packageParts.join('/') || 'package' : '';\n\n\t\treturn [Platform.npm, repository];\n\t}\n\n\tconst repository = pathParts.slice(0, 2).join('/');\n\treturn [Platform.GitHub, repository];\n};\n\nconst [platform, repository] = resolvePlatformState();\nconst resolveVscodeUrl = (path: string) => new URL(path, globalThis._VSCODE_FILE_ROOT).href;\n\nconst vscodeCommands = [\n\t{ id: 'github1s.commands.vscode.getBrowserUrl', handler: () => window.location.href },\n\t{ id: 'github1s.commands.vscode.replaceBrowserUrl', handler: (url: string) => history.replaceState(null, '', url) },\n\t{ id: 'github1s.commands.vscode.pushBrowserUrl', handler: (url: string) => history.pushState(null, '', url) },\n\t{ id: 'github1s.commands.vscode.connectToGitHub', handler: ConnectToGitHub },\n\t{ id: 'github1s.commands.vscode.connectToGitLab', handler: ConnectToGitLab },\n];\n\nglobalThis._VSCODE_WEB = {\n\tallowEditorLabelOverride: true,\n\tbuiltinExtensions: GITHUB1S_EXTENSIONS || [],\n\tonWorkbenchReady() {\n\t\tconst loadSpinner = document.querySelector('#load-spinner');\n\t\tloadSpinner && loadSpinner.remove();\n\t\trenderNotification(platform);\n\t},\n\t...createVSCodeWebConfig(platform, repository),\n};\n\nif (!DEV_VSCODE) {\n\tconst linkElement = document.createElement('link');\n\tlinkElement.setAttribute('rel', 'stylesheet');\n\tlinkElement.setAttribute('href', resolveVscodeUrl('vs/workbench/workbench.web.main.css'));\n\tdocument.head.appendChild(linkElement);\n\n\tconst languageId = document.cookie.match(/(^| )vscode.nls.locale=([^;]+)/)?.[2] || '';\n\tconst nlsUrl = AVAILABLE_LANGUAGES.includes(languageId)\n\t\t? resolveVscodeUrl(`../nls/${languageId}/nls.messages.js`)\n\t\t: resolveVscodeUrl('nls.messages.js');\n\tconst scriptElement = document.createElement('script');\n\tscriptElement.setAttribute('src', nlsUrl);\n\tdocument.body.appendChild(scriptElement);\n}\n\ndynamicImport(resolveVscodeUrl('vs/workbench/workbench.web.main.internal.js')).then(({ create, env, URI }) => {\n\tconst resolveWorkspace = (workspace: any) => {\n\t\tif (workspace?.folderUri) {\n\t\t\treturn { folderUri: URI.from(workspace.folderUri) };\n\t\t}\n\t\tif (workspace?.workspaceUri) {\n\t\t\treturn { workspaceUri: URI.from(workspace.workspaceUri) };\n\t\t}\n\t\treturn { workspaceUri: URI.from({ scheme: 'tmp', path: '/default.code-workspace' }) };\n\t};\n\n\tconst vscodeWebConfig = {\n\t\tcommands: vscodeCommands,\n\t\twebviewEndpoint: resolveVscodeUrl('vs/workbench/contrib/webview/browser/pre'),\n\t\tproductConfiguration: createProductConfiguration(platform),\n\t\tinitialColorTheme: { themeType: 'dark' as any },\n\t\t...createWorkbenchOptions(platform, repository),\n\t};\n\n\tconst workspaceProvider = {\n\t\ttrusted: true,\n\t\tworkspace: resolveWorkspace(globalThis._VSCODE_WEB.workspace),\n\t\topen: () => Promise.resolve(false),\n\t};\n\n\tcreate(document.body, { workspaceProvider, ...vscodeWebConfig });\n\tenv.getUriScheme().then((scheme: any) => globalThis._VSCODE_WEB.onWorkbenchReady?.(scheme));\n});\n"
  },
  {
    "path": "src/notification.css",
    "content": ".github1s-notification {\n  display: block;\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  height: 60px;\n  z-index: 999;\n  display: flex;\n  box-shadow: 1px 1px 5px 3px #1e1e1e;\n  background: rgba(0, 0, 0, .8);\n  font-size: 14px\n}\n\n.github1s-notification .notification-main {\n  flex: 1;\n  padding: 0 20px;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  overflow: hidden\n}\n\n.github1s-notification .notification-main .notification-title {\n  color: #ffe58f;\n  font-size: 16px;\n  margin-bottom: 2px;\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis\n}\n\n.github1s-notification .notification-main .notification-content {\n  color: #ccc;\n  font-size: 13px;\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis\n}\n\n.github1s-notification .notification-main .notification-link {\n  color: #3794ff;\n  text-decoration: none\n}\n\n.github1s-notification .notification-main .notification-link:focus {\n  outline: 1px solid #007fd4;\n  outline-offset: -1px\n}\n\n.github1s-notification .notification-footer {\n  padding-right: 20px;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  min-width: 140px\n}\n\n.github1s-notification .notification-footer .notification-confirm-button {\n  border: none;\n  width: 100%;\n  height: 26px;\n  margin-bottom: 2px;\n  text-align: center;\n  outline: 1px solid transparent;\n  outline-offset: 2px !important;\n  color: #fff;\n  background-color: #0e639c;\n  cursor: pointer\n}\n\n.github1s-notification .notification-footer .notification-confirm-button:hover {\n  background-color: #17b\n}\n\n.github1s-notification .notification-footer .notification-confirm-button:focus {\n  outline-color: #007fd4\n}\n\n.github1s-notification .notification-footer .notification-show-me-again {\n  color: #ccc;\n  font-size: 12px;\n  display: flex;\n  align-items: center\n}\n"
  },
  {
    "path": "src/notification.ts",
    "content": "/**\n * @file render notification\n * @author netcon\n */\n\nimport './notification.css';\n\nconst NOTIFICATION_STORAGE_KEY = 'GITHUB1S_NOTIFICATION';\n// Change this if a new notification should be shown\nconst NOTIFICATION_STORAGE_VALUE = '20210212';\n\n/*** begin notification block ***/\nexport const renderNotification = (platform: string) => {\n\t// If user has confirmed the notification and checked `don't show me again`, ignore it\n\tif (window.localStorage.getItem(NOTIFICATION_STORAGE_KEY) === NOTIFICATION_STORAGE_VALUE) {\n\t\treturn;\n\t}\n\n\tconst notifications = [\n\t\t{\n\t\t\ttitle: 'ATTENTION: This page is NOT officially provided by ' + platform + '.',\n\t\t\tcontent: platform + '1s is an open source project, which is not officially provided by ' + platform + '.',\n\t\t\tlink: 'https://github.com/conwnet/github1s',\n\t\t},\n\t];\n\n\tconst notificationBlocksHtml = notifications.map((item) => {\n\t\tconst linkHtml = item.link\n\t\t\t? ' <a class=\"notification-link\" href=\"' + item.link + '\" target=\"_blank\">See more</a>'\n\t\t\t: '';\n\t\tconst titleHtml = '<div class=\"notification-main\"><div class=\"notification-title\">' + item.title + '</div>';\n\t\tconst contentHtml = '<div class=\"notification-content\">' + item.content + linkHtml + '</div></div>';\n\t\treturn titleHtml + contentHtml;\n\t});\n\n\tconst notificationHtml =\n\t\tnotificationBlocksHtml +\n\t\t'<div class=\"notification-footer\"><button class=\"notification-confirm-button\">OK</button>' +\n\t\t'<div class=\"notification-show-me-again\"><input type=\"checkbox\" checked>Don\\'t show me again</div></div></div>';\n\n\tconst notificationElement = document.createElement('div');\n\tnotificationElement.classList.add('github1s-notification');\n\tnotificationElement.innerHTML = notificationHtml;\n\tdocument.body.appendChild(notificationElement);\n\n\tconst confirmButton = notificationElement.querySelector('.notification-confirm-button') as HTMLButtonElement;\n\n\tconfirmButton.onclick = () => {\n\t\tconst showAgainCheckBox = notificationElement?.querySelector('.notification-show-me-again input');\n\t\tconst notShowMeAgain = !!(showAgainCheckBox as HTMLInputElement)?.checked;\n\t\tif (notShowMeAgain) {\n\t\t\twindow.localStorage.setItem(NOTIFICATION_STORAGE_KEY, NOTIFICATION_STORAGE_VALUE);\n\t\t}\n\t\tdocument.body.removeChild(notificationElement);\n\t};\n};\n"
  },
  {
    "path": "src/product.ts",
    "content": "import { Platform } from './config';\n\nexport const createProductConfiguration = (platform: Platform) => ({\n\tnameShort: platform + '1s',\n\tnameLong: platform + '1s',\n\tapplicationName: platform + '1s',\n\treportIssueUrl: 'https://github.com/conwnet/github1s/issues/new',\n\textensionsGallery: {\n\t\tresourceUrlTemplate: 'https://open-vsx.org/vscode/unpkg/{publisher}/{name}/{version}/{path}',\n\t\textensionUrlTemplate: 'https://open-vsx.org/vscode/gallery/{publisher}/{name}/latest',\n\t\tserviceUrl: 'https://open-vsx.org/vscode/gallery',\n\t\titemUrl: 'https://open-vsx.org/vscode/item',\n\t},\n\tlinkProtectionTrustedDomains: [\n\t\t'*.github.com',\n\t\t'*.github1s.com',\n\t\t'*.gitlab.com',\n\t\t'*.gitlab1s.com',\n\t\t'*.bitbucket.org',\n\t\t'*.bitbucket1s.org',\n\t\t'*.npmjs.com',\n\t\t'*.npmjs1s.com',\n\t\t'*.microsoft.com',\n\t\t'*.sourcegraph.com',\n\t\t'*.ossinsight.io',\n\t\t'*.open-vsx.org',\n\t],\n\textensionEnabledApiProposals: { 'ms-vscode.anycode': ['extensionsAny'] },\n});\n"
  },
  {
    "path": "tests/__tests__/index.test.ts",
    "content": "import { chromium, Browser, Page } from 'playwright';\nimport { toMatchImageSnapshot, MatchImageSnapshotOptions } from 'jest-image-snapshot';\n\njest.setTimeout(60000);\nexpect.extend({ toMatchImageSnapshot });\n\nconst matchImageSnapshotOptions: MatchImageSnapshotOptions = {\n\tfailureThreshold: 0.15,\n\tfailureThresholdType: 'percent',\n\tupdatePassedSnapshot: true,\n};\n\nlet browser: Browser;\nlet page: Page;\n\nconst BASE_URL = 'http://localhost:8080';\n\nbeforeAll(async () => {\n\tbrowser = await chromium.launch();\n});\n\nafterAll(async () => {\n\tawait browser.close();\n});\n\nbeforeEach(async () => {\n\tpage = await browser.newPage();\n});\n\nafterEach(async () => {\n\tawait page.close();\n});\n\nit('should load successfully', async () => {\n\tawait page.goto(`${BASE_URL}/conwnet/github1s`);\n\texpect(await page.title()).toMatch(/.*GitHub1s/);\n\n\t// Make sure the VS Code loads\n\tawait page.click('div[role=\"application\"]');\n\n\t// Make sure the repo loads\n\tawait page.click('div[role=\"tab\"]');\n\t// GitHub repo Link available\n\tawait page.$eval('div.home-bar', (el) => el.innerHTML);\n\t// File explorer available\n\tawait page.$eval('div[role=\"tree\"][aria-label=\"Files Explorer\"]', (el) => el.innerHTML);\n\tconst tab = await page.$eval('div[role=\"tab\"] .label-name', (el: HTMLElement) => el.innerText);\n\texpect(tab).toBe('[Preview] README.md');\n\t// Title updated based on the repo\n\texpect(await page.title()).toMatch(/\\[Preview\\] README\\.md . conwnet\\/github1s . GitHub1s/);\n\tawait page.waitForTimeout(5000);\n\n\t// README file will be rendered in an iframe\n\tawait page.$eval(\n\t\t'iframe.webview.ready[sandbox=\"allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads\"][src]',\n\t\t(el: HTMLElement) => el.innerHTML,\n\t);\n\n\tconst image = await page.screenshot();\n\texpect(image).toMatchImageSnapshot(matchImageSnapshotOptions);\n});\n\nit('should open file correctly', async () => {\n\tawait page.goto(`${BASE_URL}/conwnet/github1s`);\n\tawait page.waitForTimeout(3000);\n\tawait page.click('[aria-label=\"~/tsconfig.json\"]');\n\tawait page.click('[data-resource-name=\"tsconfig.json\"]');\n\tawait page.waitForTimeout(3000);\n\n\tconst image = await page.screenshot();\n\texpect(image).toMatchImageSnapshot(matchImageSnapshotOptions);\n});\n\nit('should show Commit files', async () => {\n\tawait page.goto(`${BASE_URL}/conwnet/github1s/commit/ecd252fa54de41b1cb622ff5a1f8a1b715d3b621`);\n\tawait page.waitForSelector('.monaco-action-bar.vertical ul.actions-container[aria-label=\"Active View Switcher\"]');\n\tawait page.press('body', 'Control+Shift+G');\n\tawait page.waitForTimeout(6000);\n\n\tconst container = await page.$('[id=\"workbench.parts.sidebar\"]');\n\tconst image = await container?.screenshot();\n\texpect(image).toMatchImageSnapshot(matchImageSnapshotOptions);\n});\n"
  },
  {
    "path": "tests/jest.config.js",
    "content": "module.exports = {\n\tpreset: 'jest-playwright-preset',\n\ttestPathIgnorePatterns: ['/node_modules/', '/lib/', '/dist/'],\n\ttransform: {\n\t\t'^.+\\\\.(ts)$': 'ts-jest',\n\t},\n\ttestEnvironmentOptions: {\n\t\t'jest-playwright': {\n\t\t\tbrowsers: ['chromium', 'firefox', 'webkit'],\n\t\t},\n\t},\n};\n"
  },
  {
    "path": "tests/package.json",
    "content": "{\n  \"name\": \"github1s-test\",\n  \"version\": \"1.0.0\",\n  \"description\": \"test case for github1s\",\n  \"scripts\": {\n    \"test:ci\": \"start-server-and-test serve http://localhost:8080 test\",\n    \"test\": \"jest\",\n    \"test:watch\": \"jest --watchAll\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"@types/jest\": \"^29.5.14\",\n    \"@types/jest-image-snapshot\": \"^6.4.0\",\n    \"jest\": \"^29.7.0\",\n    \"jest-image-snapshot\": \"^6.4.0\",\n    \"jest-playwright-preset\": \"^4.0.0\",\n    \"playwright\": \"^1.55.1\",\n    \"start-server-and-test\": \"^2.0.9\",\n    \"ts-jest\": \"^29.2.5\",\n    \"typescript\": \"^5.7.3\"\n  }\n}\n"
  },
  {
    "path": "tests/tsconfig.json",
    "content": "{\n\t\"extends\": \"../tsconfig.json\",\n\t\"compilerOptions\": {\n\t\t\"esModuleInterop\": true\n\t}\n}\n"
  },
  {
    "path": "tests/typings.d.ts",
    "content": "import 'jest';\n\ndeclare global {\n\tnamespace jest {\n\t\tinterface Matchers<R> {\n\t\t\ttoMatchImageSnapshot(): R;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n\t\"include\": [\"./src/\"],\n\t\"compilerOptions\": {\n\t\t\"module\": \"es2022\",\n\t\t\"moduleResolution\": \"node\",\n\t\t\"experimentalDecorators\": true,\n\t\t\"noImplicitReturns\": true,\n\t\t\"noImplicitOverride\": true,\n\t\t\"noUnusedLocals\": true,\n\t\t\"allowUnreachableCode\": false,\n\t\t\"strict\": true,\n\t\t\"exactOptionalPropertyTypes\": false,\n\t\t\"useUnknownInCatchVariables\": false,\n\t\t\"forceConsistentCasingInFileNames\": true,\n\t\t\"baseUrl\": \".\",\n\t\t\"paths\": {\n\t\t\t\"vs/*\": [\n\t\t\t\t\"./vscode-web/src/vs/*\",\n\t\t\t\t\"./vscode-web/lib/vscode/src/vs/*\"\n\t\t\t]\n\t\t},\n\t\t\"target\": \"es2022\",\n\t\t\"useDefineForClassFields\": false,\n\t\t\"lib\": [\n\t\t\t\"ES2022\",\n\t\t\t\"DOM\",\n\t\t\t\"DOM.Iterable\",\n\t\t\t\"WebWorker.ImportScripts\"\n\t\t],\n\t\t\"allowSyntheticDefaultImports\": true\n\t}\n}\n"
  },
  {
    "path": "vscode-web/.VERSION",
    "content": "1.108.2"
  },
  {
    "path": "vscode-web/README.md",
    "content": "# @github1s/vscode-web\n\nThis is the companion NPM package to support GitHub1s. The NPM package is [@github1s/vscode-web](https://www.npmjs.com/package/@github1s/vscode-web).\n\n## Commands\n\n`npm run clone` - clone the official VS Code repo.\n\n`npm run build` - build the VS Code with the custom code under `src`.\n\n`npm run watch` - watch the code change under `src` directory and rebuild VS Code.\n\n## Usage\n\nThe codes in the package can be used independently, See [index.html](./index.html).\n\n## Publish\n\nTo publish the NPM package, please make sure you have the right access via https://www.npmjs.com/ and run the following commands:\n\n```sh\n# bump the `version` field in package.json file.\nnpm run build && cd dist\nnpm publish --access public\n```\n"
  },
  {
    "path": "vscode-web/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no\" />\n\t\t<title>VSCode Web</title>\n\t\t<link rel=\"icon\" href=\"/favicon.ico\" type=\"image/x-icon\" />\n\t\t<link rel=\"stylesheet\" href=\"/vscode/vs/workbench/workbench.web.main.css\" />\n\t</head>\n\t<body>\n\t\t<script src=\"/vscode/nls.messages.js\"></script>\n\t\t<script>\n\t\t\tglobalThis._VSCODE_FILE_ROOT = new URL('/vscode/', window.location.origin).toString();\n\t\t</script>\n\t\t<script type=\"module\">\n\t\t\timport { create, URI } from '/vscode/vs/workbench/workbench.web.main.internal.js';\n\t\t\tcreate(document.body, {\n\t\t\t\twebviewEndpoint: '/vscode/vs/workbench/contrib/webview/browser/pre',\n\t\t\t\tworkspaceProvider: {\n\t\t\t\t\tworkspace: { workspaceUri: URI.from({ scheme: 'tmp', path: '/default.code-workspace' }) },\n\t\t\t\t},\n\t\t\t});\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "vscode-web/package.json",
    "content": "{\n  \"name\": \"@github1s/vscode-web\",\n  \"version\": \"0.27.0\",\n  \"description\": \"VS Code web for GitHub1s\",\n  \"author\": \"github1s\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"repository\": \"https://github.com/conwnet/github1s\",\n  \"scripts\": {\n    \"clone\": \"node scripts/clone.js\",\n    \"patch\": \"node scripts/patch.js\",\n    \"build\": \"run-s clone patch build:*\",\n    \"build:vscode\": \"node scripts/build/vscode.js\",\n    \"build:package\": \"node scripts/build/package.js\",\n    \"build:nls\": \"node scripts/build/nls.js\",\n    \"watch\": \"run-s clone patch && run-p watch:*\",\n    \"watch:source\": \"node scripts/watch/source.js\",\n    \"watch:vscode\": \"node scripts/watch/vscode.js\",\n    \"watch:extensions\": \"node scripts/watch/extensions.js\"\n  },\n  \"private\": false,\n  \"files\": [\n    \"/dist\",\n    \".VERSION\"\n  ],\n  \"keywords\": [\n    \"vscode\",\n    \"vscode-web\",\n    \"github1s\"\n  ],\n  \"devDependencies\": {\n    \"chokidar\": \"^4.0.3\",\n    \"fs-extra\": \"^11.2.0\",\n    \"npm-run-all\": \"^4.1.5\"\n  }\n}\n"
  },
  {
    "path": "vscode-web/scripts/.patch",
    "content": "{\n  \"src/vs/workbench/browser/parts/activitybar/activitybarPart.ts\": \"3edda05b7b7cf235bc0d51f066aa8d57c447ea784ccd507316327150a4bb880c\",\n  \"src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css\": \"26cdde234b2811b42166224f3b0f12eb6d78d519d5262cc2b12ec08653b3df39\",\n  \"src/vs/workbench/browser/web.main.ts\": \"a7c43beaa0f873ce0f9edc1aa03db3e9150fb1ac6dc6479a08e0ea5c8a3b2e76\",\n  \"src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts\": \"e986095a30dbea54af56c25fa1b184b55f34f8914129b27e2f20d8c4ea9fd16b\",\n  \"src/vs/workbench/contrib/webview/browser/pre/index.html\": \"8b2e27b411b4fa493fe003c5312378ca0c7164fee99ed288c6e4f47c43dbca1f\",\n  \"src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts\": \"16fc1f8830432097a2de87ba04f9f11e930408df8f672bb7a4bbbe3c1a7c509d\",\n  \"src/vs/workbench/services/label/common/labelService.ts\": \"ac42f60193b50a4668384787468758e4b093f9f2da74a7c9604de5c455886e98\",\n  \"src/vs/workbench/services/textfile/browser/textFileService.ts\": \"c384a6ec5991888fb09cdbf482a6747fa15d486e1cd8967560da3ca1df65944e\",\n  \"src/vs/base/common/network.ts\": \"e8679d4499a7bf7474f31e3dcf61db40be3c0c5c81837cf7adf8e7ea2b656fa1\",\n  \"src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html\": \"40d576ad2307d28012b34b86858ba36ba49ae10e5aedb394bd06b14a35b869a5\"\n}"
  },
  {
    "path": "vscode-web/scripts/build/nls.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { PROJECT_ROOT } from '../utils.js';\n\nconst deepMerge = (target, source) => {\n\tfor (const key of Object.keys(source)) {\n\t\tif (typeof source[key] === 'object' && target[key]) {\n\t\t\tdeepMerge(target[key], source[key]);\n\t\t} else {\n\t\t\ttarget[key] = source[key];\n\t\t}\n\t}\n\treturn target;\n};\n\nconst main = () => {\n\tconst oputBuildPath = path.join(PROJECT_ROOT, 'lib/vscode/out-build');\n\tconst nlsKeys = JSON.parse(fs.readFileSync(path.join(oputBuildPath, 'nls.keys.json')));\n\tconst nlsMessages = JSON.parse(fs.readFileSync(path.join(oputBuildPath, 'nls.messages.json')));\n\n\tconst languageContentsMap = {};\n\tconst i18nPath = path.join(PROJECT_ROOT, 'lib/vscode-loc/i18n');\n\n\tfor (const languageDir of fs.readdirSync(i18nPath)) {\n\t\tconst languagePath = path.join(i18nPath, languageDir);\n\t\tconst packageJson = JSON.parse(fs.readFileSync(path.join(languagePath, 'package.json')));\n\n\t\tfor (const localization of packageJson.contributes.localizations) {\n\t\t\tif (!languageContentsMap[localization.languageId]) {\n\t\t\t\tlanguageContentsMap[localization.languageId] = {};\n\t\t\t}\n\n\t\t\tconst contents = languageContentsMap[localization.languageId];\n\t\t\tfor (const translation of localization.translations) {\n\t\t\t\tconst translationPath = path.join(languagePath, translation.path);\n\t\t\t\tdeepMerge(contents, JSON.parse(fs.readFileSync(translationPath)).contents);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const languageId of Object.keys(languageContentsMap)) {\n\t\tconst langMessages = [];\n\t\tconst contents = languageContentsMap[languageId];\n\n\t\tfor (const [file, keys] of nlsKeys) {\n\t\t\tfor (const key of keys) {\n\t\t\t\tlangMessages.push(contents[file]?.[key] ?? nlsMessages[langMessages.length]);\n\t\t\t}\n\t\t}\n\t\tif (langMessages.length !== nlsMessages.length) {\n\t\t\tthrow new Error(`Invalid nls messages for ${languageId}`);\n\t\t}\n\n\t\tconst nslDirPath = path.join(PROJECT_ROOT, `dist/nls/${languageId}`);\n\t\tfs.ensureDirSync(nslDirPath);\n\t\tfs.writeFileSync(\n\t\t\tpath.join(nslDirPath, 'nls.messages.js'),\n\t\t\t`globalThis._VSCODE_NLS_MESSAGES=${JSON.stringify(langMessages)};` +\n\t\t\t\t`globalThis._VSCODE_NLS_LANGUAGE=${JSON.stringify(languageId)};`,\n\t\t);\n\t}\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/scripts/build/package.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { PROJECT_ROOT } from '../utils.js';\n\nconst main = () => {\n\tconst distPath = path.join(PROJECT_ROOT, 'dist');\n\n\tfs.removeSync(distPath);\n\tfs.ensureDirSync(distPath);\n\n\tfs.copySync(path.join(PROJECT_ROOT, 'lib/vscode-web/out'), path.join(distPath, 'vscode'));\n\tfs.copySync(path.join(PROJECT_ROOT, 'lib/vscode-web/extensions'), path.join(distPath, 'extensions'));\n\tfs.copySync(path.join(PROJECT_ROOT, 'lib/vscode-web/node_modules'), path.join(distPath, 'dependencies'));\n\tfs.copyFileSync(path.join(PROJECT_ROOT, 'lib/vscode-web/favicon.ico'), path.join(distPath, 'favicon.ico'));\n\n\tfs.copyFileSync(path.join(PROJECT_ROOT, 'README.md'), path.join(distPath, 'README.md'));\n\tfs.copyFileSync(path.join(PROJECT_ROOT, 'index.html'), path.join(distPath, 'index.html'));\n\tfs.copyFileSync(path.join(PROJECT_ROOT, '.VERSION'), path.join(distPath, '.VERSION'));\n\n\tconst projectInfo = JSON.parse(fs.readFileSync(path.join(PROJECT_ROOT, 'package.json')));\n\tconst packageJson = {\n\t\tname: projectInfo.name,\n\t\tversion: projectInfo.version,\n\t\tdescription: projectInfo.description,\n\t\trepository: projectInfo.repository,\n\t\tlicense: projectInfo.license,\n\t\ttype: projectInfo.type,\n\t\tauthor: projectInfo.author,\n\t\tkeywords: projectInfo.keywords,\n\t};\n\tfs.writeFileSync(path.join(PROJECT_ROOT, 'dist/package.json'), JSON.stringify(packageJson, null, 2));\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/scripts/build/vscode.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport { executeCommand, PROJECT_ROOT } from '../utils.js';\n\nconst main = () => {\n\tconst cwd = path.join(PROJECT_ROOT, 'lib/vscode');\n\texecuteCommand('npm', ['run', 'gulp', 'vscode-web-min'], cwd);\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/scripts/clone.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport cp from 'child_process';\nimport fs from 'fs-extra';\nimport crypto from 'crypto';\nimport { executeCommand, PROJECT_ROOT, getAllFiles } from './utils.js';\n\nconst fixSourceFiles = () => {\n\tconst getDiffFiles = (base) => {\n\t\treturn getAllFiles(path.join(PROJECT_ROOT, base)).map((file) => {\n\t\t\treturn path.relative(PROJECT_ROOT, file);\n\t\t});\n\t};\n\n\tconst diffFiles = getDiffFiles('src');\n\tif (fs.existsSync(path.join(PROJECT_ROOT, 'extensions'))) {\n\t\tdiffFiles.push(...getDiffFiles('extensions'));\n\t}\n\n\tlet hasSourceUpdated = false;\n\tconst shasPath = path.join(PROJECT_ROOT, 'scripts/.patch');\n\tconst fileShas = JSON.parse(fs.readFileSync(shasPath));\n\n\tfor (const file of diffFiles) {\n\t\tconst vscodeFile = path.join(PROJECT_ROOT, 'lib/vscode', file);\n\t\tif (!fs.existsSync(vscodeFile)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst hashSum = crypto.createHash('sha256');\n\t\thashSum.update(fs.readFileSync(vscodeFile));\n\t\tconst fileSha = hashSum.digest('hex');\n\n\t\tif (fileShas[file] !== fileSha) {\n\t\t\tconst sourceFile = path.join(PROJECT_ROOT, file);\n\t\t\tcp.execSync(`code -r -w -d ${vscodeFile} ${sourceFile}`);\n\t\t\tfileShas[file] = fileSha;\n\t\t\thasSourceUpdated = true;\n\t\t}\n\t}\n\n\tif (hasSourceUpdated) {\n\t\tfs.writeFileSync(shasPath, JSON.stringify(fileShas, null, 2));\n\t}\n};\n\nconst main = () => {\n\tif (fs.existsSync(path.join(PROJECT_ROOT, 'lib/vscode'))) {\n\t\treturn;\n\t}\n\n\tconst url = 'https://github.com/microsoft/vscode.git';\n\tconst ref = cp.execSync(`cat ${PROJECT_ROOT}/.VERSION`).toString().trim();\n\texecuteCommand('git', ['clone', '--depth', '1', '-b', ref, url, 'lib/vscode'], PROJECT_ROOT);\n\n\tconst locUrl = 'https://github.com/microsoft/vscode-loc.git';\n\texecuteCommand('git', ['clone', '--depth', '1', locUrl, 'lib/vscode-loc'], PROJECT_ROOT);\n\n\tfixSourceFiles();\n\n\tconst vscodePath = path.join(PROJECT_ROOT, 'lib/vscode');\n\texecuteCommand('npm', ['install'], vscodePath);\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/scripts/patch.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { PROJECT_ROOT, getAllFiles, patchSourceFile } from './utils.js';\n\nconst main = () => {\n\tconst sourceFiles = getAllFiles(path.join(PROJECT_ROOT, 'src'));\n\tif (fs.existsSync(path.join(PROJECT_ROOT, 'extensions'))) {\n\t\tsourceFiles.push(...getAllFiles(path.join(PROJECT_ROOT, 'extensions')));\n\t}\n\n\tfor (const sourceFile of sourceFiles) {\n\t\tpatchSourceFile(sourceFile);\n\t}\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/scripts/utils.js",
    "content": "import path from 'path';\nimport fs from 'fs-extra';\nimport cp from 'child_process';\n\nexport const PROJECT_ROOT = path.join(import.meta.dirname, '..');\n\nexport const executeCommand = (command, args, cwd) => {\n\tconst result = cp.spawnSync(command, args, { stdio: 'inherit', cwd });\n\tif (result.error) {\n\t\tthrow result.error;\n\t}\n};\n\nexport const getAllFiles = (directory) => {\n\treturn fs.readdirSync(directory).flatMap((name) => {\n\t\tconst filePath = path.join(directory, name);\n\t\tconst isDirectory = fs.statSync(filePath).isDirectory();\n\t\treturn isDirectory ? getAllFiles(filePath) : filePath;\n\t});\n};\n\nexport const patchSourceFile = (sourceFile) => {\n\tconst baseFile = path.relative(PROJECT_ROOT, path.resolve(sourceFile));\n\tconst vscodeFile = path.join(PROJECT_ROOT, 'lib/vscode', baseFile);\n\tfs.writeFileSync(vscodeFile, fs.readFileSync(sourceFile));\n};\n"
  },
  {
    "path": "vscode-web/scripts/watch/extensions.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport { executeCommand, PROJECT_ROOT } from '../utils.js';\n\nconst main = () => {\n\tconst cwd = path.join(PROJECT_ROOT, 'lib/vscode');\n\texecuteCommand('npm', ['run', 'watch-web'], cwd);\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/scripts/watch/source.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport chokidar from 'chokidar';\nimport { PROJECT_ROOT, patchSourceFile } from '../utils.js';\n\nconst fileChangeHandler = (_event, file) => {\n\tif (fs.statSync(file).isFile()) {\n\t\tpatchSourceFile(file);\n\t\tconsole.log(`${path.relative(PROJECT_ROOT, file)} patched`);\n\t}\n};\n\nconst main = () => {\n\tconst srcWatcher = chokidar.watch(path.join(PROJECT_ROOT, 'src'));\n\tsrcWatcher.on('all', fileChangeHandler);\n\n\tif (fs.existsSync(path.join(PROJECT_ROOT, 'extensions'))) {\n\t\tconst extensionsWatcher = chokidar.watch(path.join(PROJECT_ROOT, 'extensions'));\n\t\textensionsWatcher.on('all', fileChangeHandler);\n\t}\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/scripts/watch/vscode.js",
    "content": "#!/usr/bin/env node\n\nimport path from 'path';\nimport { executeCommand, PROJECT_ROOT } from '../utils.js';\n\nconst main = () => {\n\tconst cwd = path.join(PROJECT_ROOT, 'lib/vscode');\n\texecuteCommand('npm', ['run', 'watch'], cwd);\n};\n\nmain();\n"
  },
  {
    "path": "vscode-web/src/setup.d.ts",
    "content": "/* eslint-disable no-var */\ndeclare var _VSCODE_WEB: {\n\tworkspace?: { folderUri?: any; workspaceUri?: any };\n\tworkspaceId?: string; // the identifier to distinguish workspace\n\tworkspaceLabel?: string; // the label shown on explorer\n\thideTextFileLabelDecorations?: boolean; // whether hide the readonly icon for readonly files\n\tallowEditorLabelOverride?: boolean; // whether allow override editor label\n\t// custom builtin extensions, types see IBundledExtension[]\n\tbuiltinExtensions?: any[] | ((builtinExtensions: any[]) => any[]);\n\tlogo?: {\n\t\t// custom editor logo, hide logo if this is undefined\n\t\ticon?: string; // logo icon image url\n\t\ttitle?: string; // logo title\n\t\tonClick?: () => void; // logo click callback\n\t};\n\tonWorkbenchReady?: (scheme: string) => void; // workbench ready callback\n};\n"
  },
  {
    "path": "vscode-web/src/vs/base/common/network.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as errors from './errors.js';\nimport * as platform from './platform.js';\nimport { equalsIgnoreCase, startsWithIgnoreCase } from './strings.js';\nimport { URI } from './uri.js';\nimport * as paths from './path.js';\n\nexport namespace Schemas {\n\n\t/**\n\t * A schema that is used for models that exist in memory\n\t * only and that have no correspondence on a server or such.\n\t */\n\texport const inMemory = 'inmemory';\n\n\t/**\n\t * A schema that is used for setting files\n\t */\n\texport const vscode = 'vscode';\n\n\t/**\n\t * A schema that is used for internal private files\n\t */\n\texport const internal = 'private';\n\n\t/**\n\t * A walk-through document.\n\t */\n\texport const walkThrough = 'walkThrough';\n\n\t/**\n\t * An embedded code snippet.\n\t */\n\texport const walkThroughSnippet = 'walkThroughSnippet';\n\n\texport const http = 'http';\n\n\texport const https = 'https';\n\n\texport const file = 'file';\n\n\texport const mailto = 'mailto';\n\n\texport const untitled = 'untitled';\n\n\texport const data = 'data';\n\n\texport const command = 'command';\n\n\texport const vscodeRemote = 'vscode-remote';\n\n\texport const vscodeRemoteResource = 'vscode-remote-resource';\n\n\texport const vscodeManagedRemoteResource = 'vscode-managed-remote-resource';\n\n\texport const vscodeUserData = 'vscode-userdata';\n\n\texport const vscodeCustomEditor = 'vscode-custom-editor';\n\n\texport const vscodeNotebookCell = 'vscode-notebook-cell';\n\texport const vscodeNotebookCellMetadata = 'vscode-notebook-cell-metadata';\n\texport const vscodeNotebookCellMetadataDiff = 'vscode-notebook-cell-metadata-diff';\n\texport const vscodeNotebookCellOutput = 'vscode-notebook-cell-output';\n\texport const vscodeNotebookCellOutputDiff = 'vscode-notebook-cell-output-diff';\n\texport const vscodeNotebookMetadata = 'vscode-notebook-metadata';\n\texport const vscodeInteractiveInput = 'vscode-interactive-input';\n\n\texport const vscodeSettings = 'vscode-settings';\n\n\texport const vscodeWorkspaceTrust = 'vscode-workspace-trust';\n\n\texport const vscodeTerminal = 'vscode-terminal';\n\n\t/** Scheme used for code blocks in chat. */\n\texport const vscodeChatCodeBlock = 'vscode-chat-code-block';\n\n\t/** Scheme used for LHS of code compare (aka diff) blocks in chat. */\n\texport const vscodeChatCodeCompareBlock = 'vscode-chat-code-compare-block';\n\n\t/** Scheme used for the chat input editor. */\n\texport const vscodeChatEditor = 'vscode-chat-editor';\n\n\t/** Scheme used for the chat input part */\n\texport const vscodeChatInput = 'chatSessionInput';\n\n\t/** Scheme used for local chat session content */\n\texport const vscodeLocalChatSession = 'vscode-chat-session';\n\n\t/**\n\t * Scheme used internally for webviews that aren't linked to a resource (i.e. not custom editors)\n\t */\n\texport const webviewPanel = 'webview-panel';\n\n\t/**\n\t * Scheme used for loading the wrapper html and script in webviews.\n\t */\n\texport const vscodeWebview = 'vscode-webview';\n\n\t/**\n\t * Scheme used for extension pages\n\t */\n\texport const extension = 'extension';\n\n\t/**\n\t * Scheme used as a replacement of `file` scheme to load\n\t * files with our custom protocol handler (desktop only).\n\t */\n\texport const vscodeFileResource = 'vscode-file';\n\n\t/**\n\t * Scheme used for temporary resources\n\t */\n\texport const tmp = 'tmp';\n\n\t/**\n\t * Scheme used vs live share\n\t */\n\texport const vsls = 'vsls';\n\n\t/**\n\t * Scheme used for the Source Control commit input's text document\n\t */\n\texport const vscodeSourceControl = 'vscode-scm';\n\n\t/**\n\t * Scheme used for input box for creating comments.\n\t */\n\texport const commentsInput = 'comment';\n\n\t/**\n\t * Scheme used for special rendering of settings in the release notes\n\t */\n\texport const codeSetting = 'code-setting';\n\n\t/**\n\t * Scheme used for output panel resources\n\t */\n\texport const outputChannel = 'output';\n\n\t/**\n\t * Scheme used for the accessible view\n\t */\n\texport const accessibleView = 'accessible-view';\n\n\t/**\n\t * Used for snapshots of chat edits\n\t */\n\texport const chatEditingSnapshotScheme = 'chat-editing-snapshot-text-model';\n\texport const chatEditingModel = 'chat-editing-text-model';\n\n\t/**\n\t * Used for rendering multidiffs in copilot agent sessions\n\t */\n\texport const copilotPr = 'copilot-pr';\n}\n\nexport function matchesScheme(target: URI | string, scheme: string): boolean {\n\tif (URI.isUri(target)) {\n\t\treturn equalsIgnoreCase(target.scheme, scheme);\n\t} else {\n\t\treturn startsWithIgnoreCase(target, scheme + ':');\n\t}\n}\n\nexport function matchesSomeScheme(target: URI | string, ...schemes: string[]): boolean {\n\treturn schemes.some(scheme => matchesScheme(target, scheme));\n}\n\nexport const connectionTokenCookieName = 'vscode-tkn';\nexport const connectionTokenQueryName = 'tkn';\n\nclass RemoteAuthoritiesImpl {\n\tprivate readonly _hosts: { [authority: string]: string | undefined } = Object.create(null);\n\tprivate readonly _ports: { [authority: string]: number | undefined } = Object.create(null);\n\tprivate readonly _connectionTokens: { [authority: string]: string | undefined } = Object.create(null);\n\tprivate _preferredWebSchema: 'http' | 'https' = 'http';\n\tprivate _delegate: ((uri: URI) => URI) | null = null;\n\tprivate _serverRootPath: string = '/';\n\n\tsetPreferredWebSchema(schema: 'http' | 'https') {\n\t\tthis._preferredWebSchema = schema;\n\t}\n\n\tsetDelegate(delegate: (uri: URI) => URI): void {\n\t\tthis._delegate = delegate;\n\t}\n\n\tsetServerRootPath(product: { quality?: string; commit?: string }, serverBasePath: string | undefined): void {\n\t\tthis._serverRootPath = paths.posix.join(serverBasePath ?? '/', getServerProductSegment(product));\n\t}\n\n\tgetServerRootPath(): string {\n\t\treturn this._serverRootPath;\n\t}\n\n\tprivate get _remoteResourcesPath(): string {\n\t\treturn paths.posix.join(this._serverRootPath, Schemas.vscodeRemoteResource);\n\t}\n\n\tset(authority: string, host: string, port: number): void {\n\t\tthis._hosts[authority] = host;\n\t\tthis._ports[authority] = port;\n\t}\n\n\tsetConnectionToken(authority: string, connectionToken: string): void {\n\t\tthis._connectionTokens[authority] = connectionToken;\n\t}\n\n\tgetPreferredWebSchema(): 'http' | 'https' {\n\t\treturn this._preferredWebSchema;\n\t}\n\n\trewrite(uri: URI): URI {\n\t\tif (this._delegate) {\n\t\t\ttry {\n\t\t\t\treturn this._delegate(uri);\n\t\t\t} catch (err) {\n\t\t\t\terrors.onUnexpectedError(err);\n\t\t\t\treturn uri;\n\t\t\t}\n\t\t}\n\t\tconst authority = uri.authority;\n\t\tlet host = this._hosts[authority];\n\t\tif (host && host.indexOf(':') !== -1 && host.indexOf('[') === -1) {\n\t\t\thost = `[${host}]`;\n\t\t}\n\t\tconst port = this._ports[authority];\n\t\tconst connectionToken = this._connectionTokens[authority];\n\t\tlet query = `path=${encodeURIComponent(uri.path)}`;\n\t\tif (typeof connectionToken === 'string') {\n\t\t\tquery += `&${connectionTokenQueryName}=${encodeURIComponent(connectionToken)}`;\n\t\t}\n\t\treturn URI.from({\n\t\t\tscheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,\n\t\t\tauthority: `${host}:${port}`,\n\t\t\tpath: this._remoteResourcesPath,\n\t\t\tquery\n\t\t});\n\t}\n}\n\nexport const RemoteAuthorities = new RemoteAuthoritiesImpl();\n\nexport function getServerProductSegment(product: { quality?: string; commit?: string }) {\n\treturn `${product.quality ?? 'oss'}-${product.commit ?? 'dev'}`;\n}\n\n/**\n * A string pointing to a path inside the app. It should not begin with ./ or ../\n */\nexport type AppResourcePath = (\n\t`a${string}` | `b${string}` | `c${string}` | `d${string}` | `e${string}` | `f${string}`\n\t| `g${string}` | `h${string}` | `i${string}` | `j${string}` | `k${string}` | `l${string}`\n\t| `m${string}` | `n${string}` | `o${string}` | `p${string}` | `q${string}` | `r${string}`\n\t| `s${string}` | `t${string}` | `u${string}` | `v${string}` | `w${string}` | `x${string}`\n\t| `y${string}` | `z${string}`\n);\n\nexport const builtinExtensionsPath: AppResourcePath = 'vs/../../extensions';\n/* below codes are changed by github1s */\n// Cloudflare Pages cannot upload `node_modules`, we renamed it to `dependencies`\nexport const nodeModulesPath: AppResourcePath = 'vs/../../dependencies';\n/* above codes are changed by github1s */\nexport const nodeModulesAsarPath: AppResourcePath = 'vs/../../node_modules.asar';\nexport const nodeModulesAsarUnpackedPath: AppResourcePath = 'vs/../../node_modules.asar.unpacked';\n\nexport const VSCODE_AUTHORITY = 'vscode-app';\n\nclass FileAccessImpl {\n\n\tprivate static readonly FALLBACK_AUTHORITY = VSCODE_AUTHORITY;\n\n\t/**\n\t * Returns a URI to use in contexts where the browser is responsible\n\t * for loading (e.g. fetch()) or when used within the DOM.\n\t *\n\t * **Note:** use `dom.ts#asCSSUrl` whenever the URL is to be used in CSS context.\n\t */\n\tasBrowserUri(resourcePath: AppResourcePath | ''): URI {\n\t\tconst uri = this.toUri(resourcePath);\n\t\treturn this.uriToBrowserUri(uri);\n\t}\n\n\t/**\n\t * Returns a URI to use in contexts where the browser is responsible\n\t * for loading (e.g. fetch()) or when used within the DOM.\n\t *\n\t * **Note:** use `dom.ts#asCSSUrl` whenever the URL is to be used in CSS context.\n\t */\n\turiToBrowserUri(uri: URI): URI {\n\t\t// Handle remote URIs via `RemoteAuthorities`\n\t\tif (uri.scheme === Schemas.vscodeRemote) {\n\t\t\treturn RemoteAuthorities.rewrite(uri);\n\t\t}\n\n\t\t// Convert to `vscode-file` resource..\n\t\tif (\n\t\t\t// ...only ever for `file` resources\n\t\t\turi.scheme === Schemas.file &&\n\t\t\t(\n\t\t\t\t// ...and we run in native environments\n\t\t\t\tplatform.isNative ||\n\t\t\t\t// ...or web worker extensions on desktop\n\t\t\t\t(platform.webWorkerOrigin === `${Schemas.vscodeFileResource}://${FileAccessImpl.FALLBACK_AUTHORITY}`)\n\t\t\t)\n\t\t) {\n\t\t\treturn uri.with({\n\t\t\t\tscheme: Schemas.vscodeFileResource,\n\t\t\t\t// We need to provide an authority here so that it can serve\n\t\t\t\t// as origin for network and loading matters in chromium.\n\t\t\t\t// If the URI is not coming with an authority already, we\n\t\t\t\t// add our own\n\t\t\t\tauthority: uri.authority || FileAccessImpl.FALLBACK_AUTHORITY,\n\t\t\t\tquery: null,\n\t\t\t\tfragment: null\n\t\t\t});\n\t\t}\n\n\t\treturn uri;\n\t}\n\n\t/**\n\t * Returns the `file` URI to use in contexts where node.js\n\t * is responsible for loading.\n\t */\n\tasFileUri(resourcePath: AppResourcePath | ''): URI {\n\t\tconst uri = this.toUri(resourcePath);\n\t\treturn this.uriToFileUri(uri);\n\t}\n\n\t/**\n\t * Returns the `file` URI to use in contexts where node.js\n\t * is responsible for loading.\n\t */\n\turiToFileUri(uri: URI): URI {\n\t\t// Only convert the URI if it is `vscode-file:` scheme\n\t\tif (uri.scheme === Schemas.vscodeFileResource) {\n\t\t\treturn uri.with({\n\t\t\t\tscheme: Schemas.file,\n\t\t\t\t// Only preserve the `authority` if it is different from\n\t\t\t\t// our fallback authority. This ensures we properly preserve\n\t\t\t\t// Windows UNC paths that come with their own authority.\n\t\t\t\tauthority: uri.authority !== FileAccessImpl.FALLBACK_AUTHORITY ? uri.authority : null,\n\t\t\t\tquery: null,\n\t\t\t\tfragment: null\n\t\t\t});\n\t\t}\n\n\t\treturn uri;\n\t}\n\n\tprivate toUri(uriOrModule: URI | string): URI {\n\t\tif (URI.isUri(uriOrModule)) {\n\t\t\treturn uriOrModule;\n\t\t}\n\n\t\tif (globalThis._VSCODE_FILE_ROOT) {\n\t\t\tconst rootUriOrPath = globalThis._VSCODE_FILE_ROOT;\n\n\t\t\t// File URL (with scheme)\n\t\t\tif (/^\\w[\\w\\d+.-]*:\\/\\//.test(rootUriOrPath)) {\n\t\t\t\treturn URI.joinPath(URI.parse(rootUriOrPath, true), uriOrModule);\n\t\t\t}\n\n\t\t\t// File Path (no scheme)\n\t\t\tconst modulePath = paths.join(rootUriOrPath, uriOrModule);\n\t\t\treturn URI.file(modulePath);\n\t\t}\n\n\t\tthrow new Error('Cannot determine URI for module id!');\n\t}\n}\n\nexport const FileAccess = new FileAccessImpl();\n\nexport const CacheControlheaders: Record<string, string> = Object.freeze({\n\t'Cache-Control': 'no-cache, no-store'\n});\n\nexport const DocumentPolicyheaders: Record<string, string> = Object.freeze({\n\t'Document-Policy': 'include-js-call-stacks-in-crash-reports'\n});\n\nexport namespace COI {\n\n\tconst coiHeaders = new Map<'3' | '2' | '1' | string, Record<string, string>>([\n\t\t['1', { 'Cross-Origin-Opener-Policy': 'same-origin' }],\n\t\t['2', { 'Cross-Origin-Embedder-Policy': 'require-corp' }],\n\t\t['3', { 'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Embedder-Policy': 'require-corp' }],\n\t]);\n\n\texport const CoopAndCoep = Object.freeze(coiHeaders.get('3'));\n\n\tconst coiSearchParamName = 'vscode-coi';\n\n\t/**\n\t * Extract desired headers from `vscode-coi` invocation\n\t */\n\texport function getHeadersFromQuery(url: string | URI | URL): Record<string, string> | undefined {\n\t\tlet params: URLSearchParams | undefined;\n\t\tif (typeof url === 'string') {\n\t\t\tparams = new URL(url).searchParams;\n\t\t} else if (url instanceof URL) {\n\t\t\tparams = url.searchParams;\n\t\t} else if (URI.isUri(url)) {\n\t\t\tparams = new URL(url.toString(true)).searchParams;\n\t\t}\n\t\tconst value = params?.get(coiSearchParamName);\n\t\tif (!value) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn coiHeaders.get(value);\n\t}\n\n\t/**\n\t * Add the `vscode-coi` query attribute based on wanting `COOP` and `COEP`. Will be a noop when `crossOriginIsolated`\n\t * isn't enabled the current context\n\t */\n\texport function addSearchParam(urlOrSearch: URLSearchParams | Record<string, string>, coop: boolean, coep: boolean): void {\n\t\tif (!(globalThis as typeof globalThis & { crossOriginIsolated?: boolean }).crossOriginIsolated) {\n\t\t\t// depends on the current context being COI\n\t\t\treturn;\n\t\t}\n\t\tconst value = coop && coep ? '3' : coep ? '2' : '1';\n\t\tif (urlOrSearch instanceof URLSearchParams) {\n\t\t\turlOrSearch.set(coiSearchParamName, value);\n\t\t} else {\n\t\t\turlOrSearch[coiSearchParamName] = value;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport './media/activitybarpart.css';\nimport './media/activityaction.css';\nimport { localize, localize2 } from '../../../../nls.js';\nimport { ActionsOrientation } from '../../../../base/browser/ui/actionbar/actionbar.js';\nimport { Part } from '../../part.js';\nimport { ActivityBarPosition, IWorkbenchLayoutService, LayoutSettings, Parts, Position } from '../../../services/layout/browser/layoutService.js';\nimport { IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';\nimport { DisposableStore, MutableDisposable } from '../../../../base/common/lifecycle.js';\nimport { ToggleSidebarPositionAction, ToggleSidebarVisibilityAction } from '../../actions/layoutActions.js';\nimport { IThemeService, IColorTheme, registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nimport { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BORDER, ACTIVITY_BAR_ACTIVE_FOCUS_BORDER } from '../../../common/theme.js';\nimport { activeContrastBorder, contrastBorder, focusBorder } from '../../../../platform/theme/common/colorRegistry.js';\nimport { addDisposableListener, append, EventType, isAncestor, $, clearNode } from '../../../../base/browser/dom.js';\nimport { assertReturnsDefined } from '../../../../base/common/types.js';\nimport { CustomMenubarControl } from '../titlebar/menubarControl.js';\nimport { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';\nimport { getMenuBarVisibility, MenuSettings } from '../../../../platform/window/common/window.js';\nimport { IAction, Separator, SubmenuAction, toAction } from '../../../../base/common/actions.js';\nimport { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';\nimport { KeyCode } from '../../../../base/common/keyCodes.js';\nimport { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js';\nimport { GestureEvent } from '../../../../base/browser/touch.js';\nimport { IPaneCompositePart } from '../paneCompositePart.js';\nimport { IPaneCompositeBarOptions, PaneCompositeBar } from '../paneCompositeBar.js';\nimport { GlobalCompositeBar } from '../globalCompositeBar.js';\nimport { IStorageService } from '../../../../platform/storage/common/storage.js';\nimport { Action2, IMenuService, MenuId, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';\nimport { ContextKeyExpr, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';\nimport { Categories } from '../../../../platform/action/common/actionCommonCategories.js';\nimport { getContextMenuActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';\nimport { IViewDescriptorService, ViewContainerLocation, ViewContainerLocationToString } from '../../../common/views.js';\nimport { IExtensionService } from '../../../services/extensions/common/extensions.js';\nimport { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';\nimport { IViewsService } from '../../../services/views/common/viewsService.js';\nimport { SwitchCompositeViewAction } from '../compositeBarActions.js';\n\nexport class ActivitybarPart extends Part {\n\n\tstatic readonly ACTION_HEIGHT = 48;\n\n\tstatic readonly pinnedViewContainersKey = 'workbench.activity.pinnedViewlets2';\n\tstatic readonly placeholderViewContainersKey = 'workbench.activity.placeholderViewlets';\n\tstatic readonly viewContainersWorkspaceStateKey = 'workbench.activity.viewletsWorkspaceState';\n\n\t//#region IView\n\n\treadonly minimumWidth: number = 48;\n\treadonly maximumWidth: number = 48;\n\treadonly minimumHeight: number = 0;\n\treadonly maximumHeight: number = Number.POSITIVE_INFINITY;\n\n\t//#endregion\n\n\tprivate readonly compositeBar = this._register(new MutableDisposable<PaneCompositeBar>());\n\tprivate content: HTMLElement | undefined;\n\n\tconstructor(\n\t\tprivate readonly paneCompositePart: IPaneCompositePart,\n\t\t@IInstantiationService private readonly instantiationService: IInstantiationService,\n\t\t@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,\n\t\t@IThemeService themeService: IThemeService,\n\t\t@IStorageService storageService: IStorageService,\n\t) {\n\t\tsuper(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);\n\t}\n\n\tprivate createCompositeBar(): PaneCompositeBar {\n\t\treturn this.instantiationService.createInstance(ActivityBarCompositeBar, {\n\t\t\tpartContainerClass: 'activitybar',\n\t\t\tpinnedViewContainersKey: ActivitybarPart.pinnedViewContainersKey,\n\t\t\tplaceholderViewContainersKey: ActivitybarPart.placeholderViewContainersKey,\n\t\t\tviewContainersWorkspaceStateKey: ActivitybarPart.viewContainersWorkspaceStateKey,\n\t\t\torientation: ActionsOrientation.VERTICAL,\n\t\t\ticon: true,\n\t\t\ticonSize: 24,\n\t\t\tactivityHoverOptions: {\n\t\t\t\tposition: () => this.layoutService.getSideBarPosition() === Position.LEFT ? HoverPosition.RIGHT : HoverPosition.LEFT,\n\t\t\t},\n\t\t\tpreventLoopNavigation: true,\n\t\t\trecomputeSizes: false,\n\t\t\tfillExtraContextMenuActions: (actions, e?: MouseEvent | GestureEvent) => { },\n\t\t\tcompositeSize: 52,\n\t\t\tcolors: (theme: IColorTheme) => ({\n\t\t\t\tactiveForegroundColor: theme.getColor(ACTIVITY_BAR_FOREGROUND),\n\t\t\t\tinactiveForegroundColor: theme.getColor(ACTIVITY_BAR_INACTIVE_FOREGROUND),\n\t\t\t\tactiveBorderColor: theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER),\n\t\t\t\tactiveBackground: theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND),\n\t\t\t\tbadgeBackground: theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND),\n\t\t\t\tbadgeForeground: theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND),\n\t\t\t\tdragAndDropBorder: theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BORDER),\n\t\t\t\tactiveBackgroundColor: undefined, inactiveBackgroundColor: undefined, activeBorderBottomColor: undefined,\n\t\t\t}),\n\t\t\toverflowActionSize: ActivitybarPart.ACTION_HEIGHT,\n\t\t}, Parts.ACTIVITYBAR_PART, this.paneCompositePart, true);\n\t}\n\n\tprotected override createContentArea(parent: HTMLElement): HTMLElement {\n\t\tthis.element = parent;\n\t\tthis.content = append(this.element, $('.content'));\n\n\t\tif (this.layoutService.isVisible(Parts.ACTIVITYBAR_PART)) {\n\t\t\tthis.show();\n\t\t}\n\n\t\treturn this.content;\n\t}\n\n\tgetPinnedPaneCompositeIds(): string[] {\n\t\treturn this.compositeBar.value?.getPinnedPaneCompositeIds() ?? [];\n\t}\n\n\tgetVisiblePaneCompositeIds(): string[] {\n\t\treturn this.compositeBar.value?.getVisiblePaneCompositeIds() ?? [];\n\t}\n\n\tgetPaneCompositeIds(): string[] {\n\t\treturn this.compositeBar.value?.getPaneCompositeIds() ?? [];\n\t}\n\n\tfocus(): void {\n\t\tthis.compositeBar.value?.focus();\n\t}\n\n\toverride updateStyles(): void {\n\t\tsuper.updateStyles();\n\n\t\tconst container = assertReturnsDefined(this.getContainer());\n\t\tconst background = this.getColor(ACTIVITY_BAR_BACKGROUND) || '';\n\t\tcontainer.style.backgroundColor = background;\n\n\t\tconst borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder) || '';\n\t\tcontainer.classList.toggle('bordered', !!borderColor);\n\t\tcontainer.style.borderColor = borderColor ? borderColor : '';\n\t}\n\n\tshow(focus?: boolean): void {\n\t\tif (!this.content) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.compositeBar.value) {\n\t\t\tthis.compositeBar.value = this.createCompositeBar();\n\t\t\tthis.compositeBar.value.create(this.content);\n\n\t\t\tif (this.dimension) {\n\t\t\t\tthis.layout(this.dimension.width, this.dimension.height);\n\t\t\t}\n\t\t}\n\n\t\tif (focus) {\n\t\t\tthis.focus();\n\t\t}\n\t}\n\n\thide(): void {\n\t\tif (!this.compositeBar.value) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.compositeBar.clear();\n\n\t\tif (this.content) {\n\t\t\tclearNode(this.content);\n\t\t}\n\t}\n\n\toverride layout(width: number, height: number): void {\n\t\tsuper.layout(width, height, 0, 0);\n\n\t\tif (!this.compositeBar.value) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Layout contents\n\t\tconst contentAreaSize = super.layoutContents(width, height).contentSize;\n\n\t\t// Layout composite bar\n\t\tthis.compositeBar.value.layout(width, contentAreaSize.height);\n\t}\n\n\ttoJSON(): object {\n\t\treturn {\n\t\t\ttype: Parts.ACTIVITYBAR_PART\n\t\t};\n\t}\n}\n\nexport class ActivityBarCompositeBar extends PaneCompositeBar {\n\n\tprivate element: HTMLElement | undefined;\n\n\tprivate readonly menuBar = this._register(new MutableDisposable<CustomMenubarControl>());\n\tprivate menuBarContainer: HTMLElement | undefined;\n\tprivate compositeBarContainer: HTMLElement | undefined;\n\tprivate readonly globalCompositeBar: GlobalCompositeBar | undefined;\n\n\tprivate readonly keyboardNavigationDisposables = this._register(new DisposableStore());\n\n\tconstructor(\n\t\toptions: IPaneCompositeBarOptions,\n\t\tpart: Parts,\n\t\tpaneCompositePart: IPaneCompositePart,\n\t\tshowGlobalActivities: boolean,\n\t\t@IInstantiationService instantiationService: IInstantiationService,\n\t\t@IStorageService storageService: IStorageService,\n\t\t@IExtensionService extensionService: IExtensionService,\n\t\t@IViewDescriptorService viewDescriptorService: IViewDescriptorService,\n\t\t@IViewsService viewService: IViewsService,\n\t\t@IContextKeyService contextKeyService: IContextKeyService,\n\t\t@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,\n\t\t@IConfigurationService private readonly configurationService: IConfigurationService,\n\t\t@IMenuService private readonly menuService: IMenuService,\n\t\t@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,\n\t) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\tfillExtraContextMenuActions: (actions, e) => {\n\t\t\t\toptions.fillExtraContextMenuActions(actions, e);\n\t\t\t\tthis.fillContextMenuActions(actions, e);\n\t\t\t}\n\t\t}, part, paneCompositePart, instantiationService, storageService, extensionService, viewDescriptorService, viewService, contextKeyService, environmentService, layoutService);\n\n\t\tif (showGlobalActivities) {\n\t\t\tthis.globalCompositeBar = this._register(instantiationService.createInstance(GlobalCompositeBar, () => this.getContextMenuActions(), (theme: IColorTheme) => this.options.colors(theme), this.options.activityHoverOptions));\n\t\t}\n\n\t\t// Register for configuration changes\n\t\tthis._register(this.configurationService.onDidChangeConfiguration(e => {\n\t\t\tif (e.affectsConfiguration(MenuSettings.MenuBarVisibility)) {\n\t\t\t\tif (getMenuBarVisibility(this.configurationService) === 'compact') {\n\t\t\t\t\tthis.installMenubar();\n\t\t\t\t} else {\n\t\t\t\t\tthis.uninstallMenubar();\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\t}\n\n\tprivate fillContextMenuActions(actions: IAction[], e?: MouseEvent | GestureEvent) {\n\t\t// Menu\n\t\tconst menuBarVisibility = getMenuBarVisibility(this.configurationService);\n\t\tif (menuBarVisibility === 'compact' || menuBarVisibility === 'hidden' || menuBarVisibility === 'toggle') {\n\t\t\tactions.unshift(...[toAction({ id: 'toggleMenuVisibility', label: localize('menu', \"Menu\"), checked: menuBarVisibility === 'compact', run: () => this.configurationService.updateValue(MenuSettings.MenuBarVisibility, menuBarVisibility === 'compact' ? 'toggle' : 'compact') }), new Separator()]);\n\t\t}\n\n\t\tif (menuBarVisibility === 'compact' && this.menuBarContainer && e?.target) {\n\t\t\tif (isAncestor(e.target as Node, this.menuBarContainer)) {\n\t\t\t\tactions.unshift(...[toAction({ id: 'hideCompactMenu', label: localize('hideMenu', \"Hide Menu\"), run: () => this.configurationService.updateValue(MenuSettings.MenuBarVisibility, 'toggle') }), new Separator()]);\n\t\t\t}\n\t\t}\n\n\t\t// Global Composite Bar\n\t\tif (this.globalCompositeBar) {\n\t\t\tactions.push(new Separator());\n\t\t\tactions.push(...this.globalCompositeBar.getContextMenuActions());\n\t\t}\n\t\tactions.push(new Separator());\n\t\tactions.push(...this.getActivityBarContextMenuActions());\n\t}\n\n\tprivate uninstallMenubar() {\n\t\tif (this.menuBar.value) {\n\t\t\tthis.menuBar.value = undefined;\n\t\t}\n\n\t\tif (this.menuBarContainer) {\n\t\t\tthis.menuBarContainer.remove();\n\t\t\tthis.menuBarContainer = undefined;\n\t\t}\n\t}\n\n\tprivate installMenubar() {\n\t\tif (this.menuBar.value) {\n\t\t\treturn; // prevent menu bar from installing twice #110720\n\t\t}\n\n\t\tthis.menuBarContainer = $('.menubar');\n\n\t\tconst content = assertReturnsDefined(this.element);\n\t\t/* below codes are changed by github1s */\n\t\tconst homeBarContainer = this.element?.querySelector('.home-bar');\n\t\tif (homeBarContainer) {\n\t\t\tcontent.insertBefore(this.menuBarContainer, homeBarContainer.nextSibling);\n\t\t} else {\n\t\t\tcontent.prepend(this.menuBarContainer);\n\t\t}\n\t\t/* above codes are changed by github1s */\n\n\t\t// Menubar: install a custom menu bar depending on configuration\n\t\tthis.menuBar.value = this._register(this.instantiationService.createInstance(CustomMenubarControl));\n\t\tthis.menuBar.value.create(this.menuBarContainer);\n\n\t}\n\n\tprivate registerKeyboardNavigationListeners(): void {\n\t\tthis.keyboardNavigationDisposables.clear();\n\n\t\t// Up/Down or Left/Right arrow on compact menu\n\t\tif (this.menuBarContainer) {\n\t\t\tthis.keyboardNavigationDisposables.add(addDisposableListener(this.menuBarContainer, EventType.KEY_DOWN, e => {\n\t\t\t\tconst kbEvent = new StandardKeyboardEvent(e);\n\t\t\t\tif (kbEvent.equals(KeyCode.DownArrow) || kbEvent.equals(KeyCode.RightArrow)) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\t// Up/Down on Activity Icons\n\t\tif (this.compositeBarContainer) {\n\t\t\tthis.keyboardNavigationDisposables.add(addDisposableListener(this.compositeBarContainer, EventType.KEY_DOWN, e => {\n\t\t\t\tconst kbEvent = new StandardKeyboardEvent(e);\n\t\t\t\tif (kbEvent.equals(KeyCode.DownArrow) || kbEvent.equals(KeyCode.RightArrow)) {\n\t\t\t\t\tthis.globalCompositeBar?.focus();\n\t\t\t\t} else if (kbEvent.equals(KeyCode.UpArrow) || kbEvent.equals(KeyCode.LeftArrow)) {\n\t\t\t\t\tthis.menuBar.value?.toggleFocus();\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\t// Up arrow on global icons\n\t\tif (this.globalCompositeBar) {\n\t\t\tthis.keyboardNavigationDisposables.add(addDisposableListener(this.globalCompositeBar.element, EventType.KEY_DOWN, e => {\n\t\t\t\tconst kbEvent = new StandardKeyboardEvent(e);\n\t\t\t\tif (kbEvent.equals(KeyCode.UpArrow) || kbEvent.equals(KeyCode.LeftArrow)) {\n\t\t\t\t\tthis.focus(this.getVisiblePaneCompositeIds().length - 1);\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\t}\n\n\toverride create(parent: HTMLElement): HTMLElement {\n\t\tthis.element = parent;\n\n\t\t/* below codes are changed by github1s */\n\t\tif (globalThis._VSCODE_WEB?.logo) {\n\t\t\tconst logo = globalThis._VSCODE_WEB.logo;\n\t\t\tconst homeBarContainer = document.createElement('div');\n\t\t\thomeBarContainer.className = 'home-bar';\n\t\t\tif (logo.icon) {\n\t\t\t\tconst logoImage = `url(${window.encodeURI(logo.icon)})`;\n\t\t\t\thomeBarContainer.style.maskImage = logoImage;\n\t\t\t\thomeBarContainer.style.webkitMaskImage = logoImage;\n\t\t\t}\n\t\t\tif (logo.title) {\n\t\t\t\thomeBarContainer.title = logo.title;\n\t\t\t}\n\t\t\tif (logo.onClick) {\n\t\t\t\thomeBarContainer.onclick = logo.onClick;\n\t\t\t\thomeBarContainer.classList.add('home-bar-clickable');\n\t\t\t}\n\t\t\tthis.element.prepend(homeBarContainer);\n\t\t}\n\t\t/* above codes are changed by github1s */\n\n\t\t// Install menubar if compact\n\t\tif (getMenuBarVisibility(this.configurationService) === 'compact') {\n\t\t\tthis.installMenubar();\n\t\t}\n\n\t\t// View Containers action bar\n\t\tthis.compositeBarContainer = super.create(this.element);\n\n\t\t// Global action bar\n\t\tif (this.globalCompositeBar) {\n\t\t\tthis.globalCompositeBar.create(this.element);\n\t\t}\n\n\t\t// Keyboard Navigation\n\t\tthis.registerKeyboardNavigationListeners();\n\n\t\treturn this.compositeBarContainer;\n\t}\n\n\toverride layout(width: number, height: number): void {\n\t\tif (this.menuBarContainer) {\n\t\t\tif (this.options.orientation === ActionsOrientation.VERTICAL) {\n\t\t\t\theight -= this.menuBarContainer.clientHeight;\n\t\t\t} else {\n\t\t\t\twidth -= this.menuBarContainer.clientWidth;\n\t\t\t}\n\t\t}\n\t\tif (this.globalCompositeBar) {\n\t\t\tif (this.options.orientation === ActionsOrientation.VERTICAL) {\n\t\t\t\theight -= (this.globalCompositeBar.size() * ActivitybarPart.ACTION_HEIGHT);\n\t\t\t} else {\n\t\t\t\twidth -= this.globalCompositeBar.element.clientWidth;\n\t\t\t}\n\t\t}\n\t\tsuper.layout(width, height);\n\t}\n\n\tgetActivityBarContextMenuActions(): IAction[] {\n\t\tconst activityBarPositionMenu = this.menuService.getMenuActions(MenuId.ActivityBarPositionMenu, this.contextKeyService, { shouldForwardArgs: true, renderShortTitle: true });\n\t\tconst positionActions = getContextMenuActions(activityBarPositionMenu).secondary;\n\t\tconst actions = [\n\t\t\tnew SubmenuAction('workbench.action.panel.position', localize('activity bar position', \"Activity Bar Position\"), positionActions),\n\t\t\ttoAction({ id: ToggleSidebarPositionAction.ID, label: ToggleSidebarPositionAction.getLabel(this.layoutService), run: () => this.instantiationService.invokeFunction(accessor => new ToggleSidebarPositionAction().run(accessor)) }),\n\t\t];\n\n\t\tif (this.part === Parts.SIDEBAR_PART) {\n\t\t\tactions.push(toAction({ id: ToggleSidebarVisibilityAction.ID, label: ToggleSidebarVisibilityAction.LABEL, run: () => this.instantiationService.invokeFunction(accessor => new ToggleSidebarVisibilityAction().run(accessor)) }));\n\t\t}\n\n\t\treturn actions;\n\t}\n\n}\n\nregisterAction2(class extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'workbench.action.activityBarLocation.default',\n\t\t\ttitle: {\n\t\t\t\t...localize2('positionActivityBarDefault', 'Move Activity Bar to Side'),\n\t\t\t\tmnemonicTitle: localize({ key: 'miDefaultActivityBar', comment: ['&& denotes a mnemonic'] }, \"&&Default\"),\n\t\t\t},\n\t\t\tshortTitle: localize('default', \"Default\"),\n\t\t\tcategory: Categories.View,\n\t\t\ttoggled: ContextKeyExpr.equals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.DEFAULT),\n\t\t\tmenu: [{\n\t\t\t\tid: MenuId.ActivityBarPositionMenu,\n\t\t\t\torder: 1\n\t\t\t}, {\n\t\t\t\tid: MenuId.CommandPalette,\n\t\t\t\twhen: ContextKeyExpr.notEquals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.DEFAULT),\n\t\t\t}]\n\t\t});\n\t}\n\trun(accessor: ServicesAccessor): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconfigurationService.updateValue(LayoutSettings.ACTIVITY_BAR_LOCATION, ActivityBarPosition.DEFAULT);\n\t}\n});\n\nregisterAction2(class extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'workbench.action.activityBarLocation.top',\n\t\t\ttitle: {\n\t\t\t\t...localize2('positionActivityBarTop', 'Move Activity Bar to Top'),\n\t\t\t\tmnemonicTitle: localize({ key: 'miTopActivityBar', comment: ['&& denotes a mnemonic'] }, \"&&Top\"),\n\t\t\t},\n\t\t\tshortTitle: localize('top', \"Top\"),\n\t\t\tcategory: Categories.View,\n\t\t\ttoggled: ContextKeyExpr.equals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.TOP),\n\t\t\tmenu: [{\n\t\t\t\tid: MenuId.ActivityBarPositionMenu,\n\t\t\t\torder: 2\n\t\t\t}, {\n\t\t\t\tid: MenuId.CommandPalette,\n\t\t\t\twhen: ContextKeyExpr.notEquals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.TOP),\n\t\t\t}]\n\t\t});\n\t}\n\trun(accessor: ServicesAccessor): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconfigurationService.updateValue(LayoutSettings.ACTIVITY_BAR_LOCATION, ActivityBarPosition.TOP);\n\t}\n});\n\nregisterAction2(class extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'workbench.action.activityBarLocation.bottom',\n\t\t\ttitle: {\n\t\t\t\t...localize2('positionActivityBarBottom', 'Move Activity Bar to Bottom'),\n\t\t\t\tmnemonicTitle: localize({ key: 'miBottomActivityBar', comment: ['&& denotes a mnemonic'] }, \"&&Bottom\"),\n\t\t\t},\n\t\t\tshortTitle: localize('bottom', \"Bottom\"),\n\t\t\tcategory: Categories.View,\n\t\t\ttoggled: ContextKeyExpr.equals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.BOTTOM),\n\t\t\tmenu: [{\n\t\t\t\tid: MenuId.ActivityBarPositionMenu,\n\t\t\t\torder: 3\n\t\t\t}, {\n\t\t\t\tid: MenuId.CommandPalette,\n\t\t\t\twhen: ContextKeyExpr.notEquals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.BOTTOM),\n\t\t\t}]\n\t\t});\n\t}\n\trun(accessor: ServicesAccessor): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconfigurationService.updateValue(LayoutSettings.ACTIVITY_BAR_LOCATION, ActivityBarPosition.BOTTOM);\n\t}\n});\n\nregisterAction2(class extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'workbench.action.activityBarLocation.hide',\n\t\t\ttitle: {\n\t\t\t\t...localize2('hideActivityBar', 'Hide Activity Bar'),\n\t\t\t\tmnemonicTitle: localize({ key: 'miHideActivityBar', comment: ['&& denotes a mnemonic'] }, \"&&Hidden\"),\n\t\t\t},\n\t\t\tshortTitle: localize('hide', \"Hidden\"),\n\t\t\tcategory: Categories.View,\n\t\t\ttoggled: ContextKeyExpr.equals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.HIDDEN),\n\t\t\tmenu: [{\n\t\t\t\tid: MenuId.ActivityBarPositionMenu,\n\t\t\t\torder: 4\n\t\t\t}, {\n\t\t\t\tid: MenuId.CommandPalette,\n\t\t\t\twhen: ContextKeyExpr.notEquals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.HIDDEN),\n\t\t\t}]\n\t\t});\n\t}\n\trun(accessor: ServicesAccessor): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconfigurationService.updateValue(LayoutSettings.ACTIVITY_BAR_LOCATION, ActivityBarPosition.HIDDEN);\n\t}\n});\n\nMenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {\n\tsubmenu: MenuId.ActivityBarPositionMenu,\n\ttitle: localize('positionActivituBar', \"Activity Bar Position\"),\n\tgroup: '3_workbench_layout_move',\n\torder: 2\n});\n\nMenuRegistry.appendMenuItem(MenuId.ViewContainerTitleContext, {\n\tsubmenu: MenuId.ActivityBarPositionMenu,\n\ttitle: localize('positionActivituBar', \"Activity Bar Position\"),\n\twhen: ContextKeyExpr.or(\n\t\tContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar)),\n\t\tContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.AuxiliaryBar))\n\t),\n\tgroup: '3_workbench_layout_move',\n\torder: 1\n});\n\nregisterAction2(class extends SwitchCompositeViewAction {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'workbench.action.previousSideBarView',\n\t\t\ttitle: localize2('previousSideBarView', 'Previous Primary Side Bar View'),\n\t\t\tcategory: Categories.View,\n\t\t\tf1: true\n\t\t}, ViewContainerLocation.Sidebar, -1);\n\t}\n});\n\nregisterAction2(class extends SwitchCompositeViewAction {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'workbench.action.nextSideBarView',\n\t\t\ttitle: localize2('nextSideBarView', 'Next Primary Side Bar View'),\n\t\t\tcategory: Categories.View,\n\t\t\tf1: true\n\t\t}, ViewContainerLocation.Sidebar, 1);\n\t}\n});\n\nregisterAction2(\n\tclass FocusActivityBarAction extends Action2 {\n\t\tconstructor() {\n\t\t\tsuper({\n\t\t\t\tid: 'workbench.action.focusActivityBar',\n\t\t\t\ttitle: localize2('focusActivityBar', 'Focus Activity Bar'),\n\t\t\t\tcategory: Categories.View,\n\t\t\t\tf1: true\n\t\t\t});\n\t\t}\n\n\t\tasync run(accessor: ServicesAccessor): Promise<void> {\n\t\t\tconst layoutService = accessor.get(IWorkbenchLayoutService);\n\t\t\tlayoutService.focusPart(Parts.ACTIVITYBAR_PART);\n\t\t}\n\t});\n\nregisterThemingParticipant((theme, collector) => {\n\n\tconst activityBarActiveBorderColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER);\n\tif (activityBarActiveBorderColor) {\n\t\tcollector.addRule(`\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before {\n\t\t\t\tborder-left-color: ${activityBarActiveBorderColor};\n\t\t\t}\n\t\t`);\n\t}\n\n\tconst activityBarActiveFocusBorderColor = theme.getColor(ACTIVITY_BAR_ACTIVE_FOCUS_BORDER);\n\tif (activityBarActiveFocusBorderColor) {\n\t\tcollector.addRule(`\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:focus::before {\n\t\t\t\tvisibility: hidden;\n\t\t\t}\n\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:focus .active-item-indicator:before {\n\t\t\t\tvisibility: visible;\n\t\t\t\tborder-left-color: ${activityBarActiveFocusBorderColor};\n\t\t\t}\n\t\t`);\n\t}\n\n\tconst activityBarActiveBackgroundColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND);\n\tif (activityBarActiveBackgroundColor) {\n\t\tcollector.addRule(`\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator {\n\t\t\t\tz-index: 0;\n\t\t\t\tbackground-color: ${activityBarActiveBackgroundColor};\n\t\t\t}\n\t\t`);\n\t}\n\n\t// Styling with Outline color (e.g. high contrast theme)\n\tconst outline = theme.getColor(activeContrastBorder);\n\tif (outline) {\n\t\tcollector.addRule(`\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label::before{\n\t\t\t\tpadding: 6px;\n\t\t\t}\n\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active .action-label::before,\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:hover .action-label::before,\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .action-label::before,\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:hover .action-label::before {\n\t\t\t\toutline: 1px solid ${outline};\n\t\t\t}\n\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover .action-label::before {\n\t\t\t\toutline: 1px dashed ${outline};\n\t\t\t}\n\n\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .active-item-indicator:before {\n\t\t\t\tborder-left-color: ${outline};\n\t\t\t}\n\t\t`);\n\t}\n\n\t// Styling without outline color\n\telse {\n\t\tconst focusBorderColor = theme.getColor(focusBorder);\n\t\tif (focusBorderColor) {\n\t\t\tcollector.addRule(`\n\t\t\t\t.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .active-item-indicator::before {\n\t\t\t\t\t\tborder-left-color: ${focusBorderColor};\n\t\t\t\t\t}\n\t\t\t\t`);\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/* Part Element */\n.monaco-workbench .part.titlebar {\n\tdisplay: flex;\n\tflex-direction: row;\n}\n\n.monaco-workbench.mac .part.titlebar {\n\tflex-direction: row-reverse;\n}\n\n/* Root Container */\n.monaco-workbench .part.titlebar > .titlebar-container {\n\tbox-sizing: border-box;\n\toverflow: hidden;\n\tflex-shrink: 1;\n\tflex-grow: 1;\n\talign-items: center;\n\tjustify-content: space-between;\n\tuser-select: none;\n\t-webkit-user-select: none;\n\tdisplay: flex;\n\theight: 100%;\n\twidth: 100%;\n}\n\n/* Account for zooming */\n.monaco-workbench .part.titlebar > .titlebar-container.counter-zoom {\n\tzoom: calc(1.0 / var(--zoom-factor));\n}\n\n/* Platform specific root element */\n.monaco-workbench.mac .part.titlebar > .titlebar-container {\n\tline-height: 22px;\n}\n\n.monaco-workbench.web .part.titlebar > .titlebar-container,\n.monaco-workbench.windows .part.titlebar > .titlebar-container,\n.monaco-workbench.linux .part.titlebar > .titlebar-container {\n\tline-height: 22px;\n\tjustify-content: left;\n}\n\n.monaco-workbench.web.safari .part.titlebar,\n.monaco-workbench.web.safari .part.titlebar > .titlebar-container {\n\t/* Must be scoped to safari due to #148851 */\n\t/* Is required in safari due to #149476 */\n\toverflow: visible;\n}\n\n/* Draggable region */\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-drag-region {\n\ttop: 0;\n\tleft: 0;\n\tdisplay: block;\n\tposition: absolute;\n\twidth: 100%;\n\theight: 100%;\n\t-webkit-app-region: drag;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-left,\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center,\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right {\n\tdisplay: flex;\n\theight: 100%;\n\talign-items: center;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container.has-center > .titlebar-left {\n\torder: 0;\n\twidth: 20%;\n\tflex-grow: 2;\n\tjustify-content: flex-start;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container.has-center > .titlebar-center {\n\torder: 1;\n\twidth: 60%;\n\tmax-width: fit-content;\n\tmin-width: 0px;\n\tmargin: 0 10px;\n\t/* flex-shrink: 10; */\n\tjustify-content: center;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container.has-center > .titlebar-right {\n\torder: 2;\n\twidth: 20%;\n\tmin-width: min-content;\n\tflex-grow: 2;\n\tjustify-content: flex-end;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container:not(.has-center) > .titlebar-left {\n\tflex: 1 1 0%;\n\tmin-width: 0;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container:not(.has-center) > .titlebar-center {\n\tdisplay: none;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container:not(.has-center) > .titlebar-right {\n\tflex: 0 0 auto;\n\tpadding-left: 16px; /* ensure there is some space between title and controls */\n}\n\n/* Window title text */\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title {\n\tflex: 0 1 auto;\n\tfont-size: 12px;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\ttext-overflow: ellipsis;\n\tmargin-left: auto;\n\tmargin-right: auto;\n}\n\n.monaco-workbench.web .part.titlebar > .titlebar-container > .titlebar-center > .window-title,\n.monaco-workbench.windows .part.titlebar > .titlebar-container > .titlebar-center > .window-title,\n.monaco-workbench.linux .part.titlebar > .titlebar-container > .titlebar-center > .window-title {\n\tcursor: default;\n}\n\n.monaco-workbench.linux .part.titlebar > .titlebar-container > .titlebar-center > .window-title {\n\tfont-size: inherit;\n\t/* see #55435 */\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container .monaco-toolbar .actions-container {\n\tgap: 4px;\n}\n\n/* Window Title Menu */\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center {\n\tz-index: 2500;\n\t-webkit-app-region: no-drag;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center.hide {\n\tvisibility: hidden;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item > .action-label,\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item.monaco-dropdown-with-primary .action-label {\n\tcolor: var(--vscode-titleBar-activeForeground);\n}\n\n.monaco-workbench .part.titlebar.inactive > .titlebar-container > .titlebar-center > .window-title > .command-center > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item > .action-label,\n.monaco-workbench .part.titlebar.inactive > .titlebar-container > .titlebar-center > .window-title > .command-center > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item.monaco-dropdown-with-primary .action-label {\n\tcolor: var(--vscode-titleBar-inactiveForeground);\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item > .action-label {\n\tcolor: inherit;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center {\n\tdisplay: flex;\n\talign-items: stretch;\n\tcolor: var(--vscode-commandCenter-foreground);\n\tbackground-color: var(--vscode-commandCenter-background);\n\tborder: 1px solid var(--vscode-commandCenter-border);\n\toverflow: hidden;\n\tmargin: 0 6px;\n\tborder-top-left-radius: 6px;\n\tborder-bottom-left-radius: 6px;\n\tborder-top-right-radius: 6px;\n\tborder-bottom-right-radius: 6px;\n\theight: 22px;\n\twidth: 38vw;\n\tmax-width: 600px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center .action-item.command-center-quick-pick {\n\tdisplay: flex;\n\tjustify-content: start;\n\toverflow: hidden;\n\tmargin: auto;\n\tmax-width: 600px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center .action-item.command-center-quick-pick .search-icon {\n\tfont-size: 14px;\n\topacity: .8;\n\tmargin: auto 3px;\n\tcolor: var(--vscode-commandCenter-foreground);\n}\n\n.monaco-workbench .part.titlebar.inactive > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center .action-item.command-center-quick-pick .search-icon {\n\tcolor: var(--vscode-titleBar-inactiveForeground);\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center .action-item.command-center-quick-pick .search-label {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center.multiple {\n\tjustify-content: flex-start;\n\tpadding: 0 12px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center.multiple.active .action-label {\n\tbackground-color: inherit;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center:only-child {\n\tmargin-left: 0; /* no margin if there is only the command center, without nav buttons */\n}\n\n.monaco-workbench .part.titlebar.inactive > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center {\n\tcolor: var(--vscode-titleBar-inactiveForeground);\n\tborder-color: var(--vscode-commandCenter-inactiveBorder) !important;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center:HOVER {\n\tcolor: var(--vscode-commandCenter-activeForeground);\n\tbackground-color: var(--vscode-commandCenter-activeBackground);\n\tborder-color: var(--vscode-commandCenter-activeBorder);\n}\n\n/* Menubar */\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-left > .menubar {\n\t/* move menubar above drag region as negative z-index on drag region cause greyscale AA */\n\tz-index: 2500;\n\tmin-width: 36px;\n\tflex-wrap: nowrap;\n\torder: 2;\n}\n\n.monaco-workbench.web .part.titlebar > .titlebar-container > .titlebar-left > .menubar {\n\tmargin-left: 4px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container.counter-zoom .menubar .menubar-menu-button > .menubar-menu-items-holder.monaco-menu-container,\n.monaco-workbench .part.titlebar > .titlebar-container.counter-zoom .monaco-toolbar .dropdown-action-container {\n\tzoom: var(--zoom-factor); /* helps to position the menu properly when counter zooming */\n}\n\n/* Resizer */\n.monaco-workbench.windows .part.titlebar > .titlebar-container > .resizer,\n.monaco-workbench.linux .part.titlebar > .titlebar-container > .resizer {\n\t-webkit-app-region: no-drag;\n\tposition: absolute;\n\ttop: 0;\n\twidth: 100%;\n\theight: 4px;\n}\n\n.monaco-workbench.windows.fullscreen .part.titlebar > .titlebar-container > .resizer,\n.monaco-workbench.linux.fullscreen .part.titlebar > .titlebar-container > .resizer {\n\tdisplay: none;\n}\n\n/* App Icon */\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-left > .window-appicon {\n\twidth: 35px;\n\theight: 100%;\n\tposition: relative;\n\tz-index: 2500;\n\tflex-shrink: 0;\n\torder: 1;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-left > .window-appicon:not(.codicon) {\n\tbackground-image: url('../../../media/code-icon.svg');\n\tbackground-repeat: no-repeat;\n\tbackground-position: center center;\n\tbackground-size: 16px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-left > .window-appicon.codicon {\n\tline-height: 30px;\n}\n\n.monaco-workbench.fullscreen .part.titlebar > .titlebar-container > .titlebar-left > .window-appicon {\n\tdisplay: none;\n}\n\n/* Window Controls Container */\n.monaco-workbench .part.titlebar .window-controls-container {\n\tdisplay: flex;\n\tflex-grow: 0;\n\tflex-shrink: 0;\n\ttext-align: center;\n\tz-index: 3000;\n\t-webkit-app-region: no-drag;\n\twidth: 0px;\n\theight: 100%;\n}\n\n.monaco-workbench.fullscreen .part.titlebar .window-controls-container {\n\tdisplay: none;\n\tbackground-color: transparent;\n}\n\n/* Window Controls Container Web: Apply WCO environment variables (https://developer.mozilla.org/en-US/docs/Web/CSS/env#titlebar-area-x) */\n.monaco-workbench.web .part.titlebar .titlebar-right .window-controls-container {\n\twidth: calc(100vw - env(titlebar-area-width, 100vw) - env(titlebar-area-x, 0px));\n\theight: env(titlebar-area-height, 35px);\n}\n\n.monaco-workbench.web .part.titlebar .titlebar-left .window-controls-container {\n\twidth: env(titlebar-area-x, 0px);\n\theight: env(titlebar-area-height, 35px);\n}\n\n.monaco-workbench.web.mac .part.titlebar .titlebar-left .window-controls-container {\n\torder: 0;\n}\n\n.monaco-workbench.web.mac .part.titlebar .titlebar-right .window-controls-container {\n\torder: 1;\n}\n\n/* Window Controls Container Desktop: apply zoom friendly size */\n.monaco-workbench:not(.web):not(.mac) .part.titlebar .window-controls-container {\n\twidth: calc(138px / var(--zoom-factor, 1));\n}\n\n.monaco-workbench:not(.web):not(.mac) .part.titlebar .titlebar-container.counter-zoom .window-controls-container {\n\twidth: 138px;\n}\n\n.monaco-workbench.linux:not(.web) .part.titlebar .window-controls-container.wco-enabled {\n\twidth: calc(100vw - env(titlebar-area-width, 100vw) - env(titlebar-area-x, 0px));\n}\n\n.monaco-workbench:not(.web):not(.mac) .part.titlebar .titlebar-container:not(.counter-zoom) .window-controls-container * {\n\tzoom: calc(1 / var(--zoom-factor, 1));\n}\n\n.monaco-workbench:not(.web).mac .part.titlebar .window-controls-container {\n\twidth: 70px;\n}\n\n/* Window Control Icons */\n.monaco-workbench .part.titlebar .window-controls-container > .window-icon {\n\tdisplay: flex;\n\tjustify-content: center;\n\talign-items: center;\n\theight: 100%;\n\twidth: 46px;\n\tfont-size: 16px;\n\tcolor: var(--vscode-titleBar-activeForeground);\n}\n\n.monaco-workbench .part.titlebar.inactive .window-controls-container > .window-icon {\n\tcolor: var(--vscode-titleBar-inactiveForeground);\n}\n\n.monaco-workbench .part.titlebar .window-controls-container > .window-icon::before {\n\theight: 16px;\n\tline-height: 16px;\n}\n\n.monaco-workbench .part.titlebar .window-controls-container > .window-icon:hover {\n\tbackground-color: rgba(255, 255, 255, 0.1);\n}\n\n.monaco-workbench .part.titlebar.light .window-controls-container > .window-icon:hover {\n\tbackground-color: rgba(0, 0, 0, 0.1);\n}\n\n.monaco-workbench .part.titlebar .window-controls-container > .window-icon.window-close:hover {\n\tbackground-color: rgba(232, 17, 35, 0.9);\n}\n\n.monaco-workbench .part.titlebar .window-controls-container .window-icon.window-close:hover {\n\tcolor: white;\n}\n\n/* Action Tool Bar Controls */\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container {\n\tdisplay: none;\n\tpadding-right: 4px;\n\tflex-grow: 0;\n\tflex-shrink: 0;\n\ttext-align: center;\n\tposition: relative;\n\tz-index: 2500;\n\t-webkit-app-region: no-drag;\n\theight: 100%;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container {\n\tmargin-left: auto;\n}\n\n.monaco-workbench.mac:not(.web) .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container {\n\tright: 8px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container:not(.has-no-actions) {\n\tdisplay: flex;\n\tjustify-content: center;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .codicon {\n\tcolor: inherit;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .monaco-action-bar .action-item {\n\tdisplay: flex;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .monaco-action-bar .badge {\n\tmargin-left: 8px;\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .monaco-action-bar .action-item.icon .badge {\n\tmargin-left: 0px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .monaco-action-bar .badge .badge-content {\n\tpadding: 3px 5px;\n\tborder-radius: 11px;\n\tfont-size: 9px;\n\tmin-width: 11px;\n\theight: 16px;\n\tline-height: 11px;\n\tfont-weight: normal;\n\ttext-align: center;\n\tdisplay: inline-block;\n\tbox-sizing: border-box;\n\tposition: relative;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .monaco-action-bar .action-item.icon .badge.compact {\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tmargin: auto;\n\tleft: 0;\n\toverflow: hidden;\n\twidth: 100%;\n\theight: 100%;\n\tz-index: 2;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .monaco-action-bar .action-item.icon .badge.compact .badge-content::before {\n\tmask-size: 12px;\n\t-webkit-mask-size: 12px;\n\ttop: 2px;\n}\n\n.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-right > .action-toolbar-container .monaco-action-bar .action-item.icon .badge.compact .badge-content {\n\tposition: absolute;\n\ttop: 10px;\n\tright: 0px;\n\tfont-size: 9px;\n\tfont-weight: 600;\n\tmin-width: 12px;\n\theight: 12px;\n\tline-height: 12px;\n\tpadding: 0 2px;\n\tborder-radius: 16px;\n\ttext-align: center;\n}\n\n/* below codes are changed by github1s */\n.monaco-workbench .activitybar > .content > .home-bar {\n\topacity: 1;\n\theight: 48px;\n\tcursor: pointer;\n\tmask-repeat: no-repeat;\n\t-webkit-mask-repeat: no-repeat;\n\tmask-size: 50% 50%;\n\t-webkit-mask-size: 50% 50%;\n\tmask-position: 50% 50%;\n\t-webkit-mask-position: 50% 50%;\n\tbackground-color: var(--vscode-activityBar-foreground);\n}\n\n.monaco-workbench .activitybar > .content > .home-bar.home-bar-clickable:hover {\n\topacity: 0.7;\n}\n\n.monaco-workbench .activitybar > .content > .home-bar.home-bar-clickable:active {\n\topacity: 0.4;\n}\n/* above codes are changed by github1s */\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/browser/web.main.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { mark } from '../../base/common/performance.js';\nimport { domContentLoaded, detectFullscreen, getCookieValue, getWindow } from '../../base/browser/dom.js';\nimport { assertReturnsDefined } from '../../base/common/types.js';\nimport { ServiceCollection } from '../../platform/instantiation/common/serviceCollection.js';\nimport { ILogService, ConsoleLogger, getLogLevel, ILoggerService, ILogger } from '../../platform/log/common/log.js';\nimport { ConsoleLogInAutomationLogger } from '../../platform/log/browser/log.js';\nimport { Disposable, DisposableStore, toDisposable } from '../../base/common/lifecycle.js';\nimport { BrowserWorkbenchEnvironmentService, IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js';\nimport { Workbench } from './workbench.js';\nimport { RemoteFileSystemProviderClient } from '../services/remote/common/remoteFileSystemProviderClient.js';\nimport { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';\nimport { IProductService } from '../../platform/product/common/productService.js';\nimport product from '../../platform/product/common/product.js';\nimport { RemoteAgentService } from '../services/remote/browser/remoteAgentService.js';\nimport { RemoteAuthorityResolverService } from '../../platform/remote/browser/remoteAuthorityResolverService.js';\nimport { IRemoteAuthorityResolverService, RemoteConnectionType } from '../../platform/remote/common/remoteAuthorityResolver.js';\nimport { IRemoteAgentService } from '../services/remote/common/remoteAgentService.js';\nimport { IFileService } from '../../platform/files/common/files.js';\nimport { FileService } from '../../platform/files/common/fileService.js';\nimport { Schemas, connectionTokenCookieName } from '../../base/common/network.js';\nimport { IAnyWorkspaceIdentifier, IWorkspaceContextService, UNKNOWN_EMPTY_WINDOW_WORKSPACE, isTemporaryWorkspace, isWorkspaceIdentifier } from '../../platform/workspace/common/workspace.js';\nimport { IWorkbenchConfigurationService } from '../services/configuration/common/configuration.js';\nimport { onUnexpectedError } from '../../base/common/errors.js';\nimport { setFullscreen } from '../../base/browser/browser.js';\nimport { URI, UriComponents } from '../../base/common/uri.js';\nimport { WorkspaceService } from '../services/configuration/browser/configurationService.js';\nimport { ConfigurationCache } from '../services/configuration/common/configurationCache.js';\nimport { ISignService } from '../../platform/sign/common/sign.js';\nimport { SignService } from '../../platform/sign/browser/signService.js';\nimport { IWorkbenchConstructionOptions, IWorkbench, IWorkspace, ITunnel } from './web.api.js';\nimport { BrowserStorageService } from '../services/storage/browser/storageService.js';\nimport { IStorageService } from '../../platform/storage/common/storage.js';\nimport { toLocalISOString } from '../../base/common/date.js';\nimport { isWorkspaceToOpen, isFolderToOpen } from '../../platform/window/common/window.js';\nimport { getSingleFolderWorkspaceIdentifier, getWorkspaceIdentifier } from '../services/workspaces/browser/workspaces.js';\nimport { InMemoryFileSystemProvider } from '../../platform/files/common/inMemoryFilesystemProvider.js';\nimport { ICommandService } from '../../platform/commands/common/commands.js';\nimport { IndexedDBFileSystemProvider } from '../../platform/files/browser/indexedDBFileSystemProvider.js';\nimport { BrowserRequestService } from '../services/request/browser/requestService.js';\nimport { IRequestService } from '../../platform/request/common/request.js';\nimport { IUserDataInitializationService, IUserDataInitializer, UserDataInitializationService } from '../services/userData/browser/userDataInit.js';\nimport { UserDataSyncStoreManagementService } from '../../platform/userDataSync/common/userDataSyncStoreService.js';\nimport { IUserDataSyncStoreManagementService } from '../../platform/userDataSync/common/userDataSync.js';\nimport { ILifecycleService } from '../services/lifecycle/common/lifecycle.js';\nimport { Action2, MenuId, registerAction2 } from '../../platform/actions/common/actions.js';\nimport { IInstantiationService, ServicesAccessor } from '../../platform/instantiation/common/instantiation.js';\nimport { localize, localize2 } from '../../nls.js';\nimport { Categories } from '../../platform/action/common/actionCommonCategories.js';\nimport { IDialogService } from '../../platform/dialogs/common/dialogs.js';\nimport { IHostService } from '../services/host/browser/host.js';\nimport { IUriIdentityService } from '../../platform/uriIdentity/common/uriIdentity.js';\nimport { UriIdentityService } from '../../platform/uriIdentity/common/uriIdentityService.js';\nimport { BrowserWindow } from './window.js';\nimport { ITimerService } from '../services/timer/browser/timerService.js';\nimport { WorkspaceTrustEnablementService, WorkspaceTrustManagementService } from '../services/workspaces/common/workspaceTrust.js';\nimport { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService } from '../../platform/workspace/common/workspaceTrust.js';\nimport { HTMLFileSystemProvider } from '../../platform/files/browser/htmlFileSystemProvider.js';\nimport { IOpenerService } from '../../platform/opener/common/opener.js';\nimport { mixin, safeStringify } from '../../base/common/objects.js';\nimport { IndexedDB } from '../../base/browser/indexedDB.js';\nimport { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';\nimport { IProgressService } from '../../platform/progress/common/progress.js';\nimport { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js';\nimport { dirname, joinPath } from '../../base/common/resources.js';\nimport { IUserDataProfile, IUserDataProfilesService } from '../../platform/userDataProfile/common/userDataProfile.js';\nimport { IPolicyService } from '../../platform/policy/common/policy.js';\nimport { IRemoteExplorerService } from '../services/remote/common/remoteExplorerService.js';\nimport { DisposableTunnel, TunnelProtocol } from '../../platform/tunnel/common/tunnel.js';\nimport { ILabelService } from '../../platform/label/common/label.js';\nimport { UserDataProfileService } from '../services/userDataProfile/common/userDataProfileService.js';\nimport { IUserDataProfileService } from '../services/userDataProfile/common/userDataProfile.js';\nimport { BrowserUserDataProfilesService } from '../../platform/userDataProfile/browser/userDataProfile.js';\nimport { DeferredPromise, timeout } from '../../base/common/async.js';\nimport { windowLogGroup, windowLogId } from '../services/log/common/logConstants.js';\nimport { LogService } from '../../platform/log/common/logService.js';\nimport { IRemoteSocketFactoryService, RemoteSocketFactoryService } from '../../platform/remote/common/remoteSocketFactoryService.js';\nimport { BrowserSocketFactory } from '../../platform/remote/browser/browserSocketFactory.js';\nimport { VSBuffer } from '../../base/common/buffer.js';\nimport { IStoredWorkspace } from '../../platform/workspaces/common/workspaces.js';\nimport { UserDataProfileInitializer } from '../services/userDataProfile/browser/userDataProfileInit.js';\nimport { UserDataSyncInitializer } from '../services/userDataSync/browser/userDataSyncInit.js';\nimport { BrowserRemoteResourceLoader } from '../services/remote/browser/browserRemoteResourceHandler.js';\nimport { BufferLogger } from '../../platform/log/common/bufferLog.js';\nimport { FileLoggerService } from '../../platform/log/common/fileLog.js';\nimport { IEmbedderTerminalService } from '../services/terminal/common/embedderTerminalService.js';\nimport { BrowserSecretStorageService } from '../services/secrets/browser/secretStorageService.js';\nimport { EncryptionService } from '../services/encryption/browser/encryptionService.js';\nimport { IEncryptionService } from '../../platform/encryption/common/encryptionService.js';\nimport { ISecretStorageService } from '../../platform/secrets/common/secrets.js';\nimport { TunnelSource } from '../services/remote/common/tunnelModel.js';\nimport { mainWindow } from '../../base/browser/window.js';\nimport { INotificationService, Severity } from '../../platform/notification/common/notification.js';\nimport { IDefaultAccountService } from '../../platform/defaultAccount/common/defaultAccount.js';\nimport { DefaultAccountService } from '../services/accounts/common/defaultAccount.js';\nimport { AccountPolicyService } from '../services/policies/common/accountPolicyService.js';\n\nexport class BrowserMain extends Disposable {\n\n\tprivate readonly onWillShutdownDisposables = this._register(new DisposableStore());\n\tprivate readonly indexedDBFileSystemProviders: IndexedDBFileSystemProvider[] = [];\n\n\tconstructor(\n\t\tprivate readonly domElement: HTMLElement,\n\t\tprivate readonly configuration: IWorkbenchConstructionOptions\n\t) {\n\t\tsuper();\n\n\t\tthis.init();\n\t}\n\n\tprivate init(): void {\n\n\t\t// Browser config\n\t\tsetFullscreen(!!detectFullscreen(mainWindow), mainWindow);\n\t}\n\n\tasync open(): Promise<IWorkbench> {\n\n\t\t// Init services and wait for DOM to be ready in parallel\n\t\tconst [services] = await Promise.all([this.initServices(), domContentLoaded(getWindow(this.domElement))]);\n\n\t\t// Create Workbench\n\t\tconst workbench = new Workbench(this.domElement, undefined, services.serviceCollection, services.logService);\n\n\t\t// Listeners\n\t\tthis.registerListeners(workbench);\n\n\t\t// Startup\n\t\tconst instantiationService = workbench.startup();\n\n\t\t// Window\n\t\tthis._register(instantiationService.createInstance(BrowserWindow));\n\n\t\t// Logging\n\t\tservices.logService.trace('workbench#open with configuration', safeStringify(this.configuration));\n\n\t\t// Return API Facade\n\t\treturn instantiationService.invokeFunction(accessor => {\n\t\t\tconst commandService = accessor.get(ICommandService);\n\t\t\tconst lifecycleService = accessor.get(ILifecycleService);\n\t\t\tconst timerService = accessor.get(ITimerService);\n\t\t\tconst openerService = accessor.get(IOpenerService);\n\t\t\tconst productService = accessor.get(IProductService);\n\t\t\tconst progressService = accessor.get(IProgressService);\n\t\t\tconst environmentService = accessor.get(IBrowserWorkbenchEnvironmentService);\n\t\t\tconst instantiationService = accessor.get(IInstantiationService);\n\t\t\tconst remoteExplorerService = accessor.get(IRemoteExplorerService);\n\t\t\tconst labelService = accessor.get(ILabelService);\n\t\t\tconst embedderTerminalService = accessor.get(IEmbedderTerminalService);\n\t\t\tconst remoteAuthorityResolverService = accessor.get(IRemoteAuthorityResolverService);\n\t\t\tconst notificationService = accessor.get(INotificationService);\n\n\t\t\tasync function showMessage<T extends string>(severity: Severity, message: string, ...items: T[]): Promise<T | undefined> {\n\t\t\t\tconst choice = new DeferredPromise<T | undefined>();\n\t\t\t\tconst handle = notificationService.prompt(severity, message, items.map(item => ({\n\t\t\t\t\tlabel: item,\n\t\t\t\t\trun: () => choice.complete(item)\n\t\t\t\t})));\n\t\t\t\tconst disposable = handle.onDidClose(() => {\n\t\t\t\t\tchoice.complete(undefined);\n\t\t\t\t\tdisposable.dispose();\n\t\t\t\t});\n\t\t\t\tconst result = await choice.p;\n\t\t\t\thandle.close();\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tlet logger: DelayedLogChannel | undefined = undefined;\n\n\t\t\treturn {\n\t\t\t\tcommands: {\n\t\t\t\t\texecuteCommand: (command, ...args) => commandService.executeCommand(command, ...args)\n\t\t\t\t},\n\t\t\t\tenv: {\n\t\t\t\t\tasync getUriScheme(): Promise<string> {\n\t\t\t\t\t\treturn productService.urlProtocol;\n\t\t\t\t\t},\n\t\t\t\t\tasync retrievePerformanceMarks() {\n\t\t\t\t\t\tawait timerService.whenReady();\n\n\t\t\t\t\t\treturn timerService.getPerformanceMarks();\n\t\t\t\t\t},\n\t\t\t\t\tasync openUri(uri: URI | UriComponents): Promise<boolean> {\n\t\t\t\t\t\treturn openerService.open(URI.isUri(uri) ? uri : URI.from(uri), {});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tlogger: {\n\t\t\t\t\tlog: (level, message) => {\n\t\t\t\t\t\tif (!logger) {\n\t\t\t\t\t\t\tlogger = instantiationService.createInstance(DelayedLogChannel, 'webEmbedder', productService.embedderIdentifier || productService.nameShort, joinPath(dirname(environmentService.logFile), 'webEmbedder.log'));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlogger.log(level, message);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\twindow: {\n\t\t\t\t\twithProgress: (options, task) => progressService.withProgress(options, task),\n\t\t\t\t\tcreateTerminal: async (options) => embedderTerminalService.createTerminal(options),\n\t\t\t\t\tshowInformationMessage: (message, ...items) => showMessage(Severity.Info, message, ...items),\n\t\t\t\t},\n\t\t\t\tworkspace: {\n\t\t\t\t\tdidResolveRemoteAuthority: async () => {\n\t\t\t\t\t\tif (!this.configuration.remoteAuthority) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait remoteAuthorityResolverService.resolveAuthority(this.configuration.remoteAuthority);\n\t\t\t\t\t},\n\t\t\t\t\topenTunnel: async tunnelOptions => {\n\t\t\t\t\t\tconst tunnel = assertReturnsDefined(await remoteExplorerService.forward({\n\t\t\t\t\t\t\tremote: tunnelOptions.remoteAddress,\n\t\t\t\t\t\t\tlocal: tunnelOptions.localAddressPort,\n\t\t\t\t\t\t\tname: tunnelOptions.label,\n\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\tsource: TunnelSource.Extension,\n\t\t\t\t\t\t\t\tdescription: labelService.getHostLabel(Schemas.vscodeRemote, this.configuration.remoteAuthority)\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\televateIfNeeded: false,\n\t\t\t\t\t\t\tprivacy: tunnelOptions.privacy\n\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\tlabel: tunnelOptions.label,\n\t\t\t\t\t\t\televateIfNeeded: undefined,\n\t\t\t\t\t\t\tonAutoForward: undefined,\n\t\t\t\t\t\t\trequireLocalPort: undefined,\n\t\t\t\t\t\t\tprotocol: tunnelOptions.protocol === TunnelProtocol.Https ? tunnelOptions.protocol : TunnelProtocol.Http\n\t\t\t\t\t\t}));\n\n\t\t\t\t\t\tif (typeof tunnel === 'string') {\n\t\t\t\t\t\t\tthrow new Error(tunnel);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn new class extends DisposableTunnel implements ITunnel {\n\t\t\t\t\t\t\tdeclare localAddress: string;\n\t\t\t\t\t\t}({\n\t\t\t\t\t\t\tport: tunnel.tunnelRemotePort,\n\t\t\t\t\t\t\thost: tunnel.tunnelRemoteHost\n\t\t\t\t\t\t}, tunnel.localAddress, () => tunnel.dispose());\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tshutdown: () => lifecycleService.shutdown()\n\t\t\t} satisfies IWorkbench;\n\t\t});\n\t}\n\n\tprivate registerListeners(workbench: Workbench): void {\n\n\t\t// Workbench Lifecycle\n\t\tthis._register(workbench.onWillShutdown(() => this.onWillShutdownDisposables.clear()));\n\t\tthis._register(workbench.onDidShutdown(() => this.dispose()));\n\t}\n\n\tprivate async initServices(): Promise<{ serviceCollection: ServiceCollection; configurationService: IWorkbenchConfigurationService; logService: ILogService }> {\n\t\tconst serviceCollection = new ServiceCollection();\n\n\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\t\t//\n\t\t// NOTE: Please do NOT register services here. Use `registerSingleton()`\n\t\t//       from `workbench.common.main.ts` if the service is shared between\n\t\t//       desktop and web or `workbench.web.main.ts` if the service\n\t\t//       is web only.\n\t\t//\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n\t\tconst workspace = this.resolveWorkspace();\n\n\t\t// Product\n\t\tconst productService: IProductService = mixin({ _serviceBrand: undefined, ...product }, this.configuration.productConfiguration);\n\t\tserviceCollection.set(IProductService, productService);\n\n\t\t// Environment\n\t\tconst logsPath = URI.file(toLocalISOString(new Date()).replace(/-|:|\\.\\d+Z$/g, '')).with({ scheme: 'vscode-log' });\n\t\tconst environmentService = new BrowserWorkbenchEnvironmentService(workspace.id, logsPath, this.configuration, productService);\n\t\tserviceCollection.set(IBrowserWorkbenchEnvironmentService, environmentService);\n\n\t\t// Files\n\t\tconst fileLogger = new BufferLogger();\n\t\tconst fileService = this._register(new FileService(fileLogger));\n\t\tserviceCollection.set(IFileService, fileService);\n\n\t\t// Logger\n\t\tconst loggerService = new FileLoggerService(getLogLevel(environmentService), logsPath, fileService);\n\t\tserviceCollection.set(ILoggerService, loggerService);\n\n\t\t// Log Service\n\t\tconst otherLoggers: ILogger[] = [new ConsoleLogger(loggerService.getLogLevel())];\n\t\tif (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {\n\t\t\totherLoggers.push(new ConsoleLogInAutomationLogger(loggerService.getLogLevel()));\n\t\t}\n\t\tconst logger = loggerService.createLogger(environmentService.logFile, { id: windowLogId, name: windowLogGroup.name, group: windowLogGroup });\n\t\tconst logService = new LogService(logger, otherLoggers);\n\t\tserviceCollection.set(ILogService, logService);\n\n\t\t// Set the logger of the fileLogger after the log service is ready.\n\t\t// This is to avoid cyclic dependency\n\t\tfileLogger.logger = logService;\n\n\t\t// Register File System Providers depending on IndexedDB support\n\t\t// Register them early because they are needed for the profiles initialization\n\t\tawait this.registerIndexedDBFileSystemProviders(environmentService, fileService, logService, loggerService, logsPath);\n\n\n\t\tconst connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName);\n\t\tconst remoteResourceLoader = this.configuration.remoteResourceProvider ? new BrowserRemoteResourceLoader(fileService, this.configuration.remoteResourceProvider) : undefined;\n\t\tconst resourceUriProvider = this.configuration.resourceUriProvider ?? remoteResourceLoader?.getResourceUriProvider();\n\t\tconst remoteAuthorityResolverService = new RemoteAuthorityResolverService(!environmentService.expectsResolverExtension, connectionToken, resourceUriProvider, this.configuration.serverBasePath, productService, logService);\n\t\tserviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);\n\n\t\t// Signing\n\t\tconst signService = new SignService(productService);\n\t\tserviceCollection.set(ISignService, signService);\n\n\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\t\t//\n\t\t// NOTE: Please do NOT register services here. Use `registerSingleton()`\n\t\t//       from `workbench.common.main.ts` if the service is shared between\n\t\t//       desktop and web or `workbench.web.main.ts` if the service\n\t\t//       is web only.\n\t\t//\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n\t\t// URI Identity\n\t\tconst uriIdentityService = new UriIdentityService(fileService);\n\t\tserviceCollection.set(IUriIdentityService, uriIdentityService);\n\n\t\t// User Data Profiles\n\t\tconst userDataProfilesService = new BrowserUserDataProfilesService(environmentService, fileService, uriIdentityService, logService);\n\t\tserviceCollection.set(IUserDataProfilesService, userDataProfilesService);\n\n\t\tconst currentProfile = await this.getCurrentProfile(workspace, userDataProfilesService, environmentService);\n\t\tawait userDataProfilesService.setProfileForWorkspace(workspace, currentProfile);\n\t\tconst userDataProfileService = new UserDataProfileService(currentProfile);\n\t\tserviceCollection.set(IUserDataProfileService, userDataProfileService);\n\n\t\t// Remote Agent\n\t\tconst remoteSocketFactoryService = new RemoteSocketFactoryService();\n\t\tremoteSocketFactoryService.register(RemoteConnectionType.WebSocket, new BrowserSocketFactory(this.configuration.webSocketFactory));\n\t\tserviceCollection.set(IRemoteSocketFactoryService, remoteSocketFactoryService);\n\t\tconst remoteAgentService = this._register(new RemoteAgentService(remoteSocketFactoryService, userDataProfileService, environmentService, productService, remoteAuthorityResolverService, signService, logService));\n\t\tserviceCollection.set(IRemoteAgentService, remoteAgentService);\n\t\tthis._register(RemoteFileSystemProviderClient.register(remoteAgentService, fileService, logService));\n\n\t\t// Default Account\n\t\tconst defaultAccountService = this._register(new DefaultAccountService());\n\t\tserviceCollection.set(IDefaultAccountService, defaultAccountService);\n\n\t\t// Policies\n\t\tconst policyService = new AccountPolicyService(logService, defaultAccountService);\n\t\tserviceCollection.set(IPolicyService, policyService);\n\n\t\t// Long running services (workspace, config, storage)\n\t\tconst [configurationService, storageService] = await Promise.all([\n\t\t\tthis.createWorkspaceService(workspace, environmentService, userDataProfileService, userDataProfilesService, fileService, remoteAgentService, uriIdentityService, policyService, logService).then(service => {\n\n\t\t\t\t// Workspace\n\t\t\t\tserviceCollection.set(IWorkspaceContextService, service);\n\n\t\t\t\t// Configuration\n\t\t\t\tserviceCollection.set(IWorkbenchConfigurationService, service);\n\n\t\t\t\treturn service;\n\t\t\t}),\n\n\t\t\tthis.createStorageService(workspace, logService, userDataProfileService).then(service => {\n\n\t\t\t\t// Storage\n\t\t\t\tserviceCollection.set(IStorageService, service);\n\n\t\t\t\treturn service;\n\t\t\t})\n\t\t]);\n\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\t\t//\n\t\t// NOTE: Please do NOT register services here. Use `registerSingleton()`\n\t\t//       from `workbench.common.main.ts` if the service is shared between\n\t\t//       desktop and web or `workbench.web.main.ts` if the service\n\t\t//       is web only.\n\t\t//\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n\t\t// Workspace Trust Service\n\t\tconst workspaceTrustEnablementService = new WorkspaceTrustEnablementService(configurationService, environmentService);\n\t\tserviceCollection.set(IWorkspaceTrustEnablementService, workspaceTrustEnablementService);\n\n\t\tconst workspaceTrustManagementService = new WorkspaceTrustManagementService(configurationService, remoteAuthorityResolverService, storageService, uriIdentityService, environmentService, configurationService, workspaceTrustEnablementService, fileService);\n\t\tserviceCollection.set(IWorkspaceTrustManagementService, workspaceTrustManagementService);\n\n\t\t// Update workspace trust so that configuration is updated accordingly\n\t\tconfigurationService.updateWorkspaceTrust(workspaceTrustManagementService.isWorkspaceTrusted());\n\t\tthis._register(workspaceTrustManagementService.onDidChangeTrust(() => configurationService.updateWorkspaceTrust(workspaceTrustManagementService.isWorkspaceTrusted())));\n\n\t\t// Request Service\n\t\tconst requestService = new BrowserRequestService(remoteAgentService, configurationService, loggerService);\n\t\tserviceCollection.set(IRequestService, requestService);\n\n\t\t// Userdata Sync Store Management Service\n\t\tconst userDataSyncStoreManagementService = new UserDataSyncStoreManagementService(productService, configurationService, storageService);\n\t\tserviceCollection.set(IUserDataSyncStoreManagementService, userDataSyncStoreManagementService);\n\n\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\t\t//\n\t\t// NOTE: Please do NOT register services here. Use `registerSingleton()`\n\t\t//       from `workbench.common.main.ts` if the service is shared between\n\t\t//       desktop and web or `workbench.web.main.ts` if the service\n\t\t//       is web only.\n\t\t//\n\t\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\t\tconst encryptionService = new EncryptionService();\n\t\tserviceCollection.set(IEncryptionService, encryptionService);\n\t\tconst secretStorageService = new BrowserSecretStorageService(storageService, encryptionService, environmentService, logService);\n\t\tserviceCollection.set(ISecretStorageService, secretStorageService);\n\n\t\t// Userdata Initialize Service\n\t\tconst userDataInitializers: IUserDataInitializer[] = [];\n\t\tuserDataInitializers.push(new UserDataSyncInitializer(environmentService, secretStorageService, userDataSyncStoreManagementService, fileService, userDataProfilesService, storageService, productService, requestService, logService, uriIdentityService));\n\t\tif (environmentService.options.profile) {\n\t\t\tuserDataInitializers.push(new UserDataProfileInitializer(environmentService, fileService, userDataProfileService, storageService, logService, uriIdentityService, requestService));\n\t\t}\n\t\tconst userDataInitializationService = new UserDataInitializationService(userDataInitializers);\n\t\tserviceCollection.set(IUserDataInitializationService, userDataInitializationService);\n\n\t\ttry {\n\t\t\tawait Promise.race([\n\t\t\t\t// Do not block more than 5s\n\t\t\t\ttimeout(5000),\n\t\t\t\tthis.initializeUserData(userDataInitializationService, configurationService)]\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tlogService.error(error);\n\t\t}\n\n\t\treturn { serviceCollection, configurationService, logService };\n\t}\n\n\tprivate async initializeUserData(userDataInitializationService: UserDataInitializationService, configurationService: WorkspaceService) {\n\t\tif (await userDataInitializationService.requiresInitialization()) {\n\t\t\tmark('code/willInitRequiredUserData');\n\n\t\t\t// Initialize required resources - settings & global state\n\t\t\tawait userDataInitializationService.initializeRequiredResources();\n\n\t\t\t// Important: Reload only local user configuration after initializing\n\t\t\t// Reloading complete configuration blocks workbench until remote configuration is loaded.\n\t\t\tawait configurationService.reloadLocalUserConfiguration();\n\n\t\t\tmark('code/didInitRequiredUserData');\n\t\t}\n\t}\n\n\tprivate async registerIndexedDBFileSystemProviders(environmentService: IWorkbenchEnvironmentService, fileService: IFileService, logService: ILogService, loggerService: ILoggerService, logsPath: URI): Promise<void> {\n\n\t\t// IndexedDB is used for logging and user data\n\t\tlet indexedDB: IndexedDB | undefined;\n\t\tconst userDataStore = 'vscode-userdata-store';\n\t\tconst logsStore = 'vscode-logs-store';\n\t\tconst handlesStore = 'vscode-filehandles-store';\n\t\ttry {\n\t\t\tindexedDB = await IndexedDB.create('vscode-web-db', 3, [userDataStore, logsStore, handlesStore]);\n\n\t\t\t// Close onWillShutdown\n\t\t\tthis.onWillShutdownDisposables.add(toDisposable(() => indexedDB?.close()));\n\t\t} catch (error) {\n\t\t\tlogService.error('Error while creating IndexedDB', error);\n\t\t}\n\n\t\t// Logger\n\t\tif (indexedDB) {\n\t\t\tconst logFileSystemProvider = new IndexedDBFileSystemProvider(logsPath.scheme, indexedDB, logsStore, false);\n\t\t\tthis.indexedDBFileSystemProviders.push(logFileSystemProvider);\n\t\t\tfileService.registerProvider(logsPath.scheme, logFileSystemProvider);\n\t\t} else {\n\t\t\tfileService.registerProvider(logsPath.scheme, new InMemoryFileSystemProvider());\n\t\t}\n\n\t\t// User data\n\t\tlet userDataProvider;\n\t\tif (indexedDB) {\n\t\t\tuserDataProvider = new IndexedDBFileSystemProvider(Schemas.vscodeUserData, indexedDB, userDataStore, true);\n\t\t\tthis.indexedDBFileSystemProviders.push(userDataProvider);\n\t\t\tthis.registerDeveloperActions(userDataProvider);\n\t\t} else {\n\t\t\tlogService.info('Using in-memory user data provider');\n\t\t\tuserDataProvider = new InMemoryFileSystemProvider();\n\t\t}\n\t\tfileService.registerProvider(Schemas.vscodeUserData, userDataProvider);\n\n\t\t// Local file access (if supported by browser)\n\t\tif (WebFileSystemAccess.supported(mainWindow)) {\n\t\t\tfileService.registerProvider(Schemas.file, new HTMLFileSystemProvider(indexedDB, handlesStore, logService));\n\t\t}\n\n\t\t// In-memory\n\t\tfileService.registerProvider(Schemas.tmp, new InMemoryFileSystemProvider());\n\t}\n\n\tprivate registerDeveloperActions(provider: IndexedDBFileSystemProvider): void {\n\t\tthis._register(registerAction2(class ResetUserDataAction extends Action2 {\n\t\t\tconstructor() {\n\t\t\t\tsuper({\n\t\t\t\t\tid: 'workbench.action.resetUserData',\n\t\t\t\t\ttitle: localize2('reset', \"Reset User Data\"),\n\t\t\t\t\tcategory: Categories.Developer,\n\t\t\t\t\tmenu: {\n\t\t\t\t\t\tid: MenuId.CommandPalette\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tasync run(accessor: ServicesAccessor): Promise<void> {\n\t\t\t\tconst dialogService = accessor.get(IDialogService);\n\t\t\t\tconst hostService = accessor.get(IHostService);\n\t\t\t\tconst storageService = accessor.get(IStorageService);\n\t\t\t\tconst logService = accessor.get(ILogService);\n\t\t\t\tconst result = await dialogService.confirm({\n\t\t\t\t\tmessage: localize('reset user data message', \"Would you like to reset your data (settings, keybindings, extensions, snippets and UI State) and reload?\")\n\t\t\t\t});\n\n\t\t\t\tif (result.confirmed) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait provider?.reset();\n\t\t\t\t\t\tif (storageService instanceof BrowserStorageService) {\n\t\t\t\t\t\t\tawait storageService.clear();\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogService.error(error);\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\thostService.reload();\n\t\t\t}\n\t\t}));\n\t}\n\n\tprivate async createStorageService(workspace: IAnyWorkspaceIdentifier, logService: ILogService, userDataProfileService: IUserDataProfileService): Promise<IStorageService> {\n\t\tconst storageService = new BrowserStorageService(workspace, userDataProfileService, logService);\n\n\t\ttry {\n\t\t\tawait storageService.initialize();\n\n\t\t\t// Register to close on shutdown\n\t\t\tthis.onWillShutdownDisposables.add(toDisposable(() => storageService.close()));\n\n\t\t\treturn storageService;\n\t\t} catch (error) {\n\t\t\tonUnexpectedError(error);\n\t\t\tlogService.error(error);\n\n\t\t\treturn storageService;\n\t\t}\n\t}\n\n\tprivate async createWorkspaceService(workspace: IAnyWorkspaceIdentifier, environmentService: IBrowserWorkbenchEnvironmentService, userDataProfileService: IUserDataProfileService, userDataProfilesService: IUserDataProfilesService, fileService: FileService, remoteAgentService: IRemoteAgentService, uriIdentityService: IUriIdentityService, policyService: IPolicyService, logService: ILogService): Promise<WorkspaceService> {\n\n\t\t// Temporary workspaces do not exist on startup because they are\n\t\t// just in memory. As such, detect this case and eagerly create\n\t\t// the workspace file empty so that it is a valid workspace.\n\n\t\tif (isWorkspaceIdentifier(workspace) && isTemporaryWorkspace(workspace.configPath)) {\n\t\t\ttry {\n\t\t\t\tconst emptyWorkspace: IStoredWorkspace = { folders: [] };\n\t\t\t\tawait fileService.createFile(workspace.configPath, VSBuffer.fromString(JSON.stringify(emptyWorkspace, null, '\\t')), { overwrite: false });\n\t\t\t} catch (error) {\n\t\t\t\t// ignore if workspace file already exists\n\t\t\t}\n\t\t}\n\n\t\tconst configurationCache = new ConfigurationCache([Schemas.file, Schemas.vscodeUserData, Schemas.tmp] /* Cache all non native resources */, environmentService, fileService);\n\t\tconst workspaceService = new WorkspaceService({ remoteAuthority: this.configuration.remoteAuthority, configurationCache }, environmentService, userDataProfileService, userDataProfilesService, fileService, remoteAgentService, uriIdentityService, logService, policyService);\n\n\t\ttry {\n\t\t\tawait workspaceService.initialize(workspace);\n\n\t\t\treturn workspaceService;\n\t\t} catch (error) {\n\t\t\tonUnexpectedError(error);\n\t\t\tlogService.error(error);\n\n\t\t\treturn workspaceService;\n\t\t}\n\t}\n\n\tprivate async getCurrentProfile(workspace: IAnyWorkspaceIdentifier, userDataProfilesService: BrowserUserDataProfilesService, environmentService: BrowserWorkbenchEnvironmentService): Promise<IUserDataProfile> {\n\t\tconst profileName = environmentService.options?.profile?.name ?? environmentService.profile;\n\t\tif (profileName) {\n\t\t\tconst profile = userDataProfilesService.profiles.find(p => p.name === profileName);\n\t\t\tif (profile) {\n\t\t\t\treturn profile;\n\t\t\t}\n\t\t\treturn userDataProfilesService.createNamedProfile(profileName, undefined, workspace);\n\t\t}\n\t\treturn userDataProfilesService.getProfileForWorkspace(workspace) ?? userDataProfilesService.defaultProfile;\n\t}\n\n\tprivate resolveWorkspace(): IAnyWorkspaceIdentifier {\n\t\tlet workspace: IWorkspace | undefined = undefined;\n\t\tif (this.configuration.workspaceProvider) {\n\t\t\tworkspace = this.configuration.workspaceProvider.workspace;\n\t\t}\n\n\t\t/* below codes are changed by github1s */\n\t\tconst id = globalThis._VSCODE_WEB?.workspaceId;\n\n\t\t// Multi-root workspace\n\t\tif (workspace && isWorkspaceToOpen(workspace)) {\n\t\t\tconst identifier = getWorkspaceIdentifier(workspace.workspaceUri);\n\t\t\treturn id ? { ...identifier, id } : identifier;\n\t\t}\n\n\t\t// Single-folder workspace\n\t\tif (workspace && isFolderToOpen(workspace)) {\n\t\t\tconst identifier = getSingleFolderWorkspaceIdentifier(workspace.folderUri);\n\t\t\treturn id ? { ...identifier, id } : identifier;\n\t\t}\n\n\t\treturn id ? { id } : UNKNOWN_EMPTY_WINDOW_WORKSPACE;\n\t\t/* above codes are changed by github1s */\n\t}\n}\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { URI } from '../../../../../base/common/uri.js';\nimport { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, EditorInputCapabilities, IEditorDescriptor, IEditorPane, IUntypedEditorInput, DEFAULT_EDITOR_ASSOCIATION, IUntypedFileEditorInput, findViewStateForEditor, isResourceEditorInput, IFileEditorInputOptions } from '../../../../common/editor.js';\nimport { EditorInput, IUntypedEditorOptions } from '../../../../common/editor/editorInput.js';\nimport { AbstractTextResourceEditorInput } from '../../../../common/editor/textResourceEditorInput.js';\nimport { ITextResourceEditorInput } from '../../../../../platform/editor/common/editor.js';\nimport { BinaryEditorModel } from '../../../../common/editor/binaryEditorModel.js';\nimport { IFileService } from '../../../../../platform/files/common/files.js';\nimport { ITextFileService, TextFileEditorModelState, TextFileResolveReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel, EncodingMode } from '../../../../services/textfile/common/textfiles.js';\nimport { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';\nimport { IReference, dispose, DisposableStore } from '../../../../../base/common/lifecycle.js';\nimport { ITextModelService } from '../../../../../editor/common/services/resolverService.js';\nimport { FILE_EDITOR_INPUT_ID, TEXT_FILE_EDITOR_ID, BINARY_FILE_EDITOR_ID } from '../../common/files.js';\nimport { ILabelService } from '../../../../../platform/label/common/label.js';\nimport { IFilesConfigurationService } from '../../../../services/filesConfiguration/common/filesConfigurationService.js';\nimport { IEditorService } from '../../../../services/editor/common/editorService.js';\nimport { isEqual } from '../../../../../base/common/resources.js';\nimport { Event } from '../../../../../base/common/event.js';\nimport { Schemas } from '../../../../../base/common/network.js';\nimport { createTextBufferFactory } from '../../../../../editor/common/model/textModel.js';\nimport { IPathService } from '../../../../services/path/common/pathService.js';\nimport { ITextResourceConfigurationService } from '../../../../../editor/common/services/textResourceConfiguration.js';\nimport { IMarkdownString } from '../../../../../base/common/htmlContent.js';\nimport { ICustomEditorLabelService } from '../../../../services/editor/common/customEditorLabelService.js';\n\nconst enum ForceOpenAs {\n\tNone,\n\tText,\n\tBinary\n}\n\n/**\n * A file editor input is the input type for the file editor of file system resources.\n */\nexport class FileEditorInput extends AbstractTextResourceEditorInput implements IFileEditorInput {\n\n\toverride get typeId(): string {\n\t\treturn FILE_EDITOR_INPUT_ID;\n\t}\n\n\toverride get editorId(): string | undefined {\n\t\treturn DEFAULT_EDITOR_ASSOCIATION.id;\n\t}\n\n\toverride get capabilities(): EditorInputCapabilities {\n\t\tlet capabilities = EditorInputCapabilities.CanSplitInGroup;\n\n\t\tif (this.model) {\n\t\t\tif (this.model.isReadonly()) {\n\t\t\t\tcapabilities |= EditorInputCapabilities.Readonly;\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.fileService.hasProvider(this.resource)) {\n\t\t\t\tif (this.filesConfigurationService.isReadonly(this.resource)) {\n\t\t\t\t\tcapabilities |= EditorInputCapabilities.Readonly;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcapabilities |= EditorInputCapabilities.Untitled;\n\t\t\t}\n\t\t}\n\n\t\tif (!(capabilities & EditorInputCapabilities.Readonly)) {\n\t\t\tcapabilities |= EditorInputCapabilities.CanDropIntoEditor;\n\t\t}\n\n\t\treturn capabilities;\n\t}\n\n\tprivate preferredName: string | undefined;\n\tprivate preferredDescription: string | undefined;\n\tprivate preferredEncoding: string | undefined;\n\tprivate preferredLanguageId: string | undefined;\n\tprivate preferredContents: string | undefined;\n\n\tprivate forceOpenAs: ForceOpenAs = ForceOpenAs.None;\n\n\tprivate model: ITextFileEditorModel | undefined = undefined;\n\tprivate cachedTextFileModelReference: IReference<ITextFileEditorModel> | undefined = undefined;\n\n\tprivate readonly modelListeners = this._register(new DisposableStore());\n\n\tconstructor(\n\t\tresource: URI,\n\t\tpreferredResource: URI | undefined,\n\t\tpreferredName: string | undefined,\n\t\tpreferredDescription: string | undefined,\n\t\tpreferredEncoding: string | undefined,\n\t\tpreferredLanguageId: string | undefined,\n\t\tpreferredContents: string | undefined,\n\t\t@IInstantiationService private readonly instantiationService: IInstantiationService,\n\t\t@ITextFileService textFileService: ITextFileService,\n\t\t@ITextModelService private readonly textModelService: ITextModelService,\n\t\t@ILabelService labelService: ILabelService,\n\t\t@IFileService fileService: IFileService,\n\t\t@IFilesConfigurationService filesConfigurationService: IFilesConfigurationService,\n\t\t@IEditorService editorService: IEditorService,\n\t\t@IPathService private readonly pathService: IPathService,\n\t\t@ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService,\n\t\t@ICustomEditorLabelService customEditorLabelService: ICustomEditorLabelService\n\t) {\n\t\tsuper(resource, preferredResource, editorService, textFileService, labelService, fileService, filesConfigurationService, textResourceConfigurationService, customEditorLabelService);\n\n\t\tthis.model = this.textFileService.files.get(resource);\n\n\t\tif (preferredName) {\n\t\t\tthis.setPreferredName(preferredName);\n\t\t}\n\n\t\tif (preferredDescription) {\n\t\t\tthis.setPreferredDescription(preferredDescription);\n\t\t}\n\n\t\tif (preferredEncoding) {\n\t\t\tthis.setPreferredEncoding(preferredEncoding);\n\t\t}\n\n\t\tif (preferredLanguageId) {\n\t\t\tthis.setPreferredLanguageId(preferredLanguageId);\n\t\t}\n\n\t\tif (typeof preferredContents === 'string') {\n\t\t\tthis.setPreferredContents(preferredContents);\n\t\t}\n\n\t\t// Attach to model that matches our resource once created\n\t\tthis._register(this.textFileService.files.onDidCreate(model => this.onDidCreateTextFileModel(model)));\n\n\t\t// If a file model already exists, make sure to wire it in\n\t\tif (this.model) {\n\t\t\tthis.registerModelListeners(this.model);\n\t\t}\n\t}\n\n\tprivate onDidCreateTextFileModel(model: ITextFileEditorModel): void {\n\n\t\t// Once the text file model is created, we keep it inside\n\t\t// the input to be able to implement some methods properly\n\t\tif (isEqual(model.resource, this.resource)) {\n\t\t\tthis.model = model;\n\n\t\t\tthis.registerModelListeners(model);\n\t\t}\n\t}\n\n\tprivate registerModelListeners(model: ITextFileEditorModel): void {\n\n\t\t// Clear any old\n\t\tthis.modelListeners.clear();\n\n\t\t// re-emit some events from the model\n\t\tthis.modelListeners.add(model.onDidChangeDirty(() => this._onDidChangeDirty.fire()));\n\t\tthis.modelListeners.add(model.onDidChangeReadonly(() => this._onDidChangeCapabilities.fire()));\n\n\t\t// important: treat save errors as potential dirty change because\n\t\t// a file that is in save conflict or error will report dirty even\n\t\t// if auto save is turned on.\n\t\tthis.modelListeners.add(model.onDidSaveError(() => this._onDidChangeDirty.fire()));\n\n\t\t// remove model association once it gets disposed\n\t\tthis.modelListeners.add(Event.once(model.onWillDispose)(() => {\n\t\t\tthis.modelListeners.clear();\n\t\t\tthis.model = undefined;\n\t\t}));\n\t}\n\n\toverride getName(): string {\n\t\treturn this.preferredName || super.getName();\n\t}\n\n\tsetPreferredName(name: string): void {\n\t\tif (!this.allowLabelOverride()) {\n\t\t\treturn; // block for specific schemes we consider to be owning\n\t\t}\n\n\t\tif (this.preferredName !== name) {\n\t\t\tthis.preferredName = name;\n\n\t\t\tthis._onDidChangeLabel.fire();\n\t\t}\n\t}\n\n\tprivate allowLabelOverride(): boolean {\n\t\t/* below codes are changed by github1s */\n\t\tif (globalThis._VSCODE_WEB?.allowEditorLabelOverride) return true;\n\t\t/* above codes are changed by github1s */\n\t\treturn this.resource.scheme !== this.pathService.defaultUriScheme &&\n\t\t\tthis.resource.scheme !== Schemas.vscodeUserData &&\n\t\t\tthis.resource.scheme !== Schemas.file &&\n\t\t\tthis.resource.scheme !== Schemas.vscodeRemote;\n\t}\n\n\tgetPreferredName(): string | undefined {\n\t\treturn this.preferredName;\n\t}\n\n\toverride isReadonly(): boolean | IMarkdownString {\n\t\treturn this.model ? this.model.isReadonly() : this.filesConfigurationService.isReadonly(this.resource);\n\t}\n\n\toverride getDescription(verbosity?: Verbosity): string | undefined {\n\t\treturn this.preferredDescription || super.getDescription(verbosity);\n\t}\n\n\tsetPreferredDescription(description: string): void {\n\t\tif (!this.allowLabelOverride()) {\n\t\t\treturn; // block for specific schemes we consider to be owning\n\t\t}\n\n\t\tif (this.preferredDescription !== description) {\n\t\t\tthis.preferredDescription = description;\n\n\t\t\tthis._onDidChangeLabel.fire();\n\t\t}\n\t}\n\n\tgetPreferredDescription(): string | undefined {\n\t\treturn this.preferredDescription;\n\t}\n\n\toverride getTitle(verbosity?: Verbosity): string {\n\t\tlet title = super.getTitle(verbosity);\n\n\t\tconst preferredTitle = this.getPreferredTitle();\n\t\tif (preferredTitle) {\n\t\t\ttitle = `${preferredTitle} (${title})`;\n\t\t}\n\n\t\treturn title;\n\t}\n\n\tprotected getPreferredTitle(): string | undefined {\n\t\tif (this.preferredName && this.preferredDescription) {\n\t\t\treturn `${this.preferredName} ${this.preferredDescription}`;\n\t\t}\n\n\t\tif (this.preferredName || this.preferredDescription) {\n\t\t\treturn this.preferredName ?? this.preferredDescription;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tgetEncoding(): string | undefined {\n\t\tif (this.model) {\n\t\t\treturn this.model.getEncoding();\n\t\t}\n\n\t\treturn this.preferredEncoding;\n\t}\n\n\tgetPreferredEncoding(): string | undefined {\n\t\treturn this.preferredEncoding;\n\t}\n\n\tasync setEncoding(encoding: string, mode: EncodingMode): Promise<void> {\n\t\tthis.setPreferredEncoding(encoding);\n\n\t\treturn this.model?.setEncoding(encoding, mode);\n\t}\n\n\tsetPreferredEncoding(encoding: string): void {\n\t\tthis.preferredEncoding = encoding;\n\n\t\t// encoding is a good hint to open the file as text\n\t\tthis.setForceOpenAsText();\n\t}\n\n\tgetLanguageId(): string | undefined {\n\t\tif (this.model) {\n\t\t\treturn this.model.getLanguageId();\n\t\t}\n\n\t\treturn this.preferredLanguageId;\n\t}\n\n\tgetPreferredLanguageId(): string | undefined {\n\t\treturn this.preferredLanguageId;\n\t}\n\n\tsetLanguageId(languageId: string, source?: string): void {\n\t\tthis.setPreferredLanguageId(languageId);\n\n\t\tthis.model?.setLanguageId(languageId, source);\n\t}\n\n\tsetPreferredLanguageId(languageId: string): void {\n\t\tthis.preferredLanguageId = languageId;\n\n\t\t// languages are a good hint to open the file as text\n\t\tthis.setForceOpenAsText();\n\t}\n\n\tsetPreferredContents(contents: string): void {\n\t\tthis.preferredContents = contents;\n\n\t\t// contents is a good hint to open the file as text\n\t\tthis.setForceOpenAsText();\n\t}\n\n\tsetForceOpenAsText(): void {\n\t\tthis.forceOpenAs = ForceOpenAs.Text;\n\t}\n\n\tsetForceOpenAsBinary(): void {\n\t\tthis.forceOpenAs = ForceOpenAs.Binary;\n\t}\n\n\toverride isDirty(): boolean {\n\t\treturn !!(this.model?.isDirty());\n\t}\n\n\toverride isSaving(): boolean {\n\t\tif (this.model?.hasState(TextFileEditorModelState.SAVED) || this.model?.hasState(TextFileEditorModelState.CONFLICT) || this.model?.hasState(TextFileEditorModelState.ERROR)) {\n\t\t\treturn false; // require the model to be dirty and not in conflict or error state\n\t\t}\n\n\t\t// Note: currently not checking for ModelState.PENDING_SAVE for a reason\n\t\t// because we currently miss an event for this state change on editors\n\t\t// and it could result in bad UX where an editor can be closed even though\n\t\t// it shows up as dirty and has not finished saving yet.\n\n\t\tif (this.filesConfigurationService.hasShortAutoSaveDelay(this)) {\n\t\t\treturn true; // a short auto save is configured, treat this as being saved\n\t\t}\n\n\t\treturn super.isSaving();\n\t}\n\n\toverride prefersEditorPane<T extends IEditorDescriptor<IEditorPane>>(editorPanes: T[]): T | undefined {\n\t\tif (this.forceOpenAs === ForceOpenAs.Binary) {\n\t\t\treturn editorPanes.find(editorPane => editorPane.typeId === BINARY_FILE_EDITOR_ID);\n\t\t}\n\n\t\treturn editorPanes.find(editorPane => editorPane.typeId === TEXT_FILE_EDITOR_ID);\n\t}\n\n\toverride resolve(options?: IFileEditorInputOptions): Promise<ITextFileEditorModel | BinaryEditorModel> {\n\n\t\t// Resolve as binary\n\t\tif (this.forceOpenAs === ForceOpenAs.Binary) {\n\t\t\treturn this.doResolveAsBinary();\n\t\t}\n\n\t\t// Resolve as text\n\t\treturn this.doResolveAsText(options);\n\t}\n\n\tprivate async doResolveAsText(options?: IFileEditorInputOptions): Promise<ITextFileEditorModel | BinaryEditorModel> {\n\t\ttry {\n\n\t\t\t// Unset preferred contents after having applied it once\n\t\t\t// to prevent this property to stick. We still want future\n\t\t\t// `resolve` calls to fetch the contents from disk.\n\t\t\tconst preferredContents = this.preferredContents;\n\t\t\tthis.preferredContents = undefined;\n\n\t\t\t// Resolve resource via text file service and only allow\n\t\t\t// to open binary files if we are instructed so\n\t\t\tawait this.textFileService.files.resolve(this.resource, {\n\t\t\t\tlanguageId: this.preferredLanguageId,\n\t\t\t\tencoding: this.preferredEncoding,\n\t\t\t\tcontents: typeof preferredContents === 'string' ? createTextBufferFactory(preferredContents) : undefined,\n\t\t\t\treload: { async: true }, // trigger a reload of the model if it exists already but do not wait to show the model\n\t\t\t\tallowBinary: this.forceOpenAs === ForceOpenAs.Text,\n\t\t\t\treason: TextFileResolveReason.EDITOR,\n\t\t\t\tlimits: this.ensureLimits(options)\n\t\t\t});\n\n\t\t\t// This is a bit ugly, because we first resolve the model and then resolve a model reference. the reason being that binary\n\t\t\t// or very large files do not resolve to a text file model but should be opened as binary files without text. First calling into\n\t\t\t// resolve() ensures we are not creating model references for these kind of resources.\n\t\t\t// In addition we have a bit of payload to take into account (encoding, reload) that the text resolver does not handle yet.\n\t\t\tif (!this.cachedTextFileModelReference) {\n\t\t\t\tthis.cachedTextFileModelReference = await this.textModelService.createModelReference(this.resource) as IReference<ITextFileEditorModel>;\n\t\t\t}\n\n\t\t\tconst model = this.cachedTextFileModelReference.object;\n\n\t\t\t// It is possible that this input was disposed before the model\n\t\t\t// finished resolving. As such, we need to make sure to dispose\n\t\t\t// the model reference to not leak it.\n\t\t\tif (this.isDisposed()) {\n\t\t\t\tthis.disposeModelReference();\n\t\t\t}\n\n\t\t\treturn model;\n\t\t} catch (error) {\n\n\t\t\t// Handle binary files with binary model\n\t\t\tif ((<TextFileOperationError>error).textFileOperationResult === TextFileOperationResult.FILE_IS_BINARY) {\n\t\t\t\treturn this.doResolveAsBinary();\n\t\t\t}\n\n\t\t\t// Bubble any other error up\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async doResolveAsBinary(): Promise<BinaryEditorModel> {\n\t\tconst model = this.instantiationService.createInstance(BinaryEditorModel, this.preferredResource, this.getName());\n\t\tawait model.resolve();\n\n\t\treturn model;\n\t}\n\n\tisResolved(): boolean {\n\t\treturn !!this.model;\n\t}\n\n\toverride async rename(group: GroupIdentifier, target: URI): Promise<IMoveResult> {\n\t\treturn {\n\t\t\teditor: {\n\t\t\t\tresource: target,\n\t\t\t\tencoding: this.getEncoding(),\n\t\t\t\toptions: {\n\t\t\t\t\tviewState: findViewStateForEditor(this, group, this.editorService)\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\toverride toUntyped(options?: IUntypedEditorOptions): ITextResourceEditorInput {\n\t\tconst untypedInput: IUntypedFileEditorInput = {\n\t\t\tresource: this.preferredResource,\n\t\t\tforceFile: true,\n\t\t\toptions: {\n\t\t\t\toverride: this.editorId\n\t\t\t}\n\t\t};\n\n\t\tif (typeof options?.preserveViewState === 'number') {\n\t\t\tuntypedInput.encoding = this.getEncoding();\n\t\t\tuntypedInput.languageId = this.getLanguageId();\n\t\t\tuntypedInput.contents = (() => {\n\t\t\t\tconst model = this.textFileService.files.get(this.resource);\n\t\t\t\tif (model?.isDirty() && !model.textEditorModel.isTooLargeForHeapOperation()) {\n\t\t\t\t\treturn model.textEditorModel.getValue(); // only if dirty and not too large\n\t\t\t\t}\n\n\t\t\t\treturn undefined;\n\t\t\t})();\n\n\t\t\tuntypedInput.options = {\n\t\t\t\t...untypedInput.options,\n\t\t\t\tviewState: findViewStateForEditor(this, options.preserveViewState, this.editorService)\n\t\t\t};\n\t\t}\n\n\t\treturn untypedInput;\n\t}\n\n\toverride matches(otherInput: EditorInput | IUntypedEditorInput): boolean {\n\t\tif (this === otherInput) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (otherInput instanceof FileEditorInput) {\n\t\t\treturn isEqual(otherInput.resource, this.resource);\n\t\t}\n\n\t\tif (isResourceEditorInput(otherInput)) {\n\t\t\treturn super.matches(otherInput);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\toverride dispose(): void {\n\n\t\t// Model\n\t\tthis.model = undefined;\n\n\t\t// Model reference\n\t\tthis.disposeModelReference();\n\n\t\tsuper.dispose();\n\t}\n\n\tprivate disposeModelReference(): void {\n\t\tdispose(this.cachedTextFileModelReference);\n\t\tthis.cachedTextFileModelReference = undefined;\n\t}\n}\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\" style=\"width: 100%; height: 100%;\">\n\n<head>\n\t<meta charset=\"UTF-8\">\n\n\t<!-- Disable pinch zooming -->\n\t<meta name=\"viewport\"\n\t\tcontent=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no\">\n</head>\n\n<body style=\"margin: 0; overflow: hidden; width: 100%; height: 100%; overscroll-behavior-x: none;\" role=\"document\">\n\t<!-- TODO: Remove additional script tag once Firefox is fixed https://bugzilla.mozilla.org/show_bug.cgi?id=1737882 -->\n\t<script></script>\n\t<script async type=\"module\">\n\t\t// @ts-check\n\t\t/// <reference lib=\"dom\" />\n\n\t\tconst isSafari = (\n\t\t\tnavigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&\n\t\t\tnavigator.userAgent &&\n\t\t\tnavigator.userAgent.indexOf('CriOS') === -1 &&\n\t\t\tnavigator.userAgent.indexOf('FxiOS') === -1\n\t\t);\n\n\t\tconst isFirefox = (\n\t\t\tnavigator.userAgent &&\n\t\t\tnavigator.userAgent.indexOf('Firefox') >= 0\n\t\t);\n\n\t\tconst searchParams = new URL(location.toString()).searchParams;\n\t\tconst ID = searchParams.get('id');\n\t\tconst webviewOrigin = searchParams.get('origin');\n\t\tconst onElectron = searchParams.get('platform') === 'electron';\n\t\tconst disableServiceWorker = searchParams.has('disableServiceWorker');\n\t\tconst expectedWorkerVersion = parseInt(searchParams.get('swVersion'));\n\n\t\t/**\n\t\t * Use polling to track focus of main webview and iframes within the webview\n\t\t *\n\t\t * @param {Object} handlers\n\t\t * @param {() => void} handlers.onFocus\n\t\t * @param {() => void} handlers.onBlur\n\t\t */\n\t\tconst trackFocus = ({ onFocus, onBlur }) => {\n\t\t\tconst interval = 250;\n\t\t\tlet isFocused = document.hasFocus();\n\t\t\tsetInterval(() => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tconst isCurrentlyFocused = document.hasFocus() || !!(target && target.contentDocument && target.contentDocument.body.classList.contains('vscode-context-menu-visible'));\n\t\t\t\tif (isCurrentlyFocused === isFocused) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tisFocused = isCurrentlyFocused;\n\t\t\t\tif (isCurrentlyFocused) {\n\t\t\t\t\tonFocus();\n\t\t\t\t} else {\n\t\t\t\t\tonBlur();\n\t\t\t\t}\n\t\t\t}, interval);\n\t\t};\n\n\t\tconst getActiveFrame = () => {\n\t\t\treturn /** @type {HTMLIFrameElement | undefined} */ (document.getElementById('active-frame'));\n\t\t};\n\n\t\tconst getPendingFrame = () => {\n\t\t\treturn /** @type {HTMLIFrameElement | undefined} */ (document.getElementById('pending-frame'));\n\t\t};\n\n\t\t/**\n\t\t * @template T\n\t\t * @param {T | undefined | null} obj\n\t\t * @return {T}\n\t\t */\n\t\tfunction assertIsDefined(obj) {\n\t\t\tif (typeof obj === 'undefined' || obj === null) {\n\t\t\t\tthrow new Error('Found unexpected null');\n\t\t\t}\n\t\t\treturn obj;\n\t\t}\n\n\t\tconst vscodePostMessageFuncName = '__vscode_post_message__';\n\n\t\tconst defaultStyles = document.createElement('style');\n\t\tdefaultStyles.id = '_defaultStyles';\n\t\tdefaultStyles.textContent = `\n\t\t\thtml {\n\t\t\t\tscrollbar-color: var(--vscode-scrollbarSlider-background) var(--vscode-editor-background);\n\t\t\t}\n\n\t\t\tbody {\n\t\t\t\toverscroll-behavior-x: none;\n\t\t\t\tbackground-color: transparent;\n\t\t\t\tcolor: var(--vscode-editor-foreground);\n\t\t\t\tfont-family: var(--vscode-font-family);\n\t\t\t\tfont-weight: var(--vscode-font-weight);\n\t\t\t\tfont-size: var(--vscode-font-size);\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0 20px;\n\t\t\t}\n\n\t\t\timg, video {\n\t\t\t\tmax-width: 100%;\n\t\t\t\tmax-height: 100%;\n\t\t\t}\n\n\t\t\ta, a code {\n\t\t\t\tcolor: var(--vscode-textLink-foreground);\n\t\t\t}\n\n\t\t\ta:hover {\n\t\t\t\tcolor: var(--vscode-textLink-activeForeground);\n\t\t\t}\n\n\t\t\ta:focus,\n\t\t\tinput:focus,\n\t\t\tselect:focus,\n\t\t\ttextarea:focus {\n\t\t\t\toutline: 1px solid -webkit-focus-ring-color;\n\t\t\t\toutline-offset: -1px;\n\t\t\t}\n\n\t\t\tcode {\n\t\t\t\tfont-family: var(--monaco-monospace-font);\n\t\t\t\tcolor: var(--vscode-textPreformat-foreground);\n\t\t\t\tbackground-color: var(--vscode-textPreformat-background);\n\t\t\t\tpadding: 1px 3px;\n\t\t\t\tborder-radius: 4px;\n\t\t\t}\n\n\t\t\tpre code {\n\t\t\t\tpadding: 0;\n\t\t\t}\n\n\t\t\tblockquote {\n\t\t\t\tbackground: var(--vscode-textBlockQuote-background);\n\t\t\t\tborder-color: var(--vscode-textBlockQuote-border);\n\t\t\t}\n\n\t\t\tkbd {\n\t\t\t\tbackground-color: var(--vscode-keybindingLabel-background);\n\t\t\t\tcolor: var(--vscode-keybindingLabel-foreground);\n\t\t\t\tborder-style: solid;\n\t\t\t\tborder-width: 1px;\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tborder-color: var(--vscode-keybindingLabel-border);\n\t\t\t\tborder-bottom-color: var(--vscode-keybindingLabel-bottomBorder);\n\t\t\t\tbox-shadow: inset 0 -1px 0 var(--vscode-widget-shadow);\n\t\t\t\tvertical-align: middle;\n\t\t\t\tpadding: 1px 3px;\n\t\t\t}\n\n\t\t\t::-webkit-scrollbar {\n\t\t\t\twidth: 10px;\n\t\t\t\theight: 10px;\n\t\t\t}\n\n\t\t\t::-webkit-scrollbar-corner {\n\t\t\t\tbackground-color: var(--vscode-editor-background);\n\t\t\t}\n\n\t\t\t::-webkit-scrollbar-thumb {\n\t\t\t\tbackground-color: var(--vscode-scrollbarSlider-background);\n\t\t\t}\n\t\t\t::-webkit-scrollbar-thumb:hover {\n\t\t\t\tbackground-color: var(--vscode-scrollbarSlider-hoverBackground);\n\t\t\t}\n\t\t\t::-webkit-scrollbar-thumb:active {\n\t\t\t\tbackground-color: var(--vscode-scrollbarSlider-activeBackground);\n\t\t\t}\n\t\t\t::highlight(find-highlight) {\n\t\t\t\tbackground-color: var(--vscode-editor-findMatchHighlightBackground);\n\t\t\t}\n\t\t\t::highlight(current-find-highlight) {\n\t\t\t\tbackground-color: var(--vscode-editor-findMatchBackground);\n\t\t\t}`;\n\n\t\t/**\n\t\t * @param {boolean} allowMultipleAPIAcquire\n\t\t * @param {*} [state]\n\t\t * @return {string}\n\t\t */\n\t\tfunction getVsCodeApiScript(allowMultipleAPIAcquire, state) {\n\t\t\tconst encodedState = state ? encodeURIComponent(state) : undefined;\n\t\t\treturn /* js */`\n\t\t\t\t\tglobalThis.acquireVsCodeApi = (function() {\n\t\t\t\t\t\tconst originalPostMessage = window.parent['${vscodePostMessageFuncName}'].bind(window.parent);\n\t\t\t\t\t\tconst doPostMessage = (channel, data, transfer) => {\n\t\t\t\t\t\t\toriginalPostMessage(channel, data, transfer);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tlet acquired = false;\n\n\t\t\t\t\t\tlet state = ${state ? `JSON.parse(decodeURIComponent(\"${encodedState}\"))` : undefined};\n\n\t\t\t\t\t\treturn () => {\n\t\t\t\t\t\t\tif (acquired && !${allowMultipleAPIAcquire}) {\n\t\t\t\t\t\t\t\tthrow new Error('An instance of the VS Code API has already been acquired');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tacquired = true;\n\t\t\t\t\t\t\treturn Object.freeze({\n\t\t\t\t\t\t\t\tpostMessage: function(message, transfer) {\n\t\t\t\t\t\t\t\t\tdoPostMessage('onmessage', { message, transfer }, transfer);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsetState: function(newState) {\n\t\t\t\t\t\t\t\t\tstate = newState;\n\t\t\t\t\t\t\t\t\tdoPostMessage('do-update-state', JSON.stringify(newState));\n\t\t\t\t\t\t\t\t\treturn newState;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tgetState: function() {\n\t\t\t\t\t\t\t\t\treturn state;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t};\n\t\t\t\t\t})();\n\t\t\t\t\tdelete window.parent;\n\t\t\t\t\tdelete window.top;\n\t\t\t\t\tdelete window.frameElement;\n\t\t\t\t`;\n\t\t}\n\n\t\t/** @type {Promise<void>} */\n\t\tconst workerReady = new Promise((resolve, reject) => {\n\t\t\tif (disableServiceWorker) {\n\t\t\t\treturn resolve();\n\t\t\t}\n\n\t\t\tif (!areServiceWorkersEnabled()) {\n\t\t\t\treturn reject(new Error('Service Workers are not enabled. Webviews will not work. Try disabling private/incognito mode.'));\n\t\t\t}\n\n\t\t\tconst swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&id=${ID}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}`);\n\t\t\tnavigator.serviceWorker.register(swPath)\n\t\t\t\t.then(async registration => {\n\t\t\t\t\t/**\n\t\t\t\t\t * @param {MessageEvent} event\n\t\t\t\t\t */\n\t\t\t\t\tconst versionHandler = async (event) => {\n\t\t\t\t\t\tif (event.data.channel !== 'version') {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnavigator.serviceWorker.removeEventListener('message', versionHandler);\n\t\t\t\t\t\tif (event.data.version === expectedWorkerVersion) {\n\t\t\t\t\t\t\treturn resolve();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.log(`Found unexpected service worker version. Found: ${event.data.version}. Expected: ${expectedWorkerVersion}`);\n\t\t\t\t\t\t\tconsole.log(`Attempting to reload service worker`);\n\n\t\t\t\t\t\t\t// If we have the wrong version, try once (and only once) to unregister and re-register\n\t\t\t\t\t\t\t// Note that `.update` doesn't seem to work desktop electron at the moment so we use\n\t\t\t\t\t\t\t// `unregister` and `register` here.\n\t\t\t\t\t\t\treturn registration.unregister()\n\t\t\t\t\t\t\t\t.then(() => navigator.serviceWorker.register(swPath))\n\t\t\t\t\t\t\t\t.finally(() => { resolve(); });\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tnavigator.serviceWorker.addEventListener('message', versionHandler);\n\n\t\t\t\t\tconst postVersionMessage = (/** @type {ServiceWorker} */ controller) => {\n\t\t\t\t\t\tcontroller.postMessage({ channel: 'version' });\n\t\t\t\t\t};\n\n\t\t\t\t\t// At this point, either the service worker is ready and\n\t\t\t\t\t// became our controller, or we need to wait for it.\n\t\t\t\t\t// Note that navigator.serviceWorker.controller could be a\n\t\t\t\t\t// controller from a previously loaded service worker.\n\t\t\t\t\tconst currentController = navigator.serviceWorker.controller;\n\t\t\t\t\tif (currentController?.scriptURL.endsWith(swPath)) {\n\t\t\t\t\t\t// service worker already loaded & ready to receive messages\n\t\t\t\t\t\tpostVersionMessage(currentController);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (currentController) {\n\t\t\t\t\t\t\tconsole.log(`Found unexpected service worker controller. Found: ${currentController.scriptURL}. Expected: ${swPath}. Waiting for controllerchange.`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.log(`No service worker controller found. Waiting for controllerchange.`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Either there's no controlling service worker, or it's an old one.\n\t\t\t\t\t\t// Wait for it to change before posting the message\n\t\t\t\t\t\tconst onControllerChange = () => {\n\t\t\t\t\t\t\tnavigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);\n\t\t\t\t\t\t\tif (navigator.serviceWorker.controller) {\n\t\t\t\t\t\t\t\tpostVersionMessage(navigator.serviceWorker.controller);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn reject(new Error('No controller found.'));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\tnavigator.serviceWorker.addEventListener('controllerchange', onControllerChange);\n\t\t\t\t\t}\n\t\t\t\t}).catch(error => {\n\t\t\t\t\tif (!onElectron && error instanceof Error && error.message.includes('user denied permission')) {\n\t\t\t\t\t\treturn reject(new Error(`Could not register service worker. Please make sure third party cookies are enabled: ${error}`));\n\t\t\t\t\t}\n\t\t\t\t\treturn reject(new Error(`Could not register service worker: ${error}.`));\n\t\t\t\t});\n\t\t});\n\n\t\t/**\n\t\t *  @type {import('../webviewMessages').WebviewHostMessaging}\n\t\t */\n\t\tconst hostMessaging = new class HostMessaging {\n\n\t\t\tconstructor() {\n\t\t\t\tthis.channel = new MessageChannel();\n\n\t\t\t\t/** @type {Map<string, Array<(event: MessageEvent, data: any) => void>>} */\n\t\t\t\tthis.handlers = new Map();\n\n\t\t\t\tthis.channel.port1.onmessage = (e) => {\n\t\t\t\t\tconst channel = e.data.channel;\n\t\t\t\t\tconst handlers = this.handlers.get(channel);\n\t\t\t\t\tif (handlers) {\n\t\t\t\t\t\tfor (const handler of handlers) {\n\t\t\t\t\t\t\thandler(e, e.data.args);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log('no handler for ', e);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tpostMessage(channel, data, transfer) {\n\t\t\t\tthis.channel.port1.postMessage({ channel, data }, transfer);\n\t\t\t}\n\n\t\t\tonMessage(channel, handler) {\n\t\t\t\tlet handlers = this.handlers.get(channel);\n\t\t\t\tif (!handlers) {\n\t\t\t\t\thandlers = [];\n\t\t\t\t\tthis.handlers.set(channel, handlers);\n\t\t\t\t}\n\t\t\t\thandlers.push(handler);\n\t\t\t}\n\n\t\t\tasync signalReady() {\n\t\t\t\t/* below codes are changed by github1s */\n\t\t\t\tconst parentOrigin = searchParams.get('parentOrigin') || '';\n\t\t\t\twindow.parent.postMessage({ target: ID, channel: 'webview-ready', data: {} }, parentOrigin, [this.channel.port2]);\n\t\t\t\t/* above codes are changed by github1s */\n\t\t\t}\n\t\t}();\n\n\t\tconst unloadMonitor = new class {\n\n\t\t\tconstructor() {\n\t\t\t\tthis.confirmBeforeClose = 'keyboardOnly';\n\t\t\t\tthis.isModifierKeyDown = false;\n\n\t\t\t\thostMessaging.onMessage('set-confirm-before-close', (_e, data) => {\n\t\t\t\t\tthis.confirmBeforeClose = data;\n\t\t\t\t});\n\n\t\t\t\thostMessaging.onMessage('content', (_e, data) => {\n\t\t\t\t\tthis.confirmBeforeClose = data.confirmBeforeClose;\n\t\t\t\t});\n\n\t\t\t\twindow.addEventListener('beforeunload', (event) => {\n\t\t\t\t\tif (onElectron) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch (this.confirmBeforeClose) {\n\t\t\t\t\t\tcase 'always': {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.returnValue = '';\n\t\t\t\t\t\t\treturn '';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'never': {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'keyboardOnly':\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\tif (this.isModifierKeyDown) {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tevent.returnValue = '';\n\t\t\t\t\t\t\t\treturn '';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tonIframeLoaded(/** @type {HTMLIFrameElement} */ frame) {\n\t\t\t\tassertIsDefined(frame.contentWindow).addEventListener('keydown', e => {\n\t\t\t\t\tthis.isModifierKeyDown = e.metaKey || e.ctrlKey || e.altKey;\n\t\t\t\t});\n\n\t\t\t\tassertIsDefined(frame.contentWindow).addEventListener('keyup', () => {\n\t\t\t\t\tthis.isModifierKeyDown = false;\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\t// state\n\t\tlet firstLoad = true;\n\t\t/** @type {any} */\n\t\tlet loadTimeout;\n\t\tlet styleVersion = 0;\n\n\t\t/** @type {Array<{ readonly message: any, transfer?: ArrayBuffer[] }>} */\n\t\tlet pendingMessages = [];\n\n\t\tconst initData = {\n\t\t\t/** @type {number | undefined} */\n\t\t\tinitialScrollProgress: undefined,\n\n\t\t\t/** @type {{ [key: string]: string } | undefined} */\n\t\t\tstyles: undefined,\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tactiveTheme: undefined,\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tthemeId: undefined,\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tthemeLabel: undefined,\n\n\t\t\t/** @type {boolean} */\n\t\t\tscreenReader: false,\n\n\t\t\t/** @type {boolean} */\n\t\t\treduceMotion: false,\n\t\t};\n\n\t\tif (!disableServiceWorker) {\n\t\t\thostMessaging.onMessage('did-load-resource', (_event, data) => {\n\t\t\t\tassertIsDefined(navigator.serviceWorker.controller).postMessage({ channel: 'did-load-resource', data }, data.data?.buffer ? [data.data.buffer] : []);\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('did-load-localhost', (_event, data) => {\n\t\t\t\tassertIsDefined(navigator.serviceWorker.controller).postMessage({ channel: 'did-load-localhost', data });\n\t\t\t});\n\n\t\t\tnavigator.serviceWorker.addEventListener('message', event => {\n\t\t\t\tswitch (event.data.channel) {\n\t\t\t\t\tcase 'load-resource':\n\t\t\t\t\tcase 'load-localhost':\n\t\t\t\t\t\thostMessaging.postMessage(event.data.channel, event.data);\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * @param {HTMLDocument?} document\n\t\t * @param {HTMLElement?} body\n\t\t */\n\t\tconst applyStyles = (document, body) => {\n\t\t\tif (!document) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (body) {\n\t\t\t\tbody.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast', 'vscode-high-contrast-light', 'vscode-reduce-motion', 'vscode-using-screen-reader');\n\n\t\t\t\tif (initData.activeTheme) {\n\t\t\t\t\tbody.classList.add(initData.activeTheme);\n\t\t\t\t\tif (initData.activeTheme === 'vscode-high-contrast-light') {\n\t\t\t\t\t\t// backwards compatibility\n\t\t\t\t\t\tbody.classList.add('vscode-high-contrast');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (initData.reduceMotion) {\n\t\t\t\t\tbody.classList.add('vscode-reduce-motion');\n\t\t\t\t}\n\n\t\t\t\tif (initData.screenReader) {\n\t\t\t\t\tbody.classList.add('vscode-using-screen-reader');\n\t\t\t\t}\n\n\t\t\t\tbody.dataset.vscodeThemeKind = initData.activeTheme;\n\t\t\t\t/** @deprecated data-vscode-theme-name will be removed, use data-vscode-theme-id instead */\n\t\t\t\tbody.dataset.vscodeThemeName = initData.themeLabel || '';\n\t\t\t\tbody.dataset.vscodeThemeId = initData.themeId || '';\n\t\t\t}\n\n\t\t\tif (initData.styles) {\n\t\t\t\tconst documentStyle = document.documentElement.style;\n\n\t\t\t\t// Remove stale properties\n\t\t\t\tfor (let i = documentStyle.length - 1; i >= 0; i--) {\n\t\t\t\t\tconst property = documentStyle[i];\n\n\t\t\t\t\t// Don't remove properties that the webview might have added separately\n\t\t\t\t\tif (property && property.startsWith('--vscode-')) {\n\t\t\t\t\t\tdocumentStyle.removeProperty(property);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Re-add new properties\n\t\t\t\tfor (const [variable, value] of Object.entries(initData.styles)) {\n\t\t\t\t\tdocumentStyle.setProperty(`--${variable}`, value);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * @param {MouseEvent} event\n\t\t */\n\t\tconst handleInnerClick = (event) => {\n\t\t\tif (!event?.view?.document) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst baseElement = event.view.document.querySelector('base');\n\n\t\t\tfor (const pathElement of event.composedPath()) {\n\t\t\t\t/** @type {any} */\n\t\t\t\tconst node = pathElement;\n\t\t\t\tif (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) {\n\t\t\t\t\tif (node.getAttribute('href') === '#') {\n\t\t\t\t\t\tevent.view.scrollTo(0, 0);\n\t\t\t\t\t} else if (node.hash && (node.getAttribute('href') === node.hash || (baseElement && node.href === baseElement.href + node.hash))) {\n\t\t\t\t\t\tconst fragment = node.hash.slice(1);\n\t\t\t\t\t\tconst decodedFragment = decodeURIComponent(fragment);\n\t\t\t\t\t\tconst scrollTarget = event.view.document.getElementById(fragment) ?? event.view.document.getElementById(decodedFragment);\n\t\t\t\t\t\tif (scrollTarget) {\n\t\t\t\t\t\t\tscrollTarget.scrollIntoView();\n\t\t\t\t\t\t} else if (decodedFragment.toLowerCase() === 'top') {\n\t\t\t\t\t\t\tevent.view.scrollTo(0, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\thostMessaging.postMessage('did-click-link', { uri: node.href.baseVal || node.href });\n\t\t\t\t\t}\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * @param {MouseEvent} event\n\t\t */\n\t\tconst handleAuxClick = (event) => {\n\t\t\t// Prevent middle clicks opening a broken link in the browser\n\t\t\tif (!event?.view?.document) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (event.button === 1) {\n\t\t\t\tfor (const pathElement of event.composedPath()) {\n\t\t\t\t\t/** @type {any} */\n\t\t\t\t\tconst node = pathElement;\n\t\t\t\t\tif (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t */\n\t\tconst handleInnerKeydown = (e) => {\n\t\t\t// If the keypress would trigger a browser event, such as copy or paste,\n\t\t\t// make sure we block the browser from dispatching it. Instead VS Code\n\t\t\t// handles these events and will dispatch a copy/paste back to the webview\n\t\t\t// if needed\n\t\t\tif (isUndoRedo(e) || isPrint(e) || isFindEvent(e) || isSaveEvent(e)) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if (isCopyPasteOrCut(e)) {\n\t\t\t\tif (onElectron) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t} else {\n\t\t\t\t\treturn; // let the browser handle this\n\t\t\t\t}\n\t\t\t} else if (!onElectron && (isCloseTab(e) || isNewWindow(e) || isHelp(e) || isRefresh(e))) {\n\t\t\t\t// Prevent Ctrl+W closing window / Ctrl+N opening new window in PWA.\n\t\t\t\t// (No effect in a regular browser tab.)\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\thostMessaging.postMessage('did-keydown', {\n\t\t\t\tkey: e.key,\n\t\t\t\tkeyCode: e.keyCode,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\trepeat: e.repeat\n\t\t\t});\n\t\t};\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t */\n\t\tconst handleInnerKeyup = (e) => {\n\t\t\thostMessaging.postMessage('did-keyup', {\n\t\t\t\tkey: e.key,\n\t\t\t\tkeyCode: e.keyCode,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\trepeat: e.repeat\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isCopyPasteOrCut(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 45: keyCode of \"Insert\"\n\t\t\tconst shiftInsert = e.shiftKey && e.keyCode === 45;\n\t\t\t// 67, 86, 88: keyCode of \"C\", \"V\", \"X\"\n\t\t\treturn (hasMeta && [67, 86, 88].includes(e.keyCode)) || shiftInsert;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isUndoRedo(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 90, 89: keyCode of \"Z\", \"Y\"\n\t\t\treturn hasMeta && [90, 89].includes(e.keyCode);\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isPrint(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 80: keyCode of \"P\"\n\t\t\treturn hasMeta && e.keyCode === 80;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isFindEvent(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 70: keyCode of \"F\"\n\t\t\treturn hasMeta && e.keyCode === 70;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isSaveEvent(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 83: keyCode of \"S\"\n\t\t\treturn hasMeta && e.keyCode === 83;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isCloseTab(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 87: keyCode of \"W\"\n\t\t\treturn hasMeta && e.keyCode === 87;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isNewWindow(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 78: keyCode of \"N\"\n\t\t\treturn hasMeta && e.keyCode === 78;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isHelp(e) {\n\t\t\t// 112: keyCode of \"F1\"\n\t\t\treturn e.keyCode === 112;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isRefresh(e) {\n\t\t\t// 116: keyCode of \"F5\"\n\t\t\treturn e.keyCode === 116;\n\t\t}\n\n\t\tlet isHandlingScroll = false;\n\n\t\t/**\n\t\t * @param {WheelEvent} event\n\t\t */\n\t\tconst handleWheel = (event) => {\n\t\t\tif (isHandlingScroll) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thostMessaging.postMessage('did-scroll-wheel', {\n\t\t\t\tdeltaMode: event.deltaMode,\n\t\t\t\tdeltaX: event.deltaX,\n\t\t\t\tdeltaY: event.deltaY,\n\t\t\t\tdeltaZ: event.deltaZ,\n\t\t\t\tdetail: event.detail,\n\t\t\t\ttype: event.type\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * @param {Event} event\n\t\t */\n\t\tconst handleInnerScroll = (event) => {\n\t\t\tif (isHandlingScroll) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst target = /** @type {HTMLDocument | null} */ (event.target);\n\t\t\tconst currentTarget = /** @type {Window | null} */ (event.currentTarget);\n\t\t\tif (!currentTarget || !target?.body) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst progress = currentTarget.scrollY / target.body.clientHeight;\n\t\t\tif (isNaN(progress)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tisHandlingScroll = true;\n\t\t\twindow.requestAnimationFrame(() => {\n\t\t\t\ttry {\n\t\t\t\t\thostMessaging.postMessage('did-scroll', { scrollYPercentage: progress });\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t\tisHandlingScroll = false;\n\t\t\t});\n\t\t};\n\n\t\tfunction handleInnerDragStartEvent(/** @type {DragEvent} */ e) {\n\t\t\tif (e.defaultPrevented) {\n\t\t\t\t// Extension code has already handled this event\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!e.dataTransfer || e.shiftKey) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only handle drags from outside editor for now\n\t\t\tif (e.dataTransfer.items.length && Array.prototype.every.call(e.dataTransfer.items, item => item.kind === 'file')) {\n\t\t\t\thostMessaging.postMessage('drag-start', undefined);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * @param {() => void} callback\n\t\t */\n\t\tfunction onDomReady(callback) {\n\t\t\tif (document.readyState === 'interactive' || document.readyState === 'complete') {\n\t\t\t\tcallback();\n\t\t\t} else {\n\t\t\t\tdocument.addEventListener('DOMContentLoaded', callback);\n\t\t\t}\n\t\t}\n\n\t\tfunction areServiceWorkersEnabled() {\n\t\t\ttry {\n\t\t\t\treturn !!navigator.serviceWorker;\n\t\t\t} catch (e) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * @param {import('../webviewMessages').UpdateContentEvent} data\n\t\t * @return {string}\n\t\t */\n\t\tfunction toContentHtml(data) {\n\t\t\tconst options = data.options;\n\t\t\tconst text = data.contents;\n\t\t\tconst newDocument = new DOMParser().parseFromString(text, 'text/html');\n\n\t\t\tnewDocument.querySelectorAll('a').forEach(a => {\n\t\t\t\tif (!a.title) {\n\t\t\t\t\tconst href = a.getAttribute('href');\n\t\t\t\t\tif (typeof href === 'string') {\n\t\t\t\t\t\ta.title = href;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Set default aria role\n\t\t\tif (!newDocument.body.hasAttribute('role')) {\n\t\t\t\tnewDocument.body.setAttribute('role', 'document');\n\t\t\t}\n\n\t\t\t// Inject default script\n\t\t\tif (options.allowScripts) {\n\t\t\t\tconst defaultScript = newDocument.createElement('script');\n\t\t\t\tdefaultScript.id = '_vscodeApiScript';\n\t\t\t\tdefaultScript.textContent = getVsCodeApiScript(options.allowMultipleAPIAcquire, data.state);\n\t\t\t\tnewDocument.head.prepend(defaultScript);\n\t\t\t}\n\n\t\t\t// Inject default styles\n\t\t\tnewDocument.head.prepend(defaultStyles.cloneNode(true));\n\n\t\t\tapplyStyles(newDocument, newDocument.body);\n\n\t\t\t// Strip out unsupported http-equiv tags\n\t\t\tfor (const metaElement of Array.from(newDocument.querySelectorAll('meta'))) {\n\t\t\t\tconst httpEquiv = metaElement.getAttribute('http-equiv');\n\t\t\t\tif (httpEquiv && !/^(content-security-policy|default-style|content-type)$/i.test(httpEquiv)) {\n\t\t\t\t\tconsole.warn(`Removing unsupported meta http-equiv: ${httpEquiv}`);\n\t\t\t\t\tmetaElement.remove();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for CSP\n\t\t\tconst csp = newDocument.querySelector('meta[http-equiv=\"Content-Security-Policy\"]');\n\t\t\tif (!csp) {\n\t\t\t\thostMessaging.postMessage('no-csp-found', undefined);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\t// Attempt to rewrite CSPs that hardcode old-style resource endpoint\n\t\t\t\t\tconst cspContent = csp.getAttribute('content');\n\t\t\t\t\tif (cspContent) {\n\t\t\t\t\t\tconst newCsp = cspContent.replace(/(vscode-webview-resource|vscode-resource):(?=(\\s|;|$))/g, data.cspSource);\n\t\t\t\t\t\tcsp.setAttribute('content', newCsp);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(`Could not rewrite csp: ${e}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// set DOCTYPE for newDocument explicitly as DOMParser.parseFromString strips it off\n\t\t\t// and DOCTYPE is needed in the iframe to ensure that the user agent stylesheet is correctly overridden\n\t\t\treturn '<!DOCTYPE html>\\n' + newDocument.documentElement.outerHTML;\n\t\t}\n\n\t\t// Also forward events before the contents of the webview have loaded\n\t\twindow.addEventListener('keydown', handleInnerKeydown);\n\t\twindow.addEventListener('keyup', handleInnerKeyup);\n\t\twindow.addEventListener('dragenter', handleInnerDragStartEvent);\n\t\twindow.addEventListener('dragover', handleInnerDragStartEvent);\n\n\t\tonDomReady(() => {\n\t\t\tif (!document.body) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thostMessaging.onMessage('styles', (_event, data) => {\n\t\t\t\t++styleVersion;\n\n\t\t\t\tinitData.styles = data.styles;\n\t\t\t\tinitData.activeTheme = data.activeTheme;\n\t\t\t\tinitData.themeLabel = data.themeLabel;\n\t\t\t\tinitData.themeId = data.themeId;\n\t\t\t\tinitData.reduceMotion = data.reduceMotion;\n\t\t\t\tinitData.screenReader = data.screenReader;\n\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (target.contentDocument) {\n\t\t\t\t\tapplyStyles(target.contentDocument, target.contentDocument.body);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// propagate focus\n\t\t\thostMessaging.onMessage('focus', () => {\n\t\t\t\tconst activeFrame = getActiveFrame();\n\t\t\t\tif (!activeFrame || !activeFrame.contentWindow) {\n\t\t\t\t\t// Focus the top level webview instead\n\t\t\t\t\twindow.focus();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (document.activeElement === activeFrame) {\n\t\t\t\t\t// We are already focused on the iframe (or one of its children) so no need\n\t\t\t\t\t// to refocus.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tactiveFrame.contentWindow.focus();\n\t\t\t});\n\n\t\t\t// update iframe-contents\n\t\t\tlet updateId = 0;\n\t\t\thostMessaging.onMessage('content', async (_event, /** @type {import('../webviewMessages').UpdateContentEvent} */ data) => {\n\t\t\t\tconst currentUpdateId = ++updateId;\n\t\t\t\ttry {\n\t\t\t\t\tawait workerReady;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(`Webview fatal error: ${e}`);\n\t\t\t\t\thostMessaging.postMessage('fatal-error', { message: e + '' });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (currentUpdateId !== updateId) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst options = data.options;\n\t\t\t\tconst newDocument = toContentHtml(data);\n\n\t\t\t\tconst initialStyleVersion = styleVersion;\n\n\t\t\t\tconst frame = getActiveFrame();\n\t\t\t\tconst wasFirstLoad = firstLoad;\n\t\t\t\t// keep current scrollY around and use later\n\t\t\t\t/** @type {(body: HTMLElement, window: Window) => void} */\n\t\t\t\tlet setInitialScrollPosition;\n\t\t\t\tif (firstLoad) {\n\t\t\t\t\tfirstLoad = false;\n\t\t\t\t\tsetInitialScrollPosition = (body, window) => {\n\t\t\t\t\t\tif (typeof initData.initialScrollProgress === 'number' && !isNaN(initData.initialScrollProgress)) {\n\t\t\t\t\t\t\tif (window.scrollY === 0) {\n\t\t\t\t\t\t\t\twindow.scroll(0, body.clientHeight * initData.initialScrollProgress);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tconst scrollY = frame && frame.contentDocument && frame.contentDocument.body ? assertIsDefined(frame.contentWindow).scrollY : 0;\n\t\t\t\t\tsetInitialScrollPosition = (body, window) => {\n\t\t\t\t\t\tif (window.scrollY === 0) {\n\t\t\t\t\t\t\twindow.scroll(0, scrollY);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Clean up old pending frames and set current one as new one\n\t\t\t\tconst previousPendingFrame = getPendingFrame();\n\t\t\t\tif (previousPendingFrame) {\n\t\t\t\t\tpreviousPendingFrame.setAttribute('id', '');\n\t\t\t\t\tpreviousPendingFrame.remove();\n\t\t\t\t}\n\t\t\t\tif (!wasFirstLoad) {\n\t\t\t\t\tpendingMessages = [];\n\t\t\t\t}\n\n\t\t\t\tconst newFrame = document.createElement('iframe');\n\t\t\t\tnewFrame.title = data.title;\n\t\t\t\tnewFrame.setAttribute('id', 'pending-frame');\n\t\t\t\tnewFrame.setAttribute('frameborder', '0');\n\n\t\t\t\tconst sandboxRules = new Set(['allow-same-origin', 'allow-pointer-lock']);\n\t\t\t\tif (options.allowScripts) {\n\t\t\t\t\tsandboxRules.add('allow-scripts');\n\t\t\t\t\tsandboxRules.add('allow-downloads');\n\t\t\t\t}\n\t\t\t\tif (options.allowForms) {\n\t\t\t\t\tsandboxRules.add('allow-forms');\n\t\t\t\t}\n\t\t\t\tnewFrame.setAttribute('sandbox', Array.from(sandboxRules).join(' '));\n\n\t\t\t\tconst allowRules = ['cross-origin-isolated;', 'autoplay;'];\n\t\t\t\tif (!isFirefox && options.allowScripts) {\n\t\t\t\t\tallowRules.push('clipboard-read;', 'clipboard-write;');\n\t\t\t\t}\n\t\t\t\tnewFrame.setAttribute('allow', allowRules.join(' '));\n\t\t\t\t// We should just be able to use srcdoc, but I wasn't\n\t\t\t\t// seeing the service worker applying properly.\n\t\t\t\t// Fake load an empty on the correct origin and then write real html\n\t\t\t\t// into it to get around this.\n\t\t\t\tconst fakeUrlParams = new URLSearchParams({ id: ID });\n\t\t\t\tif (globalThis.crossOriginIsolated) {\n\t\t\t\t\tfakeUrlParams.set('vscode-coi', '3'); /*COOP+COEP*/\n\t\t\t\t}\n\t\t\t\tnewFrame.src = `./fake.html?${fakeUrlParams.toString()}`;\n\n\t\t\t\tnewFrame.style.cssText = 'display: block; margin: 0; overflow: hidden; position: absolute; width: 100%; height: 100%; visibility: hidden';\n\t\t\t\tdocument.body.appendChild(newFrame);\n\n\t\t\t\tnewFrame.contentWindow.addEventListener('keydown', handleInnerKeydown);\n\t\t\t\tnewFrame.contentWindow.addEventListener('keyup', handleInnerKeyup);\n\n\t\t\t\t/**\n\t\t\t\t * @param {Document} contentDocument\n\t\t\t\t */\n\t\t\t\tfunction onFrameLoaded(contentDocument) {\n\t\t\t\t\t// Workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=978325\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tcontentDocument.open();\n\t\t\t\t\t\tcontentDocument.write(newDocument);\n\t\t\t\t\t\tcontentDocument.close();\n\t\t\t\t\t\thookupOnLoadHandlers(newFrame);\n\n\t\t\t\t\t\tif (initialStyleVersion !== styleVersion) {\n\t\t\t\t\t\t\tapplyStyles(contentDocument, contentDocument.body);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\n\t\t\t\tif (!options.allowScripts && isSafari) {\n\t\t\t\t\t// On Safari for iframes with scripts disabled, the `DOMContentLoaded` never seems to be fired: https://bugs.webkit.org/show_bug.cgi?id=33604\n\t\t\t\t\t// Use polling instead.\n\t\t\t\t\tconst interval = setInterval(() => {\n\t\t\t\t\t\t// If the frame is no longer mounted, loading has stopped\n\t\t\t\t\t\tif (!newFrame.parentElement) {\n\t\t\t\t\t\t\tclearInterval(interval);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst contentDocument = assertIsDefined(newFrame.contentDocument);\n\t\t\t\t\t\tif (contentDocument.location.pathname.endsWith('/fake.html') && contentDocument.readyState !== 'loading') {\n\t\t\t\t\t\t\tclearInterval(interval);\n\t\t\t\t\t\t\tonFrameLoaded(contentDocument);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 10);\n\t\t\t\t} else {\n\t\t\t\t\tassertIsDefined(newFrame.contentWindow).addEventListener('DOMContentLoaded', e => {\n\t\t\t\t\t\tconst contentDocument = e.target ? (/** @type {HTMLDocument} */ (e.target)) : undefined;\n\t\t\t\t\t\tonFrameLoaded(assertIsDefined(contentDocument));\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * @param {Document} contentDocument\n\t\t\t\t * @param {Window} contentWindow\n\t\t\t\t */\n\t\t\t\tconst onLoad = (contentDocument, contentWindow) => {\n\t\t\t\t\tif (contentDocument && contentDocument.body) {\n\t\t\t\t\t\t// Workaround for https://github.com/microsoft/vscode/issues/12865\n\t\t\t\t\t\t// check new scrollY and reset if necessary\n\t\t\t\t\t\tsetInitialScrollPosition(contentDocument.body, contentWindow);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newFrame = getPendingFrame();\n\t\t\t\t\tif (newFrame && newFrame.contentDocument && newFrame.contentDocument === contentDocument) {\n\t\t\t\t\t\tconst wasFocused = document.hasFocus();\n\t\t\t\t\t\tconst oldActiveFrame = getActiveFrame();\n\t\t\t\t\t\toldActiveFrame?.remove();\n\t\t\t\t\t\t// Styles may have changed since we created the element. Make sure we re-style\n\t\t\t\t\t\tif (initialStyleVersion !== styleVersion) {\n\t\t\t\t\t\t\tapplyStyles(newFrame.contentDocument, newFrame.contentDocument.body);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnewFrame.setAttribute('id', 'active-frame');\n\t\t\t\t\t\tnewFrame.style.visibility = 'visible';\n\n\t\t\t\t\t\tcontentWindow.addEventListener('scroll', handleInnerScroll);\n\t\t\t\t\t\tcontentWindow.addEventListener('wheel', handleWheel);\n\n\t\t\t\t\t\tif (wasFocused) {\n\t\t\t\t\t\t\tcontentWindow.focus();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpendingMessages.forEach((message) => {\n\t\t\t\t\t\t\tcontentWindow.postMessage(message.message, window.origin, message.transfer);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpendingMessages = [];\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t/**\n\t\t\t\t * @param {HTMLIFrameElement} newFrame\n\t\t\t\t */\n\t\t\t\tfunction hookupOnLoadHandlers(newFrame) {\n\t\t\t\t\tclearTimeout(loadTimeout);\n\t\t\t\t\tloadTimeout = undefined;\n\t\t\t\t\tloadTimeout = setTimeout(() => {\n\t\t\t\t\t\tclearTimeout(loadTimeout);\n\t\t\t\t\t\tloadTimeout = undefined;\n\t\t\t\t\t\tonLoad(assertIsDefined(newFrame.contentDocument), assertIsDefined(newFrame.contentWindow));\n\t\t\t\t\t}, 200);\n\n\t\t\t\t\tconst contentWindow = assertIsDefined(newFrame.contentWindow);\n\n\t\t\t\t\tcontentWindow.addEventListener('load', function (e) {\n\t\t\t\t\t\tconst contentDocument = /** @type {Document} */ (e.target);\n\n\t\t\t\t\t\tif (loadTimeout) {\n\t\t\t\t\t\t\tclearTimeout(loadTimeout);\n\t\t\t\t\t\t\tloadTimeout = undefined;\n\t\t\t\t\t\t\tonLoad(contentDocument, this);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// Bubble out various events\n\t\t\t\t\tcontentWindow.addEventListener('click', handleInnerClick);\n\t\t\t\t\tcontentWindow.addEventListener('auxclick', handleAuxClick);\n\t\t\t\t\tcontentWindow.addEventListener('keydown', handleInnerKeydown);\n\t\t\t\t\tcontentWindow.addEventListener('keyup', handleInnerKeyup);\n\t\t\t\t\tcontentWindow.addEventListener('contextmenu', e => {\n\t\t\t\t\t\tif (e.defaultPrevented) {\n\t\t\t\t\t\t\t// Extension code has already handled this event\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t/** @type { Record<string, boolean>} */\n\t\t\t\t\t\tlet context = {};\n\n\t\t\t\t\t\t/** @type {HTMLElement | null} */\n\t\t\t\t\t\tlet el = e.target;\n\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\tif (!el) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Search self/ancestors for the closest context data attribute\n\t\t\t\t\t\t\tel = el.closest('[data-vscode-context]');\n\t\t\t\t\t\t\tif (!el) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tcontext = { ...JSON.parse(el.dataset.vscodeContext), ...context };\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\tconsole.error(`Error parsing 'data-vscode-context' as json`, el, e);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tel = el.parentElement;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thostMessaging.postMessage('did-context-menu', {\n\t\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\t\tcontext: context\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tcontentWindow.addEventListener('dragenter', handleInnerDragStartEvent);\n\t\t\t\t\tcontentWindow.addEventListener('dragover', handleInnerDragStartEvent);\n\n\t\t\t\t\tunloadMonitor.onIframeLoaded(newFrame);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// propagate vscode-context-menu-visible class\n\t\t\thostMessaging.onMessage('set-context-menu-visible', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (target && target.contentDocument) {\n\t\t\t\t\ttarget.contentDocument.body.classList.toggle('vscode-context-menu-visible', data.visible);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('set-title', async (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (target) {\n\t\t\t\t\ttarget.title = data;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Forward message to the embedded iframe\n\t\t\thostMessaging.onMessage('message', (_event, data) => {\n\t\t\t\tconst pending = getPendingFrame();\n\t\t\t\tif (!pending) {\n\t\t\t\t\tconst target = getActiveFrame();\n\t\t\t\t\tif (target) {\n\t\t\t\t\t\tassertIsDefined(target.contentWindow).postMessage(data.message, window.origin, data.transfer);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingMessages.push(data);\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('initial-scroll-position', (_event, progress) => {\n\t\t\t\tinitData.initialScrollProgress = progress;\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('execCommand', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tassertIsDefined(target.contentDocument).execCommand(data);\n\t\t\t});\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tlet lastFindValue = undefined;\n\n\t\t\thostMessaging.onMessage('find', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!data.previous && lastFindValue !== data.value && target.contentWindow) {\n\t\t\t\t\t// Reset selection so we start search at the head of the last search\n\t\t\t\t\tconst selection = target.contentWindow.getSelection();\n\t\t\t\t\tif (selection) {\n\t\t\t\t\t\tselection.collapse(selection.anchorNode);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastFindValue = data.value;\n\n\t\t\t\tconst didFind = (/** @type {any} */ (target.contentWindow)).find(\n\t\t\t\t\tdata.value,\n\t\t\t\t\t/* caseSensitive*/ false,\n\t\t\t\t\t/* backwards*/ data.previous,\n\t\t\t\t\t/* wrapAround*/ true,\n\t\t\t\t\t/* wholeWord */ false,\n\t\t\t\t\t/* searchInFrames*/ false,\n\t\t\t\t\tfalse);\n\t\t\t\thostMessaging.postMessage('did-find', didFind);\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('find-stop', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlastFindValue = undefined;\n\n\t\t\t\tif (!data.clearSelection && target.contentWindow) {\n\t\t\t\t\tconst selection = target.contentWindow.getSelection();\n\t\t\t\t\tif (selection) {\n\t\t\t\t\t\tfor (let i = 0; i < selection.rangeCount; i++) {\n\t\t\t\t\t\t\tselection.removeRange(selection.getRangeAt(i));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttrackFocus({\n\t\t\t\tonFocus: () => hostMessaging.postMessage('did-focus', undefined),\n\t\t\t\tonBlur: () => hostMessaging.postMessage('did-blur', undefined)\n\t\t\t});\n\n\t\t\t(/** @type {any} */ (window))[vscodePostMessageFuncName] = (/** @type {string} */ command, /** @type {any} */ data) => {\n\t\t\t\tswitch (command) {\n\t\t\t\t\tcase 'onmessage':\n\t\t\t\t\tcase 'do-update-state':\n\t\t\t\t\t\thostMessaging.postMessage(command, data);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\thostMessaging.signalReady();\n\t\t});\n\t</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/contrib/webview/browser/pre/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\" style=\"width: 100%; height: 100%;\">\n\n<head>\n\t<meta charset=\"UTF-8\">\n\n\t<!-- below codes are changed by github1s -->\n\t<meta http-equiv=\"Content-Security-Policy\"\n\t\tcontent=\"default-src 'none'; script-src 'unsafe-inline' 'self'; frame-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self' https: data:; media-src 'self' https: data:; font-src 'self' https: data:;\">\n\t<!-- above codes are changed by github1s -->\n\n\t<!-- Disable pinch zooming -->\n\t<meta name=\"viewport\"\n\t\tcontent=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no\">\n</head>\n\n<body style=\"margin: 0; overflow: hidden; width: 100%; height: 100%; overscroll-behavior-x: none;\" role=\"document\">\n\t<script async type=\"module\">\n\t\t// @ts-check\n\t\t/// <reference lib=\"dom\" />\n\n\t\tconst isSafari = (\n\t\t\tnavigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&\n\t\t\tnavigator.userAgent &&\n\t\t\tnavigator.userAgent.indexOf('CriOS') === -1 &&\n\t\t\tnavigator.userAgent.indexOf('FxiOS') === -1\n\t\t);\n\n\t\tconst isFirefox = (\n\t\t\tnavigator.userAgent &&\n\t\t\tnavigator.userAgent.indexOf('Firefox') >= 0\n\t\t);\n\n\t\tconst searchParams = new URL(location.toString()).searchParams;\n\t\tconst ID = searchParams.get('id');\n\t\tconst webviewOrigin = searchParams.get('origin');\n\t\tconst onElectron = searchParams.get('platform') === 'electron';\n\t\tconst disableServiceWorker = searchParams.has('disableServiceWorker');\n\t\tconst expectedWorkerVersion = parseInt(searchParams.get('swVersion'));\n\n\t\t/**\n\t\t * @param {string} name\n\t\t * @param {Record<string, string>} [options]\n\t\t */\n\t\tconst perfMark = (name, options = {}) => {\n\t\t\tperformance.mark(`webview/index.html/${name}`, {\n\t\t\t\tdetail: {\n\t\t\t\t\tid: ID,\n\t\t\t\t\t...options\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tperfMark('scriptStart');\n\n\t\t/** @type {MessageChannel | undefined} */\n\t\tlet outerIframeMessageChannel;\n\n\t\t/**\n\t\t * Use polling to track focus of main webview and iframes within the webview\n\t\t *\n\t\t * @param {Object} handlers\n\t\t * @param {() => void} handlers.onFocus\n\t\t * @param {() => void} handlers.onBlur\n\t\t */\n\t\tconst trackFocus = ({ onFocus, onBlur }) => {\n\t\t\tconst interval = 250;\n\t\t\tlet isFocused = document.hasFocus();\n\t\t\tsetInterval(() => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tconst isCurrentlyFocused = document.hasFocus() || !!(target && target.contentDocument && target.contentDocument.body.classList.contains('vscode-context-menu-visible'));\n\t\t\t\tif (isCurrentlyFocused === isFocused) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tisFocused = isCurrentlyFocused;\n\t\t\t\tif (isCurrentlyFocused) {\n\t\t\t\t\tonFocus();\n\t\t\t\t} else {\n\t\t\t\t\tonBlur();\n\t\t\t\t}\n\t\t\t}, interval);\n\t\t};\n\n\t\tconst getActiveFrame = () => {\n\t\t\treturn /** @type {HTMLIFrameElement | undefined} */ (document.getElementById('active-frame'));\n\t\t};\n\n\t\tconst getPendingFrame = () => {\n\t\t\treturn /** @type {HTMLIFrameElement | undefined} */ (document.getElementById('pending-frame'));\n\t\t};\n\n\t\t/**\n\t\t * @template T\n\t\t * @param {T | undefined | null} obj\n\t\t * @return {T}\n\t\t */\n\t\tfunction assertIsDefined(obj) {\n\t\t\tif (typeof obj === 'undefined' || obj === null) {\n\t\t\t\tthrow new Error('Found unexpected null');\n\t\t\t}\n\t\t\treturn obj;\n\t\t}\n\n\t\tconst vscodePostMessageFuncName = '__vscode_post_message__';\n\n\t\tconst defaultStyles = document.createElement('style');\n\t\tdefaultStyles.id = '_defaultStyles';\n\t\tdefaultStyles.textContent = `\n\t\t@layer vscode-default {\n\t\t\thtml {\n\t\t\t\tscrollbar-color: var(--vscode-scrollbarSlider-background) var(--vscode-editor-background);\n\t\t\t}\n\n\t\t\tbody {\n\t\t\t\toverscroll-behavior-x: none;\n\t\t\t\tbackground-color: transparent;\n\t\t\t\tcolor: var(--vscode-editor-foreground);\n\t\t\t\tfont-family: var(--vscode-font-family);\n\t\t\t\tfont-weight: var(--vscode-font-weight);\n\t\t\t\tfont-size: var(--vscode-font-size);\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0 20px;\n\t\t\t}\n\n\t\t\timg, video {\n\t\t\t\tmax-width: 100%;\n\t\t\t\tmax-height: 100%;\n\t\t\t}\n\n\t\t\ta, a code {\n\t\t\t\tcolor: var(--vscode-textLink-foreground);\n\t\t\t}\n\n\t\t\tp > a {\n\t\t\t\ttext-decoration: var(--text-link-decoration);\n\t\t\t}\n\n\t\t\ta:hover {\n\t\t\t\tcolor: var(--vscode-textLink-activeForeground);\n\t\t\t}\n\n\t\t\ta:focus,\n\t\t\tinput:focus,\n\t\t\tselect:focus,\n\t\t\ttextarea:focus {\n\t\t\t\toutline: 1px solid -webkit-focus-ring-color;\n\t\t\t\toutline-offset: -1px;\n\t\t\t}\n\n\t\t\tcode {\n\t\t\t\tfont-family: var(--monaco-monospace-font);\n\t\t\t\tcolor: var(--vscode-textPreformat-foreground);\n\t\t\t\tbackground-color: var(--vscode-textPreformat-background);\n\t\t\t\tpadding: 1px 3px;\n\t\t\t\tborder-radius: 4px;\n\t\t\t}\n\n\t\t\tpre code {\n\t\t\t\tpadding: 0;\n\t\t\t}\n\n\t\t\tblockquote {\n\t\t\t\tbackground: var(--vscode-textBlockQuote-background);\n\t\t\t\tborder-color: var(--vscode-textBlockQuote-border);\n\t\t\t}\n\n\t\t\tkbd {\n\t\t\t\tbackground-color: var(--vscode-keybindingLabel-background);\n\t\t\t\tcolor: var(--vscode-keybindingLabel-foreground);\n\t\t\t\tborder-style: solid;\n\t\t\t\tborder-width: 1px;\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tborder-color: var(--vscode-keybindingLabel-border);\n\t\t\t\tborder-bottom-color: var(--vscode-keybindingLabel-bottomBorder);\n\t\t\t\tbox-shadow: inset 0 -1px 0 var(--vscode-widget-shadow);\n\t\t\t\tvertical-align: middle;\n\t\t\t\tpadding: 1px 3px;\n\t\t\t}\n\n\t\t\t::-webkit-scrollbar {\n\t\t\t\twidth: 10px;\n\t\t\t\theight: 10px;\n\t\t\t}\n\n\t\t\t::-webkit-scrollbar-corner {\n\t\t\t\tbackground-color: var(--vscode-editor-background);\n\t\t\t}\n\n\t\t\t::-webkit-scrollbar-thumb {\n\t\t\t\tbackground-color: var(--vscode-scrollbarSlider-background);\n\t\t\t}\n\t\t\t::-webkit-scrollbar-thumb:hover {\n\t\t\t\tbackground-color: var(--vscode-scrollbarSlider-hoverBackground);\n\t\t\t}\n\t\t\t::-webkit-scrollbar-thumb:active {\n\t\t\t\tbackground-color: var(--vscode-scrollbarSlider-activeBackground);\n\t\t\t}\n\t\t\t::highlight(find-highlight) {\n\t\t\t\tbackground-color: var(--vscode-editor-findMatchHighlightBackground);\n\t\t\t}\n\t\t\t::highlight(current-find-highlight) {\n\t\t\t\tbackground-color: var(--vscode-editor-findMatchBackground);\n\t\t\t}\n\t\t}`;\n\n\t\t/**\n\t\t * @param {boolean} allowMultipleAPIAcquire\n\t\t * @param {*} [state]\n\t\t * @return {string}\n\t\t */\n\t\tfunction getVsCodeApiScript(allowMultipleAPIAcquire, state) {\n\t\t\tconst encodedState = state ? encodeURIComponent(state) : undefined;\n\t\t\treturn /* js */`\n\t\t\t\t\tglobalThis.acquireVsCodeApi = (function() {\n\t\t\t\t\t\tconst originalPostMessage = window.parent['${vscodePostMessageFuncName}'].bind(window.parent);\n\t\t\t\t\t\tconst doPostMessage = (channel, data, transfer) => {\n\t\t\t\t\t\t\toriginalPostMessage(channel, data, transfer);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tlet acquired = false;\n\n\t\t\t\t\t\tlet state = ${state ? `JSON.parse(decodeURIComponent(\"${encodedState}\"))` : undefined};\n\n\t\t\t\t\t\treturn () => {\n\t\t\t\t\t\t\tif (acquired && !${allowMultipleAPIAcquire}) {\n\t\t\t\t\t\t\t\tthrow new Error('An instance of the VS Code API has already been acquired');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tacquired = true;\n\t\t\t\t\t\t\treturn Object.freeze({\n\t\t\t\t\t\t\t\tpostMessage: function(message, transfer) {\n\t\t\t\t\t\t\t\t\tdoPostMessage('onmessage', { message, transfer }, transfer);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsetState: function(newState) {\n\t\t\t\t\t\t\t\t\tstate = newState;\n\t\t\t\t\t\t\t\t\tdoPostMessage('do-update-state', JSON.stringify(newState));\n\t\t\t\t\t\t\t\t\treturn newState;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tgetState: function() {\n\t\t\t\t\t\t\t\t\treturn state;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t};\n\t\t\t\t\t})();\n\t\t\t\t\twindow.parent = window;\n\t\t\t\t\twindow.top = window;\n\t\t\t\t\twindow.frameElement = null;\n\t\t\t\t`;\n\t\t}\n\n\t\t/** @type {Promise<void>} */\n\t\tconst workerReady = new Promise((resolve, reject) => {\n\t\t\tif (disableServiceWorker) {\n\t\t\t\treturn resolve();\n\t\t\t}\n\n\t\t\tif (!areServiceWorkersEnabled()) {\n\t\t\t\treturn reject(new Error('Service Workers are not enabled. Webviews will not work. Try disabling private/incognito mode.'));\n\t\t\t}\n\n\t\t\tconst swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}`);\n\t\t\tnavigator.serviceWorker.register(swPath, { type: 'module' })\n\t\t\t\t.then(async registration => {\n\t\t\t\t\t/**\n\t\t\t\t\t * @param {MessageEvent} event\n\t\t\t\t\t */\n\t\t\t\t\tconst versionHandler = async (event) => {\n\t\t\t\t\t\tif (event.data.channel !== 'version') {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnavigator.serviceWorker.removeEventListener('message', versionHandler);\n\t\t\t\t\t\tif (event.data.version === expectedWorkerVersion) {\n\t\t\t\t\t\t\treturn resolve();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.log(`Found unexpected service worker version. Found: ${event.data.version}. Expected: ${expectedWorkerVersion}`);\n\t\t\t\t\t\t\tconsole.log(`Attempting to reload service worker`);\n\n\t\t\t\t\t\t\t// If we have the wrong version, try once (and only once) to unregister and re-register\n\t\t\t\t\t\t\t// Note that `.update` doesn't seem to work desktop electron at the moment so we use\n\t\t\t\t\t\t\t// `unregister` and `register` here.\n\t\t\t\t\t\t\treturn registration.unregister()\n\t\t\t\t\t\t\t\t.then(() => navigator.serviceWorker.register(swPath))\n\t\t\t\t\t\t\t\t.finally(() => { resolve(); });\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tnavigator.serviceWorker.addEventListener('message', versionHandler);\n\n\t\t\t\t\tconst postVersionMessage = (/** @type {ServiceWorker} */ controller) => {\n\t\t\t\t\t\touterIframeMessageChannel = new MessageChannel();\n\t\t\t\t\t\tcontroller.postMessage({ channel: 'version' }, [outerIframeMessageChannel.port2]);\n\t\t\t\t\t};\n\n\t\t\t\t\t// At this point, either the service worker is ready and\n\t\t\t\t\t// became our controller, or we need to wait for it.\n\t\t\t\t\t// Note that navigator.serviceWorker.controller could be a\n\t\t\t\t\t// controller from a previously loaded service worker.\n\t\t\t\t\tconst currentController = navigator.serviceWorker.controller;\n\t\t\t\t\tif (currentController?.scriptURL.endsWith(swPath)) {\n\t\t\t\t\t\t// service worker already loaded & ready to receive messages\n\t\t\t\t\t\tpostVersionMessage(currentController);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (currentController) {\n\t\t\t\t\t\t\tconsole.log(`Found unexpected service worker controller. Found: ${currentController.scriptURL}. Expected: ${swPath}. Waiting for controllerchange.`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.log(`No service worker controller found. Waiting for controllerchange.`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Either there's no controlling service worker, or it's an old one.\n\t\t\t\t\t\t// Wait for it to change before posting the message\n\t\t\t\t\t\tconst onControllerChange = () => {\n\t\t\t\t\t\t\tnavigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);\n\t\t\t\t\t\t\tif (navigator.serviceWorker.controller) {\n\t\t\t\t\t\t\t\tpostVersionMessage(navigator.serviceWorker.controller);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn reject(new Error('No controller found.'));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\tnavigator.serviceWorker.addEventListener('controllerchange', onControllerChange);\n\t\t\t\t\t}\n\t\t\t\t}).catch(error => {\n\t\t\t\t\tif (!onElectron && error instanceof Error && error.message.includes('user denied permission')) {\n\t\t\t\t\t\treturn reject(new Error(`Could not register service worker. Please make sure third party cookies are enabled: ${error}`));\n\t\t\t\t\t}\n\t\t\t\t\treturn reject(new Error(`Could not register service worker: ${error}.`));\n\t\t\t\t});\n\t\t});\n\n\t\t/**\n\t\t *  @type {import('../webviewMessages').WebviewHostMessaging}\n\t\t */\n\t\tconst hostMessaging = new class HostMessaging {\n\n\t\t\tconstructor() {\n\t\t\t\tthis.channel = new MessageChannel();\n\n\t\t\t\t/** @type {Map<string, Array<(event: MessageEvent, data: any) => void>>} */\n\t\t\t\tthis.handlers = new Map();\n\n\t\t\t\tthis.channel.port1.onmessage = (e) => {\n\t\t\t\t\tconst channel = e.data.channel;\n\t\t\t\t\tconst handlers = this.handlers.get(channel);\n\t\t\t\t\tif (handlers) {\n\t\t\t\t\t\tfor (const handler of handlers) {\n\t\t\t\t\t\t\thandler(e, e.data.args);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log('no handler for ', e);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tpostMessage(channel, data, transfer) {\n\t\t\t\tthis.channel.port1.postMessage({ channel, data }, transfer);\n\t\t\t}\n\n\t\t\tonMessage(channel, handler) {\n\t\t\t\tlet handlers = this.handlers.get(channel);\n\t\t\t\tif (!handlers) {\n\t\t\t\t\thandlers = [];\n\t\t\t\t\tthis.handlers.set(channel, handlers);\n\t\t\t\t}\n\t\t\t\thandlers.push(handler);\n\t\t\t}\n\n\t\t\tasync signalReady() {\n\t\t\t\t/* below codes are changed by github1s */\n\t\t\t\tconst parentOrigin = searchParams.get('parentOrigin') || '';\n\t\t\t\twindow.parent.postMessage({ target: ID, channel: 'webview-ready', data: {} }, parentOrigin, [this.channel.port2]);\n\t\t\t\t/* above codes are changed by github1s */\n\t\t\t}\n\t\t}();\n\n\t\tconst unloadMonitor = new class {\n\n\t\t\tconstructor() {\n\t\t\t\tthis.confirmBeforeClose = 'keyboardOnly';\n\t\t\t\tthis.isModifierKeyDown = false;\n\n\t\t\t\thostMessaging.onMessage('set-confirm-before-close', (_e, data) => {\n\t\t\t\t\tthis.confirmBeforeClose = data;\n\t\t\t\t});\n\n\t\t\t\thostMessaging.onMessage('content', (_e, data) => {\n\t\t\t\t\tthis.confirmBeforeClose = data.confirmBeforeClose;\n\t\t\t\t});\n\n\t\t\t\twindow.addEventListener('beforeunload', (event) => {\n\t\t\t\t\tif (onElectron) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch (this.confirmBeforeClose) {\n\t\t\t\t\t\tcase 'always': {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.returnValue = '';\n\t\t\t\t\t\t\treturn '';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'never': {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'keyboardOnly':\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\tif (this.isModifierKeyDown) {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tevent.returnValue = '';\n\t\t\t\t\t\t\t\treturn '';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tonIframeLoaded(/** @type {HTMLIFrameElement} */ frame) {\n\t\t\t\tassertIsDefined(frame.contentWindow).addEventListener('keydown', e => {\n\t\t\t\t\tthis.isModifierKeyDown = e.metaKey || e.ctrlKey || e.altKey;\n\t\t\t\t});\n\n\t\t\t\tassertIsDefined(frame.contentWindow).addEventListener('keyup', () => {\n\t\t\t\t\tthis.isModifierKeyDown = false;\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\t// state\n\t\tlet firstLoad = true;\n\t\t/** @type {any} */\n\t\tlet loadTimeout;\n\t\tlet styleVersion = 0;\n\n\t\t/** @type {Array<{ readonly message: any, transfer?: ArrayBuffer[] }>} */\n\t\tlet pendingMessages = [];\n\n\t\tconst initData = {\n\t\t\t/** @type {number | undefined} */\n\t\t\tinitialScrollProgress: undefined,\n\n\t\t\t/** @type {{ [key: string]: string } | undefined} */\n\t\t\tstyles: undefined,\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tactiveTheme: undefined,\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tthemeId: undefined,\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tthemeLabel: undefined,\n\n\t\t\t/** @type {boolean} */\n\t\t\tscreenReader: false,\n\n\t\t\t/** @type {boolean} */\n\t\t\treduceMotion: false,\n\t\t};\n\n\t\tif (!disableServiceWorker) {\n\t\t\thostMessaging.onMessage('did-load-resource', (_event, data) => {\n\t\t\t\tassertIsDefined(navigator.serviceWorker.controller).postMessage({ channel: 'did-load-resource', data }, data.data?.buffer ? [data.data.buffer] : []);\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('did-load-localhost', (_event, data) => {\n\t\t\t\tassertIsDefined(navigator.serviceWorker.controller).postMessage({ channel: 'did-load-localhost', data });\n\t\t\t});\n\n\t\t\tnavigator.serviceWorker.addEventListener('message', event => {\n\t\t\t\tswitch (event.data.channel) {\n\t\t\t\t\tcase 'load-resource':\n\t\t\t\t\tcase 'load-localhost':\n\t\t\t\t\t\thostMessaging.postMessage(event.data.channel, event.data);\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * @param {HTMLDocument?} document\n\t\t * @param {HTMLElement?} body\n\t\t */\n\t\tconst applyStyles = (document, body) => {\n\t\t\tif (!document) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (body) {\n\t\t\t\tbody.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast', 'vscode-high-contrast-light', 'vscode-reduce-motion', 'vscode-using-screen-reader');\n\n\t\t\t\tif (initData.activeTheme) {\n\t\t\t\t\tbody.classList.add(initData.activeTheme);\n\t\t\t\t\tif (initData.activeTheme === 'vscode-high-contrast-light') {\n\t\t\t\t\t\t// backwards compatibility\n\t\t\t\t\t\tbody.classList.add('vscode-high-contrast');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (initData.reduceMotion) {\n\t\t\t\t\tbody.classList.add('vscode-reduce-motion');\n\t\t\t\t}\n\n\t\t\t\tif (initData.screenReader) {\n\t\t\t\t\tbody.classList.add('vscode-using-screen-reader');\n\t\t\t\t}\n\n\t\t\t\tbody.dataset.vscodeThemeKind = initData.activeTheme;\n\t\t\t\t/** @deprecated data-vscode-theme-name will be removed, use data-vscode-theme-id instead */\n\t\t\t\tbody.dataset.vscodeThemeName = initData.themeLabel || '';\n\t\t\t\tbody.dataset.vscodeThemeId = initData.themeId || '';\n\t\t\t}\n\n\t\t\tif (initData.styles) {\n\t\t\t\tconst documentStyle = document.documentElement.style;\n\n\t\t\t\t// Remove stale properties\n\t\t\t\tfor (let i = documentStyle.length - 1; i >= 0; i--) {\n\t\t\t\t\tconst property = documentStyle[i];\n\n\t\t\t\t\t// Don't remove properties that the webview might have added separately\n\t\t\t\t\tif (property && property.startsWith('--vscode-')) {\n\t\t\t\t\t\tdocumentStyle.removeProperty(property);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Re-add new properties\n\t\t\t\tfor (const [variable, value] of Object.entries(initData.styles)) {\n\t\t\t\t\tdocumentStyle.setProperty(`--${variable}`, value);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * @param {MouseEvent} event\n\t\t */\n\t\tconst handleInnerClick = (event) => {\n\t\t\tif (!event?.view?.document) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst baseElement = event.view.document.querySelector('base');\n\n\t\t\tfor (const pathElement of event.composedPath()) {\n\t\t\t\t/** @type {any} */\n\t\t\t\tconst node = pathElement;\n\t\t\t\tif (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) {\n\t\t\t\t\tif (node.getAttribute('href') === '#') {\n\t\t\t\t\t\tevent.view.scrollTo(0, 0);\n\t\t\t\t\t} else if (node.hash && (node.getAttribute('href') === node.hash || (baseElement && node.href === baseElement.href + node.hash))) {\n\t\t\t\t\t\tconst fragment = node.hash.slice(1);\n\t\t\t\t\t\tconst decodedFragment = decodeURIComponent(fragment);\n\t\t\t\t\t\tconst scrollTarget = event.view.document.getElementById(fragment) ?? event.view.document.getElementById(decodedFragment);\n\t\t\t\t\t\tif (scrollTarget) {\n\t\t\t\t\t\t\tscrollTarget.scrollIntoView();\n\t\t\t\t\t\t} else if (decodedFragment.toLowerCase() === 'top') {\n\t\t\t\t\t\t\tevent.view.scrollTo(0, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\thostMessaging.postMessage('did-click-link', { uri: node.href.baseVal || node.href });\n\t\t\t\t\t}\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * @param {MouseEvent} event\n\t\t */\n\t\tconst handleAuxClick = (event) => {\n\t\t\t// Prevent middle clicks opening a broken link in the browser\n\t\t\tif (!event?.view?.document) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (event.button === 1) {\n\t\t\t\tfor (const pathElement of event.composedPath()) {\n\t\t\t\t\t/** @type {any} */\n\t\t\t\t\tconst node = pathElement;\n\t\t\t\t\tif (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t */\n\t\tconst handleInnerKeydown = (e) => {\n\t\t\t// If the keypress would trigger a browser event, such as copy or paste,\n\t\t\t// make sure we block the browser from dispatching it. Instead VS Code\n\t\t\t// handles these events and will dispatch a copy/paste back to the webview\n\t\t\t// if needed\n\t\t\tif (isUndoRedo(e) || isPrint(e) || isFindEvent(e) || isSaveEvent(e)) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if (isCopyPasteOrCut(e)) {\n\t\t\t\tif (onElectron) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t} else {\n\t\t\t\t\treturn; // let the browser handle this\n\t\t\t\t}\n\t\t\t} else if (!onElectron && (isCloseTab(e) || isNewWindow(e) || isHelp(e) || isRefresh(e))) {\n\t\t\t\t// Prevent Ctrl+W closing window / Ctrl+N opening new window in PWA.\n\t\t\t\t// (No effect in a regular browser tab.)\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\thostMessaging.postMessage('did-keydown', {\n\t\t\t\tkey: e.key,\n\t\t\t\tkeyCode: e.keyCode,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\trepeat: e.repeat\n\t\t\t});\n\t\t};\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t */\n\t\tconst handleInnerKeyup = (e) => {\n\t\t\thostMessaging.postMessage('did-keyup', {\n\t\t\t\tkey: e.key,\n\t\t\t\tkeyCode: e.keyCode,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\trepeat: e.repeat\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isCopyPasteOrCut(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 45: keyCode of \"Insert\"\n\t\t\tconst shiftInsert = e.shiftKey && e.keyCode === 45;\n\t\t\t// 67, 86, 88: keyCode of \"C\", \"V\", \"X\"\n\t\t\treturn (hasMeta && [67, 86, 88].includes(e.keyCode)) || shiftInsert;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isUndoRedo(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 90, 89: keyCode of \"Z\", \"Y\"\n\t\t\treturn hasMeta && [90, 89].includes(e.keyCode);\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isPrint(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 80: keyCode of \"P\"\n\t\t\treturn hasMeta && e.keyCode === 80;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isFindEvent(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 70: keyCode of \"F\"\n\t\t\treturn hasMeta && e.keyCode === 70;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isSaveEvent(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 83: keyCode of \"S\"\n\t\t\treturn hasMeta && e.keyCode === 83;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isCloseTab(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 87: keyCode of \"W\"\n\t\t\treturn hasMeta && e.keyCode === 87;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isNewWindow(e) {\n\t\t\tconst hasMeta = e.ctrlKey || e.metaKey;\n\t\t\t// 78: keyCode of \"N\"\n\t\t\treturn hasMeta && e.keyCode === 78;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isHelp(e) {\n\t\t\t// 112: keyCode of \"F1\"\n\t\t\treturn e.keyCode === 112;\n\t\t}\n\n\t\t/**\n\t\t * @param {KeyboardEvent} e\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isRefresh(e) {\n\t\t\t// 116: keyCode of \"F5\"\n\t\t\treturn e.keyCode === 116;\n\t\t}\n\n\t\tlet isHandlingScroll = false;\n\n\t\t/**\n\t\t * @param {WheelEvent} event\n\t\t */\n\t\tconst handleWheel = (event) => {\n\t\t\tif (isHandlingScroll) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thostMessaging.postMessage('did-scroll-wheel', {\n\t\t\t\tdeltaMode: event.deltaMode,\n\t\t\t\tdeltaX: event.deltaX,\n\t\t\t\tdeltaY: event.deltaY,\n\t\t\t\tdeltaZ: event.deltaZ,\n\t\t\t\tdetail: event.detail,\n\t\t\t\ttype: event.type\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * @param {Event} event\n\t\t */\n\t\tconst handleInnerScroll = (event) => {\n\t\t\tif (isHandlingScroll) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst target = /** @type {HTMLDocument | null} */ (event.target);\n\t\t\tconst currentTarget = /** @type {Window | null} */ (event.currentTarget);\n\t\t\tif (!currentTarget || !target?.body) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst progress = currentTarget.scrollY / target.body.clientHeight;\n\t\t\tif (isNaN(progress)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tisHandlingScroll = true;\n\t\t\twindow.requestAnimationFrame(() => {\n\t\t\t\ttry {\n\t\t\t\t\thostMessaging.postMessage('did-scroll', { scrollYPercentage: progress });\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t\tisHandlingScroll = false;\n\t\t\t});\n\t\t};\n\n\t\tfunction handleInnerDragStartEvent(/** @type {DragEvent} */ e) {\n\t\t\tif (e.defaultPrevented) {\n\t\t\t\t// Extension code has already handled this event\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!e.dataTransfer || e.shiftKey) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only handle drags from outside editor for now\n\t\t\tif (e.dataTransfer.items.length && Array.prototype.every.call(e.dataTransfer.items, item => item.kind === 'file')) {\n\t\t\t\thostMessaging.postMessage('drag-start', undefined);\n\t\t\t}\n\t\t}\n\n\n\t\tfunction handleInnerDragEvent(/** @type {DragEvent} */ e) {\n\t\t\t/**\n\t\t\t * To ensure that the drop event always fires as expected, you should always include a preventDefault() call in the part of your code which handles the dragover event.\n\t\t\t * source: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event\n\t\t\t **/\n\t\t\te.preventDefault();\n\n\t\t\tif (!e.dataTransfer) {\n\t\t\t\treturn;\n\t\t\t}\n\n\n\t\t\t// Only handle drags from outside editor for now\n\t\t\tif (e.dataTransfer.items.length && Array.prototype.every.call(e.dataTransfer.items, item => item.kind === 'file')) {\n\t\t\t\thostMessaging.postMessage('drag', {\n\t\t\t\t\tshiftKey: e.shiftKey\n\t\t\t\t});\n\t\t\t}\n\n\t\t}\n\n\t\tfunction handleInnerDropEvent(/**@type {DragEvent} */e) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\t/**\n\t\t * @param {() => void} callback\n\t\t */\n\t\tfunction onDomReady(callback) {\n\t\t\tif (document.readyState === 'interactive' || document.readyState === 'complete') {\n\t\t\t\tcallback();\n\t\t\t} else {\n\t\t\t\tdocument.addEventListener('DOMContentLoaded', callback);\n\t\t\t}\n\t\t}\n\n\t\tfunction areServiceWorkersEnabled() {\n\t\t\ttry {\n\t\t\t\treturn !!navigator.serviceWorker;\n\t\t\t} catch (e) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * @param {import('../webviewMessages').UpdateContentEvent} data\n\t\t * @return {string}\n\t\t */\n\t\tfunction toContentHtml(data) {\n\t\t\tconst options = data.options;\n\t\t\tconst text = data.contents;\n\t\t\tconst newDocument = new DOMParser().parseFromString(text, 'text/html');\n\n\t\t\tnewDocument.querySelectorAll('a').forEach(a => {\n\t\t\t\tif (!a.title) {\n\t\t\t\t\tconst href = a.getAttribute('href');\n\t\t\t\t\tif (typeof href === 'string') {\n\t\t\t\t\t\ta.title = href;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Set default aria role\n\t\t\tif (!newDocument.body.hasAttribute('role')) {\n\t\t\t\tnewDocument.body.setAttribute('role', 'document');\n\t\t\t}\n\n\t\t\t// Inject default script\n\t\t\tif (options.allowScripts) {\n\t\t\t\tconst defaultScript = newDocument.createElement('script');\n\t\t\t\tdefaultScript.id = '_vscodeApiScript';\n\t\t\t\tdefaultScript.textContent = getVsCodeApiScript(options.allowMultipleAPIAcquire, data.state);\n\t\t\t\tnewDocument.head.prepend(defaultScript);\n\t\t\t}\n\n\t\t\t// Inject default styles\n\t\t\tnewDocument.head.prepend(defaultStyles.cloneNode(true));\n\n\t\t\tapplyStyles(newDocument, newDocument.body);\n\n\t\t\t// Strip out unsupported http-equiv tags\n\t\t\tfor (const metaElement of Array.from(newDocument.querySelectorAll('meta'))) {\n\t\t\t\tconst httpEquiv = metaElement.getAttribute('http-equiv');\n\t\t\t\tif (httpEquiv && !/^(content-security-policy|default-style|content-type)$/i.test(httpEquiv)) {\n\t\t\t\t\tconsole.warn(`Removing unsupported meta http-equiv: ${httpEquiv}`);\n\t\t\t\t\tmetaElement.remove();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for CSP\n\t\t\tconst csp = newDocument.querySelector('meta[http-equiv=\"Content-Security-Policy\"]');\n\t\t\tif (!csp) {\n\t\t\t\thostMessaging.postMessage('no-csp-found', undefined);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\t// Attempt to rewrite CSPs that hardcode old-style resource endpoint\n\t\t\t\t\tconst cspContent = csp.getAttribute('content');\n\t\t\t\t\tif (cspContent) {\n\t\t\t\t\t\tconst newCsp = cspContent.replace(/(vscode-webview-resource|vscode-resource):(?=(\\s|;|$))/g, data.cspSource);\n\t\t\t\t\t\tcsp.setAttribute('content', newCsp);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(`Could not rewrite csp: ${e}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// set DOCTYPE for newDocument explicitly as DOMParser.parseFromString strips it off\n\t\t\t// and DOCTYPE is needed in the iframe to ensure that the user agent stylesheet is correctly overridden\n\t\t\treturn '<!DOCTYPE html>\\n' + newDocument.documentElement.outerHTML;\n\t\t}\n\n\t\t// Also forward events before the contents of the webview have loaded\n\t\twindow.addEventListener('keydown', handleInnerKeydown);\n\t\twindow.addEventListener('keyup', handleInnerKeyup);\n\t\twindow.addEventListener('dragenter', handleInnerDragStartEvent);\n\t\twindow.addEventListener('dragover', handleInnerDragEvent);\n\t\twindow.addEventListener('drag', handleInnerDragEvent);\n\t\twindow.addEventListener('drop', handleInnerDropEvent);\n\n\n\t\tonDomReady(() => {\n\t\t\tif (!document.body) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thostMessaging.onMessage('styles', (_event, data) => {\n\t\t\t\t++styleVersion;\n\n\t\t\t\tinitData.styles = data.styles;\n\t\t\t\tinitData.activeTheme = data.activeTheme;\n\t\t\t\tinitData.themeLabel = data.themeLabel;\n\t\t\t\tinitData.themeId = data.themeId;\n\t\t\t\tinitData.reduceMotion = data.reduceMotion;\n\t\t\t\tinitData.screenReader = data.screenReader;\n\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (target.contentDocument) {\n\t\t\t\t\tapplyStyles(target.contentDocument, target.contentDocument.body);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// propagate focus\n\t\t\thostMessaging.onMessage('focus', () => {\n\t\t\t\tconst activeFrame = getActiveFrame();\n\t\t\t\tif (!activeFrame || !activeFrame.contentWindow) {\n\t\t\t\t\t// Focus the top level webview instead\n\t\t\t\t\twindow.focus();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (document.activeElement === activeFrame) {\n\t\t\t\t\t// We are already focused on the iframe (or one of its children) so no need\n\t\t\t\t\t// to refocus.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tactiveFrame.contentWindow.focus();\n\t\t\t});\n\n\t\t\t// update iframe-contents\n\t\t\tlet updateId = 0;\n\t\t\thostMessaging.onMessage('content', async (_event, /** @type {import('../webviewMessages').UpdateContentEvent} */ data) => {\n\t\t\t\tperfMark('content/started');\n\n\t\t\t\tconst currentUpdateId = ++updateId;\n\t\t\t\ttry {\n\t\t\t\t\tawait workerReady;\n\t\t\t\t\tperfMark('content/workerReady');\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(`Webview fatal error: ${e}`);\n\t\t\t\t\thostMessaging.postMessage('fatal-error', { message: e + '' });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (currentUpdateId !== updateId) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst options = data.options;\n\t\t\t\tconst newDocument = toContentHtml(data);\n\n\t\t\t\tconst initialStyleVersion = styleVersion;\n\n\t\t\t\tconst frame = getActiveFrame();\n\t\t\t\tconst wasFirstLoad = firstLoad;\n\t\t\t\t// keep current scrollY around and use later\n\t\t\t\t/** @type {(body: HTMLElement, window: Window) => void} */\n\t\t\t\tlet setInitialScrollPosition;\n\t\t\t\tif (firstLoad) {\n\t\t\t\t\tfirstLoad = false;\n\t\t\t\t\tsetInitialScrollPosition = (body, window) => {\n\t\t\t\t\t\tif (typeof initData.initialScrollProgress === 'number' && !isNaN(initData.initialScrollProgress)) {\n\t\t\t\t\t\t\tif (window.scrollY === 0) {\n\t\t\t\t\t\t\t\twindow.scroll(0, body.clientHeight * initData.initialScrollProgress);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tconst scrollY = frame && frame.contentDocument && frame.contentDocument.body ? assertIsDefined(frame.contentWindow).scrollY : 0;\n\t\t\t\t\tsetInitialScrollPosition = (body, window) => {\n\t\t\t\t\t\tif (window.scrollY === 0) {\n\t\t\t\t\t\t\twindow.scroll(0, scrollY);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Clean up old pending frames and set current one as new one\n\t\t\t\tconst previousPendingFrame = getPendingFrame();\n\t\t\t\tif (previousPendingFrame) {\n\t\t\t\t\tpreviousPendingFrame.setAttribute('id', '');\n\t\t\t\t\tpreviousPendingFrame.remove();\n\t\t\t\t}\n\t\t\t\tif (!wasFirstLoad) {\n\t\t\t\t\tpendingMessages = [];\n\t\t\t\t}\n\n\t\t\t\tconst newFrame = document.createElement('iframe');\n\t\t\t\tnewFrame.title = data.title;\n\t\t\t\tnewFrame.setAttribute('id', 'pending-frame');\n\t\t\t\tnewFrame.setAttribute('frameborder', '0');\n\n\t\t\t\tconst sandboxRules = new Set(['allow-same-origin', 'allow-pointer-lock']);\n\t\t\t\tif (options.allowScripts) {\n\t\t\t\t\tsandboxRules.add('allow-scripts');\n\t\t\t\t\tsandboxRules.add('allow-downloads');\n\t\t\t\t}\n\t\t\t\tif (options.allowForms) {\n\t\t\t\t\tsandboxRules.add('allow-forms');\n\t\t\t\t}\n\t\t\t\tnewFrame.setAttribute('sandbox', Array.from(sandboxRules).join(' '));\n\n\t\t\t\tconst allowRules = ['cross-origin-isolated;', 'autoplay;', 'local-network-access;'];\n\t\t\t\tif (!isFirefox && options.allowScripts) {\n\t\t\t\t\tallowRules.push('clipboard-read;', 'clipboard-write;');\n\t\t\t\t}\n\t\t\t\tnewFrame.setAttribute('allow', allowRules.join(' '));\n\t\t\t\t// We should just be able to use srcdoc, but I wasn't\n\t\t\t\t// seeing the service worker applying properly.\n\t\t\t\t// Fake load an empty on the correct origin and then write real html\n\t\t\t\t// into it to get around this.\n\t\t\t\tconst fakeUrlParams = new URLSearchParams({ id: ID });\n\t\t\t\tif (globalThis.crossOriginIsolated) {\n\t\t\t\t\tfakeUrlParams.set('vscode-coi', '3'); /*COOP+COEP*/\n\t\t\t\t}\n\t\t\t\tnewFrame.src = `./fake.html?${fakeUrlParams.toString()}`;\n\n\t\t\t\tnewFrame.style.cssText = 'display: block; margin: 0; overflow: hidden; position: absolute; width: 100%; height: 100%; visibility: hidden';\n\t\t\t\tdocument.body.appendChild(newFrame);\n\n\t\t\t\tnewFrame.contentWindow.addEventListener('keydown', handleInnerKeydown);\n\t\t\t\tnewFrame.contentWindow.addEventListener('keyup', handleInnerKeyup);\n\n\t\t\t\t/**\n\t\t\t\t * @param {Document} contentDocument\n\t\t\t\t */\n\t\t\t\tfunction onFrameLoaded(contentDocument) {\n\t\t\t\t\tperfMark('content/innerFrameLoaded')\n\n\t\t\t\t\t// Workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=978325\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tcontentDocument.open();\n\t\t\t\t\t\tcontentDocument.write(newDocument);\n\t\t\t\t\t\tcontentDocument.close();\n\t\t\t\t\t\thookupOnLoadHandlers(newFrame);\n\t\t\t\t\t\tperfMark('content/wroteInnerContent')\n\n\t\t\t\t\t\tif (initialStyleVersion !== styleVersion) {\n\t\t\t\t\t\t\tapplyStyles(contentDocument, contentDocument.body);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\n\t\t\t\tif (!options.allowScripts && isSafari) {\n\t\t\t\t\t// On Safari for iframes with scripts disabled, the `DOMContentLoaded` never seems to be fired: https://bugs.webkit.org/show_bug.cgi?id=33604\n\t\t\t\t\t// Use polling instead.\n\t\t\t\t\tconst interval = setInterval(() => {\n\t\t\t\t\t\t// If the frame is no longer mounted, loading has stopped\n\t\t\t\t\t\tif (!newFrame.parentElement) {\n\t\t\t\t\t\t\tclearInterval(interval);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst contentDocument = assertIsDefined(newFrame.contentDocument);\n\t\t\t\t\t\tif (contentDocument.location.pathname.endsWith('/fake.html') && contentDocument.readyState !== 'loading') {\n\t\t\t\t\t\t\tclearInterval(interval);\n\t\t\t\t\t\t\tonFrameLoaded(contentDocument);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 10);\n\t\t\t\t} else {\n\t\t\t\t\tassertIsDefined(newFrame.contentWindow).addEventListener('DOMContentLoaded', e => {\n\t\t\t\t\t\tconst contentDocument = e.target ? (/** @type {HTMLDocument} */ (e.target)) : undefined;\n\t\t\t\t\t\tonFrameLoaded(assertIsDefined(contentDocument));\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * @param {Document} contentDocument\n\t\t\t\t * @param {Window} contentWindow\n\t\t\t\t */\n\t\t\t\tconst onLoad = (contentDocument, contentWindow) => {\n\t\t\t\t\tif (contentDocument && contentDocument.body) {\n\t\t\t\t\t\t// Workaround for https://github.com/microsoft/vscode/issues/12865\n\t\t\t\t\t\t// check new scrollY and reset if necessary\n\t\t\t\t\t\tsetInitialScrollPosition(contentDocument.body, contentWindow);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newFrame = getPendingFrame();\n\t\t\t\t\tif (newFrame && newFrame.contentDocument && newFrame.contentDocument === contentDocument) {\n\t\t\t\t\t\tconst wasFocused = document.hasFocus();\n\t\t\t\t\t\tconst oldActiveFrame = getActiveFrame();\n\t\t\t\t\t\toldActiveFrame?.remove();\n\t\t\t\t\t\t// Styles may have changed since we created the element. Make sure we re-style\n\t\t\t\t\t\tif (initialStyleVersion !== styleVersion) {\n\t\t\t\t\t\t\tapplyStyles(newFrame.contentDocument, newFrame.contentDocument.body);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnewFrame.setAttribute('id', 'active-frame');\n\t\t\t\t\t\tnewFrame.style.visibility = 'visible';\n\n\t\t\t\t\t\tcontentWindow.addEventListener('scroll', handleInnerScroll);\n\t\t\t\t\t\tcontentWindow.addEventListener('wheel', handleWheel);\n\n\t\t\t\t\t\tif (wasFocused) {\n\t\t\t\t\t\t\tcontentWindow.focus();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Get body size\n\t\t\t\t\t\tconst docEl = contentDocument.documentElement;\n\t\t\t\t\t\tif (docEl) {\n\t\t\t\t\t\t\tconst postSize = () => {\n\t\t\t\t\t\t\t\thostMessaging.postMessage('updated-intrinsic-content-size', {\n\t\t\t\t\t\t\t\t\twidth: docEl.offsetWidth,\n\t\t\t\t\t\t\t\t\theight: docEl.offsetHeight\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tconst resizeObserver = new ResizeObserver(postSize);\n\t\t\t\t\t\t\tresizeObserver.observe(docEl);\n\t\t\t\t\t\t\tpostSize();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpendingMessages.forEach((message) => {\n\t\t\t\t\t\t\tcontentWindow.postMessage(message.message, window.origin, message.transfer);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpendingMessages = [];\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t/**\n\t\t\t\t * @param {HTMLIFrameElement} newFrame\n\t\t\t\t */\n\t\t\t\tfunction hookupOnLoadHandlers(newFrame) {\n\t\t\t\t\tclearTimeout(loadTimeout);\n\t\t\t\t\tloadTimeout = undefined;\n\t\t\t\t\tloadTimeout = setTimeout(() => {\n\t\t\t\t\t\tclearTimeout(loadTimeout);\n\t\t\t\t\t\tloadTimeout = undefined;\n\t\t\t\t\t\tonLoad(assertIsDefined(newFrame.contentDocument), assertIsDefined(newFrame.contentWindow));\n\t\t\t\t\t}, 200);\n\n\t\t\t\t\tconst contentWindow = assertIsDefined(newFrame.contentWindow);\n\n\t\t\t\t\tcontentWindow.addEventListener('load', function (e) {\n\t\t\t\t\t\tconst contentDocument = /** @type {Document} */ (e.target);\n\n\t\t\t\t\t\tif (loadTimeout) {\n\t\t\t\t\t\t\tclearTimeout(loadTimeout);\n\t\t\t\t\t\t\tloadTimeout = undefined;\n\t\t\t\t\t\t\tonLoad(contentDocument, this);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// Bubble out various events\n\t\t\t\t\tcontentWindow.addEventListener('click', handleInnerClick);\n\t\t\t\t\tcontentWindow.addEventListener('auxclick', handleAuxClick);\n\t\t\t\t\tcontentWindow.addEventListener('keydown', handleInnerKeydown);\n\t\t\t\t\tcontentWindow.addEventListener('keyup', handleInnerKeyup);\n\t\t\t\t\tcontentWindow.addEventListener('contextmenu', e => {\n\t\t\t\t\t\tif (e.defaultPrevented) {\n\t\t\t\t\t\t\t// Extension code has already handled this event\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t/** @type { Record<string, boolean>} */\n\t\t\t\t\t\tlet context = {};\n\n\t\t\t\t\t\t/** @type {HTMLElement | null} */\n\t\t\t\t\t\tlet el = e.target;\n\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\tif (!el) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Search self/ancestors for the closest context data attribute\n\t\t\t\t\t\t\tel = el.closest('[data-vscode-context]');\n\t\t\t\t\t\t\tif (!el) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tcontext = { ...JSON.parse(el.dataset.vscodeContext), ...context };\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\tconsole.error(`Error parsing 'data-vscode-context' as json`, el, e);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tel = el.parentElement;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thostMessaging.postMessage('did-context-menu', {\n\t\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\t\tcontext: context\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tcontentWindow.addEventListener('dragenter', handleInnerDragStartEvent);\n\t\t\t\t\tcontentWindow.addEventListener('dragover', handleInnerDragEvent);\n\t\t\t\t\tcontentWindow.addEventListener('drag', handleInnerDragEvent);\n\t\t\t\t\tcontentWindow.addEventListener('drop', handleInnerDropEvent);\n\n\t\t\t\t\tunloadMonitor.onIframeLoaded(newFrame);\n\t\t\t\t}\n\n\t\t\t\tif (!disableServiceWorker && outerIframeMessageChannel) {\n\t\t\t\t\touterIframeMessageChannel.port1.onmessage = event => {\n\t\t\t\t\t\tswitch (event.data.channel) {\n\t\t\t\t\t\t\tcase 'load-resource':\n\t\t\t\t\t\t\tcase 'load-localhost':\n\t\t\t\t\t\t\t\thostMessaging.postMessage(event.data.channel, event.data);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// propagate vscode-context-menu-visible class\n\t\t\thostMessaging.onMessage('set-context-menu-visible', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (target && target.contentDocument) {\n\t\t\t\t\ttarget.contentDocument.body.classList.toggle('vscode-context-menu-visible', data.visible);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('set-title', async (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (target) {\n\t\t\t\t\ttarget.title = data;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Forward message to the embedded iframe\n\t\t\thostMessaging.onMessage('message', (_event, data) => {\n\t\t\t\tconst pending = getPendingFrame();\n\t\t\t\tif (!pending) {\n\t\t\t\t\tconst target = getActiveFrame();\n\t\t\t\t\tif (target) {\n\t\t\t\t\t\tassertIsDefined(target.contentWindow).postMessage(data.message, window.origin, data.transfer);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingMessages.push(data);\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('initial-scroll-position', (_event, progress) => {\n\t\t\t\tinitData.initialScrollProgress = progress;\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('execCommand', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tassertIsDefined(target.contentDocument).execCommand(data);\n\t\t\t});\n\n\t\t\t/** @type {string | undefined} */\n\t\t\tlet lastFindValue = undefined;\n\n\t\t\thostMessaging.onMessage('find', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!data.previous && lastFindValue !== data.value && target.contentWindow) {\n\t\t\t\t\t// Reset selection so we start search at the head of the last search\n\t\t\t\t\tconst selection = target.contentWindow.getSelection();\n\t\t\t\t\tif (selection) {\n\t\t\t\t\t\tselection.collapse(selection.anchorNode);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastFindValue = data.value;\n\n\t\t\t\tconst didFind = (/** @type {any} */ (target.contentWindow)).find(\n\t\t\t\t\tdata.value,\n\t\t\t\t\t/* caseSensitive*/ false,\n\t\t\t\t\t/* backwards*/ data.previous,\n\t\t\t\t\t/* wrapAround*/ true,\n\t\t\t\t\t/* wholeWord */ false,\n\t\t\t\t\t/* searchInFrames*/ false,\n\t\t\t\t\tfalse);\n\t\t\t\thostMessaging.postMessage('did-find', didFind);\n\t\t\t});\n\n\t\t\thostMessaging.onMessage('find-stop', (_event, data) => {\n\t\t\t\tconst target = getActiveFrame();\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlastFindValue = undefined;\n\n\t\t\t\tif (!data.clearSelection && target.contentWindow) {\n\t\t\t\t\tconst selection = target.contentWindow.getSelection();\n\t\t\t\t\tif (selection) {\n\t\t\t\t\t\tfor (let i = 0; i < selection.rangeCount; i++) {\n\t\t\t\t\t\t\tselection.removeRange(selection.getRangeAt(i));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttrackFocus({\n\t\t\t\tonFocus: () => hostMessaging.postMessage('did-focus', undefined),\n\t\t\t\tonBlur: () => hostMessaging.postMessage('did-blur', undefined)\n\t\t\t});\n\n\t\t\t(/** @type {any} */ (window))[vscodePostMessageFuncName] = (/** @type {string} */ command, /** @type {any} */ data) => {\n\t\t\t\tswitch (command) {\n\t\t\t\t\tcase 'onmessage':\n\t\t\t\t\tcase 'do-update-state':\n\t\t\t\t\t\thostMessaging.postMessage(command, data);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\thostMessaging.signalReady();\n\t\t});\n\t</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IBuiltinExtensionsScannerService, ExtensionType, IExtensionManifest, TargetPlatform, IExtension } from '../../../../platform/extensions/common/extensions.js';\nimport { isWeb, Language } from '../../../../base/common/platform.js';\nimport { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';\nimport { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';\nimport { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';\nimport { getGalleryExtensionId } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';\nimport { builtinExtensionsPath, FileAccess } from '../../../../base/common/network.js';\nimport { URI } from '../../../../base/common/uri.js';\nimport { IExtensionResourceLoaderService } from '../../../../platform/extensionResourceLoader/common/extensionResourceLoader.js';\nimport { IProductService } from '../../../../platform/product/common/productService.js';\nimport { ITranslations, localizeManifest } from '../../../../platform/extensionManagement/common/extensionNls.js';\nimport { ILogService } from '../../../../platform/log/common/log.js';\nimport { mainWindow } from '../../../../base/browser/window.js';\n\ninterface IBundledExtension {\n\textensionPath: string;\n\tpackageJSON: IExtensionManifest;\n\tpackageNLS?: ITranslations;\n\treadmePath?: string;\n\tchangelogPath?: string;\n}\n\nexport class BuiltinExtensionsScannerService implements IBuiltinExtensionsScannerService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate readonly builtinExtensionsPromises: Promise<IExtension>[] = [];\n\n\tprivate nlsUrl: URI | undefined;\n\n\tconstructor(\n\t\t@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,\n\t\t@IUriIdentityService uriIdentityService: IUriIdentityService,\n\t\t@IExtensionResourceLoaderService private readonly extensionResourceLoaderService: IExtensionResourceLoaderService,\n\t\t@IProductService productService: IProductService,\n\t\t@ILogService private readonly logService: ILogService\n\t) {\n\t\tif (isWeb) {\n\t\t\tconst nlsBaseUrl = productService.extensionsGallery?.nlsBaseUrl;\n\t\t\t// Only use the nlsBaseUrl if we are using a language other than the default, English.\n\t\t\tif (nlsBaseUrl && productService.commit && !Language.isDefaultVariant()) {\n\t\t\t\tthis.nlsUrl = URI.joinPath(URI.parse(nlsBaseUrl), productService.commit, productService.version, Language.value());\n\t\t\t}\n\n\t\t\tconst builtinExtensionsServiceUrl = FileAccess.asBrowserUri(builtinExtensionsPath);\n\t\t\tif (builtinExtensionsServiceUrl) {\n\t\t\t\tlet bundledExtensions: IBundledExtension[] = [];\n\n\t\t\t\tif (environmentService.isBuilt) {\n\t\t\t\t\t// Built time configuration (do NOT modify)\n\t\t\t\t\tbundledExtensions = [/*BUILD->INSERT_BUILTIN_EXTENSIONS*/];\n\t\t\t\t} else {\n\t\t\t\t\t// Find builtin extensions by checking for DOM\n\t\t\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\t\t\tconst builtinExtensionsElement = mainWindow.document.getElementById('vscode-workbench-builtin-extensions');\n\t\t\t\t\tconst builtinExtensionsElementAttribute = builtinExtensionsElement ? builtinExtensionsElement.getAttribute('data-settings') : undefined;\n\t\t\t\t\tif (builtinExtensionsElementAttribute) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tbundledExtensions = JSON.parse(builtinExtensionsElementAttribute);\n\t\t\t\t\t\t} catch (error) { /* ignore error*/ }\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// below codes are changed by github1s\n\t\t\t\tif (Array.isArray(globalThis._VSCODE_WEB?.builtinExtensions)) {\n\t\t\t\t\tbundledExtensions.push(...globalThis._VSCODE_WEB.builtinExtensions);\n\t\t\t\t} else if (typeof globalThis._VSCODE_WEB?.builtinExtensions === 'function') {\n\t\t\t\t\tbundledExtensions = globalThis._VSCODE_WEB.builtinExtensions(bundledExtensions);\n\t\t\t\t}\n\t\t\t\t// above codes are changed by github1s\n\n\t\t\t\tthis.builtinExtensionsPromises = bundledExtensions.map(async e => {\n\t\t\t\t\tconst id = getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tidentifier: { id },\n\t\t\t\t\t\tlocation: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl, e.extensionPath),\n\t\t\t\t\t\ttype: ExtensionType.System,\n\t\t\t\t\t\tisBuiltin: true,\n\t\t\t\t\t\tmanifest: e.packageNLS ? await this.localizeManifest(id, e.packageJSON, e.packageNLS) : e.packageJSON,\n\t\t\t\t\t\treadmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl, e.readmePath) : undefined,\n\t\t\t\t\t\tchangelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl, e.changelogPath) : undefined,\n\t\t\t\t\t\ttargetPlatform: TargetPlatform.WEB,\n\t\t\t\t\t\tvalidations: [],\n\t\t\t\t\t\tisValid: true,\n\t\t\t\t\t\tpreRelease: false,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tasync scanBuiltinExtensions(): Promise<IExtension[]> {\n\t\treturn [...await Promise.all(this.builtinExtensionsPromises)];\n\t}\n\n\tprivate async localizeManifest(extensionId: string, manifest: IExtensionManifest, fallbackTranslations: ITranslations): Promise<IExtensionManifest> {\n\t\tif (!this.nlsUrl) {\n\t\t\treturn localizeManifest(this.logService, manifest, fallbackTranslations);\n\t\t}\n\t\t// the `package` endpoint returns the translations in a key-value format similar to the package.nls.json file.\n\t\tconst uri = URI.joinPath(this.nlsUrl, extensionId, 'package');\n\t\ttry {\n\t\t\tconst res = await this.extensionResourceLoaderService.readExtensionResource(uri);\n\t\t\tconst json = JSON.parse(res.toString());\n\t\t\treturn localizeManifest(this.logService, manifest, json, fallbackTranslations);\n\t\t} catch (e) {\n\t\t\tthis.logService.error(e);\n\t\t\treturn localizeManifest(this.logService, manifest, fallbackTranslations);\n\t\t}\n\t}\n}\n\nregisterSingleton(IBuiltinExtensionsScannerService, BuiltinExtensionsScannerService, InstantiationType.Delayed);\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/services/label/common/labelService.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { localize } from '../../../../nls.js';\nimport { URI } from '../../../../base/common/uri.js';\nimport { IDisposable, Disposable, dispose } from '../../../../base/common/lifecycle.js';\nimport { posix, sep, win32 } from '../../../../base/common/path.js';\nimport { Emitter } from '../../../../base/common/event.js';\nimport { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from '../../../common/contributions.js';\nimport { Registry } from '../../../../platform/registry/common/platform.js';\nimport { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';\nimport { IWorkspaceContextService, IWorkspace, isWorkspace, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier, toWorkspaceIdentifier, WORKSPACE_EXTENSION, isUntitledWorkspace, isTemporaryWorkspace } from '../../../../platform/workspace/common/workspace.js';\nimport { basenameOrAuthority, basename, joinPath, dirname } from '../../../../base/common/resources.js';\nimport { tildify, getPathLabel } from '../../../../base/common/labels.js';\nimport { ILabelService, ResourceLabelFormatter, ResourceLabelFormatting, IFormatterChangeEvent, Verbosity } from '../../../../platform/label/common/label.js';\nimport { ExtensionsRegistry } from '../../extensions/common/extensionsRegistry.js';\nimport { match } from '../../../../base/common/glob.js';\nimport { ILifecycleService, LifecyclePhase } from '../../lifecycle/common/lifecycle.js';\nimport { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';\nimport { IPathService } from '../../path/common/pathService.js';\nimport { isProposedApiEnabled } from '../../extensions/common/extensions.js';\nimport { OperatingSystem, OS } from '../../../../base/common/platform.js';\nimport { IRemoteAgentService } from '../../remote/common/remoteAgentService.js';\nimport { Schemas } from '../../../../base/common/network.js';\nimport { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';\nimport { Memento } from '../../../common/memento.js';\n\nconst resourceLabelFormattersExtPoint = ExtensionsRegistry.registerExtensionPoint<ResourceLabelFormatter[]>({\n\textensionPoint: 'resourceLabelFormatters',\n\tjsonSchema: {\n\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters', 'Contributes resource label formatting rules.'),\n\t\ttype: 'array',\n\t\titems: {\n\t\t\ttype: 'object',\n\t\t\trequired: ['scheme', 'formatting'],\n\t\t\tproperties: {\n\t\t\t\tscheme: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.scheme', 'URI scheme on which to match the formatter on. For example \"file\". Simple glob patterns are supported.'),\n\t\t\t\t},\n\t\t\t\tauthority: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.authority', 'URI authority on which to match the formatter on. Simple glob patterns are supported.'),\n\t\t\t\t},\n\t\t\t\tformatting: {\n\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.formatting', \"Rules for formatting uri resource labels.\"),\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.label', \"Label rules to display. For example: myLabel:/${path}. ${path}, ${scheme}, ${authority} and ${authoritySuffix} are supported as variables.\")\n\t\t\t\t\t\t},\n\t\t\t\t\t\tseparator: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.separator', \"Separator to be used in the uri label display. '/' or '\\' as an example.\")\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstripPathStartingSeparator: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.stripPathStartingSeparator', \"Controls whether `${path}` substitutions should have starting separator characters stripped.\")\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttildify: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.tildify', \"Controls if the start of the uri label should be tildified when possible.\")\n\t\t\t\t\t\t},\n\t\t\t\t\t\tworkspaceSuffix: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: localize('vscode.extension.contributes.resourceLabelFormatters.formatting.workspaceSuffix', \"Suffix appended to the workspace label.\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\nconst posixPathSeparatorRegexp = /\\//g; // on Unix, backslash is a valid filename character\nconst winPathSeparatorRegexp = /[\\\\\\/]/g; // on Windows, neither slash nor backslash are valid filename characters\nconst labelMatchingRegexp = /\\$\\{(scheme|authoritySuffix|authority|path|(query)\\.(.+?))\\}/g;\n\nfunction hasDriveLetterIgnorePlatform(path: string): boolean {\n\treturn !!(path && path[2] === ':');\n}\n\nclass ResourceLabelFormattersHandler implements IWorkbenchContribution {\n\n\tprivate readonly formattersDisposables = new Map<ResourceLabelFormatter, IDisposable>();\n\n\tconstructor(@ILabelService labelService: ILabelService) {\n\t\tresourceLabelFormattersExtPoint.setHandler((extensions, delta) => {\n\t\t\tfor (const added of delta.added) {\n\t\t\t\tfor (const untrustedFormatter of added.value) {\n\n\t\t\t\t\t// We cannot trust that the formatter as it comes from an extension\n\t\t\t\t\t// adheres to our interface, so for the required properties we fill\n\t\t\t\t\t// in some defaults if missing.\n\n\t\t\t\t\tconst formatter = { ...untrustedFormatter };\n\t\t\t\t\tif (typeof formatter.formatting.label !== 'string') {\n\t\t\t\t\t\tformatter.formatting.label = '${authority}${path}';\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof formatter.formatting.separator !== `string`) {\n\t\t\t\t\t\tformatter.formatting.separator = sep;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isProposedApiEnabled(added.description, 'contribLabelFormatterWorkspaceTooltip') && formatter.formatting.workspaceTooltip) {\n\t\t\t\t\t\tformatter.formatting.workspaceTooltip = undefined; // workspaceTooltip is only proposed\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.formattersDisposables.set(formatter, labelService.registerFormatter(formatter));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const removed of delta.removed) {\n\t\t\t\tfor (const formatter of removed.value) {\n\t\t\t\t\tdispose(this.formattersDisposables.get(formatter));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\nRegistry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ResourceLabelFormattersHandler, LifecyclePhase.Restored);\n\nconst FORMATTER_CACHE_SIZE = 50;\n\ninterface IStoredFormatters {\n\tformatters?: ResourceLabelFormatter[];\n\ti?: number;\n}\n\nexport class LabelService extends Disposable implements ILabelService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate formatters: ResourceLabelFormatter[];\n\n\tprivate readonly _onDidChangeFormatters = this._register(new Emitter<IFormatterChangeEvent>({ leakWarningThreshold: 400 }));\n\treadonly onDidChangeFormatters = this._onDidChangeFormatters.event;\n\n\tprivate readonly storedFormattersMemento: Memento<IStoredFormatters>;\n\tprivate readonly storedFormatters: IStoredFormatters;\n\tprivate os: OperatingSystem;\n\tprivate userHome: URI | undefined;\n\n\tconstructor(\n\t\t@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,\n\t\t@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,\n\t\t@IPathService private readonly pathService: IPathService,\n\t\t@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,\n\t\t@IStorageService storageService: IStorageService,\n\t\t@ILifecycleService lifecycleService: ILifecycleService,\n\t) {\n\t\tsuper();\n\n\t\t// Find some meaningful defaults until the remote environment\n\t\t// is resolved, by taking the current OS we are running in\n\t\t// and by taking the local `userHome` if we run on a local\n\t\t// file scheme.\n\t\tthis.os = OS;\n\t\tthis.userHome = pathService.defaultUriScheme === Schemas.file ? this.pathService.userHome({ preferLocal: true }) : undefined;\n\n\t\tconst memento = this.storedFormattersMemento = new Memento('cachedResourceLabelFormatters2', storageService);\n\t\tthis.storedFormatters = memento.getMemento(StorageScope.PROFILE, StorageTarget.MACHINE);\n\t\tthis.formatters = this.storedFormatters?.formatters?.slice() || [];\n\n\t\t// Remote environment is potentially long running\n\t\tthis.resolveRemoteEnvironment();\n\t}\n\n\tprivate async resolveRemoteEnvironment(): Promise<void> {\n\n\t\t// OS\n\t\tconst env = await this.remoteAgentService.getEnvironment();\n\t\tthis.os = env?.os ?? OS;\n\n\t\t// User home\n\t\tthis.userHome = await this.pathService.userHome();\n\t}\n\n\tfindFormatting(resource: URI): ResourceLabelFormatting | undefined {\n\t\tlet bestResult: ResourceLabelFormatter | undefined;\n\n\t\tfor (const formatter of this.formatters) {\n\t\t\tif (formatter.scheme === resource.scheme) {\n\t\t\t\tif (!formatter.authority && (!bestResult || formatter.priority)) {\n\t\t\t\t\tbestResult = formatter;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!formatter.authority) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (match(formatter.authority, resource.authority, { ignoreCase: true }) &&\n\t\t\t\t\t(\n\t\t\t\t\t\t!bestResult?.authority ||\n\t\t\t\t\t\tformatter.authority.length > bestResult.authority.length ||\n\t\t\t\t\t\t((formatter.authority.length === bestResult.authority.length) && formatter.priority)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tbestResult = formatter;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn bestResult ? bestResult.formatting : undefined;\n\t}\n\n\tgetUriLabel(resource: URI, options: { relative?: boolean; noPrefix?: boolean; separator?: '/' | '\\\\'; appendWorkspaceSuffix?: boolean } = {}): string {\n\t\tlet formatting = this.findFormatting(resource);\n\t\tif (formatting && options.separator) {\n\t\t\t// mixin separator if defined from the outside\n\t\t\tformatting = { ...formatting, separator: options.separator };\n\t\t}\n\n\t\tlet label = this.doGetUriLabel(resource, formatting, options);\n\n\t\t// Without formatting we still need to support the separator\n\t\t// as provided in options (https://github.com/microsoft/vscode/issues/130019)\n\t\tif (!formatting && options.separator) {\n\t\t\tlabel = this.adjustPathSeparators(label, options.separator);\n\t\t}\n\n\t\tif (options.appendWorkspaceSuffix && formatting?.workspaceSuffix) {\n\t\t\tlabel = this.appendWorkspaceSuffix(label, resource);\n\t\t}\n\n\t\treturn label;\n\t}\n\n\tprivate doGetUriLabel(resource: URI, formatting?: ResourceLabelFormatting, options: { relative?: boolean; noPrefix?: boolean } = {}): string {\n\t\tif (!formatting) {\n\t\t\treturn getPathLabel(resource, {\n\t\t\t\tos: this.os,\n\t\t\t\ttildify: this.userHome ? { userHome: this.userHome } : undefined,\n\t\t\t\trelative: options.relative ? {\n\t\t\t\t\tnoPrefix: options.noPrefix,\n\t\t\t\t\tgetWorkspace: () => this.contextService.getWorkspace(),\n\t\t\t\t\tgetWorkspaceFolder: resource => this.contextService.getWorkspaceFolder(resource)\n\t\t\t\t} : undefined\n\t\t\t});\n\t\t}\n\n\t\t// Relative label\n\t\tif (options.relative && this.contextService) {\n\t\t\tlet folder = this.contextService.getWorkspaceFolder(resource);\n\t\t\tif (!folder) {\n\n\t\t\t\t// It is possible that the resource we want to resolve the\n\t\t\t\t// workspace folder for is not using the same scheme as\n\t\t\t\t// the folders in the workspace, so we help by trying again\n\t\t\t\t// to resolve a workspace folder by trying again with a\n\t\t\t\t// scheme that is workspace contained.\n\n\t\t\t\tconst workspace = this.contextService.getWorkspace();\n\t\t\t\tconst firstFolder = workspace.folders.at(0);\n\t\t\t\tif (firstFolder && resource.scheme !== firstFolder.uri.scheme && resource.path.startsWith(posix.sep)) {\n\t\t\t\t\tfolder = this.contextService.getWorkspaceFolder(firstFolder.uri.with({ path: resource.path }));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (folder) {\n\t\t\t\tconst folderLabel = this.formatUri(folder.uri, formatting, options.noPrefix);\n\n\t\t\t\tlet relativeLabel = this.formatUri(resource, formatting, options.noPrefix);\n\t\t\t\tlet overlap = 0;\n\t\t\t\twhile (relativeLabel[overlap] && relativeLabel[overlap] === folderLabel[overlap]) {\n\t\t\t\t\toverlap++;\n\t\t\t\t}\n\n\t\t\t\tif (!relativeLabel[overlap] || relativeLabel[overlap] === formatting.separator) {\n\t\t\t\t\trelativeLabel = relativeLabel.substring(1 + overlap);\n\t\t\t\t} else if (overlap === folderLabel.length && folder.uri.path === posix.sep) {\n\t\t\t\t\trelativeLabel = relativeLabel.substring(overlap);\n\t\t\t\t}\n\n\t\t\t\t// always show root basename if there are multiple folders\n\t\t\t\tconst hasMultipleRoots = this.contextService.getWorkspace().folders.length > 1;\n\t\t\t\tif (hasMultipleRoots && !options.noPrefix) {\n\t\t\t\t\tconst rootName = folder?.name ?? basenameOrAuthority(folder.uri);\n\t\t\t\t\trelativeLabel = relativeLabel ? `${rootName} • ${relativeLabel}` : rootName;\n\t\t\t\t}\n\n\t\t\t\treturn relativeLabel;\n\t\t\t}\n\t\t}\n\n\t\t// Absolute label\n\t\treturn this.formatUri(resource, formatting, options.noPrefix);\n\t}\n\n\tgetUriBasenameLabel(resource: URI): string {\n\t\tconst formatting = this.findFormatting(resource);\n\t\tconst label = this.doGetUriLabel(resource, formatting);\n\n\t\tlet pathLib: typeof win32 | typeof posix;\n\t\tif (formatting?.separator === win32.sep) {\n\t\t\tpathLib = win32;\n\t\t} else if (formatting?.separator === posix.sep) {\n\t\t\tpathLib = posix;\n\t\t} else {\n\t\t\tpathLib = (this.os === OperatingSystem.Windows) ? win32 : posix;\n\t\t}\n\n\t\treturn pathLib.basename(label);\n\t}\n\n\tgetWorkspaceLabel(workspace: IWorkspace | IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI, options?: { verbose: Verbosity }): string {\n\t\t/* below codes are changed by github1s */\n\t\tif (globalThis._VSCODE_WEB?.workspaceLabel) {\n\t\t\treturn globalThis._VSCODE_WEB.workspaceLabel;\n\t\t}\n\t\t/* above codes are changed by github1s */\n\n\t\tif (isWorkspace(workspace)) {\n\t\t\tconst identifier = toWorkspaceIdentifier(workspace);\n\t\t\tif (isSingleFolderWorkspaceIdentifier(identifier) || isWorkspaceIdentifier(identifier)) {\n\t\t\t\treturn this.getWorkspaceLabel(identifier, options);\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\n\t\t// Workspace: Single Folder (as URI)\n\t\tif (URI.isUri(workspace)) {\n\t\t\treturn this.doGetSingleFolderWorkspaceLabel(workspace, options);\n\t\t}\n\n\t\t// Workspace: Single Folder (as workspace identifier)\n\t\tif (isSingleFolderWorkspaceIdentifier(workspace)) {\n\t\t\treturn this.doGetSingleFolderWorkspaceLabel(workspace.uri, options);\n\t\t}\n\n\t\t// Workspace: Multi Root\n\t\tif (isWorkspaceIdentifier(workspace)) {\n\t\t\treturn this.doGetWorkspaceLabel(workspace.configPath, options);\n\t\t}\n\n\t\treturn '';\n\t}\n\n\tprivate doGetWorkspaceLabel(workspaceUri: URI, options?: { verbose: Verbosity }): string {\n\n\t\t// Workspace: Untitled\n\t\tif (isUntitledWorkspace(workspaceUri, this.environmentService)) {\n\t\t\treturn localize('untitledWorkspace', \"Untitled (Workspace)\");\n\t\t}\n\n\t\t// Workspace: Temporary\n\t\tif (isTemporaryWorkspace(workspaceUri)) {\n\t\t\treturn localize('temporaryWorkspace', \"Workspace\");\n\t\t}\n\n\t\t// Workspace: Saved\n\t\tlet filename = basename(workspaceUri);\n\t\tif (filename.endsWith(WORKSPACE_EXTENSION)) {\n\t\t\tfilename = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1);\n\t\t}\n\n\t\tlet label: string;\n\t\tswitch (options?.verbose) {\n\t\t\tcase Verbosity.SHORT:\n\t\t\t\tlabel = filename; // skip suffix for short label\n\t\t\t\tbreak;\n\t\t\tcase Verbosity.LONG:\n\t\t\t\tlabel = localize('workspaceNameVerbose', \"{0} (Workspace)\", this.getUriLabel(joinPath(dirname(workspaceUri), filename)));\n\t\t\t\tbreak;\n\t\t\tcase Verbosity.MEDIUM:\n\t\t\tdefault:\n\t\t\t\tlabel = localize('workspaceName', \"{0} (Workspace)\", filename);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (options?.verbose === Verbosity.SHORT) {\n\t\t\treturn label; // skip suffix for short label\n\t\t}\n\n\t\treturn this.appendWorkspaceSuffix(label, workspaceUri);\n\t}\n\n\tprivate doGetSingleFolderWorkspaceLabel(folderUri: URI, options?: { verbose: Verbosity }): string {\n\t\tlet label: string;\n\t\tswitch (options?.verbose) {\n\t\t\tcase Verbosity.LONG:\n\t\t\t\tlabel = this.getUriLabel(folderUri);\n\t\t\t\tbreak;\n\t\t\tcase Verbosity.SHORT:\n\t\t\tcase Verbosity.MEDIUM:\n\t\t\tdefault:\n\t\t\t\tlabel = basename(folderUri) || posix.sep;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (options?.verbose === Verbosity.SHORT) {\n\t\t\treturn label; // skip suffix for short label\n\t\t}\n\n\t\treturn this.appendWorkspaceSuffix(label, folderUri);\n\t}\n\n\tgetSeparator(scheme: string, authority?: string): '/' | '\\\\' {\n\t\tconst formatter = this.findFormatting(URI.from({ scheme, authority }));\n\n\t\treturn formatter?.separator || posix.sep;\n\t}\n\n\tgetHostLabel(scheme: string, authority?: string): string {\n\t\tconst formatter = this.findFormatting(URI.from({ scheme, authority }));\n\n\t\treturn formatter?.workspaceSuffix || authority || '';\n\t}\n\n\tgetHostTooltip(scheme: string, authority?: string): string | undefined {\n\t\tconst formatter = this.findFormatting(URI.from({ scheme, authority }));\n\n\t\treturn formatter?.workspaceTooltip;\n\t}\n\n\tregisterCachedFormatter(formatter: ResourceLabelFormatter): IDisposable {\n\t\tconst list = this.storedFormatters.formatters ??= [];\n\n\t\tlet replace = list.findIndex(f => f.scheme === formatter.scheme && f.authority === formatter.authority);\n\t\tif (replace === -1 && list.length >= FORMATTER_CACHE_SIZE) {\n\t\t\treplace = FORMATTER_CACHE_SIZE - 1; // at max capacity, replace the last element\n\t\t}\n\n\t\tif (replace === -1) {\n\t\t\tlist.unshift(formatter);\n\t\t} else {\n\t\t\tfor (let i = replace; i > 0; i--) {\n\t\t\t\tlist[i] = list[i - 1];\n\t\t\t}\n\t\t\tlist[0] = formatter;\n\t\t}\n\n\t\tthis.storedFormattersMemento.saveMemento();\n\n\t\treturn this.registerFormatter(formatter);\n\t}\n\n\tregisterFormatter(formatter: ResourceLabelFormatter): IDisposable {\n\t\tthis.formatters.push(formatter);\n\t\tthis._onDidChangeFormatters.fire({ scheme: formatter.scheme });\n\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tthis.formatters = this.formatters.filter(f => f !== formatter);\n\t\t\t\tthis._onDidChangeFormatters.fire({ scheme: formatter.scheme });\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate formatUri(resource: URI, formatting: ResourceLabelFormatting, forceNoTildify?: boolean): string {\n\t\tlet label = formatting.label.replace(labelMatchingRegexp, (match, token, qsToken, qsValue) => {\n\t\t\tswitch (token) {\n\t\t\t\tcase 'scheme': return resource.scheme;\n\t\t\t\tcase 'authority': return resource.authority;\n\t\t\t\tcase 'authoritySuffix': {\n\t\t\t\t\tconst i = resource.authority.indexOf('+');\n\t\t\t\t\treturn i === -1 ? resource.authority : resource.authority.slice(i + 1);\n\t\t\t\t}\n\t\t\t\tcase 'path':\n\t\t\t\t\treturn formatting.stripPathStartingSeparator\n\t\t\t\t\t\t? resource.path.slice(resource.path[0] === formatting.separator ? 1 : 0)\n\t\t\t\t\t\t: resource.path;\n\t\t\t\tdefault: {\n\t\t\t\t\tif (qsToken === 'query') {\n\t\t\t\t\t\tconst { query } = resource;\n\t\t\t\t\t\tif (query && query[0] === '{' && query[query.length - 1] === '}') {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\treturn JSON.parse(query)[qsValue] || '';\n\t\t\t\t\t\t\t} catch { }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn '';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// convert \\c:\\something => C:\\something\n\t\tif (formatting.normalizeDriveLetter && hasDriveLetterIgnorePlatform(label)) {\n\t\t\tlabel = label.charAt(1).toUpperCase() + label.substr(2);\n\t\t}\n\n\t\tif (formatting.tildify && !forceNoTildify) {\n\t\t\tif (this.userHome) {\n\t\t\t\tlabel = tildify(label, this.userHome.fsPath, this.os);\n\t\t\t}\n\t\t}\n\n\t\tif (formatting.authorityPrefix && resource.authority) {\n\t\t\tlabel = formatting.authorityPrefix + label;\n\t\t}\n\n\t\treturn this.adjustPathSeparators(label, formatting.separator);\n\t}\n\n\tprivate adjustPathSeparators(label: string, separator: '/' | '\\\\' | ''): string {\n\t\treturn label.replace(this.os === OperatingSystem.Windows ? winPathSeparatorRegexp : posixPathSeparatorRegexp, separator);\n\t}\n\n\tprivate appendWorkspaceSuffix(label: string, uri: URI): string {\n\t\tconst formatting = this.findFormatting(uri);\n\t\tconst suffix = formatting && (typeof formatting.workspaceSuffix === 'string') ? formatting.workspaceSuffix : undefined;\n\n\t\treturn suffix ? `${label} [${suffix}]` : label;\n\t}\n}\n\nregisterSingleton(ILabelService, LabelService, InstantiationType.Delayed);\n"
  },
  {
    "path": "vscode-web/src/vs/workbench/services/textfile/browser/textFileService.ts",
    "content": "/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { localize } from '../../../../nls.js';\nimport { URI } from '../../../../base/common/uri.js';\nimport { IEncodingSupport, ITextFileService, ITextFileStreamContent, ITextFileContent, IResourceEncodings, IReadTextFileOptions, IWriteTextFileOptions, toBufferOrReadable, TextFileOperationError, TextFileOperationResult, ITextFileSaveOptions, ITextFileEditorModelManager, IResourceEncoding, stringToSnapshot, ITextFileSaveAsOptions, IReadTextFileEncodingOptions, TextFileEditorModelState, IResolvedTextFileEditorModel } from '../common/textfiles.js';\nimport { IRevertOptions, SaveSourceRegistry } from '../../../common/editor.js';\nimport { ILifecycleService } from '../../lifecycle/common/lifecycle.js';\nimport { IFileService, FileOperationError, FileOperationResult, IFileStatWithMetadata, ICreateFileOptions, IFileStreamContent } from '../../../../platform/files/common/files.js';\nimport { Disposable } from '../../../../base/common/lifecycle.js';\nimport { extname as pathExtname } from '../../../../base/common/path.js';\nimport { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';\nimport { IUntitledTextEditorService, IUntitledTextEditorModelManager } from '../../untitled/common/untitledTextEditorService.js';\nimport { IResolvedUntitledTextEditorModel, UntitledTextEditorModel } from '../../untitled/common/untitledTextEditorModel.js';\nimport { TextFileEditorModelManager } from '../common/textFileEditorModelManager.js';\nimport { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';\nimport { Schemas } from '../../../../base/common/network.js';\nimport { createTextBufferFactoryFromSnapshot, createTextBufferFactoryFromStream } from '../../../../editor/common/model/textModel.js';\nimport { IModelService } from '../../../../editor/common/services/model.js';\nimport { joinPath, dirname, basename, toLocalResource, extname, isEqual } from '../../../../base/common/resources.js';\nimport { IDialogService, IFileDialogService } from '../../../../platform/dialogs/common/dialogs.js';\nimport { VSBuffer, VSBufferReadable, bufferToStream, VSBufferReadableStream } from '../../../../base/common/buffer.js';\nimport { ITextSnapshot, ITextModel } from '../../../../editor/common/model.js';\nimport { ITextResourceConfigurationService } from '../../../../editor/common/services/textResourceConfiguration.js';\nimport { PLAINTEXT_LANGUAGE_ID } from '../../../../editor/common/languages/modesRegistry.js';\nimport { IFilesConfigurationService } from '../../filesConfiguration/common/filesConfigurationService.js';\nimport { IResolvedTextEditorModel } from '../../../../editor/common/services/resolverService.js';\nimport { BaseTextEditorModel } from '../../../common/editor/textEditorModel.js';\nimport { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';\nimport { IPathService } from '../../path/common/pathService.js';\nimport { IWorkingCopyFileService, IFileOperationUndoRedoInfo, ICreateFileOperation } from '../../workingCopy/common/workingCopyFileService.js';\nimport { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';\nimport { IWorkspaceContextService, WORKSPACE_EXTENSION } from '../../../../platform/workspace/common/workspace.js';\nimport { UTF8, UTF8_with_bom, UTF16be, UTF16le, encodingExists, toEncodeReadable, toDecodeStream, IDecodeStreamResult, DecodeStreamError, DecodeStreamErrorKind } from '../common/encoding.js';\nimport { consumeStream, ReadableStream } from '../../../../base/common/stream.js';\nimport { ILanguageService } from '../../../../editor/common/languages/language.js';\nimport { ILogService } from '../../../../platform/log/common/log.js';\nimport { CancellationToken, CancellationTokenSource } from '../../../../base/common/cancellation.js';\nimport { IElevatedFileService } from '../../files/common/elevatedFileService.js';\nimport { IDecorationData, IDecorationsProvider, IDecorationsService } from '../../decorations/common/decorations.js';\nimport { Emitter } from '../../../../base/common/event.js';\nimport { Codicon } from '../../../../base/common/codicons.js';\nimport { listErrorForeground } from '../../../../platform/theme/common/colorRegistry.js';\n\nexport abstract class AbstractTextFileService extends Disposable implements ITextFileService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate static readonly TEXTFILE_SAVE_CREATE_SOURCE = SaveSourceRegistry.registerSource('textFileCreate.source', localize('textFileCreate.source', \"File Created\"));\n\tprivate static readonly TEXTFILE_SAVE_REPLACE_SOURCE = SaveSourceRegistry.registerSource('textFileOverwrite.source', localize('textFileOverwrite.source', \"File Replaced\"));\n\n\treadonly files: ITextFileEditorModelManager;\n\n\treadonly untitled: IUntitledTextEditorModelManager;\n\n\tconstructor(\n\t\t@IFileService protected readonly fileService: IFileService,\n\t\t@IUntitledTextEditorService untitledTextEditorService: IUntitledTextEditorModelManager,\n\t\t@ILifecycleService protected readonly lifecycleService: ILifecycleService,\n\t\t@IInstantiationService protected readonly instantiationService: IInstantiationService,\n\t\t@IModelService private readonly modelService: IModelService,\n\t\t@IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService,\n\t\t@IDialogService private readonly dialogService: IDialogService,\n\t\t@IFileDialogService private readonly fileDialogService: IFileDialogService,\n\t\t@ITextResourceConfigurationService protected readonly textResourceConfigurationService: ITextResourceConfigurationService,\n\t\t@IFilesConfigurationService protected readonly filesConfigurationService: IFilesConfigurationService,\n\t\t@ICodeEditorService private readonly codeEditorService: ICodeEditorService,\n\t\t@IPathService private readonly pathService: IPathService,\n\t\t@IWorkingCopyFileService private readonly workingCopyFileService: IWorkingCopyFileService,\n\t\t@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,\n\t\t@ILanguageService private readonly languageService: ILanguageService,\n\t\t@ILogService protected readonly logService: ILogService,\n\t\t@IElevatedFileService private readonly elevatedFileService: IElevatedFileService,\n\t\t@IDecorationsService private readonly decorationsService: IDecorationsService\n\t) {\n\t\tsuper();\n\n\t\tthis.files = this._register(this.instantiationService.createInstance(TextFileEditorModelManager));\n\t\tthis.untitled = untitledTextEditorService;\n\n\t\t/* below codes are changed by github1s */\n\t\tif (!globalThis._VSCODE_WEB?.hideTextFileLabelDecorations) {\n\t\t\tthis.provideDecorations();\n\t\t}\n\t\t/* above codes are changed by github1s */\n\t}\n\n\t//#region decorations\n\n\tprivate provideDecorations(): void {\n\n\t\t// Text file model decorations\n\t\tconst provider = this._register(new class extends Disposable implements IDecorationsProvider {\n\n\t\t\treadonly label = localize('textFileModelDecorations', \"Text File Model Decorations\");\n\n\t\t\tprivate readonly _onDidChange = this._register(new Emitter<URI[]>());\n\t\t\treadonly onDidChange = this._onDidChange.event;\n\n\t\t\tconstructor(private readonly files: ITextFileEditorModelManager) {\n\t\t\t\tsuper();\n\n\t\t\t\tthis.registerListeners();\n\t\t\t}\n\n\t\t\tprivate registerListeners(): void {\n\n\t\t\t\t// Creates\n\t\t\t\tthis._register(this.files.onDidResolve(({ model }) => {\n\t\t\t\t\tif (model.isReadonly() || model.hasState(TextFileEditorModelState.ORPHAN)) {\n\t\t\t\t\t\tthis._onDidChange.fire([model.resource]);\n\t\t\t\t\t}\n\t\t\t\t}));\n\n\t\t\t\t// Removals: once a text file model is no longer\n\t\t\t\t// under our control, make sure to signal this as\n\t\t\t\t// decoration change because from this point on we\n\t\t\t\t// have no way of updating the decoration anymore.\n\t\t\t\tthis._register(this.files.onDidRemove(modelUri => this._onDidChange.fire([modelUri])));\n\n\t\t\t\t// Changes\n\t\t\t\tthis._register(this.files.onDidChangeReadonly(model => this._onDidChange.fire([model.resource])));\n\t\t\t\tthis._register(this.files.onDidChangeOrphaned(model => this._onDidChange.fire([model.resource])));\n\t\t\t}\n\n\t\t\tprovideDecorations(uri: URI): IDecorationData | undefined {\n\t\t\t\tconst model = this.files.get(uri);\n\t\t\t\tif (!model || model.isDisposed()) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst isReadonly = model.isReadonly();\n\t\t\t\tconst isOrphaned = model.hasState(TextFileEditorModelState.ORPHAN);\n\n\t\t\t\t// Readonly + Orphaned\n\t\t\t\tif (isReadonly && isOrphaned) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcolor: listErrorForeground,\n\t\t\t\t\t\tletter: Codicon.lockSmall,\n\t\t\t\t\t\tstrikethrough: true,\n\t\t\t\t\t\ttooltip: localize('readonlyAndDeleted', \"Deleted, Read-only\"),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Readonly\n\t\t\t\telse if (isReadonly) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tletter: Codicon.lockSmall,\n\t\t\t\t\t\ttooltip: localize('readonly', \"Read-only\"),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Orphaned\n\t\t\t\telse if (isOrphaned) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcolor: listErrorForeground,\n\t\t\t\t\t\tstrikethrough: true,\n\t\t\t\t\t\ttooltip: localize('deleted', \"Deleted\"),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}(this.files));\n\n\t\tthis._register(this.decorationsService.registerDecorationsProvider(provider));\n\t}\n\n\t//#endregion\n\n\t//#region text file read / write / create\n\n\tprivate _encoding: EncodingOracle | undefined;\n\n\tget encoding(): EncodingOracle {\n\t\tif (!this._encoding) {\n\t\t\tthis._encoding = this._register(this.instantiationService.createInstance(EncodingOracle));\n\t\t}\n\n\t\treturn this._encoding;\n\t}\n\n\tasync read(resource: URI, options?: IReadTextFileOptions): Promise<ITextFileContent> {\n\t\tconst [bufferStream, decoder] = await this.doRead(resource, {\n\t\t\t...options,\n\t\t\t// optimization: since we know that the caller does not\n\t\t\t// care about buffering, we indicate this to the reader.\n\t\t\t// this reduces all the overhead the buffered reading\n\t\t\t// has (open, read, close) if the provider supports\n\t\t\t// unbuffered reading.\n\t\t\tpreferUnbuffered: true\n\t\t});\n\n\t\treturn {\n\t\t\t...bufferStream,\n\t\t\tencoding: decoder.detected.encoding || UTF8,\n\t\t\tvalue: await consumeStream(decoder.stream, strings => strings.join(''))\n\t\t};\n\t}\n\n\tasync readStream(resource: URI, options?: IReadTextFileOptions): Promise<ITextFileStreamContent> {\n\t\tconst [bufferStream, decoder] = await this.doRead(resource, options);\n\n\t\treturn {\n\t\t\t...bufferStream,\n\t\t\tencoding: decoder.detected.encoding || UTF8,\n\t\t\tvalue: await createTextBufferFactoryFromStream(decoder.stream)\n\t\t};\n\t}\n\n\tprivate async doRead(resource: URI, options?: IReadTextFileOptions & { preferUnbuffered?: boolean }): Promise<[IFileStreamContent, IDecodeStreamResult]> {\n\t\tconst cts = new CancellationTokenSource();\n\n\t\t// read stream raw (either buffered or unbuffered)\n\t\tlet bufferStream: IFileStreamContent;\n\t\tif (options?.preferUnbuffered) {\n\t\t\tconst content = await this.fileService.readFile(resource, options, cts.token);\n\t\t\tbufferStream = {\n\t\t\t\t...content,\n\t\t\t\tvalue: bufferToStream(content.value)\n\t\t\t};\n\t\t} else {\n\t\t\tbufferStream = await this.fileService.readFileStream(resource, options, cts.token);\n\t\t}\n\n\t\t// read through encoding library\n\t\ttry {\n\t\t\tconst decoder = await this.doGetDecodedStream(resource, bufferStream.value, options);\n\n\t\t\treturn [bufferStream, decoder];\n\t\t} catch (error) {\n\n\t\t\t// Make sure to cancel reading on error to\n\t\t\t// stop file service activity as soon as\n\t\t\t// possible. When for example a large binary\n\t\t\t// file is read we want to cancel the read\n\t\t\t// instantly.\n\t\t\t// Refs:\n\t\t\t// - https://github.com/microsoft/vscode/issues/138805\n\t\t\t// - https://github.com/microsoft/vscode/issues/132771\n\t\t\tcts.dispose(true);\n\n\t\t\t// special treatment for streams that are binary\n\t\t\tif ((<DecodeStreamError>error).decodeStreamErrorKind === DecodeStreamErrorKind.STREAM_IS_BINARY) {\n\t\t\t\tthrow new TextFileOperationError(localize('fileBinaryError', \"File seems to be binary and cannot be opened as text\"), TextFileOperationResult.FILE_IS_BINARY, options);\n\t\t\t}\n\n\t\t\t// re-throw any other error as it is\n\t\t\telse {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n\n\tasync create(operations: { resource: URI; value?: string | ITextSnapshot; options?: ICreateFileOptions }[], undoInfo?: IFileOperationUndoRedoInfo): Promise<readonly IFileStatWithMetadata[]> {\n\t\tconst operationsWithContents: ICreateFileOperation[] = await Promise.all(operations.map(async operation => {\n\t\t\tconst contents = await this.getEncodedReadable(operation.resource, operation.value);\n\t\t\treturn {\n\t\t\t\tresource: operation.resource,\n\t\t\t\tcontents,\n\t\t\t\toverwrite: operation.options?.overwrite\n\t\t\t};\n\t\t}));\n\n\t\treturn this.workingCopyFileService.create(operationsWithContents, CancellationToken.None, undoInfo);\n\t}\n\n\tasync write(resource: URI, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<IFileStatWithMetadata> {\n\t\tconst readable = await this.getEncodedReadable(resource, value, options);\n\n\t\tif (options?.writeElevated && this.elevatedFileService.isSupported(resource)) {\n\t\t\treturn this.elevatedFileService.writeFileElevated(resource, readable, options);\n\t\t}\n\n\t\treturn this.fileService.writeFile(resource, readable, options);\n\t}\n\n\tasync getEncodedReadable(resource: URI | undefined, value: ITextSnapshot): Promise<VSBufferReadable>;\n\tasync getEncodedReadable(resource: URI | undefined, value: string): Promise<VSBuffer | VSBufferReadable>;\n\tasync getEncodedReadable(resource: URI | undefined, value?: ITextSnapshot): Promise<VSBufferReadable | undefined>;\n\tasync getEncodedReadable(resource: URI | undefined, value?: string): Promise<VSBuffer | VSBufferReadable | undefined>;\n\tasync getEncodedReadable(resource: URI | undefined, value?: string | ITextSnapshot): Promise<VSBuffer | VSBufferReadable | undefined>;\n\tasync getEncodedReadable(resource: URI | undefined, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<VSBuffer | VSBufferReadable>;\n\tasync getEncodedReadable(resource: URI | undefined, value?: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<VSBuffer | VSBufferReadable | undefined> {\n\n\t\t// check for encoding\n\t\tconst { encoding, addBOM } = await this.encoding.getWriteEncoding(resource, options);\n\n\t\t// when encoding is standard skip encoding step\n\t\tif (encoding === UTF8 && !addBOM) {\n\t\t\treturn typeof value === 'undefined'\n\t\t\t\t? undefined\n\t\t\t\t: toBufferOrReadable(value);\n\t\t}\n\n\t\t// otherwise create encoded readable\n\t\tvalue = value || '';\n\t\tconst snapshot = typeof value === 'string' ? stringToSnapshot(value) : value;\n\t\treturn toEncodeReadable(snapshot, encoding, { addBOM });\n\t}\n\n\tasync getDecodedStream(resource: URI | undefined, value: VSBufferReadableStream, options?: IReadTextFileEncodingOptions): Promise<ReadableStream<string>> {\n\t\treturn (await this.doGetDecodedStream(resource, value, options)).stream;\n\t}\n\n\tprivate doGetDecodedStream(resource: URI | undefined, stream: VSBufferReadableStream, options?: IReadTextFileEncodingOptions): Promise<IDecodeStreamResult> {\n\n\t\t// read through encoding library\n\t\treturn toDecodeStream(stream, {\n\t\t\tacceptTextOnly: options?.acceptTextOnly ?? false,\n\t\t\tguessEncoding:\n\t\t\t\toptions?.autoGuessEncoding ||\n\t\t\t\tthis.textResourceConfigurationService.getValue(resource, 'files.autoGuessEncoding'),\n\t\t\tcandidateGuessEncodings:\n\t\t\t\toptions?.candidateGuessEncodings ||\n\t\t\t\tthis.textResourceConfigurationService.getValue(resource, 'files.candidateGuessEncodings'),\n\t\t\toverwriteEncoding: async detectedEncoding => this.validateDetectedEncoding(resource, detectedEncoding ?? undefined, options)\n\t\t});\n\t}\n\n\tgetEncoding(resource: URI): string {\n\t\tconst model = resource.scheme === Schemas.untitled ? this.untitled.get(resource) : this.files.get(resource);\n\t\treturn model?.getEncoding() ?? this.encoding.getUnvalidatedEncodingForResource(resource);\n\t}\n\n\tasync resolveDecoding(resource: URI | undefined, options?: IReadTextFileEncodingOptions): Promise<{ preferredEncoding: string; guessEncoding: boolean; candidateGuessEncodings: string[] }> {\n\t\treturn {\n\t\t\tpreferredEncoding: (await this.encoding.getPreferredReadEncoding(resource, options, undefined)).encoding,\n\t\t\tguessEncoding:\n\t\t\t\toptions?.autoGuessEncoding ||\n\t\t\t\tthis.textResourceConfigurationService.getValue(resource, 'files.autoGuessEncoding'),\n\t\t\tcandidateGuessEncodings:\n\t\t\t\toptions?.candidateGuessEncodings ||\n\t\t\t\tthis.textResourceConfigurationService.getValue(resource, 'files.candidateGuessEncodings'),\n\t\t};\n\t}\n\n\tasync validateDetectedEncoding(resource: URI | undefined, detectedEncoding: string | undefined, options?: IReadTextFileEncodingOptions): Promise<string> {\n\t\tconst { encoding } = await this.encoding.getPreferredReadEncoding(resource, options, detectedEncoding);\n\n\t\treturn encoding;\n\t}\n\n\tresolveEncoding(resource: URI | undefined, options?: IWriteTextFileOptions): Promise<{ encoding: string; addBOM: boolean }> {\n\t\treturn this.encoding.getWriteEncoding(resource, options);\n\t}\n\n\t//#endregion\n\n\n\t//#region save\n\n\tasync save(resource: URI, options?: ITextFileSaveOptions): Promise<URI | undefined> {\n\n\t\t// Untitled\n\t\tif (resource.scheme === Schemas.untitled) {\n\t\t\tconst model = this.untitled.get(resource);\n\t\t\tif (model) {\n\t\t\t\tlet targetUri: URI | undefined;\n\n\t\t\t\t// Untitled with associated file path don't need to prompt\n\t\t\t\tif (model.hasAssociatedFilePath) {\n\t\t\t\t\ttargetUri = await this.suggestSavePath(resource);\n\t\t\t\t}\n\n\t\t\t\t// Otherwise ask user\n\t\t\t\telse {\n\t\t\t\t\ttargetUri = await this.fileDialogService.pickFileToSave(await this.suggestSavePath(resource), options?.availableFileSystems);\n\t\t\t\t}\n\n\t\t\t\t// Save as if target provided\n\t\t\t\tif (targetUri) {\n\t\t\t\t\treturn this.saveAs(resource, targetUri, options);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// File\n\t\telse {\n\t\t\tconst model = this.files.get(resource);\n\t\t\tif (model) {\n\t\t\t\treturn await model.save(options) ? resource : undefined;\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tasync saveAs(source: URI, target?: URI, options?: ITextFileSaveAsOptions): Promise<URI | undefined> {\n\n\t\t// Get to target resource\n\t\tif (!target) {\n\t\t\ttarget = await this.fileDialogService.pickFileToSave(await this.suggestSavePath(options?.suggestedTarget ?? source), options?.availableFileSystems);\n\t\t}\n\n\t\tif (!target) {\n\t\t\treturn; // user canceled\n\t\t}\n\n\t\t// Ensure target is not marked as readonly and prompt otherwise\n\t\tif (this.filesConfigurationService.isReadonly(target)) {\n\t\t\tconst confirmed = await this.confirmMakeWriteable(target);\n\t\t\tif (!confirmed) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthis.filesConfigurationService.updateReadonly(target, false);\n\t\t\t}\n\t\t}\n\n\t\t// Just save if target is same as models own resource\n\t\tif (isEqual(source, target)) {\n\t\t\treturn this.save(source, { ...options, force: true  /* force to save, even if not dirty (https://github.com/microsoft/vscode/issues/99619) */ });\n\t\t}\n\n\t\t// If the target is different but of same identity, we\n\t\t// move the source to the target, knowing that the\n\t\t// underlying file system cannot have both and then save.\n\t\t// However, this will only work if the source exists\n\t\t// and is not orphaned, so we need to check that too.\n\t\tif (this.fileService.hasProvider(source) && this.uriIdentityService.extUri.isEqual(source, target) && (await this.fileService.exists(source))) {\n\t\t\tawait this.workingCopyFileService.move([{ file: { source, target } }], CancellationToken.None);\n\n\t\t\t// At this point we don't know whether we have a\n\t\t\t// model for the source or the target URI so we\n\t\t\t// simply try to save with both resources.\n\t\t\tconst success = await this.save(source, options);\n\t\t\tif (!success) {\n\t\t\t\tawait this.save(target, options);\n\t\t\t}\n\n\t\t\treturn target;\n\t\t}\n\n\t\t// Do it\n\t\treturn this.doSaveAs(source, target, options);\n\t}\n\n\tprivate async doSaveAs(source: URI, target: URI, options?: ITextFileSaveOptions): Promise<URI | undefined> {\n\t\tlet success = false;\n\n\t\tlet resolvedTextModel: IResolvedTextFileEditorModel | IResolvedUntitledTextEditorModel | undefined;\n\t\tif (source.scheme !== Schemas.untitled) {\n\t\t\tconst textFileModel = this.files.get(source);\n\t\t\tif (textFileModel?.isResolved()) {\n\t\t\t\tresolvedTextModel = textFileModel;\n\t\t\t}\n\t\t} else {\n\t\t\tconst untitledTextModel = this.untitled.get(source);\n\t\t\tif (untitledTextModel?.isResolved()) {\n\t\t\t\tresolvedTextModel = untitledTextModel;\n\t\t\t}\n\t\t}\n\n\t\t// If the source is an existing resolved file or untitled text model, we can\n\t\t// directly use that model to copy the contents to the target destination\n\t\tif (resolvedTextModel) {\n\t\t\tsuccess = await this.doSaveAsTextFile(resolvedTextModel, source, target, options);\n\t\t}\n\n\t\t// Otherwise if the source can be handled by the file service\n\t\t// we can simply invoke the copy() function to save as\n\t\telse if (this.fileService.hasProvider(source)) {\n\t\t\tawait this.fileService.copy(source, target, true);\n\n\t\t\tsuccess = true;\n\t\t}\n\n\t\t// Finally we simply check if we can find a editor model that\n\t\t// would give us access to the contents.\n\t\telse {\n\t\t\tconst textModel = this.modelService.getModel(source);\n\t\t\tif (textModel) {\n\t\t\t\tsuccess = await this.doSaveAsTextFile(textModel, source, target, options);\n\t\t\t}\n\t\t}\n\n\t\tif (!success) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Revert the source\n\t\ttry {\n\t\t\tawait this.revert(source);\n\t\t} catch (error) {\n\n\t\t\t// It is possible that reverting the source fails, for example\n\t\t\t// when a remote is disconnected and we cannot read it anymore.\n\t\t\t// However, this should not interrupt the \"Save As\" flow, so\n\t\t\t// we gracefully catch the error and just log it.\n\n\t\t\tthis.logService.error(error);\n\t\t}\n\n\t\t// Events\n\t\tif (source.scheme === Schemas.untitled) {\n\t\t\tthis.untitled.notifyDidSave(source, target);\n\t\t}\n\n\t\treturn target;\n\t}\n\n\tprivate async doSaveAsTextFile(sourceModel: IResolvedTextEditorModel | IResolvedUntitledTextEditorModel | ITextModel, source: URI, target: URI, options?: ITextFileSaveOptions): Promise<boolean> {\n\n\t\t// Find source encoding if any\n\t\tlet sourceModelEncoding: string | undefined = undefined;\n\t\tconst sourceModelWithEncodingSupport = (sourceModel as unknown as IEncodingSupport);\n\t\tif (typeof sourceModelWithEncodingSupport.getEncoding === 'function') {\n\t\t\tsourceModelEncoding = sourceModelWithEncodingSupport.getEncoding();\n\t\t}\n\n\t\t// Prefer an existing model if it is already resolved for the given target resource\n\t\tlet targetExists = false;\n\t\tlet targetModel = this.files.get(target);\n\t\tif (targetModel?.isResolved()) {\n\t\t\ttargetExists = true;\n\t\t}\n\n\t\t// Otherwise create the target file empty if it does not exist already and resolve it from there\n\t\telse {\n\t\t\ttargetExists = await this.fileService.exists(target);\n\n\t\t\t// create target file adhoc if it does not exist yet\n\t\t\tif (!targetExists) {\n\t\t\t\tawait this.create([{ resource: target, value: '' }]);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\ttargetModel = await this.files.resolve(target, { encoding: sourceModelEncoding });\n\t\t\t} catch (error) {\n\t\t\t\t// if the target already exists and was not created by us, it is possible\n\t\t\t\t// that we cannot resolve the target as text model if it is binary or too\n\t\t\t\t// large. in that case we have to delete the target file first and then\n\t\t\t\t// re-run the operation.\n\t\t\t\tif (targetExists) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t(<TextFileOperationError>error).textFileOperationResult === TextFileOperationResult.FILE_IS_BINARY ||\n\t\t\t\t\t\t(<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_TOO_LARGE\n\t\t\t\t\t) {\n\t\t\t\t\t\tawait this.fileService.del(target);\n\n\t\t\t\t\t\treturn this.doSaveAsTextFile(sourceModel, source, target, options);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\t// Confirm to overwrite if we have an untitled file with associated file where\n\t\t// the file actually exists on disk and we are instructed to save to that file\n\t\t// path. This can happen if the file was created after the untitled file was opened.\n\t\t// See https://github.com/microsoft/vscode/issues/67946\n\t\tlet write: boolean;\n\t\tif (sourceModel instanceof UntitledTextEditorModel && sourceModel.hasAssociatedFilePath && targetExists && this.uriIdentityService.extUri.isEqual(target, toLocalResource(sourceModel.resource, this.environmentService.remoteAuthority, this.pathService.defaultUriScheme))) {\n\t\t\twrite = await this.confirmOverwrite(target);\n\t\t} else {\n\t\t\twrite = true;\n\t\t}\n\n\t\tif (!write) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet sourceTextModel: ITextModel | undefined = undefined;\n\t\tif (sourceModel instanceof BaseTextEditorModel) {\n\t\t\tif (sourceModel.isResolved()) {\n\t\t\t\tsourceTextModel = sourceModel.textEditorModel ?? undefined;\n\t\t\t}\n\t\t} else {\n\t\t\tsourceTextModel = sourceModel as ITextModel;\n\t\t}\n\n\t\tlet targetTextModel: ITextModel | undefined = undefined;\n\t\tif (targetModel.isResolved()) {\n\t\t\ttargetTextModel = targetModel.textEditorModel;\n\t\t}\n\n\t\t// take over model value, encoding and language (only if more specific) from source model\n\t\tif (sourceTextModel && targetTextModel) {\n\n\t\t\t// encoding\n\t\t\ttargetModel.updatePreferredEncoding(sourceModelEncoding);\n\n\t\t\t// content\n\t\t\tthis.modelService.updateModel(targetTextModel, createTextBufferFactoryFromSnapshot(sourceTextModel.createSnapshot()));\n\n\t\t\t// language\n\t\t\tconst sourceLanguageId = sourceTextModel.getLanguageId();\n\t\t\tconst targetLanguageId = targetTextModel.getLanguageId();\n\t\t\tif (sourceLanguageId !== PLAINTEXT_LANGUAGE_ID && targetLanguageId === PLAINTEXT_LANGUAGE_ID) {\n\t\t\t\ttargetTextModel.setLanguage(sourceLanguageId); // only use if more specific than plain/text\n\t\t\t}\n\n\t\t\t// transient properties\n\t\t\tconst sourceTransientProperties = this.codeEditorService.getTransientModelProperties(sourceTextModel);\n\t\t\tif (sourceTransientProperties) {\n\t\t\t\tfor (const [key, value] of sourceTransientProperties) {\n\t\t\t\t\tthis.codeEditorService.setTransientModelProperty(targetTextModel, key, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// set source options depending on target exists or not\n\t\tif (!options?.source) {\n\t\t\toptions = {\n\t\t\t\t...options,\n\t\t\t\tsource: targetExists ? AbstractTextFileService.TEXTFILE_SAVE_REPLACE_SOURCE : AbstractTextFileService.TEXTFILE_SAVE_CREATE_SOURCE\n\t\t\t};\n\t\t}\n\n\t\t// save model\n\t\treturn targetModel.save({\n\t\t\t...options,\n\t\t\tfrom: source\n\t\t});\n\t}\n\n\tprivate async confirmOverwrite(resource: URI): Promise<boolean> {\n\t\tconst { confirmed } = await this.dialogService.confirm({\n\t\t\ttype: 'warning',\n\t\t\tmessage: localize('confirmOverwrite', \"'{0}' already exists. Do you want to replace it?\", basename(resource)),\n\t\t\tdetail: localize('overwriteIrreversible', \"A file or folder with the name '{0}' already exists in the folder '{1}'. Replacing it will overwrite its current contents.\", basename(resource), basename(dirname(resource))),\n\t\t\tprimaryButton: localize({ key: 'replaceButtonLabel', comment: ['&& denotes a mnemonic'] }, \"&&Replace\"),\n\t\t});\n\n\t\treturn confirmed;\n\t}\n\n\tprivate async confirmMakeWriteable(resource: URI): Promise<boolean> {\n\t\tconst { confirmed } = await this.dialogService.confirm({\n\t\t\ttype: 'warning',\n\t\t\tmessage: localize('confirmMakeWriteable', \"'{0}' is marked as read-only. Do you want to save anyway?\", basename(resource)),\n\t\t\tdetail: localize('confirmMakeWriteableDetail', \"Paths can be configured as read-only via settings.\"),\n\t\t\tprimaryButton: localize({ key: 'makeWriteableButtonLabel', comment: ['&& denotes a mnemonic'] }, \"&&Save Anyway\")\n\t\t});\n\n\t\treturn confirmed;\n\t}\n\n\tprivate async suggestSavePath(resource: URI): Promise<URI> {\n\n\t\t// Just take the resource as is if the file service can handle it\n\t\tif (this.fileService.hasProvider(resource)) {\n\t\t\treturn resource;\n\t\t}\n\n\t\tconst remoteAuthority = this.environmentService.remoteAuthority;\n\t\tconst defaultFilePath = await this.fileDialogService.defaultFilePath();\n\n\t\t// Otherwise try to suggest a path that can be saved\n\t\tlet suggestedFilename: string | undefined = undefined;\n\t\tif (resource.scheme === Schemas.untitled) {\n\t\t\tconst model = this.untitled.get(resource);\n\t\t\tif (model) {\n\n\t\t\t\t// Untitled with associated file path\n\t\t\t\tif (model.hasAssociatedFilePath) {\n\t\t\t\t\treturn toLocalResource(resource, remoteAuthority, this.pathService.defaultUriScheme);\n\t\t\t\t}\n\n\t\t\t\t// Untitled without associated file path: use name\n\t\t\t\t// of untitled model if it is a valid path name and\n\t\t\t\t// figure out the file extension from the mode if any.\n\n\t\t\t\tlet nameCandidate: string;\n\t\t\t\tif (await this.pathService.hasValidBasename(joinPath(defaultFilePath, model.name), model.name)) {\n\t\t\t\t\tnameCandidate = model.name;\n\t\t\t\t} else {\n\t\t\t\t\tnameCandidate = basename(resource);\n\t\t\t\t}\n\n\t\t\t\tconst languageId = model.getLanguageId();\n\t\t\t\tif (languageId && languageId !== PLAINTEXT_LANGUAGE_ID) {\n\t\t\t\t\tsuggestedFilename = this.suggestFilename(languageId, nameCandidate);\n\t\t\t\t} else {\n\t\t\t\t\tsuggestedFilename = nameCandidate;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to basename of resource\n\t\tif (!suggestedFilename) {\n\t\t\tsuggestedFilename = basename(resource);\n\t\t}\n\n\t\t// Try to place where last active file was if any\n\t\t// Otherwise fallback to user home\n\t\treturn joinPath(defaultFilePath, suggestedFilename);\n\t}\n\n\tsuggestFilename(languageId: string, untitledName: string) {\n\t\tconst languageName = this.languageService.getLanguageName(languageId);\n\t\tif (!languageName) {\n\t\t\treturn untitledName; // unknown language, so we cannot suggest a better name\n\t\t}\n\n\t\tconst untitledExtension = pathExtname(untitledName);\n\n\t\tconst extensions = this.languageService.getExtensions(languageId);\n\t\tif (extensions.includes(untitledExtension)) {\n\t\t\treturn untitledName; // preserve extension if it is compatible with the mode\n\t\t}\n\n\t\tconst primaryExtension = extensions.at(0);\n\t\tif (primaryExtension) {\n\t\t\tif (untitledExtension) {\n\t\t\t\treturn `${untitledName.substring(0, untitledName.indexOf(untitledExtension))}${primaryExtension}`;\n\t\t\t}\n\n\t\t\treturn `${untitledName}${primaryExtension}`;\n\t\t}\n\n\t\tconst filenames = this.languageService.getFilenames(languageId);\n\t\tif (filenames.includes(untitledName)) {\n\t\t\treturn untitledName; // preserve name if it is compatible with the mode\n\t\t}\n\n\t\treturn filenames.at(0) ?? untitledName;\n\t}\n\n\t//#endregion\n\n\t//#region revert\n\n\tasync revert(resource: URI, options?: IRevertOptions): Promise<void> {\n\n\t\t// Untitled\n\t\tif (resource.scheme === Schemas.untitled) {\n\t\t\tconst model = this.untitled.get(resource);\n\t\t\tif (model) {\n\t\t\t\treturn model.revert(options);\n\t\t\t}\n\t\t}\n\n\t\t// File\n\t\telse {\n\t\t\tconst model = this.files.get(resource);\n\t\t\tif (model && (model.isDirty() || options?.force)) {\n\t\t\t\treturn model.revert(options);\n\t\t\t}\n\t\t}\n\t}\n\n\t//#endregion\n\n\t//#region dirty\n\n\tisDirty(resource: URI): boolean {\n\t\tconst model = resource.scheme === Schemas.untitled ? this.untitled.get(resource) : this.files.get(resource);\n\t\tif (model) {\n\t\t\treturn model.isDirty();\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//#endregion\n}\n\nexport interface IEncodingOverride {\n\tparent?: URI;\n\textension?: string;\n\tencoding: string;\n}\n\nexport class EncodingOracle extends Disposable implements IResourceEncodings {\n\n\tprivate _encodingOverrides: IEncodingOverride[];\n\tprotected get encodingOverrides(): IEncodingOverride[] { return this._encodingOverrides; }\n\tprotected set encodingOverrides(value: IEncodingOverride[]) { this._encodingOverrides = value; }\n\n\tconstructor(\n\t\t@ITextResourceConfigurationService private textResourceConfigurationService: ITextResourceConfigurationService,\n\t\t@IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService,\n\t\t@IWorkspaceContextService private contextService: IWorkspaceContextService,\n\t\t@IUriIdentityService private readonly uriIdentityService: IUriIdentityService\n\t) {\n\t\tsuper();\n\n\t\tthis._encodingOverrides = this.getDefaultEncodingOverrides();\n\n\t\tthis.registerListeners();\n\t}\n\n\tprivate registerListeners(): void {\n\n\t\t// Workspace Folder Change\n\t\tthis._register(this.contextService.onDidChangeWorkspaceFolders(() => this.encodingOverrides = this.getDefaultEncodingOverrides()));\n\t}\n\n\tprivate getDefaultEncodingOverrides(): IEncodingOverride[] {\n\t\tconst defaultEncodingOverrides: IEncodingOverride[] = [];\n\n\t\t// Global settings\n\t\tdefaultEncodingOverrides.push({ parent: this.environmentService.userRoamingDataHome, encoding: UTF8 });\n\n\t\t// Workspace files (via extension and via untitled workspaces location)\n\t\tdefaultEncodingOverrides.push({ extension: WORKSPACE_EXTENSION, encoding: UTF8 });\n\t\tdefaultEncodingOverrides.push({ parent: this.environmentService.untitledWorkspacesHome, encoding: UTF8 });\n\n\t\t// Folder Settings\n\t\tthis.contextService.getWorkspace().folders.forEach(folder => {\n\t\t\tdefaultEncodingOverrides.push({ parent: joinPath(folder.uri, '.vscode'), encoding: UTF8 });\n\t\t});\n\n\t\treturn defaultEncodingOverrides;\n\t}\n\n\tasync getWriteEncoding(resource: URI | undefined, options?: IWriteTextFileOptions): Promise<{ encoding: string; addBOM: boolean }> {\n\t\tconst { encoding, hasBOM } = await this.getPreferredWriteEncoding(resource, options ? options.encoding : undefined);\n\n\t\treturn { encoding, addBOM: hasBOM };\n\t}\n\n\tasync getPreferredWriteEncoding(resource: URI | undefined, preferredEncoding?: string): Promise<IResourceEncoding> {\n\t\tconst resourceEncoding = await this.getValidatedEncodingForResource(resource, preferredEncoding);\n\n\t\treturn {\n\t\t\tencoding: resourceEncoding,\n\t\t\thasBOM: resourceEncoding === UTF16be || resourceEncoding === UTF16le || resourceEncoding === UTF8_with_bom // enforce BOM for certain encodings\n\t\t};\n\t}\n\n\tasync getPreferredReadEncoding(resource: URI | undefined, options?: IReadTextFileEncodingOptions, detectedEncoding?: string): Promise<IResourceEncoding> {\n\t\tlet preferredEncoding: string | undefined;\n\n\t\t// Encoding passed in as option\n\t\tif (options?.encoding) {\n\t\t\tif (detectedEncoding === UTF8_with_bom && options.encoding === UTF8) {\n\t\t\t\tpreferredEncoding = UTF8_with_bom; // indicate the file has BOM if we are to resolve with UTF 8\n\t\t\t} else {\n\t\t\t\tpreferredEncoding = options.encoding; // give passed in encoding highest priority\n\t\t\t}\n\t\t}\n\n\t\t// Encoding detected\n\t\telse if (typeof detectedEncoding === 'string') {\n\t\t\tpreferredEncoding = detectedEncoding;\n\t\t}\n\n\t\t// Encoding configured\n\t\telse if (this.textResourceConfigurationService.getValue(resource, 'files.encoding') === UTF8_with_bom) {\n\t\t\tpreferredEncoding = UTF8; // if we did not detect UTF 8 BOM before, this can only be UTF 8 then\n\t\t}\n\n\t\tconst encoding = await this.getValidatedEncodingForResource(resource, preferredEncoding);\n\n\t\treturn {\n\t\t\tencoding,\n\t\t\thasBOM: encoding === UTF16be || encoding === UTF16le || encoding === UTF8_with_bom // enforce BOM for certain encodings\n\t\t};\n\t}\n\n\tgetUnvalidatedEncodingForResource(resource: URI | undefined, preferredEncoding?: string): string {\n\t\tlet fileEncoding: string;\n\n\t\tconst override = this.getEncodingOverride(resource);\n\t\tif (override) {\n\t\t\tfileEncoding = override; // encoding override always wins\n\t\t} else if (preferredEncoding) {\n\t\t\tfileEncoding = preferredEncoding; // preferred encoding comes second\n\t\t} else {\n\t\t\tfileEncoding = this.textResourceConfigurationService.getValue(resource, 'files.encoding'); // and last we check for settings\n\t\t}\n\n\t\treturn fileEncoding || UTF8;\n\t}\n\n\tprivate async getValidatedEncodingForResource(resource: URI | undefined, preferredEncoding?: string): Promise<string> {\n\t\tlet fileEncoding = this.getUnvalidatedEncodingForResource(resource, preferredEncoding);\n\t\tif (fileEncoding !== UTF8 && !(await encodingExists(fileEncoding))) {\n\t\t\tfileEncoding = UTF8;\n\t\t}\n\n\t\treturn fileEncoding;\n\t}\n\n\tprivate getEncodingOverride(resource: URI | undefined): string | undefined {\n\t\tif (resource && this.encodingOverrides?.length) {\n\t\t\tfor (const override of this.encodingOverrides) {\n\n\t\t\t\t// check if the resource is child of encoding override path\n\t\t\t\tif (override.parent && this.uriIdentityService.extUri.isEqualOrParent(resource, override.parent)) {\n\t\t\t\t\treturn override.encoding;\n\t\t\t\t}\n\n\t\t\t\t// check if the resource extension is equal to encoding override\n\t\t\t\tif (override.extension && extname(resource) === `.${override.extension}`) {\n\t\t\t\t\treturn override.encoding;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n}\n"
  },
  {
    "path": "vscode-web/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\"\n}"
  },
  {
    "path": "webpack.config.js",
    "content": "import path from 'path';\nimport fs from 'fs-extra';\nimport cp from 'child_process';\nimport webpack from 'webpack';\nimport CleanCSS from 'clean-css';\nimport UglifyJS from 'uglify-js';\nimport CopyPlugin from 'copy-webpack-plugin';\nimport HtmlWebpackPlugin from 'html-webpack-plugin';\nimport * as packUtils from './scripts/webpack.js';\n\nconst commitId = cp.execSync('git rev-parse HEAD').toString().trim();\nconst staticDir = `static-${commitId.padStart(7, '0').slice(0, 7)}`;\nconst vscodeWebPath = path.join(import.meta.dirname, 'node_modules/@github1s/vscode-web');\n\nconst skipMinified = { info: { minimized: true } };\nconst skipNodeModules = { globOptions: { dot: true, ignore: ['**/node_modules/**'] } };\nconst fileLoaderOptions = { outputPath: staticDir, name: '[name].[ext]' };\n\nconst copyPluginPatterns = [\n\t{ from: 'extensions', to: `${staticDir}/extensions`, ...skipNodeModules, ...skipMinified },\n\t{ from: path.join(vscodeWebPath, 'vscode'), to: `${staticDir}/vscode`, ...skipMinified },\n\t{ from: path.join(vscodeWebPath, 'extensions'), to: `${staticDir}/extensions`, ...skipMinified },\n\t{ from: path.join(vscodeWebPath, 'dependencies'), to: `${staticDir}/dependencies`, ...skipMinified },\n\t{ from: path.join(vscodeWebPath, 'nls'), to: `${staticDir}/nls`, ...skipMinified },\n];\n\nconst devVscodeStatic = [\n\t...fs.readdirSync(path.join(import.meta.dirname, 'extensions')).map((item) => ({\n\t\tpublicPath: `/${staticDir}/extensions/${item}`,\n\t\tdirectory: path.join(import.meta.dirname, `extensions/${item}`),\n\t})),\n\t{\n\t\tpublicPath: `/${staticDir}/vscode/`,\n\t\tdirectory: path.join(import.meta.dirname, 'vscode-web/lib/vscode/out'),\n\t},\n\t{\n\t\tpublicPath: `/${staticDir}/extensions/`,\n\t\tdirectory: path.join(import.meta.dirname, 'vscode-web/lib/vscode/extensions'),\n\t},\n\t{\n\t\tpublicPath: `/${staticDir}/dependencies/`,\n\t\tdirectory: path.join(import.meta.dirname, 'vscode-web/lib/vscode/node_modules'),\n\t},\n];\n\nexport default (env, argv) => {\n\tconst devMode = argv.mode === 'development';\n\tconst devVscode = !!process.env.DEV_VSCODE;\n\tconst minifyCSS = (code) => (devMode ? code : new CleanCSS().minify(code).styles);\n\tconst minifyJS = (code) => (devMode ? code : UglifyJS.minify(code).code);\n\tconst availableLanguages = devVscode ? [] : fs.readdirSync(path.join(vscodeWebPath, 'nls'));\n\n\treturn {\n\t\tmode: env.mode || 'production',\n\t\tentry: path.resolve(import.meta.dirname, 'src/index.ts'),\n\t\toutput: { clean: true, publicPath: '/', filename: `${staticDir}/bootstrap.js` },\n\t\tresolve: { extensions: ['.js', '.ts'] },\n\t\tmodule: {\n\t\t\trules: [\n\t\t\t\t{ test: /\\.tsx?$/, use: 'ts-loader' },\n\t\t\t\t{ test: /\\.css?$/, use: ['style-loader', 'css-loader'] },\n\t\t\t\t{ test: /\\.svg$/, use: [{ loader: 'file-loader', options: fileLoaderOptions }] },\n\t\t\t],\n\t\t},\n\t\tplugins: [\n\t\t\tnew CopyPlugin({\n\t\t\t\tpatterns: [\n\t\t\t\t\t{ from: 'public/favicon*', to: '[name][ext]' },\n\t\t\t\t\t{ from: 'public/manifest.json', to: '[name][ext]' },\n\t\t\t\t\t{ from: 'public/robots.txt', to: '[name][ext]' },\n\t\t\t\t\t...(devVscode ? [] : copyPluginPatterns),\n\t\t\t\t].filter(Boolean),\n\t\t\t}),\n\t\t\tnew HtmlWebpackPlugin({\n\t\t\t\tminify: !devMode,\n\t\t\t\tscriptLoading: 'module',\n\t\t\t\ttemplate: 'public/index.html',\n\t\t\t\ttemplateParameters: {\n\t\t\t\t\tspinnerStyle: minifyCSS(fs.readFileSync('./public/spinner.css').toString()),\n\t\t\t\t\tpageTitleScript: minifyJS(fs.readFileSync('./public/page-title.js').toString()),\n\t\t\t\t\tglobalScript: minifyJS(packUtils.createGlobalScript(staticDir, devVscode)),\n\t\t\t\t},\n\t\t\t}),\n\t\t\tnew webpack.DefinePlugin({\n\t\t\t\tDEV_VSCODE: JSON.stringify(devVscode),\n\t\t\t\tGITHUB_ORIGIN: JSON.stringify(process.env.GITHUB_DOMAIN || 'https://github.com'),\n\t\t\t\tGITLAB_ORIGIN: JSON.stringify(process.env.GITLAB_DOMAIN || 'https://gitlab.com'),\n\t\t\t\tGITHUB1S_EXTENSIONS: JSON.stringify(packUtils.getBuiltinExtensions(devVscode)),\n\t\t\t\tAVAILABLE_LANGUAGES: JSON.stringify(availableLanguages),\n\t\t\t}),\n\t\t],\n\t\tperformance: false,\n\t\tdevServer: {\n\t\t\tport: 8080,\n\t\t\tliveReload: false,\n\t\t\tallowedHosts: 'all',\n\t\t\tclient: { overlay: false },\n\t\t\tdevMiddleware: { writeToDisk: true },\n\t\t\tstatic: devVscode ? devVscodeStatic : [],\n\t\t\thistoryApiFallback: { disableDotRule: true },\n\t\t},\n\t};\n};\n"
  }
]