Skip to content

Commit e53d19c

Browse files
committed
format
format
1 parent 77e1b00 commit e53d19c

File tree

211 files changed

+43414
-405
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

211 files changed

+43414
-405
lines changed

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"compile-hero.disable-compile-files-on-did-save-code": true
3+
}

CHANGELOG.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ All notable changes to the `Vue` extension will be documented in this file.
55
- 2019.11.28 Update html sinppets
66
- 2019.11.29 Update javascript sinppets
77
- 2019.11.30 Delete useless configuration
8-
- 2019.12.1 Change the extension logo
9-
- 2019.12.2 Update html and javascript sinppets
10-
- 2019.12.3 Add vue snippets
8+
- 2019.12.01 Change the extension logo
9+
- 2019.12.02 Update html and javascript sinppets
10+
- 2019.12.03 Add vue snippets
11+
- 2020.08.22 Add syntax highlight
12+
- 2020.08.23 Support formatting
1113

1214
# Unreleased
1315

README.md

+226-393
Large diffs are not rendered by default.

extension.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const vscode = require("vscode");
2+
const statusBarUi = require("./status");
3+
const format = require('./format');
4+
5+
function activate(context) {
6+
let compileOff = vscode.commands.registerCommand("vue3snippets.compileOff", () => {
7+
let config = vscode.workspace.getConfiguration("vue3snippets");
8+
config.update("enable-compile-vue-file-on-did-save-code", true);
9+
statusBarUi.StatusBarUi.watching();
10+
});
11+
let compileOn = vscode.commands.registerCommand("vue3snippets.compileOn", () => {
12+
let config = vscode.workspace.getConfiguration("vue3snippets");
13+
config.update("enable-compile-vue-file-on-did-save-code", false);
14+
statusBarUi.StatusBarUi.notWatching();
15+
});
16+
context.subscriptions.push(compileOn);
17+
context.subscriptions.push(compileOff);
18+
vscode.workspace.onDidSaveTextDocument(() => {
19+
let config = vscode.workspace.getConfiguration("vue3snippets");
20+
let isEnableOnDidSaveTextDocument = config.get("enable-compile-vue-file-on-did-save-code");
21+
if (!isEnableOnDidSaveTextDocument) { return };
22+
let activeTextEditor = vscode.window.activeTextEditor;
23+
if (activeTextEditor && activeTextEditor.document.languageId === 'vue') {
24+
format.init();
25+
} else {
26+
vscode.window.showInformationMessage('It‘s not a .vue file');
27+
}
28+
});
29+
statusBarUi.StatusBarUi.init(vscode.workspace.getConfiguration("vue3snippets").get("enable-compile-vue-file-on-did-save-code"));
30+
}
31+
exports.activate = activate;
32+
function deactivate() {
33+
}
34+
exports.deactivate = deactivate;

format/index.js

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
const {
2+
window,
3+
Position,
4+
Range,
5+
workspace
6+
} = require('vscode');
7+
const beautify = require('js-beautify');
8+
const pugBeautify = require('pug-beautify');
9+
const {
10+
breakTagAttr
11+
} = require('./plugins');
12+
let defaultConf = require('./js-beautify.conf');
13+
let editor;
14+
15+
let methods = {
16+
doc: null,
17+
text: '',
18+
newText: '',
19+
lineCount: 1,
20+
jsBeautifyConf: defaultConf['js-beautify'],
21+
pugBeautifyConf: defaultConf['pug-beautify'],
22+
editorConf: {},
23+
init() {
24+
// 活动窗口tab
25+
editor = window.activeTextEditor;
26+
if (!editor) throw new Error('no active editor');
27+
// 当前窗口document
28+
this.doc = editor.document;
29+
// 获取配置
30+
this.getConfig();
31+
32+
// 行数
33+
this.lineCount = this.doc.lineCount;
34+
// 内容
35+
this.text = this.doc.getText();
36+
// 每次执行清空格式化后的内容
37+
this.newText = '';
38+
// 分别处理 html(pug)、css、js
39+
this.splitContent(this.text);
40+
// 内容回写到文件
41+
this.writeFile();
42+
},
43+
splitContent(text) {
44+
let formatNeed = this.vueFormatConf.format_need || ['html', 'js', 'css'];
45+
46+
let htmlText = text.match(/<template[\w\W]+<\/template>\s?/);
47+
let jsText = text.match(/<script[\w\W]+<\/script>\s?/);
48+
let cssText = text.match(/<style[\w\W]+<\/style>\s?/);
49+
50+
if (htmlText && formatNeed.includes('html')) {
51+
text = text.replace(htmlText[0], this.beautyHtml(htmlText[0]) + '\n');
52+
}
53+
if (jsText && formatNeed.includes('js')) {
54+
let jsArr = jsText[0].split(/<\/script>\n*/);
55+
jsArr.forEach((item, index) => {
56+
let pre = '';
57+
if (index === 0) {
58+
pre = '\n';
59+
}
60+
let str = item + '</script>';
61+
text = item ? text.replace(str, pre + this.beautyJs(str)) : text;
62+
});
63+
}
64+
if (cssText && formatNeed.includes('css')) {
65+
let cssArr = cssText[0].split(/<\/style>\n*/);
66+
cssArr.forEach((item, index) => {
67+
let pre = '';
68+
if (index === 0) {
69+
pre = '\n';
70+
}
71+
let str = item + '</style>';
72+
text = item ? text.replace(str, pre + this.beautyCss(str)) : text;
73+
});
74+
}
75+
this.newText = text.replace(/(\n|\t|\r)\s*(\n|\t|\r){2,}/g, '$1$1').trim() + '\n';
76+
},
77+
mergeFormatTag(arrUnFormat = [], arrForceFormat = []) {
78+
arrForceFormat.forEach(item => {
79+
let index = arrUnFormat.indexOf(item);
80+
if (index > -1) {
81+
arrUnFormat.splice(index, 1);
82+
}
83+
});
84+
return arrUnFormat;
85+
},
86+
beautyHtml(text) {
87+
let str = '';
88+
let defaultHtmlOptions = beautify.html.defaultOptions();
89+
let htmlUnFormat = defaultHtmlOptions.inline;
90+
let indentRoot = this.vueFormatConf['html_indent_root'] || false;
91+
let functional = /<template[^>]*\s+functional/.test(text) ? ' functional' : '';
92+
let lang = this.getLang(text);
93+
94+
text = indentRoot ? text : text.replace(/<template[^>]*>([\w\W]+)<\/template>/, '$1');
95+
if (/pug/.test(lang)) {
96+
str = pugBeautify(text, this.pugBeautifyConf)
97+
.trim();
98+
} else {
99+
let tempConf = Object.assign(this.jsBeautifyConf, this.jsBeautifyConf.html);
100+
str = beautify.html(text, tempConf);
101+
if (tempConf.wrap_attributes == 'auto' && +this.vueFormatConf.break_attr_limit > -1) {
102+
str = breakTagAttr(str, +this.vueFormatConf.break_attr_limit, {
103+
indentSize: +this.jsBeautifyConf.indent_size,
104+
attrEndWithGt: this.vueFormatConf.attr_end_with_gt,
105+
tempConf: Object.assign(tempConf, {
106+
unBreakAttrList: htmlUnFormat
107+
})
108+
});
109+
}
110+
}
111+
112+
return indentRoot ? `${str}\n` : `<template${lang}${functional}>\n${str}\n</template>\n`;
113+
},
114+
beautyCss(text) {
115+
let scoped = /<style[^>]*\s+scoped/.test(text) ? ' scoped' : '';
116+
let lang = this.getLang(text);
117+
let str = text;
118+
text = text.replace(/<style[^>]*>([\w\W]*)<\/style>/, '$1');
119+
if (text.trim()) {
120+
let tempConf = Object.assign({}, this.jsBeautifyConf, this.jsBeautifyConf.css);
121+
str = beautify.css(text, tempConf);
122+
return `<style${lang}${scoped}>\n${str}\n</style>`;
123+
} else {
124+
return str;
125+
}
126+
},
127+
beautyJs(text) {
128+
let scoped = /<script[^>]*\s+scoped/.test(text) ? ' scoped' : '';
129+
let lang = this.getLang(text);
130+
let str = text;
131+
text = text.replace(/<script[^>]*>([\w\W]*)<\/script>/, '$1');
132+
if (text.trim()) {
133+
let tempConf = Object.assign({}, this.jsBeautifyConf, this.jsBeautifyConf.js);
134+
str = beautify.js(text, tempConf);
135+
return `<script${lang}${scoped}>\n${str}\n</script>`;
136+
} else {
137+
return str;
138+
}
139+
},
140+
getLang(text) {
141+
let lang = text.match(/lang=(["'])([a-zA-Z\-\_]*)\1/, '$2');
142+
return lang && ` lang="${lang.pop()}"` || '';
143+
},
144+
writeFile() {
145+
let start = new Position(0, 0);
146+
let end = new Position(this.lineCount + 1, 0);
147+
let range = new Range(start, end);
148+
editor.edit((editBuilder, error) => {
149+
error && window.showErrorMessage(error);
150+
editBuilder.replace(range, this.newText);
151+
});
152+
},
153+
getConfig() {
154+
155+
this.editorConf = Object.assign({}, workspace.getConfiguration('editor'));
156+
this.initDefaultJsBConf(this.jsBeautifyConf);
157+
let vueFormatConf = workspace.getConfiguration('vue3snippets');
158+
this.vueFormatConf = vueFormatConf;
159+
if (!vueFormatConf) {
160+
return;
161+
}
162+
let jsBConf = vueFormatConf.get('js-beautify') || {};
163+
this.mergeBeautifyConf(jsBConf, 'jsBeautifyConf');
164+
let pugBConf = vueFormatConf.get('pug-beautify') || {};
165+
this.mergeBeautifyConf(pugBConf, 'pugBeautifyConf');
166+
},
167+
initDefaultJsBConf(conf) {
168+
this.jsBeautifyConf.indent_size = this.editorConf.tabSize;
169+
if (this.editorConf.insertSpaces) {
170+
this.jsBeautifyConf.indent_char = ' ';
171+
} else {
172+
this.indent_with_tabs = true;
173+
}
174+
},
175+
mergeBeautifyConf(conf, type) {
176+
for (let k in conf) {
177+
let cont = conf[k];
178+
if (typeof cont === 'string') {
179+
let teMatch = cont.match(/editor\.(\w+)/g);
180+
if (teMatch) {
181+
let editKey = teMatch[0].replace('editor.', '');
182+
cont = this.editorConf[editKey];
183+
}
184+
}
185+
if (cont instanceof Object) {
186+
Object.assign(this[type][k], cont);
187+
} else {
188+
this[type][k] = cont;
189+
}
190+
}
191+
return this[type];
192+
}
193+
};
194+
195+
module.exports = methods;

format/js-beautify.conf.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module.exports = {
2+
"html_indent_root": false,
3+
"break_attr_limit": -1,
4+
"attr_end_with_gt": true,
5+
"format_need": ["html", "js", "css"],
6+
"js-beautify": {
7+
"indent_size": "editor.tabSize",
8+
"indent_char": " ",
9+
"indent_with_tabs": false,
10+
"brace-style": "collapse",
11+
"space_after_anon_function": true,
12+
"css": {},
13+
"js": {},
14+
"html": {
15+
"force_format": ["template"],
16+
"wrap_attributes": "auto"
17+
}
18+
},
19+
"pug-beautify": {
20+
"fill_tab": false
21+
}
22+
};

format/plugins.js

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* 强制多属性换行
3+
* @param {String} str 需要格式化的字符串
4+
* @param {Number} breakLimitNum 多余这个数量的属性,才会断行
5+
*/
6+
7+
function breakTagAttr(str = '', breakLimitNum = 1, opt = {
8+
indentSize: 4,
9+
attrEndWithGt: true,
10+
tempConf: {}
11+
}) {
12+
if (breakLimitNum === -1) {
13+
return str;
14+
}
15+
let {
16+
indentSize,
17+
attrEndWithGt,
18+
tempConf
19+
} = opt;
20+
let {
21+
unBreakAttrList
22+
} = tempConf;
23+
let padIndent = ' '.repeat(indentSize);
24+
const TAG_REG = /[\n\r\t]*(\s*)\<[A-z\-\_0-9]+/;
25+
const TAG_END_REG = /\s*(>|\/>)/;
26+
const TAG_NAME_REG = /\<([A-z][\w\-]*)/;
27+
28+
const ATTR_REG = /(\s(\:|\@)?[A-z0-9\-\_\.\:]+(=("[^"]*"|'[^']+'|`[^`]+`|[A-z0-9\_]+))?)/g;
29+
const TAG_ATTR_REG = new RegExp(TAG_REG.source + ATTR_REG.source + '+' + TAG_END_REG.source, 'g');
30+
const TAG_CLOSE_REG = new RegExp(TAG_END_REG.source + '$');
31+
32+
let loop = true;
33+
while (loop) {
34+
// 匹配带有属性的 start tag
35+
let res = TAG_ATTR_REG.exec(str);
36+
if (res) {
37+
// 缩进
38+
let indent = res[1];
39+
// tag 内容
40+
let tagContent = res[0];
41+
let tagName = tagContent.match(TAG_NAME_REG);
42+
if (unBreakAttrList.includes(tagName[1])) {
43+
// 行内标签
44+
continue;
45+
}
46+
// console.log(tagContent + '\n\n');
47+
// 匹配 tagContent 的 attr
48+
let matchRes = tagContent.match(ATTR_REG);
49+
// matchRes 处理
50+
// console.log(matchRes);
51+
if (matchRes.length > breakLimitNum) { // 一个属性强制断行,或者多属性
52+
// 每个 attr 先 trim,然后加换行,空格
53+
let newStr = tagContent.replace(ATTR_REG, (match, $1) => {
54+
return '\n' + indent + padIndent + $1.trim();
55+
});
56+
// tag 结束括号换行
57+
newStr = attrEndWithGt ? newStr : newStr.replace(TAG_CLOSE_REG, '\n' + indent + '$1');
58+
// 替换整个字符串中的对应内容
59+
str = str.replace(tagContent, newStr);
60+
}
61+
} else {
62+
loop = false;
63+
}
64+
}
65+
return str;
66+
}
67+
68+
module.exports = {
69+
breakTagAttr
70+
};

node_modules/.bin/css-beautify

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/.bin/editorconfig

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/.bin/html-beautify

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/.bin/js-beautify

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/.bin/mkdirp

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/.bin/nopt

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/.bin/semver

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)