Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/markdown-language-features/src/test/pasteUrl.test.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import * as assert from 'assert';
6
import 'mocha';
7
import * as vscode from 'vscode';
8
import { InMemoryDocument } from '../client/inMemoryDocument';
9
import { createInsertUriListEdit, imageEditKind, linkEditKind } from '../languageFeatures/copyFiles/shared';
10
import { InsertMarkdownLink, findValidUriInText, shouldInsertMarkdownLinkByDefault } from '../languageFeatures/copyFiles/smartDropOrPaste';
11
import { noopToken } from '../util/cancellation';
12
import { UriList } from '../util/uriList';
13
import { createNewMarkdownEngine } from './engine';
14
import { joinLines } from './util';
15
16
function makeTestDoc(contents: string) {
17
return new InMemoryDocument(vscode.Uri.file('test.md'), contents);
18
}
19
20
suite('createEditAddingLinksForUriList', () => {
21
22
test('Markdown Link Pasting should occur for a valid link (end to end)', async () => {
23
const result = createInsertUriListEdit(
24
new InMemoryDocument(vscode.Uri.file('test.md'), 'hello world!'), [new vscode.Range(0, 0, 0, 12)], UriList.from('https://www.microsoft.com/'));
25
// need to check the actual result -> snippet value
26
assert.strictEqual(result?.label, 'Insert Markdown Link');
27
});
28
29
suite('validateLink', () => {
30
31
test('Markdown pasting should occur for a valid link', () => {
32
assert.strictEqual(
33
findValidUriInText('https://www.microsoft.com/'),
34
'https://www.microsoft.com/');
35
});
36
37
test('Markdown pasting should occur for a valid link preceded by a new line', () => {
38
assert.strictEqual(
39
findValidUriInText('\r\nhttps://www.microsoft.com/'),
40
'https://www.microsoft.com/');
41
});
42
43
test('Markdown pasting should occur for a valid link followed by a new line', () => {
44
assert.strictEqual(
45
findValidUriInText('https://www.microsoft.com/\r\n'),
46
'https://www.microsoft.com/');
47
});
48
49
test('Markdown pasting should not occur for a valid hostname and invalid protool', () => {
50
assert.strictEqual(
51
findValidUriInText('invalid:www.microsoft.com'),
52
undefined);
53
});
54
55
test('Markdown pasting should not occur for plain text', () => {
56
assert.strictEqual(
57
findValidUriInText('hello world!'),
58
undefined);
59
});
60
61
test('Markdown pasting should not occur for plain text including a colon', () => {
62
assert.strictEqual(
63
findValidUriInText('hello: world!'),
64
undefined);
65
});
66
67
test('Markdown pasting should not occur for plain text including a slashes', () => {
68
assert.strictEqual(
69
findValidUriInText('helloworld!'),
70
undefined);
71
});
72
73
test('Markdown pasting should not occur for a link followed by text', () => {
74
assert.strictEqual(
75
findValidUriInText('https://www.microsoft.com/ hello world!'),
76
undefined);
77
});
78
79
test('Markdown pasting should occur for a link preceded or followed by spaces', () => {
80
assert.strictEqual(
81
findValidUriInText(' https://www.microsoft.com/ '),
82
'https://www.microsoft.com/');
83
});
84
85
test('Markdown pasting should not occur for a link with an invalid scheme', () => {
86
assert.strictEqual(
87
findValidUriInText('hello:www.microsoft.com'),
88
undefined);
89
});
90
91
test('Markdown pasting should not occur for multiple links being pasted', () => {
92
assert.strictEqual(
93
findValidUriInText('https://www.microsoft.com/\r\nhttps://www.microsoft.com/\r\nhttps://www.microsoft.com/\r\nhttps://www.microsoft.com/'),
94
undefined);
95
});
96
97
test('Markdown pasting should not occur for multiple links with spaces being pasted', () => {
98
assert.strictEqual(
99
findValidUriInText('https://www.microsoft.com/ \r\nhttps://www.microsoft.com/\r\nhttps://www.microsoft.com/\r\n hello \r\nhttps://www.microsoft.com/'),
100
undefined);
101
});
102
103
test('Markdown pasting should not occur for just a valid uri scheme', () => {
104
assert.strictEqual(
105
findValidUriInText('https://'),
106
undefined);
107
});
108
});
109
110
suite('createInsertUriListEdit', () => {
111
test('Should create snippet with < > when pasted link has an mismatched parentheses', () => {
112
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.mic(rosoft.com'));
113
assert.strictEqual(edit?.edits?.[0].snippet.value, '[${1:text}](<https://www.mic(rosoft.com>)');
114
});
115
116
test('Should create Markdown link snippet when pasteAsMarkdownLink is true', () => {
117
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.microsoft.com'));
118
assert.strictEqual(edit?.edits?.[0].snippet.value, '[${1:text}](https://www.microsoft.com)');
119
});
120
121
test('Should use an unencoded URI string in Markdown link when passing in an external browser link', () => {
122
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.microsoft.com'));
123
assert.strictEqual(edit?.edits?.[0].snippet.value, '[${1:text}](https://www.microsoft.com)');
124
});
125
126
test('Should not decode an encoded URI string when passing in an external browser link', () => {
127
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.microsoft.com/%20'));
128
assert.strictEqual(edit?.edits?.[0].snippet.value, '[${1:text}](https://www.microsoft.com/%20)');
129
});
130
131
test('Should not encode an unencoded URI string when passing in an external browser link', () => {
132
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.example.com/path?query=value&another=value#fragment'));
133
assert.strictEqual(edit?.edits?.[0].snippet.value, '[${1:text}](https://www.example.com/path?query=value&another=value#fragment)');
134
});
135
136
test('Should add image for image file by default', () => {
137
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.example.com/cat.png'));
138
assert.strictEqual(edit?.edits?.[0].snippet.value, '![${1:alt text}](https://www.example.com/cat.png)');
139
});
140
141
test('Should be able to override insert style to use link', () => {
142
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.example.com/cat.png'), {
143
linkKindHint: linkEditKind,
144
});
145
assert.strictEqual(edit?.edits?.[0].snippet.value, '[${1:text}](https://www.example.com/cat.png)');
146
});
147
148
test('Should be able to override insert style to use images', () => {
149
const edit = createInsertUriListEdit(makeTestDoc(''), [new vscode.Range(0, 0, 0, 0)], UriList.from('https://www.example.com/'), {
150
linkKindHint: imageEditKind,
151
});
152
assert.strictEqual(edit?.edits?.[0].snippet.value, '![${1:alt text}](https://www.example.com/)');
153
});
154
});
155
156
157
suite('shouldInsertMarkdownLinkByDefault', () => {
158
159
test('Smart should be enabled for selected plain text', async () => {
160
assert.strictEqual(
161
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('hello world'), InsertMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 12)], noopToken),
162
true);
163
});
164
165
test('Smart should be enabled in headers', async () => {
166
assert.strictEqual(
167
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('# title'), InsertMarkdownLink.Smart, [new vscode.Range(0, 2, 0, 2)], noopToken),
168
true);
169
});
170
171
test('Smart should be enabled in lists', async () => {
172
assert.strictEqual(
173
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('1. text'), InsertMarkdownLink.Smart, [new vscode.Range(0, 3, 0, 3)], noopToken),
174
true);
175
});
176
177
test('Smart should be enabled in blockquotes', async () => {
178
assert.strictEqual(
179
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('> text'), InsertMarkdownLink.Smart, [new vscode.Range(0, 3, 0, 3)], noopToken),
180
true);
181
});
182
183
test('Smart should be disabled in indented code blocks', async () => {
184
assert.strictEqual(
185
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(' code'), InsertMarkdownLink.Smart, [new vscode.Range(0, 4, 0, 4)], noopToken),
186
false);
187
});
188
189
test('Smart should be disabled in fenced code blocks', async () => {
190
assert.strictEqual(
191
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('```\r\n\r\n```'), InsertMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 5)], noopToken),
192
false);
193
194
assert.strictEqual(
195
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('~~~\r\n\r\n~~~'), InsertMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 5)], noopToken),
196
false);
197
});
198
199
test('Smart should be disabled in math blocks', async () => {
200
201
let katex: any = (await import('@vscode/markdown-it-katex')).default;
202
if (typeof katex === 'object') {
203
katex = katex.default;
204
}
205
206
const engine = createNewMarkdownEngine();
207
(await engine.getEngine(undefined)).use(katex);
208
assert.strictEqual(
209
await shouldInsertMarkdownLinkByDefault(engine, makeTestDoc('$$\r\n\r\n$$'), InsertMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 5)], noopToken),
210
false);
211
});
212
213
test('Smart should be disabled in link definitions', async () => {
214
assert.strictEqual(
215
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[ref]: http://example.com'), InsertMarkdownLink.Smart, [new vscode.Range(0, 4, 0, 6)], noopToken),
216
false);
217
218
assert.strictEqual(
219
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[ref]: '), InsertMarkdownLink.Smart, [new vscode.Range(0, 7, 0, 7)], noopToken),
220
false);
221
222
assert.strictEqual(
223
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[ref]: '), InsertMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 0)], noopToken),
224
false);
225
});
226
227
test('Smart should be disabled in html blocks', async () => {
228
assert.strictEqual(
229
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<p>\na\n</p>'), InsertMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
230
false);
231
});
232
233
test('Smart should be disabled in html blocks where paste creates the block', async () => {
234
assert.strictEqual(
235
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<p>\n\n</p>'), InsertMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
236
false,
237
'Between two html tags should be treated as html block');
238
239
assert.strictEqual(
240
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<p>\n\ntext'), InsertMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
241
false,
242
'Between opening html tag and text should be treated as html block');
243
244
assert.strictEqual(
245
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<p>\n\n\n</p>'), InsertMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
246
true,
247
'Extra new line after paste should not be treated as html block');
248
});
249
250
test('Smart should be disabled in Markdown links', async () => {
251
assert.strictEqual(
252
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[a](bcdef)'), InsertMarkdownLink.Smart, [new vscode.Range(0, 4, 0, 6)], noopToken),
253
false);
254
});
255
256
test('Smart should be disabled in Markdown images', async () => {
257
assert.strictEqual(
258
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('![a](bcdef)'), InsertMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 10)], noopToken),
259
false);
260
});
261
262
test('Smart should be disabled in inline code', async () => {
263
assert.strictEqual(
264
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('``'), InsertMarkdownLink.Smart, [new vscode.Range(0, 1, 0, 1)], noopToken),
265
false,
266
'Should be disabled inside of inline code');
267
268
assert.strictEqual(
269
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('``'), InsertMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 0)], noopToken),
270
true,
271
'Should be enabled when cursor is outside but next to inline code');
272
273
assert.strictEqual(
274
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('`a`'), InsertMarkdownLink.Smart, [new vscode.Range(0, 3, 0, 3)], noopToken),
275
true,
276
'Should be enabled when cursor is outside but next to inline code');
277
});
278
279
test('Smart should be enabled when pasting over inline code ', async () => {
280
assert.strictEqual(
281
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('`xyz`'), InsertMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 5)], noopToken),
282
true);
283
});
284
285
test('Smart should be disabled in inline math', async () => {
286
assert.strictEqual(
287
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('$$'), InsertMarkdownLink.SmartWithSelection, [new vscode.Range(0, 1, 0, 1)], noopToken),
288
false);
289
});
290
291
test('Smart should be enabled for empty selection', async () => {
292
assert.strictEqual(
293
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('xyz'), InsertMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 0)], noopToken),
294
true);
295
});
296
297
test('SmartWithSelection should disable for empty selection', async () => {
298
assert.strictEqual(
299
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('xyz'), InsertMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 0)], noopToken),
300
false);
301
});
302
303
test('Smart should disable for selected link', async () => {
304
assert.strictEqual(
305
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('https://www.microsoft.com'), InsertMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 25)], noopToken),
306
false);
307
});
308
309
test('Smart should disable for selected link with trailing whitespace', async () => {
310
assert.strictEqual(
311
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(' https://www.microsoft.com '), InsertMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 30)], noopToken),
312
false);
313
});
314
315
test('Should evaluate pasteAsMarkdownLink as true for a link pasted in square brackets', async () => {
316
assert.strictEqual(
317
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[abc]'), InsertMarkdownLink.SmartWithSelection, [new vscode.Range(0, 1, 0, 4)], noopToken),
318
true);
319
});
320
321
test('Should evaluate pasteAsMarkdownLink as false for selected whitespace and new lines', async () => {
322
assert.strictEqual(
323
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(' \r\n\r\n'), InsertMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 7)], noopToken),
324
false);
325
});
326
327
test('Smart should be disabled inside of autolinks', async () => {
328
assert.strictEqual(
329
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<>'), InsertMarkdownLink.Smart, [new vscode.Range(0, 1, 0, 1)], noopToken),
330
false);
331
});
332
333
test('Smart should be disabled in frontmatter', async () => {
334
const textDoc = makeTestDoc(joinLines(
335
`---`,
336
`layout: post`,
337
`title: Blogging Like a Hacker`,
338
`---`,
339
``,
340
`Link Text`
341
));
342
assert.strictEqual(
343
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), textDoc, InsertMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 0)], noopToken),
344
false);
345
346
assert.strictEqual(
347
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), textDoc, InsertMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
348
false);
349
});
350
351
test('Smart should enabled after frontmatter', async () => {
352
assert.strictEqual(
353
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(joinLines(
354
`---`,
355
`layout: post`,
356
`title: Blogging Like a Hacker`,
357
`---`,
358
``,
359
`Link Text`
360
)), InsertMarkdownLink.Smart, [new vscode.Range(5, 0, 5, 0)], noopToken),
361
true);
362
});
363
});
364
});
365
366