mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-28 04:23:32 +01:00
Merge remote-tracking branch 'origin/master' into alex/node-modules-vscode
This commit is contained in:
@@ -4,8 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { parseDocument, validate, getHtmlNode } from './util';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
import { validate, getHtmlNodeLS, toLSTextDocument, offsetRangeToVsRange } from './util';
|
||||
|
||||
export function removeTag() {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
@@ -13,54 +12,113 @@ export function removeTag() {
|
||||
}
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
|
||||
let rootNode = <HtmlNode>parseDocument(editor.document);
|
||||
if (!rootNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
let indentInSpaces = '';
|
||||
const tabSize: number = editor.options.tabSize ? +editor.options.tabSize : 0;
|
||||
for (let i = 0; i < tabSize || 0; i++) {
|
||||
indentInSpaces += ' ';
|
||||
}
|
||||
|
||||
let rangesToRemove: vscode.Range[] = [];
|
||||
editor.selections.reverse().forEach(selection => {
|
||||
rangesToRemove = rangesToRemove.concat(getRangeToRemove(editor, rootNode, selection, indentInSpaces));
|
||||
});
|
||||
const tabSize: number = +editor.options.tabSize!;
|
||||
let finalRangesToRemove = editor.selections.reverse()
|
||||
.reduce<vscode.Range[]>((prev, selection) =>
|
||||
prev.concat(getRangesToRemove(editor.document, selection, tabSize)), []);
|
||||
|
||||
return editor.edit(editBuilder => {
|
||||
rangesToRemove.forEach(range => {
|
||||
finalRangesToRemove.forEach(range => {
|
||||
editBuilder.replace(range, '');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getRangeToRemove(editor: vscode.TextEditor, rootNode: HtmlNode, selection: vscode.Selection, indentInSpaces: string): vscode.Range[] {
|
||||
|
||||
let nodeToUpdate = getHtmlNode(editor.document, rootNode, selection.start, true);
|
||||
/**
|
||||
* Calculates the ranges to remove, along with what to replace those ranges with.
|
||||
* It finds the node to remove based on the selection's start position
|
||||
* and then removes that node, reindenting the content in between.
|
||||
* Assumption: The document indents consist of only tabs or only spaces.
|
||||
*/
|
||||
function getRangesToRemove(document: vscode.TextDocument, selection: vscode.Selection, tabSize: number): vscode.Range[] {
|
||||
const lsDocument = toLSTextDocument(document);
|
||||
const nodeToUpdate = getHtmlNodeLS(lsDocument, selection.start, true);
|
||||
if (!nodeToUpdate) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let openRange = new vscode.Range(nodeToUpdate.open.start, nodeToUpdate.open.end);
|
||||
let closeRange: vscode.Range | null = null;
|
||||
if (nodeToUpdate.close) {
|
||||
closeRange = new vscode.Range(nodeToUpdate.close.start, nodeToUpdate.close.end);
|
||||
const openTagRange = offsetRangeToVsRange(lsDocument, nodeToUpdate.start, nodeToUpdate.startTagEnd ?? nodeToUpdate.end);
|
||||
let closeTagRange: vscode.Range | undefined;
|
||||
if (nodeToUpdate.endTagStart !== undefined) {
|
||||
closeTagRange = offsetRangeToVsRange(lsDocument, nodeToUpdate.endTagStart, nodeToUpdate.end);
|
||||
}
|
||||
|
||||
let ranges = [openRange];
|
||||
if (closeRange) {
|
||||
for (let i = openRange.start.line + 1; i <= closeRange.start.line; i++) {
|
||||
let lineContent = editor.document.lineAt(i).text;
|
||||
if (lineContent.startsWith('\t')) {
|
||||
ranges.push(new vscode.Range(i, 0, i, 1));
|
||||
} else if (lineContent.startsWith(indentInSpaces)) {
|
||||
ranges.push(new vscode.Range(i, 0, i, indentInSpaces.length));
|
||||
}
|
||||
let rangesToRemove = [openTagRange];
|
||||
if (closeTagRange) {
|
||||
const indentAmountToRemove = calculateIndentAmountToRemove(document, openTagRange, closeTagRange, tabSize);
|
||||
for (let i = openTagRange.start.line + 1; i < closeTagRange.start.line; i++) {
|
||||
rangesToRemove.push(new vscode.Range(i, 0, i, indentAmountToRemove));
|
||||
}
|
||||
ranges.push(closeRange);
|
||||
rangesToRemove.push(closeTagRange);
|
||||
}
|
||||
return ranges;
|
||||
return rangesToRemove;
|
||||
}
|
||||
|
||||
type IndentInfo = {
|
||||
indentAmount: number,
|
||||
tabsOnly: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the amount of indent to remove for getRangesToRemove.
|
||||
*/
|
||||
function calculateIndentAmountToRemove(document: vscode.TextDocument, openRange: vscode.Range, closeRange: vscode.Range, tabSize: number): number {
|
||||
const startLine = openRange.start.line;
|
||||
const endLine = closeRange.start.line;
|
||||
|
||||
const startLineIndent = calculateLineIndentInSpaces(document.lineAt(startLine).text, tabSize);
|
||||
const endLineIndent = calculateLineIndentInSpaces(document.lineAt(endLine).text, tabSize);
|
||||
|
||||
let contentIndent: IndentInfo | undefined;
|
||||
for (let i = startLine + 1; i <= endLine - 1; i++) {
|
||||
const lineContent = document.lineAt(i).text;
|
||||
const indent = calculateLineIndentInSpaces(lineContent, tabSize);
|
||||
contentIndent = !contentIndent ? indent :
|
||||
{
|
||||
indentAmount: Math.min(contentIndent.indentAmount, indent.indentAmount),
|
||||
tabsOnly: contentIndent.tabsOnly && indent.tabsOnly
|
||||
};
|
||||
}
|
||||
|
||||
let indentAmountSpaces = 0;
|
||||
let tabsOnly = startLineIndent.tabsOnly && endLineIndent.tabsOnly;
|
||||
|
||||
if (contentIndent) {
|
||||
if (contentIndent.indentAmount < startLineIndent.indentAmount
|
||||
|| contentIndent.indentAmount < endLineIndent.indentAmount) {
|
||||
indentAmountSpaces = 0;
|
||||
}
|
||||
else {
|
||||
indentAmountSpaces = Math.min(
|
||||
contentIndent.indentAmount - startLineIndent.indentAmount,
|
||||
contentIndent.indentAmount - endLineIndent.indentAmount
|
||||
);
|
||||
}
|
||||
tabsOnly = tabsOnly && contentIndent.tabsOnly;
|
||||
}
|
||||
return tabsOnly ? Math.trunc(indentAmountSpaces / tabSize) : indentAmountSpaces;
|
||||
}
|
||||
|
||||
function calculateLineIndentInSpaces(line: string, tabSize: number): IndentInfo {
|
||||
const whiteSpaceMatch = line.match(/^\s+/);
|
||||
const whiteSpaceContent = whiteSpaceMatch ? whiteSpaceMatch[0] : '';
|
||||
|
||||
if (!whiteSpaceContent) {
|
||||
return { indentAmount: 0, tabsOnly: true };
|
||||
}
|
||||
|
||||
let numSpaces = 0;
|
||||
let numTabs = 0;
|
||||
let tabsOnly = true;
|
||||
for (const c of whiteSpaceContent) {
|
||||
if (c === '\t') {
|
||||
numTabs++;
|
||||
}
|
||||
else {
|
||||
numSpaces++;
|
||||
tabsOnly = false;
|
||||
}
|
||||
}
|
||||
|
||||
return { indentAmount: numTabs * tabSize + numSpaces, tabsOnly };
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ suite('Tests for Emmet actions on html tags', () => {
|
||||
<li><span>Hello</span></li>
|
||||
<li><span>There</span></li>
|
||||
<div><li><span>Bye</span></li></div>
|
||||
\t
|
||||
\t\t
|
||||
<span/>
|
||||
</script>
|
||||
`;
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
"@types/keytar": "^4.4.2",
|
||||
"@types/node": "^10.12.21",
|
||||
"@types/node-fetch": "2.5.7",
|
||||
"@types/uuid": "8.0.0",
|
||||
"typescript": "^3.7.5"
|
||||
"@types/uuid": "8.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,11 +518,6 @@ tunnel-agent@^0.6.0:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
typescript@^3.7.5:
|
||||
version "3.9.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a"
|
||||
integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
|
||||
@@ -335,7 +335,6 @@
|
||||
"@types/lodash.throttle": "^4.1.3",
|
||||
"@types/markdown-it": "0.0.2",
|
||||
"@types/node": "^12.11.7",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"typescript": "^3.7.3"
|
||||
"lodash.throttle": "^4.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,11 +105,6 @@ semver@^5.3.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
||||
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
|
||||
|
||||
typescript@^3.7.3:
|
||||
version "3.7.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69"
|
||||
integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==
|
||||
|
||||
uc.micro@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
|
||||
|
||||
@@ -43,8 +43,7 @@
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/randombytes": "^2.0.0",
|
||||
"@types/sha.js": "^2.4.0",
|
||||
"@types/uuid": "^8.0.0",
|
||||
"typescript": "^3.7.4"
|
||||
"@types/uuid": "^8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"buffer": "^5.6.0",
|
||||
|
||||
@@ -561,11 +561,6 @@ tunnel-agent@^0.6.0:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
typescript@^3.7.4:
|
||||
version "3.7.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.4.tgz#1743a5ec5fef6a1fa9f3e4708e33c81c73876c19"
|
||||
integrity sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "2.2.43",
|
||||
"@types/node": "^12.11.7",
|
||||
"typescript": "^1.6.2"
|
||||
"@types/node": "^12.11.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,3 @@
|
||||
version "12.11.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
|
||||
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
|
||||
|
||||
typescript@^1.6.2:
|
||||
version "1.8.10"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-1.8.10.tgz#b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e"
|
||||
integrity sha1-tHXW4N/wv1DyluXKbvn7tccyDx4=
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"typescript": "^3.8.3",
|
||||
"@types/node": "^12.11.7"
|
||||
},
|
||||
"contributes": {
|
||||
|
||||
@@ -6,8 +6,3 @@
|
||||
version "12.12.37"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.37.tgz#cb4782d847f801fa58316da5b4801ca3a59ae790"
|
||||
integrity sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg==
|
||||
|
||||
typescript@^3.8.3:
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
||||
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
|
||||
|
||||
Reference in New Issue
Block a user