Skip to content

Commit 98d5533

Browse files
authored
Fix md pasting inside of incomplete html block (microsoft#203476)
Fix pasting inside of incomplete html block Fixes microsoft#188868
1 parent 0d22ba3 commit 98d5533

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-5
lines changed

extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ export async function shouldInsertMarkdownLinkByDefault(
124124
}
125125
}
126126

127+
const textTokenTypes = new Set(['paragraph_open', 'inline', 'heading_open', 'ordered_list_open', 'bullet_list_open', 'list_item_open', 'blockquote_open']);
128+
127129
async function shouldSmartPasteForSelection(
128130
parser: IMdParser,
129131
document: ITextDocument,
@@ -150,9 +152,29 @@ async function shouldSmartPasteForSelection(
150152
if (token.isCancellationRequested) {
151153
return false;
152154
}
153-
for (const token of tokens) {
154-
if (token.map && token.map[0] <= selectedRange.start.line && token.map[1] > selectedRange.start.line) {
155-
if (!['paragraph_open', 'inline', 'heading_open', 'ordered_list_open', 'bullet_list_open', 'list_item_open', 'blockquote_open'].includes(token.type)) {
155+
156+
for (let i = 0; i < tokens.length; i++) {
157+
const token = tokens[i];
158+
if (!token.map) {
159+
continue;
160+
}
161+
if (token.map[0] <= selectedRange.start.line && token.map[1] > selectedRange.start.line) {
162+
if (!textTokenTypes.has(token.type)) {
163+
return false;
164+
}
165+
}
166+
167+
// Special case for html such as:
168+
//
169+
// <b>
170+
// |
171+
// </b>
172+
//
173+
// In this case pasting will cause the html block to be created even though the cursor is not currently inside a block
174+
if (token.type === 'html_block' && token.map[1] === selectedRange.start.line) {
175+
const nextToken = tokens.at(i + 1);
176+
// The next token does not need to be a html_block, but it must be on the next line
177+
if (nextToken?.map?.[0] === selectedRange.end.line + 1) {
156178
return false;
157179
}
158180
}

extensions/markdown-language-features/src/test/markdownLink.test.ts renamed to extensions/markdown-language-features/src/test/pasteUrl.test.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,23 @@ suite('createEditAddingLinksForUriList', () => {
203203
false);
204204
});
205205

206+
test('Smart should be disabled in html blocks where paste creates the block', async () => {
207+
assert.strictEqual(
208+
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<p>\n\n</p>'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
209+
false,
210+
'Between two html tags should be treated as html block');
211+
212+
assert.strictEqual(
213+
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<p>\n\ntext'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
214+
false,
215+
'Between opening html tag and text should be treated as html block');
216+
217+
assert.strictEqual(
218+
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('<p>\n\n\n</p>'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken),
219+
true,
220+
'Extra new line after paste should not be treated as html block');
221+
});
222+
206223
test('Smart should be disabled in Markdown links', async () => {
207224
assert.strictEqual(
208225
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[a](bcdef)'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 4, 0, 6)], noopToken),
@@ -266,7 +283,5 @@ suite('createEditAddingLinksForUriList', () => {
266283
await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(' \r\n\r\n'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 7)], noopToken),
267284
false);
268285
});
269-
270-
271286
});
272287
});

0 commit comments

Comments
 (0)