Skip to content

Commit 33c9c1c

Browse files
feat: VitePress support (#1399)
1 parent 1630f5a commit 33c9c1c

33 files changed

+775
-220
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"autoClosingPairs": [
3+
// html
4+
{
5+
"open": "{",
6+
"close": "}"
7+
},
8+
{
9+
"open": "[",
10+
"close": "]"
11+
},
12+
{
13+
"open": "(",
14+
"close": ")"
15+
},
16+
{
17+
"open": "'",
18+
"close": "'"
19+
},
20+
{
21+
"open": "\"",
22+
"close": "\""
23+
},
24+
{
25+
"open": "<!--",
26+
"close": "-->",
27+
"notIn": [
28+
"comment",
29+
"string"
30+
]
31+
},
32+
// javascript
33+
{
34+
"open": "`",
35+
"close": "`",
36+
"notIn": [
37+
"string",
38+
"comment"
39+
]
40+
},
41+
{
42+
"open": "/**",
43+
"close": " */",
44+
"notIn": [
45+
"string"
46+
]
47+
}
48+
],
49+
"colorizedBracketPairs": [
50+
[
51+
"{{",
52+
"}}"
53+
],
54+
]
55+
}

extensions/vscode-vue-language-features/package.json

+42
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
],
2626
"activationEvents": [
2727
"onLanguage:vue",
28+
"onLanguage:markdown",
2829
"onLanguage:javascript",
2930
"onLanguage:typescript",
3031
"onLanguage:javascriptreact",
@@ -45,6 +46,11 @@
4546
}
4647
},
4748
"contributes": {
49+
"configurationDefaults": {
50+
"[markdown]": {
51+
"editor.quickSuggestions": true
52+
}
53+
},
4854
"jsonValidation": [
4955
{
5056
"fileMatch": "tsconfig.json",
@@ -119,6 +125,10 @@
119125
],
120126
"configuration": "./languages/vue-language-configuration.json"
121127
},
128+
{
129+
"id": "markdown",
130+
"configuration": "./languages/markdown-language-configuration.json"
131+
},
122132
{
123133
"id": "html",
124134
"configuration": "./languages/sfc-template-language-configuration.json"
@@ -450,6 +460,38 @@
450460
"support.class.component.vue"
451461
]
452462
}
463+
},
464+
{
465+
"language": "markdown",
466+
"scopes": {
467+
"property": [
468+
"variable.other.property.vue"
469+
],
470+
"property.readonly": [
471+
"variable.other.constant.property.vue"
472+
],
473+
"variable": [
474+
"variable.other.readwrite.vue"
475+
],
476+
"variable.readonly": [
477+
"variable.other.constant.object.vue"
478+
],
479+
"function": [
480+
"entity.name.function.vue"
481+
],
482+
"namespace": [
483+
"entity.name.type.module.vue"
484+
],
485+
"variable.defaultLibrary": [
486+
"support.variable.vue"
487+
],
488+
"function.defaultLibrary": [
489+
"support.function.vue"
490+
],
491+
"componentTag": [
492+
"support.class.component.vue"
493+
]
494+
}
453495
}
454496
],
455497
"commands": [

extensions/vscode-vue-language-features/src/browserClientMain.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function activate(context: vscode.ExtensionContext) {
1717
initializationOptions: initOptions,
1818
progressOnInitialization: true,
1919
synchronize: {
20-
fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.vue,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.json}')
20+
fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.vue,**/*.md,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.json}')
2121
}
2222
};
2323
const client = new lsp.LanguageClient(

extensions/vscode-vue-language-features/src/common.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export async function activate(context: vscode.ExtensionContext, createLc: Creat
4545
}
4646

4747
const currentlangId = vscode.window.activeTextEditor.document.languageId;
48-
if (currentlangId === 'vue') {
48+
if (currentlangId === 'vue' || currentlangId === 'markdown') {
4949
doActivate(context, createLc);
5050
stopCheck.dispose();
5151
}
@@ -66,23 +66,27 @@ async function doActivate(context: vscode.ExtensionContext, createLc: CreateLang
6666
const languageFeaturesDocumentSelector: lsp.DocumentSelector = takeOverMode ?
6767
[
6868
{ scheme: 'file', language: 'vue' },
69+
{ scheme: 'file', language: 'markdown' },
6970
{ scheme: 'file', language: 'javascript' },
7071
{ scheme: 'file', language: 'typescript' },
7172
{ scheme: 'file', language: 'javascriptreact' },
7273
{ scheme: 'file', language: 'typescriptreact' },
7374
{ scheme: 'file', language: 'json' },
7475
] : [
7576
{ scheme: 'file', language: 'vue' },
77+
{ scheme: 'file', language: 'markdown' },
7678
];
7779
const documentFeaturesDocumentSelector: lsp.DocumentSelector = takeOverMode ?
7880
[
7981
{ language: 'vue' },
82+
{ language: 'markdown' },
8083
{ language: 'javascript' },
8184
{ language: 'typescript' },
8285
{ language: 'javascriptreact' },
8386
{ language: 'typescriptreact' },
8487
] : [
8588
{ language: 'vue' },
89+
{ language: 'markdown' },
8690
];
8791
const _useSecondServer = useSecondServer();
8892
const _serverMaxOldSpaceSize = serverMaxOldSpaceSize();

extensions/vscode-vue-language-features/src/features/attrNameCase.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export async function activate(context: vscode.ExtensionContext, languageClient:
6767
};
6868

6969
async function onChangeDocument(newDoc: vscode.TextDocument | undefined) {
70-
if (newDoc?.languageId === 'vue') {
70+
if (newDoc?.languageId === 'vue' || newDoc?.languageId === 'markdown') {
7171
let attrCase = attrCases.uriGet(newDoc.uri.toString());
7272
if (!attrCase) {
7373
const attrMode = vscode.workspace.getConfiguration('volar').get<'auto-kebab' | 'auto-camel' | 'kebab' | 'camel'>('completion.preferredAttrNameCase');

extensions/vscode-vue-language-features/src/features/autoInsertion.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export async function activate(context: vscode.ExtensionContext, htmlClient: Bas
66

77
const supportedLanguages: Record<string, boolean> = {
88
vue: true,
9+
markdown: true,
910
javascript: true,
1011
typescript: true,
1112
javascriptreact: true,

extensions/vscode-vue-language-features/src/features/tagNameCase.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export async function activate(context: vscode.ExtensionContext, languageClient:
9797
};
9898

9999
async function onChangeDocument(newDoc: vscode.TextDocument | undefined) {
100-
if (newDoc?.languageId === 'vue') {
100+
if (newDoc?.languageId === 'vue' || newDoc?.languageId === 'markdown') {
101101
let tagCase = tagCases.uriGet(newDoc.uri.toString());
102102
if (!tagCase) {
103103
const tagMode = vscode.workspace.getConfiguration('volar').get<'auto' | 'both' | 'kebab' | 'pascal'>('completion.preferredTagNameCase');

extensions/vscode-vue-language-features/src/features/tsVersion.ts

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export async function activate(context: vscode.ExtensionContext, clients: BaseLa
8787
function updateStatusBar() {
8888
if (
8989
vscode.window.activeTextEditor?.document.languageId !== 'vue'
90+
&& vscode.window.activeTextEditor?.document.languageId !== 'markdown'
9091
&& !(
9192
takeOverModeEnabled()
9293
&& vscode.window.activeTextEditor

extensions/vscode-vue-language-features/src/features/tsconfig.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export async function activate(context: vscode.ExtensionContext, languageClient:
2020
async function updateStatusBar() {
2121
if (
2222
vscode.window.activeTextEditor?.document.languageId !== 'vue'
23+
&& vscode.window.activeTextEditor?.document.languageId !== 'markdown'
2324
&& !(
2425
takeOverModeEnabled()
2526
&& vscode.window.activeTextEditor

extensions/vscode-vue-language-features/src/nodeClientMain.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function activate(context: vscode.ExtensionContext) {
3535
initializationOptions: initOptions,
3636
progressOnInitialization: true,
3737
synchronize: {
38-
fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.vue,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.json}')
38+
fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.vue,**/*.md,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.json}')
3939
}
4040
};
4141
const client = new lsp.LanguageClient(

packages/shared/src/common.ts

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export function syntaxToLanguageId(syntax: string) {
1313
case 'jsx': return 'javascriptreact';
1414
case 'tsx': return 'typescriptreact';
1515
case 'pug': return 'jade';
16+
case 'md': return 'markdown';
1617
}
1718
return syntax;
1819
}
@@ -24,6 +25,7 @@ export function languageIdToSyntax(languageId: string) {
2425
case 'javascriptreact': return 'jsx';
2526
case 'typescriptreact': return 'tsx';
2627
case 'jade': return 'pug';
28+
case 'markdown': return 'md';
2729
}
2830
return languageId;
2931
}

packages/typescript-vue-plugin/src/index.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const init: ts.server.PluginModuleFactory = (modules) => {
1919
info.project.getScriptKind = fileName => {
2020
switch (path.extname(fileName)) {
2121
case '.vue': return ts.ScriptKind.TSX; // can't use External, Unknown
22+
case '.md': return ts.ScriptKind.TSX; // can't use External, Unknown
2223
case '.js': return ts.ScriptKind.JS;
2324
case '.jsx': return ts.ScriptKind.JSX;
2425
case '.ts': return ts.ScriptKind.TS;
@@ -158,7 +159,7 @@ function createProxyHost(ts: typeof import('typescript/lib/tsserverlibrary'), in
158159
};
159160

160161
async function onAnyDriveFileUpdated(fileName: string) {
161-
if (fileName.endsWith('.vue') && info.project.fileExists(fileName) && !vueFiles.has(fileName)) {
162+
if ((fileName.endsWith('.vue') || fileName.endsWith('.md')) && info.project.fileExists(fileName) && !vueFiles.has(fileName)) {
162163
onConfigUpdated();
163164
}
164165
}
@@ -202,7 +203,7 @@ function createProxyHost(ts: typeof import('typescript/lib/tsserverlibrary'), in
202203
const parseConfigHost: ts.ParseConfigHost = {
203204
useCaseSensitiveFileNames: info.project.useCaseSensitiveFileNames(),
204205
readDirectory: (path, extensions, exclude, include, depth) => {
205-
return info.project.readDirectory(path, ['.vue'], exclude, include, depth);
206+
return info.project.readDirectory(path, ['.vue', '.md'], exclude, include, depth);
206207
},
207208
fileExists: fileName => info.project.fileExists(fileName),
208209
readFile: fileName => info.project.readFile(fileName),

packages/vue-code-gen/src/generators/template.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export function generate(
6565
allowTypeNarrowingInEventExpressions: boolean,
6666
hasScriptSetup: boolean,
6767
cssScopedClasses: string[] = [],
68-
htmlToTemplate: (htmlStart: number, htmlEnd: number) => { start: number, end: number; } | undefined,
68+
htmlToTemplate: (htmlRange: { start: number, end: number; }) => { start: number, end: number; } | undefined,
6969
searchTexts: {
7070
getEmitCompletion(tag: string): string,
7171
getPropsCompletion(tag: string): string,
@@ -228,7 +228,7 @@ export function generate(
228228
tagResolves[tagName] = {
229229
component: var_rawComponent,
230230
emit: var_emit,
231-
offsets: tagOffsets.map(offset => htmlToTemplate(offset, offset)?.start).filter(notEmpty),
231+
offsets: tagOffsets.map(offset => htmlToTemplate({ start: offset, end: offset })?.start).filter(notEmpty),
232232
};
233233
}
234234

@@ -1182,7 +1182,7 @@ export function generate(
11821182
end: prop.arg.loc.start.offset + end,
11831183
};
11841184

1185-
const newStart = htmlToTemplate(sourceRange.start, sourceRange.end)?.start;
1185+
const newStart = htmlToTemplate({ start: sourceRange.start, end: sourceRange.end })?.start;
11861186
if (newStart === undefined) continue;
11871187
const offset = newStart - sourceRange.start;
11881188
sourceRange.start += offset;
@@ -1847,7 +1847,7 @@ export function generate(
18471847
function addMapping(gen: typeof tsCodeGen, mapping: SourceMaps.Mapping<EmbeddedFileMappingData>) {
18481848
const newMapping = { ...mapping };
18491849

1850-
const templateStart = htmlToTemplate(mapping.sourceRange.start, mapping.sourceRange.end)?.start;
1850+
const templateStart = htmlToTemplate(mapping.sourceRange)?.start;
18511851
if (templateStart === undefined) return; // not found
18521852
const offset = templateStart - mapping.sourceRange.start;
18531853
newMapping.sourceRange = {
@@ -1858,7 +1858,7 @@ export function generate(
18581858
if (mapping.additional) {
18591859
newMapping.additional = [];
18601860
for (const other of mapping.additional) {
1861-
let otherTemplateStart = htmlToTemplate(other.sourceRange.start, other.sourceRange.end)?.start;
1861+
let otherTemplateStart = htmlToTemplate(other.sourceRange)?.start;
18621862
if (otherTemplateStart === undefined) continue;
18631863
const otherOffset = otherTemplateStart - other.sourceRange.start;
18641864
newMapping.additional.push({

packages/vue-language-server/src/features/languageFeatures.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ export function register(
279279
});
280280
connection.workspace.onWillRenameFiles(async handler => {
281281

282-
const hasTsFile = handler.files.some(file => file.newUri.endsWith('.vue') || file.newUri.endsWith('.ts') || file.newUri.endsWith('.tsx'));
282+
const hasTsFile = handler.files.some(file => file.newUri.endsWith('.vue') || file.newUri.endsWith('.md') || file.newUri.endsWith('.ts') || file.newUri.endsWith('.tsx'));
283283
const config: 'prompt' | 'always' | 'never' | null | undefined = await connection.workspace.getConfiguration(hasTsFile ? 'typescript.updateImportsOnFileMove.enabled' : 'javascript.updateImportsOnFileMove.enabled');
284284

285285
if (config === 'always') {

packages/vue-language-server/src/project.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export async function createProject(
243243
const parseConfigHost: ts.ParseConfigHost = {
244244
useCaseSensitiveFileNames: projectSys.useCaseSensitiveFileNames,
245245
readDirectory: (path, extensions, exclude, include, depth) => {
246-
return projectSys.readDirectory(path, [...extensions, '.vue'], exclude, include, depth);
246+
return projectSys.readDirectory(path, [...extensions, '.vue', '.md'], exclude, include, depth);
247247
},
248248
fileExists: projectSys.fileExists,
249249
readFile: projectSys.readFile,

packages/vue-language-server/src/registers/registerlanguageFeatures.ts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export function register(
3636
willRename: {
3737
filters: [
3838
{ pattern: { glob: '**/*.vue' } },
39+
{ pattern: { glob: '**/*.md' } },
3940
{ pattern: { glob: '**/*.js' } },
4041
{ pattern: { glob: '**/*.ts' } },
4142
{ pattern: { glob: '**/*.jsx' } },

packages/vue-language-service/src/documentService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export function getDocumentService(
116116

117117
function getVueDocument(document: TextDocument) {
118118

119-
if (document.languageId !== 'vue')
119+
if (document.languageId !== 'vue' && document.languageId !== 'markdown')
120120
return;
121121

122122
let vueDoc = vueDocuments.get(document);

packages/vue-language-service/src/languageService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ export function createLanguageService(
327327

328328
document = TextDocument.create(
329329
uri,
330-
uri.endsWith('.vue') ? 'vue' : 'typescript', // TODO
330+
shared.syntaxToLanguageId(upath.extname(uri).slice(1)),
331331
newVersion,
332332
scriptSnapshot.getText(0, scriptSnapshot.getLength()),
333333
);

packages/vue-language-service/src/plugins/vue-convert-htmlpug.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export default function (options: {
9595
function worker<T>(uri: string, callback: (vueDocument: VueDocument) => T) {
9696

9797
const vueDocument = options.getVueDocument(uri);
98-
if (!vueDocument)
98+
if (!vueDocument || vueDocument.file.fileName.endsWith('.md'))
9999
return;
100100

101101
return callback(vueDocument);

0 commit comments

Comments
 (0)