Skip to content

Commit 56ae259

Browse files
authored
feat(vscode): add settings to enable per-block formatting (#5784)
1 parent 2f2352d commit 56ae259

File tree

10 files changed

+218
-1
lines changed

10 files changed

+218
-1
lines changed

extensions/vscode/lib/generated-meta.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Meta info
55
export const publisher = 'Vue';
66
export const name = 'volar';
7-
export const version = '3.1.0';
7+
export const version = '3.1.5';
88
export const displayName = 'Vue (Official)';
99
export const description = 'Language Support for Vue';
1010
export const extensionId = `${publisher}.${name}`;
@@ -56,6 +56,9 @@ export type ConfigKey =
5656
| 'vue.format.template.initialIndent'
5757
| 'vue.format.script.initialIndent'
5858
| 'vue.format.style.initialIndent'
59+
| 'vue.format.script.enabled'
60+
| 'vue.format.template.enabled'
61+
| 'vue.format.style.enabled'
5962
| 'vue.format.wrapAttributes';
6063

6164
export interface ConfigKeyTypeMap {
@@ -79,6 +82,9 @@ export interface ConfigKeyTypeMap {
7982
'vue.format.template.initialIndent': boolean;
8083
'vue.format.script.initialIndent': boolean;
8184
'vue.format.style.initialIndent': boolean;
85+
'vue.format.script.enabled': boolean;
86+
'vue.format.template.enabled': boolean;
87+
'vue.format.style.enabled': boolean;
8288
'vue.format.wrapAttributes':
8389
| 'auto'
8490
| 'force'
@@ -110,6 +116,9 @@ export interface ConfigShorthandMap {
110116
formatTemplateInitialIndent: 'vue.format.template.initialIndent';
111117
formatScriptInitialIndent: 'vue.format.script.initialIndent';
112118
formatStyleInitialIndent: 'vue.format.style.initialIndent';
119+
formatScriptEnabled: 'vue.format.script.enabled';
120+
formatTemplateEnabled: 'vue.format.template.enabled';
121+
formatStyleEnabled: 'vue.format.style.enabled';
113122
formatWrapAttributes: 'vue.format.wrapAttributes';
114123
}
115124

@@ -134,6 +143,9 @@ export interface ConfigShorthandTypeMap {
134143
formatTemplateInitialIndent: boolean;
135144
formatScriptInitialIndent: boolean;
136145
formatStyleInitialIndent: boolean;
146+
formatScriptEnabled: boolean;
147+
formatTemplateEnabled: boolean;
148+
formatStyleEnabled: boolean;
137149
formatWrapAttributes:
138150
| 'auto'
139151
| 'force'
@@ -333,6 +345,33 @@ export const configs = {
333345
key: 'vue.format.style.initialIndent',
334346
default: false,
335347
} as ConfigItem<'vue.format.style.initialIndent'>,
348+
/**
349+
* @key `vue.format.script.enabled`
350+
* @default `true`
351+
* @type `boolean`
352+
*/
353+
formatScriptEnabled: {
354+
key: 'vue.format.script.enabled',
355+
default: true,
356+
} as ConfigItem<'vue.format.script.enabled'>,
357+
/**
358+
* @key `vue.format.template.enabled`
359+
* @default `true`
360+
* @type `boolean`
361+
*/
362+
formatTemplateEnabled: {
363+
key: 'vue.format.template.enabled',
364+
default: true,
365+
} as ConfigItem<'vue.format.template.enabled'>,
366+
/**
367+
* @key `vue.format.style.enabled`
368+
* @default `true`
369+
* @type `boolean`
370+
*/
371+
formatStyleEnabled: {
372+
key: 'vue.format.style.enabled',
373+
default: true,
374+
} as ConfigItem<'vue.format.style.enabled'>,
336375
/**
337376
* @key `vue.format.wrapAttributes`
338377
* @default `"auto"`
@@ -365,6 +404,9 @@ export interface ScopedConfigKeyTypeMap {
365404
'format.template.initialIndent': boolean;
366405
'format.script.initialIndent': boolean;
367406
'format.style.initialIndent': boolean;
407+
'format.script.enabled': boolean;
408+
'format.template.enabled': boolean;
409+
'format.style.enabled': boolean;
368410
'format.wrapAttributes':
369411
| 'auto'
370412
| 'force'
@@ -398,6 +440,9 @@ export const scopedConfigs = {
398440
'format.template.initialIndent': true,
399441
'format.script.initialIndent': false,
400442
'format.style.initialIndent': false,
443+
'format.script.enabled': true,
444+
'format.template.enabled': true,
445+
'format.style.enabled': true,
401446
'format.wrapAttributes': 'auto',
402447
} satisfies ScopedConfigKeyTypeMap,
403448
};
@@ -438,12 +483,15 @@ export interface NestedConfigs {
438483
'format': {
439484
'template': {
440485
'initialIndent': boolean;
486+
'enabled': boolean;
441487
};
442488
'script': {
443489
'initialIndent': boolean;
490+
'enabled': boolean;
444491
};
445492
'style': {
446493
'initialIndent': boolean;
494+
'enabled': boolean;
447495
};
448496
'wrapAttributes':
449497
| 'auto'
@@ -492,12 +540,15 @@ export interface NestedScopedConfigs {
492540
'format': {
493541
'template': {
494542
'initialIndent': boolean;
543+
'enabled': boolean;
495544
};
496545
'script': {
497546
'initialIndent': boolean;
547+
'enabled': boolean;
498548
};
499549
'style': {
500550
'initialIndent': boolean;
551+
'enabled': boolean;
501552
};
502553
'wrapAttributes':
503554
| 'auto'

extensions/vscode/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,21 @@
380380
"default": false,
381381
"markdownDescription": "%configuration.format.style.initialIndent%"
382382
},
383+
"vue.format.script.enabled": {
384+
"type": "boolean",
385+
"default": true,
386+
"markdownDescription": "%configuration.format.script.enabled%"
387+
},
388+
"vue.format.template.enabled": {
389+
"type": "boolean",
390+
"default": true,
391+
"markdownDescription": "%configuration.format.template.enabled%"
392+
},
393+
"vue.format.style.enabled": {
394+
"type": "boolean",
395+
"default": true,
396+
"markdownDescription": "%configuration.format.style.enabled%"
397+
},
383398
"vue.format.wrapAttributes": {
384399
"type": "string",
385400
"default": "auto",

extensions/vscode/package.nls.ja.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"configuration.format.template.initialIndent": "`<template>` ブロックの初期インデント。",
1717
"configuration.format.script.initialIndent": "`<script>` ブロックの初期インデント。",
1818
"configuration.format.style.initialIndent": "`<style>` ブロックの初期インデント。",
19+
"configuration.format.template.enabled": "`<template>` ブロックのフォーマットを有効化。",
20+
"configuration.format.script.enabled": "`<script>` ブロックのフォーマットを有効化。",
21+
"configuration.format.style.enabled": "`<style>` ブロックのフォーマットを有効化。",
1922
"configuration.format.wrapAttributes": "属性を折り返します。",
2023
"configuration.editor.focusMode": "トップレベル SFC タグをフェード。",
2124
"configuration.editor.reactivityVisualization": "リアクティブシステムの可視化。",

extensions/vscode/package.nls.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"configuration.format.template.initialIndent": "Initial indent for `<template>` block.",
1717
"configuration.format.script.initialIndent": "Initial indent for `<script>` block.",
1818
"configuration.format.style.initialIndent": "Initial indent for `<style>` block.",
19+
"configuration.format.template.enabled": "Enable formatting for `<template>` block.",
20+
"configuration.format.script.enabled": "Enable formatting for `<script>` block.",
21+
"configuration.format.style.enabled": "Enable formatting for `<style>` block.",
1922
"configuration.format.wrapAttributes": "Wrap attributes.",
2023
"configuration.editor.focusMode": "Fade top-level SFC tags.",
2124
"configuration.editor.reactivityVisualization": "Reactivity system visualization.",

extensions/vscode/package.nls.ru.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"configuration.format.template.initialIndent": "Начальный отступ для блока `<template>`.",
1717
"configuration.format.script.initialIndent": "Начальный отступ для блока `<script>`.",
1818
"configuration.format.style.initialIndent": "Начальный отступ для блока `<style>`.",
19+
"configuration.format.template.enabled": "Включить форматирование для блока `<template>`.",
20+
"configuration.format.script.enabled": "Включить форматирование для блока `<script>`.",
21+
"configuration.format.style.enabled": "Включить форматирование для блока `<style>`.",
1922
"configuration.format.wrapAttributes": "Переносить атрибуты.",
2023
"configuration.editor.focusMode": "Затемнить теги SFC верхнего уровня.",
2124
"configuration.editor.reactivityVisualization": "Визуализация системы реактивности.",

extensions/vscode/package.nls.zh-CN.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"configuration.format.template.initialIndent": "`<template>` 块的初始缩进。",
1717
"configuration.format.script.initialIndent": "`<script>` 块的初始缩进。",
1818
"configuration.format.style.initialIndent": "`<style>` 块的初始缩进。",
19+
"configuration.format.template.enabled": "启用 `<template>` 块的格式化。",
20+
"configuration.format.script.enabled": "启用 `<script>` 块的格式化。",
21+
"configuration.format.style.enabled": "启用 `<style>` 块的格式化。",
1922
"configuration.format.wrapAttributes": "对属性进行换行。",
2023
"configuration.editor.focusMode": "淡化顶层 SFC 标签。",
2124
"configuration.editor.reactivityVisualization": "响应性系统可视化。",

extensions/vscode/package.nls.zh-TW.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"configuration.format.template.initialIndent": "`<template>` 區塊的初始縮排。",
1717
"configuration.format.script.initialIndent": "`<script>` 區塊的初始縮排。",
1818
"configuration.format.style.initialIndent": "`<style>` 區塊的初始縮排。",
19+
"configuration.format.template.enabled": "啟用 `<template>` 區塊的格式化。",
20+
"configuration.format.script.enabled": "啟用 `<script>` 區塊的格式化。",
21+
"configuration.format.style.enabled": "啟用 `<style>` 區塊的格式化。",
1922
"configuration.format.wrapAttributes": "對屬性進行換行。",
2023
"configuration.editor.focusMode": "淡化頂層 SFC 標籤。",
2124
"configuration.editor.reactivityVisualization": "響應性系統視覺化。",

packages/language-service/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { create as createVueDirectiveCommentsPlugin } from './lib/plugins/vue-di
2020
import { create as createVueDocumentDropPlugin } from './lib/plugins/vue-document-drop';
2121
import { create as createVueDocumentHighlightsPlugin } from './lib/plugins/vue-document-highlights';
2222
import { create as createVueExtractFilePlugin } from './lib/plugins/vue-extract-file';
23+
import { create as createVueFormatTakeOverPlugin } from './lib/plugins/vue-format-takeover';
2324
import { create as createVueGlobalTypesErrorPlugin } from './lib/plugins/vue-global-types-error';
2425
import { create as createVueInlayHintsPlugin } from './lib/plugins/vue-inlayhints';
2526
import { create as createVueMissingPropsHintsPlugin } from './lib/plugins/vue-missing-props-hints';
@@ -43,6 +44,7 @@ export function createVueLanguageServicePlugins(
4344
return [
4445
createJsonPlugin(),
4546
createPugFormatPlugin(),
47+
createVueFormatTakeOverPlugin(),
4648
createVueAutoSpacePlugin(),
4749
createVueCompilerDomErrorsPlugin(),
4850
createVueDirectiveCommentsPlugin(),
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import type { LanguageServicePlugin, LanguageServicePluginInstance, TextDocument } from '@volar/language-service';
2+
import { URI } from 'vscode-uri';
3+
4+
export function create(): LanguageServicePlugin {
5+
return {
6+
name: 'vue-format-takeover',
7+
capabilities: {
8+
documentFormattingProvider: true,
9+
documentOnTypeFormattingProvider: {
10+
triggerCharacters: [],
11+
},
12+
},
13+
create(context): LanguageServicePluginInstance {
14+
return {
15+
async provideDocumentFormattingEdits(document) {
16+
if (await shouldSkip(document)) {
17+
return [];
18+
}
19+
return undefined;
20+
},
21+
async provideOnTypeFormattingEdits(document) {
22+
if (await shouldSkip(document)) {
23+
return [];
24+
}
25+
return undefined;
26+
},
27+
};
28+
async function shouldSkip(document: TextDocument): Promise<boolean> {
29+
const decoded = context.decodeEmbeddedDocumentUri(URI.parse(document.uri));
30+
if (!decoded) {
31+
return false;
32+
}
33+
34+
const [, embeddedCodeId] = decoded;
35+
36+
if (embeddedCodeId === 'script_raw' || embeddedCodeId === 'scriptsetup_raw') {
37+
return await context.env.getConfiguration<boolean>?.('vue.format.script.enabled') === false;
38+
}
39+
if (embeddedCodeId.startsWith('style_')) {
40+
return await context.env.getConfiguration<boolean>?.('vue.format.style.enabled') === false;
41+
}
42+
if (
43+
embeddedCodeId === 'template'
44+
|| embeddedCodeId.startsWith('template_inline_ts_')
45+
|| embeddedCodeId === 'root_tags'
46+
) {
47+
return await context.env.getConfiguration<boolean>?.('vue.format.template.enabled') === false;
48+
}
49+
50+
return false;
51+
}
52+
},
53+
};
54+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { defineFormatTest } from '../utils/format';
2+
3+
const snippet = `
4+
<template>
5+
<div />
6+
</template>
7+
<script>
8+
if (true)
9+
console.log('hello');
10+
</script>
11+
<style>
12+
body {
13+
color: red;
14+
}
15+
</style>`;
16+
17+
const units = {
18+
'vue.format.style.enabled': {
19+
description: 'disable style formatting',
20+
output: `
21+
<template>
22+
\t<div />
23+
</template>
24+
<script>
25+
if (true)
26+
\tconsole.log('hello');
27+
</script>
28+
<style>
29+
body {
30+
color: red;
31+
}
32+
</style>
33+
`,
34+
},
35+
'vue.format.script.enabled': {
36+
description: 'disable script formatting',
37+
output: `
38+
<template>
39+
\t<div />
40+
</template>
41+
<script>
42+
if (true)
43+
console.log('hello');
44+
</script>
45+
<style>
46+
body {
47+
\tcolor: red;
48+
}
49+
</style>
50+
`,
51+
},
52+
'vue.format.template.enabled': {
53+
description: 'disable template formatting',
54+
output: `
55+
<template>
56+
<div />
57+
</template>
58+
<script>
59+
if (true)
60+
\tconsole.log('hello');
61+
</script>
62+
<style>
63+
body {
64+
\tcolor: red;
65+
}
66+
</style>
67+
`,
68+
},
69+
};
70+
71+
for (const [setting, { description, output }] of Object.entries(units)) {
72+
const title = '#' + __filename.split('.')[0];
73+
defineFormatTest({
74+
title: title + ' (' + description + ')',
75+
languageId: 'vue',
76+
input: snippet.trim(),
77+
output: output.trim(),
78+
settings: { [setting]: false },
79+
});
80+
}

0 commit comments

Comments
 (0)