├── .browserslistrc ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── extension.js ├── icon.png ├── jsconfig.json ├── package-lock.json ├── package.json ├── test ├── index.js ├── runTests.js └── view.test.js ├── view.js └── webpack.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | Electron 11.3.0 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | indent_size = 2 4 | charset = utf-8 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | 8 | [*.md] 9 | trim_trailing_whitespace = false 10 | insert_final_newline = false 11 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": false, 4 | "commonjs": true, 5 | "es6": true, 6 | "node": true 7 | }, 8 | "parserOptions": { 9 | "ecmaFeatures": { 10 | "jsx": true 11 | }, 12 | "sourceType": "module" 13 | }, 14 | "rules": { 15 | "no-const-assign": "warn", 16 | "no-this-before-super": "warn", 17 | "no-undef": "warn", 18 | "no-unreachable": "warn", 19 | "no-unused-vars": "warn", 20 | "constructor-super": "warn", 21 | "valid-typeof": "warn" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode-test 3 | dist 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.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": [ 11 | "--extensionDevelopmentPath=${workspaceRoot}", 12 | "--disable-extensions" 13 | ], 14 | "stopOnEntry": false 15 | }, 16 | { 17 | "name": "Launch Tests", 18 | "type": "extensionHost", 19 | "request": "launch", 20 | "runtimeExecutable": "${execPath}", 21 | "args": [ 22 | "--extensionDevelopmentPath=${workspaceRoot}", 23 | "--extensionTestsPath=${workspaceRoot}/test" 24 | ], 25 | "stopOnEntry": false 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version 4 | } 5 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | test/** 4 | .gitignore 5 | jsconfig.json 6 | .eslintrc.json 7 | extension.js 8 | view.js 9 | node_modules 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.2.1 - Keep vscode minimum version to 1.54.0 2 | 3 | - Keep supporting VSCode 1.54.0+ 4 | 5 | ## 3.2.0 - A few updates and fixes 6 | 7 | - Added Support typescript file mime type. 8 | - Updated filesize-calculator to 4.1.0. 9 | - Changed activation event to load the extension after VSCode is done loading. 10 | - Created show brotli option to show the size on the status bar. 11 | - Created show raw bytes option to show the total size in bytes inside the detailed view. 12 | 13 | 14 | ## 3.1.0 - Reduced extension bundle 15 | 16 | - Update filesize-calculator to 4.0.1, using lighter dependencies 17 | - Faster extension loading. 18 | 19 | ## 3.0.0 - New features and fixes 20 | 21 | - Added brotli info in the detailed description. 22 | - Added option to show the status bar info on the right side. 23 | - Added extension bundling for faster loading. 24 | - Fixed incompatibility with VS Code 1.54+ 25 | - Updated dependencies 26 | 27 | ## 2.1.4 - Updated dependencies 28 | 29 | - Updated dependencies 30 | 31 | ## 2.1.3 - Updated dependencies 32 | 33 | - Updated dependencies 34 | 35 | ## 2.1.2 - Updated dependencies 36 | 37 | - Updated dependencies 38 | 39 | ## 2.1.1 - Fixed useDecimal comment and updates dependencies 40 | 41 | - useDecimal comment is now indicating the use of the boolean config correctly. Thanks to @matthewfarlymn! 42 | - Updated dependencies. 43 | 44 | ## 2.1.0 - Changed keyboard shortcut, updates dependencies 45 | 46 | - We have a new keyboard shortcut for opening detailed info (Ctrl+Shift+') on Windows/Linux and (Cmd+Shift+') on Mac. Thanks @gonssal for the heads up! 47 | - Updated dependencies 48 | 49 | ## 2.0.0 - Quicker, keyboard shortcut, absolute file info, new icon and more 50 | 51 | - Extension now has an icon thanks to @coliff! 52 | - Absolute file info now shows in the detailed view. 53 | - Keyboard shortcut to toggle detailed view is now available. See README. 54 | - Added `showGzip` config to enable toggling gzip info in detailed view. 55 | - Changed `useKibibyteRepresentation` config to `useDecimal`, now set to `false` by default. 56 | - Slightly faster code and bug fixes. 57 | 58 | ## 1.1.0 - Panel support and some fixes 59 | 60 | - **Panel support!** Now the extension should have no problems dealing with more than one panel in screen. The focused one is considered active. 61 | - Status bar element now keeps its place. Some users were experiencing problems when there were other 62 | extensions present in the status bar. Place switching often occured, now we set a priority of 1 to the status-bar component so it should stay in place. 63 | - Fixed bug where info would not appear after visiting certain parts of the editor and coming back like settings and etc. 64 | - Fixed bug when switching files quickly would lead to file info queries being stacked, now new calls cancel old ones. 65 | 66 | ## 1.0.0 - First Version 67 | 68 | - The first version of `vscode-filesize` is here! 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Matheus R. Kautzmann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # filesize package for Visual Studio Code 2 | 3 | This package is intended for use with the [Visual Studio Code](https://code.visualstudio.com) editor and it displays the size of the focused file in the status bar of the editor. 4 | 5 | **Bonus:** If you click on the status bar component it will display more information about the file! 6 | 7 | ## Installation 8 | 9 | In VS Code, press Ctrl-P or Cmd-P (Mac) and type in `ext install vscode-filesize`. Click install in the left bar. Once the extension is installed you will be prompted to restart Visual Studio Code. 10 | 11 | Or you can just search for `filesize` in the extension search bar inside the editor. 12 | 13 | ## Screenshots 14 | 15 | `filesize` with the status bar component active in simple view: 16 | 17 | ![status bar component](https://cldup.com/_Y52O-UfkK.jpg) 18 | 19 | ### **NEW!** Expanded view 20 | 21 | `filesize` with the status bar component active in expanded view (with gzip enabled): 22 | 23 | ![status bar component](https://cldup.com/urhtudAVO3.jpg) 24 | 25 | ### Detailed view 26 | 27 | To open the detailed view for the current file in focus you can just click at the size in the status bar or use `Crtl`-`shift`-`'` or `Cmd`-`shift`-`'` if you are on a Mac. 28 | 29 | `filesize` with the detailed info panel open: 30 | 31 | ![detailed info](https://cldup.com/x6qsyVLtee.jpg) 32 | 33 | ## Settings 34 | 35 | This package has the following user-configurable settings: 36 | 37 | - `displayInfoOnTheRightSideOfStatusBar`: Show the status bar info on the right side instead of the left. (Default: `false`) 38 | - `showBrotli`: Show the calculated brotli-compressed size in the detailed info view. (Default: `false`) 39 | - `showGzip`: Show the calculated gzip-compressed size in the detailed info view. (Default: `true`) 40 | - `showGzipInStatusBar`: Show the calculated gzip-compressed size directly in the status bar. (Default: `false`) 41 | - `use24HourFormat`: Use the 24-hour clock format for time display; set to `false` for 12-hour format. (Default: `true`) 42 | - `useDecimal`: Display file sizes using the [SI unit system](https://en.wikipedia.org/wiki/International_System_of_Units); set to `false` to use [IEC's](https://en.wikipedia.org/wiki/Binary_prefix) format. (Default: `false`) 43 | 44 | ## Contributing 45 | 46 | You are welcome to send any issues or pull requests. 47 | 48 | Please run eslint in the code and test it with Visual Studio Code before sending changes. 49 | 50 | Any bugs? Please file an [issue](https://github.com/mkxml/vscode-filesize/issues/new). 51 | 52 | Did something nice with the code? Please send a [pull request](https://github.com/mkxml/vscode-filesize/pulls). 53 | 54 | ## Authors 55 | 56 | - [Matheus Kautzmann](https://github.com/mkxml) 57 | 58 | ## License 59 | 60 | [MIT](LICENSE) 61 | -------------------------------------------------------------------------------- /extension.js: -------------------------------------------------------------------------------- 1 | var vscode = require('vscode'); 2 | var renderTableInOutputChannel = require('./view'); 3 | var fzCalculator = require('filesize-calculator'); 4 | 5 | var window = vscode.window; 6 | var workspace = vscode.workspace; 7 | 8 | var cachedLocation = 'left'; 9 | 10 | var statusBarItem, oc, info, config, isShowingDetailedInfo; 11 | 12 | function updateConfig() { 13 | var configuration = workspace.getConfiguration('filesize'); 14 | config = { 15 | useDecimal: configuration.get('useDecimal'), 16 | use24HourFormat: configuration.get('use24HourFormat'), 17 | showGzip: configuration.get('showGzip'), 18 | showBrotli: configuration.get('showBrotli'), 19 | showGzipInStatusBar: configuration.get('showGzipInStatusBar'), 20 | showBrotliInStatusBar: configuration.get('showBrotliInStatusBar'), 21 | showRawInBytes: configuration.get('showRawInBytes'), 22 | displayInfoOnTheRightSideOfStatusBar: configuration.get('displayInfoOnTheRightSideOfStatusBar') 23 | }; 24 | updateStatusBarItem(); 25 | return config; 26 | } 27 | 28 | function showStatusBarItem(newInfo) { 29 | info = fzCalculator.addPrettySize(newInfo, config); 30 | if (info && info.prettySize) { 31 | if (config.showGzipInStatusBar || config.showBrotliInStatusBar) { 32 | statusBarItem.text = `Raw: ${info.prettySize}`; 33 | } else { 34 | statusBarItem.text = info.prettySize; 35 | } 36 | if (config.showGzipInStatusBar) { 37 | info = fzCalculator.addGzipSize(info, config); 38 | statusBarItem.text += ` | Gz: ${info.gzipSize}`; 39 | } 40 | if (config.showBrotliInStatusBar) { 41 | info = fzCalculator.addBrotliSize(info, config); 42 | statusBarItem.text += ` | Br: ${info.brotliSize}`; 43 | } 44 | statusBarItem.show(); 45 | } 46 | } 47 | 48 | function hideStatusBarItem() { 49 | hideDetailedInfo(); 50 | statusBarItem.text = ''; 51 | statusBarItem.hide(); 52 | } 53 | 54 | // Update simple info in the status bar 55 | function updateStatusBarItem() { 56 | // Check where to display the status bar 57 | var location = config.displayInfoOnTheRightSideOfStatusBar ? 'right' : 'left'; 58 | // Set up statusBarItem 59 | if (cachedLocation !== location) { 60 | cachedLocation = location; 61 | if (location === 'right') { 62 | statusBarItem = window.createStatusBarItem(vscode.StatusBarAlignment.Right, 1); 63 | } else { 64 | statusBarItem = window.createStatusBarItem(vscode.StatusBarAlignment.Left, 1); 65 | } 66 | statusBarItem.command = 'extension.toggleFilesizeInfo'; 67 | statusBarItem.tooltip = 'Current file size - Click to toggle more info'; 68 | } 69 | try { 70 | var currentEditor = window.activeTextEditor.document; 71 | if (currentEditor && currentEditor.uri.scheme === 'file') { 72 | hideDetailedInfo(); 73 | showStatusBarItem(fzCalculator.loadFileInfoSync(currentEditor.fileName)); 74 | } else { 75 | if (currentEditor.uri.scheme !== 'output') hideStatusBarItem(); 76 | } 77 | } catch (e) { 78 | hideStatusBarItem(); 79 | } 80 | } 81 | 82 | // Show detailed filesize info in the OC 83 | function showDetailedInfo() { 84 | if (info && info.prettySize) { 85 | info = config.showGzip ? fzCalculator.addGzipSize(info, config) : info; 86 | info = config.showBrotli ? fzCalculator.addBrotliSize(info, config) : info; 87 | info = fzCalculator.addMimeTypeInfo(info); 88 | info = fzCalculator.addPrettyDateInfo(info, config); 89 | const table = []; 90 | if (info.prettySize) table.push({ header: 'Size', content: info.prettySize }); 91 | if (info.size && config.showRawInBytes) table.push({ header: 'Raw size', content: info.size + ' bytes' }); 92 | if (info.gzipSize) table.push({ header: 'Gzipped', content: info.gzipSize }); 93 | if (info.brotliSize) table.push({ header: 'Brotli', content: info.brotliSize }); 94 | if (info.mimeType) table.push({ header: 'Mime type', content: info.mimeType }); 95 | if (info.prettyDateCreated) table.push({ header: 'Created', content: info.prettyDateCreated }); 96 | if (info.prettyDateChanged) table.push({ header: 'Changed', content: info.prettyDateChanged }); 97 | renderTableInOutputChannel(oc, info.absolutePath, table); 98 | } else { 99 | oc.clear(); 100 | oc.appendLine('No file information available for this context!'); 101 | } 102 | oc.show(true); 103 | isShowingDetailedInfo = true; 104 | } 105 | 106 | function hideDetailedInfo() { 107 | oc.hide(); 108 | isShowingDetailedInfo = false; 109 | } 110 | 111 | function toggleDetailedInfo() { 112 | if (isShowingDetailedInfo) { 113 | hideDetailedInfo(); 114 | } else { 115 | showDetailedInfo(); 116 | } 117 | } 118 | 119 | // Called when VS Code activates the extension 120 | function activate(context) { 121 | console.log('filesize is active'); 122 | 123 | // Set up statusBarItem 124 | statusBarItem = window.createStatusBarItem(vscode.StatusBarAlignment.Left, 1); 125 | statusBarItem.command = 'extension.toggleFilesizeInfo'; 126 | statusBarItem.tooltip = 'Current file size - Click to toggle more info'; 127 | 128 | // Global OutputChannel to be used for the extension detailed info 129 | oc = window.createOutputChannel('filesize'); 130 | 131 | // Update handlers 132 | var onSave = workspace.onDidSaveTextDocument(updateStatusBarItem); 133 | var onActiveEditorChanged = window.onDidChangeActiveTextEditor(updateStatusBarItem); 134 | var onChangeConfig = workspace.onDidChangeConfiguration(updateConfig); 135 | 136 | // Show detailed info through custom command 137 | var command = vscode.commands.registerCommand('extension.toggleFilesizeInfo', toggleDetailedInfo); 138 | 139 | // Register disposables that get disposed when deactivating 140 | context.subscriptions.push(onSave); 141 | context.subscriptions.push(onChangeConfig); 142 | context.subscriptions.push(onActiveEditorChanged); 143 | context.subscriptions.push(command); 144 | 145 | // Set default config 146 | updateConfig(); 147 | } 148 | 149 | // Called when VS Code deactivates the extension 150 | function deactivate() { 151 | try { 152 | if (oc) { 153 | oc.clear(); 154 | oc.dispose(); 155 | } 156 | if (statusBarItem) { 157 | statusBarItem.hide(); 158 | statusBarItem.dispose(); 159 | } 160 | oc = null; 161 | statusBarItem = null; 162 | config = null; 163 | info = null; 164 | } catch(e) { 165 | console.log('Error disposing filesize disposable when deactivating'); 166 | } 167 | return undefined; 168 | } 169 | 170 | module.exports = { 171 | activate: activate, 172 | deactivate: deactivate 173 | }; 174 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkxml/vscode-filesize/76e3d64367a4a0e51d0694585fe35fc793b81e9b/icon.png -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ] 8 | }, 9 | "exclude": [ 10 | "node_modules" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-filesize", 3 | "displayName": "filesize", 4 | "description": "Show the current file size in the status bar", 5 | "version": "3.2.2", 6 | "icon": "icon.png", 7 | "publisher": "mkxml", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/mkxml/vscode-filesize" 11 | }, 12 | "keywords": [ 13 | "file", 14 | "size", 15 | "filesize", 16 | "status bar", 17 | "info" 18 | ], 19 | "license": "MIT", 20 | "engines": { 21 | "vscode": "^1.54.0" 22 | }, 23 | "categories": [ 24 | "Other" 25 | ], 26 | "activationEvents": [ 27 | "onStartupFinished" 28 | ], 29 | "main": "./dist/extension", 30 | "extensionKind": [ 31 | "workspace" 32 | ], 33 | "contributes": { 34 | "commands": [ 35 | { 36 | "command": "extension.toggleFilesizeInfo", 37 | "title": "Toggle filesize detailed information" 38 | } 39 | ], 40 | "keybindings": [ 41 | { 42 | "command": "extension.toggleFilesizeInfo", 43 | "key": "ctrl+shift+'", 44 | "mac": "cmd+shift+'", 45 | "when": "editorTextFocus" 46 | } 47 | ], 48 | "configuration": { 49 | "type": "object", 50 | "title": "filesize configuration", 51 | "properties": { 52 | "filesize.useDecimal": { 53 | "type": "boolean", 54 | "default": false, 55 | "description": "Defaults to false, using IEC's representation. Set to true to get SI representation." 56 | }, 57 | "filesize.use24HourFormat": { 58 | "type": "boolean", 59 | "default": true, 60 | "description": "Defaults to true, using 24-hour format. Set to false to get 12-hour format." 61 | }, 62 | "filesize.showGzip": { 63 | "type": "boolean", 64 | "default": true, 65 | "description": "Defaults to true, whether to show gzip size in detailed view or not." 66 | }, 67 | "filesize.showBrotli": { 68 | "type": "boolean", 69 | "default": false, 70 | "description": "Defaults to false, whether to show brotli size in the detailed view." 71 | }, 72 | "filesize.showRawInBytes": { 73 | "type": "boolean", 74 | "default": false, 75 | "description": "Defaults to false, whether to show raw size in bytes in the detailed view." 76 | }, 77 | "filesize.showGzipInStatusBar": { 78 | "type": "boolean", 79 | "default": false, 80 | "description": "Defaults to false, whether to show gzip size in the status bar." 81 | }, 82 | "filesize.showBrotliInStatusBar": { 83 | "type": "boolean", 84 | "default": false, 85 | "description": "Defaults to false, whether to show brotli size in the status bar." 86 | }, 87 | "filesize.displayInfoOnTheRightSideOfStatusBar": { 88 | "type": "boolean", 89 | "default": false, 90 | "description": "Defaults to false, whether to show the filesize info on the right side of the status bar." 91 | } 92 | } 93 | } 94 | }, 95 | "scripts": { 96 | "vscode:prepublish": "webpack --mode production", 97 | "webpack": "webpack --mode development", 98 | "webpack-dev": "webpack --mode development --watch", 99 | "test": "node test/runTests.js" 100 | }, 101 | "devDependencies": { 102 | "@babel/core": "^7.26.0", 103 | "@babel/preset-env": "^7.26.0", 104 | "@types/mocha": "^10.0.9", 105 | "@types/node": "^22.8.6", 106 | "@types/vscode": "^1.54.0", 107 | "babel-loader": "^9.2.1", 108 | "eslint": "^8.2.0", 109 | "glob": "^11.0.0", 110 | "mocha": "^10.8.2", 111 | "typescript": "^5.6.3", 112 | "vscode-test": "^1.5.1", 113 | "webpack": "^5.96.1", 114 | "webpack-cli": "^5.1.4" 115 | }, 116 | "dependencies": { 117 | "filesize-calculator": "^4.1.0" 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const Mocha = require('mocha'); 3 | const glob = require('glob'); 4 | 5 | module.exports.run = function run() { 6 | console.log('RUNNING TESTS'); 7 | // Create the mocha test 8 | const mocha = new Mocha({ 9 | ui: 'tdd', 10 | color: true 11 | }); 12 | 13 | const testsRoot = path.resolve(__dirname, '.'); 14 | 15 | return new Promise((c, e) => { 16 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 17 | if (err) { 18 | return e(err); 19 | } 20 | 21 | // Add files to the test suite 22 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 23 | 24 | try { 25 | // Run the mocha test 26 | mocha.run(failures => { 27 | if (failures > 0) { 28 | e(new Error(`${failures} tests failed.`)); 29 | } else { 30 | c(); 31 | } 32 | }); 33 | } catch (err) { 34 | e(err); 35 | } 36 | }); 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /test/runTests.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const vscodeTest = require('vscode-test'); 4 | 5 | async function main() { 6 | try { 7 | // The folder containing the Extension Manifest package.json 8 | // Passed to `--extensionDevelopmentPath` 9 | const extensionDevelopmentPath = path.resolve(__dirname, '../'); 10 | 11 | // The path to the extension test runner script 12 | // Passed to --extensionTestsPath 13 | const extensionTestsPath = path.resolve(__dirname, './index'); 14 | 15 | console.log(extensionDevelopmentPath); 16 | console.log(extensionTestsPath); 17 | 18 | // Download VS Code, unzip it and run the integration test 19 | await vscodeTest.runTests({ extensionDevelopmentPath, extensionTestsPath }); 20 | } catch (err) { 21 | console.error(err); 22 | console.error('Failed to run tests'); 23 | process.exit(1); 24 | } 25 | } 26 | 27 | main(); 28 | -------------------------------------------------------------------------------- /test/view.test.js: -------------------------------------------------------------------------------- 1 | /* global suite, test */ 2 | var assert = require('assert'); 3 | var view = require('../view'); 4 | 5 | // Simple mock of OutputChannel for this test 6 | var oc = { 7 | content: '', 8 | clear: function () { this.content = '' }, 9 | appendLine: function (line) { this.content += (line + '\n'); }, 10 | show: function () { } // Noop 11 | }; 12 | 13 | suite('View', function () { 14 | test('can render a table with header and a single item', function () { 15 | var expected = '/home/mypath\n\n'; 16 | expected += '+--------------------------------------------------------------+\n'; 17 | expected += '| Size | 20 bytes |\n'; 18 | expected += '+--------------------------------------------------------------+\n'; 19 | view(oc, '/home/mypath', [{ 20 | header: 'Size', 21 | content: '20 bytes' 22 | }]); 23 | assert.equal(oc.content, expected); 24 | }); 25 | test('can render a table with many items', function () { 26 | var expected = '/home/mypath\n\n'; 27 | expected += '+--------------------------------------------------------------+\n'; 28 | expected += '| Size | 20 bytes |\n'; 29 | expected += '|--------------------------------------------------------------|\n'; 30 | expected += '| Gzipped | 35 bytes |\n'; 31 | expected += '|--------------------------------------------------------------|\n'; 32 | expected += '| Mime type | text/plain |\n'; 33 | expected += '|--------------------------------------------------------------|\n'; 34 | expected += '| Created | October 11th 2016, 10:54:22 |\n'; 35 | expected += '|--------------------------------------------------------------|\n'; 36 | expected += '| Changed | January 13th 2017, 09:59:17 |\n'; 37 | expected += '+--------------------------------------------------------------+\n'; 38 | view(oc, '/home/mypath', [ 39 | { 40 | header: 'Size', 41 | content: '20 bytes' 42 | }, 43 | { 44 | header: 'Gzipped', 45 | content: '35 bytes' 46 | }, 47 | { 48 | header: 'Mime type', 49 | content: 'text/plain' 50 | }, 51 | { 52 | header: 'Created', 53 | content: 'October 11th 2016, 10:54:22' 54 | }, 55 | { 56 | header: 'Changed', 57 | content: 'January 13th 2017, 09:59:17' 58 | } 59 | ]); 60 | assert.equal(oc.content, expected); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /view.js: -------------------------------------------------------------------------------- 1 | // Table constants 2 | var TABLE_WIDTH = 64; 3 | var HEADER_WIDTH = 16; 4 | var CONTENT_WIDTH = 48; 5 | var CORNER_CHAR = '+'; 6 | var SEPARATOR_CHAR = '|'; 7 | var DIVIDER_CHAR = '-'; 8 | var DIVIDER = function makeTableLine() { 9 | var newString = ''; 10 | for (var i = 0; i < TABLE_WIDTH - 2; i++) newString += DIVIDER_CHAR; 11 | return newString; 12 | } (); 13 | var VERTICAL_BORDER = CORNER_CHAR + DIVIDER + CORNER_CHAR; 14 | var SEPARATOR = SEPARATOR_CHAR + DIVIDER + SEPARATOR_CHAR; 15 | 16 | // Get column formatted 17 | function formatColumn(text, maxChars, first) { 18 | var output = ((first) ? '| ' : ' ') + text; 19 | for (var i = output.length; i < maxChars - 1; i++) output += ' '; 20 | output += '|'; 21 | return output; 22 | } 23 | 24 | // Render a human readable table in OC by passing the OC and header: content 25 | function renderTableInOutputChannel(outputChannel, title, data) { 26 | // Make sure it's clean 27 | outputChannel.clear(); 28 | 29 | // Title, file path 30 | if (title) outputChannel.appendLine(title + '\n'); 31 | 32 | // Start table 33 | outputChannel.appendLine(VERTICAL_BORDER); 34 | 35 | for (var i = 0, length = data.length; i < length; i++) { 36 | var header = formatColumn(data[i].header, HEADER_WIDTH, true); 37 | var content = formatColumn(data[i].content, CONTENT_WIDTH); 38 | var line = header + content; 39 | outputChannel.appendLine(line); 40 | if (i < length - 1) outputChannel.appendLine(SEPARATOR); 41 | } 42 | 43 | // End table 44 | outputChannel.appendLine(VERTICAL_BORDER); 45 | } 46 | 47 | module.exports = renderTableInOutputChannel; 48 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const config = { 4 | target: 'node', 5 | entry: './extension.js', 6 | output: { 7 | path: path.resolve(__dirname, 'dist'), 8 | filename: 'extension.js', 9 | libraryTarget: 'commonjs2', 10 | // devtoolModuleFilenameTemplate: '../[resource-path]' 11 | }, 12 | devtool: 'source-map', 13 | externals: { 14 | vscode: 'commonjs vscode' 15 | }, 16 | resolve: { 17 | extensions: ['.js'] 18 | }, 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.js$/, 23 | exclude: /node_modules/, 24 | use: { 25 | loader: 'babel-loader', 26 | options: { 27 | presets: [ 28 | [ 29 | '@babel/preset-env', 30 | { 31 | useBuiltIns: false 32 | } 33 | ] 34 | ] 35 | } 36 | } 37 | } 38 | ] 39 | } 40 | }; 41 | module.exports = config; 42 | --------------------------------------------------------------------------------