├── img ├── VW.png └── img.gif ├── px-to-vw-0.0.1.vsix ├── jsconfig.json ├── CHANGELOG.md ├── test ├── extension.test.js └── index.js ├── README.md ├── package.json ├── vsc-extension-quickstart.md └── extension.js /img/VW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usecodelee/px-to-vw/HEAD/img/VW.png -------------------------------------------------------------------------------- /img/img.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usecodelee/px-to-vw/HEAD/img/img.gif -------------------------------------------------------------------------------- /px-to-vw-0.0.1.vsix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usecodelee/px-to-vw/HEAD/px-to-vw-0.0.1.vsix -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "checkJs": false, /* Typecheck .js files. */ 6 | "lib": [ 7 | "es6" 8 | ] 9 | }, 10 | "exclude": [ 11 | "node_modules" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "px-to-vw" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [Unreleased] 8 | 9 | - Initial release -------------------------------------------------------------------------------- /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 | const 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 | // const vscode = require('vscode'); 14 | // const 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 | }); 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # px-to-vw 2 | 3 | This is an extension for Visual Studio Code that allows you to convert px to viewport, and viewport to px. 4 | 5 | ## Usage 6 | 7 | The use of this extension is very simple: 8 | 9 | 1. Install it. 10 | 11 | 2. Select the parts that need to be converted. 12 | 13 | 3. Press "Alt + Z" (Mac press "option + Z"). 14 | 15 | For example : 16 | 17 | ![](https://github.com/usecodelee/px-to-vw/blob/master/img/img.gif?raw=true) 18 | 19 | ## Extension Settings 20 | 21 | This extension contributes the following settings: 22 | 23 | * `px-to-vw.viewportWidth`: number of viewportWidth. Default is 750px. 24 | * `px-to-vw.unitPrecision`: maximum number of decimals digits a px or vw can have. Default is 3. 25 | 26 | ## github 27 | 28 | https://github.com/usecodelee/px-to-vw 29 | 30 | ----------------------------------------------------------------------------------------------------------- 31 | 32 | **Enjoy!** 33 | -------------------------------------------------------------------------------- /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(testsRoot: string, clb: (error: Error, failures?: number) => void): void 9 | // that the extension 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 | const testRunner = require('vscode/lib/testrunner'); 14 | 15 | // You can directly control Mocha options by configuring the test runner below 16 | // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options 17 | // for more info 18 | testRunner.configure({ 19 | ui: 'tdd', // the TDD UI is being used in extension.test.js (suite, test, etc.) 20 | useColors: true // colored output from test results 21 | }); 22 | 23 | module.exports = testRunner; 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "px-to-vw", 3 | "displayName": "px-to-vw", 4 | "description": "px to viewport", 5 | "version": "1.0.1", 6 | "publisher":"leechaojiang", 7 | "engines": { 8 | "vscode": "^1.33.0" 9 | }, 10 | "categories": [ 11 | "Formatters", 12 | "Snippets", 13 | "Other" 14 | ],"keywords": [ 15 | "px", 16 | "vw", 17 | "viewport", 18 | "px to vw", 19 | "px to viewport" 20 | ], 21 | "icon": "img/VW.png", 22 | "activationEvents": [ 23 | "onCommand:extension.pxToVw", 24 | "onCommand:extension.vwToPx", 25 | "onCommand:extension.pxTovwAndVwToPx" 26 | ], 27 | "main": "./extension.js", 28 | "contributes": { 29 | "configuration":{ 30 | "title": "Px to vw configuration", 31 | "properties": { 32 | "px-to-vw.viewportWidth": { 33 | "type": "integer", 34 | "default": 750, 35 | "description": "viewportWidth" 36 | }, 37 | "px-to-vw.unitPrecision": { 38 | "type": "integer", 39 | "default": 3, 40 | "description": "unitPrecision(几位小数)" 41 | } 42 | } 43 | }, 44 | 45 | "commands": [ 46 | { 47 | "command": "extension.pxToVw", 48 | "title": "Px to vw: Converts px to vw" 49 | }, 50 | { 51 | "command": "extension.vwToPx", 52 | "title": "Vw to px: Convert vw to px" 53 | }, 54 | { 55 | "command": "extension.pxTovwAndVwToPx", 56 | "title": "Px to vw, and vw to px. Converts selected text from px to vw, and vw to px." 57 | } 58 | ], 59 | "keybindings": [ 60 | {"command": "extension.pxTovwAndVwToPx","key": "Alt+z"} 61 | ] 62 | }, 63 | "scripts": { 64 | "postinstall": "node ./node_modules/vscode/bin/install", 65 | "test": "node ./node_modules/vscode/bin/test" 66 | }, 67 | "devDependencies": { 68 | "typescript": "^3.3.1", 69 | "vscode": "^1.1.28", 70 | "eslint": "^5.13.0", 71 | "@types/node": "^10.12.21", 72 | "@types/mocha": "^2.2.42" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | 5 | * This folder contains all of the files necessary for your extension. 6 | * `package.json` - this is the manifest file in which you declare your extension and command. 7 | * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. 8 | * `extension.js` - this is the main file where you will provide the implementation of your command. 9 | * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. 10 | * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. 11 | 12 | ## Get up and running straight away 13 | 14 | * Press `F5` to open a new window with your extension loaded. 15 | * Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. 16 | * Set breakpoints in your code inside `extension.js` to debug your extension. 17 | * Find output from your extension in the debug console. 18 | 19 | ## Make changes 20 | 21 | * You can relaunch the extension from the debug toolbar after changing code in `extension.js`. 22 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 23 | 24 | ## Explore the API 25 | 26 | * You can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts`. 27 | 28 | ## Run tests 29 | 30 | * Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`. 31 | * Press `F5` to run the tests in a new window with your extension loaded. 32 | * See the output of the test result in the debug console. 33 | * Make changes to `test/extension.test.js` or create new test files inside the `test` folder. 34 | * By convention, the test runner will only consider files matching the name pattern `**.test.js`. 35 | * You can create folders inside the `test` folder to structure your tests any way you want. 36 | 37 | ## Go further 38 | 39 | * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace. 40 | * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). 41 | -------------------------------------------------------------------------------- /extension.js: -------------------------------------------------------------------------------- 1 | var vscode = require('vscode'); 2 | function activate(context) { 3 | var disposable = vscode.commands.registerTextEditorCommand('extension.vwToPx', function (textEditor, textEditorEdit) { 4 | const config = vscode.workspace.getConfiguration("px-to-vw"); 5 | const viewportWidth = config.get('viewportWidth'); 6 | var regexStr = "([0-9]*\\.?[0-9]+)vw"; 7 | placeholder(regexStr, (match, value) => `${vw2Px(value, viewportWidth)}px`, textEditor, textEditorEdit); 8 | }); 9 | context.subscriptions.push(disposable); 10 | 11 | disposable = vscode.commands.registerTextEditorCommand('extension.pxToVw', function (textEditor, textEditorEdit) { 12 | const config = vscode.workspace.getConfiguration("px-to-vw"); 13 | const viewportWidth = config.get('viewportWidth'); 14 | var regexStr = "([0-9]*\\.?[0-9]+)px"; 15 | placeholder(regexStr, (match, value) => `${px2Vw(value, viewportWidth)}vw`, textEditor, textEditorEdit); 16 | }); 17 | context.subscriptions.push(disposable); 18 | 19 | disposable = vscode.commands.registerTextEditorCommand('extension.pxTovwAndVwToPx', function (textEditor, textEditorEdit) { 20 | const config = vscode.workspace.getConfiguration("px-to-vw"); 21 | const viewportWidth = config.get('viewportWidth'); 22 | var regexStr = "([0-9]*\\.?[0-9]+)(px|vw)"; 23 | placeholder(regexStr, (match, value, unit) => unit == "px" ? `${px2Vw(value, viewportWidth)}vw` : `${vw2Px(value, viewportWidth)}px`, textEditor, textEditorEdit); 24 | }); 25 | context.subscriptions.push(disposable); 26 | } 27 | exports.activate = activate; 28 | 29 | function deactivate() { 30 | } 31 | 32 | function px2Vw(px, viewportWidth) { 33 | if (viewportWidth == 0) { return 0; } 34 | const config = vscode.workspace.getConfiguration("px-to-vw"); 35 | var unitPrecision = config.get('unitPrecision'); 36 | const value = parseFloat(((px * 100)/ viewportWidth).toFixed(unitPrecision)); 37 | return value; 38 | } 39 | function vw2Px(vw, viewportWidth) { 40 | const config = vscode.workspace.getConfiguration("px-to-vw"); 41 | var unitPrecision = config.get('unitPrecision'); 42 | const value = parseFloat(((vw / 100) * viewportWidth).toFixed(unitPrecision)); 43 | return value; 44 | } 45 | 46 | function placeholder(regexString, replaceFunction, textEditor, textEditorEdit) { 47 | let regexExp = new RegExp(regexString, "i"); 48 | let regexExpG = new RegExp(regexString, "ig"); 49 | const selections = textEditor.selections; 50 | if (selections.length == 0 || selections.reduce((acc, val) => acc || val.isEmpty), false) { return; } 51 | const config = vscode.workspace.getConfiguration("px-to-vw"); 52 | const changesMade = new Map(); 53 | textEditor.edit(builder => { 54 | let numOcurrences = 0; 55 | selections.forEach((selection) => { 56 | for (var index = selection.start.line; index <= selection.end.line; index++) { 57 | let start = 0, end = textEditor.document.lineAt(index).range.end.character; 58 | if (index === selection.start.line) { 59 | let tmpSelection = selection.with({ end: selection.start }); 60 | let range = findValueRangeToConvert(tmpSelection, regexString, textEditor); 61 | if (range) { 62 | start = range.start.character; 63 | } else { 64 | start = selection.start.character; 65 | } 66 | } 67 | if (index === selection.end.line) { 68 | let tmpSelection = selection.with({ start: selection.end }); 69 | let range = findValueRangeToConvert(tmpSelection, regexString, textEditor); 70 | if (range) { 71 | end = range.end.character; 72 | } else { 73 | end = selection.end.character; 74 | } 75 | } 76 | let text = textEditor.document.lineAt(index).text.slice(start, end); 77 | const matches = text.match(regexExpG); 78 | numOcurrences += matches ? matches.length : 0; 79 | if (numOcurrences == 0) { continue; } 80 | const regex = regexExpG; 81 | const newText = text.replace(regex, replaceFunction); 82 | const selectionTmp = new vscode.Selection(index, start, index, end); 83 | const key = `${index}-${start}-${end}`; 84 | if (!changesMade.has(key)) { 85 | changesMade.set(key, true); 86 | builder.replace(selectionTmp, newText); 87 | } 88 | } 89 | return; 90 | }, this); 91 | if (numOcurrences == 0) { 92 | vscode.window.showWarningMessage("There were no values to transform"); 93 | } 94 | }) 95 | .then(success => { 96 | textEditor.selections.forEach((selection, index, newSelections) => { 97 | if (selections[index].start.isEqual(selections[index].end)) { 98 | const newPosition = selection.end; 99 | const newSelection = new vscode.Selection(newPosition, newPosition); 100 | textEditor.selections[index] = newSelection; 101 | } 102 | }); 103 | textEditor.selections = textEditor.selections; 104 | if (!success) { 105 | console.log(`Error: ${success}`); 106 | } 107 | }); 108 | }; 109 | 110 | function findValueRangeToConvert(selection, regexString, textEditor) { 111 | const line = selection.start.line; 112 | const startChar = selection.start.character; 113 | const text = textEditor.document.lineAt(line).text; 114 | const regexExpG = new RegExp(regexString, "ig"); 115 | 116 | var result, indices = []; 117 | while ((result = regexExpG.exec(text))) { 118 | const resultStart = result.index; 119 | const resultEnd = result.index + result[0].length; 120 | if (startChar >= resultStart && startChar <= resultEnd) { 121 | return new vscode.Range(line, resultStart, line, resultEnd); 122 | } 123 | } 124 | return null; 125 | } 126 | 127 | exports.deactivate = deactivate; --------------------------------------------------------------------------------