Emmet Toggle Comment CSS Improvements
This commit is contained in:
parent
7f88053372
commit
478a82e133
2 changed files with 230 additions and 56 deletions
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue