Permalink
Browse files

Change config and allow selection beautify

  • Loading branch information...
1 parent d028974 commit 54078fd113ba6ab5e6d3f5a4aa64808edf0e86c9 Hooky committed Oct 8, 2016
Showing with 370 additions and 144 deletions.
  1. +1 −0 .jshintrc
  2. +26 −14 README.md
  3. +135 −72 extension.js
  4. +114 −21 package.json
  5. +1 −0 test/.jshintrc
  6. +9 −1 test/.vscode/settings.json
  7. +1 −1 test/data/.jsbeautifyrc
  8. +1 −2 test/data/test.css
  9. +2 −2 test/data/test.html
  10. +2 −1 test/data/test.json
  11. +1 −0 test/data/test.scss
  12. +56 −17 test/extension.test.js
  13. +21 −13 test/testData.js
View
@@ -7,6 +7,7 @@
"futurehostile": true,
"lastsemic": true,
"latedef": true,
+ "indent": 1,
"maxdepth": 5,
"maxerr": 100,
"noarg": true,
View
@@ -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
View
@@ -1,43 +1,14 @@
"use strict";
const vscode = require('vscode'),
beautify = require('js-beautify'),
- path = require('path'),
minimatch = require('minimatch'),
options = require('./options');
const dumpError = e => {
if (e) console.log('beautify err:', 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,34 +49,142 @@ 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);
}
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) {
delete doc.beautified;
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;
Oops, something went wrong.

0 comments on commit 54078fd

Please sign in to comment.