Skip to content

Commit f39385b

Browse files
committed
Treat style tag contents as css when commenting fixes #31685
1 parent d53301d commit f39385b

File tree

3 files changed

+109
-38
lines changed

3 files changed

+109
-38
lines changed

extensions/emmet/src/test/toggleComment.test.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
2323
<li>Another Node</li>
2424
</ul>
2525
<span/>
26+
<style>
27+
.boo {
28+
margin: 10px;
29+
padding: 20px;
30+
}
31+
.hoo {
32+
margin: 10px;
33+
padding: 20px;
34+
}
35+
</style>
2636
</div>
2737
`;
2838

@@ -39,14 +49,26 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
3949
<li>Another Node</li>
4050
</ul>-->
4151
<span/>
52+
<style>
53+
.boo {
54+
/*margin: 10px;*/
55+
padding: 20px;
56+
}
57+
/*.hoo {
58+
margin: 10px;
59+
padding: 20px;
60+
}*/
61+
</style>
4262
</div>
4363
`;
4464
return withRandomFileEditor(contents, 'html', (editor, doc) => {
4565
editor.selections = [
4666
new Selection(3, 17, 3, 17), // cursor inside the inner span element
4767
new Selection(4, 5, 4, 5), // cursor inside opening tag
4868
new Selection(5, 35, 5, 35), // cursor inside closing tag
49-
new Selection(7, 3, 7, 3) // cursor inside open tag of <ul> one of of whose children is already commented
69+
new Selection(7, 3, 7, 3), // cursor inside open tag of <ul> one of of whose children is already commented
70+
new Selection(14, 8, 14, 8), // cursor inside the css property inside the style tag
71+
new Selection(18, 3, 18, 3) // cursor inside the css rule inside the style tag
5072
];
5173

5274
return toggleComment().then(() => {
@@ -69,13 +91,25 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
6991
<li>Another Node</li>
7092
</ul>-->
7193
<span/>
94+
<style>
95+
.boo {
96+
/*margin: 10px;*/
97+
padding: 20px;
98+
}
99+
/*.hoo {
100+
margin: 10px;
101+
padding: 20px;
102+
}*/
103+
</style>
72104
</div>
73105
`;
74106
return withRandomFileEditor(contents, 'html', (editor, doc) => {
75107
editor.selections = [
76108
new Selection(3, 7, 3, 25), // <span>Hello</span><
77109
new Selection(4, 3, 4, 30), // <li><span>There</span></li>
78-
new Selection(7, 2, 10, 7) // The <ul> one of of whose children is already commented
110+
new Selection(7, 2, 10, 7), // The <ul> one of of whose children is already commented
111+
new Selection(14, 4, 14, 17), // css property inside the style tag
112+
new Selection(17, 3, 20, 4) // the css rule inside the style tag
79113
];
80114

81115
return toggleComment().then(() => {
@@ -98,11 +132,22 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
98132
<li>Another Node</li>
99133
</ul>
100134
<span/>
135+
<style>
136+
.boo {
137+
/*margin: 10px;
138+
padding: 20px;*/
139+
}
140+
.hoo {
141+
margin: 10px;
142+
padding: 20px;
143+
}
144+
</style>
101145
</div>
102146
`;
103147
return withRandomFileEditor(contents, 'html', (editor, doc) => {
104148
editor.selections = [
105-
new Selection(3, 4, 4, 30)
149+
new Selection(3, 4, 4, 30),
150+
new Selection(14, 4, 15, 18) // 2 css properties inside the style tag
106151
];
107152

108153
return toggleComment().then(() => {
@@ -125,6 +170,16 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
125170
<li>Another Node</li>
126171
</ul>-->
127172
<span/>
173+
<style>
174+
.boo {
175+
margin: 10px;
176+
padding: 20px;
177+
}
178+
.hoo {
179+
margin: 10px;
180+
padding: 20px;
181+
}
182+
</style>
128183
</div>
129184
`;
130185
return withRandomFileEditor(contents, 'html', (editor, doc) => {

extensions/emmet/src/toggleComment.ts

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as vscode from 'vscode';
7-
import { getNodesInBetween, getNode, parseDocument } from './util';
8-
import { Node, Stylesheet, Rule } from 'EmmetNode';
7+
import { getNodesInBetween, getNode, parseDocument, sameNodes } from './util';
8+
import { Node, Stylesheet, Rule, HtmlNode } from 'EmmetNode';
99
import { isStyleSheet } from 'vscode-emmet-helper';
10+
import parseStylesheet from '@emmetio/css-parser';
11+
import { DocumentStreamReader } from './bufferStream';
1012

1113
const startCommentStylesheet = '/*';
1214
const endCommentStylesheet = '*/';
@@ -21,17 +23,11 @@ export function toggleComment(): Thenable<boolean> {
2123
}
2224

2325
let toggleCommentInternal;
24-
let startComment;
25-
let endComment;
2626

2727
if (isStyleSheet(editor.document.languageId)) {
2828
toggleCommentInternal = toggleCommentStylesheet;
29-
startComment = startCommentStylesheet;
30-
endComment = endCommentStylesheet;
3129
} else {
3230
toggleCommentInternal = toggleCommentHTML;
33-
startComment = startCommentHTML;
34-
endComment = endCommentHTML;
3531
}
3632

3733
let rootNode = parseDocument(editor.document);
@@ -41,65 +37,73 @@ export function toggleComment(): Thenable<boolean> {
4137

4238
return editor.edit(editBuilder => {
4339
editor.selections.reverse().forEach(selection => {
44-
let [rangesToUnComment, rangeToComment] = toggleCommentInternal(editor.document, selection, rootNode);
45-
rangesToUnComment.forEach((rangeToUnComment: vscode.Range) => {
46-
editBuilder.delete(new vscode.Range(rangeToUnComment.start, rangeToUnComment.start.translate(0, startComment.length)));
47-
editBuilder.delete(new vscode.Range(rangeToUnComment.end.translate(0, -endComment.length), rangeToUnComment.end));
40+
let edits = toggleCommentInternal(editor.document, selection, rootNode);
41+
edits.forEach(x => {
42+
editBuilder.replace(x.range, x.newText);
4843
});
49-
if (rangeToComment) {
50-
editBuilder.insert(rangeToComment.start, startComment);
51-
editBuilder.insert(rangeToComment.end, endComment);
52-
}
53-
5444
});
5545
});
5646
}
5747

58-
function toggleCommentHTML(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node): [vscode.Range[], vscode.Range] {
48+
function toggleCommentHTML(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node): vscode.TextEdit[] {
5949
const selectionStart = selection.isReversed ? selection.active : selection.anchor;
6050
const selectionEnd = selection.isReversed ? selection.anchor : selection.active;
6151

62-
let startNode = getNode(rootNode, selectionStart, true);
63-
let endNode = getNode(rootNode, selectionEnd, true);
52+
let startNode = <HtmlNode>getNode(rootNode, selectionStart, true);
53+
let endNode = <HtmlNode>getNode(rootNode, selectionEnd, true);
6454

6555
if (!startNode || !endNode) {
66-
return [[], null];
56+
return [];
57+
}
58+
59+
if (sameNodes(startNode, endNode) && startNode.name === 'style'
60+
&& startNode.open.end.isBefore(selectionStart)
61+
&& startNode.close.start.isAfter(selectionEnd)) {
62+
let buffer = new DocumentStreamReader(document, startNode.open.end, new vscode.Range(startNode.open.end, startNode.close.start));
63+
let cssRootNode = parseStylesheet(buffer);
64+
65+
return toggleCommentStylesheet(document, selection, cssRootNode);
6766
}
6867

6968
let allNodes: Node[] = getNodesInBetween(startNode, endNode);
70-
let rangesToUnComment: vscode.Range[] = [];
69+
let edits: vscode.TextEdit[] = [];
7170

7271
allNodes.forEach(node => {
73-
rangesToUnComment = rangesToUnComment.concat(getRangesToUnCommentHTML(node, document));
72+
edits = edits.concat(getRangesToUnCommentHTML(node, document));
7473
});
7574

7675
if (startNode.type === 'comment') {
77-
return [rangesToUnComment, null];
76+
return edits;
7877
}
7978

80-
let rangeToComment = new vscode.Range(allNodes[0].start, allNodes[allNodes.length - 1].end);
81-
return [rangesToUnComment, rangeToComment];
79+
80+
edits.push(new vscode.TextEdit(new vscode.Range(allNodes[0].start, allNodes[0].start), startCommentHTML));
81+
edits.push(new vscode.TextEdit(new vscode.Range(allNodes[allNodes.length - 1].end, allNodes[allNodes.length - 1].end), endCommentHTML));
82+
83+
return edits;
8284
}
8385

84-
function getRangesToUnCommentHTML(node: Node, document: vscode.TextDocument): vscode.Range[] {
85-
let rangesToUnComment = [];
86+
function getRangesToUnCommentHTML(node: Node, document: vscode.TextDocument): vscode.TextEdit[] {
87+
let unCommentTextEdits: vscode.TextEdit[] = [];
8688

8789
// If current node is commented, then uncomment and return
8890
if (node.type === 'comment') {
89-
rangesToUnComment.push(new vscode.Range(node.start, node.end));
9091

91-
return rangesToUnComment;
92+
unCommentTextEdits.push(new vscode.TextEdit(new vscode.Range(node.start, node.start.translate(0, startCommentHTML.length)), ''));
93+
unCommentTextEdits.push(new vscode.TextEdit(new vscode.Range(node.end.translate(0, -endCommentHTML.length), node.end), ''));
94+
95+
return unCommentTextEdits;
9296
}
9397

9498
// All children of current node should be uncommented
9599
node.children.forEach(childNode => {
96-
rangesToUnComment = rangesToUnComment.concat(getRangesToUnCommentHTML(childNode, document));
100+
unCommentTextEdits = unCommentTextEdits.concat(getRangesToUnCommentHTML(childNode, document));
97101
});
98102

99-
return rangesToUnComment;
103+
return unCommentTextEdits;
100104
}
101105

102-
function toggleCommentStylesheet(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Stylesheet): [vscode.Range[], vscode.Range] {
106+
function toggleCommentStylesheet(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Stylesheet): vscode.TextEdit[] {
103107
let selectionStart = selection.isReversed ? selection.active : selection.anchor;
104108
let selectionEnd = selection.isReversed ? selection.anchor : selection.active;
105109

@@ -114,14 +118,26 @@ function toggleCommentStylesheet(document: vscode.TextDocument, selection: vscod
114118

115119
// Uncomment the comments that intersect with the selection.
116120
let rangesToUnComment: vscode.Range[] = [];
121+
let edits: vscode.TextEdit[] = [];
117122
rootNode.comments.forEach(comment => {
118123
let commentRange = new vscode.Range(comment.start, comment.end);
119124
if (selection.intersection(commentRange)) {
120125
rangesToUnComment.push(commentRange);
126+
edits.push(new vscode.TextEdit(new vscode.Range(comment.start, comment.start.translate(0, startCommentStylesheet.length)), ''));
127+
edits.push(new vscode.TextEdit(new vscode.Range(comment.end.translate(0, -endCommentStylesheet.length), comment.end), ''));
121128
}
122129
});
123130

124-
return [rangesToUnComment, rangesToUnComment.length > 0 ? null : selection];
131+
if (edits.length > 0) {
132+
return edits;
133+
}
134+
135+
return [
136+
new vscode.TextEdit(new vscode.Range(selection.start, selection.start), startCommentStylesheet),
137+
new vscode.TextEdit(new vscode.Range(selection.end, selection.end), endCommentStylesheet)
138+
];
139+
140+
125141
}
126142

127143
function adjustStartNodeCss(node: Node, pos: vscode.Position, rootNode: Stylesheet): vscode.Position {

extensions/emmet/src/updateImageSize.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function updateImageSizeStyleTag(editor: TextEditor, position: Position): Promis
7777
if (currentNode && currentNode.name === 'style'
7878
&& currentNode.open.end.isBefore(position)
7979
&& currentNode.close.start.isAfter(position)) {
80-
let buffer = new DocumentStreamReader(editor.document, currentNode.start, new Range(currentNode.start, currentNode.end));
80+
let buffer = new DocumentStreamReader(editor.document, currentNode.open.end, new Range(currentNode.open.end, currentNode.close.start));
8181
let rootNode = parseStylesheet(buffer);
8282
const node = getNode(rootNode, position);
8383
return (node && node.type === 'property') ? <Property>node : null;

0 commit comments

Comments
 (0)