refactor: big rewrite
This commit is contained in:
parent
3b3f41af23
commit
aa5e0c97da
21 changed files with 4232 additions and 1403 deletions
23
.github/workflows/lint.yml
vendored
23
.github/workflows/lint.yml
vendored
|
@ -1,23 +0,0 @@
|
||||||
name: Lint
|
|
||||||
on: [push, pull_request]
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
name: Lint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install Node v12
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: 12
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
run: curl -L https://unpkg.com/@pnpm/self-installer | node
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm i
|
|
||||||
|
|
||||||
- name: Run Lint
|
|
||||||
uses: icrawl/action-eslint@v1
|
|
23
.github/workflows/test.yml
vendored
Normal file
23
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
name: Testing
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Node v14
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: 14
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run ESLint
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Run TSC
|
||||||
|
run: npm run build
|
23
.github/workflows/tsc.yml
vendored
23
.github/workflows/tsc.yml
vendored
|
@ -1,23 +0,0 @@
|
||||||
name: TSC
|
|
||||||
on: [push, pull_request]
|
|
||||||
jobs:
|
|
||||||
tsc:
|
|
||||||
name: TSC
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install Node v12
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: 12
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
run: curl -L https://unpkg.com/@pnpm/self-installer | node
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm i
|
|
||||||
|
|
||||||
- name: Run TSC
|
|
||||||
uses: icrawl/action-tsc@v1
|
|
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"useTabs": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"quoteProps": "as-needed",
|
||||||
|
"trailingComma": "all",
|
||||||
|
"endOfLine": "lf"
|
||||||
|
}
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017-2020 iCrawl
|
Copyright (c) 2017-2021 iCrawl
|
||||||
Copyright (c) 2017-2019 Khinenw
|
Copyright (c) 2017-2019 Khinenw
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
|
20
README.md
20
README.md
|
@ -1,4 +1,5 @@
|
||||||
# Discord Presence
|
# Discord Presence
|
||||||
|
|
||||||
> Update your discord status with the newly added rich presence.
|
> Update your discord status with the newly added rich presence.
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
@ -14,19 +15,20 @@
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Shows what you are editing in VSCode with no bullsh*t involved
|
- Shows what you are editing in VSCode with no bullsh\*t involved
|
||||||
* Support for over 130 of the most popular languages
|
- Support for over 130 of the most popular languages
|
||||||
* Enable/Disable Rich Presence for individual workspaces (enabled by default)
|
- Enable/Disable Rich Presence for individual workspaces (enabled by default)
|
||||||
* Custom string support
|
- Custom string support
|
||||||
* Respects Discords 15sec limit when it comes to updating your status
|
- Respects Discords 15sec limit when it comes to updating your status
|
||||||
* Stable or Insiders build detection
|
- Stable or Insiders build detection
|
||||||
* Debug mode detection
|
- Debug mode detection
|
||||||
* Easily manually reconnect to Discord
|
- Easily manually reconnect to Discord
|
||||||
* VSCode Live Share support
|
- VSCode Live Share support
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Can't connect to Discord? Check those:
|
### Can't connect to Discord? Check those:
|
||||||
|
|
||||||
https://github.com/iCrawl/discord-vscode/issues/77#issuecomment-435622205
|
https://github.com/iCrawl/discord-vscode/issues/77#issuecomment-435622205
|
||||||
https://github.com/iCrawl/discord-vscode/issues/85#issuecomment-417895483
|
https://github.com/iCrawl/discord-vscode/issues/85#issuecomment-417895483
|
||||||
|
|
||||||
|
|
3291
package-lock.json
generated
3291
package-lock.json
generated
File diff suppressed because it is too large
Load diff
111
package.json
111
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "discord-vscode",
|
"name": "discord-vscode",
|
||||||
"displayName": "Discord Presence",
|
"displayName": "Discord Presence",
|
||||||
"version": "4.1.0",
|
"version": "5.0.0",
|
||||||
"description": "Update your discord status with the newly added rich presence.",
|
"description": "Update your discord status with the newly added rich presence.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"author": {
|
"author": {
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "npm run lint",
|
"prebuild": "npm run lint",
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
"tsc": "tsc",
|
|
||||||
"lint": "eslint src --ext .ts",
|
"lint": "eslint src --ext .ts",
|
||||||
"lint:fix": "eslint src --ext .ts --fix"
|
"lint:fix": "eslint src --ext .ts --fix"
|
||||||
},
|
},
|
||||||
|
@ -34,42 +33,22 @@
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"command": "discord.enable",
|
"command": "discord.enable",
|
||||||
"title": "Enable Discord Presence in the Current Workspace",
|
"title": "Enable Discord Presence in the current workspace",
|
||||||
"category": "Discord Presence"
|
"category": "Discord Presence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "discord.disable",
|
"command": "discord.disable",
|
||||||
"title": "Disable Discord Presence in the Current Workspace",
|
"title": "Disable Discord Presence in the current workspace",
|
||||||
"category": "Discord Presence"
|
"category": "Discord Presence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "discord.reconnect",
|
"command": "discord.reconnect",
|
||||||
"title": "Reconnect Discord Presence to Discord RPC",
|
"title": "Reconnect Discord Presence to Discord",
|
||||||
"category": "Discord Presence"
|
"category": "Discord Presence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "discord.disconnect",
|
"command": "discord.disconnect",
|
||||||
"title": "Disconnect Discord Presence from Discord RPC",
|
"title": "Disconnect Discord Presence from Discord",
|
||||||
"category": "Discord Presence"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"command": "discord.allowSpectate",
|
|
||||||
"title": "Allow Spectating",
|
|
||||||
"category": "Discord Presence"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"command": "discord.disableSpectate",
|
|
||||||
"title": "Disable Spectating",
|
|
||||||
"category": "Discord Presence"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"command": "discord.allowJoinRequests",
|
|
||||||
"title": "Allow Join Requests",
|
|
||||||
"category": "Discord Presence"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"command": "discord.disableJoinRequests",
|
|
||||||
"title": "Disable Join Requests",
|
|
||||||
"category": "Discord Presence"
|
"category": "Discord Presence"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -83,67 +62,67 @@
|
||||||
"default": true,
|
"default": true,
|
||||||
"description": "Controls if the Discord Presence should show across all workspaces"
|
"description": "Controls if the Discord Presence should show across all workspaces"
|
||||||
},
|
},
|
||||||
"discord.detailsEditing": {
|
"discord.details_idling": {
|
||||||
"type": "string",
|
|
||||||
"default": "Editing {filename}",
|
|
||||||
"description": "Custom string for the details section of the rich presence\n\t- '{null}' will be replaced with an empty space.\n\t- '{filename}' will be replaced with the current file name.\n\t- '{dirname}' will get replaced with the folder name that has the current file.\n\t- '{fulldirname}' will get replaced with the full directory name without the current file name.\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspaceFolder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspaceAndFolder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{currentcolumn}' will get replaced with the current column of the current line.\n\t- '{currentline}' will get replaced with the current line number.\n\t- '{totallines}' will get replaced with the total line number.\n\t- '{filesize}' will get replaced with the current file's size.\n\t- '{gitreponame}' will be replaced with the active Git repository name (from the git URL)\n\t- '{gitbranch}' will be replaced with the current active branch name."
|
|
||||||
},
|
|
||||||
"discord.detailsDebugging": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "Debugging {filename}",
|
|
||||||
"description": "Custom string for the details section of the rich presence when debugging\n\t- '{null}' will be replaced with an empty space.\n\t- '{filename}' will be replaced with the current file name.\n\t- '{dirname}' will get replaced with the folder name that has the current file.\n\t- '{fulldirname}' will get replaced with the full directory name without the current file name.\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspaceFolder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspaceAndFolder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{currentcolumn}' will get replaced with the current column of the current line.\n\t- '{currentline}' will get replaced with the current line number.\n\t- '{totallines}' will get replaced with the total line number.\n\t- '{filesize}' will get replaced with the current file's size.\n\t- '{gitreponame}' will be replaced with the active Git repository name (from the git URL)\n\t- '{gitbranch}' will be replaced with the current active branch name."
|
|
||||||
},
|
|
||||||
"discord.detailsIdle": {
|
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "Idling",
|
"default": "Idling",
|
||||||
"description": "Custom string for the details section of the rich presence when idling\n\t- '{null}' will be replaced with an empty space."
|
"description": "Custom string for the details section of the rich presence when idling\n\t- '{empty}' will be replaced with an empty space."
|
||||||
},
|
},
|
||||||
"discord.lowerDetailsEditing": {
|
"discord.details_editing": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "Editing {file_name}",
|
||||||
|
"description": "Custom string for the details section of the rich presence\n\t- '{empty}' will be replaced with an empty space.\n\t- '{file_name}' will be replaced with the current file name.\n\t- '{dir_name}' will get replaced with the folder name that has the current file.\n\t- '{full_dir_name}' will get replaced with the full directory name without the current file name.\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspace_folder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspace_and_folder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{current_column}' will get replaced with the current column of the current line.\n\t- '{current_line}' will get replaced with the current line number.\n\t- '{total_lines}' will get replaced with the total line number.\n\t- '{file_size}' will get replaced with the current file's size.\n\t- '{git_repo_name}' will be replaced with the active Git repository name (from the git URL)\n\t- '{git_branch}' will be replaced with the current active branch name."
|
||||||
|
},
|
||||||
|
"discord.details_debugging": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "Debugging {file_name}",
|
||||||
|
"description": "Custom string for the details section of the rich presence when debugging\n\t- '{empty}' will be replaced with an empty space.\n\t- '{file_name}' will be replaced with the current file name.\n\t- '{dir_name}' will get replaced with the folder name that has the current file.\n\t- '{full_dir_name}' will get replaced with the full directory name without the current file name.\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspace_folder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspace_and_folder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{current_column}' will get replaced with the current column of the current line.\n\t- '{current_line}' will get replaced with the current line number.\n\t- '{total_lines}' will get replaced with the total line number.\n\t- '{file_size}' will get replaced with the current file's size.\n\t- '{git_repo_name}' will be replaced with the active Git repository name (from the git URL)\n\t- '{git_branch}' will be replaced with the current active branch name."
|
||||||
|
},
|
||||||
|
"discord.lower_details_idling": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "Idling",
|
||||||
|
"description": "Custom string for the state section of the rich presence when idling\n\t- '{empty}' will be replaced with an empty space."
|
||||||
|
},
|
||||||
|
"discord.lower_details_editing": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "Workspace: {workspace}",
|
"default": "Workspace: {workspace}",
|
||||||
"description": "Custom string for the state section of the rich presence\n\t- '{null}' will be replaced with an empty space.\n\t- '{filename}' will be replaced with the current file name.\n\t- '{dirname}' will get replaced with the folder name that has the current file.\n\t- '{fulldirname}' will get replaced with the full directory name without the current file name.\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspaceFolder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspaceAndFolder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{currentcolumn}' will get replaced with the current column of the current line.\n\t- '{currentline}' will get replaced with the current line number.\n\t- '{totallines}' will get replaced with the total line number.\n\t- '{filesize}' will get replaced with the current file's size.\n\t- '{gitreponame}' will be replaced with the active Git repository name (from the git URL)\n\t- '{gitbranch}' will be replaced with the current active branch name."
|
"description": "Custom string for the state section of the rich presence\n\t- '{empty}' will be replaced with an empty space.\n\t- '{file_name}' will be replaced with the current file name.\n\t- '{dir_name}' will get replaced with the folder name that has the current file.\n\t- '{full_dir_name}' will get replaced with the full directory name without the current file name.\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspace_folder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspace_and_folder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{current_column}' will get replaced with the current column of the current line.\n\t- '{current_line}' will get replaced with the current line number.\n\t- '{total_lines}' will get replaced with the total line number.\n\t- '{file_size}' will get replaced with the current file's size.\n\t- '{git_repo_name}' will be replaced with the active Git repository name (from the git URL)\n\t- '{git_branch}' will be replaced with the current active branch name."
|
||||||
},
|
},
|
||||||
"discord.lowerDetailsDebugging": {
|
"discord.lower_details_debugging": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "Debugging: {workspace}",
|
"default": "Debugging: {workspace}",
|
||||||
"description": "Custom string for the state section of the rich presence when debugging\n\t- '{null}' will be replaced with an empty space.\n\t- '{filename}' will be replaced with the current file name.\n\t- '{dirname}' will get replaced with the folder name that has the current file.\n\t- '{fulldirname}' will get replaced with the full directory name without the current file name..\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspaceFolder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspaceAndFolder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{currentcolumn}' will get replaced with the current column of the current line.\n\t- '{currentline}' will get replaced with the current line number.\n\t- '{totallines}' will get replaced with the total line number.\n\t- '{filesize}' will get replaced with the current file's size.\n\t- '{gitreponame}' will be replaced with the active Git repository name (from the git URL)\n\t- '{gitbranch}' will be replaced with the current active branch name."
|
"description": "Custom string for the state section of the rich presence when debugging\n\t- '{empty}' will be replaced with an empty space.\n\t- '{file_name}' will be replaced with the current file name.\n\t- '{dir_name}' will get replaced with the folder name that has the current file.\n\t- '{full_dir_name}' will get replaced with the full directory name without the current file name.\n\t- '{workspace}' will be replaced with the current workspace name, if any.\n\t- '{workspace_folder}' will be replaced with the currently accessed workspace folder, if any.\n\t- '{workspace_and_folder} will be replaced with the currently accessed workspace and workspace folder like this: 'Workspace - WorkspaceFolder'\n\t- '{current_column}' will get replaced with the current column of the current line.\n\t- '{current_line}' will get replaced with the current line number.\n\t- '{total_lines}' will get replaced with the total line number.\n\t- '{file_size}' will get replaced with the current file's size.\n\t- '{git_repo_name}' will be replaced with the active Git repository name (from the git URL)\n\t- '{git_branch}' will be replaced with the current active branch name."
|
||||||
},
|
},
|
||||||
"discord.lowerDetailsIdle": {
|
"discord.lower_details_no_workspace_found": {
|
||||||
"type": "string",
|
|
||||||
"default": "Idling",
|
|
||||||
"description": "Custom string for the state section of the rich presence when idling\n\t- '{null}' will be replaced with an empty space."
|
|
||||||
},
|
|
||||||
"discord.lowerDetailsNotFound": {
|
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "No workspace.",
|
"default": "No workspace.",
|
||||||
"description": "Custom string for the state section of the rich presence when no workspace is found.\nIf set to '{null}', this will be an empty space.\n\t- '{currentline}' will get replaced with the current line number.\n\t- '{totallines}' will get replaced with the total line number.\n\t- '{filesize}' will get replaced with the current file's size."
|
"description": "Custom string for the state section of the rich presence when no workspace is found.\nIf set to '{empty}', this will be an empty space.\n\t- '{current_line}' will get replaced with the current line number.\n\t- '{total_lines}' will get replaced with the total line number.\n\t- '{file_size}' will get replaced with the current file's size."
|
||||||
},
|
},
|
||||||
"discord.largeImage": {
|
"discord.large_image_idling": {
|
||||||
"type": "string",
|
|
||||||
"default": "Editing a {LANG} file",
|
|
||||||
"description": "Custom string for the largeImageText section of the rich presence.\n\t- '{lang}' will be replaced with the lowercased language ID\n\t- '{LANG}' will be replaced with the uppercased language ID"
|
|
||||||
},
|
|
||||||
"discord.largeImageIdle": {
|
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "Idling",
|
"default": "Idling",
|
||||||
"description": "Custom string for the largeImageText section of the rich presence when idling"
|
"description": "Custom string for the largeImageText section of the rich presence when idling"
|
||||||
},
|
},
|
||||||
"discord.smallImage": {
|
"discord.large_image": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "{appname}",
|
"default": "Editing a {LANG} file",
|
||||||
"description": "Custom string for the smallImageText section of the rich presence\n\t- '{appname}' will get replaced with the current Visual Studio Code version."
|
"description": "Custom string for the largeImageText section of the rich presence.\n\t- '{lang}' will be replaced with the lowercased language ID\n\t- '{LANG}' will be replaced with the uppercased language ID"
|
||||||
},
|
},
|
||||||
"discord.silent": {
|
"discord.small_image": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "{app_name}",
|
||||||
|
"description": "Custom string for the smallImageText section of the rich presence\n\t- '{app_name}' will get replaced with the current Visual Studio Code version."
|
||||||
|
},
|
||||||
|
"discord.suppress_notifications": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"description": "Decides if error messages are shown to the user"
|
"description": "Decides if error messages are shown to the user"
|
||||||
},
|
},
|
||||||
"discord.workspaceElapsedTime": {
|
"discord.workspace_elapsed_time": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": true,
|
||||||
"description": "Decides whether to display elapsed time for a workspace or a single file"
|
"description": "Decides whether to display elapsed time for a workspace or a single file"
|
||||||
},
|
},
|
||||||
"discord.workspaceExcludePatterns": {
|
"discord.workspace_exclude_patterns": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -181,10 +160,10 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bufferutil": "^4.0.3",
|
"bufferutil": "^4.0.3",
|
||||||
|
"dayjs": "^1.10.4",
|
||||||
"discord-rpc": "github:discordjs/RPC",
|
"discord-rpc": "github:discordjs/RPC",
|
||||||
"tslib": "^2.1.0",
|
"tslib": "^2.1.0",
|
||||||
"utf-8-validate": "^5.0.4",
|
"utf-8-validate": "^5.0.4"
|
||||||
"vsls": "^1.0.3015"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^14.14.25",
|
"@types/node": "^14.14.25",
|
||||||
|
@ -193,7 +172,7 @@
|
||||||
"@typescript-eslint/parser": "^4.15.0",
|
"@typescript-eslint/parser": "^4.15.0",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"eslint": "^7.19.0",
|
"eslint": "^7.19.0",
|
||||||
"eslint-config-marine": "^7.2.0",
|
"eslint-config-marine": "^8.1.0",
|
||||||
"eslint-config-prettier": "^7.2.0",
|
"eslint-config-prettier": "^7.2.0",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
|
@ -204,6 +183,6 @@
|
||||||
"webpack-cli": "^4.5.0"
|
"webpack-cli": "^4.5.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.51.0"
|
"vscode": "^1.53.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
193
src/activity.ts
Normal file
193
src/activity.ts
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
import { basename, parse, sep } from 'path';
|
||||||
|
import { debug, env, extensions, Selection, TextDocument, window, workspace } from 'vscode';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CONFIG_KEYS,
|
||||||
|
DEBUG_IMAGE_KEY,
|
||||||
|
EMPTY,
|
||||||
|
FILE_SIZES,
|
||||||
|
IDLE_IMAGE_KEY,
|
||||||
|
REPLACE_KEYS,
|
||||||
|
VSCODE_IMAGE_KEY,
|
||||||
|
VSCODE_INSIDERS_IMAGE_KEY,
|
||||||
|
} from './constants';
|
||||||
|
import { GitExtension } from './git';
|
||||||
|
import { log, LogLevel } from './logger';
|
||||||
|
import { getConfig, resolveFileIcon, toLower, toTitle, toUpper } from './util';
|
||||||
|
|
||||||
|
interface ActivityPayload {
|
||||||
|
details: string;
|
||||||
|
state?: string;
|
||||||
|
startTimestamp?: number | null;
|
||||||
|
largeImageKey?: string;
|
||||||
|
largeImageText?: string;
|
||||||
|
smallImageKey?: string;
|
||||||
|
smallImageText?: string;
|
||||||
|
partyId?: string;
|
||||||
|
partySize?: number;
|
||||||
|
partyMax?: number;
|
||||||
|
matchSecret?: string;
|
||||||
|
joinSecret?: string;
|
||||||
|
spectateSecret?: string;
|
||||||
|
instance?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function activity() {
|
||||||
|
const config = getConfig();
|
||||||
|
|
||||||
|
const appName = env.appName;
|
||||||
|
const defaultSmallImageKey = debug.activeDebugSession
|
||||||
|
? DEBUG_IMAGE_KEY
|
||||||
|
: appName.includes('Insiders')
|
||||||
|
? VSCODE_INSIDERS_IMAGE_KEY
|
||||||
|
: VSCODE_IMAGE_KEY;
|
||||||
|
|
||||||
|
let state: ActivityPayload = {
|
||||||
|
details: await details(CONFIG_KEYS.DetailsIdling, CONFIG_KEYS.DetailsEditing, CONFIG_KEYS.DetailsDebugging),
|
||||||
|
state: await details(
|
||||||
|
CONFIG_KEYS.LowerDetailsIdling,
|
||||||
|
CONFIG_KEYS.LowerDetailsEditing,
|
||||||
|
CONFIG_KEYS.LowerDetailsDebugging,
|
||||||
|
),
|
||||||
|
startTimestamp: null,
|
||||||
|
largeImageKey: IDLE_IMAGE_KEY,
|
||||||
|
largeImageText: config[CONFIG_KEYS.LargeImageIdling],
|
||||||
|
smallImageKey: defaultSmallImageKey,
|
||||||
|
smallImageText: config[CONFIG_KEYS.SmallImage].replace(REPLACE_KEYS.AppName, appName),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (window.activeTextEditor) {
|
||||||
|
const largeImageKey = resolveFileIcon(window.activeTextEditor.document);
|
||||||
|
const largeImageText = config[CONFIG_KEYS.LargeImage]
|
||||||
|
.replace(REPLACE_KEYS.LanguageLowerCase, toLower(largeImageKey))
|
||||||
|
.replace(REPLACE_KEYS.LanguageTitleCase, toTitle(largeImageKey))
|
||||||
|
.replace(REPLACE_KEYS.LanguageUpperCase, toUpper(largeImageKey))
|
||||||
|
.padEnd(2, EMPTY);
|
||||||
|
|
||||||
|
state = {
|
||||||
|
...state,
|
||||||
|
details: await details(CONFIG_KEYS.DetailsIdling, CONFIG_KEYS.DetailsEditing, CONFIG_KEYS.DetailsDebugging),
|
||||||
|
state: await details(
|
||||||
|
CONFIG_KEYS.LowerDetailsIdling,
|
||||||
|
CONFIG_KEYS.LowerDetailsEditing,
|
||||||
|
CONFIG_KEYS.LowerDetailsDebugging,
|
||||||
|
),
|
||||||
|
largeImageKey,
|
||||||
|
largeImageText,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
log(LogLevel.Debug, JSON.stringify(state, null, 2));
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function details(idling: CONFIG_KEYS, editing: CONFIG_KEYS, debugging: CONFIG_KEYS) {
|
||||||
|
const config = getConfig();
|
||||||
|
let raw = (config[idling] as string).replace(REPLACE_KEYS.Empty, EMPTY);
|
||||||
|
|
||||||
|
if (window.activeTextEditor) {
|
||||||
|
const fileName = basename(window.activeTextEditor.document.fileName);
|
||||||
|
const { dir } = parse(window.activeTextEditor.document.fileName);
|
||||||
|
const split = dir.split(sep);
|
||||||
|
const dirName = split[split.length - 1];
|
||||||
|
|
||||||
|
const noWorkspaceFound = config[CONFIG_KEYS.LowerDetailsNoWorkspaceFound].replace(REPLACE_KEYS.Empty, EMPTY);
|
||||||
|
const workspaceFolder = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri);
|
||||||
|
const workspaceFolderName = workspaceFolder?.name ?? noWorkspaceFound;
|
||||||
|
const workspaceName = workspace.name ?? workspaceFolderName;
|
||||||
|
const workspaceAndFolder = `${workspaceName}${workspaceFolderName === EMPTY ? '' : ` - ${workspaceFolderName}`}`;
|
||||||
|
|
||||||
|
const fileIcon = resolveFileIcon(window.activeTextEditor.document);
|
||||||
|
|
||||||
|
if (debug.activeDebugSession) {
|
||||||
|
raw = config[debugging] as string;
|
||||||
|
} else {
|
||||||
|
raw = config[editing] as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workspaceFolder) {
|
||||||
|
const { name } = workspaceFolder;
|
||||||
|
const relativePath = workspace.asRelativePath(window.activeTextEditor.document.fileName).split(sep);
|
||||||
|
relativePath.splice(-1, 1);
|
||||||
|
raw = raw.replace(REPLACE_KEYS.FullDirName, `${name}${sep}${relativePath.join(sep)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
raw = await fileDetails(raw, window.activeTextEditor.document, window.activeTextEditor.selection);
|
||||||
|
raw = raw
|
||||||
|
.replace(REPLACE_KEYS.FileName, fileName)
|
||||||
|
.replace(REPLACE_KEYS.DirName, dirName)
|
||||||
|
.replace(REPLACE_KEYS.Workspace, workspaceName)
|
||||||
|
.replace(REPLACE_KEYS.WorkspaceFolder, workspaceFolderName)
|
||||||
|
.replace(REPLACE_KEYS.WorkspaceAndFolder, workspaceAndFolder)
|
||||||
|
.replace(REPLACE_KEYS.LanguageLowerCase, toLower(fileIcon))
|
||||||
|
.replace(REPLACE_KEYS.LanguageTitleCase, toTitle(fileIcon))
|
||||||
|
.replace(REPLACE_KEYS.LanguageUpperCase, toUpper(fileIcon));
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fileDetails(_raw: string, document: TextDocument, selection: Selection) {
|
||||||
|
let raw = _raw.slice();
|
||||||
|
const gitExtension = extensions.getExtension<GitExtension>('vscode.git');
|
||||||
|
const git = gitExtension?.exports.getAPI(1);
|
||||||
|
|
||||||
|
if (raw.includes(REPLACE_KEYS.TotalLines)) {
|
||||||
|
raw = raw.replace(REPLACE_KEYS.TotalLines, document.toLocaleString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw.includes(REPLACE_KEYS.CurrentLine)) {
|
||||||
|
raw = raw.replace(REPLACE_KEYS.CurrentLine, (selection.active.line + 1).toLocaleString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw.includes(REPLACE_KEYS.CurrentColumn)) {
|
||||||
|
raw = raw.replace(REPLACE_KEYS.CurrentColumn, (selection.active.character + 1).toLocaleString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw.includes(REPLACE_KEYS.FileSize)) {
|
||||||
|
let currentDivision = 0;
|
||||||
|
let { size } = await workspace.fs.stat(document.uri);
|
||||||
|
const originalSize = size;
|
||||||
|
if (originalSize > 1000) {
|
||||||
|
size /= 1000;
|
||||||
|
currentDivision++;
|
||||||
|
while (size > 1000) {
|
||||||
|
currentDivision++;
|
||||||
|
size /= 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
raw = raw.replace(
|
||||||
|
REPLACE_KEYS.FileSize,
|
||||||
|
`${originalSize > 1000 ? size.toFixed(2) : size}${FILE_SIZES[currentDivision]}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw.includes(REPLACE_KEYS.GitBranch)) {
|
||||||
|
if (git?.repositories.length) {
|
||||||
|
raw = raw.replace(
|
||||||
|
REPLACE_KEYS.GitBranch,
|
||||||
|
git.repositories.find((repo) => repo.ui.selected)?.state.HEAD?.name ?? EMPTY,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
raw = raw.replace(REPLACE_KEYS.GitBranch, 'Unknown');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw.includes(REPLACE_KEYS.GitRepoName)) {
|
||||||
|
if (git?.repositories.length) {
|
||||||
|
raw = raw.replace(
|
||||||
|
REPLACE_KEYS.GitRepoName,
|
||||||
|
git.repositories
|
||||||
|
.find((repo) => repo.ui.selected)
|
||||||
|
?.state.remotes[0].fetchUrl?.split('/')[1]
|
||||||
|
.replace('.git', '') ?? EMPTY,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
raw = raw.replace(REPLACE_KEYS.GitRepoName, 'Unknown');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw;
|
||||||
|
}
|
|
@ -1,172 +0,0 @@
|
||||||
const { Client } = require('discord-rpc'); // eslint-disable-line
|
|
||||||
import { Disposable, StatusBarItem, Uri, window, workspace, env } from 'vscode';
|
|
||||||
import * as vsls from 'vsls';
|
|
||||||
import Activity from '../structures/Activity';
|
|
||||||
import Logger from '../structures/Logger';
|
|
||||||
import { API } from '../git';
|
|
||||||
|
|
||||||
let activityTimer: NodeJS.Timer | undefined;
|
|
||||||
|
|
||||||
export default class RPCClient implements Disposable {
|
|
||||||
public config = workspace.getConfiguration('discord');
|
|
||||||
|
|
||||||
public git?: API;
|
|
||||||
|
|
||||||
private rpc: any;
|
|
||||||
|
|
||||||
private readonly activity = new Activity(this);
|
|
||||||
|
|
||||||
public constructor(private readonly clientId: string, public statusBarIcon: StatusBarItem) {}
|
|
||||||
|
|
||||||
public get client() {
|
|
||||||
return this.rpc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async setActivity(workspaceElapsedTime = false) {
|
|
||||||
if (!this.rpc) return;
|
|
||||||
const activity = await this.activity.generate(workspaceElapsedTime);
|
|
||||||
if (!activity) return;
|
|
||||||
Logger.log('Sending activity to Discord.');
|
|
||||||
this.rpc.setActivity(activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public allowSpectate() {
|
|
||||||
if (!this.rpc) return;
|
|
||||||
Logger.log('Allowed spectating.');
|
|
||||||
Logger.log('Sending spectate activity to Discord.');
|
|
||||||
void this.activity.allowSpectate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public disableSpectate() {
|
|
||||||
if (!this.rpc) return;
|
|
||||||
Logger.log('Disabled spectating.');
|
|
||||||
void this.activity.disableSpectate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public allowJoinRequests() {
|
|
||||||
if (!this.rpc) return;
|
|
||||||
Logger.log('Allowed join requests.');
|
|
||||||
Logger.log('Sending join activity to Discord.');
|
|
||||||
void this.activity.allowJoinRequests();
|
|
||||||
}
|
|
||||||
|
|
||||||
public disableJoinRequests() {
|
|
||||||
if (!this.rpc) return;
|
|
||||||
Logger.log('Disabled join requests.');
|
|
||||||
void this.activity.disableJoinRequests();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async login() {
|
|
||||||
if (this.rpc) {
|
|
||||||
this.dispose();
|
|
||||||
}
|
|
||||||
this.rpc = new Client({ transport: 'ipc' });
|
|
||||||
|
|
||||||
Logger.log('Logging into RPC...');
|
|
||||||
|
|
||||||
this.rpc.transport.once('close', () => {
|
|
||||||
if (!this.config.get<boolean>('enabled')) return;
|
|
||||||
void this.dispose();
|
|
||||||
this.statusBarIcon.text = '$(plug) Reconnect to Discord';
|
|
||||||
this.statusBarIcon.command = 'discord.reconnect';
|
|
||||||
this.statusBarIcon.tooltip = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
this.rpc.once('ready', async () => {
|
|
||||||
Logger.log('Successfully connected to Discord.');
|
|
||||||
|
|
||||||
this.statusBarIcon.text = '$(globe) Connected to Discord';
|
|
||||||
this.statusBarIcon.tooltip = 'Connected to Discord';
|
|
||||||
|
|
||||||
setTimeout(() => (this.statusBarIcon.text = '$(globe)'), 5000);
|
|
||||||
|
|
||||||
if (activityTimer) clearInterval(activityTimer);
|
|
||||||
void this.setActivity(this.config.get<boolean>('workspaceElapsedTime'));
|
|
||||||
|
|
||||||
activityTimer = setInterval(() => {
|
|
||||||
this.config = workspace.getConfiguration('discord');
|
|
||||||
void this.setActivity(this.config.get<boolean>('workspaceElapsedTime'));
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
this.rpc.subscribe('ACTIVITY_SPECTATE', async ({ secret }: { secret: string }) => {
|
|
||||||
const liveshare = await vsls.getApi();
|
|
||||||
if (!liveshare) return;
|
|
||||||
try {
|
|
||||||
const s = Buffer.from(secret, 'base64').toString();
|
|
||||||
// You might be asking yourself: "but why?"
|
|
||||||
// VS Liveshare has this annoying bug where you convert a URL string to a URI object to autofill
|
|
||||||
// But the autofill will be empty, so to circumvent this I need to add copying the link to the clipboard
|
|
||||||
// And immediately pasting it after the window pops up empty
|
|
||||||
await env.clipboard.writeText(s);
|
|
||||||
const uriString = await env.clipboard.readText();
|
|
||||||
const uri = Uri.parse(uriString);
|
|
||||||
await liveshare.join(uri);
|
|
||||||
} catch (error) {
|
|
||||||
Logger.log(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// You might be asking yourself again: "but why?"
|
|
||||||
// Same here, this is a real nasty race condition that happens inside the discord-rpc module currently
|
|
||||||
// To circumvent this we need to timeout sending the subscribe events to the discord client
|
|
||||||
setTimeout(() => {
|
|
||||||
this.rpc.subscribe(
|
|
||||||
'ACTIVITY_JOIN_REQUEST',
|
|
||||||
async ({ user }: { user: { username: string; discriminator: string } }) => {
|
|
||||||
const val = await window.showInformationMessage(
|
|
||||||
`${user.username}#${user.discriminator} wants to join your session`,
|
|
||||||
{ title: 'Accept' },
|
|
||||||
{ title: 'Decline' },
|
|
||||||
);
|
|
||||||
if (val && val.title === 'Accept') await this.rpc.sendJoinInvite(user);
|
|
||||||
else await this.rpc.closeJoinRequest(user);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}, 1000);
|
|
||||||
setTimeout(() => {
|
|
||||||
this.rpc.subscribe('ACTIVITY_JOIN', async ({ secret }: { secret: string }) => {
|
|
||||||
const liveshare = await vsls.getApi();
|
|
||||||
if (!liveshare) return;
|
|
||||||
try {
|
|
||||||
const s = Buffer.from(secret, 'base64').toString();
|
|
||||||
// You might be asking yourself again again: "but why?"
|
|
||||||
// See first comment above
|
|
||||||
await env.clipboard.writeText(s);
|
|
||||||
const uriString = await env.clipboard.readText();
|
|
||||||
const uri = Uri.parse(uriString);
|
|
||||||
await liveshare.join(uri);
|
|
||||||
} catch (error) {
|
|
||||||
Logger.log(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
const liveshare = await vsls.getApi();
|
|
||||||
if (!liveshare) return;
|
|
||||||
|
|
||||||
liveshare.onDidChangeSession(({ session }) => {
|
|
||||||
if (session.id) return this.activity.changePartyId(session.id);
|
|
||||||
return this.activity.changePartyId();
|
|
||||||
});
|
|
||||||
liveshare.onDidChangePeers(({ added, removed }) => {
|
|
||||||
if (added.length) return this.activity.increasePartySize(added.length);
|
|
||||||
else if (removed.length) return this.activity.decreasePartySize(removed.length);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.rpc.login({ clientId: this.clientId });
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public dispose() {
|
|
||||||
this.activity.dispose();
|
|
||||||
if (this.rpc) this.rpc.destroy();
|
|
||||||
this.rpc = null;
|
|
||||||
this.statusBarIcon.tooltip = '';
|
|
||||||
|
|
||||||
if (activityTimer) clearInterval(activityTimer);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,51 @@
|
||||||
export const LIVE_SHARE_BASE_URL = 'insiders.liveshare.vsengsaas.visualstudio.com';
|
import LANG from './data/languages.json';
|
||||||
export const VSLS_EXTENSION_ID = 'ms-vsliveshare.vsliveshare';
|
|
||||||
|
|
||||||
export const LIVE_SHARE_COMMANDS = {
|
export const CLIENT_ID = '383226320970055681' as const;
|
||||||
Start: 'liveshare.start',
|
|
||||||
End: 'liveshare.end',
|
export const KNOWN_EXTENSIONS: { [key: string]: { image: string } } = LANG.KNOWN_EXTENSIONS;
|
||||||
Join: 'liveshare.join',
|
export const KNOWN_LANGUAGES: { language: string; image: string }[] = LANG.KNOWN_LANGUAGES;
|
||||||
};
|
|
||||||
|
export const EMPTY = '\u200b\u200b';
|
||||||
|
export const FILE_SIZES = [' bytes', 'kb', 'mb', 'gb', 'tb'];
|
||||||
|
|
||||||
|
export const IDLE_IMAGE_KEY = 'vscode-big';
|
||||||
|
export const DEBUG_IMAGE_KEY = 'debug';
|
||||||
|
export const VSCODE_IMAGE_KEY = 'vscode';
|
||||||
|
export const VSCODE_INSIDERS_IMAGE_KEY = 'vscode-insiders';
|
||||||
|
|
||||||
|
export const enum REPLACE_KEYS {
|
||||||
|
Empty = '{empty}',
|
||||||
|
FileName = '{file_name}',
|
||||||
|
DirName = '{dir_name}',
|
||||||
|
FullDirName = '{full_dir_name}',
|
||||||
|
Workspace = '{workspace}',
|
||||||
|
WorkspaceFolder = '{workspace_folder}',
|
||||||
|
WorkspaceAndFolder = '{workspace_and_folder}',
|
||||||
|
LanguageLowerCase = '{lang}',
|
||||||
|
LanguageTitleCase = '{Lang}',
|
||||||
|
LanguageUpperCase = '{LANG}',
|
||||||
|
TotalLines = '{total_lines}',
|
||||||
|
CurrentLine = '{current_line}',
|
||||||
|
CurrentColumn = '{current_column}',
|
||||||
|
FileSize = '{file_size}',
|
||||||
|
AppName = '{app_name}',
|
||||||
|
GitRepoName = '{git_repo_name}',
|
||||||
|
GitBranch = '{git_branch}',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum CONFIG_KEYS {
|
||||||
|
Enabled = 'enabled',
|
||||||
|
DetailsIdling = 'details_idling',
|
||||||
|
DetailsEditing = 'details_editing',
|
||||||
|
DetailsDebugging = 'details_debugging',
|
||||||
|
LowerDetailsIdling = 'lower_details_idling',
|
||||||
|
LowerDetailsEditing = 'lower_details_editing',
|
||||||
|
LowerDetailsDebugging = 'lower_details_debugging',
|
||||||
|
LowerDetailsNoWorkspaceFound = 'lower_details_no_workspace_found',
|
||||||
|
LargeImageIdling = 'large_image_idling',
|
||||||
|
LargeImage = 'large_image',
|
||||||
|
SmallImage = 'small_image',
|
||||||
|
SuppressNotifications = 'suppress_notifications',
|
||||||
|
WorkspaceElapsedTime = 'workspace_elapsed_time',
|
||||||
|
WorkspaceExcludePatterns = 'workspace_exclude_patterns',
|
||||||
|
}
|
||||||
|
|
|
@ -1,520 +1,445 @@
|
||||||
{
|
{
|
||||||
"knownLanguages": [
|
"KNOWN_LANGUAGES": [
|
||||||
"ahk",
|
{ "language": "abap", "image": "text" },
|
||||||
"android",
|
{ "language": "bat", "image": "bat" },
|
||||||
"angular",
|
{ "language": "bibtex", "image": "text" },
|
||||||
"applescript",
|
{ "language": "clojure", "image": "clojure" },
|
||||||
"appveyor",
|
{ "language": "coffeescript", "image": "coffeescript" },
|
||||||
"arduino",
|
{ "language": "c", "image": "c" },
|
||||||
"as",
|
{ "language": "cpp", "image": "cpp" },
|
||||||
"asp",
|
{ "language": "csharp", "image": "csharp" },
|
||||||
"assembly",
|
{ "language": "css", "image": "css" },
|
||||||
"autoit",
|
{ "language": "diff", "image": "manifest" },
|
||||||
"babel",
|
{ "language": "dockerfile", "image": "docker" },
|
||||||
"bat",
|
{ "language": "fsharp", "image": "fsharp" },
|
||||||
"bower",
|
{ "language": "git-commit", "image": "manifest" },
|
||||||
"brainfuck",
|
{ "language": "git-rebase", "image": "manifest" },
|
||||||
"c",
|
{ "language": "go", "image": "go" },
|
||||||
"cargo",
|
{ "language": "groovy", "image": "groovy" },
|
||||||
"cfml",
|
{ "language": "handlebars", "image": "handlebars" },
|
||||||
"circleci",
|
{ "language": "haml", "image": "text" },
|
||||||
"clojure",
|
{ "language": "html", "image": "html" },
|
||||||
"cmake",
|
{ "language": "ini", "image": "manifest" },
|
||||||
"codeclimate",
|
{ "language": "java", "image": "java" },
|
||||||
"coffee",
|
{ "language": "javascript", "image": "javascript" },
|
||||||
"cpp",
|
{ "language": "javascriptreact", "image": "jsx" },
|
||||||
"crystal",
|
{ "language": "jsx", "image": "jsx" },
|
||||||
"csharp",
|
{ "language": "json", "image": "json" },
|
||||||
"cshtml",
|
{ "language": "jsonc", "image": "json" },
|
||||||
"css",
|
{ "language": "latex", "image": "text" },
|
||||||
"cuda",
|
{ "language": "less", "image": "less" },
|
||||||
"d",
|
{ "language": "lua", "image": "lua" },
|
||||||
"dart",
|
{ "language": "makefile", "image": "makefile" },
|
||||||
"delphi",
|
{ "language": "markdown", "image": "markdown" },
|
||||||
"denizen",
|
{ "language": "objective-c", "image": "objective-c" },
|
||||||
"dm",
|
{ "language": "objective-cpp", "image": "objective-c" },
|
||||||
"docker",
|
{ "language": "perl", "image": "perl" },
|
||||||
"editorconfig",
|
{ "language": "perl6", "image": "perl" },
|
||||||
"ejs",
|
{ "language": "php", "image": "php" },
|
||||||
"elixir",
|
{ "language": "plaintext", "image": "text" },
|
||||||
"elm",
|
{ "language": "powershell", "image": "powershell" },
|
||||||
"env",
|
{ "language": "jade", "image": "pug" },
|
||||||
"erlang",
|
{ "language": "pug", "image": "pug" },
|
||||||
"eslint",
|
{ "language": "python", "image": "python" },
|
||||||
"flowconfig",
|
{ "language": "r", "image": "r" },
|
||||||
"fsharp",
|
{ "language": "razor", "image": "cshtml" },
|
||||||
"gemfile",
|
{ "language": "ruby", "image": "ruby" },
|
||||||
"git",
|
{ "language": "rust", "image": "rust" },
|
||||||
"go",
|
{ "language": "scss", "image": "scss" },
|
||||||
"godot",
|
{ "language": "sass", "image": "scss" },
|
||||||
"gradle",
|
{ "language": "shaderlab", "image": "manifest" },
|
||||||
"graphql",
|
{ "language": "slim", "image": "text" },
|
||||||
"groovy",
|
{ "language": "sql", "image": "sql" },
|
||||||
"gruntfile",
|
{ "language": "stylus", "image": "stylus" },
|
||||||
"gulp",
|
{ "language": "swift", "image": "swift" },
|
||||||
"handlebars",
|
{ "language": "typescript", "image": "typescript" },
|
||||||
"harbour",
|
{ "language": "typescriptreact", "image": "tsx" },
|
||||||
"haskell",
|
{ "language": "tex", "image": "tex" },
|
||||||
"haxe",
|
{ "language": "vb", "image": "vb" },
|
||||||
"heroku",
|
{ "language": "vue", "image": "vue" },
|
||||||
"hjson",
|
{ "language": "vue-html", "image": "vue" },
|
||||||
"html",
|
{ "language": "xml", "image": "xml" },
|
||||||
"http",
|
{ "language": "xsl", "image": "xml" },
|
||||||
"ini",
|
{ "language": "yaml", "image": "yaml" }
|
||||||
"jar",
|
],
|
||||||
"java",
|
"KNOWN_EXTENSIONS": {
|
||||||
"jest",
|
".ahk": { "image": "ahk" },
|
||||||
"jinja",
|
".ahkl": { "image": "ahk" },
|
||||||
"js",
|
"androidmanifest.xml": { "image": "android" },
|
||||||
"jsmap",
|
"/^angular[^.]*\\.js$/i": { "image": "angular" },
|
||||||
"json",
|
".applescript": { "image": "applescript" },
|
||||||
"jsx",
|
"/(\\.)?appveyor\\.yml/i": { "image": "appveyor" },
|
||||||
"julia",
|
".ino": { "image": "arduino" },
|
||||||
"jupyter",
|
".swf": { "image": "as" },
|
||||||
"kotlin",
|
".as": { "image": "as" },
|
||||||
"less",
|
".jsfl": { "image": "as" },
|
||||||
"lisp",
|
".swc": { "image": "as" },
|
||||||
"livescript",
|
".asp": { "image": "asp" },
|
||||||
"log",
|
".asax": { "image": "asp" },
|
||||||
"lua",
|
".ascx": { "image": "asp" },
|
||||||
"makefile",
|
".ashx": { "image": "asp" },
|
||||||
"manifest",
|
".asmx": { "image": "asp" },
|
||||||
"markdown",
|
".aspx": { "image": "asp" },
|
||||||
"markdownx",
|
".axd": { "image": "asp" },
|
||||||
"marko",
|
"/\\.(l?a|[ls]?o|out|s|a51|asm|axf|elf|prx|puff|z80)$/i": { "image": "assembly" },
|
||||||
"nim",
|
".agc": { "image": "assembly" },
|
||||||
"nix",
|
".ko": { "image": "assembly" },
|
||||||
"nodemon",
|
".lst": { "image": "assembly" },
|
||||||
"npm",
|
"/\\.((c([+px]{2}?)?-?)?objdump|bsdiff|bin|dat|pak|pdb)$/i": { "image": "assembly" },
|
||||||
"objc",
|
".d-objdump": { "image": "assembly" },
|
||||||
"ocaml",
|
"/\\.gcode|\\.gco/i": { "image": "assembly" },
|
||||||
"pascal",
|
"/\\.rpy[bc]$/i": { "image": "assembly" },
|
||||||
"pawn",
|
"/\\.py[co]$/i": { "image": "assembly" },
|
||||||
"perl",
|
".swp": { "image": "assembly" },
|
||||||
"php",
|
".DS_Store": { "image": "assembly" },
|
||||||
"ponylang",
|
".au3": { "image": "autoit" },
|
||||||
"postcss",
|
"babel.config.js": { "image": "babel" },
|
||||||
"powershell",
|
"/\\.babelrc/i": { "image": "babel" },
|
||||||
"prettier",
|
".bat": { "image": "bat" },
|
||||||
"prisma",
|
".batch": { "image": "bat" },
|
||||||
"processing",
|
".cmd": { "image": "bat" },
|
||||||
"pug",
|
"/\\.(exe|com|msi)$/i": { "image": "bat" },
|
||||||
"purescript",
|
".reg": { "image": "bat" },
|
||||||
"python",
|
"/^(\\.bowerrc|bower\\.json|Bowerfile)$/i": { "image": "bower" },
|
||||||
"r",
|
"/\\.bf?$/i": { "image": "brainfuck" },
|
||||||
"reasonml",
|
"/\\.c$/i": { "image": "c" },
|
||||||
"ruby",
|
"/(cargo.toml|cargo.lock)/i": { "image": "cargo" },
|
||||||
"rust",
|
".cfc": { "image": "cfml" },
|
||||||
"scala",
|
".cfm": { "image": "cfml" },
|
||||||
"scss",
|
"circle.yml": { "image": "circleci" },
|
||||||
"shell",
|
".clj": { "image": "clojure" },
|
||||||
"sqf",
|
".cl2": { "image": "clojure" },
|
||||||
"sql",
|
".cljc": { "image": "clojure" },
|
||||||
"stylus",
|
".cljx": { "image": "clojure" },
|
||||||
"svelte",
|
".hic": { "image": "clojure" },
|
||||||
"svg",
|
"/\\.cljs(cm)?$/i": { "image": "clojure" },
|
||||||
"swift",
|
".cmake": { "image": "cmake" },
|
||||||
"tex",
|
"/^CMakeLists\\.txt$/": { "image": "cmake" },
|
||||||
"text",
|
"/\\.codeclimate\\.(yml|json)/i": { "image": "codeclimate" },
|
||||||
"toml",
|
".coffee": { "image": "coffeescript" },
|
||||||
"travis",
|
".cjsx": { "image": "coffeescript" },
|
||||||
"ts",
|
".coffee.ecr": { "image": "coffeescript" },
|
||||||
"tsx",
|
".coffee.erb": { "image": "coffeescript" },
|
||||||
"twig",
|
".litcoffee": { "image": "coffeescript" },
|
||||||
"typescript-def",
|
".iced": { "image": "coffeescript" },
|
||||||
"v",
|
"/\\.c[+px]{2}$|\\.cc$/i": { "image": "cpp" },
|
||||||
"v",
|
"/\\.h[+px]{2}$/i": { "image": "cpp" },
|
||||||
"vala",
|
"/\\.[it]pp$/i": { "image": "cpp" },
|
||||||
"vb",
|
"/\\.(tcc|inl)$/i": { "image": "cpp" },
|
||||||
"vba",
|
".cats": { "image": "cpp" },
|
||||||
"vbhtml",
|
".idc": { "image": "cpp" },
|
||||||
"vbproj",
|
".w": { "image": "cpp" },
|
||||||
"vcxproj",
|
".nc": { "image": "cpp" },
|
||||||
"vscodeignore",
|
".upc": { "image": "cpp" },
|
||||||
"vue",
|
".xpm": { "image": "cpp" },
|
||||||
"wasm",
|
"/\\.e?cr$/i": { "image": "crystal" },
|
||||||
"webpack",
|
".cs": { "image": "csharp" },
|
||||||
"xml",
|
".csx": { "image": "csharp" },
|
||||||
"yaml",
|
".cshtml": { "image": "cshtml" },
|
||||||
"yarn",
|
".css": { "image": "css" },
|
||||||
"zig"
|
".css.map": { "image": "cssmap" },
|
||||||
],
|
".cu": { "image": "cuda" },
|
||||||
"knownExtensions": {
|
"/\\.di?$/i": { "image": "d" },
|
||||||
".ahk": { "image": "ahk" },
|
".dart": { "image": "dart" },
|
||||||
".ahkl": { "image": "ahk" },
|
".dfm": { "image": "delphi" },
|
||||||
"androidmanifest.xml": { "image": "android" },
|
".dpr": { "image": "delphi" },
|
||||||
"/^angular[^.]*\\.js$/i": { "image": "angular" },
|
".dsc": { "image": "denizen" },
|
||||||
".applescript": { "image": "applescript" },
|
".dm": { "image": "dm" },
|
||||||
"/(\\.)?appveyor\\.yml/i": { "image": "appveyor" },
|
".dme": { "image": "dm" },
|
||||||
".ino": { "image": "arduino" },
|
".dmm": { "image": "dm" },
|
||||||
".swf": { "image": "as" },
|
"/^(Dockerfile|docker-compose)|\\.docker(file|ignore)$/i": { "image": "docker" },
|
||||||
".as": { "image": "as" },
|
"/^docker-sync\\.yml$/i": { "image": "docker" },
|
||||||
".jsfl": { "image": "as" },
|
".editorconfig": { "image": "editorconfig" },
|
||||||
".swc": { "image": "as" },
|
".ejs": { "image": "ejs" },
|
||||||
".asp": { "image": "asp" },
|
".ex": { "image": "elixir" },
|
||||||
".asax": { "image": "asp" },
|
"/\\.(exs|l?eex)$/i": { "image": "elixir" },
|
||||||
".ascx": { "image": "asp" },
|
"/^mix\\.(exs?|lock)$/i": { "image": "elixir" },
|
||||||
".ashx": { "image": "asp" },
|
".elm": { "image": "elm" },
|
||||||
".asmx": { "image": "asp" },
|
".env": { "image": "env" },
|
||||||
".aspx": { "image": "asp" },
|
".erl": { "image": "erlang" },
|
||||||
".axd": { "image": "asp" },
|
".beam": { "image": "erlang" },
|
||||||
"/\\.(l?a|[ls]?o|out|s|a51|asm|axf|elf|prx|puff|z80)$/i": { "image": "assembly" },
|
".hrl": { "image": "erlang" },
|
||||||
".agc": { "image": "assembly" },
|
".xrl": { "image": "erlang" },
|
||||||
".ko": { "image": "assembly" },
|
".yrl": { "image": "erlang" },
|
||||||
".lst": { "image": "assembly" },
|
".app.src": { "image": "erlang" },
|
||||||
"/\\.((c([+px]{2}?)?-?)?objdump|bsdiff|bin|dat|pak|pdb)$/i": { "image": "assembly" },
|
"/^Emakefile$/": { "image": "erlang" },
|
||||||
".d-objdump": { "image": "assembly" },
|
"/^rebar(\\.config)?\\.lock$/i": { "image": "erlang" },
|
||||||
"/\\.gcode|\\.gco/i": { "image": "assembly" },
|
"/\\.(eslintrc|eslintignore)/i": { "image": "eslint" },
|
||||||
"/\\.rpy[bc]$/i": { "image": "assembly" },
|
"/(\\.firebaserc|firebase\\.json)/i": { "image": "firebase" },
|
||||||
"/\\.py[co]$/i": { "image": "assembly" },
|
".flowconfig": { "image": "flowconfig" },
|
||||||
".swp": { "image": "assembly" },
|
".fs": { "image": "fsharp" },
|
||||||
".DS_Store": { "image": "assembly" },
|
".fsi": { "image": "fsharp" },
|
||||||
".au3": { "image": "autoit" },
|
".fsscript": { "image": "fsharp" },
|
||||||
"babel.config.js": { "image": "babel" },
|
".fsx": { "image": "fsharp" },
|
||||||
"/\\.babelrc/i": { "image": "babel" },
|
"/gatsby-(browser|node|ssr|config)\\.js/i": { "image": "gatsbyjs" },
|
||||||
".bat": { "image": "bat" },
|
"/^Gemfile(\\.lock)?$/i": { "image": "gemfile" },
|
||||||
".batch": { "image": "bat" },
|
"/^\\.git|^\\.keep$|\\.mailmap$/i": { "image": "git" },
|
||||||
".cmd": { "image": "bat" },
|
".go": { "image": "go" },
|
||||||
"/\\.(exe|com|msi)$/i": { "image": "bat" },
|
".gd": { "image": "godot" },
|
||||||
".reg": { "image": "bat" },
|
".gradle": { "image": "gradle" },
|
||||||
"/^(\\.bowerrc|bower\\.json|Bowerfile)$/i": { "image": "bower" },
|
"gradlew": { "image": "gradle" },
|
||||||
"/\\.bf?$/i": { "image": "brainfuck" },
|
".gql": { "image": "graphql" },
|
||||||
"/\\.c$/i": { "image": "c" },
|
".graphql": { "image": "graphql" },
|
||||||
"/(cargo.toml|cargo.lock)/i": { "image": "cargo" },
|
".groovy": { "image": "groovy" },
|
||||||
".cfc": { "image": "cfml" },
|
".gvy": { "image": "groovy" },
|
||||||
".cfm": { "image": "cfml" },
|
".gy": { "image": "groovy" },
|
||||||
"circle.yml": { "image": "circleci" },
|
".gsh": { "image": "groovy" },
|
||||||
".clj": { "image": "clojure" },
|
"/gruntfile\\.(js|coffee)/i": { "image": "gruntfile" },
|
||||||
".cl2": { "image": "clojure" },
|
"gulpfile.js": { "image": "gulp" },
|
||||||
".cljc": { "image": "clojure" },
|
"/\\.(hbs|handlebars|(mu)?stache)$/i": { "image": "handlebars" },
|
||||||
".cljx": { "image": "clojure" },
|
".prg": { "image": "harbour" },
|
||||||
".hic": { "image": "clojure" },
|
".hbp": { "image": "harbour" },
|
||||||
"/\\.cljs(cm)?$/i": { "image": "clojure" },
|
".hbc": { "image": "harbour" },
|
||||||
".cmake": { "image": "cmake" },
|
".rc": { "image": "harbour" },
|
||||||
"/^CMakeLists\\.txt$/": { "image": "cmake" },
|
".fmg": { "image": "harbour" },
|
||||||
"/\\.codeclimate\\.(yml|json)/i": { "image": "codeclimate" },
|
".hs": { "image": "haskell" },
|
||||||
".coffee": { "image": "coffee" },
|
".hsc": { "image": "haskell" },
|
||||||
".cjsx": { "image": "coffee" },
|
".c2hs": { "image": "haskell" },
|
||||||
".coffee.ecr": { "image": "coffee" },
|
".lhs": { "image": "haskell" },
|
||||||
".coffee.erb": { "image": "coffee" },
|
".hx": { "image": "haxe" },
|
||||||
".litcoffee": { "image": "coffee" },
|
".hxml": { "image": "haxe" },
|
||||||
".iced": { "image": "coffee" },
|
"/^procfile/i": { "image": "heroku" },
|
||||||
"/\\.c[+px]{2}$|\\.cc$/i": { "image": "cpp" },
|
"heroku.yml": { "image": "heroku" },
|
||||||
"/\\.h[+px]{2}$/i": { "image": "cpp" },
|
".hjson": { "image": "hjson" },
|
||||||
"/\\.[it]pp$/i": { "image": "cpp" },
|
"/\\.x?html?$/i": { "image": "html" },
|
||||||
"/\\.(tcc|inl)$/i": { "image": "cpp" },
|
".http": { "image": "http" },
|
||||||
".cats": { "image": "cpp" },
|
".rest": { "image": "http" },
|
||||||
".idc": { "image": "cpp" },
|
".jar": { "image": "jar" },
|
||||||
".w": { "image": "cpp" },
|
".java": { "image": "java" },
|
||||||
".nc": { "image": "cpp" },
|
"jest.config.js": { "image": "jest" },
|
||||||
".upc": { "image": "cpp" },
|
".jinja": { "image": "jinja" },
|
||||||
".xpm": { "image": "cpp" },
|
".js": { "image": "javascript" },
|
||||||
"/\\.e?cr$/i": { "image": "crystal" },
|
".es6": { "image": "javascript" },
|
||||||
".cs": { "image": "csharp" },
|
".es": { "image": "javascript" },
|
||||||
".csx": { "image": "csharp" },
|
".mjs": { "image": "javascript" },
|
||||||
".cshtml": { "image": "cshtml" },
|
".js.map": { "image": "jsmap" },
|
||||||
".css": { "image": "css" },
|
".json": { "image": "json" },
|
||||||
".css.map": { "image": "cssmap" },
|
".jsonc": { "image": "json" },
|
||||||
".cu": { "image": "cuda" },
|
".jsx": { "image": "jsx" },
|
||||||
"/\\.di?$/i": { "image": "d" },
|
"/\\.(jil|jl)/i": { "image": "julia" },
|
||||||
".dart": { "image": "dart" },
|
".ipynb": { "image": "jupyter" },
|
||||||
".dfm": { "image": "delphi" },
|
".kt": { "image": "kotlin" },
|
||||||
".dpr": { "image": "delphi" },
|
".ktm": { "image": "kotlin" },
|
||||||
".dsc": { "image": "denizen" },
|
".kts": { "image": "kotlin" },
|
||||||
".dm": { "image": "dm" },
|
".less": { "image": "less" },
|
||||||
".dme": { "image": "dm" },
|
".lsp": { "image": "lisp" },
|
||||||
".dmm": { "image": "dm" },
|
".lisp": { "image": "lisp" },
|
||||||
"/^(Dockerfile|docker-compose)|\\.docker(file|ignore)$/i": { "image": "docker" },
|
".l": { "image": "lisp" },
|
||||||
"/^docker-sync\\.yml$/i": { "image": "docker" },
|
".nl": { "image": "lisp" },
|
||||||
".editorconfig": { "image": "editorconfig" },
|
".ny": { "image": "lisp" },
|
||||||
".ejs": { "image": "ejs" },
|
".podsl": { "image": "lisp" },
|
||||||
".ex": { "image": "elixir" },
|
".sexp": { "image": "lisp" },
|
||||||
"/\\.(exs|l?eex)$/i": { "image": "elixir" },
|
".ls": { "image": "livescript" },
|
||||||
"/^mix\\.(exs?|lock)$/i": { "image": "elixir" },
|
".log": { "image": "log" },
|
||||||
".elm": { "image": "elm" },
|
".lua": { "image": "lua" },
|
||||||
".env": { "image": "env" },
|
".pd_lua": { "image": "lua" },
|
||||||
".erl": { "image": "erlang" },
|
".rbxs": { "image": "lua" },
|
||||||
".beam": { "image": "erlang" },
|
".wlua": { "image": "lua" },
|
||||||
".hrl": { "image": "erlang" },
|
"/^Makefile/": { "image": "makefile" },
|
||||||
".xrl": { "image": "erlang" },
|
"/^mk\\.config$/": { "image": "makefile" },
|
||||||
".yrl": { "image": "erlang" },
|
"/\\.(mk|mak|make)$/i": { "image": "makefile" },
|
||||||
".app.src": { "image": "erlang" },
|
"/^BSDmakefile$/i": { "image": "makefile" },
|
||||||
"/^Emakefile$/": { "image": "erlang" },
|
"/^GNUmakefile$/i": { "image": "makefile" },
|
||||||
"/^rebar(\\.config)?\\.lock$/i": { "image": "erlang" },
|
"/^makefile\\.sco$/i": { "image": "makefile" },
|
||||||
"/\\.(eslintrc|eslintignore)/i": { "image": "eslint" },
|
"/^Kbuild$/": { "image": "makefile" },
|
||||||
"/(\\.firebaserc|firebase\\.json)/i": { "image": "firebase" },
|
"/^makefile$/": { "image": "makefile" },
|
||||||
".flowconfig": { "image": "flowconfig" },
|
"/^mkfile$/i": { "image": "makefile" },
|
||||||
".fs": { "image": "fsharp" },
|
"/^\\.?qmake$/i": { "image": "makefile" },
|
||||||
".fsi": { "image": "fsharp" },
|
"/\\.(h|geo|topo)$/i": { "image": "manifest" },
|
||||||
".fsscript": { "image": "fsharp" },
|
".cson": { "image": "manifest" },
|
||||||
".fsx": { "image": "fsharp" },
|
".json5": { "image": "manifest" },
|
||||||
"/gatsby-(browser|node|ssr|config)\\.js/i": { "image": "gatsbyjs" },
|
".ndjson": { "image": "manifest" },
|
||||||
"/^Gemfile(\\.lock)?$/i": { "image": "gemfile" },
|
".fea": { "image": "manifest" },
|
||||||
"/^\\.git|^\\.keep$|\\.mailmap$/i": { "image": "git" },
|
".json.eex": { "image": "manifest" },
|
||||||
".go": { "image": "go" },
|
".proto": { "image": "manifest" },
|
||||||
".gd": { "image": "godot" },
|
".pytb": { "image": "manifest" },
|
||||||
".gradle": { "image": "gradle" },
|
".pydeps": { "image": "manifest" },
|
||||||
"gradlew": { "image": "gradle" },
|
"/\\.pot?$/i": { "image": "manifest" },
|
||||||
".gql": { "image": "graphql" },
|
".ejson": { "image": "manifest" },
|
||||||
".graphql": { "image": "graphql" },
|
".edn": { "image": "manifest" },
|
||||||
".groovy": { "image": "groovy" },
|
".eam.fs": { "image": "manifest" },
|
||||||
".gvy": { "image": "groovy" },
|
".qml": { "image": "manifest" },
|
||||||
".gy": { "image": "groovy" },
|
".qbs": { "image": "manifest" },
|
||||||
".gsh": { "image": "groovy" },
|
".ston": { "image": "manifest" },
|
||||||
"/gruntfile\\.(js|coffee)/i": { "image": "gruntfile" },
|
".ttl": { "image": "manifest" },
|
||||||
"gulpfile.js": { "image": "gulp" },
|
".rviz": { "image": "manifest" },
|
||||||
"/\\.(hbs|handlebars|(mu)?stache)$/i": { "image": "handlebars" },
|
".syntax": { "image": "manifest" },
|
||||||
".prg": { "image": "harbour" },
|
".webmanifest": { "image": "manifest" },
|
||||||
".hbp": { "image": "harbour" },
|
"/^pkginfo$/": { "image": "manifest" },
|
||||||
".hbc": { "image": "harbour" },
|
"/^mime\\.types$/i": { "image": "manifest" },
|
||||||
".rc": { "image": "harbour" },
|
"/^METADATA\\.pb$/": { "image": "manifest" },
|
||||||
".fmg": { "image": "harbour" },
|
"/[\\/\\\\](?:magic[\\/\\\\]Magdir|file[\\/\\\\]magic)[\\/\\\\][-.\\w]+$/i": { "image": "manifest" },
|
||||||
".hs": { "image": "haskell" },
|
"/(\\\\|\\/)dev[-\\w]+\\1(?:[^\\\\\\/]+\\1)*(?!DESC|NOTES)(?:[A-Z][-A-Z]*)(?:\\.in)?$/": { "image": "manifest" },
|
||||||
".hsc": { "image": "haskell" },
|
"lib/icons/.icondb.js": { "image": "manifest" },
|
||||||
".c2hs": { "image": "haskell" },
|
"/\\.git[\\/\\\\](.*[\\/\\\\])?(HEAD|ORIG_HEAD|packed-refs|logs[\\/\\\\](.+[\\/\\\\])?[^\\/\\\\]+)$/": {
|
||||||
".lhs": { "image": "haskell" },
|
"image": "manifest"
|
||||||
".hx": { "image": "haxe" },
|
},
|
||||||
".hxml": { "image": "haxe" },
|
"/\\.(md|mdown|markdown|mkd|mkdown|mdwn|mkdn|rmd|ron|pmd)$/i": { "image": "markdown" },
|
||||||
"/^procfile/i": { "image": "heroku" },
|
".mdx": { "image": "markdownx" },
|
||||||
"heroku.yml": { "image": "heroku" },
|
".marko": { "image": "marko" },
|
||||||
".hjson": { "image": "hjson" },
|
".nim": { "image": "nim" },
|
||||||
"/\\.x?html?$/i": { "image": "html" },
|
".nims": { "image": "nim" },
|
||||||
".http": { "image": "http" },
|
".nimble": { "image": "nim" },
|
||||||
".rest": { "image": "http" },
|
".nix": { "image": "nix" },
|
||||||
".jar": { "image": "jar" },
|
"nodemon.json": { "image": "nodemon" },
|
||||||
".java": { "image": "java" },
|
".npmrc": { "image": "npm" },
|
||||||
"jest.config.js": { "image": "jest" },
|
"/\\.mm?$/i": { "image": "objective-c" },
|
||||||
".jinja": { "image": "jinja" },
|
".pch": { "image": "objective-c" },
|
||||||
".js": { "image": "js" },
|
".x": { "image": "objective-c" },
|
||||||
".es6": { "image": "js" },
|
".ml": { "image": "ocaml" },
|
||||||
".es": { "image": "js" },
|
".mli": { "image": "ocaml" },
|
||||||
".mjs": { "image": "js" },
|
".eliom": { "image": "ocaml" },
|
||||||
".js.map": { "image": "jsmap" },
|
".eliomi": { "image": "ocaml" },
|
||||||
".json": { "image": "json" },
|
".ml4": { "image": "ocaml" },
|
||||||
".jsonc": { "image": "json" },
|
".mll": { "image": "ocaml" },
|
||||||
".jsx": { "image": "jsx" },
|
".mly": { "image": "ocaml" },
|
||||||
"/\\.(jil|jl)/i": { "image": "julia" },
|
"/\\.pas(cal)?$/i": { "image": "pascal" },
|
||||||
".ipynb": { "image": "jupyter" },
|
".lpr": { "image": "pascal" },
|
||||||
".kt": { "image": "kotlin" },
|
".p": { "image": "pawn" },
|
||||||
".ktm": { "image": "kotlin" },
|
".inc": { "image": "pawn" },
|
||||||
".kts": { "image": "kotlin" },
|
".sma": { "image": "pawn" },
|
||||||
".less": { "image": "less" },
|
".pwn": { "image": "pawn" },
|
||||||
".lsp": { "image": "lisp" },
|
".sp": { "image": "pawn" },
|
||||||
".lisp": { "image": "lisp" },
|
"/\\.p(er)?l$/i": { "image": "perl" },
|
||||||
".l": { "image": "lisp" },
|
".al": { "image": "perl" },
|
||||||
".nl": { "image": "lisp" },
|
".ph": { "image": "perl" },
|
||||||
".ny": { "image": "lisp" },
|
".plx": { "image": "perl" },
|
||||||
".podsl": { "image": "lisp" },
|
".pm": { "image": "perl" },
|
||||||
".sexp": { "image": "lisp" },
|
"/\\.(psgi|xs)$/i": { "image": "perl" },
|
||||||
".ls": { "image": "livescript" },
|
".pl6": { "image": "perl" },
|
||||||
".log": { "image": "log" },
|
"/\\.[tp]6$|\\.6pl$/i": { "image": "perl" },
|
||||||
".lua": { "image": "lua" },
|
"/\\.(pm6|p6m)$/i": { "image": "perl" },
|
||||||
".pd_lua": { "image": "lua" },
|
".6pm": { "image": "perl" },
|
||||||
".rbxs": { "image": "lua" },
|
".nqp": { "image": "perl" },
|
||||||
".wlua": { "image": "lua" },
|
".p6l": { "image": "perl" },
|
||||||
"/^Makefile/": { "image": "makefile" },
|
".pod6": { "image": "perl" },
|
||||||
"/^mk\\.config$/": { "image": "makefile" },
|
"/^Rexfile$/": { "image": "perl" },
|
||||||
"/\\.(mk|mak|make)$/i": { "image": "makefile" },
|
"/\\.php([st\\d]|_cs)?$/i": { "image": "php" },
|
||||||
"/^BSDmakefile$/i": { "image": "makefile" },
|
"/^Phakefile/": { "image": "php" },
|
||||||
"/^GNUmakefile$/i": { "image": "makefile" },
|
".pony": { "image": "ponylang" },
|
||||||
"/^makefile\\.sco$/i": { "image": "makefile" },
|
".pcss": { "image": "postcss" },
|
||||||
"/^Kbuild$/": { "image": "makefile" },
|
".ps1": { "image": "powershell" },
|
||||||
"/^makefile$/": { "image": "makefile" },
|
".psd1": { "image": "powershell" },
|
||||||
"/^mkfile$/i": { "image": "makefile" },
|
".psm1": { "image": "powershell" },
|
||||||
"/^\\.?qmake$/i": { "image": "makefile" },
|
".ps1xml": { "image": "powershell" },
|
||||||
"/\\.(h|geo|topo)$/i": { "image": "manifest" },
|
".prettierignore": { "image": "prettier" },
|
||||||
".cson": { "image": "manifest" },
|
"/\\.prettier((rc)|(\\.(toml|yml|yaml|json|js))?$){2}/i": { "image": "prettier" },
|
||||||
".json5": { "image": "manifest" },
|
"prettier.config.js": { "image": "prettier" },
|
||||||
".ndjson": { "image": "manifest" },
|
"prisma.yml": { "image": "prisma" },
|
||||||
".fea": { "image": "manifest" },
|
".pde": { "image": "processing" },
|
||||||
".json.eex": { "image": "manifest" },
|
".jade": { "image": "pug" },
|
||||||
".proto": { "image": "manifest" },
|
".pug": { "image": "pug" },
|
||||||
".pytb": { "image": "manifest" },
|
".purs": { "image": "purescript" },
|
||||||
".pydeps": { "image": "manifest" },
|
".py": { "image": "python" },
|
||||||
"/\\.pot?$/i": { "image": "manifest" },
|
".ipy": { "image": "python" },
|
||||||
".ejson": { "image": "manifest" },
|
".isolate": { "image": "python" },
|
||||||
".edn": { "image": "manifest" },
|
".pep": { "image": "python" },
|
||||||
".eam.fs": { "image": "manifest" },
|
".gyp": { "image": "python" },
|
||||||
".qml": { "image": "manifest" },
|
".gypi": { "image": "python" },
|
||||||
".qbs": { "image": "manifest" },
|
".pyde": { "image": "python" },
|
||||||
".ston": { "image": "manifest" },
|
".pyp": { "image": "python" },
|
||||||
".ttl": { "image": "manifest" },
|
".pyt": { "image": "python" },
|
||||||
".rviz": { "image": "manifest" },
|
".py3": { "image": "python" },
|
||||||
".syntax": { "image": "manifest" },
|
".pyi": { "image": "python" },
|
||||||
".webmanifest": { "image": "manifest" },
|
".pyw": { "image": "python" },
|
||||||
"/^pkginfo$/": { "image": "manifest" },
|
".tac": { "image": "python" },
|
||||||
"/^mime\\.types$/i": { "image": "manifest" },
|
".wsgi": { "image": "python" },
|
||||||
"/^METADATA\\.pb$/": { "image": "manifest" },
|
".xpy": { "image": "python" },
|
||||||
"/[\\/\\\\](?:magic[\\/\\\\]Magdir|file[\\/\\\\]magic)[\\/\\\\][-.\\w]+$/i": { "image": "manifest" },
|
".rpy": { "image": "python" },
|
||||||
"/(\\\\|\\/)dev[-\\w]+\\1(?:[^\\\\\\/]+\\1)*(?!DESC|NOTES)(?:[A-Z][-A-Z]*)(?:\\.in)?$/": { "image": "manifest" },
|
"/\\.?(pypirc|pythonrc|python-venv)$/i": { "image": "python" },
|
||||||
"lib/icons/.icondb.js": { "image": "manifest" },
|
"/^(SConstruct|SConscript)$/": { "image": "python" },
|
||||||
"/\\.git[\\/\\\\](.*[\\/\\\\])?(HEAD|ORIG_HEAD|packed-refs|logs[\\/\\\\](.+[\\/\\\\])?[^\\/\\\\]+)$/": {
|
"/^(Snakefile|WATCHLISTS)$/": { "image": "python" },
|
||||||
"image": "manifest"
|
"/^wscript$/": { "image": "python" },
|
||||||
},
|
"/\\.(r|Rprofile|rsx|rd)$/i": { "image": "r" },
|
||||||
"/\\.(md|mdown|markdown|mkd|mkdown|mdwn|mkdn|rmd|ron|pmd)$/i": { "image": "markdown" },
|
".re": { "image": "reasonml" },
|
||||||
".mdx": { "image": "markdownx" },
|
"/\\.(rb|ru|ruby|erb|gemspec|god|mspec|pluginspec|podspec|rabl|rake|opal)$/i": { "image": "ruby" },
|
||||||
".marko": { "image": "marko" },
|
"/^\\.?(irbrc|gemrc|pryrc|ruby-(gemset|version))$/i": { "image": "ruby" },
|
||||||
".nim": { "image": "nim" },
|
"/^(Appraisals|(Rake|[bB]uild|Cap|Danger|Deliver|Fast|Guard|Jar|Maven|Pod|Puppet|Snap)file(\\.lock)?)$/": {
|
||||||
".nims": { "image": "nim" },
|
"image": "ruby"
|
||||||
".nimble": { "image": "nim" },
|
},
|
||||||
".nix": { "image": "nix" },
|
"/\\.(jbuilder|rbuild|rb[wx]|builder)$/i": { "image": "ruby" },
|
||||||
"nodemon.json": { "image": "nodemon" },
|
"/^rails$/": { "image": "ruby" },
|
||||||
".npmrc": { "image": "npm" },
|
".watchr": { "image": "ruby" },
|
||||||
"/\\.mm?$/i": { "image": "objc" },
|
".rs": { "image": "rust" },
|
||||||
".pch": { "image": "objc" },
|
"/\\.(sc|scala)$/i": { "image": "scala" },
|
||||||
".x": { "image": "objc" },
|
".scss": { "image": "scss" },
|
||||||
".ml": { "image": "ocaml" },
|
".sass": { "image": "scss" },
|
||||||
".mli": { "image": "ocaml" },
|
"/\\.(sh|rc|bats|bash|tool|install|command)$/i": { "image": "shell" },
|
||||||
".eliom": { "image": "ocaml" },
|
"/^(\\.?bash(rc|[-_]?(profile|login|logout|history|prompt))|_osc|config|install-sh|PKGBUILD)$/i": {
|
||||||
".eliomi": { "image": "ocaml" },
|
"image": "shell"
|
||||||
".ml4": { "image": "ocaml" },
|
},
|
||||||
".mll": { "image": "ocaml" },
|
"/\\.(ksh|mksh|pdksh)$/i": { "image": "shell" },
|
||||||
".mly": { "image": "ocaml" },
|
".sh-session": { "image": "shell" },
|
||||||
"/\\.pas(cal)?$/i": { "image": "pascal" },
|
"/\\.zsh(-theme|_history)?$|^\\.?(antigen|zpreztorc|zlogin|zlogout|zprofile|zshenv|zshrc)$/i": { "image": "shell" },
|
||||||
".lpr": { "image": "pascal" },
|
"/\\.fish$|^\\.fishrc$/i": { "image": "shell" },
|
||||||
".p": { "image": "pawn" },
|
"/^\\.?(login|profile)$/": { "image": "shell" },
|
||||||
".inc": { "image": "pawn" },
|
".inputrc": { "image": "shell" },
|
||||||
".sma": { "image": "pawn" },
|
".tmux": { "image": "shell" },
|
||||||
".pwn": { "image": "pawn" },
|
"/^(configure|config\\.(guess|rpath|status|sub)|depcomp|libtool|compile)$/": { "image": "shell" },
|
||||||
".sp": { "image": "pawn" },
|
"/^\\/(private\\/)?etc\\/([^\\/]+\\/)*(profile$|nanorc$|rc\\.|csh\\.)/i": { "image": "shell" },
|
||||||
"/\\.p(er)?l$/i": { "image": "perl" },
|
"/^\\.?cshrc$/i": { "image": "shell" },
|
||||||
".al": { "image": "perl" },
|
".profile": { "image": "shell" },
|
||||||
".ph": { "image": "perl" },
|
".tcsh": { "image": "shell" },
|
||||||
".plx": { "image": "perl" },
|
".csh": { "image": "shell" },
|
||||||
".pm": { "image": "perl" },
|
".sqf": { "image": "sqf" },
|
||||||
"/\\.(psgi|xs)$/i": { "image": "perl" },
|
"/\\.(my)?sql$/i": { "image": "sql" },
|
||||||
".pl6": { "image": "perl" },
|
".ddl": { "image": "sql" },
|
||||||
"/\\.[tp]6$|\\.6pl$/i": { "image": "perl" },
|
".udf": { "image": "sql" },
|
||||||
"/\\.(pm6|p6m)$/i": { "image": "perl" },
|
".hql": { "image": "sql" },
|
||||||
".6pm": { "image": "perl" },
|
".viw": { "image": "sql" },
|
||||||
".nqp": { "image": "perl" },
|
".prc": { "image": "sql" },
|
||||||
".p6l": { "image": "perl" },
|
".cql": { "image": "sql" },
|
||||||
".pod6": { "image": "perl" },
|
".db2": { "image": "sql" },
|
||||||
"/^Rexfile$/": { "image": "perl" },
|
"/\\.(styl|stylus)$/i": { "image": "stylus" },
|
||||||
"/\\.php([st\\d]|_cs)?$/i": { "image": "php" },
|
".svelte": { "image": "svelte" },
|
||||||
"/^Phakefile/": { "image": "php" },
|
".svg": { "image": "svg" },
|
||||||
".pony": { "image": "ponylang" },
|
".swift": { "image": "swift" },
|
||||||
".pcss": { "image": "postcss" },
|
".tex": { "image": "tex" },
|
||||||
".ps1": { "image": "powershell" },
|
".ltx": { "image": "tex" },
|
||||||
".psd1": { "image": "powershell" },
|
".aux": { "image": "tex" },
|
||||||
".psm1": { "image": "powershell" },
|
".sty": { "image": "tex" },
|
||||||
".ps1xml": { "image": "powershell" },
|
".dtx": { "image": "tex" },
|
||||||
".prettierignore": { "image": "prettier" },
|
".cls": { "image": "tex" },
|
||||||
"/\\.prettier((rc)|(\\.(toml|yml|yaml|json|js))?$){2}/i": { "image": "prettier" },
|
".ins": { "image": "tex" },
|
||||||
"prettier.config.js": { "image": "prettier" },
|
".lbx": { "image": "tex" },
|
||||||
"prisma.yml": { "image": "prisma" },
|
".mkiv": { "image": "tex" },
|
||||||
".pde": { "image": "processing" },
|
".mkvi": { "image": "tex" },
|
||||||
".jade": { "image": "pug" },
|
".mkii": { "image": "tex" },
|
||||||
".pug": { "image": "pug" },
|
".texi": { "image": "tex" },
|
||||||
".purs": { "image": "purescript" },
|
"/^hyphen(ex)?\\.(cs|den|det|fr|sv|us)$/": { "image": "tex" },
|
||||||
".py": { "image": "python" },
|
"/\\.te?xt$/i": { "image": "text" },
|
||||||
".ipy": { "image": "python" },
|
".rtf": { "image": "text" },
|
||||||
".isolate": { "image": "python" },
|
"/\\.i?nfo$/i": { "image": "text" },
|
||||||
".pep": { "image": "python" },
|
".msg": { "image": "text" },
|
||||||
".gyp": { "image": "python" },
|
"/\\.(utxt|utf8)$/i": { "image": "text" },
|
||||||
".gypi": { "image": "python" },
|
".toml": { "image": "toml" },
|
||||||
".pyde": { "image": "python" },
|
".travis.yml": { "image": "travis" },
|
||||||
".pyp": { "image": "python" },
|
".ts": { "image": "typescript" },
|
||||||
".pyt": { "image": "python" },
|
".tsx": { "image": "tsx" },
|
||||||
".py3": { "image": "python" },
|
".twig": { "image": "twig" },
|
||||||
".pyi": { "image": "python" },
|
"/.*\\.d\\.ts/i": { "image": "typescript-def" },
|
||||||
".pyw": { "image": "python" },
|
".v": { "image": "v" },
|
||||||
".tac": { "image": "python" },
|
".vh": { "image": "v" },
|
||||||
".wsgi": { "image": "python" },
|
".vala": { "image": "vala" },
|
||||||
".xpy": { "image": "python" },
|
".vapi": { "image": "vala" },
|
||||||
".rpy": { "image": "python" },
|
".vb": { "image": "vb" },
|
||||||
"/\\.?(pypirc|pythonrc|python-venv)$/i": { "image": "python" },
|
".vbs": { "image": "vb" },
|
||||||
"/^(SConstruct|SConscript)$/": { "image": "python" },
|
".vbhtml": { "image": "vb" },
|
||||||
"/^(Snakefile|WATCHLISTS)$/": { "image": "python" },
|
".vbproj": { "image": "vb" },
|
||||||
"/^wscript$/": { "image": "python" },
|
".vba": { "image": "vba" },
|
||||||
"/\\.(r|Rprofile|rsx|rd)$/i": { "image": "r" },
|
".vcxproj": { "image": "vcxproj" },
|
||||||
".re": { "image": "reasonml" },
|
".vscodeignore": { "image": "vscodeignore" },
|
||||||
"/\\.(rb|ru|ruby|erb|gemspec|god|mspec|pluginspec|podspec|rabl|rake|opal)$/i": { "image": "ruby" },
|
".vue": { "image": "vue" },
|
||||||
"/^\\.?(irbrc|gemrc|pryrc|ruby-(gemset|version))$/i": { "image": "ruby" },
|
".wat": { "image": "wasm" },
|
||||||
"/^(Appraisals|(Rake|[bB]uild|Cap|Danger|Deliver|Fast|Guard|Jar|Maven|Pod|Puppet|Snap)file(\\.lock)?)$/": {
|
".wast": { "image": "wasm" },
|
||||||
"image": "ruby"
|
".wasm": { "image": "wasm" },
|
||||||
},
|
"/webpack(\\.dev|\\.development|\\.prod|\\.production)?\\.config(\\.babel)?\\.(js|jsx|coffee|ts|json|json5|yaml|yml)/i": {
|
||||||
"/\\.(jbuilder|rbuild|rb[wx]|builder)$/i": { "image": "ruby" },
|
"image": "webpack"
|
||||||
"/^rails$/": { "image": "ruby" },
|
},
|
||||||
".watchr": { "image": "ruby" },
|
".xml": { "image": "xml" },
|
||||||
".rs": { "image": "rust" },
|
"/\\.ya?ml$/i": { "image": "yaml" },
|
||||||
"/\\.(sc|scala)$/i": { "image": "scala" },
|
"/^yarn(\\.lock)?$/i": { "image": "yarn" },
|
||||||
".scss": { "image": "scss" },
|
".yarnrc": { "image": "yarn" },
|
||||||
".sass": { "image": "scss" },
|
".zig": { "image": "zig" }
|
||||||
"/\\.(sh|rc|bats|bash|tool|install|command)$/i": { "image": "shell" },
|
}
|
||||||
"/^(\\.?bash(rc|[-_]?(profile|login|logout|history|prompt))|_osc|config|install-sh|PKGBUILD)$/i": {
|
|
||||||
"image": "shell"
|
|
||||||
},
|
|
||||||
"/\\.(ksh|mksh|pdksh)$/i": { "image": "shell" },
|
|
||||||
".sh-session": { "image": "shell" },
|
|
||||||
"/\\.zsh(-theme|_history)?$|^\\.?(antigen|zpreztorc|zlogin|zlogout|zprofile|zshenv|zshrc)$/i": { "image": "shell" },
|
|
||||||
"/\\.fish$|^\\.fishrc$/i": { "image": "shell" },
|
|
||||||
"/^\\.?(login|profile)$/": { "image": "shell" },
|
|
||||||
".inputrc": { "image": "shell" },
|
|
||||||
".tmux": { "image": "shell" },
|
|
||||||
"/^(configure|config\\.(guess|rpath|status|sub)|depcomp|libtool|compile)$/": { "image": "shell" },
|
|
||||||
"/^\\/(private\\/)?etc\\/([^\\/]+\\/)*(profile$|nanorc$|rc\\.|csh\\.)/i": { "image": "shell" },
|
|
||||||
"/^\\.?cshrc$/i": { "image": "shell" },
|
|
||||||
".profile": { "image": "shell" },
|
|
||||||
".tcsh": { "image": "shell" },
|
|
||||||
".csh": { "image": "shell" },
|
|
||||||
".sqf": { "image": "sqf" },
|
|
||||||
"/\\.(my)?sql$/i": { "image": "sql" },
|
|
||||||
".ddl": { "image": "sql" },
|
|
||||||
".udf": { "image": "sql" },
|
|
||||||
".hql": { "image": "sql" },
|
|
||||||
".viw": { "image": "sql" },
|
|
||||||
".prc": { "image": "sql" },
|
|
||||||
".cql": { "image": "sql" },
|
|
||||||
".db2": { "image": "sql" },
|
|
||||||
"/\\.(styl|stylus)$/i": { "image": "stylus" },
|
|
||||||
".svelte": { "image": "svelte" },
|
|
||||||
".svg": { "image": "svg" },
|
|
||||||
".swift": { "image": "swift" },
|
|
||||||
".tex": { "image": "tex" },
|
|
||||||
".ltx": { "image": "tex" },
|
|
||||||
".aux": { "image": "tex" },
|
|
||||||
".sty": { "image": "tex" },
|
|
||||||
".dtx": { "image": "tex" },
|
|
||||||
".cls": { "image": "tex" },
|
|
||||||
".ins": { "image": "tex" },
|
|
||||||
".lbx": { "image": "tex" },
|
|
||||||
".mkiv": { "image": "tex" },
|
|
||||||
".mkvi": { "image": "tex" },
|
|
||||||
".mkii": { "image": "tex" },
|
|
||||||
".texi": { "image": "tex" },
|
|
||||||
"/^hyphen(ex)?\\.(cs|den|det|fr|sv|us)$/": { "image": "tex" },
|
|
||||||
"/\\.te?xt$/i": { "image": "text" },
|
|
||||||
".rtf": { "image": "text" },
|
|
||||||
"/\\.i?nfo$/i": { "image": "text" },
|
|
||||||
".msg": { "image": "text" },
|
|
||||||
"/\\.(utxt|utf8)$/i": { "image": "text" },
|
|
||||||
".toml": { "image": "toml" },
|
|
||||||
".travis.yml": { "image": "travis" },
|
|
||||||
".ts": { "image": "ts" },
|
|
||||||
".tsx": { "image": "tsx" },
|
|
||||||
".twig": { "image": "twig" },
|
|
||||||
"/.*\\.d\\.ts/i": { "image": "typescript-def" },
|
|
||||||
".v": { "image": "v" },
|
|
||||||
".vh": { "image": "v" },
|
|
||||||
".vala": { "image": "vala" },
|
|
||||||
".vapi": { "image": "vala" },
|
|
||||||
".vb": { "image": "vb" },
|
|
||||||
".vbs": { "image": "vb" },
|
|
||||||
".vbhtml": { "image": "vb" },
|
|
||||||
".vbproj": { "image": "vb" },
|
|
||||||
".vba": { "image": "vba" },
|
|
||||||
".vcxproj": { "image": "vcxproj" },
|
|
||||||
".vscodeignore": { "image": "vscodeignore" },
|
|
||||||
".vue": { "image": "vue" },
|
|
||||||
".wat": { "image": "wasm" },
|
|
||||||
".wast": { "image": "wasm" },
|
|
||||||
".wasm": { "image": "wasm" },
|
|
||||||
"/webpack(\\.dev|\\.development|\\.prod|\\.production)?\\.config(\\.babel)?\\.(js|jsx|coffee|ts|json|json5|yaml|yml)/i": { "image": "webpack" },
|
|
||||||
".xml": { "image": "xml" },
|
|
||||||
"/\\.ya?ml$/i": { "image": "yaml" },
|
|
||||||
"/^yarn(\\.lock)?$/i": { "image": "yarn" },
|
|
||||||
".yarnrc": { "image": "yarn" },
|
|
||||||
".zig": { "image": "zig" }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
162
src/extension.ts
162
src/extension.ts
|
@ -1,112 +1,118 @@
|
||||||
import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, workspace, extensions } from 'vscode';
|
const { Client } = require('discord-rpc'); // eslint-disable-line
|
||||||
import RPCClient from './client/RPCClient';
|
import {
|
||||||
import Logger from './structures/Logger';
|
commands,
|
||||||
import { GitExtension } from './git';
|
ExtensionContext,
|
||||||
const { register } = require('discord-rpc'); // eslint-disable-line
|
StatusBarAlignment,
|
||||||
|
StatusBarItem,
|
||||||
|
window,
|
||||||
|
workspace,
|
||||||
|
extensions,
|
||||||
|
debug,
|
||||||
|
} from 'vscode';
|
||||||
|
import { activity } from './activity';
|
||||||
|
|
||||||
let loginTimeout: NodeJS.Timer | undefined;
|
import { CLIENT_ID, CONFIG_KEYS } from './constants';
|
||||||
|
import { GitExtension } from './git';
|
||||||
|
import { log, LogLevel } from './logger';
|
||||||
|
import { getConfig } from './util';
|
||||||
|
|
||||||
const statusBarIcon: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
|
const statusBarIcon: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
|
||||||
statusBarIcon.text = '$(pulse) Connecting to Discord...';
|
statusBarIcon.text = '$(pulse) Connecting to Discord...';
|
||||||
|
|
||||||
const clientId = '383226320970055681';
|
const rpc = new Client({ transport: 'ipc' });
|
||||||
const config = workspace.getConfiguration('discord');
|
const config = getConfig();
|
||||||
register(clientId);
|
|
||||||
const rpc = new RPCClient(clientId, statusBarIcon);
|
|
||||||
|
|
||||||
export async function activate(context: ExtensionContext) {
|
async function sendActivity() {
|
||||||
Logger.log('Discord Presence activated!');
|
rpc.setActivity(await activity());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login(context: ExtensionContext) {
|
||||||
|
rpc.once('ready', () => {
|
||||||
|
log(LogLevel.Info, 'Successfully connected to Discord');
|
||||||
|
|
||||||
|
statusBarIcon.text = '$(globe) Connected to Discord';
|
||||||
|
statusBarIcon.tooltip = 'Connected to Discord';
|
||||||
|
|
||||||
|
void sendActivity();
|
||||||
|
const onChangeActiveTextEditor = window.onDidChangeActiveTextEditor(() => sendActivity());
|
||||||
|
const onChangeTextDocument = workspace.onDidChangeTextDocument(() => sendActivity());
|
||||||
|
const onStartDebugSession = debug.onDidStartDebugSession(() => sendActivity());
|
||||||
|
const onTerminateDebugSession = debug.onDidTerminateDebugSession(() => sendActivity());
|
||||||
|
|
||||||
|
context.subscriptions.push(
|
||||||
|
onChangeActiveTextEditor,
|
||||||
|
onChangeTextDocument,
|
||||||
|
onStartDebugSession,
|
||||||
|
onTerminateDebugSession,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await rpc.login({ clientId: CLIENT_ID });
|
||||||
|
} catch (error) {
|
||||||
|
log(LogLevel.Error, `Encountered following error while trying to login:\n${error as string}`);
|
||||||
|
rpc.dispose();
|
||||||
|
if (!config[CONFIG_KEYS.SuppressNotifications]) {
|
||||||
|
if (error?.message?.includes('ENOENT')) void window.showErrorMessage('No Discord client detected');
|
||||||
|
else void window.showErrorMessage(`Couldn't connect to Discord via RPC: ${error as string}`);
|
||||||
|
}
|
||||||
|
rpc.statusBarIcon.text = '$(pulse) Reconnect to Discord';
|
||||||
|
rpc.statusBarIcon.command = 'discord.reconnect';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function activate(context: ExtensionContext) {
|
||||||
|
log(LogLevel.Info, 'Discord Presence activated');
|
||||||
|
|
||||||
let isWorkspaceExcluded = false;
|
let isWorkspaceExcluded = false;
|
||||||
const excludePatterns = config.get<string[]>('workspaceExcludePatterns');
|
for (const pattern of config[CONFIG_KEYS.WorkspaceExcludePatterns]) {
|
||||||
if (excludePatterns?.length) {
|
const regex = new RegExp(pattern);
|
||||||
for (const pattern of excludePatterns) {
|
const folders = workspace.workspaceFolders;
|
||||||
const regex = new RegExp(pattern);
|
if (!folders) break;
|
||||||
const folders = workspace.workspaceFolders;
|
if (folders.some((folder) => regex.test(folder.uri.fsPath))) {
|
||||||
if (!folders) break;
|
isWorkspaceExcluded = true;
|
||||||
if (folders.some((folder) => regex.test(folder.uri.fsPath))) {
|
break;
|
||||||
isWorkspaceExcluded = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const enabler = commands.registerCommand('discord.enable', () => {
|
const enabler = commands.registerCommand('discord.enable', () => {
|
||||||
rpc.dispose();
|
rpc.destroy();
|
||||||
void config.update('enabled', true);
|
void config.update('enabled', true);
|
||||||
rpc.config = workspace.getConfiguration('discord');
|
statusBarIcon.text = '$(pulse) Connecting to Discord...';
|
||||||
rpc.statusBarIcon.text = '$(pulse) Connecting to Discord...';
|
statusBarIcon.show();
|
||||||
rpc.statusBarIcon.show();
|
void login(context);
|
||||||
void rpc.login();
|
void window.showInformationMessage('Enabled Discord Presence for this workspace');
|
||||||
void window.showInformationMessage('Enabled Discord Rich Presence for this workspace.');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const disabler = commands.registerCommand('discord.disable', () => {
|
const disabler = commands.registerCommand('discord.disable', () => {
|
||||||
void config.update('enabled', false);
|
void config.update('enabled', false);
|
||||||
rpc.config = workspace.getConfiguration('discord');
|
rpc.destroy();
|
||||||
rpc.dispose();
|
|
||||||
rpc.statusBarIcon.hide();
|
rpc.statusBarIcon.hide();
|
||||||
void window.showInformationMessage('Disabled Discord Rich Presence for this workspace.');
|
void window.showInformationMessage('Disabled Discord Presence for this workspace');
|
||||||
});
|
});
|
||||||
|
|
||||||
const reconnecter = commands.registerCommand('discord.reconnect', () => {
|
const reconnecter = commands.registerCommand('discord.reconnect', () => {
|
||||||
if (loginTimeout) clearTimeout(loginTimeout);
|
deactivate();
|
||||||
rpc.dispose();
|
void activate(context);
|
||||||
loginTimeout = setTimeout(() => {
|
|
||||||
void rpc.login();
|
|
||||||
if (!config.get('silent')) void window.showInformationMessage('Reconnecting to Discord RPC...');
|
|
||||||
rpc.statusBarIcon.text = '$(pulse) Reconnecting to Discord...';
|
|
||||||
rpc.statusBarIcon.command = 'discord.reconnect';
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const disconnect = commands.registerCommand('discord.disconnect', () => {
|
const disconnect = commands.registerCommand('discord.disconnect', () => {
|
||||||
rpc.dispose();
|
rpc.destroy();
|
||||||
rpc.statusBarIcon.text = '$(pulse) Reconnect to Discord';
|
rpc.statusBarIcon.text = '$(pulse) Reconnect to Discord';
|
||||||
rpc.statusBarIcon.command = 'discord.reconnect';
|
rpc.statusBarIcon.command = 'discord.reconnect';
|
||||||
});
|
});
|
||||||
const allowSpectate = commands.registerCommand('discord.allowSpectate', () => rpc.allowSpectate());
|
|
||||||
const disableSpectate = commands.registerCommand('discord.disableSpectate', () => rpc.disableSpectate());
|
|
||||||
const allowJoinRequests = commands.registerCommand('discord.allowJoinRequests', () => rpc.allowJoinRequests());
|
|
||||||
const disableJoinRequests = commands.registerCommand('discord.disableJoinRequests', () => rpc.disableJoinRequests());
|
|
||||||
|
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(enabler, disabler, reconnecter, disconnect);
|
||||||
enabler,
|
|
||||||
disabler,
|
|
||||||
reconnecter,
|
|
||||||
disconnect,
|
|
||||||
allowSpectate,
|
|
||||||
disableSpectate,
|
|
||||||
allowJoinRequests,
|
|
||||||
disableJoinRequests,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isWorkspaceExcluded && config.get<boolean>('enabled')) {
|
if (!isWorkspaceExcluded && config[CONFIG_KEYS.Enabled]) {
|
||||||
statusBarIcon.show();
|
statusBarIcon.show();
|
||||||
try {
|
void login(context);
|
||||||
await rpc.login();
|
|
||||||
} catch (error) {
|
|
||||||
Logger.log(`Encountered following error after trying to login:\n${error as string}`);
|
|
||||||
rpc.dispose();
|
|
||||||
if (!config.get('silent')) {
|
|
||||||
if (error?.message?.includes('ENOENT')) void window.showErrorMessage('No Discord Client detected!');
|
|
||||||
else void window.showErrorMessage(`Couldn't connect to Discord via RPC: ${error as string}`);
|
|
||||||
}
|
|
||||||
rpc.statusBarIcon.text = '$(pulse) Reconnect to Discord';
|
|
||||||
rpc.statusBarIcon.command = 'discord.reconnect';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const gitExtension = extensions.getExtension<GitExtension>('vscode.git');
|
const gitExtension = extensions.getExtension<GitExtension>('vscode.git');
|
||||||
if (gitExtension) {
|
void gitExtension?.activate();
|
||||||
if (gitExtension.isActive) {
|
|
||||||
rpc.git = gitExtension.exports.getAPI(1);
|
|
||||||
} else {
|
|
||||||
const extension = await gitExtension.activate();
|
|
||||||
rpc.git = extension.getAPI(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deactivate() {
|
export function deactivate() {
|
||||||
rpc.dispose();
|
rpc.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on('unhandledRejection', (err) => Logger.log(err as string));
|
|
||||||
|
|
95
src/git.d.ts
vendored
95
src/git.d.ts
vendored
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// eslint-disable-next-line
|
import { Uri, Event, Disposable, ProviderResult } from 'vscode';
|
||||||
import { Uri, SourceControlInputBox, Event, CancellationToken } from 'vscode';
|
export { ProviderResult } from 'vscode';
|
||||||
|
|
||||||
export interface Git {
|
export interface Git {
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
|
@ -14,6 +14,11 @@ export interface InputBox {
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const enum ForcePushMode {
|
||||||
|
Force,
|
||||||
|
ForceWithLease,
|
||||||
|
}
|
||||||
|
|
||||||
export const enum RefType {
|
export const enum RefType {
|
||||||
Head,
|
Head,
|
||||||
RemoteHead,
|
RemoteHead,
|
||||||
|
@ -42,7 +47,10 @@ export interface Commit {
|
||||||
readonly hash: string;
|
readonly hash: string;
|
||||||
readonly message: string;
|
readonly message: string;
|
||||||
readonly parents: string[];
|
readonly parents: string[];
|
||||||
readonly authorEmail?: string | undefined;
|
readonly authorDate?: Date;
|
||||||
|
readonly authorName?: string;
|
||||||
|
readonly authorEmail?: string;
|
||||||
|
readonly commitDate?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Submodule {
|
export interface Submodule {
|
||||||
|
@ -117,6 +125,24 @@ export interface RepositoryUIState {
|
||||||
export interface LogOptions {
|
export interface LogOptions {
|
||||||
/** Max number of log entries to retrieve. If not specified, the default is 32. */
|
/** Max number of log entries to retrieve. If not specified, the default is 32. */
|
||||||
readonly maxEntries?: number;
|
readonly maxEntries?: number;
|
||||||
|
readonly path?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CommitOptions {
|
||||||
|
all?: boolean | 'tracked';
|
||||||
|
amend?: boolean;
|
||||||
|
signoff?: boolean;
|
||||||
|
signCommit?: boolean;
|
||||||
|
empty?: boolean;
|
||||||
|
noVerify?: boolean;
|
||||||
|
requireUserConfig?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BranchQuery {
|
||||||
|
readonly remote?: boolean;
|
||||||
|
readonly pattern?: string;
|
||||||
|
readonly count?: number;
|
||||||
|
readonly contains?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Repository {
|
export interface Repository {
|
||||||
|
@ -157,6 +183,7 @@ export interface Repository {
|
||||||
createBranch(name: string, checkout: boolean, ref?: string): Promise<void>;
|
createBranch(name: string, checkout: boolean, ref?: string): Promise<void>;
|
||||||
deleteBranch(name: string, force?: boolean): Promise<void>;
|
deleteBranch(name: string, force?: boolean): Promise<void>;
|
||||||
getBranch(name: string): Promise<Branch>;
|
getBranch(name: string): Promise<Branch>;
|
||||||
|
getBranches(query: BranchQuery): Promise<Ref[]>;
|
||||||
setBranchUpstream(name: string, upstream: string): Promise<void>;
|
setBranchUpstream(name: string, upstream: string): Promise<void>;
|
||||||
|
|
||||||
getMergeBase(ref1: string, ref2: string): Promise<string>;
|
getMergeBase(ref1: string, ref2: string): Promise<string>;
|
||||||
|
@ -166,24 +193,75 @@ export interface Repository {
|
||||||
|
|
||||||
addRemote(name: string, url: string): Promise<void>;
|
addRemote(name: string, url: string): Promise<void>;
|
||||||
removeRemote(name: string): Promise<void>;
|
removeRemote(name: string): Promise<void>;
|
||||||
|
renameRemote(name: string, newName: string): Promise<void>;
|
||||||
|
|
||||||
fetch(remote?: string, ref?: string, depth?: number): Promise<void>;
|
fetch(remote?: string, ref?: string, depth?: number): Promise<void>;
|
||||||
pull(unshallow?: boolean): Promise<void>;
|
pull(unshallow?: boolean): Promise<void>;
|
||||||
push(remoteName?: string, branchName?: string, setUpstream?: boolean): Promise<void>;
|
push(remoteName?: string, branchName?: string, setUpstream?: boolean, force?: ForcePushMode): Promise<void>;
|
||||||
|
|
||||||
blame(path: string): Promise<string>;
|
blame(path: string): Promise<string>;
|
||||||
log(options?: LogOptions): Promise<Commit[]>;
|
log(options?: LogOptions): Promise<Commit[]>;
|
||||||
|
|
||||||
|
commit(message: string, opts?: CommitOptions): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RemoteSource {
|
||||||
|
readonly name: string;
|
||||||
|
readonly description?: string;
|
||||||
|
readonly url: string | string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RemoteSourceProvider {
|
||||||
|
readonly name: string;
|
||||||
|
readonly icon?: string; // codicon name
|
||||||
|
readonly supportsQuery?: boolean;
|
||||||
|
getRemoteSources(query?: string): ProviderResult<RemoteSource[]>;
|
||||||
|
getBranches?(url: string): ProviderResult<string[]>;
|
||||||
|
publishRepository?(repository: Repository): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Credentials {
|
||||||
|
readonly username: string;
|
||||||
|
readonly password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CredentialsProvider {
|
||||||
|
getCredentials(host: Uri): ProviderResult<Credentials>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PushErrorHandler {
|
||||||
|
handlePushError(
|
||||||
|
repository: Repository,
|
||||||
|
remote: Remote,
|
||||||
|
refspec: string,
|
||||||
|
error: Error & { gitErrorCode: GitErrorCodes },
|
||||||
|
): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type APIState = 'uninitialized' | 'initialized';
|
export type APIState = 'uninitialized' | 'initialized';
|
||||||
|
|
||||||
|
export interface PublishEvent {
|
||||||
|
repository: Repository;
|
||||||
|
branch?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface API {
|
export interface API {
|
||||||
readonly state: APIState;
|
readonly state: APIState;
|
||||||
readonly onDidChangeState: Event<APIState>;
|
readonly onDidChangeState: Event<APIState>;
|
||||||
|
readonly onDidPublish: Event<PublishEvent>;
|
||||||
readonly git: Git;
|
readonly git: Git;
|
||||||
readonly repositories: Repository[];
|
readonly repositories: Repository[];
|
||||||
readonly onDidOpenRepository: Event<Repository>;
|
readonly onDidOpenRepository: Event<Repository>;
|
||||||
readonly onDidCloseRepository: Event<Repository>;
|
readonly onDidCloseRepository: Event<Repository>;
|
||||||
|
|
||||||
|
toGitUri(uri: Uri, ref: string): Uri;
|
||||||
|
getRepository(uri: Uri): Repository | null;
|
||||||
|
init(root: Uri): Promise<Repository | null>;
|
||||||
|
openRepository(root: Uri): Promise<Repository | null>;
|
||||||
|
|
||||||
|
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
|
||||||
|
registerCredentialsProvider(provider: CredentialsProvider): Disposable;
|
||||||
|
registerPushErrorHandler(handler: PushErrorHandler): Disposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GitExtension {
|
export interface GitExtension {
|
||||||
|
@ -220,6 +298,7 @@ export const enum GitErrorCodes {
|
||||||
CantOpenResource = 'CantOpenResource',
|
CantOpenResource = 'CantOpenResource',
|
||||||
GitNotFound = 'GitNotFound',
|
GitNotFound = 'GitNotFound',
|
||||||
CantCreatePipe = 'CantCreatePipe',
|
CantCreatePipe = 'CantCreatePipe',
|
||||||
|
PermissionDenied = 'PermissionDenied',
|
||||||
CantAccessRemote = 'CantAccessRemote',
|
CantAccessRemote = 'CantAccessRemote',
|
||||||
RepositoryNotFound = 'RepositoryNotFound',
|
RepositoryNotFound = 'RepositoryNotFound',
|
||||||
RepositoryIsLocked = 'RepositoryIsLocked',
|
RepositoryIsLocked = 'RepositoryIsLocked',
|
||||||
|
|
33
src/logger.ts
Normal file
33
src/logger.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { window } from 'vscode';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const outputChannel = window.createOutputChannel('Discord Presence');
|
||||||
|
|
||||||
|
export const enum LogLevel {
|
||||||
|
Trace = 'TRACE',
|
||||||
|
Debug = 'DEBUG',
|
||||||
|
Info = 'INFO',
|
||||||
|
Warn = 'WARN',
|
||||||
|
Error = 'ERROR',
|
||||||
|
}
|
||||||
|
|
||||||
|
function send(level: string, message: string) {
|
||||||
|
outputChannel.appendLine(`[${dayjs().format('DD/MM/YYYY HH:mm:ss')} - ${level}] ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function log(level: LogLevel, message: string | Error) {
|
||||||
|
if (typeof message === 'string') {
|
||||||
|
send(level, message);
|
||||||
|
} else if (message instanceof Error) {
|
||||||
|
send(level, message.message);
|
||||||
|
|
||||||
|
if (message.stack) {
|
||||||
|
send(level, message.stack);
|
||||||
|
}
|
||||||
|
} else if (typeof message === 'object') {
|
||||||
|
try {
|
||||||
|
const json = JSON.stringify(message, null, 2);
|
||||||
|
send(level, json);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,376 +0,0 @@
|
||||||
import { basename, parse, sep } from 'path';
|
|
||||||
import { debug, Disposable, env, window, workspace } from 'vscode';
|
|
||||||
import * as vsls from 'vsls';
|
|
||||||
import RPCClient from '../client/RPCClient';
|
|
||||||
import lang from '../data/languages.json';
|
|
||||||
|
|
||||||
const knownExtensions: { [key: string]: { image: string } } = lang.knownExtensions;
|
|
||||||
const knownLanguages: string[] = lang.knownLanguages;
|
|
||||||
|
|
||||||
const empty = '\u200b\u200b';
|
|
||||||
const sizes = [' bytes', 'kb', 'mb', 'gb', 'tb'];
|
|
||||||
|
|
||||||
export interface State {
|
|
||||||
details?: string;
|
|
||||||
state?: string;
|
|
||||||
startTimestamp?: number | null;
|
|
||||||
largeImageKey?: string;
|
|
||||||
largeImageText?: string;
|
|
||||||
smallImageKey?: string;
|
|
||||||
smallImageText?: string;
|
|
||||||
partyId?: string;
|
|
||||||
partySize?: number;
|
|
||||||
partyMax?: number;
|
|
||||||
matchSecret?: string;
|
|
||||||
joinSecret?: string;
|
|
||||||
spectateSecret?: string;
|
|
||||||
instance?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FileDetail {
|
|
||||||
size?: string;
|
|
||||||
totalLines?: string;
|
|
||||||
currentLine?: string;
|
|
||||||
currentColumn?: string;
|
|
||||||
gitbranch?: string;
|
|
||||||
gitreponame?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Activity implements Disposable {
|
|
||||||
private _state: State | null = null;
|
|
||||||
|
|
||||||
private lastKnownFile = '';
|
|
||||||
|
|
||||||
public constructor(private readonly client: RPCClient) {}
|
|
||||||
|
|
||||||
public get state() {
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async generate(workspaceElapsedTime = false) {
|
|
||||||
let largeImageKey: any = 'vscode-big';
|
|
||||||
if (window.activeTextEditor) {
|
|
||||||
if (window.activeTextEditor.document.languageId === 'Log') return this._state;
|
|
||||||
if (this._state && window.activeTextEditor.document.fileName === this.lastKnownFile) {
|
|
||||||
return (this._state = {
|
|
||||||
...this._state,
|
|
||||||
details: await this._generateDetails(
|
|
||||||
'detailsDebugging',
|
|
||||||
'detailsEditing',
|
|
||||||
'detailsIdle',
|
|
||||||
this._state.largeImageKey,
|
|
||||||
),
|
|
||||||
smallImageKey: debug.activeDebugSession
|
|
||||||
? 'debug'
|
|
||||||
: env.appName.includes('Insiders')
|
|
||||||
? 'vscode-insiders'
|
|
||||||
: 'vscode',
|
|
||||||
state: await this._generateDetails(
|
|
||||||
'lowerDetailsDebugging',
|
|
||||||
'lowerDetailsEditing',
|
|
||||||
'lowerDetailsIdle',
|
|
||||||
this._state.largeImageKey,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.lastKnownFile = window.activeTextEditor.document.fileName;
|
|
||||||
const filename = basename(window.activeTextEditor.document.fileName);
|
|
||||||
largeImageKey =
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
||||||
knownExtensions[
|
|
||||||
Object.keys(knownExtensions).find((key) => {
|
|
||||||
if (filename.endsWith(key)) return true;
|
|
||||||
const match = /^\/(.*)\/([mgiy]+)$/.exec(key);
|
|
||||||
if (!match) return false;
|
|
||||||
const regex = new RegExp(match[1], match[2]);
|
|
||||||
return regex.test(filename);
|
|
||||||
})!
|
|
||||||
] ??
|
|
||||||
(knownLanguages.includes(window.activeTextEditor.document.languageId)
|
|
||||||
? window.activeTextEditor.document.languageId
|
|
||||||
: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
let previousTimestamp = null;
|
|
||||||
if (this._state?.startTimestamp) previousTimestamp = this._state.startTimestamp;
|
|
||||||
|
|
||||||
this._state = {
|
|
||||||
...this._state,
|
|
||||||
details: await this._generateDetails('detailsDebugging', 'detailsEditing', 'detailsIdle', largeImageKey),
|
|
||||||
startTimestamp:
|
|
||||||
window.activeTextEditor && previousTimestamp && workspaceElapsedTime
|
|
||||||
? previousTimestamp
|
|
||||||
: window.activeTextEditor
|
|
||||||
? new Date().getTime()
|
|
||||||
: null,
|
|
||||||
state: await this._generateDetails(
|
|
||||||
'lowerDetailsDebugging',
|
|
||||||
'lowerDetailsEditing',
|
|
||||||
'lowerDetailsIdle',
|
|
||||||
largeImageKey,
|
|
||||||
),
|
|
||||||
largeImageKey: largeImageKey ? largeImageKey.image || largeImageKey : 'txt',
|
|
||||||
largeImageText: window.activeTextEditor
|
|
||||||
? this.client.config
|
|
||||||
.get<string>('largeImage')!
|
|
||||||
.replace('{lang}', largeImageKey ? largeImageKey.image || largeImageKey : 'txt')
|
|
||||||
.replace(
|
|
||||||
'{Lang}',
|
|
||||||
largeImageKey
|
|
||||||
? (largeImageKey.image || largeImageKey).toLowerCase().replace(/^\w/, (c: string) => c.toUpperCase())
|
|
||||||
: 'Txt',
|
|
||||||
)
|
|
||||||
.replace('{LANG}', largeImageKey ? (largeImageKey.image || largeImageKey).toUpperCase() : 'TXT') ||
|
|
||||||
window.activeTextEditor.document.languageId.padEnd(2, '\u200b')
|
|
||||||
: this.client.config.get<string>('largeImageIdle'),
|
|
||||||
smallImageKey: debug.activeDebugSession
|
|
||||||
? 'debug'
|
|
||||||
: env.appName.includes('Insiders')
|
|
||||||
? 'vscode-insiders'
|
|
||||||
: 'vscode',
|
|
||||||
smallImageText: this.client.config.get<string>('smallImage')!.replace('{appname}', env.appName),
|
|
||||||
};
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async allowSpectate() {
|
|
||||||
if (!this._state) return;
|
|
||||||
const liveshare = await vsls.getApi();
|
|
||||||
if (!liveshare) return;
|
|
||||||
const join = await liveshare.share({ suppressNotification: true, access: vsls.Access.ReadOnly });
|
|
||||||
this._state = {
|
|
||||||
...this._state,
|
|
||||||
spectateSecret: join ? Buffer.from(join.toString()).toString('base64') : undefined,
|
|
||||||
instance: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async disableSpectate() {
|
|
||||||
if (!this._state) return;
|
|
||||||
const liveshare = await vsls.getApi();
|
|
||||||
if (!liveshare) return;
|
|
||||||
await liveshare.end();
|
|
||||||
|
|
||||||
delete this._state.spectateSecret;
|
|
||||||
this._state.instance = false;
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async allowJoinRequests() {
|
|
||||||
if (!this._state) return;
|
|
||||||
const liveshare = await vsls.getApi();
|
|
||||||
if (!liveshare) return;
|
|
||||||
const join = await liveshare.share({ suppressNotification: true });
|
|
||||||
this._state = {
|
|
||||||
...this._state,
|
|
||||||
partyId: join ? join.query : undefined,
|
|
||||||
partySize: 1,
|
|
||||||
partyMax: 5,
|
|
||||||
joinSecret: join ? Buffer.from(join.toString()).toString('base64') : undefined,
|
|
||||||
instance: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async disableJoinRequests() {
|
|
||||||
if (!this._state) return;
|
|
||||||
const liveshare = await vsls.getApi();
|
|
||||||
if (!liveshare) return;
|
|
||||||
await liveshare.end();
|
|
||||||
|
|
||||||
delete this._state.partyId;
|
|
||||||
delete this._state.partySize;
|
|
||||||
delete this._state.partyMax;
|
|
||||||
delete this._state.joinSecret;
|
|
||||||
this._state.instance = false;
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public changePartyId(id?: string) {
|
|
||||||
if (!this._state) return;
|
|
||||||
if (!id) {
|
|
||||||
delete this._state.partyId;
|
|
||||||
delete this._state.partySize;
|
|
||||||
delete this._state.partyMax;
|
|
||||||
this._state.instance = false;
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
this._state = {
|
|
||||||
...this._state,
|
|
||||||
partyId: id,
|
|
||||||
partySize: this._state.partySize ? this._state.partySize + 1 : 1,
|
|
||||||
partyMax: 5,
|
|
||||||
instance: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public increasePartySize(size?: number) {
|
|
||||||
if (!this._state) return;
|
|
||||||
if (this._state.partySize === 5) return;
|
|
||||||
this._state = {
|
|
||||||
...this._state,
|
|
||||||
partySize: this._state.partySize ? this._state.partySize + 1 : size,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public decreasePartySize(size?: number) {
|
|
||||||
if (!this._state) return;
|
|
||||||
if (this._state.partySize === 1) return;
|
|
||||||
this._state = {
|
|
||||||
...this._state,
|
|
||||||
partySize: this._state.partySize ? this._state.partySize - 1 : size,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public dispose() {
|
|
||||||
this._state = null;
|
|
||||||
this.lastKnownFile = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _generateDetails(debugging: string, editing: string, idling: string, largeImageKey: any) {
|
|
||||||
let raw = this.client.config.get<string>(idling)!.replace('{null}', empty);
|
|
||||||
let filename = null;
|
|
||||||
let dirname = null;
|
|
||||||
let checkState = false;
|
|
||||||
let workspaceName = null;
|
|
||||||
let workspaceFolder = null;
|
|
||||||
let fullDirname = null;
|
|
||||||
if (window.activeTextEditor) {
|
|
||||||
filename = basename(window.activeTextEditor.document.fileName);
|
|
||||||
|
|
||||||
const { dir } = parse(window.activeTextEditor.document.fileName);
|
|
||||||
const split = dir.split(sep);
|
|
||||||
dirname = split[split.length - 1];
|
|
||||||
|
|
||||||
checkState = Boolean(workspace.getWorkspaceFolder(window.activeTextEditor.document.uri));
|
|
||||||
workspaceName = workspace.name;
|
|
||||||
workspaceFolder = checkState ? workspace.getWorkspaceFolder(window.activeTextEditor.document.uri) : null;
|
|
||||||
|
|
||||||
if (workspaceFolder) {
|
|
||||||
const { name } = workspaceFolder;
|
|
||||||
const relativePath = workspace.asRelativePath(window.activeTextEditor.document.fileName).split(sep);
|
|
||||||
relativePath.splice(-1, 1);
|
|
||||||
fullDirname = `${name}${sep}${relativePath.join(sep)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug.activeDebugSession) {
|
|
||||||
raw = this.client.config.get<string>(debugging)!;
|
|
||||||
} else {
|
|
||||||
raw = this.client.config.get<string>(editing)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { totalLines, size, currentLine, currentColumn, gitbranch, gitreponame } = await this._generateFileDetails(
|
|
||||||
raw,
|
|
||||||
);
|
|
||||||
raw = raw
|
|
||||||
.replace('{null}', empty)
|
|
||||||
.replace('{filename}', filename)
|
|
||||||
.replace('{dirname}', dirname)
|
|
||||||
.replace('{fulldirname}', fullDirname!)
|
|
||||||
.replace(
|
|
||||||
'{workspace}',
|
|
||||||
workspaceName
|
|
||||||
? workspaceName
|
|
||||||
: checkState && workspaceFolder
|
|
||||||
? workspaceFolder.name
|
|
||||||
: this.client.config.get<string>('lowerDetailsNotFound')!.replace('{null}', empty),
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
'{workspaceFolder}',
|
|
||||||
checkState && workspaceFolder
|
|
||||||
? workspaceFolder.name
|
|
||||||
: this.client.config.get<string>('lowerDetailsNotFound')!.replace('{null}', empty),
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
'{workspaceAndFolder}',
|
|
||||||
checkState && workspaceName && workspaceFolder
|
|
||||||
? `${workspaceName} - ${workspaceFolder.name}`
|
|
||||||
: this.client.config.get<string>('lowerDetailsNotFound')!.replace('{null}', empty),
|
|
||||||
)
|
|
||||||
.replace('{lang}', largeImageKey ? largeImageKey.image || largeImageKey : 'txt')
|
|
||||||
.replace(
|
|
||||||
'{Lang}',
|
|
||||||
largeImageKey
|
|
||||||
? (largeImageKey.image || largeImageKey).toLowerCase().replace(/^\w/, (c: string) => c.toUpperCase())
|
|
||||||
: 'Txt',
|
|
||||||
)
|
|
||||||
.replace('{LANG}', largeImageKey ? (largeImageKey.image || largeImageKey).toUpperCase() : 'TXT');
|
|
||||||
if (totalLines) raw = raw.replace('{totallines}', totalLines);
|
|
||||||
if (size) raw = raw.replace('{filesize}', size);
|
|
||||||
if (currentLine) raw = raw.replace('{currentline}', currentLine);
|
|
||||||
if (currentColumn) raw = raw.replace('{currentcolumn}', currentColumn);
|
|
||||||
if (gitbranch) raw = raw.replace('{gitbranch}', gitbranch);
|
|
||||||
if (gitreponame) raw = raw.replace('{gitreponame}', gitreponame);
|
|
||||||
}
|
|
||||||
|
|
||||||
return raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _generateFileDetails(str?: string) {
|
|
||||||
const fileDetail: FileDetail = {};
|
|
||||||
if (!str) return fileDetail;
|
|
||||||
|
|
||||||
if (window.activeTextEditor) {
|
|
||||||
if (str.includes('{totallines}')) {
|
|
||||||
fileDetail.totalLines = window.activeTextEditor.document.lineCount.toLocaleString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str.includes('{currentline}')) {
|
|
||||||
fileDetail.currentLine = (window.activeTextEditor.selection.active.line + 1).toLocaleString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str.includes('{currentcolumn}')) {
|
|
||||||
fileDetail.currentColumn = (window.activeTextEditor.selection.active.character + 1).toLocaleString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str.includes('{filesize}')) {
|
|
||||||
let currentDivision = 0;
|
|
||||||
let { size } = await workspace.fs.stat(window.activeTextEditor.document.uri);
|
|
||||||
const originalSize = size;
|
|
||||||
if (originalSize > 1000) {
|
|
||||||
size /= 1000;
|
|
||||||
currentDivision++;
|
|
||||||
while (size > 1000) {
|
|
||||||
currentDivision++;
|
|
||||||
size /= 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fileDetail.size = `${originalSize > 1000 ? size.toFixed(2) : size}${sizes[currentDivision]}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str.includes('{gitbranch}')) {
|
|
||||||
if (this.client.git?.repositories.length) {
|
|
||||||
fileDetail.gitbranch = this.client.git.repositories.find((repo) => repo.ui.selected)!.state.HEAD!.name;
|
|
||||||
} else {
|
|
||||||
fileDetail.gitbranch = 'Unknown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str.includes('{gitreponame}')) {
|
|
||||||
if (this.client.git?.repositories.length) {
|
|
||||||
fileDetail.gitreponame = this.client.git.repositories
|
|
||||||
.find((repo) => repo.ui.selected)!
|
|
||||||
.state.remotes[0].fetchUrl!.split('/')[1]
|
|
||||||
.replace('.git', '');
|
|
||||||
} else {
|
|
||||||
fileDetail.gitreponame = 'Unknown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileDetail;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { OutputChannel, window } from 'vscode';
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
export default class Logger {
|
|
||||||
private static output?: OutputChannel;
|
|
||||||
|
|
||||||
public static log(message: string) {
|
|
||||||
if (!this.output) {
|
|
||||||
this.output = window.createOutputChannel('Discord Presence');
|
|
||||||
}
|
|
||||||
this.output.appendLine(message);
|
|
||||||
}
|
|
||||||
}
|
|
56
src/util.ts
Normal file
56
src/util.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { basename } from 'path';
|
||||||
|
import { TextDocument, workspace, WorkspaceConfiguration } from 'vscode';
|
||||||
|
|
||||||
|
import { KNOWN_EXTENSIONS, KNOWN_LANGUAGES } from './constants';
|
||||||
|
|
||||||
|
type WorkspaceExtensionConfigurationuration = WorkspaceConfiguration & {
|
||||||
|
enabled: boolean;
|
||||||
|
details_editing: string;
|
||||||
|
details_debugging: string;
|
||||||
|
details_idling: string;
|
||||||
|
lower_details_editing: string;
|
||||||
|
lower_details_debugging: string;
|
||||||
|
lower_details_idling: string;
|
||||||
|
lower_details_no_workspace_found: string;
|
||||||
|
large_image: string;
|
||||||
|
large_image_idling: string;
|
||||||
|
small_image: string;
|
||||||
|
suppress_notifications: boolean;
|
||||||
|
workspace_elapsed_time: boolean;
|
||||||
|
workspace_exclude_patterns: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getConfig() {
|
||||||
|
return workspace.getConfiguration('discord') as WorkspaceExtensionConfigurationuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toLower = (str: string) => str.toLocaleLowerCase();
|
||||||
|
|
||||||
|
export const toUpper = (str: string) => str.toLocaleUpperCase();
|
||||||
|
|
||||||
|
export const toTitle = (str: string) => toLower(str).replace(/^\w/, (c) => toUpper(c));
|
||||||
|
|
||||||
|
export function resolveFileIcon(document: TextDocument) {
|
||||||
|
const filename = basename(document.fileName);
|
||||||
|
const findKnownExtension = Object.keys(KNOWN_EXTENSIONS).find((key) => {
|
||||||
|
if (filename.endsWith(key)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = /^\/(.*)\/([mgiy]+)$/.exec(key);
|
||||||
|
if (!match) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const regex = new RegExp(match[1], match[2]);
|
||||||
|
return regex.test(filename);
|
||||||
|
});
|
||||||
|
const findKnownLanguage = KNOWN_LANGUAGES.find((key) => key.language === document.languageId);
|
||||||
|
const fileIcon = findKnownExtension
|
||||||
|
? KNOWN_EXTENSIONS[findKnownExtension]
|
||||||
|
: findKnownLanguage
|
||||||
|
? findKnownLanguage.image
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return typeof fileIcon === 'string' ? fileIcon : fileIcon?.image ?? 'text';
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowJs": true,
|
"allowJs": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"**/*.ts",
|
"**/*.ts",
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
"**/*.test.ts",
|
"**/*.test.ts",
|
||||||
"**/*.test.js",
|
"**/*.test.js",
|
||||||
"**/*.spec.ts",
|
"**/*.spec.ts",
|
||||||
"**/*.spec.js",
|
"**/*.spec.js"
|
||||||
],
|
],
|
||||||
"exclude": []
|
"exclude": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
"removeComments": false,
|
"removeComments": false,
|
||||||
"alwaysStrict": true,
|
"alwaysStrict": true,
|
||||||
"pretty": true,
|
"pretty": true,
|
||||||
"target": "es2017",
|
"target": "ES2019",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"lib": [
|
"lib": ["ESNext"],
|
||||||
"ESNext"
|
|
||||||
],
|
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"inlineSources": true,
|
"inlineSources": true,
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||||
|
|
||||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
/** @type {import('webpack').Configuration} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: './src/extension.ts',
|
entry: './src/extension.ts',
|
||||||
|
|
Loading…
Reference in a new issue