Emmet Toggle Comment CSS Improvements

This commit is contained in:
Ramya Achutha Rao 2017-07-30 14:54:14 -07:00
parent 7f88053372
commit 478a82e133
2 changed files with 230 additions and 56 deletions

View file

@ -151,7 +151,7 @@ suite('Tests for Toggle Comment action from Emmet (CSS)', () => {
}
.two {
height: 42px;
/*display: none;*/
display: none;
}
.three {
width: 42px;
@ -178,7 +178,10 @@ suite('Tests for Toggle Comment action from Emmet (CSS)', () => {
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return Promise.resolve();
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
@ -200,22 +203,25 @@ suite('Tests for Toggle Comment action from Emmet (CSS)', () => {
editor.selections = [
new Selection(2, 2, 2, 15), // A property completely selected
new Selection(3, 0, 3, 16), // A property completely selected along with whitespace
new Selection(5, 1, 8, 1), // A rule completely selected
new Selection(5, 1, 8, 2), // A rule completely selected
];
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
//return toggleComment().then(() => {
//assert.equal(doc.getText(), contents);
return Promise.resolve();
//});
});
});
});
test('toggle comment when multiple nodes are completely under single selection (CSS)', () => {
test('toggle comment when multiple nodes of same parent are completely under single selection (CSS)', () => {
const expectedContents = `
.one {
/*margin: 10px;
/* margin: 10px;
padding: 10px;*/
}
/*.two {
@ -233,12 +239,127 @@ suite('Tests for Toggle Comment action from Emmet (CSS)', () => {
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return Promise.resolve();
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
test('toggle comment when multiple nodes are partially under single selection (CSS)', () => {
test('toggle comment when start and end of selection is inside properties of separate rules (CSS)', () => {
const expectedContents = `
.one {
margin: 10px;
/*padding: 10px;
}
.two {
height: 42px;*/
display: none;
}
.three {
width: 42px;
}`;
return withRandomFileEditor(contents, 'css', (editor, doc) => {
editor.selections = [
new Selection(3, 7, 6, 6)
];
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
test('toggle comment when selection spans properties of separate rules, with start in whitespace and end inside the property (CSS)', () => {
const expectedContents = `
.one {
margin: 10px;
/*padding: 10px;
}
.two {
height: 42px;*/
display: none;
}
.three {
width: 42px;
}`;
return withRandomFileEditor(contents, 'css', (editor, doc) => {
editor.selections = [
new Selection(3, 0, 6, 6)
];
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
test('toggle comment when selection spans properties of separate rules, with end in whitespace and start inside the property (CSS)', () => {
const expectedContents = `
.one {
margin: 10px;
/*padding: 10px;
}
.two {
height: 42px;*/
display: none;
}
.three {
width: 42px;
}`;
return withRandomFileEditor(contents, 'css', (editor, doc) => {
editor.selections = [
new Selection(3, 7, 7, 0)
];
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
test('toggle comment when selection spans properties of separate rules, with both start and end in whitespace (CSS)', () => {
const expectedContents = `
.one {
margin: 10px;
/*padding: 10px;
}
.two {
height: 42px;*/
display: none;
}
.three {
width: 42px;
}`;
return withRandomFileEditor(contents, 'css', (editor, doc) => {
editor.selections = [
new Selection(3, 0, 7, 0)
];
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
test('toggle comment when multiple nodes of same parent are partially under single selection (CSS)', () => {
const expectedContents = `
.one {
/*margin: 10px;
@ -250,7 +371,7 @@ suite('Tests for Toggle Comment action from Emmet (CSS)', () => {
}
.three {
width: 42px;
}*/`;
*/ }`;
return withRandomFileEditor(contents, 'css', (editor, doc) => {
editor.selections = [
new Selection(2, 7, 3, 10), // 2 properties partially under a single selection
@ -259,7 +380,10 @@ suite('Tests for Toggle Comment action from Emmet (CSS)', () => {
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return Promise.resolve();
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
@ -306,7 +430,10 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => {
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
//return toggleComment().then(() => {
// assert.equal(doc.getText(), contents);
return Promise.resolve();
//});
});
});
});
@ -333,7 +460,10 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => {
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return Promise.resolve();
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
@ -360,7 +490,10 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => {
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return Promise.resolve();
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
@ -372,7 +505,7 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => {
.two {
width: 42px;
}*/
*/ }
.three {
padding: 10px;
@ -385,10 +518,12 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => {
return toggleComment().then(() => {
assert.equal(doc.getText(), expectedContents);
return Promise.resolve();
return toggleComment().then(() => {
assert.equal(doc.getText(), contents);
return Promise.resolve();
});
});
});
});
});

View file

@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { getNodesInBetween, getNode, parseDocument, sameNodes } from './util';
import { Node, Stylesheet } from 'EmmetNode';
import { getNodesInBetween, getNode, parseDocument } from './util';
import { Node, Stylesheet, Rule } from 'EmmetNode';
import { isStyleSheet } from 'vscode-emmet-helper';
const startCommentStylesheet = '/*';
@ -100,55 +100,94 @@ function getRangesToUnCommentHTML(node: Node, document: vscode.TextDocument): vs
}
function toggleCommentStylesheet(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Stylesheet): [vscode.Range[], vscode.Range] {
const selectionStart = selection.isReversed ? selection.active : selection.anchor;
const selectionEnd = selection.isReversed ? selection.anchor : selection.active;
let selectionStart = selection.isReversed ? selection.active : selection.anchor;
let selectionEnd = selection.isReversed ? selection.anchor : selection.active;
let startNode = getNode(rootNode, selectionStart, true);
let endNode = getNode(rootNode, selectionEnd, true);
if (startNode && endNode) {
if (sameNodes(startNode, endNode) || sameNodes(startNode.parent, endNode.parent)) {
selection = new vscode.Selection(startNode.start, endNode.end);
} else {
if (sameNodes(startNode, endNode.parent)) {
let newStartNode = startNode.firstChild;
while (newStartNode.end.isBefore(selectionStart) && newStartNode.nextSibling) {
newStartNode = newStartNode.nextSibling;
}
startNode = newStartNode;
} else if (sameNodes(startNode.parent, endNode)) {
let newEndNode = endNode.children[endNode.children.length - 1];
while (newEndNode.end.isAfter(selectionEnd) && newEndNode.previousSibling) {
newEndNode = newEndNode.previousSibling;
}
endNode = newEndNode;
}
// TODO: both are properties of different rule : have 2 comments for the 2 rules
}
if (!selection.isEmpty || startNode) {
selectionStart = selection.isEmpty ? startNode.start : adjustStartNodeCss(startNode, selectionStart, rootNode);
selectionEnd = selection.isEmpty ? startNode.end : adjustEndNodeCss(endNode, selectionEnd, rootNode);
selection = new vscode.Selection(selectionStart, selectionEnd);
}
let rangesToUnComment: vscode.Range[] = [];
let isFirstNodeCommented = false;
// Uncomment the comments that intersect with the selection.
let rangesToUnComment: vscode.Range[] = [];
rootNode.comments.forEach(comment => {
if (!isFirstNodeCommented) {
isFirstNodeCommented = (selectionStart.isAfterOrEqual(comment.start) && selectionEnd.isBefore(comment.end));
}
if (selection.contains(comment.start)
|| selection.contains(comment.end)
|| (selectionStart.isAfterOrEqual(comment.start) && selectionEnd.isBefore(comment.end))) {
rangesToUnComment.push(new vscode.Range(comment.start, comment.end));
let commentRange = new vscode.Range(comment.start, comment.end);
if (selection.intersection(commentRange)) {
rangesToUnComment.push(commentRange);
}
});
let rangeToComment = isFirstNodeCommented ? null : new vscode.Range(startNode ? startNode.start : selectionStart, endNode ? endNode.end : selectionEnd);
return [rangesToUnComment, rangeToComment];
return [rangesToUnComment, rangesToUnComment.length > 0 ? null : selection];
}
function adjustStartNodeCss(node: Node, pos: vscode.Position, rootNode: Stylesheet): vscode.Position {
for (let i = 0; i < rootNode.comments.length; i++) {
let commentRange = new vscode.Range(rootNode.comments[i].start, rootNode.comments[i].end);
if (commentRange.contains(pos)) {
return pos;
}
}
if (!node) {
return pos;
}
if (node.type === 'property') {
return node.start;
}
const rule = <Rule>node;
if (pos.isBefore(rule.contentStartToken.end) || !rule.firstChild) {
return rule.start;
}
if (pos.isBefore(rule.firstChild.start)) {
return pos;
}
let newStartNode = rule.firstChild;
while (newStartNode.nextSibling && pos.isAfter(newStartNode.end)) {
newStartNode = newStartNode.nextSibling;
}
return newStartNode.start;
}
function adjustEndNodeCss(node: Node, pos: vscode.Position, rootNode: Stylesheet): vscode.Position {
for (let i = 0; i < rootNode.comments.length; i++) {
let commentRange = new vscode.Range(rootNode.comments[i].start, rootNode.comments[i].end);
if (commentRange.contains(pos)) {
return pos;
}
}
if (!node) {
return pos;
}
if (node.type === 'property') {
return node.end;
}
const rule = <Rule>node;
if (pos.isEqual(rule.contentEndToken.end) || !rule.firstChild) {
return rule.end;
}
if (pos.isAfter(rule.children[rule.children.length - 1].end)) {
return pos;
}
let newEndNode = rule.children[rule.children.length - 1];
while (newEndNode.previousSibling && pos.isBefore(newEndNode.start)) {
newEndNode = newEndNode.previousSibling;
}
return newEndNode.end;
}