diff --git a/.jshintrc b/.jshintrc index f5277be..975608f 100644 --- a/.jshintrc +++ b/.jshintrc @@ -7,6 +7,7 @@ "futurehostile": true, "lastsemic": true, "latedef": true, + "indent": 1, "maxdepth": 5, "maxerr": 100, "noarg": true, diff --git a/README.md b/README.md index 41470c3..d23b342 100755 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ # js-beautify for VS Code -[![Build Status](https://api.travis-ci.org/HookyQR/VSCodeBeautify.svg?branch=master)](https://travis-ci.org/HookyQR/VSCodeBeautify) -[![Build status](https://ci.appveyor.com/api/projects/status/mu73cgat3r1t0weu/branch/master?svg=true)](https://ci.appveyor.com/project/HookyQR/vscodebeautify) -[![Licence](https://img.shields.io/github/license/HookyQR/VSCodeBeautify.svg)](https://github.com/HookyQR/VSCodeBeautify) +[![Build Status](https://api.travis-ci.org/HookyQR/VSCodeBeautify.svg?branch=master)](https://travis-ci.org/HookyQR/VSCodeBeautify) [![Build status](https://ci.appveyor.com/api/projects/status/mu73cgat3r1t0weu/branch/master?svg=true)](https://ci.appveyor.com/project/HookyQR/vscodebeautify) [![Licence](https://img.shields.io/github/license/HookyQR/VSCodeBeautify.svg)](https://github.com/HookyQR/VSCodeBeautify) [![VS Code Marketplace](http://vsmarketplacebadge.apphb.com/version-short/HookyQR.beautify.svg) ![Rating](http://vsmarketplacebadge.apphb.com/rating-short/HookyQR.beautify.svg) ![Installs](http://vsmarketplacebadge.apphb.com/installs/HookyQR.beautify.svg)](https://marketplace.visualstudio.com/items?itemName=HookyQR.beautify) Beautify `javascript`, `JSON`, `CSS`, `Sass`, and `HTML` in Visual Studio Code. -VS Code uses js-beautify internally, but it lacks the ability to modify the style you wish to use. This extension enables running [js-beautify](http://jsbeautifier.org/) in VS Code, _AND_ honouring any `.jsbeautifyrc` file in the open file's path tree to load *your* code styling. Run with **F1** `Beautify`. +VS Code uses js-beautify internally, but it lacks the ability to modify the style you wish to use. This extension enables running [js-beautify](http://jsbeautifier.org/) in VS Code, _AND_ honouring any `.jsbeautifyrc` file in the open file's path tree to load *your* code styling. Run with **F1** `Beautify` (to beautify a selection) or **F1** `Beautify file`. ### How we determine what settings to use: @@ -21,7 +19,7 @@ otherwise... 5. If **`"beautify.editorconfig"` is set to `true`**: editorconfig settings are searched for (See http://editorconfig.org/) and are merged in. -### VS Code | .jsbeautifyrc settings map: +### VS Code | .jsbeautifyrc settings map: .jsbeautifyrc setting | VS Code setting --- | --- @@ -61,27 +59,36 @@ Will result in the `indent_size` being set to 4 for Javascript and HTML, but set If the file is unsaved, or the type is undetermined, you'll be prompted for which beautifier to use. -Extra (permanent) file extensions may be added under user or workspace settings as shown below. (Defaults shown) +You can contol which file types, extensions, or specific file names should be beautified with the `beautify.language` setting. + +_Note:_ This used to be controlled by the `beautify.*Files` settings. If you still have those settings in your configuration, you'll be told that they're deprecated. Note that you may have to fix your global and project settings before the notification stops. ```javascript { - "beautify.CSSfiles": ["css", "scss"], - "beautify.JSfiles": ["js", "json", "jsbeautifyrc", "jshintrc"], - "beautify.HTMLfiles": ["htm", "html"] + "beautify.language": { + "js": { + "type": ["javascript", "json"], + "filename": [".jshintrc", ".jsbeautify"] + // "ext": ["js", "json"] + // ^^ to set extensions to be beautified using the javascript beautifier + }, + "css": ["css", "scss"], + "html": ["htm", "html"] + // ^^ providing just an array sets the VS Code file type + } } ``` Beautify on save can be enabled for all, or just specific file types. Files that you do not wish to be beautified can be excluded in the user or workspace settings files. Settings examples: ```javascript -"beautify.onSave": true, // beautify HTML, CSS, JavaScript, and JSON on save - //or -"beautify.onSave": ["js","json"], //only beautify JavaScript and JSON files on save +"beautify.onSave": true, // beautify all matching types using the selected beautifier +"beautify.onSave": ["js","css"], // only beautify those that match the js and css types "beautify.onSaveIgnore": [ - //don't beautify any file in any 'minified' directory, at any depth: + // don't beautify any file in any 'minified' directory, at any depth: "**/minified/**", - //don't minify any file that contains '.min.', '_min.', '-min.' in the filename (This is the default ignore setting): + // don't minify any file that contains '.min.', '_min.', '-min.' in the filename (This is the default ignore setting): "**/*+(.|_|-)min.*", ] ``` @@ -91,6 +98,11 @@ If you wish to exclude the files that are included by default, set `"beautify.on Embedded version of js-beautify is v1.6.4. ## Changes: +### 0.4.0: 08 Oct 2016 +* Change settings structure +* Reload file association settings when user config is changed +* Allow beautify of (primary) selected lines only + ### 0.3.0: 03 Oct 2016 * Add editorconfig as a settings source diff --git a/extension.js b/extension.js index e7d7a9c..482b36c 100755 --- a/extension.js +++ b/extension.js @@ -1,7 +1,6 @@ "use strict"; const vscode = require('vscode'), beautify = require('js-beautify'), - path = require('path'), minimatch = require('minimatch'), options = require('./options'); const dumpError = e => { @@ -9,35 +8,7 @@ const dumpError = e => { return []; }; -const extMatch = n => ({ - pattern: n.startsWith("**/") ? n : ("**/" + n) -}); - -const getBeautifyType = function(doc, dontAsk) { - if (doc.languageId === 'javascript') return 'js'; - if (doc.languageId === 'json') return 'js'; - if (doc.languageId === 'html') return 'html'; - if (doc.languageId === 'css') return 'css'; - if (doc.languageId === 'scss') return 'css'; - const type = doc.isUntitled ? "" : path.extname(doc.fileName) - .toLowerCase(); - const cfg = vscode.workspace.getConfiguration('beautify'); - //if a type is set on the window, use that - //check if the file is in the users json schema set - const jsSchema = vscode.workspace.getConfiguration('json') - .schemas; - if (jsSchema.length) { - let matcher = []; - jsSchema.forEach(schema => { - if (typeof schema.fileMatch === 'string') matcher.push(extMatch(schema.fileMatch)); - else matcher = matcher.concat(schema.fileMatch.map(extMatch)); - }); - if (vscode.languages.match(matcher, doc)) return "js"; - } - if (cfg.HTMLfiles.indexOf(type) >= 0 || (type[0] === '.' && cfg.HTMLfiles.indexOf(type.slice(1)) >= 0)) return 'html'; - else if (cfg.CSSfiles.indexOf(type) >= 0 || (type[0] === '.' && cfg.CSSfiles.indexOf(type.slice(1)) >= 0)) return 'css'; - else if (cfg.JSfiles.indexOf(type) >= 0 || (type[0] === '.' && cfg.JSfiles.indexOf(type.slice(1)) >= 0)) return 'js'; - if (dontAsk) return; +const getBeautifyType = () => { return new Promise((resolve, reject) => { //Ask what they want to do: return vscode.window.showQuickPick([{ @@ -65,10 +36,10 @@ function beautifyDoc(doc, range, type, formattingOptions) { "Beautify can't get the file information because the editor won't supply it. (File probably too large)"); throw ""; } - return Promise.resolve(type ? type : getBeautifyType(doc)) + return Promise.resolve(type ? type : getBeautifyType()) .then(type => options(doc, type, formattingOptions) .then(config => { - const original = doc.getText(doc.validateRange(range)); + const original = doc.getText(range); return beautify[type](original, config); })); } @@ -78,7 +49,10 @@ function documentEdit(range, newText) { } function extendRange(doc, rng) { - const r = new vscode.Range(new vscode.Position(rng.start.line, 0), rng.end.translate(0, Infinity)); + let end = rng.end; + if (end.character === 0) end = end.translate(-1, Number.MAX_VALUE); + else end = end.translate(0, Number.MAX_VALUE); + const r = new vscode.Range(new vscode.Position(rng.start.line, 0), end); return doc.validateRange(r); } @@ -86,19 +60,122 @@ function fullRange(doc) { return doc.validateRange(new vscode.Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE)); } -const fullEdit = (doc, formattingOptions) => { - const type = getBeautifyType(doc, true); +function fullEdit(type, doc, formattingOptions) { const rng = fullRange(doc); return beautifyDoc(doc, rng, type, formattingOptions) .then(newText => documentEdit(rng, newText), dumpError); -}; +} -const rangeEdit = (doc, rng, formattingOptions) => { - const type = getBeautifyType(doc, true); +function rangeEdit(type, doc, rng, formattingOptions) { rng = extendRange(doc, rng); return beautifyDoc(doc, rng, type, formattingOptions) .then(newText => documentEdit(rng, newText), dumpError); +} + +const register = (type, selector, partial) => { + if (partial) return vscode.languages.registerDocumentRangeFormattingEditProvider(selector, { + provideDocumentRangeFormattingEdits: rangeEdit.bind(0, type) + }); + else return vscode.languages.registerDocumentFormattingEditProvider(selector, { + provideDocumentFormattingEdits: fullEdit.bind(0, type) + }); }; +class Formatters { + constructor() { + this.available = { + js: beautify.js, + css: beautify.css, + html: beautify.html + }; + this.configTypes = { + type: 1, + ext: 1, + filename: 1 + }; + this.handlers = {}; + } + configure() { + let cfg = vscode.workspace.getConfiguration('beautify.language'); + let beautifyCfg = vscode.workspace.getConfiguration('beautify'); + let js = beautifyCfg.JSFiles; + let css = beautifyCfg.CSSFiles; + let html = beautifyCfg.HTMLFiles; + if (js || css || html) { + cfg = {}; + if (js) cfg.js = { + ext: js + }; + if (css) cfg.css = { + ext: css + }; + if (html) cfg.html = { + ext: html + }; + vscode.window.showInformationMessage( + "`beautify.*Files` setting is deprecated. please use `beautify.language` instead. Open settings ->", + "Global", "Workspace") + .then(open => { + if (open) { + vscode.commands.executeCommand(`workbench.action.open${open}Settings`); + } + }); + } + cfg = cfg || {}; + this.dispose(); + for (let a in cfg) { + if (!(a in this.available)) continue; + // dispose of the current + let selector = []; + if (Array.isArray(cfg[a])) { + selector = [].concat(cfg[a]); + } else { + for (let b in cfg[a]) { + let adder; + switch (b) { + case 'type': + adder = cfg[a][b]; + break; + case 'ext': + adder = [{ + pattern: `**/*.{${cfg[a][b].join(',')}}` + }]; + break; + case 'filename': + adder = [{ + pattern: `**/{${cfg[a][b].join(',')}}` + }]; + break; + default: + continue; + } + selector = selector.concat(adder); + } + } + this.handlers[a] = { + selector, + full: register(a, selector), + partial: register(a, selector, true) + }; + } + } + getFormat(doc) { + for (let a in this.handlers) { + if (vscode.languages.match(this.handlers[a].selector, doc)) { + return a; + } + } + } + dispose() { + for (let a in this.handlers) { + this.handlers[a].full.dispose(); + this.handlers[a].partial.dispose(); + } + this.handlers = {}; + } +} + +const formatters = new Formatters(); +formatters.configure(); function beautifyOnSave(doc) { if (doc.beautified) { @@ -106,6 +183,8 @@ function beautifyOnSave(doc) { return; } const cfg = vscode.workspace.getConfiguration('beautify'); + if (!cfg.onSave) return; + let matcher = cfg.onSaveIgnore || ["**/*+(.|_|-)min.*"]; if (typeof matcher === 'string') matcher = [matcher]; if (Array.isArray(matcher)) { @@ -116,15 +195,9 @@ function beautifyOnSave(doc) { } if (matcher.some(m => minimatch(fName, m))) return; } - let refType = doc.languageId; - if (refType === 'javascript') refType = 'js'; - if (['js', 'json', 'html', 'css', 'sass'].indexOf(refType) === -1) { - refType = getBeautifyType(doc, true); - if (!refType) return; - } + + const refType = formatters.getFormat(doc); if (cfg.onSave === true || (Array.isArray(cfg.onSave) && cfg.onSave.indexOf(refType) >= 0)) { - if (refType === 'json') refType = 'js'; - if (refType === 'sass') refType = 'css'; let range = fullRange(doc); //determine a default options return beautifyDoc(doc, range, refType) @@ -138,41 +211,31 @@ function beautifyOnSave(doc) { .then(() => 1, () => 1); } } + //register on activation function activate(context) { context.subscriptions.push(vscode.commands.registerCommand('HookyQR.beautify', () => { const active = vscode.window.activeTextEditor; if (!active) return; if (!active.document) return; - let range = fullRange(active.document); - return beautifyDoc(active.document, range) + let range = active.selection; + if (range.isEmpty) range = fullRange(active.document); + else range = extendRange(active.document, range); + const type = formatters.getFormat(active.document); + return beautifyDoc(active.document, range, type) .then(newText => active.edit(editor => editor.replace(range, newText)), dumpError); })); - // setupFormatters(context.subscriptions); - // context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(()=>{ - // setupFormatters(context.subscriptions); - // })); - context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider('html', { - provideDocumentFormattingEdits: fullEdit - })); - context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider('html', { - provideDocumentRangeFormattingEdits: rangeEdit - })); - context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider(['css', 'sass'], { - provideDocumentFormattingEdits: fullEdit - })); - context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider('scss', { - provideDocumentFormattingEdits: fullEdit - })); - context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider(['css', 'sass'], { - provideDocumentRangeFormattingEdits: rangeEdit - })); - context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider(['javascript', 'json'], { - provideDocumentFormattingEdits: fullEdit - })); - context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider(['javascript', 'json'], { - provideDocumentRangeFormattingEdits: rangeEdit + context.subscriptions.push(vscode.commands.registerCommand('HookyQR.beautifyFile', () => { + const active = vscode.window.activeTextEditor; + if (!active) return; + if (!active.document) return; + let range = fullRange(active.document); + const type = formatters.getFormat(active.document); + return beautifyDoc(active.document, range, type) + .then(newText => active.edit(editor => editor.replace(range, newText)), dumpError); })); + context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(formatters.configure.bind(formatters))); + vscode.workspace.onDidSaveTextDocument(beautifyOnSave); } exports.activate = activate; diff --git a/package.json b/package.json index 6ea6a87..30c3317 100755 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "beautify", "displayName": "beautify", "description": "Beautify code in place for VS Code", - "version": "0.3.0", + "version": "0.4.0", "publisher": "HookyQR", "engines": { "vscode": "^0.10.1" @@ -20,7 +20,7 @@ "languages": [{ "id": "json", "aliases": ["JSON"], - "filenames": [".jsbeautifyrc"] + "filenames": [".jsbeautifyrc", ".jshintrc"] }], "jsonValidation": [{ "fileMatch": ".jsbeautifyrc", @@ -28,7 +28,10 @@ }], "commands": [{ "command": "HookyQR.beautify", - "title": "Beautify" + "title": "Beautify selection" + }, { + "command": "HookyQR.beautifyFile", + "title": "Beautify file" }], "configuration": { "type": "object", @@ -37,10 +40,10 @@ "beautify.onSave": { "type": ["array", "boolean"], "default": false, - "description": "Automatically beautify files on save. Set to true to run for JSON, javascript, html, css and sass. Use array to set indiviaul types to beautify: [\"js\", \"json\", \"html\", \"css\", \"sass\"]", + "description": "Automatically beautify files on save. Set to true to run for all three provided beautifiers. Use array to set indiviaul types to beautify: [\"js\", \"html\", \"css\"]", "items": { "type": "string", - "enum": ["js", "json", "html", "css"], + "enum": ["js", "html", "css"], "description": "Set to beautify only provided types on save." } }, @@ -54,21 +57,111 @@ "default": false, "description": "Use `.editorconfig` settings" }, - "beautify.JSfiles": { - "type": "array", - "default": ["js", "json", "jsbeautifyrc", "jshintrc"], - "description": "File extensions that can be beautified as javascript or JSON." - }, - "beautify.HTMLfiles": { - "type": "array", - "default": ["htm", "html"], - "description": "File extensions that can be beautified as HTML." - }, - "beautify.CSSfiles": { - "type": "array", - "default": ["css", "scss"], - "description": "File extensions that can be beautified as CSS." + "beautify.language": { + "type": "object", + "description": "Link file types to the beautifier type", + "default": { + "js": { + "type": ["javascript", "json"], + "filename": [".jshintrc", ".jsbeautify"] + }, + "css": ["css", "scss"], + "html": ["htm", "html"] + }, + "properties": { + "js": { + "type": ["object", "array"], + "items": { + "type": "string" + }, + "description": "Array of language types, or an object containing types, extensions and filenames to associate", + "properties": { + "type": { + "type": "array", + "items": { + "type": "string" + }, + "description": "VS Code language name" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + }, + "description": "File extensions (without the leading dot)" + }, + "filename": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Full filenames (eg: '.jsbeautifyrc')" + } + } + }, + "css": { + "type": ["object", "array"], + "items": { + "type": "string" + }, + "description": "Array of language types, or an object containing types, extensions and filenames to associate", + "properties": { + "type": { + "type": "array", + "items": { + "type": "string" + }, + "description": "VS Code language name" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + }, + "description": "File extensions (without the leading dot)" + }, + "filename": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Full filenames (eg: '.jsbeautifyrc')" + } + } + }, + "html": { + "type": ["object", "array"], + "items": { + "type": "string" + }, + "description": "Array of language types, or an object containing types, extensions and filenames to associate", + "properties": { + "type": { + "type": "array", + "items": { + "type": "string" + }, + "description": "VS Code language name" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + }, + "description": "File extensions (without the leading dot)" + }, + "filename": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Full filenames (eg: '.jsbeautifyrc')" + } + } + } + } } + } } }, @@ -80,7 +173,7 @@ "devDependencies": { "mocha": "^3.0.0", "expect.js": "~0.3.1", - "vscode": "^0.11.18" + "vscode": "^1.0.0" }, "scripts": { "test": "node ./node_modules/vscode/bin/test" @@ -92,4 +185,4 @@ "bugs": { "url": "https://github.com/HookyQR/VSCodeBeautify/issues" } -} \ No newline at end of file +} diff --git a/test/.jshintrc b/test/.jshintrc index e1f1fc7..36f4946 100644 --- a/test/.jshintrc +++ b/test/.jshintrc @@ -5,6 +5,7 @@ "freeze": true, "funcscope": true, "futurehostile": true, + "indent": 1, "lastsemic": true, "latedef": true, "maxdepth": 5, diff --git a/test/.vscode/settings.json b/test/.vscode/settings.json index d0f2143..26c612e 100644 --- a/test/.vscode/settings.json +++ b/test/.vscode/settings.json @@ -7,5 +7,13 @@ "javascript.validate.enable": false, "editor.insertSpaces": true, "editor.tabSize": 4, - "beautify.editorconfig": true + "beautify.editorconfig": true, + "beautify.language": { + "js": { + "type": ["javascript", "json"], + "filename": [".jshintrc", ".jsbeautify"] + }, + "css": ["css", "scss"], + "html": ["htm", "html"] + } } diff --git a/test/data/.jsbeautifyrc b/test/data/.jsbeautifyrc index 26b5579..bc9a7b0 100644 --- a/test/data/.jsbeautifyrc +++ b/test/data/.jsbeautifyrc @@ -1 +1 @@ -{"js":{"indent_size":5},"css":{"indent_size":4},"html":{"indent_size":3},"eol":"\r\n","indent_with_tabs":false,"indent_size":2} +{"js":{"indent_size":5},"css":{"indent_size":4},"html":{"indent_size":3},"eol":"\r\n","indent_with_tabs":false,"indent_size":2} \ No newline at end of file diff --git a/test/data/test.css b/test/data/test.css index b00f648..d5f8c7b 100644 --- a/test/data/test.css +++ b/test/data/test.css @@ -1,3 +1,2 @@ -a -,b>c{border: +a,b>c{border: 1px;color:blue} \ No newline at end of file diff --git a/test/data/test.html b/test/data/test.html index bba34f9..ba98af5 100644 --- a/test/data/test.html +++ b/test/data/test.html @@ -1,2 +1,2 @@ -
-
Article Content
\ No newline at end of file +
+Article Content
\ No newline at end of file diff --git a/test/data/test.json b/test/data/test.json index ede9749..f3a9c2c 100644 --- a/test/data/test.json +++ b/test/data/test.json @@ -1 +1,2 @@ -{"a": true} \ No newline at end of file +{"a": true, +"b":false} \ No newline at end of file diff --git a/test/data/test.scss b/test/data/test.scss index 78ef07a..41896ac 100644 --- a/test/data/test.scss +++ b/test/data/test.scss @@ -1,3 +1,4 @@ +a{border:1} @mixin first(){ &:before,&:after{content: "|"} border: 1px solid green} .a {@include first(); diff --git a/test/extension.test.js b/test/extension.test.js index d092333..f233dc5 100644 --- a/test/extension.test.js +++ b/test/extension.test.js @@ -5,7 +5,7 @@ const vscode = require('vscode'), fs = require('fs'), testData = require('./testData'); -const slow = 700 + (process.platform === 'win32' ? 200 : 0); +const slow = 800 + (process.platform === 'win32' ? 100 : 0); const root = path.join(__dirname, 'data', ''); const lag = () => new Promise(resolve => setTimeout(resolve, slow / 2)); @@ -18,16 +18,20 @@ const setupConfigs = (beautify, editor) => { vscode.window.onDidChangeActiveTextEditor(editor => { if (!editor.document.test || !editor.document.test.eol) return; - const eol = editor.document.test.eol; - const cmd = editor.document.test.cmd; - return editor.edit(te => te.setEndOfLine(eol)) + const doc = editor.document; + const eol = doc.test.eol; + const cmd = doc.test.cmd; + const resolve = doc.test.resolve; + const tea = doc.test.texteditorAction; + return editor.edit(te => { + te.setEndOfLine(eol); + if (tea) return tea(te); + }) .then(() => { return vscode.commands.executeCommand(cmd) .then(() => { - const doc = editor.document; - const resolve = doc.test.resolve; // somehow, calling this stops the timeout errors. Go figure - const t = process.hrtime(doc.test.t); + const t = process.hrtime(doc.test.t); //jshint -W098 const txt = doc.getText(); return vscode.commands.executeCommand('workbench.action.closeAllEditors') .then(() => resolve(txt)); @@ -35,25 +39,39 @@ vscode.window.onDidChangeActiveTextEditor(editor => { }); }); -const executeWithCommand = (cmd, name, eol) => vscode.workspace.openTextDocument(name) +const executeWithCommand = (cmd, texteditorAction, name, eol) => vscode.workspace.openTextDocument(name) .then(doc => new Promise(resolve => { vscode.window.showTextDocument(doc); doc.test = { cmd, eol, resolve, + texteditorAction, t: process.hrtime() }; })); -const getBeautifiedText = (name, eol) => executeWithCommand('HookyQR.beautify', name, eol); -const getFormattedText = (name, eol) => executeWithCommand('editor.action.format', name, eol); +const getPartialBeautifiedText = (name, eol) => executeWithCommand('HookyQR.beautify', () => { + return vscode.commands.executeCommand('cursorMove', { + to: 'right', + by: 'character', + amount: 1, + select: true + }) + .then(() => { + return new Promise(res => setTimeout(res, 1000)); + }); +}, name, eol); + +const getBeautifiedText = (name, eol) => executeWithCommand('HookyQR.beautifyFile', null, name, eol); +const getFormattedText = (name, eol) => executeWithCommand('editor.action.format', null, name, eol); + const getOnSaveText = (name, eol) => vscode.workspace.openTextDocument(name) .then(doc => vscode.window.showTextDocument(doc) - .then(editor => editor.edit(te => { - te.setEndOfLine(eol); - te.insert(doc.positionAt(Infinity), ' '); - }))) + .then(editor => editor.edit(te => { + te.setEndOfLine(eol); + te.insert(doc.positionAt(Infinity), ' '); + }))) .then(() => vscode.commands.executeCommand('workbench.action.files.save')) .then(lag) .then(() => vscode.commands.executeCommand('workbench.action.closeAllEditors')) @@ -62,7 +80,7 @@ const getOnSaveText = (name, eol) => vscode.workspace.openTextDocument(name) function beautifyEach(fmt) { testData.types.forEach(function(ext) { - it(`For '${ext}' "beautify" changes for ${fmt[0]}`, function() { + it(`For '${ext}' "beautifyFile" changes for ${fmt[0]}`, function() { return getBeautifiedText(path.join(root, 'test.' + ext), fmt[1]) .then(txt => expect(txt) .to.be(testData.expected(fmt[0], ext))); @@ -72,7 +90,7 @@ function beautifyEach(fmt) { function formatEach(fmt) { testData.types.forEach(function(ext) { - // inbuild format command doesn't allow beautify to run. Maybe in 1.6? + // inbuild format command doesn't allow beautify to run. Maybe in 1.6? if (ext === 'json') return; it(`For '${ext}' "format" changes for ${fmt[0]}`, function() { return getFormattedText(path.join(root, 'test.' + ext), fmt[1]) @@ -82,6 +100,16 @@ function formatEach(fmt) { }); } +function beautifyPartialEach(fmt) { + testData.types.forEach(function(ext) { + it(`For '${ext}' "beautify" changes for ${fmt[0]}`, function() { + return getPartialBeautifiedText(path.join(root, 'test.' + ext), fmt[1]) + .then(txt => expect(txt) + .to.be(testData.expected(fmt[0], ext))); + }); + }); +} + function doSaveEach(fmt) { testData.types.forEach(function(ext) { //if (ext === 'js') return; @@ -99,6 +127,7 @@ describe("VS code beautify", function() { testData.clean(root); vscode.commands.executeCommand("workbench.action.toggleSidebarVisibility"); }); + let eolstr = { "\\n": ["lf", vscode.EndOfLine.LF], "\\r\\n": ["crlf", vscode.EndOfLine.CRLF] @@ -159,7 +188,17 @@ describe("VS code beautify", function() { formatEach(['nested', vscode.EndOfLine.CRLF]); }); + context('partial', function() { + before(() => setupConfigs({ + eol: "\r\n", + indent_with_tabs: false, + indent_size: 2 + }, "")); + beautifyPartialEach(['partial', vscode.EndOfLine.LF]); + }); context('on save', function() { + this.timeout(slow * 4); + this.slow(slow * 2); let preconfig; before(() => { preconfig = fs.readFileSync(path.join(__dirname, '.vscode', 'settings.json'), 'utf8'); @@ -187,4 +226,4 @@ describe("VS code beautify", function() { }); doSaveEach(['nested', vscode.EndOfLine.CRLF]); }); -}); \ No newline at end of file +}); diff --git a/test/testData.js b/test/testData.js index a9a4f01..17fb5b6 100644 --- a/test/testData.js +++ b/test/testData.js @@ -5,34 +5,42 @@ const fs = require('fs'), const inputFiles = { js: "var a=1;\n\nfunction b(){a= 5}", - json: '{"a": true}', - html: "
\n
Article Content
", - css: "a\n,b>c{border:\n1px;color:blue}", - scss: "@mixin first(){\n&:before,&:after{content:\n\"|\"} border: 1px solid green} .a {@include first();\nmargin:1px}" + json: '{"a": true,\n"b":false}', + html: "
\nArticle Content
", + css: "a,b>c{border:\n1px;color:blue}", + scss: "a{border:1}\n@mixin first(){\n&:before,&:after{content:\n\"|\"} border: 1px solid green} .a {@include first();\nmargin:1px}" }; const outputFiles = { lf: { js: 'var a = 1;\n\nfunction b() {\n a = 5\n}', - json: '{\n "a": true\n}', - html: '
\n
Article Content
\n
', + json: '{\n "a": true,\n "b": false\n}', + html: '
\n
\n Article Content
\n
', css: 'a,\nb>c {\n border: 1px;\n color: blue\n}', - scss: '@mixin first() {\n &:before,\n &:after {\n content: "|"\n }\n border: 1px solid green\n}\n\n.a {\n @include first();\n margin: 1px\n}' + scss: 'a {\n border: 1\n}\n\n@mixin first() {\n &:before,\n &:after {\n content: "|"\n }\n border: 1px solid green\n}\n\n.a {\n @include first();\n margin: 1px\n}' }, crlf: {}, tab: { js: 'var a = 1;\n\nfunction b() {\n\ta = 5\n}', - json: '{\n\t"a": true\n}', - html: '
\n\t
Article Content
\n
', + json: '{\n\t"a": true,\n\t"b": false\n}', + html: '
\n\t
\n\t\tArticle Content
\n
', css: 'a,\nb>c {\n\tborder: 1px;\n\tcolor: blue\n}', - scss: '@mixin first() {\n\t&:before,\n\t&:after {\n\t\tcontent: "|"\n\t}\n\tborder: 1px solid green\n}\n\n.a {\n\t@include first();\n\tmargin: 1px\n}' + scss: 'a {\n\tborder: 1\n}\n\n@mixin first() {\n\t&:before,\n\t&:after {\n\t\tcontent: "|"\n\t}\n\tborder: 1px solid green\n}\n\n.a {\n\t@include first();\n\tmargin: 1px\n}' }, nested: { js: 'var a = 1;\r\n\r\nfunction b() {\r\n a = 5\r\n}', - json: '{\r\n "a": true\r\n}', - html: '
\r\n
Article Content
\r\n
', + json: '{\r\n "a": true,\r\n "b": false\r\n}', + html: '
\r\n
\r\n Article Content
\r\n
', css: 'a,\r\nb>c {\r\n border: 1px;\r\n color: blue\r\n}', - scss: '@mixin first() {\r\n &:before,\r\n &:after {\r\n content: "|"\r\n }\r\n border: 1px solid green\r\n}\r\n\r\n.a {\r\n @include first();\r\n margin: 1px\r\n}' + scss: 'a {\r\n border: 1\r\n}\r\n\r\n@mixin first() {\r\n &:before,\r\n &:after {\r\n content: "|"\r\n }\r\n border: 1px solid green\r\n}\r\n\r\n.a {\r\n @include first();\r\n margin: 1px\r\n}' + }, + partial: { + // only the first line will be changed. + js: 'var a = 1;\n\nfunction b(){a= 5}', + json: '{\n "a": true,\n"b":false}', + html: '
\n
\nArticle Content
', + css: ' a,\nb>c {\n border:\n1px;color:blue}', + scss: 'a {\n border: 1\n}\n@mixin first(){\n&:before,&:after{content:\n"|"} border: 1px solid green} .a {@include first();\nmargin:1px}' } };