├── .eslintrc.js ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── .vscodeignore ├── LICENSE ├── README.md ├── image └── icon.png ├── package.json ├── src ├── api.ts ├── commands.ts ├── const.ts ├── extension.ts ├── types │ ├── rambdax.d.ts │ └── vcslack.d.ts └── utils.ts ├── test ├── extension.test.js └── index.js ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserOptions: { 3 | ecmaVersion: '2018', 4 | sourceType: 'module', 5 | }, 6 | plugins: [ 7 | 'prettier' 8 | ], 9 | extends: [ 10 | 'prettier', 11 | ], 12 | env: { 13 | es6: true, 14 | node: true 15 | }, 16 | rules: { 17 | 'prettier/prettier': ['error', { 18 | singleQuote: true, 19 | semi: false, 20 | bracketSpacing: true 21 | }] 22 | }, 23 | overrides: [ 24 | { 25 | files: ['**/*.{ts,tsx}'], 26 | parser: '@typescript-eslint/parser', 27 | plugins: [ 28 | '@typescript-eslint', 29 | ], 30 | extends: [ 31 | 'plugin:@typescript-eslint/recommended', 32 | 'prettier/@typescript-eslint', 33 | ], 34 | rules: { 35 | '@typescript-eslint/explicit-function-return-type': 0, 36 | '@typescript-eslint/no-explicit-any': 0, 37 | '@typescript-eslint/no-use-before-define': 0, 38 | }, 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | out 3 | .DS_Store 4 | lib 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | { 3 | "version": "0.1.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], 11 | "stopOnEntry": false 12 | }, 13 | { 14 | "name": "Launch Tests", 15 | "type": "extensionHost", 16 | "request": "launch", 17 | "runtimeExecutable": "${execPath}", 18 | "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/test" ], 19 | "stopOnEntry": false 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "eslint.enable": true 4 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | typings/** 3 | test/** 4 | node_modules 5 | .gitignore 6 | jsconfig.json 7 | webpack.config.js 8 | vsc-extension-quickstart.md 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Daniel Veremchuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VSCode -> Slack 2 | 3 | ![How To Use](https://thumbs.gfycat.com/PoliteRadiantEft-size_restricted.gif) 4 | 5 | You tired of copying your code then going to Slack to copy it only to realize that it doesn't automatically format code? That you have to manually push the little paperclip in the corner, select "Create new...", click on "Code or text snippet", then you have to paste, select the right format for your code because Slack's automatic code detection SUCKS? 6 | 7 | Rejoice, there's a solution for you! Just highlight the code you want to send, bring up the Command Palette, type "VCSlack", pick your team and channel, all fuzzyfind searchable, and off you go! No need for your hands to leave the keyboard. 8 | 9 | ## Features 10 | 11 | - 🔂 Automatic sending of file if nothing highlighted 12 | - 🤟 Sends highlighted editor text 13 | - 📍 Shows the workspace and relative path of file so your coworkers can find it 14 | - 🧠 Syntax Detection and syntax normalization for Slack 15 | - 🔥 Fast! Cached in VSCode on every load 16 | - 🕺💃🧚‍♀️ Support for multiple Slack teams 17 | 18 | ## Installation 19 | 20 | 1. Open command palette ([Shift] + [CMD(⌘)/Ctrl] + [P]) 21 | 2. select "Extensions: Install Extension". 22 | 3. Type "VCSlack" and click install button. 23 | 24 | ## Settings 25 | 26 | To add your team(s): 27 | 28 | 1. Get a Slack [legacy token](https://api.slack.com/custom-integrations/legacy-tokens) 29 | 2. Open User Setting (File > Preferences > User Settings or [CMD(⌘)/Ctrl] + [,]) 30 | 3. Search for "VCSlack" 31 | 4. Click "Edit in settings.json" 32 | 5. Add tokens in following format: 33 | 34 | ```json 35 | "vcslack.selfToken": [ 36 | "xoxp-3915.....", 37 | "xoxp-69420....", 38 | ], 39 | ``` 40 | 41 | ## Using VCSlack 42 | 43 | 1. Have an open document 44 | 2. Highlight the text you wish to send, if nothign is highlighted, it will send entire document 45 | 3. Open command palette (Open command palette ([Shift] + [CMD(⌘)/Ctrl] + [P]) 46 | 4. Type "VCSlack" 47 | 5. Select Slack team then channel or user 48 | 6. It will send the snippet and automatically attempt to deduce the language, if it fails, it will send as plain text 49 | -------------------------------------------------------------------------------- /image/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verydanny/vcslack/0c005b05ab51087fec8d2421dec5334850155164/image/icon.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcslack", 3 | "displayName": "VCSlack", 4 | "description": "send snippet or text to slack", 5 | "version": "2.7.1", 6 | "publisher": "verydanny", 7 | "homepage": "https://github.com/verydanny/vcslack/blob/master/README.md", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/verydanny/vcslack" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/verydanny/vcslack/issues" 14 | }, 15 | "license": "MIT", 16 | "engines": { 17 | "vscode": "^1.40.0" 18 | }, 19 | "icon": "image/icon.png", 20 | "categories": [ 21 | "Other" 22 | ], 23 | "author": { 24 | "name": "Daniil Veremchuk", 25 | "email": "daniel@verydanny.com", 26 | "url": "https://github.com/verydanny/" 27 | }, 28 | "keywords": [ 29 | "Slack", 30 | "chat", 31 | "communication", 32 | "collaboration", 33 | "messenger", 34 | "slack snippets", 35 | "snippets" 36 | ], 37 | "activationEvents": [ 38 | "*", 39 | "onCommand:vcslack.sendSnippet" 40 | ], 41 | "files": [ 42 | "./lib" 43 | ], 44 | "main": "./lib/extension.js", 45 | "contributes": { 46 | "commands": [ 47 | { 48 | "command": "vcslack.sendSnippet", 49 | "title": "VCSlack: Send Snippet" 50 | } 51 | ], 52 | "configuration": { 53 | "type": "object", 54 | "title": "VCSlack configuration", 55 | "properties": { 56 | "vcslack.selfToken": { 57 | "type": "array", 58 | "description": "Specify the tokens of your slack team" 59 | } 60 | } 61 | } 62 | }, 63 | "scripts": { 64 | "vscode:prepublish": "rm -rf lib && yarn webpack --mode production", 65 | "test-compile": "rm -r lib && tsc -p ./", 66 | "watch": "rm -r lib && tsc -watch -p ./", 67 | "webpack-prod": "rm -r lib && webpack --mode production", 68 | "webpack-dev": "rm -r lib && webpack --mode development --watch", 69 | "postinstall": "node ./node_modules/vscode/bin/install", 70 | "test": "node ./node_modules/vscode/bin/test", 71 | "lint": "eslint src/**/* --ignore-pattern src/**/*.d.ts", 72 | "eslint-check": "eslint --print-config path/to/main.js | eslint-config-prettier-check" 73 | }, 74 | "devDependencies": { 75 | "@types/lodash": "^4.14.150", 76 | "@types/mocha": "^7.0.2", 77 | "@types/phin": "^3.4.0", 78 | "@types/request": "^2.48.4", 79 | "@types/request-promise": "^4.1.46", 80 | "@types/request-promise-native": "^1.0.17", 81 | "@typescript-eslint/eslint-plugin": "^2.29.0", 82 | "@typescript-eslint/parser": "^2.29.0", 83 | "babel-eslint": "^10.1.0", 84 | "eslint": "^6.8.0", 85 | "eslint-config-prettier": "^6.11.0", 86 | "eslint-plugin-prettier": "^3.1.3", 87 | "mocha": "^7.1.1", 88 | "phin": "^3.4.1", 89 | "prettier": "^2.0.5", 90 | "rambdax": "^3.7.0", 91 | "request": "^2.88.2", 92 | "request-promise-native": "^1.0.8", 93 | "ts-loader": "^7.0.1", 94 | "typescript": "^3.8.3", 95 | "vscode": "^1.1.36", 96 | "webpack": "^4.43.0", 97 | "webpack-bundle-analyzer": "^3.7.0", 98 | "webpack-cli": "^3.3.11" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/api.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode' 2 | import phin from 'phin' 3 | import { pipe, resolve, mapAsync } from 'rambdax' 4 | import { getText, buildFilename } from './utils' 5 | import { 6 | noSelectionOrDocument, 7 | noChannelId, 8 | checkTokenPleaseError 9 | } from './const' 10 | 11 | import { 12 | Team, 13 | Channel, 14 | ChannelList, 15 | DataT, 16 | Member, 17 | Group, 18 | SlackFileTypes 19 | } from './types/vcslack' 20 | 21 | export const SLACK_API = { 22 | post: 'https://slack.com/api/', 23 | fileUpload: 'files.upload', 24 | apiChatPost: 'chat.postMessage', 25 | teamInfo: 'team.info', 26 | groupsList: 'groups.list', 27 | channelsList: 'channels.list', 28 | userList: 'users.list' 29 | } 30 | 31 | export const fetchTeams = async (token: string) => { 32 | const form = { token: token } 33 | 34 | const data = await phin({ 35 | url: `${SLACK_API.post + SLACK_API.teamInfo}`, 36 | form, 37 | method: 'POST', 38 | parse: 'json' 39 | }) 40 | .then(res => res.body) 41 | .catch(e => vscode.window.showErrorMessage(e)) 42 | 43 | if (data && (data as any).team && (data as any).team.name) { 44 | return { 45 | name: (data as any).team.name, 46 | token: token 47 | } 48 | } 49 | 50 | return vscode.window.showErrorMessage(checkTokenPleaseError) 51 | } 52 | 53 | const organizeUserInfo = (data: any) => { 54 | if (data) { 55 | if (data && data.channels) { 56 | return data.channels.map((channel: Channel) => ({ 57 | id: channel.id, 58 | label: `#${channel.name}`, 59 | detail: 60 | channel.purpose && channel.purpose.value ? channel.purpose.value : '', 61 | description: '' 62 | })) 63 | } 64 | 65 | if (data.members) { 66 | return data.members.map((member: Member) => ({ 67 | id: member.id, 68 | label: `@${member.name}`, 69 | detail: '', 70 | description: 71 | member.profile && member.profile.real_name 72 | ? member.profile.real_name 73 | : member.real_name 74 | ? member.real_name 75 | : member.name 76 | })) 77 | } 78 | 79 | if (data.groups) { 80 | return data.groups.map((group: Group) => { 81 | if (group.purpose && group.purpose.value) { 82 | const groupPurpose = group.purpose.value.substr(22) 83 | 84 | return { 85 | id: group.id, 86 | label: `Group Messaging:`, 87 | detail: '', 88 | description: `${groupPurpose}` 89 | } 90 | } 91 | 92 | return { 93 | id: group.id, 94 | label: `Group Messaging:`, 95 | detail: '', 96 | description: `${group.name}` 97 | } 98 | }) 99 | } 100 | } 101 | } 102 | 103 | export const getPostList = async ({ 104 | name, 105 | token 106 | }: { 107 | name: string 108 | token: string 109 | }) => { 110 | const channels = SLACK_API.post + SLACK_API.channelsList 111 | const groups = SLACK_API.post + SLACK_API.groupsList 112 | const users = SLACK_API.post + SLACK_API.userList 113 | const form = { token: token } 114 | 115 | return { 116 | name, 117 | token, 118 | channelList: (await Promise.all( 119 | [channels, users, groups].map( 120 | async url => 121 | await phin({ 122 | url, 123 | form, 124 | method: 'POST', 125 | parse: 'json' 126 | }) 127 | .then(res => organizeUserInfo(res.body)) 128 | .catch(e => { 129 | if (e) { 130 | vscode.window 131 | .showErrorMessage( 132 | `Error fetching ${url}, Report Issues: https://github.com/verydanny/vcslack/issues`, 133 | 'Copy Error To Clipboard' 134 | ) 135 | .then(result => { 136 | if (result === 'Copy Error To Clipboard') { 137 | vscode.env.clipboard.writeText(`${url}, ${e.toString()}`) 138 | } 139 | }) 140 | } 141 | }) 142 | ) 143 | )).flat() 144 | } 145 | } 146 | 147 | export const buildTeamData = pipe( 148 | mapAsync(fetchTeams), 149 | resolve(mapAsync(getPostList)) 150 | ) as (x: any[]) => Promise 151 | 152 | export const sendData = async ( 153 | matchingChannel: ChannelList, 154 | { token }: Team 155 | ) => { 156 | if (!vscode.window.activeTextEditor) { 157 | return 158 | } 159 | 160 | const { selection, document } = vscode.window.activeTextEditor 161 | const { fileName: filenameWithPath, languageId: filetype } = document 162 | const content = getText(selection, document.getText) 163 | const channels = matchingChannel && matchingChannel.id 164 | 165 | if (!content) { 166 | return vscode.window.showErrorMessage(noSelectionOrDocument) 167 | } else if (!channels) { 168 | return vscode.window.showErrorMessage(noChannelId) 169 | } 170 | 171 | const filedetails = buildFilename( 172 | filetype as keyof SlackFileTypes, 173 | filenameWithPath, 174 | document 175 | ) 176 | const url = SLACK_API.post + SLACK_API.fileUpload 177 | const lineNum = selection.start.line + 1 178 | const data: DataT = { 179 | token, 180 | channels, 181 | content, 182 | filename: filedetails.cleanedFilename, 183 | filetype: filedetails.slackCompatible, 184 | title: filedetails.path 185 | ? `${filedetails.path}:${lineNum} sent from VCSlack` 186 | : `${filedetails.cleanedFilename}:${lineNum} sent from VCSlack` 187 | } 188 | 189 | return phin({ 190 | url, 191 | form: data, 192 | method: 'POST', 193 | parse: 'json' 194 | }) 195 | .then(() => vscode.window.showInformationMessage('Snippet Sent Success!')) 196 | .catch(async e => { 197 | if (e) { 198 | vscode.window 199 | .showErrorMessage( 200 | `Error sending snippet to ${url}, Report Issues: https://github.com/verydanny/vcslack/issues`, 201 | 'Copy Error To Clipboard' 202 | ) 203 | .then(result => { 204 | if (result === 'Copy Error To Clipboard') { 205 | const error = { 206 | errorDetails: e.toString(), 207 | sendData: data, 208 | filedetails 209 | } 210 | 211 | vscode.env.clipboard.writeText(JSON.stringify(error)) 212 | } 213 | }) 214 | } 215 | }) 216 | } 217 | -------------------------------------------------------------------------------- /src/commands.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode' 2 | import { legacyTokenError, noOpenDocumentError } from './const' 3 | import { buildTeamData, sendData } from './api' 4 | import { Team } from './types/vcslack' 5 | 6 | export const reloadConfig = async (context: vscode.ExtensionContext) => { 7 | const newConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration( 8 | 'vcslack' 9 | ) 10 | const newTokens: string[] | undefined = newConfig.get('selfToken') 11 | 12 | if (!newTokens || (Array.isArray(newTokens) && newTokens.length === 0)) { 13 | vscode.window.showErrorMessage(legacyTokenError) 14 | } else { 15 | context.globalState.update('tokens', newTokens) 16 | context.globalState.update('teams', await buildTeamData([...newTokens])) 17 | } 18 | } 19 | 20 | export const selectTeam = async (context: vscode.ExtensionContext) => { 21 | if (typeof vscode.window.activeTextEditor === 'undefined') { 22 | return vscode.window.showErrorMessage(noOpenDocumentError) 23 | } 24 | 25 | const tokens = context.globalState.get('tokens') as string[] 26 | const teams = context.globalState.get('teams') as Team[] 27 | const options = { 28 | placeHolder: 'Which team/user would you like to send a snippet to?', 29 | ignoreFocusOut: true 30 | } 31 | 32 | if (!tokens || (Array.isArray(tokens) && tokens.length === 0)) { 33 | return vscode.window.showErrorMessage(legacyTokenError) 34 | } 35 | 36 | if (teams && teams.length > 0) { 37 | const names = teams 38 | .filter(x => x && x.name) 39 | .map(x => x.name) 40 | .concat(['Missing Team? Reload VCSlack Teams']) 41 | 42 | return vscode.window 43 | .showQuickPick(names, options) 44 | .then(selectedChannel => selectChannel(selectedChannel, context)) 45 | } 46 | 47 | if (tokens && teams.length === 0) { 48 | context.globalState.update('teams', await buildTeamData([...tokens])) 49 | 50 | const newTeams = context.globalState.get('teams') as Team[] 51 | const names = newTeams 52 | .filter(x => x && x.name) 53 | .map(x => x.name) 54 | .concat(['Missing Team? Reload VCSlack Teams']) 55 | 56 | return vscode.window 57 | .showQuickPick(names, options) 58 | .then(selectedChannel => selectChannel(selectedChannel, context)) 59 | } 60 | 61 | return 62 | } 63 | 64 | const selectChannel = async ( 65 | selectedChannel: string | undefined, 66 | context: vscode.ExtensionContext 67 | ): Promise => { 68 | const tokens = context.globalState.get('tokens') as string[] 69 | const teams = context.globalState.get('teams') as Team[] 70 | 71 | if (selectedChannel === 'Missing Team? Reload VCSlack Teams') { 72 | vscode.window.showInformationMessage('VCSlack: Fetching team data') 73 | context.globalState.update('teams', await buildTeamData([...tokens])) 74 | 75 | return selectTeam(context) 76 | } 77 | 78 | if (teams.length > 0) { 79 | const [matchingTeam] = teams.filter(x => x.name === selectedChannel) 80 | 81 | if (matchingTeam && matchingTeam.channelList) { 82 | const channelList = matchingTeam.channelList.map( 83 | ({ label, description, id, detail }) => ({ 84 | label: label ? label : 'Unknown', 85 | description, 86 | detail, 87 | id 88 | }) 89 | ) 90 | 91 | return vscode.window 92 | .showQuickPick(channelList, { 93 | matchOnDescription: true, 94 | matchOnDetail: false, 95 | ignoreFocusOut: true, 96 | placeHolder: 'Please select a Slack channel, group, or user' 97 | }) 98 | .then( 99 | matchingChannel => 100 | matchingChannel && sendData(matchingChannel, matchingTeam) 101 | ) 102 | } 103 | 104 | return 105 | } 106 | 107 | return 108 | } 109 | -------------------------------------------------------------------------------- /src/const.ts: -------------------------------------------------------------------------------- 1 | import { SlackFileTypes } from './types/vcslack' 2 | 3 | export const defaultTokens = ['your slack token 1', 'your slack token 2'] 4 | 5 | export const checkTokenPleaseError = ` 6 | VCSlack Error: Could not fetch Slack teams. Please check your token 7 | ` 8 | 9 | export const legacyTokenError = ` 10 | VCSlack Error: Please add a Slack legacy token before proceeding, 11 | README: https://github.com/verydanny/vcslack/blob/master/README.md 12 | ` 13 | 14 | export const legacyTokenHelpfulError = ` 15 | VCSlack Error: You should probably add some Slack tokens! 16 | 1. Go to settings 17 | 2. Search for "vcslack" 18 | 3. Click edit in settings.json 19 | 4. Add VCSlack setting in following format: 20 | "vcslack.selfToken": [ 21 | "xoxp-358484..." 22 | ] 23 | ` 24 | 25 | export const noOpenDocumentError = ` 26 | VCSlack Error: Can't send snippet with no open code document! 27 | ` 28 | 29 | export const noSelectionOrDocument = ` 30 | VCSlack Error: Your selection/document appears to be empty 31 | ` 32 | 33 | export const noChannelId = ` 34 | VCSlack Error: The channel/user you selected seems to be invalid 35 | ` 36 | 37 | export const filetypeMap: SlackFileTypes = { 38 | plaintext: { 39 | slackCompatible: 'text' 40 | }, 41 | scss: { 42 | slackCompatible: 'sass' 43 | }, 44 | javascriptreact: { 45 | slackCompatible: 'jsx' 46 | }, 47 | typescriptreact: { 48 | slackCompatible: 'JSX', // @TODO: Slack has horrible support for TSX, JSX works for now though 49 | actual: 'tsx' 50 | }, 51 | auto: { 52 | slackCompatible: 'auto' 53 | }, 54 | text: { 55 | slackCompatible: 'text' 56 | }, 57 | ai: { 58 | slackCompatible: 'ai' 59 | }, 60 | apk: { 61 | slackCompatible: 'apk' 62 | }, 63 | applescript: { 64 | slackCompatible: 'applescript' 65 | }, 66 | binary: { 67 | slackCompatible: 'binary' 68 | }, 69 | bmp: { 70 | slackCompatible: 'bmp' 71 | }, 72 | boxnote: { 73 | slackCompatible: 'boxnote' 74 | }, 75 | c: { 76 | slackCompatible: 'c' 77 | }, 78 | csharp: { 79 | slackCompatible: 'csharp' 80 | }, 81 | cpp: { 82 | slackCompatible: 'cpp' 83 | }, 84 | css: { 85 | slackCompatible: 'css' 86 | }, 87 | csv: { 88 | slackCompatible: 'csv' 89 | }, 90 | clojure: { 91 | slackCompatible: 'clojure' 92 | }, 93 | coffeescript: { 94 | slackCompatible: 'coffeescript' 95 | }, 96 | cfm: { 97 | slackCompatible: 'cfm' 98 | }, 99 | d: { 100 | slackCompatible: 'd' 101 | }, 102 | dart: { 103 | slackCompatible: 'dart' 104 | }, 105 | diff: { 106 | slackCompatible: 'diff' 107 | }, 108 | doc: { 109 | slackCompatible: 'doc' 110 | }, 111 | docx: { 112 | slackCompatible: 'docx' 113 | }, 114 | dockerfile: { 115 | slackCompatible: 'dockerfile' 116 | }, 117 | dotx: { 118 | slackCompatible: 'dotx' 119 | }, 120 | email: { 121 | slackCompatible: 'email' 122 | }, 123 | eps: { 124 | slackCompatible: 'eps' 125 | }, 126 | epub: { 127 | slackCompatible: 'epub' 128 | }, 129 | erlang: { 130 | slackCompatible: 'erlang' 131 | }, 132 | fla: { 133 | slackCompatible: 'fla' 134 | }, 135 | flv: { 136 | slackCompatible: 'flv' 137 | }, 138 | fsharp: { 139 | slackCompatible: 'fsharp' 140 | }, 141 | fortran: { 142 | slackCompatible: 'fortran' 143 | }, 144 | gdoc: { 145 | slackCompatible: 'gdoc' 146 | }, 147 | gdraw: { 148 | slackCompatible: 'gdraw' 149 | }, 150 | gif: { 151 | slackCompatible: 'gif' 152 | }, 153 | go: { 154 | slackCompatible: 'go' 155 | }, 156 | gpres: { 157 | slackCompatible: 'gpres' 158 | }, 159 | groovy: { 160 | slackCompatible: 'groovy' 161 | }, 162 | gsheet: { 163 | slackCompatible: 'gsheet' 164 | }, 165 | gzip: { 166 | slackCompatible: 'gzip' 167 | }, 168 | html: { 169 | slackCompatible: 'html' 170 | }, 171 | handlebars: { 172 | slackCompatible: 'handlebars' 173 | }, 174 | haskell: { 175 | slackCompatible: 'haskell' 176 | }, 177 | haxe: { 178 | slackCompatible: 'haxe' 179 | }, 180 | indd: { 181 | slackCompatible: 'indd' 182 | }, 183 | java: { 184 | slackCompatible: 'java' 185 | }, 186 | javascript: { 187 | slackCompatible: 'javascript' 188 | }, 189 | jpg: { 190 | slackCompatible: 'jpg' 191 | }, 192 | keynote: { 193 | slackCompatible: 'keynote' 194 | }, 195 | kotlin: { 196 | slackCompatible: 'kotlin' 197 | }, 198 | latex: { 199 | slackCompatible: 'latex' 200 | }, 201 | lisp: { 202 | slackCompatible: 'lisp' 203 | }, 204 | lua: { 205 | slackCompatible: 'lua' 206 | }, 207 | m4a: { 208 | slackCompatible: 'm4a' 209 | }, 210 | markdown: { 211 | slackCompatible: 'markdown' 212 | }, 213 | matlab: { 214 | slackCompatible: 'matlab' 215 | }, 216 | mhtml: { 217 | slackCompatible: 'mhtml' 218 | }, 219 | mkv: { 220 | slackCompatible: 'mkv' 221 | }, 222 | mov: { 223 | slackCompatible: 'mov' 224 | }, 225 | mp3: { 226 | slackCompatible: 'mp3' 227 | }, 228 | mp4: { 229 | slackCompatible: 'mp4' 230 | }, 231 | mpg: { 232 | slackCompatible: 'mpg' 233 | }, 234 | mumps: { 235 | slackCompatible: 'mumps' 236 | }, 237 | numbers: { 238 | slackCompatible: 'numbers' 239 | }, 240 | nzb: { 241 | slackCompatible: 'nzb' 242 | }, 243 | objc: { 244 | slackCompatible: 'objc' 245 | }, 246 | ocaml: { 247 | slackCompatible: 'ocaml' 248 | }, 249 | odg: { 250 | slackCompatible: 'odg' 251 | }, 252 | odi: { 253 | slackCompatible: 'odi' 254 | }, 255 | odp: { 256 | slackCompatible: 'odp' 257 | }, 258 | ods: { 259 | slackCompatible: 'ods' 260 | }, 261 | odt: { 262 | slackCompatible: 'odt' 263 | }, 264 | ogg: { 265 | slackCompatible: 'ogg' 266 | }, 267 | ogv: { 268 | slackCompatible: 'ogv' 269 | }, 270 | pages: { 271 | slackCompatible: 'pages' 272 | }, 273 | pascal: { 274 | slackCompatible: 'pascal' 275 | }, 276 | pdf: { 277 | slackCompatible: 'pdf' 278 | }, 279 | perl: { 280 | slackCompatible: 'perl' 281 | }, 282 | php: { 283 | slackCompatible: 'php' 284 | }, 285 | pig: { 286 | slackCompatible: 'pig' 287 | }, 288 | png: { 289 | slackCompatible: 'png' 290 | }, 291 | post: { 292 | slackCompatible: 'post' 293 | }, 294 | powershell: { 295 | slackCompatible: 'powershell' 296 | }, 297 | ppt: { 298 | slackCompatible: 'ppt' 299 | }, 300 | pptx: { 301 | slackCompatible: 'pptx' 302 | }, 303 | psd: { 304 | slackCompatible: 'psd' 305 | }, 306 | puppet: { 307 | slackCompatible: 'puppet' 308 | }, 309 | python: { 310 | slackCompatible: 'python' 311 | }, 312 | qtz: { 313 | slackCompatible: 'qtz' 314 | }, 315 | r: { 316 | slackCompatible: 'r' 317 | }, 318 | rtf: { 319 | slackCompatible: 'rtf' 320 | }, 321 | ruby: { 322 | slackCompatible: 'ruby' 323 | }, 324 | rust: { 325 | slackCompatible: 'rust' 326 | }, 327 | sql: { 328 | slackCompatible: 'sql' 329 | }, 330 | sass: { 331 | slackCompatible: 'sass' 332 | }, 333 | scala: { 334 | slackCompatible: 'scala' 335 | }, 336 | scheme: { 337 | slackCompatible: 'scheme' 338 | }, 339 | sketch: { 340 | slackCompatible: 'sketch' 341 | }, 342 | shell: { 343 | slackCompatible: 'shell' 344 | }, 345 | smalltalk: { 346 | slackCompatible: 'smalltalk' 347 | }, 348 | svg: { 349 | slackCompatible: 'svg' 350 | }, 351 | swf: { 352 | slackCompatible: 'swf' 353 | }, 354 | swift: { 355 | slackCompatible: 'swift' 356 | }, 357 | tar: { 358 | slackCompatible: 'tar' 359 | }, 360 | tiff: { 361 | slackCompatible: 'tiff' 362 | }, 363 | tsv: { 364 | slackCompatible: 'tsv' 365 | }, 366 | vb: { 367 | slackCompatible: 'vb' 368 | }, 369 | vbscript: { 370 | slackCompatible: 'vbscript' 371 | }, 372 | vcard: { 373 | slackCompatible: 'vcard' 374 | }, 375 | velocity: { 376 | slackCompatible: 'velocity' 377 | }, 378 | verilog: { 379 | slackCompatible: 'verilog' 380 | }, 381 | wav: { 382 | slackCompatible: 'wav' 383 | }, 384 | webm: { 385 | slackCompatible: 'webm' 386 | }, 387 | wmv: { 388 | slackCompatible: 'wmv' 389 | }, 390 | xls: { 391 | slackCompatible: 'xls' 392 | }, 393 | xlsx: { 394 | slackCompatible: 'xlsx' 395 | }, 396 | xlsb: { 397 | slackCompatible: 'xlsb' 398 | }, 399 | xlsm: { 400 | slackCompatible: 'xlsm' 401 | }, 402 | xltx: { 403 | slackCompatible: 'xltx' 404 | }, 405 | xml: { 406 | slackCompatible: 'xml' 407 | }, 408 | yaml: { 409 | slackCompatible: 'yaml' 410 | }, 411 | zip: { 412 | slackCompatible: 'zip' 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode' 2 | import { legacyTokenHelpfulError } from './const' 3 | import { buildTeamData } from './api' 4 | import { reloadConfig, selectTeam } from './commands' 5 | 6 | export const activate = async (context: vscode.ExtensionContext) => { 7 | const config = vscode.workspace.getConfiguration('vcslack') 8 | const tokens: string[] | undefined = config.get('selfToken') 9 | 10 | if (!tokens || (Array.isArray(tokens) && tokens.length === 0)) { 11 | vscode.window.showErrorMessage(legacyTokenHelpfulError) 12 | } else { 13 | context.globalState.update('tokens', tokens) 14 | context.globalState.update('teams', await buildTeamData([...tokens])) 15 | } 16 | 17 | context.subscriptions.push( 18 | vscode.commands.registerCommand('vcslack.sendSnippet', () => 19 | selectTeam(context) 20 | ), 21 | vscode.workspace.onDidChangeConfiguration(() => reloadConfig(context)) 22 | ) 23 | } 24 | 25 | export const deactivate = () => {} 26 | -------------------------------------------------------------------------------- /src/types/rambdax.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'rambdax' { 2 | declare namespace R { 3 | // RAMBDA_START 4 | type RambdaTypes = 5 | | 'Async' 6 | | 'Array' 7 | | 'Boolean' 8 | | 'Function' 9 | | 'Null' 10 | | 'Number' 11 | | 'Object' 12 | | 'Promise' 13 | | 'RegExp' 14 | | 'String' 15 | | 'Undefined' 16 | 17 | type Func = (input: any) => T 18 | type Pred = (input: T) => boolean 19 | type Predicate = (input: T, index: number) => boolean 20 | type Fn = (x: In) => Out 21 | type FnTwo = (x: In, y: In) => Out 22 | type MapFn = (x: In, index: number) => Out 23 | 24 | type FilterFunction = (x: T, prop?: string, inputObj?: object) => boolean 25 | type MapFunction = (x: In, prop?: string, inputObj?: object) => Out 26 | type Omit = Pick> 27 | 28 | interface MapInterface { 29 | (list: T[]): T[] 30 | (obj: Dictionary): Dictionary 31 | } 32 | 33 | interface HeadObject { 34 | prop: string 35 | value: T 36 | } 37 | 38 | type IdentityFunction = (x: T) => T 39 | 40 | interface Filter { 41 | (list: T[]): T[] 42 | (obj: Dictionary): Dictionary 43 | } 44 | 45 | interface Dictionary { 46 | [index: string]: T 47 | } 48 | // RAMBDA_END 49 | // RAMBDAX_START 50 | type ArgumentTypes = T extends (...args: infer U) => infer R ? U : never 51 | type ReplaceReturnType = ( 52 | ...a: ArgumentTypes 53 | ) => TNewReturn 54 | 55 | type isfn = (x: any, y: any) => T 56 | 57 | interface Switchem { 58 | is: isfn> 59 | default: IdentityFunction 60 | } 61 | // RAMBDAX_END 62 | // RAMDA_START 63 | type Ord = number | string | boolean 64 | 65 | type Path = Array 66 | 67 | interface KeyValuePair extends Array { 68 | 0: K 69 | 1: V 70 | } 71 | 72 | type Arity1Fn = (a: any) => any 73 | 74 | interface CurriedTypeGuard2 { 75 | (t1: T1): (t2: T2) => t2 is R 76 | (t1: T1, t2: T2): t2 is R 77 | } 78 | 79 | interface CurriedTypeGuard3 { 80 | (t1: T1): CurriedTypeGuard2 81 | (t1: T1, t2: T2): (t3: T3) => t3 is R 82 | (t1: T1, t2: T2, t3: T3): t3 is R 83 | } 84 | 85 | interface CurriedTypeGuard4 { 86 | (t1: T1): CurriedTypeGuard3 87 | (t1: T1, t2: T2): CurriedTypeGuard2 88 | (t1: T1, t2: T2, t3: T3): (t4: T4) => t4 is R 89 | (t1: T1, t2: T2, t3: T3, t4: T4): t4 is R 90 | } 91 | 92 | interface CurriedTypeGuard5 { 93 | (t1: T1): CurriedTypeGuard4 94 | (t1: T1, t2: T2): CurriedTypeGuard3 95 | (t1: T1, t2: T2, t3: T3): CurriedTypeGuard2 96 | (t1: T1, t2: T2, t3: T3, t4: T4): (t5: T5) => t5 is R 97 | (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): t5 is R 98 | } 99 | 100 | interface CurriedTypeGuard6 { 101 | (t1: T1): CurriedTypeGuard5 102 | (t1: T1, t2: T2): CurriedTypeGuard4 103 | (t1: T1, t2: T2, t3: T3): CurriedTypeGuard3 104 | (t1: T1, t2: T2, t3: T3, t4: T4): CurriedTypeGuard2 105 | (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): (t6: T6) => t6 is R 106 | (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6): t6 is R 107 | } 108 | 109 | interface CurriedFunction2 { 110 | (t1: T1): (t2: T2) => R 111 | (t1: T1, t2: T2): R 112 | } 113 | 114 | interface CurriedFunction3 { 115 | (t1: T1): CurriedFunction2 116 | (t1: T1, t2: T2): (t3: T3) => R 117 | (t1: T1, t2: T2, t3: T3): R 118 | } 119 | 120 | interface CurriedFunction4 { 121 | (t1: T1): CurriedFunction3 122 | (t1: T1, t2: T2): CurriedFunction2 123 | (t1: T1, t2: T2, t3: T3): (t4: T4) => R 124 | (t1: T1, t2: T2, t3: T3, t4: T4): R 125 | } 126 | 127 | interface CurriedFunction5 { 128 | (t1: T1): CurriedFunction4 129 | (t1: T1, t2: T2): CurriedFunction3 130 | (t1: T1, t2: T2, t3: T3): CurriedFunction2 131 | (t1: T1, t2: T2, t3: T3, t4: T4): (t5: T5) => R 132 | (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): R 133 | } 134 | 135 | interface CurriedFunction6 { 136 | (t1: T1): CurriedFunction5 137 | (t1: T1, t2: T2): CurriedFunction4 138 | (t1: T1, t2: T2, t3: T3): CurriedFunction3 139 | (t1: T1, t2: T2, t3: T3, t4: T4): CurriedFunction2 140 | (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): (t6: T6) => R 141 | (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6): R 142 | } 143 | 144 | interface Reduced { 145 | [index: number]: any 146 | [index: string]: any 147 | } 148 | 149 | interface ObjectWithPromises { 150 | [key: string]: Promise 151 | } 152 | 153 | interface Schema { 154 | [key: string]: any 155 | } 156 | 157 | interface IsValid { 158 | input: object 159 | schema: Schema 160 | } 161 | 162 | type Async = (x: any) => Promise 163 | type AsyncWithProp = (x: any, prop?: string) => Promise 164 | 165 | interface TypedObject { 166 | [key: string]: T 167 | } 168 | // RAMDA_END 169 | interface X { 170 | // RAMBDAX_START 171 | allFalse(...input: Array): boolean 172 | anyFalse(...input: Array): boolean 173 | 174 | allTrue(...input: Array): boolean 175 | anyTrue(...input: Array): boolean 176 | 177 | allType(targetType: RambdaTypes): (...input: Array) => boolean 178 | anyType(targetType: RambdaTypes): (...input: Array) => boolean 179 | 180 | change(origin: object, path: string, changeData: any): object 181 | 182 | compact(x: any[]): T[] 183 | 184 | composeAsync( 185 | ...fns: Array | Function> 186 | ): (input: any) => Promise 187 | 188 | composed(...fnList: any[]): T 189 | 190 | count(target: T, list: any[]): number 191 | count(target: T): (list: any[]) => number 192 | 193 | debounce(fn: T, ms: number): ReplaceReturnType 194 | 195 | defaultToStrict(fallback: T, ...inputs: Array): T 196 | 197 | defaultToWhen(fallback: T, fn: Pred, ...inputs: Array): T 198 | 199 | delay(ms: number): Promise<'RAMBDAX_DELAY'> 200 | 201 | DELAY: 'RAMBDAX_DELAY' 202 | 203 | findInObject(fn: Function, obj: object): object 204 | findInObject(fn: Function): (obj: object) => object 205 | 206 | glue(input: string, glueString?: string): string 207 | 208 | getter(keyOrKeys: string | string[] | undefined): T 209 | setter(keyOrObject: string | object, value?: any): void 210 | reset(): void 211 | 212 | headObject(input: object): HeadObject 213 | 214 | hasPath(path: string | string[], input: object): boolean 215 | hasPath(path: string | string[]): (input: object) => boolean 216 | 217 | ifElseAsync( 218 | condition: Async | Function, 219 | ifFn: Async | Function, 220 | elseFn: Async | Function 221 | ): Async 222 | 223 | inject(toInjectAfterMarker: string, marker: string, input: string): string 224 | 225 | includesAny(targets: any[], stringOrList: string | any[]): boolean 226 | includesAny(targets: any[]): (stringOrList: string | any[]) => boolean 227 | 228 | includesType(targetType: RambdaTypes): (list: any[]) => boolean 229 | includesType(targetType: RambdaTypes, list: any[]): boolean 230 | 231 | isArray(input: any): boolean 232 | isFalsy(input: any): boolean 233 | isObject(input: any): boolean 234 | isString(input: any): boolean 235 | isType(targetType: RambdaTypes, input: any): boolean 236 | 237 | isPromise(maybePromiseOrAsync: any): boolean 238 | 239 | isFunction(maybePromiseFunctionOrAsync: any): boolean 240 | 241 | maybe(ifRule: any, whenIf: any, whenElse: any, maybeInput?: any): T 242 | 243 | mapAsync(fn: Async, list: any[]): Promise> 244 | mapAsync(fn: AsyncWithProp, obj: object): Promise> 245 | mapAsync(fn: Async): (list: any[]) => Promise> 246 | mapAsync(fn: AsyncWithProp): (obj: object) => Promise> 247 | 248 | mapFastAsync(fn: Async, list: any[]): Promise> 249 | mapFastAsync(fn: Async): (list: any[]) => Promise> 250 | 251 | mapToObject(fn: (input: T) => object, list: T[]): U 252 | mapToObject(fn: (input: T) => object): (list: T[]) => U 253 | 254 | memoize(fn: Function | Async): T 255 | 256 | mergeRight(x: object, y: object): object 257 | mergeRight(x: object): (y: object) => object 258 | 259 | mergeAll(input: object[]): object 260 | mergeDeep(slave: object, master: object): T 261 | 262 | nextIndex(index: number, list: any[]): number 263 | prevIndex(index: number, list: any[]): number 264 | 265 | opposite(fn: Fn): Fn 266 | 267 | ok(...inputs: any[]): (...rules: any[]) => true | never 268 | pass(...inputs: any[]): (...rules: any[]) => boolean 269 | isValid(x: IsValid): boolean 270 | isAttach(): boolean 271 | 272 | once(fn: Function): Function 273 | 274 | otherwise(fallback: Function, toResolve: Promise): Promise 275 | otherwise(fallback: Function): (toResolve: Promise) => Promise 276 | 277 | then(afterResolve: Function, toResolve: Promise): Promise 278 | then(toResolve: Function): (toResolve: Promise) => Promise 279 | 280 | resolve(afterResolve: Function, toResolve: Promise): Promise 281 | resolve(toResolve: Function): (toResolve: Promise) => Promise 282 | 283 | partition( 284 | rule: FilterFunction, 285 | input: Record 286 | ): [Record, Record] 287 | partition( 288 | rule: FilterFunction 289 | ): ( 290 | input: Record 291 | ) => [Record, Record] 292 | 293 | partition(rule: Predicate, input: Array): [Array, Array] 294 | partition( 295 | rule: Predicate 296 | ): (input: Array) => [Array, Array] 297 | 298 | pathEq(path: string | string[], target: any, obj: object): boolean 299 | pathEq(path: string | string[], target: any): (obj: object) => boolean 300 | 301 | piped(input: any, ...fnList: Function[]): T 302 | 303 | pipedAsync( 304 | input: any, 305 | ...fns: Array> 306 | ): Promise 307 | 308 | produce(conditions: any, input: any): T 309 | produce(conditions: any): (input: any) => T 310 | 311 | promiseAllObject(input: ObjectWithPromises): Promise 312 | 313 | random(minInclusive: number, maxInclusive: number): number 314 | 315 | remove( 316 | inputs: string | RegExp | Array, 317 | text: string 318 | ): string 319 | 320 | remove( 321 | inputs: string | RegExp | Array 322 | ): (text: string) => string 323 | 324 | renameProps(fromKeyToProp: object, input: object): object 325 | renameProps(fromKeyToProp: object): (input: object) => object 326 | 327 | s(): boolean 328 | 329 | shuffle(arr: T[]): T[] 330 | 331 | switcher(valueToMatch: any): Switchem 332 | 333 | tapAsync(fn: Function | Promise, input: T): T 334 | tapAsync(fn: Function | Promise): (input: T) => T 335 | 336 | then( 337 | createResultFn: Fn 338 | ): (createInputFn: Promise) => Promise 339 | then( 340 | createResultFn: Fn, 341 | createInputFn: Promise 342 | ): Promise 343 | 344 | throttle(fn: T, ms: number): ReplaceReturnType 345 | 346 | toDecimal(num: number, charsAfterDecimalPoint?: number): number 347 | 348 | template(inputWithTags: string, templateArguments: object): string 349 | template(inputWithTags: string): (templateArguments: object) => string 350 | 351 | tryCatch(fn: any, fallback: any): Async | T 352 | 353 | where(conditions: object, input: object): boolean 354 | 355 | wait(fn: Async): Promise<[T, Error]> 356 | 357 | waitFor( 358 | waitForTrueCondition: Function | Promise, 359 | msHowLong: number 360 | ): (input?: any) => Promise 361 | 362 | when(rule: Func | boolean, ruleTrue: any): IdentityFunction 363 | when( 364 | rule: Func | boolean 365 | ): (ruleTrue: any) => IdentityFunction 366 | 367 | unless( 368 | rule: Func | boolean, 369 | ruleFalse: any 370 | ): IdentityFunction 371 | unless( 372 | ruleFalse: Func | boolean 373 | ): (ruleTrue: any) => IdentityFunction 374 | 375 | uuid(): string 376 | 377 | whereEq(rule: Record, input: any): boolean 378 | whereEq(rule: Record): (input: any) => boolean 379 | 380 | whenAsync( 381 | rule: Async | Func | boolean, 382 | ruleTrueFn: Async | Function 383 | ): Async 384 | // RAMBDAX_END 385 | // RAMBDA_MARKER 386 | add(a: number, b: number): number 387 | add(first: string, second: string): string 388 | add(a: number): (b: number) => number 389 | add(first: string): (second: string) => string 390 | 391 | adjust(fn: Fn, index: number, list: T[]): T[] 392 | adjust(fn: Fn, index: number): (list: T[]) => T[] 393 | 394 | all(predicate: Predicate, list: T[]): boolean 395 | all(predicate: Predicate): (list: T[]) => boolean 396 | 397 | allPass(predicates: Predicate[], input: any): boolean 398 | allPass(predicates: Predicate[]): (input: any) => boolean 399 | 400 | always(x: T): () => T 401 | 402 | any(predicate: Predicate, list: T[]): boolean 403 | any(predicate: Predicate): (list: T[]) => boolean 404 | 405 | anyPass(predicates: Predicate[], input: any): boolean 406 | anyPass(predicates: Predicate[]): (input: any) => boolean 407 | 408 | append(lastToBe: T, list: T[]): T[] 409 | append(lastToBe: T): (list: T[]) => T[] 410 | 411 | assoc(prop: K, val: T, obj: U): Record & U 412 | assoc( 413 | prop: K 414 | ): (val: T, obj: U) => Record & U 415 | assoc( 416 | prop: K, 417 | val: T 418 | ): (obj: U) => Record & U 419 | 420 | both(firstRule: Pred, secondRule: Pred): Pred 421 | both(firstRule: Pred): (secondRule: Pred) => Pred 422 | 423 | complement(fn: Fn): Fn 424 | 425 | compose(fn0: (x0: V0) => T1): (x0: V0) => T1 426 | compose(fn0: (x0: V0, x1: V1) => T1): (x0: V0, x1: V1) => T1 427 | compose( 428 | fn0: (x0: V0, x1: V1, x2: V2) => T1 429 | ): (x0: V0, x1: V1, x2: V2) => T1 430 | 431 | compose( 432 | fn1: (x: T1) => T2, 433 | fn0: (x0: V0) => T1 434 | ): (x0: V0) => T2 435 | compose( 436 | fn1: (x: T1) => T2, 437 | fn0: (x0: V0, x1: V1) => T1 438 | ): (x0: V0, x1: V1) => T2 439 | compose( 440 | fn1: (x: T1) => T2, 441 | fn0: (x0: V0, x1: V1, x2: V2) => T1 442 | ): (x0: V0, x1: V1, x2: V2) => T2 443 | 444 | compose( 445 | fn2: (x: T2) => T3, 446 | fn1: (x: T1) => T2, 447 | fn0: (x: V0) => T1 448 | ): (x: V0) => T3 449 | compose( 450 | fn2: (x: T2) => T3, 451 | fn1: (x: T1) => T2, 452 | fn0: (x0: V0, x1: V1) => T1 453 | ): (x0: V0, x1: V1) => T3 454 | compose( 455 | fn2: (x: T2) => T3, 456 | fn1: (x: T1) => T2, 457 | fn0: (x0: V0, x1: V1, x2: V2) => T1 458 | ): (x0: V0, x1: V1, x2: V2) => T3 459 | 460 | compose( 461 | fn3: (x: T3) => T4, 462 | fn2: (x: T2) => T3, 463 | fn1: (x: T1) => T2, 464 | fn0: (x: V0) => T1 465 | ): (x: V0) => T4 466 | compose( 467 | fn3: (x: T3) => T4, 468 | fn2: (x: T2) => T3, 469 | fn1: (x: T1) => T2, 470 | fn0: (x0: V0, x1: V1) => T1 471 | ): (x0: V0, x1: V1) => T4 472 | compose( 473 | fn3: (x: T3) => T4, 474 | fn2: (x: T2) => T3, 475 | fn1: (x: T1) => T2, 476 | fn0: (x0: V0, x1: V1, x2: V2) => T1 477 | ): (x0: V0, x1: V1, x2: V2) => T4 478 | 479 | compose( 480 | fn4: (x: T4) => T5, 481 | fn3: (x: T3) => T4, 482 | fn2: (x: T2) => T3, 483 | fn1: (x: T1) => T2, 484 | fn0: (x: V0) => T1 485 | ): (x: V0) => T5 486 | compose( 487 | fn4: (x: T4) => T5, 488 | fn3: (x: T3) => T4, 489 | fn2: (x: T2) => T3, 490 | fn1: (x: T1) => T2, 491 | fn0: (x0: V0, x1: V1) => T1 492 | ): (x0: V0, x1: V1) => T5 493 | compose( 494 | fn4: (x: T4) => T5, 495 | fn3: (x: T3) => T4, 496 | fn2: (x: T2) => T3, 497 | fn1: (x: T1) => T2, 498 | fn0: (x0: V0, x1: V1, x2: V2) => T1 499 | ): (x0: V0, x1: V1, x2: V2) => T5 500 | 501 | compose( 502 | fn5: (x: T5) => T6, 503 | fn4: (x: T4) => T5, 504 | fn3: (x: T3) => T4, 505 | fn2: (x: T2) => T3, 506 | fn1: (x: T1) => T2, 507 | fn0: (x: V0) => T1 508 | ): (x: V0) => T6 509 | compose( 510 | fn5: (x: T5) => T6, 511 | fn4: (x: T4) => T5, 512 | fn3: (x: T3) => T4, 513 | fn2: (x: T2) => T3, 514 | fn1: (x: T1) => T2, 515 | fn0: (x0: V0, x1: V1) => T1 516 | ): (x0: V0, x1: V1) => T6 517 | compose( 518 | fn5: (x: T5) => T6, 519 | fn4: (x: T4) => T5, 520 | fn3: (x: T3) => T4, 521 | fn2: (x: T2) => T3, 522 | fn1: (x: T1) => T2, 523 | fn0: (x0: V0, x1: V1, x2: V2) => T1 524 | ): (x0: V0, x1: V1, x2: V2) => T6 525 | 526 | concat(first: T[], second: T[]): T[] 527 | concat(first: T[]): (second: T[]) => T[] 528 | concat(first: string, second: string): string 529 | concat(first: string): (second: string) => string 530 | 531 | contains(target: string, list: string): boolean 532 | contains(target: T, list: T[]): boolean 533 | contains(target: string): (list: string) => boolean 534 | contains(target: T): (list: T[]) => boolean 535 | 536 | curry( 537 | fn: (a: T1, b: T2) => b is TResult 538 | ): CurriedTypeGuard2 539 | curry( 540 | fn: (a: T1, b: T2, c: T3) => c is TResult 541 | ): CurriedTypeGuard3 542 | curry( 543 | fn: (a: T1, b: T2, c: T3, d: T4) => d is TResult 544 | ): CurriedTypeGuard4 545 | curry( 546 | fn: (a: T1, b: T2, c: T3, d: T4, e: T5) => e is TResult 547 | ): CurriedTypeGuard5 548 | curry( 549 | fn: (a: T1, b: T2, c: T3, d: T4, e: T5, f: T6) => f is TResult 550 | ): CurriedTypeGuard6 551 | curry( 552 | fn: (a: T1, b: T2) => TResult 553 | ): CurriedFunction2 554 | curry( 555 | fn: (a: T1, b: T2, c: T3) => TResult 556 | ): CurriedFunction3 557 | curry( 558 | fn: (a: T1, b: T2, c: T3, d: T4) => TResult 559 | ): CurriedFunction4 560 | curry( 561 | fn: (a: T1, b: T2, c: T3, d: T4, e: T5) => TResult 562 | ): CurriedFunction5 563 | curry( 564 | fn: (a: T1, b: T2, c: T3, d: T4, e: T5, f: T6) => TResult 565 | ): CurriedFunction6 566 | curry(fn: (...a: any[]) => any): (...a: any[]) => any 567 | 568 | dec(n: number): number 569 | 570 | defaultTo(defaultValue: T, actualInput: null | undefined | T): T 571 | defaultTo(defaultValue: T): (actualInput: null | undefined | T) => T 572 | defaultTo( 573 | defaultValue: T, 574 | ...inputArguments: Array 575 | ): T 576 | 577 | dissoc(prop: string, obj: any): T 578 | dissoc(prop: string): (obj: any) => U 579 | 580 | divide(a: number, b: number): number 581 | divide(a: number): (b: number) => number 582 | 583 | drop(n: number, input: string): string 584 | drop(n: number, input: T[]): T[] 585 | drop( 586 | n: number 587 | ): { 588 | (input: string): string 589 | (input: T[]): T[] 590 | } 591 | 592 | dropLast(n: number, input: string): string 593 | dropLast(n: number, input: T[]): T[] 594 | dropLast( 595 | n: number 596 | ): { 597 | (input: T[]): T[] 598 | (input: string): string 599 | } 600 | 601 | either(firstRule: Pred, secondRule: Pred): Pred 602 | either(firstRule: Pred): (secondRule: Pred) => Pred 603 | 604 | endsWith(target: string, input: string): boolean 605 | endsWith(target: string): (input: string) => boolean 606 | 607 | equals(a: T, b: T): boolean 608 | equals(a: T): (b: T) => boolean 609 | 610 | fromPairs( 611 | pairs: Array> 612 | ): { [index: string]: V } 613 | fromPairs( 614 | pairs: Array> 615 | ): { [index: number]: V } 616 | 617 | toPairs( 618 | obj: { [k: string]: S } | { [k: number]: S } 619 | ): Array<[string, S]> 620 | 621 | F(): boolean 622 | 623 | filter(fn: FilterFunction): Filter 624 | filter(fn: FilterFunction, list: T[]): T[] 625 | filter(fn: FilterFunction, obj: Dictionary): Dictionary 626 | 627 | find(predicate: Pred, list: T[]): T | undefined 628 | find(predicate: Pred): (list: T[]) => T | undefined 629 | 630 | findIndex(predicate: Predicate, list: T[]): number 631 | findIndex(predicate: Predicate): (list: T[]) => number 632 | 633 | flatten(x: Array): T[] 634 | 635 | flip( 636 | fn: (arg0: T, arg1: U) => TResult 637 | ): (arg1: U, arg0?: T) => TResult 638 | flip( 639 | fn: (arg0: T, arg1: U, ...args: any[]) => TResult 640 | ): (arg1: U, arg0?: T, ...args: any[]) => TResult 641 | 642 | forEach(fn: MapFn, list: T[]): T[] 643 | forEach(fn: MapFn): (list: T[]) => T[] 644 | 645 | forEach(fn: MapFunction, inputObj: T): T 646 | forEach(fn: MapFunction): (inputObj: T) => T 647 | 648 | groupBy(fn: (x: T) => string, list: T[]): { [index: string]: T[] } 649 | groupBy(fn: (x: T) => string): (list: T[]) => { [index: string]: T[] } 650 | 651 | has(prop: string, obj: T): boolean 652 | has(prop: string): (obj: T) => boolean 653 | 654 | head(list: T[]): T | undefined 655 | head(list: string): string 656 | 657 | identity(x: T): T 658 | 659 | ifElse( 660 | fn: Pred | boolean, 661 | onTrue: Arity1Fn, 662 | onFalse: Arity1Fn 663 | ): Arity1Fn 664 | 665 | inc(n: number): number 666 | 667 | includes(target: any, input: string | any[]): boolean 668 | includes(target: any): (input: string | any[]) => boolean 669 | 670 | indexBy(fn: (x: T) => string, list: T[]): { [key: string]: T } 671 | indexBy(fn: (x: T) => string): (list: T[]) => { [key: string]: T } 672 | 673 | indexOf(target: T, arr: T[]): number 674 | indexOf(target: T): (arr: T[]) => number 675 | 676 | init(list: T[]): T[] 677 | init(list: string): string 678 | 679 | is(inputPrototype: any, input: any): boolean 680 | is(inputPrototype: any): (input: any) => boolean 681 | 682 | isNil(value: any): value is null | undefined 683 | 684 | join(x: string, input: any[]): string 685 | join(x: string): (input: any[]) => string 686 | 687 | keys(x: T): Array 688 | keys(x: T): string[] 689 | 690 | last(list: T[]): T | undefined 691 | last(list: string): string 692 | 693 | lastIndexOf(x: T, arr: T[]): number 694 | lastIndexOf(x: T): (arr: T[]) => number 695 | 696 | length(list: T[]): number 697 | 698 | map(fn: MapFunction, list: In[]): Out[] 699 | map(fn: MapFunction): (list: In[]) => Out[] 700 | 701 | map( 702 | fn: MapFunction, 703 | obj: Dictionary 704 | ): Dictionary 705 | map(fn: MapFunction): Dictionary 706 | 707 | match(regexp: RegExp, input: string): any[] 708 | match(regexp: RegExp): (input: string) => any[] 709 | 710 | merge(obj: T1, higher: T2): T1 & T2 711 | merge(obj: T1): (higher: T2) => T1 & T2 712 | 713 | modulo(a: number, b: number): number 714 | modulo(a: number): (b: number) => number 715 | 716 | multiply(a: number, b: number): number 717 | multiply(a: number): (b: number) => number 718 | 719 | max(a: T, b: T): T 720 | max(a: T): (b: T) => T 721 | 722 | maxBy(keyFn: Function, a: T, b: T): T 723 | maxBy(keyFn: Function, a: T): (b: T) => T 724 | maxBy(keyFn: Function): CurriedFunction2 725 | 726 | min(a: T, b: T): T 727 | min(a: T): (b: T) => T 728 | 729 | minBy(keyFn: Function, a: T, b: T): T 730 | minBy(keyFn: Function, a: T): (b: T) => T 731 | minBy(keyFn: Function): CurriedFunction2 732 | 733 | none(predicate: Pred, list: T[]): boolean 734 | none(predicate: Pred): (list: T[]) => boolean 735 | 736 | not(value: T): boolean 737 | nth(n: number, list: T[]): T | undefined 738 | nth(n: number): (list: T[]) => T | undefined 739 | 740 | omit>(names: K, obj: T): Omit 741 | omit(name: K, obj: T): Omit 742 | omit>( 743 | names: K 744 | ): (obj: T) => Omit 745 | 746 | omit(name: K): (obj: T) => Omit 747 | 748 | partial(fn: Function, ...inputs: Array): U 749 | 750 | partialCurry( 751 | fn: (input: Dictionary) => Out, 752 | input: Dictionary 753 | ): (input: Dictionary) => Out 754 | 755 | path(path: Path | string, obj: any): T 756 | path(path: Path | string): (obj: any) => T 757 | 758 | pathOr(d: T, p: Path | string, obj: any): T | any 759 | pathOr(d: T, p: Path | string): (obj: any) => T | any 760 | pathOr(d: T): CurriedFunction2 761 | 762 | pick( 763 | props: Array | string, 764 | input: T 765 | ): Pick 766 | pick(props: string[] | string): (obj: T) => U 767 | 768 | pickAll(props: string[], obj: T): U 769 | pickAll(props: string[]): (obj: T) => U 770 | 771 | pipe(fn0: (x0: V0) => T1): (x0: V0) => T1 772 | pipe(fn0: (x0: V0, x1: V1) => T1): (x0: V0, x1: V1) => T1 773 | pipe( 774 | fn0: (x0: V0, x1: V1, x2: V2) => T1 775 | ): (x0: V0, x1: V1, x2: V2) => T1 776 | 777 | pipe(fn0: (x0: V0) => T1, fn1: (x: T1) => T2): (x0: V0) => T2 778 | pipe( 779 | fn0: (x0: V0, x1: V1) => T1, 780 | fn1: (x: T1) => T2 781 | ): (x0: V0, x1: V1) => T2 782 | pipe( 783 | fn0: (x0: V0, x1: V1, x2: V2) => T1, 784 | fn1: (x: T1) => T2 785 | ): (x0: V0, x1: V1, x2: V2) => T2 786 | 787 | pipe( 788 | fn0: (x: V0) => T1, 789 | fn1: (x: T1) => T2, 790 | fn2: (x: T2) => T3 791 | ): (x: V0) => T3 792 | pipe( 793 | fn0: (x0: V0, x1: V1) => T1, 794 | fn1: (x: T1) => T2, 795 | fn2: (x: T2) => T3 796 | ): (x0: V0, x1: V1) => T3 797 | pipe( 798 | fn0: (x0: V0, x1: V1, x2: V2) => T1, 799 | fn1: (x: T1) => T2, 800 | fn2: (x: T2) => T3 801 | ): (x0: V0, x1: V1, x2: V2) => T3 802 | 803 | pipe( 804 | fn0: (x: V0) => T1, 805 | fn1: (x: T1) => T2, 806 | fn2: (x: T2) => T3, 807 | fn3: (x: T3) => T4 808 | ): (x: V0) => T4 809 | pipe( 810 | fn0: (x0: V0, x1: V1) => T1, 811 | fn1: (x: T1) => T2, 812 | fn2: (x: T2) => T3, 813 | fn3: (x: T3) => T4 814 | ): (x0: V0, x1: V1) => T4 815 | pipe( 816 | fn0: (x0: V0, x1: V1, x2: V2) => T1, 817 | fn1: (x: T1) => T2, 818 | fn2: (x: T2) => T3, 819 | fn3: (x: T3) => T4 820 | ): (x0: V0, x1: V1, x2: V2) => T4 821 | 822 | pipe( 823 | fn0: (x: V0) => T1, 824 | fn1: (x: T1) => T2, 825 | fn2: (x: T2) => T3, 826 | fn3: (x: T3) => T4, 827 | fn4: (x: T4) => T5 828 | ): (x: V0) => T5 829 | pipe( 830 | fn0: (x0: V0, x1: V1) => T1, 831 | fn1: (x: T1) => T2, 832 | fn2: (x: T2) => T3, 833 | fn3: (x: T3) => T4, 834 | fn4: (x: T4) => T5 835 | ): (x0: V0, x1: V1) => T5 836 | pipe( 837 | fn0: (x0: V0, x1: V1, x2: V2) => T1, 838 | fn1: (x: T1) => T2, 839 | fn2: (x: T2) => T3, 840 | fn3: (x: T3) => T4, 841 | fn4: (x: T4) => T5 842 | ): (x0: V0, x1: V1, x2: V2) => T5 843 | 844 | pipe( 845 | fn0: (x: V0) => T1, 846 | fn1: (x: T1) => T2, 847 | fn2: (x: T2) => T3, 848 | fn3: (x: T3) => T4, 849 | fn4: (x: T4) => T5, 850 | fn5: (x: T5) => T6 851 | ): (x: V0) => T6 852 | pipe( 853 | fn0: (x0: V0, x1: V1) => T1, 854 | fn1: (x: T1) => T2, 855 | fn2: (x: T2) => T3, 856 | fn3: (x: T3) => T4, 857 | fn4: (x: T4) => T5, 858 | fn5: (x: T5) => T6 859 | ): (x0: V0, x1: V1) => T6 860 | pipe( 861 | fn0: (x0: V0, x1: V1, x2: V2) => T1, 862 | fn1: (x: T1) => T2, 863 | fn2: (x: T2) => T3, 864 | fn3: (x: T3) => T4, 865 | fn4: (x: T4) => T5, 866 | fn5: (x: T5) => T6 867 | ): (x0: V0, x1: V1, x2: V2) => T6 868 | 869 | pluck(propOrIndex: string, input: any[]): T[] 870 | pluck(propOrIndex: number, input: T[][]): T[] 871 | pluck(propOrIndex: string): (input: any[]) => T[] 872 | pluck(propOrIndex: number): (input: T[][]) => T[] 873 | 874 | prepend(firstToBe: T, list: T[]): T[] 875 | prepend(firstToBe: T): (list: T[]) => T[] 876 | 877 | prop

(p: P, obj: T): T[P] 878 | prop

(p: P): (obj: Record) => T 879 | 880 | propEq(name: string, val: T, obj: any): boolean 881 | propEq(name: string, val: T): (obj: any) => boolean 882 | propEq(name: string): (val: T, obj: any) => boolean 883 | 884 | range(fromInclusive: number, toExclusive: number): number[] 885 | range(fromInclusive: number): (toExclusive: number) => number[] 886 | 887 | reduce( 888 | fn: (acc: TResult, elem: T) => TResult | Reduced, 889 | acc: TResult, 890 | list: T[] 891 | ): TResult 892 | reduce( 893 | fn: (acc: TResult, elem: T) => TResult | Reduced 894 | ): (acc: TResult, list: T[]) => TResult 895 | reduce( 896 | fn: (acc: TResult, elem: T) => TResult | Reduced, 897 | acc: TResult 898 | ): (list: T[]) => TResult 899 | 900 | reject(predicate: Predicate): Filter 901 | reject(predicate: Predicate, list: T[]): T[] 902 | reject(predicate: Predicate, obj: Dictionary): Dictionary 903 | 904 | repeat(a: T, n: number): T[] 905 | repeat(a: T): (n: number) => T[] 906 | 907 | replace( 908 | pattern: RegExp | string, 909 | replacement: string, 910 | str: string 911 | ): string 912 | replace( 913 | pattern: RegExp | string, 914 | replacement: string 915 | ): (str: string) => string 916 | replace( 917 | pattern: RegExp | string 918 | ): (replacement: string) => (str: string) => string 919 | 920 | reverse(list: T[]): T[] 921 | 922 | sort(sortingRule: FnTwo, list: T[]): T[] 923 | sort(sortingRule: FnTwo): (list: T[]) => T[] 924 | 925 | sortBy(fn: (a: T) => Ord, list: T[]): T[] 926 | sortBy(fn: (a: any) => Ord): (list: T[]) => T[] 927 | 928 | split(sep: string | RegExp): (str: string) => string[] 929 | split(sep: string | RegExp, str: string): string[] 930 | 931 | splitEvery(a: number, list: T[]): T[][] 932 | splitEvery(a: number): (list: T[]) => T[][] 933 | 934 | startsWith(x: string, str: string): boolean 935 | startsWith(x: string): (str: string) => boolean 936 | 937 | subtract(a: number, b: number): number 938 | subtract(a: number): (b: number) => number 939 | 940 | T(): boolean 941 | 942 | tail(list: T[]): T[] 943 | tail(list: string): string 944 | 945 | take(n: number, input: string): string 946 | take(n: number, input: T[]): T[] 947 | take( 948 | n: number 949 | ): { 950 | (input: string): string 951 | (input: T[]): T[] 952 | } 953 | 954 | takeLast(n: number, input: string): string 955 | takeLast(n: number, input: T[]): T[] 956 | takeLast( 957 | n: number 958 | ): { 959 | (input: T[]): T[] 960 | (input: string): string 961 | } 962 | 963 | tap(fn: (a: T) => any, value: T): T 964 | tap(fn: (a: T) => any): (value: T) => T 965 | 966 | test(regexp: RegExp, input: string): boolean 967 | test(regexp: RegExp): (input: string) => boolean 968 | 969 | times(fn: (i: number) => T, n: number): T[] 970 | times(fn: (i: number) => T): (n: number) => T[] 971 | 972 | toLower(input: string): string 973 | toString(input: T): string 974 | toUpper(input: string): string 975 | trim(input: string): string 976 | 977 | type(input: any): RambdaTypes 978 | 979 | uniq(list: T[]): T[] 980 | 981 | uniqWith(predicate: FnTwo, list: T[]): T[] 982 | uniqWith(predicate: FnTwo): (list: T[]) => T[] 983 | 984 | update(index: number, newValue: T, list: T[]): T[] 985 | update(index: number, newValue: T): (list: T[]) => T[] 986 | 987 | values(obj: T): Array 988 | 989 | without(listOfWithouts: T[], input: T[]): T[] 990 | without(listOfWithouts: T[]): (input: T[]) => T[] 991 | 992 | zip(list1: K[], list2: V[]): Array> 993 | zip(list1: K[]): (list2: V[]) => Array> 994 | 995 | zipObj(keys: string[], values: T[]): { [index: string]: T } 996 | zipObj(keys: string[]): (values: T[]) => { [index: string]: T } 997 | } 998 | } 999 | 1000 | declare let Rambdax: R.X 1001 | 1002 | export = Rambdax 1003 | } 1004 | -------------------------------------------------------------------------------- /src/types/vcslack.d.ts: -------------------------------------------------------------------------------- 1 | export type DataT = { 2 | token: string 3 | channels: string 4 | content: string 5 | filename: string 6 | filetype: string 7 | title: string 8 | } 9 | 10 | export type Channel = { 11 | id: string 12 | name: string 13 | purpose?: { 14 | value?: string 15 | } 16 | } 17 | 18 | export type Member = { 19 | id: string 20 | name: string 21 | profile?: { 22 | real_name?: string 23 | } 24 | real_name?: string 25 | } 26 | 27 | export type Group = { 28 | id: string 29 | name: string 30 | topic?: { 31 | value?: string 32 | } 33 | purpose?: { 34 | value?: string 35 | } 36 | } 37 | 38 | export interface ChannelList { 39 | id?: string 40 | label?: string 41 | description?: string 42 | detail?: string 43 | } 44 | 45 | export interface Team { 46 | token: string 47 | name: string 48 | channelList: ChannelList[] 49 | } 50 | 51 | export interface FileType { 52 | slackCompatible: string 53 | actual?: string 54 | } 55 | 56 | export type SlackFileTypes = { 57 | plaintext: FileType 58 | scss: FileType 59 | javascriptreact: FileType 60 | typescriptreact: FileType 61 | auto: FileType 62 | text: FileType 63 | ai: FileType 64 | apk: FileType 65 | applescript: FileType 66 | binary: FileType 67 | bmp: FileType 68 | boxnote: FileType 69 | c: FileType 70 | csharp: FileType 71 | cpp: FileType 72 | css: FileType 73 | csv: FileType 74 | clojure: FileType 75 | coffeescript: FileType 76 | cfm: FileType 77 | d: FileType 78 | dart: FileType 79 | diff: FileType 80 | doc: FileType 81 | docx: FileType 82 | dockerfile: FileType 83 | dotx: FileType 84 | email: FileType 85 | eps: FileType 86 | epub: FileType 87 | erlang: FileType 88 | fla: FileType 89 | flv: FileType 90 | fsharp: FileType 91 | fortran: FileType 92 | gdoc: FileType 93 | gdraw: FileType 94 | gif: FileType 95 | go: FileType 96 | gpres: FileType 97 | groovy: FileType 98 | gsheet: FileType 99 | gzip: FileType 100 | html: FileType 101 | handlebars: FileType 102 | haskell: FileType 103 | haxe: FileType 104 | indd: FileType 105 | java: FileType 106 | javascript: FileType 107 | jpg: FileType 108 | keynote: FileType 109 | kotlin: FileType 110 | latex: FileType 111 | lisp: FileType 112 | lua: FileType 113 | m4a: FileType 114 | markdown: FileType 115 | matlab: FileType 116 | mhtml: FileType 117 | mkv: FileType 118 | mov: FileType 119 | mp3: FileType 120 | mp4: FileType 121 | mpg: FileType 122 | mumps: FileType 123 | numbers: FileType 124 | nzb: FileType 125 | objc: FileType 126 | ocaml: FileType 127 | odg: FileType 128 | odi: FileType 129 | odp: FileType 130 | ods: FileType 131 | odt: FileType 132 | ogg: FileType 133 | ogv: FileType 134 | pages: FileType 135 | pascal: FileType 136 | pdf: FileType 137 | perl: FileType 138 | php: FileType 139 | pig: FileType 140 | png: FileType 141 | post: FileType 142 | powershell: FileType 143 | ppt: FileType 144 | pptx: FileType 145 | psd: FileType 146 | puppet: FileType 147 | python: FileType 148 | qtz: FileType 149 | r: FileType 150 | rtf: FileType 151 | ruby: FileType 152 | rust: FileType 153 | sql: FileType 154 | sass: FileType 155 | scala: FileType 156 | scheme: FileType 157 | sketch: FileType 158 | shell: FileType 159 | smalltalk: FileType 160 | svg: FileType 161 | swf: FileType 162 | swift: FileType 163 | tar: FileType 164 | tiff: FileType 165 | tsv: FileType 166 | vb: FileType 167 | vbscript: FileType 168 | vcard: FileType 169 | velocity: FileType 170 | verilog: FileType 171 | wav: FileType 172 | webm: FileType 173 | wmv: FileType 174 | xls: FileType 175 | xlsx: FileType 176 | xlsb: FileType 177 | xlsm: FileType 178 | xltx: FileType 179 | xml: FileType 180 | yaml: FileType 181 | zip: FileType 182 | } 183 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode' 2 | import { filetypeMap } from './const' 3 | import { SlackFileTypes, FileType } from './types/vcslack' 4 | 5 | export const getText = ( 6 | selection: vscode.Selection, 7 | fn: vscode.TextDocument['getText'] 8 | ) => { 9 | const text = fn(selection) 10 | const allText = fn() 11 | 12 | if (text !== '') { 13 | return text 14 | } else if (allText !== '') { 15 | return allText 16 | } 17 | 18 | return undefined 19 | } 20 | 21 | const cleanFiletype = (filetype: keyof SlackFileTypes): FileType => { 22 | if (filetypeMap[filetype]) { 23 | return filetypeMap[filetype] 24 | } 25 | 26 | return { 27 | slackCompatible: filetype 28 | } 29 | } 30 | 31 | const cleanFilename = (filename: string) => { 32 | if (filename.indexOf('\\') !== -1) { 33 | return filename.substring(filename.lastIndexOf('\\') + 1) 34 | } 35 | 36 | return filename.substring(filename.lastIndexOf('/') + 1) 37 | } 38 | 39 | export const buildFilename = ( 40 | filetype: keyof SlackFileTypes, 41 | filepath: string, 42 | document: vscode.TextDocument 43 | ) => { 44 | const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri) 45 | const relativePath = vscode.workspace.asRelativePath(document.uri) 46 | const cleanedFiletype = cleanFiletype(filetype) 47 | const cleanedFilename = cleanFilename(filepath) 48 | 49 | if (workspaceFolder) { 50 | if (workspaceFolder.name) { 51 | return { 52 | path: `${workspaceFolder.name}/${relativePath}`, 53 | cleanedFilename, 54 | ...cleanedFiletype 55 | } 56 | } 57 | 58 | return { 59 | path: `${relativePath}`, 60 | cleanedFilename, 61 | ...cleanedFiletype 62 | } 63 | } 64 | 65 | return { 66 | path: undefined, 67 | cleanedFilename, 68 | ...cleanedFiletype 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /test/extension.test.js: -------------------------------------------------------------------------------- 1 | /* global suite, test */ 2 | 3 | // 4 | // Note: This example test is leveraging the Mocha test framework. 5 | // Please refer to their documentation on https://mochajs.org/ for help. 6 | // 7 | 8 | // The module 'assert' provides assertion methods from node 9 | var assert = require('assert'); 10 | 11 | // You can import and use all API from the 'vscode' module 12 | // as well as import your extension to test it 13 | var vscode = require('vscode'); 14 | var myExtension = require('../extension'); 15 | 16 | // Defines a Mocha test suite to group tests of similar kind together 17 | suite("Extension Tests", function() { 18 | 19 | // Defines a Mocha unit test 20 | test("Something 1", function() { 21 | assert.equal(-1, [1, 2, 3].indexOf(5)); 22 | assert.equal(-1, [1, 2, 3].indexOf(0)); 23 | }); 24 | }); -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING 3 | // 4 | // This file is providing the test runner to use when running extension tests. 5 | // By default the test runner in use is Mocha based. 6 | // 7 | // You can provide your own test runner if you want to override it by exporting 8 | // a function run(testRoot: string, clb: (error:Error) => void) that the extension 9 | // host can call to run the tests. The test runner is expected to use console.log 10 | // to report the results back to the caller. When the tests are finished, return 11 | // a possible error to the callback or null if none. 12 | 13 | var testRunner = require('vscode/lib/testrunner'); 14 | 15 | // You can directly control Mocha options by uncommenting the following lines 16 | // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info 17 | testRunner.configure({ 18 | ui: 'tdd', // the TDD UI is being used in extension.test.js (suite, test, etc.) 19 | useColors: true // colored output from test results 20 | }); 21 | 22 | module.exports = testRunner; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "target": "esnext", 5 | "outDir": "lib", 6 | "lib": ["esnext"], 7 | "sourceMap": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noImplicitReturns": true, 10 | "strict": true, 11 | "noUnusedLocals": true, 12 | "noImplicitAny": true, 13 | "skipLibCheck": true, 14 | "skipDefaultLibCheck": true, 15 | "strictFunctionTypes": false, 16 | "esModuleInterop": true, 17 | "moduleResolution": "node", 18 | }, 19 | "exclude": [ 20 | "node_modules", 21 | "test", 22 | ] 23 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 3 | 4 | const config = { 5 | target: 'node', 6 | entry: './src/extension.ts', 7 | output: { 8 | path: path.resolve(__dirname, 'lib'), 9 | filename: 'extension.js', 10 | libraryTarget: 'commonjs2', 11 | devtoolModuleFilenameTemplate: '../[resource-path]' 12 | }, 13 | devtool: 'source-map', 14 | externals: { 15 | vscode: 'commonjs vscode' 16 | }, 17 | resolve: { 18 | extensions: ['.ts', '.js'] 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.ts$/, 24 | exclude: /node_modules/, 25 | use: [ 26 | { 27 | loader: 'ts-loader' 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | } 34 | 35 | module.exports = config 36 | --------------------------------------------------------------------------------