Skip to content

Commit 0da90fc

Browse files
committed
toggle comment across html nodes microsoft#27629
1 parent a5c9a7c commit 0da90fc

2 files changed

Lines changed: 71 additions & 10 deletions

File tree

extensions/emmet/src/toggleComment.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as vscode from 'vscode';
7-
import { getNode, isStyleSheet } from './util';
7+
import { getNode, isStyleSheet, getNodesInBetween } from './util';
88
import parse from '@emmetio/html-matcher';
99
import parseStylesheet from '@emmetio/css-parser';
1010
import Node from '@emmetio/node';
@@ -58,19 +58,29 @@ export function toggleComment() {
5858
}
5959

6060
function toggleCommentHTML(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node): [vscode.Range[], vscode.Position, vscode.Position] {
61-
let offset = document.offsetAt(selection.start);
62-
let nodeToUpdate = getNode(rootNode, offset);
63-
if (!nodeToUpdate) {
61+
const selectionStart = document.offsetAt(selection.isReversed ? selection.active : selection.anchor);
62+
const selectionEnd = document.offsetAt(selection.isReversed ? selection.anchor : selection.active);
63+
64+
let startNode = getNode(rootNode, selectionStart, true);
65+
let endNode = getNode(rootNode, selectionEnd, true);
66+
67+
if (!startNode || !endNode) {
6468
return [[], null, null];
6569
}
6670

67-
let rangesToUnComment = getRangesToUnCommentHTML(nodeToUpdate, document);
68-
if (nodeToUpdate.type === 'comment') {
71+
let allNodes: Node[] = getNodesInBetween(startNode, endNode);
72+
let rangesToUnComment: vscode.Range[] = [];
73+
74+
allNodes.forEach(node => {
75+
rangesToUnComment = rangesToUnComment.concat(getRangesToUnCommentHTML(node, document));
76+
});
77+
78+
if (startNode.type === 'comment') {
6979
return [rangesToUnComment, null, null];
7080
}
7181

72-
let positionForCommentStart = document.positionAt(nodeToUpdate.start);
73-
let positionForCommentEnd = document.positionAt(nodeToUpdate.end);
82+
let positionForCommentStart = document.positionAt(allNodes[0].start);
83+
let positionForCommentEnd = document.positionAt(allNodes[allNodes.length - 1].end);
7484
return [rangesToUnComment, positionForCommentStart, positionForCommentEnd];
7585
}
7686

@@ -95,8 +105,8 @@ function getRangesToUnCommentHTML(node: Node, document: vscode.TextDocument): vs
95105

96106
function toggleCommentStylesheet(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node): [vscode.Range[], vscode.Position, vscode.Position] {
97107

98-
let selectionStart = document.offsetAt(selection.anchor);
99-
let selectionEnd = document.offsetAt(selection.active);
108+
const selectionStart = document.offsetAt(selection.isReversed ? selection.active : selection.anchor);
109+
const selectionEnd = document.offsetAt(selection.isReversed ? selection.anchor : selection.active);
100110

101111
// If current node is commented, then uncomment and return
102112
let rangesToUnComment = getRangesToUnCommentStylesheet(rootNode, selectionStart, selectionEnd, document, true);

extensions/emmet/src/util.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,55 @@ export function findPrevWord(propertyValue: string, pos: number): [number, numbe
215215
}
216216

217217
return [newSelectionStart, newSelectionEnd];
218+
}
219+
220+
export function getNodesInBetween(node1: Node, node2: Node): Node[] {
221+
// Same node
222+
if (sameNodes(node1, node2)) {
223+
return [node1];
224+
}
225+
226+
// Same parent
227+
if (sameNodes(node1.parent, node2.parent)) {
228+
return getNextSiblingsTillPosition(node1, node2.end);
229+
}
230+
231+
// node2 is ancestor of node1
232+
if (node2.start < node1.start) {
233+
return [node2];
234+
}
235+
236+
// node1 is ancestor of node2
237+
if (node2.start < node1.end) {
238+
return [node1];
239+
}
240+
241+
// Get the highest ancestor of node1 that should be commented
242+
while (node1.parent && node1.parent.end < node2.start) {
243+
node1 = node1.parent;
244+
}
245+
246+
// Get the highest ancestor of node2 that should be commented
247+
while (node2.parent && node2.parent.start > node1.start) {
248+
node2 = node2.parent;
249+
}
250+
251+
return getNextSiblingsTillPosition(node1, node2.end);
252+
}
253+
254+
function getNextSiblingsTillPosition(node: Node, position: number): Node[] {
255+
let siblings: Node[] = [];
256+
let currentNode = node;
257+
while (currentNode && currentNode.start < position) {
258+
siblings.push(currentNode);
259+
currentNode = currentNode.nextSibling;
260+
}
261+
return siblings;
262+
}
263+
264+
export function sameNodes(node1: Node, node2: Node): boolean {
265+
if (!node1 || !node2) {
266+
return false;
267+
}
268+
return node1.start === node2.start && node1.end === node2.end;
218269
}

0 commit comments

Comments
 (0)