From 0da90fcc62c44d2ac99ce45c8f0fbd4ac53a95f2 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Tue, 6 Jun 2017 18:17:36 -0700 Subject: [PATCH] toggle comment across html nodes #27629 --- extensions/emmet/src/toggleComment.ts | 30 ++++++++++------ extensions/emmet/src/util.ts | 51 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/extensions/emmet/src/toggleComment.ts b/extensions/emmet/src/toggleComment.ts index 17aabeaca44..b26e31ad1e2 100644 --- a/extensions/emmet/src/toggleComment.ts +++ b/extensions/emmet/src/toggleComment.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { getNode, isStyleSheet } from './util'; +import { getNode, isStyleSheet, getNodesInBetween } from './util'; import parse from '@emmetio/html-matcher'; import parseStylesheet from '@emmetio/css-parser'; import Node from '@emmetio/node'; @@ -58,19 +58,29 @@ export function toggleComment() { } function toggleCommentHTML(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node): [vscode.Range[], vscode.Position, vscode.Position] { - let offset = document.offsetAt(selection.start); - let nodeToUpdate = getNode(rootNode, offset); - if (!nodeToUpdate) { + const selectionStart = document.offsetAt(selection.isReversed ? selection.active : selection.anchor); + const selectionEnd = document.offsetAt(selection.isReversed ? selection.anchor : selection.active); + + let startNode = getNode(rootNode, selectionStart, true); + let endNode = getNode(rootNode, selectionEnd, true); + + if (!startNode || !endNode) { return [[], null, null]; } - let rangesToUnComment = getRangesToUnCommentHTML(nodeToUpdate, document); - if (nodeToUpdate.type === 'comment') { + let allNodes: Node[] = getNodesInBetween(startNode, endNode); + let rangesToUnComment: vscode.Range[] = []; + + allNodes.forEach(node => { + rangesToUnComment = rangesToUnComment.concat(getRangesToUnCommentHTML(node, document)); + }); + + if (startNode.type === 'comment') { return [rangesToUnComment, null, null]; } - let positionForCommentStart = document.positionAt(nodeToUpdate.start); - let positionForCommentEnd = document.positionAt(nodeToUpdate.end); + let positionForCommentStart = document.positionAt(allNodes[0].start); + let positionForCommentEnd = document.positionAt(allNodes[allNodes.length - 1].end); return [rangesToUnComment, positionForCommentStart, positionForCommentEnd]; } @@ -95,8 +105,8 @@ function getRangesToUnCommentHTML(node: Node, document: vscode.TextDocument): vs function toggleCommentStylesheet(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node): [vscode.Range[], vscode.Position, vscode.Position] { - let selectionStart = document.offsetAt(selection.anchor); - let selectionEnd = document.offsetAt(selection.active); + const selectionStart = document.offsetAt(selection.isReversed ? selection.active : selection.anchor); + const selectionEnd = document.offsetAt(selection.isReversed ? selection.anchor : selection.active); // If current node is commented, then uncomment and return let rangesToUnComment = getRangesToUnCommentStylesheet(rootNode, selectionStart, selectionEnd, document, true); diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index d6b80549fdf..bc3f3893e89 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -215,4 +215,55 @@ export function findPrevWord(propertyValue: string, pos: number): [number, numbe } return [newSelectionStart, newSelectionEnd]; +} + +export function getNodesInBetween(node1: Node, node2: Node): Node[] { + // Same node + if (sameNodes(node1, node2)) { + return [node1]; + } + + // Same parent + if (sameNodes(node1.parent, node2.parent)) { + return getNextSiblingsTillPosition(node1, node2.end); + } + + // node2 is ancestor of node1 + if (node2.start < node1.start) { + return [node2]; + } + + // node1 is ancestor of node2 + if (node2.start < node1.end) { + return [node1]; + } + + // Get the highest ancestor of node1 that should be commented + while (node1.parent && node1.parent.end < node2.start) { + node1 = node1.parent; + } + + // Get the highest ancestor of node2 that should be commented + while (node2.parent && node2.parent.start > node1.start) { + node2 = node2.parent; + } + + return getNextSiblingsTillPosition(node1, node2.end); +} + +function getNextSiblingsTillPosition(node: Node, position: number): Node[] { + let siblings: Node[] = []; + let currentNode = node; + while (currentNode && currentNode.start < position) { + siblings.push(currentNode); + currentNode = currentNode.nextSibling; + } + return siblings; +} + +export function sameNodes(node1: Node, node2: Node): boolean { + if (!node1 || !node2) { + return false; + } + return node1.start === node2.start && node1.end === node2.end; } \ No newline at end of file -- GitLab