volar-service-markdown 0.0.45 → 0.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +3 -2
- package/index.js +177 -145
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type DocumentSelector, type LanguageServicePlugin, type ProviderResult, type ServiceContext } from '@volar/language-service';
|
|
2
2
|
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
3
|
import type { DiagnosticOptions, IMdLanguageService } from 'vscode-markdown-languageservice';
|
|
4
4
|
export interface Provide {
|
|
5
5
|
'markdown/languageService': () => IMdLanguageService;
|
|
6
6
|
}
|
|
7
|
-
export declare function create({ documentSelector, getDiagnosticOptions, }?: {
|
|
7
|
+
export declare function create({ documentSelector, fileExtensions, getDiagnosticOptions, }?: {
|
|
8
8
|
documentSelector?: DocumentSelector;
|
|
9
|
+
fileExtensions?: string[];
|
|
9
10
|
getDiagnosticOptions?(document: TextDocument, context: ServiceContext): ProviderResult<DiagnosticOptions | undefined>;
|
|
10
11
|
}): LanguageServicePlugin;
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -7,22 +7,23 @@ const vscode_markdown_languageservice_1 = require("vscode-markdown-languageservi
|
|
|
7
7
|
const vscode_uri_1 = require("vscode-uri");
|
|
8
8
|
const MarkdownIt = require("markdown-it");
|
|
9
9
|
const md = new MarkdownIt();
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
function create({ documentSelector = ['markdown'], fileExtensions = [
|
|
11
|
+
'md',
|
|
12
|
+
'mkd',
|
|
13
|
+
'mdwn',
|
|
14
|
+
'mdown',
|
|
15
|
+
'markdown',
|
|
16
|
+
'markdn',
|
|
17
|
+
'mdtxt',
|
|
18
|
+
'mdtext',
|
|
19
|
+
'workbook',
|
|
20
|
+
], getDiagnosticOptions = async (_document, context) => {
|
|
16
21
|
return await context.env.getConfiguration?.('markdown.validate');
|
|
17
22
|
}, } = {}) {
|
|
18
23
|
return {
|
|
19
24
|
name: 'markdown',
|
|
20
25
|
triggerCharacters: ['.', '/', '#'],
|
|
21
26
|
create(context) {
|
|
22
|
-
let lastProjectVersion;
|
|
23
|
-
const { fs, onDidChangeWatchedFiles } = context.env;
|
|
24
|
-
assert(fs, 'context.env.fs must be defined');
|
|
25
|
-
assert(onDidChangeWatchedFiles, 'context.env.fs.onDidChangeWatchedFiles must be defined');
|
|
26
27
|
const logger = {
|
|
27
28
|
level: vscode_markdown_languageservice_1.LogLevel.Off,
|
|
28
29
|
log(_logLevel, message) {
|
|
@@ -35,136 +36,24 @@ function create({ documentSelector = ['markdown'], getDiagnosticOptions = async
|
|
|
35
36
|
return md.parse(document.getText(), {});
|
|
36
37
|
}
|
|
37
38
|
};
|
|
38
|
-
const
|
|
39
|
-
const onDidCreateMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
40
|
-
const onDidDeleteMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
41
|
-
const fileWatcher = onDidChangeWatchedFiles(event => {
|
|
42
|
-
for (const change of event.changes) {
|
|
43
|
-
switch (change.type) {
|
|
44
|
-
case 2: {
|
|
45
|
-
const document = getTextDocument(change.uri, false);
|
|
46
|
-
if (document) {
|
|
47
|
-
onDidChangeMarkdownDocument.fire(document);
|
|
48
|
-
}
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
case 1: {
|
|
52
|
-
const document = getTextDocument(change.uri, false);
|
|
53
|
-
if (document) {
|
|
54
|
-
onDidCreateMarkdownDocument.fire(document);
|
|
55
|
-
}
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
case 3: {
|
|
59
|
-
onDidDeleteMarkdownDocument.fire(vscode_uri_1.URI.parse(change.uri));
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
const workspace = {
|
|
66
|
-
async getAllMarkdownDocuments() {
|
|
67
|
-
sync();
|
|
68
|
-
return syncedVersions.values();
|
|
69
|
-
},
|
|
70
|
-
getContainingDocument() {
|
|
71
|
-
return undefined;
|
|
72
|
-
},
|
|
73
|
-
hasMarkdownDocument(resource) {
|
|
74
|
-
const document = getTextDocument(resource.toString(), true);
|
|
75
|
-
return Boolean(document && matchDocument(documentSelector, document));
|
|
76
|
-
},
|
|
77
|
-
onDidChangeMarkdownDocument: onDidChangeMarkdownDocument.event,
|
|
78
|
-
onDidCreateMarkdownDocument: onDidCreateMarkdownDocument.event,
|
|
79
|
-
onDidDeleteMarkdownDocument: onDidDeleteMarkdownDocument.event,
|
|
80
|
-
async openMarkdownDocument(resource) {
|
|
81
|
-
return getTextDocument(resource.toString(), true);
|
|
82
|
-
},
|
|
83
|
-
async readDirectory(resource) {
|
|
84
|
-
const directory = await fs.readDirectory(resource.toString());
|
|
85
|
-
return directory.map(([fileName, fileType]) => [
|
|
86
|
-
fileName,
|
|
87
|
-
{ isDirectory: fileType === 2 }
|
|
88
|
-
]);
|
|
89
|
-
},
|
|
90
|
-
async stat(resource) {
|
|
91
|
-
const stat = await fs.stat(resource.toString());
|
|
92
|
-
if (stat) {
|
|
93
|
-
return { isDirectory: stat.type === 2 };
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
workspaceFolders: [vscode_uri_1.URI.parse(context.env.workspaceFolder)],
|
|
97
|
-
};
|
|
39
|
+
const workspace = getMarkdownWorkspace();
|
|
98
40
|
const ls = (0, vscode_markdown_languageservice_1.createLanguageService)({
|
|
99
41
|
logger,
|
|
100
42
|
parser,
|
|
101
|
-
workspace
|
|
43
|
+
workspace: workspace.workspace,
|
|
102
44
|
});
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const { languageServiceHost } = context.language.typescript;
|
|
109
|
-
const newProjectVersion = languageServiceHost.getProjectVersion?.();
|
|
110
|
-
const shouldUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion;
|
|
111
|
-
if (!shouldUpdate) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
lastProjectVersion = newProjectVersion;
|
|
115
|
-
const oldVersions = new Set(syncedVersions.keys());
|
|
116
|
-
const newVersions = new Map();
|
|
117
|
-
for (const fileName of languageServiceHost.getScriptFileNames()) {
|
|
118
|
-
const uri = context.env.typescript.fileNameToUri(fileName);
|
|
119
|
-
const decoded = context.decodeEmbeddedDocumentUri(uri);
|
|
120
|
-
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
121
|
-
if (sourceScript?.generated) {
|
|
122
|
-
for (const virtualCode of (0, language_service_1.forEachEmbeddedCode)(sourceScript.generated.root)) {
|
|
123
|
-
if (matchDocument(documentSelector, virtualCode)) {
|
|
124
|
-
const uri = context.encodeEmbeddedDocumentUri(sourceScript.id, virtualCode.id);
|
|
125
|
-
const document = context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
|
|
126
|
-
newVersions.set(document.uri, document);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
else if (sourceScript) {
|
|
131
|
-
const document = context.documents.get(fileName, sourceScript.languageId, sourceScript.snapshot);
|
|
132
|
-
if (document && matchDocument(documentSelector, document)) {
|
|
133
|
-
newVersions.set(document.uri, document);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
for (const [uri, document] of Array.from(newVersions)) {
|
|
138
|
-
const old = syncedVersions.get(uri);
|
|
139
|
-
syncedVersions.set(uri, document);
|
|
140
|
-
if (old) {
|
|
141
|
-
onDidChangeMarkdownDocument.fire(document);
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
onDidCreateMarkdownDocument.fire(document);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
for (const uri of Array.from(oldVersions)) {
|
|
148
|
-
if (!newVersions.has(uri)) {
|
|
149
|
-
syncedVersions.delete(uri);
|
|
150
|
-
onDidDeleteMarkdownDocument.fire(vscode_uri_1.URI.parse(uri));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
const prepare = (document) => {
|
|
155
|
-
if (!matchDocument(documentSelector, document)) {
|
|
156
|
-
return false;
|
|
45
|
+
const firedDocumentChanges = new Map();
|
|
46
|
+
const fsSourceScripts = new Map();
|
|
47
|
+
const fileWatcher = context.env.onDidChangeWatchedFiles?.(event => {
|
|
48
|
+
for (const change of event.changes) {
|
|
49
|
+
fsSourceScripts.delete(change.uri);
|
|
157
50
|
}
|
|
158
|
-
|
|
159
|
-
return true;
|
|
160
|
-
};
|
|
51
|
+
});
|
|
161
52
|
return {
|
|
162
53
|
dispose() {
|
|
163
54
|
ls.dispose();
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
onDidCreateMarkdownDocument.dispose();
|
|
167
|
-
onDidChangeMarkdownDocument.dispose();
|
|
55
|
+
workspace.dispose();
|
|
56
|
+
fileWatcher?.dispose();
|
|
168
57
|
},
|
|
169
58
|
provide: {
|
|
170
59
|
'markdown/languageService': () => ls
|
|
@@ -212,9 +101,9 @@ function create({ documentSelector = ['markdown'], getDiagnosticOptions = async
|
|
|
212
101
|
return ls.getDocumentHighlights(document, position, token);
|
|
213
102
|
}
|
|
214
103
|
},
|
|
215
|
-
provideDocumentLinks(document, token) {
|
|
104
|
+
async provideDocumentLinks(document, token) {
|
|
216
105
|
if (prepare(document)) {
|
|
217
|
-
return ls.getDocumentLinks(document, token);
|
|
106
|
+
return await ls.getDocumentLinks(document, token);
|
|
218
107
|
}
|
|
219
108
|
},
|
|
220
109
|
provideDocumentSymbols(document, token) {
|
|
@@ -258,26 +147,169 @@ function create({ documentSelector = ['markdown'], getDiagnosticOptions = async
|
|
|
258
147
|
}
|
|
259
148
|
},
|
|
260
149
|
provideWorkspaceSymbols(query, token) {
|
|
261
|
-
sync();
|
|
262
150
|
return ls.getWorkspaceSymbols(query, token);
|
|
263
151
|
},
|
|
264
152
|
async resolveDocumentLink(link, token) {
|
|
265
|
-
|
|
266
|
-
return result || link;
|
|
153
|
+
return await ls.resolveDocumentLink(link, token) ?? link;
|
|
267
154
|
}
|
|
268
155
|
};
|
|
269
|
-
function
|
|
270
|
-
if (
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
156
|
+
function prepare(document) {
|
|
157
|
+
if (matchDocument(documentSelector, document)) {
|
|
158
|
+
if (firedDocumentChanges.get(document.uri) !== document.version) {
|
|
159
|
+
firedDocumentChanges.set(document.uri, document.version);
|
|
160
|
+
workspace.onDidChangeMarkdownDocument.fire(document);
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
function getMarkdownWorkspace() {
|
|
167
|
+
const onDidChangeMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
168
|
+
const onDidCreateMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
169
|
+
const onDidDeleteMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
170
|
+
const { fs, onDidChangeWatchedFiles } = context.env;
|
|
171
|
+
const fileWatcher = onDidChangeWatchedFiles?.(event => {
|
|
172
|
+
for (const change of event.changes) {
|
|
173
|
+
switch (change.type) {
|
|
174
|
+
case 2: {
|
|
175
|
+
const document = getTextDocument(change.uri);
|
|
176
|
+
if (document) {
|
|
177
|
+
onDidChangeMarkdownDocument.fire(document);
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
case 1: {
|
|
182
|
+
const document = getTextDocument(change.uri);
|
|
183
|
+
if (document) {
|
|
184
|
+
onDidCreateMarkdownDocument.fire(document);
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
case 3: {
|
|
189
|
+
onDidDeleteMarkdownDocument.fire(vscode_uri_1.URI.parse(change.uri));
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
const workspace = {
|
|
196
|
+
async getAllMarkdownDocuments() {
|
|
197
|
+
// TODO: Add opened files (such as untitled files)
|
|
198
|
+
// const openTextDocumentResults = this.documents.all()
|
|
199
|
+
// .filter(doc => this.isRelevantMarkdownDocument(doc));
|
|
200
|
+
return await findMarkdownFilesInWorkspace(vscode_uri_1.URI.parse(context.env.workspaceFolder));
|
|
201
|
+
},
|
|
202
|
+
getContainingDocument() {
|
|
203
|
+
return undefined;
|
|
204
|
+
},
|
|
205
|
+
hasMarkdownDocument(resource) {
|
|
206
|
+
const document = getTextDocument(resource.toString());
|
|
207
|
+
return Boolean(document && matchDocument(documentSelector, document));
|
|
208
|
+
},
|
|
209
|
+
onDidChangeMarkdownDocument: onDidChangeMarkdownDocument.event,
|
|
210
|
+
onDidCreateMarkdownDocument: onDidCreateMarkdownDocument.event,
|
|
211
|
+
onDidDeleteMarkdownDocument: onDidDeleteMarkdownDocument.event,
|
|
212
|
+
async openMarkdownDocument(resource) {
|
|
213
|
+
return getTextDocument(resource.toString());
|
|
214
|
+
},
|
|
215
|
+
async readDirectory(resource) {
|
|
216
|
+
const directory = await fs?.readDirectory(resource.toString()) ?? [];
|
|
217
|
+
return directory
|
|
218
|
+
.filter(file => file[1] !== 0)
|
|
219
|
+
.map(([fileName, fileType]) => [
|
|
220
|
+
fileName,
|
|
221
|
+
{ isDirectory: fileType === 2 }
|
|
222
|
+
]);
|
|
223
|
+
},
|
|
224
|
+
async stat(resource) {
|
|
225
|
+
const stat = await fs?.stat(resource.toString());
|
|
226
|
+
if (stat?.type === 0) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
return { isDirectory: stat?.type === 2 };
|
|
230
|
+
},
|
|
231
|
+
workspaceFolders: [vscode_uri_1.URI.parse(context.env.workspaceFolder)],
|
|
232
|
+
};
|
|
233
|
+
return {
|
|
234
|
+
workspace,
|
|
235
|
+
onDidChangeMarkdownDocument,
|
|
236
|
+
onDidCreateMarkdownDocument,
|
|
237
|
+
onDidDeleteMarkdownDocument,
|
|
238
|
+
dispose() {
|
|
239
|
+
fileWatcher?.dispose();
|
|
240
|
+
onDidDeleteMarkdownDocument.dispose();
|
|
241
|
+
onDidCreateMarkdownDocument.dispose();
|
|
242
|
+
onDidChangeMarkdownDocument.dispose();
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
async function findMarkdownFilesInWorkspace(folder) {
|
|
247
|
+
const { fs } = context.env;
|
|
248
|
+
const files = await fs?.readDirectory(folder.toString()) ?? [];
|
|
249
|
+
const docs = [];
|
|
250
|
+
await Promise.all(files.map(async ([fileName, fileType]) => {
|
|
251
|
+
if (fileType === 2 && fileName !== 'node_modules') {
|
|
252
|
+
for (const doc of await findMarkdownFilesInWorkspace(vscode_uri_1.Utils.joinPath(folder, fileName))) {
|
|
253
|
+
docs.push(doc);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else if (fileExtensions.some(ext => fileName.endsWith('.' + ext))) {
|
|
257
|
+
const fileUri = vscode_uri_1.Utils.joinPath(folder, fileName);
|
|
258
|
+
let sourceScript = context.language.scripts.get(fileUri.toString());
|
|
259
|
+
if (!sourceScript) {
|
|
260
|
+
if (!fsSourceScripts.has(fileUri.toString())) {
|
|
261
|
+
fsSourceScripts.set(fileUri.toString(), undefined);
|
|
262
|
+
const fileContent = await fs?.readFile(fileUri.toString());
|
|
263
|
+
if (fileContent !== undefined) {
|
|
264
|
+
fsSourceScripts.set(fileUri.toString(), context.language.scripts.set(fileUri.toString(), {
|
|
265
|
+
getText(start, end) {
|
|
266
|
+
return fileContent.substring(start, end);
|
|
267
|
+
},
|
|
268
|
+
getLength() {
|
|
269
|
+
return fileContent.length;
|
|
270
|
+
},
|
|
271
|
+
getChangeRange() {
|
|
272
|
+
return undefined;
|
|
273
|
+
},
|
|
274
|
+
}));
|
|
275
|
+
context.language.scripts.delete(fileUri.toString());
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
sourceScript = fsSourceScripts.get(fileUri.toString());
|
|
279
|
+
}
|
|
280
|
+
if (sourceScript?.generated) {
|
|
281
|
+
for (const virtualCode of (0, language_service_1.forEachEmbeddedCode)(sourceScript.generated.root)) {
|
|
282
|
+
if (matchDocument(documentSelector, virtualCode)) {
|
|
283
|
+
const uri = context.encodeEmbeddedDocumentUri(sourceScript.id, virtualCode.id);
|
|
284
|
+
const doc = context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
|
|
285
|
+
docs.push(doc);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else if (sourceScript) {
|
|
290
|
+
const doc = context.documents.get(fileName, sourceScript.languageId, sourceScript.snapshot);
|
|
291
|
+
if (doc && matchDocument(documentSelector, doc)) {
|
|
292
|
+
docs.push(doc);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}));
|
|
297
|
+
return docs;
|
|
298
|
+
}
|
|
299
|
+
function getTextDocument(uri) {
|
|
300
|
+
const decoded = context.decodeEmbeddedDocumentUri(uri);
|
|
301
|
+
if (decoded) {
|
|
302
|
+
const sourceScript = context.language.scripts.get(decoded[0]);
|
|
303
|
+
const virtualCode = sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
274
304
|
if (virtualCode) {
|
|
275
305
|
return context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
|
|
276
306
|
}
|
|
277
307
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
308
|
+
else {
|
|
309
|
+
const sourceScript = context.language.scripts.get(uri);
|
|
310
|
+
if (sourceScript) {
|
|
311
|
+
return context.documents.get(uri, sourceScript.languageId, sourceScript.snapshot);
|
|
312
|
+
}
|
|
281
313
|
}
|
|
282
314
|
}
|
|
283
315
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "volar-service-markdown",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.46",
|
|
4
4
|
"description": "Integrate vscode-markdown-languageservice into Volar",
|
|
5
5
|
"homepage": "https://github.com/volarjs/services/tree/master/packages/markdown",
|
|
6
6
|
"bugs": "https://github.com/volarjs/services/issues",
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"optional": true
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "a5bc7172ea25a43dd403a1b7c926a297f70750ec"
|
|
45
45
|
}
|