mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-10 16:58:55 -05:00
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
import { getNode, parseDocument, validate } from './util';
|
||||
import { getHtmlNode, parseDocument, validate } from './util';
|
||||
|
||||
let balanceOutStack: Array<vscode.Selection[]> = [];
|
||||
let lastOut = false;
|
||||
@@ -61,7 +61,7 @@ function balance(out: boolean) {
|
||||
}
|
||||
|
||||
function getRangeToBalanceOut(document: vscode.TextDocument, selection: vscode.Selection, rootNode: HtmlNode): vscode.Selection {
|
||||
let nodeToBalance = <HtmlNode>getNode(rootNode, selection.start);
|
||||
let nodeToBalance = getHtmlNode(document, rootNode, selection.start);
|
||||
if (!nodeToBalance) {
|
||||
return selection;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ function getRangeToBalanceOut(document: vscode.TextDocument, selection: vscode.S
|
||||
}
|
||||
|
||||
function getRangeToBalanceIn(document: vscode.TextDocument, selection: vscode.Selection, rootNode: HtmlNode): vscode.Selection {
|
||||
let nodeToBalance = <HtmlNode>getNode(rootNode, selection.start, true);
|
||||
let nodeToBalance = getHtmlNode(document, rootNode, selection.start, true);
|
||||
if (!nodeToBalance) {
|
||||
return selection;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { parseDocument, validate, getNode } from './util';
|
||||
import { parseDocument, validate, getHtmlNode } from './util';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
|
||||
export function removeTag() {
|
||||
@@ -38,7 +38,7 @@ export function removeTag() {
|
||||
|
||||
function getRangeToRemove(editor: vscode.TextEditor, rootNode: HtmlNode, selection: vscode.Selection, indentInSpaces: string): vscode.Range[] {
|
||||
|
||||
let nodeToUpdate = <HtmlNode>getNode(rootNode, selection.start);
|
||||
let nodeToUpdate = getHtmlNode(editor.document, rootNode, selection.start);
|
||||
if (!nodeToUpdate) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { getDeepestNode, findNextWord, findPrevWord, getNode } from './util';
|
||||
import { getDeepestNode, findNextWord, findPrevWord, getHtmlNode } from './util';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
|
||||
export function nextItemHTML(selectionStart: vscode.Position, selectionEnd: vscode.Position, editor: vscode.TextEditor, rootNode: HtmlNode): vscode.Selection | undefined {
|
||||
let currentNode = <HtmlNode>getNode(rootNode, selectionEnd);
|
||||
let currentNode = getHtmlNode(editor.document, rootNode, selectionEnd);
|
||||
let nextNode: HtmlNode | undefined = undefined;
|
||||
|
||||
if (!currentNode) {
|
||||
@@ -54,7 +54,7 @@ export function nextItemHTML(selectionStart: vscode.Position, selectionEnd: vsco
|
||||
}
|
||||
|
||||
export function prevItemHTML(selectionStart: vscode.Position, selectionEnd: vscode.Position, editor: vscode.TextEditor, rootNode: HtmlNode): vscode.Selection | undefined {
|
||||
let currentNode = <HtmlNode>getNode(rootNode, selectionStart);
|
||||
let currentNode = getHtmlNode(editor.document, rootNode, selectionStart);
|
||||
let prevNode: HtmlNode | undefined = undefined;
|
||||
|
||||
if (!currentNode) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
import { getNode, parseDocument, validate, getEmmetMode, getEmmetConfiguration } from './util';
|
||||
import { getHtmlNode, parseDocument, validate, getEmmetMode, getEmmetConfiguration } from './util';
|
||||
|
||||
export function splitJoinTag() {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
@@ -20,7 +20,7 @@ export function splitJoinTag() {
|
||||
|
||||
return editor.edit(editBuilder => {
|
||||
editor.selections.reverse().forEach(selection => {
|
||||
let nodeToUpdate = <HtmlNode>getNode(rootNode, selection.start);
|
||||
let nodeToUpdate = getHtmlNode(editor.document, rootNode, selection.start);
|
||||
if (nodeToUpdate) {
|
||||
let textEdit = getRangesToReplace(editor.document, nodeToUpdate);
|
||||
editBuilder.replace(textEdit.range, textEdit.newText);
|
||||
|
||||
@@ -19,7 +19,7 @@ suite('Tests for Next/Previous Select/Edit point and Balance actions', () => {
|
||||
margin: 20px 10px;
|
||||
background-image: url('tryme.png');
|
||||
}
|
||||
|
||||
|
||||
.boo .hoo {
|
||||
margin: 10px;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ suite('Tests for Next/Previous Select/Edit point and Balance actions', () => {
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
\t\t
|
||||
</div>
|
||||
<div class="header">
|
||||
<ul class="nav main">
|
||||
@@ -113,6 +113,43 @@ suite('Tests for Next/Previous Select/Edit point and Balance actions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Emmet Next/Prev Item in html template', function (): any {
|
||||
const templateContents = `
|
||||
<script type="text/template">
|
||||
<div class="header">
|
||||
<ul class="nav main">
|
||||
</ul>
|
||||
</div>
|
||||
</script>
|
||||
`;
|
||||
return withRandomFileEditor(templateContents, '.html', (editor, doc) => {
|
||||
editor.selections = [new Selection(2, 2, 2, 2)];
|
||||
|
||||
let expectedNextItemPoints: [number, number, number][] = [
|
||||
[2, 2, 5], // div
|
||||
[2, 6, 20], // class="header"
|
||||
[2, 13, 19], // header
|
||||
[3, 3, 5], // ul
|
||||
[3, 6, 22], // class="nav main"
|
||||
[3, 13, 21], // nav main
|
||||
[3, 13, 16], // nav
|
||||
[3, 17, 21], // main
|
||||
];
|
||||
expectedNextItemPoints.forEach(([line, colstart, colend]) => {
|
||||
fetchSelectItem('next');
|
||||
testSelection(editor.selection, colstart, line, colend);
|
||||
});
|
||||
|
||||
editor.selections = [new Selection(4, 1, 4, 1)];
|
||||
expectedNextItemPoints.reverse().forEach(([line, colstart, colend]) => {
|
||||
fetchSelectItem('prev');
|
||||
testSelection(editor.selection, colstart, line, colend);
|
||||
});
|
||||
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
test('Emmet Select Next/Prev Item in css file', function (): any {
|
||||
return withRandomFileEditor(cssContents, '.css', (editor, doc) => {
|
||||
editor.selections = [new Selection(0, 0, 0, 0)];
|
||||
@@ -240,6 +277,42 @@ suite('Tests for Next/Previous Select/Edit point and Balance actions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Emmet Balance In/Out in html template', function (): any {
|
||||
const htmlTemplate = `
|
||||
<script type="text/html">
|
||||
<div class="header">
|
||||
<ul class="nav main">
|
||||
<li class="item1">Item 1</li>
|
||||
<li class="item2">Item 2</li>
|
||||
</ul>
|
||||
</div>
|
||||
</script>`;
|
||||
|
||||
return withRandomFileEditor(htmlTemplate, 'html', (editor, doc) => {
|
||||
|
||||
editor.selections = [new Selection(5, 24, 5, 24)];
|
||||
let expectedBalanceOutRanges: [number, number, number, number][] = [
|
||||
[5, 20, 5, 26], // <li class="item1">``Item 2''</li>
|
||||
[5, 2, 5, 31], // ``<li class="item1">Item 2</li>''
|
||||
[3, 22, 6, 1], // inner contents of ul
|
||||
[3, 1, 6, 6], // outer contents of ul
|
||||
[2, 20, 7, 0], // inner contents of div
|
||||
[2, 0, 7, 6], // outer contents of div
|
||||
];
|
||||
expectedBalanceOutRanges.forEach(([linestart, colstart, lineend, colend]) => {
|
||||
balanceOut();
|
||||
testSelection(editor.selection, colstart, linestart, colend, lineend);
|
||||
});
|
||||
|
||||
expectedBalanceOutRanges.pop();
|
||||
expectedBalanceOutRanges.reverse().forEach(([linestart, colstart, lineend, colend]) => {
|
||||
balanceIn();
|
||||
testSelection(editor.selection, colstart, linestart, colend, lineend);
|
||||
});
|
||||
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function testSelection(selection: Selection, startChar: number, startline: number, endChar?: number, endLine?: number) {
|
||||
|
||||
@@ -30,6 +30,17 @@ suite('Tests for Emmet actions on html tags', () => {
|
||||
</div>
|
||||
`;
|
||||
|
||||
let contentsWithTemplate = `
|
||||
<script type="text/template">
|
||||
<ul>
|
||||
<li><span>Hello</span></li>
|
||||
<li><span>There</span></li>
|
||||
<div><li><span>Bye</span></li></div>
|
||||
</ul>
|
||||
<span/>
|
||||
</script>
|
||||
`;
|
||||
|
||||
test('update tag with multiple cursors', () => {
|
||||
const expectedContents = `
|
||||
<div class="hello">
|
||||
@@ -55,6 +66,30 @@ suite('Tests for Emmet actions on html tags', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('update tag with template', () => {
|
||||
const expectedContents = `
|
||||
<script type="text/template">
|
||||
<section>
|
||||
<li><span>Hello</span></li>
|
||||
<li><span>There</span></li>
|
||||
<div><li><span>Bye</span></li></div>
|
||||
</section>
|
||||
<span/>
|
||||
</script>
|
||||
`;
|
||||
|
||||
return withRandomFileEditor(contentsWithTemplate, 'html', (editor, doc) => {
|
||||
editor.selections = [
|
||||
new Selection(2, 4, 2, 4), // cursor inside ul tag
|
||||
];
|
||||
|
||||
return updateTag('section')!.then(() => {
|
||||
assert.equal(doc.getText(), expectedContents);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('remove tag with mutliple cursors', () => {
|
||||
const expectedContents = `
|
||||
@@ -81,6 +116,30 @@ suite('Tests for Emmet actions on html tags', () => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('remove tag with template', () => {
|
||||
const expectedContents = `
|
||||
<script type="text/template">
|
||||
\t\t
|
||||
<li><span>Hello</span></li>
|
||||
<li><span>There</span></li>
|
||||
<div><li><span>Bye</span></li></div>
|
||||
\t
|
||||
<span/>
|
||||
</script>
|
||||
`;
|
||||
return withRandomFileEditor(contentsWithTemplate, 'html', (editor, doc) => {
|
||||
editor.selections = [
|
||||
new Selection(2, 4, 2, 4), // cursor inside ul tag
|
||||
];
|
||||
|
||||
return removeTag()!.then(() => {
|
||||
assert.equal(doc.getText(), expectedContents);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('split/join tag with mutliple cursors', () => {
|
||||
const expectedContents = `
|
||||
<div class="hello">
|
||||
@@ -105,6 +164,30 @@ suite('Tests for Emmet actions on html tags', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('split/join tag with templates', () => {
|
||||
const expectedContents = `
|
||||
<script type="text/template">
|
||||
<ul>
|
||||
<li><span/></li>
|
||||
<li><span>There</span></li>
|
||||
<div><li><span>Bye</span></li></div>
|
||||
</ul>
|
||||
<span></span>
|
||||
</script>
|
||||
`;
|
||||
return withRandomFileEditor(contentsWithTemplate, 'html', (editor, doc) => {
|
||||
editor.selections = [
|
||||
new Selection(3, 17, 3, 17), // join tag
|
||||
new Selection(7, 5, 7, 5), // split tag
|
||||
];
|
||||
|
||||
return splitJoinTag()!.then(() => {
|
||||
assert.equal(doc.getText(), expectedContents);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('split/join tag in jsx with xhtml self closing tag', () => {
|
||||
const expectedContents = `
|
||||
<div class="hello">
|
||||
|
||||
@@ -247,6 +247,36 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('toggle comment within script template', () => {
|
||||
const templateContents = `
|
||||
<script type="text/template">
|
||||
<li><span>Hello</span></li>
|
||||
<li><!--<span>There</span>--></li>
|
||||
<div><li><span>Bye</span></li></div>
|
||||
<span/>
|
||||
</script>
|
||||
`;
|
||||
const expectedContents = `
|
||||
<script type="text/template">
|
||||
<!--<li><span>Hello</span></li>-->
|
||||
<li><span>There</span></li>
|
||||
<div><li><!--<span>Bye</span>--></li></div>
|
||||
<span/>
|
||||
</script>
|
||||
`;
|
||||
return withRandomFileEditor(templateContents, 'html', (editor, doc) => {
|
||||
editor.selections = [
|
||||
new Selection(2, 2, 2, 28), // select entire li element
|
||||
new Selection(3, 17, 3, 17), // cursor inside the commented span
|
||||
new Selection(4, 18, 4, 18), // cursor inside the noncommented span
|
||||
];
|
||||
return toggleComment().then(() => {
|
||||
assert.equal(doc.getText(), expectedContents);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Tests for Toggle Comment action from Emmet (CSS)', () => {
|
||||
@@ -541,7 +571,7 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => {
|
||||
assert.equal(doc.getText(), expectedContents);
|
||||
return toggleComment().then(() => {
|
||||
assert.equal(doc.getText(), contents);
|
||||
return Promise.resolve();
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { getNodesInBetween, getNode, parseDocument, sameNodes, isStyleSheet, validate } from './util';
|
||||
import { Node, Stylesheet, Rule, HtmlNode } from 'EmmetNode';
|
||||
import { getNodesInBetween, getNode, getHtmlNode, parseDocument, sameNodes, isStyleSheet, validate } from './util';
|
||||
import { Node, Stylesheet, Rule } from 'EmmetNode';
|
||||
import parseStylesheet from '@emmetio/css-parser';
|
||||
import { DocumentStreamReader } from './bufferStream';
|
||||
|
||||
@@ -63,8 +63,8 @@ function toggleCommentHTML(document: vscode.TextDocument, selection: vscode.Sele
|
||||
const selectionStart = selection.isReversed ? selection.active : selection.anchor;
|
||||
const selectionEnd = selection.isReversed ? selection.anchor : selection.active;
|
||||
|
||||
let startNode = <HtmlNode>getNode(rootNode, selectionStart, true);
|
||||
let endNode = <HtmlNode>getNode(rootNode, selectionEnd, true);
|
||||
let startNode = getHtmlNode(document, rootNode, selectionStart, true);
|
||||
let endNode = getHtmlNode(document, rootNode, selectionEnd, true);
|
||||
|
||||
if (!startNode || !endNode) {
|
||||
return [];
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
import { getNode, parseDocument, validate } from './util';
|
||||
import { getHtmlNode, parseDocument, validate } from './util';
|
||||
|
||||
export function updateTag(tagName: string): Thenable<boolean> | undefined {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
@@ -30,7 +30,7 @@ export function updateTag(tagName: string): Thenable<boolean> | undefined {
|
||||
}
|
||||
|
||||
function getRangesToUpdate(editor: vscode.TextEditor, selection: vscode.Selection, rootNode: HtmlNode): vscode.Range[] {
|
||||
let nodeToUpdate = <HtmlNode>getNode(rootNode, selection.start);
|
||||
let nodeToUpdate = getHtmlNode(editor.document, rootNode, selection.start);
|
||||
if (!nodeToUpdate) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ export function getNode(root: Node | undefined, position: vscode.Position, inclu
|
||||
}
|
||||
|
||||
export function getHtmlNode(document: vscode.TextDocument, root: Node | undefined, position: vscode.Position, includeNodeBoundary: boolean = false): HtmlNode | undefined {
|
||||
let currentNode = <HtmlNode>getNode(root, position, true);
|
||||
let currentNode = <HtmlNode>getNode(root, position, includeNodeBoundary);
|
||||
if (!currentNode) { return; }
|
||||
|
||||
if (isTemplateScript(currentNode) && currentNode.close &&
|
||||
@@ -321,7 +321,7 @@ export function getHtmlNode(document: vscode.TextDocument, root: Node | undefine
|
||||
|
||||
try {
|
||||
let scriptInnerNodes = parse(buffer);
|
||||
currentNode = <HtmlNode>getNode(scriptInnerNodes, position, true) || currentNode;
|
||||
currentNode = <HtmlNode>getNode(scriptInnerNodes, position, includeNodeBoundary) || currentNode;
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user