Upgrade to latest Emmet (#113848)
This commit is contained in:
parent
6f56b47c69
commit
dc5a3da3ab
|
@ -430,14 +430,16 @@
|
|||
"deps": "yarn add vscode-emmet-helper"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.19.9"
|
||||
"@types/node": "^12.19.9",
|
||||
"emmet": "https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emmetio/abbreviation": "^2.2.0",
|
||||
"@emmetio/css-parser": "ramya-rao-a/css-parser#vscode",
|
||||
"@emmetio/html-matcher": "^0.3.3",
|
||||
"@emmetio/math-expression": "^1.0.4",
|
||||
"image-size": "^0.5.2",
|
||||
"vscode-emmet-helper": "~2.0.0",
|
||||
"vscode-emmet-helper": "2.2.4-2",
|
||||
"vscode-languageserver-textdocument": "^1.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,16 @@ import * as vscode from 'vscode';
|
|||
import { Node, HtmlNode, Rule, Property, Stylesheet } from 'EmmetFlatNode';
|
||||
import { getEmmetHelper, getFlatNode, getMappingForIncludedLanguages, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode, parsePartialStylesheet, isStyleAttribute, getEmbeddedCssNodeIfAny, allowedMimeTypesInScriptTag, toLSTextDocument } from './util';
|
||||
import { getRootNode as parseDocument } from './parseDocument';
|
||||
import { MarkupAbbreviation } from 'emmet';
|
||||
// import { AbbreviationNode } from '@emmetio/abbreviation';
|
||||
|
||||
const trimRegex = /[\u00a0]*[\d#\-\*\u2022]+\.?/;
|
||||
const hexColorRegex = /^#[\da-fA-F]{0,6}$/;
|
||||
const inlineElements = ['a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo',
|
||||
'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i',
|
||||
'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'object', 'q',
|
||||
's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup',
|
||||
'textarea', 'tt', 'u', 'var'];
|
||||
// const inlineElements = ['a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo',
|
||||
// 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i',
|
||||
// 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'object', 'q',
|
||||
// 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup',
|
||||
// 'textarea', 'tt', 'u', 'var'];
|
||||
|
||||
interface ExpandAbbreviationInput {
|
||||
syntax: string;
|
||||
|
@ -32,29 +34,29 @@ interface PreviewRangesWithContent {
|
|||
}
|
||||
|
||||
export function wrapWithAbbreviation(args: any) {
|
||||
return doWrapping(false, args);
|
||||
return doWrapping(true, args);
|
||||
}
|
||||
|
||||
export function wrapIndividualLinesWithAbbreviation(args: any) {
|
||||
return doWrapping(true, args);
|
||||
}
|
||||
|
||||
function doWrapping(individualLines: boolean, args: any) {
|
||||
function doWrapping(_: boolean, args: any) {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (individualLines) {
|
||||
if (editor.selections.length === 1 && editor.selection.isEmpty) {
|
||||
vscode.window.showInformationMessage('Select more than 1 line and try again.');
|
||||
return;
|
||||
}
|
||||
if (editor.selections.find(x => x.isEmpty)) {
|
||||
vscode.window.showInformationMessage('Select more than 1 line in each selection and try again.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if (individualLines) {
|
||||
// if (editor.selections.length === 1 && editor.selection.isEmpty) {
|
||||
// vscode.window.showInformationMessage('Select more than 1 line and try again.');
|
||||
// return;
|
||||
// }
|
||||
// if (editor.selections.find(x => x.isEmpty)) {
|
||||
// vscode.window.showInformationMessage('Select more than 1 line in each selection and try again.');
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
args = args || {};
|
||||
if (!args['language']) {
|
||||
args['language'] = editor.document.languageId;
|
||||
|
@ -99,14 +101,15 @@ function doWrapping(individualLines: boolean, args: any) {
|
|||
|
||||
let textToWrapInPreview: string[];
|
||||
const textToReplace = document.getText(rangeToReplace);
|
||||
if (individualLines) {
|
||||
textToWrapInPreview = textToReplace.split('\n').map(x => x.trim());
|
||||
} else {
|
||||
const wholeFirstLine = document.lineAt(rangeToReplace.start).text;
|
||||
const otherMatches = wholeFirstLine.match(/^(\s*)/);
|
||||
const precedingWhitespace = otherMatches ? otherMatches[1] : '';
|
||||
textToWrapInPreview = rangeToReplace.isSingleLine ? [textToReplace] : ['\n\t' + textToReplace.split('\n' + precedingWhitespace).join('\n\t') + '\n'];
|
||||
}
|
||||
// if (individualLines) {
|
||||
// textToWrapInPreview = textToReplace.split('\n').map(x => x.trim());
|
||||
// } else {
|
||||
// the following assumes the lines are indented the same way
|
||||
const wholeFirstLine = document.lineAt(rangeToReplace.start).text;
|
||||
const otherMatches = wholeFirstLine.match(/^(\s*)/);
|
||||
const precedingWhitespace = otherMatches ? otherMatches[1] : '';
|
||||
textToWrapInPreview = rangeToReplace.isSingleLine ? [textToReplace] : textToReplace.split('\n' + precedingWhitespace).map(x => x.trimEnd());
|
||||
// }
|
||||
textToWrapInPreview = textToWrapInPreview.map(e => e.replace(/(\$\d)/g, '\\$1'));
|
||||
|
||||
return {
|
||||
|
@ -117,7 +120,7 @@ function doWrapping(individualLines: boolean, args: any) {
|
|||
};
|
||||
});
|
||||
|
||||
function revertPreview(): Thenable<any> {
|
||||
function revertPreview(): Thenable<boolean> {
|
||||
return editor.edit(builder => {
|
||||
for (const rangeToReplace of rangesToReplace) {
|
||||
builder.replace(rangeToReplace.previewRange, rangeToReplace.originalContent);
|
||||
|
@ -143,7 +146,8 @@ function doWrapping(individualLines: boolean, args: any) {
|
|||
const preceedingText = editor.document.getText(new vscode.Range(oldPreviewRange.start.line, 0, oldPreviewRange.start.line, oldPreviewRange.start.character));
|
||||
const indentPrefix = (preceedingText.match(/^(\s*)/) || ['', ''])[1];
|
||||
|
||||
let newText = expandedText.replace(/\n/g, '\n' + indentPrefix); // Adding indentation on each line of expanded text
|
||||
let newText = expandedText;
|
||||
newText = newText.replace(/\n/g, '\n' + indentPrefix); // Adding indentation on each line of expanded text
|
||||
newText = newText.replace(/\$\{[\d]*\}/g, '|'); // Removing Tabstops
|
||||
newText = newText.replace(/\$\{[\d]*(:[^}]*)?\}/g, (match) => { // Replacing Placeholders
|
||||
return match.replace(/^\$\{[\d]*:/, '').replace('}', '');
|
||||
|
@ -197,19 +201,21 @@ function doWrapping(individualLines: boolean, args: any) {
|
|||
|
||||
const { abbreviation, filter } = extractedResults;
|
||||
if (definitive) {
|
||||
const revertPromise = inPreview ? revertPreview() : Promise.resolve();
|
||||
const revertPromise = inPreview ? revertPreview() : Promise.resolve(true);
|
||||
return revertPromise.then(() => {
|
||||
const expandAbbrList: ExpandAbbreviationInput[] = rangesToReplace.map(rangesAndContent => {
|
||||
const rangeToReplace = rangesAndContent.originalRange;
|
||||
let textToWrap: string[];
|
||||
if (individualLines) {
|
||||
textToWrap = rangesAndContent.textToWrapInPreview;
|
||||
} else {
|
||||
textToWrap = rangeToReplace.isSingleLine ? ['$TM_SELECTED_TEXT'] : ['\n\t$TM_SELECTED_TEXT\n'];
|
||||
}
|
||||
// if (individualLines) {
|
||||
textToWrap = rangesAndContent.textToWrapInPreview;
|
||||
// } else {
|
||||
// // use the p tag as a dummy element to get Emmet to wrap the expression properly
|
||||
// textToWrap = rangeToReplace.isSingleLine ?
|
||||
// ['$TM_SELECTED_TEXT'] : ['<p>$TM_SELECTED_TEXT</p>'];
|
||||
// }
|
||||
return { syntax: syntax || '', abbreviation, rangeToReplace, textToWrap, filter };
|
||||
});
|
||||
return expandAbbreviationInRange(editor, expandAbbrList, !individualLines).then(() => { return true; });
|
||||
return expandAbbreviationInRange(editor, expandAbbrList, false).then(() => { return true; });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -224,14 +230,15 @@ function doWrapping(individualLines: boolean, args: any) {
|
|||
if (value !== currentValue) {
|
||||
currentValue = value;
|
||||
makeChanges(value, false).then((out) => {
|
||||
if (typeof out === 'boolean') {
|
||||
inPreview = out;
|
||||
}
|
||||
inPreview = out;
|
||||
});
|
||||
}
|
||||
return '';
|
||||
}
|
||||
const abbreviationPromise: Thenable<string | undefined> = (args && args['abbreviation']) ? Promise.resolve(args['abbreviation']) : vscode.window.showInputBox({ prompt: 'Enter Abbreviation', validateInput: inputChanged });
|
||||
|
||||
const abbreviationPromise: Thenable<string | undefined> = (args && args['abbreviation']) ?
|
||||
Promise.resolve(args['abbreviation']) :
|
||||
vscode.window.showInputBox({ prompt: 'Enter Abbreviation', validateInput: inputChanged });
|
||||
return abbreviationPromise.then(inputAbbreviation => {
|
||||
return makeChanges(inputAbbreviation, true);
|
||||
});
|
||||
|
@ -597,7 +604,7 @@ function expandAbbreviationInRange(editor: vscode.TextEditor, expandAbbrList: Ex
|
|||
const insertPromises: Thenable<boolean>[] = [];
|
||||
if (!insertSameSnippet) {
|
||||
expandAbbrList.sort((a: ExpandAbbreviationInput, b: ExpandAbbreviationInput) => { return b.rangeToReplace.start.compareTo(a.rangeToReplace.start); }).forEach((expandAbbrInput: ExpandAbbreviationInput) => {
|
||||
let expandedText = expandAbbr(expandAbbrInput);
|
||||
const expandedText = expandAbbr(expandAbbrInput);
|
||||
if (expandedText) {
|
||||
insertPromises.push(editor.insertSnippet(new vscode.SnippetString(expandedText), expandAbbrInput.rangeToReplace, { undoStopBefore: false, undoStopAfter: false }));
|
||||
}
|
||||
|
@ -622,24 +629,26 @@ function expandAbbreviationInRange(editor: vscode.TextEditor, expandAbbrList: Ex
|
|||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walks the tree rooted at root and apply function fn on each node.
|
||||
* if fn return false at any node, the further processing of tree is stopped.
|
||||
*/
|
||||
function walk(root: any, fn: ((node: any) => boolean)): boolean {
|
||||
let ctx = root;
|
||||
while (ctx) {
|
||||
// /*
|
||||
// * Walks the tree rooted at root and apply function fn on each node.
|
||||
// * if fn return false at any node, the further processing of tree is stopped.
|
||||
// */
|
||||
// function walk(root: AbbreviationNode, fn: ((node: AbbreviationNode) => boolean)): boolean {
|
||||
// if (fn(root) === false || walkChildren(root.children, fn) === false) {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
const next = ctx.next;
|
||||
if (fn(ctx) === false || walk(ctx.firstChild, fn) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx = next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// function walkChildren(children: AbbreviationNode[], fn: ((node: AbbreviationNode) => boolean)): boolean {
|
||||
// for (let i = 0; i < children.length; i++) {
|
||||
// const child = children[i];
|
||||
// if (walk(child, fn) === false) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Expands abbreviation as detailed in given input.
|
||||
|
@ -649,7 +658,7 @@ function expandAbbr(input: ExpandAbbreviationInput): string | undefined {
|
|||
const expandOptions = helper.getExpandOptions(input.syntax, getEmmetConfiguration(input.syntax), input.filter);
|
||||
|
||||
if (input.textToWrap) {
|
||||
if (input.filter && input.filter.indexOf('t') > -1) {
|
||||
if (input.filter && input.filter.includes('t')) {
|
||||
input.textToWrap = input.textToWrap.map(line => {
|
||||
return line.replace(trimRegex, '').trim();
|
||||
});
|
||||
|
@ -659,46 +668,47 @@ function expandAbbr(input: ExpandAbbreviationInput): string | undefined {
|
|||
// Below fixes https://github.com/microsoft/vscode/issues/29898
|
||||
// With this, Emmet formats inline elements as block elements
|
||||
// ensuring the wrapped multi line text does not get merged to a single line
|
||||
if (!input.rangeToReplace.isSingleLine) {
|
||||
expandOptions.profile['inlineBreak'] = 1;
|
||||
if (!input.rangeToReplace.isSingleLine && expandOptions.options) {
|
||||
expandOptions.options['output.inlineBreak'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
let expandedText;
|
||||
try {
|
||||
// Expand the abbreviation
|
||||
if (input.textToWrap && !isStyleSheet(input.syntax)) {
|
||||
const parsedAbbr = <MarkupAbbreviation>helper.parseAbbreviation(input.abbreviation, expandOptions);
|
||||
// if (input.rangeToReplace.isSingleLine && input.textToWrap.length === 1) {
|
||||
// // Fetch rightmost element in the parsed abbreviation (i.e the element that will contain the wrapped text).
|
||||
// const wrappingNodeChildren = parsedAbbr.children;
|
||||
// let wrappingNode = wrappingNodeChildren[wrappingNodeChildren.length - 1];
|
||||
// while (wrappingNode && wrappingNode.children && wrappingNode.children.length > 0) {
|
||||
// wrappingNode = wrappingNode.children[wrappingNode.children.length - 1];
|
||||
// }
|
||||
|
||||
if (input.textToWrap) {
|
||||
const parsedAbbr = helper.parseAbbreviation(input.abbreviation, expandOptions);
|
||||
if (input.rangeToReplace.isSingleLine && input.textToWrap.length === 1) {
|
||||
|
||||
// Fetch rightmost element in the parsed abbreviation (i.e the element that will contain the wrapped text).
|
||||
let wrappingNode = parsedAbbr;
|
||||
while (wrappingNode && wrappingNode.children && wrappingNode.children.length > 0) {
|
||||
wrappingNode = wrappingNode.children[wrappingNode.children.length - 1];
|
||||
}
|
||||
|
||||
// If wrapping with a block element, insert newline in the text to wrap.
|
||||
if (wrappingNode && inlineElements.indexOf(wrappingNode.name) === -1 && (expandOptions['profile'].hasOwnProperty('format') ? expandOptions['profile'].format : true)) {
|
||||
wrappingNode.value = '\n\t' + wrappingNode.value + '\n';
|
||||
}
|
||||
}
|
||||
// // If wrapping with a block element, insert newline in the text to wrap.
|
||||
// // const format = expandOptions.options ? (expandOptions.options['output.format'] ?? true) : true;
|
||||
// // if (wrappingNode && wrappingNode.name && wrappingNode.value
|
||||
// // && inlineElements.indexOf(wrappingNode.name) === -1
|
||||
// // && format) {
|
||||
// // wrappingNode.value[0] = '\n\t' + wrappingNode.value[0] + '\n';
|
||||
// // }
|
||||
// }
|
||||
|
||||
// Below fixes https://github.com/microsoft/vscode/issues/78219
|
||||
// walk the tree and remove tags for empty values
|
||||
walk(parsedAbbr, node => {
|
||||
if (node.name !== null && node.value === '' && !node.isSelfClosing && node.children.length === 0) {
|
||||
node.name = '';
|
||||
node.value = '\n';
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
// walkChildren(parsedAbbr.children, node => {
|
||||
// if (node.name !== null && node.value && node.value[0] === '' && !node.selfClosing && node.children.length === 0) {
|
||||
// node.name = '';
|
||||
// node.value[0] = '\n';
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
|
||||
expandedText = helper.expandAbbreviation(parsedAbbr, expandOptions);
|
||||
// All $anyword would have been escaped by the emmet helper.
|
||||
// Remove the escaping backslash from $TM_SELECTED_TEXT so that VS Code Snippet controller can treat it as a variable
|
||||
expandedText = expandedText.replace('\\$TM_SELECTED_TEXT', '$TM_SELECTED_TEXT');
|
||||
expandedText = expandedText.replace('<p>\\$TM_SELECTED_TEXT</p>', '$TM_SELECTED_TEXT');
|
||||
} else {
|
||||
expandedText = helper.expandAbbreviation(input.abbreviation, expandOptions);
|
||||
}
|
||||
|
|
|
@ -9,13 +9,20 @@ import { Selection, workspace, ConfigurationTarget } from 'vscode';
|
|||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
import { wrapWithAbbreviation, wrapIndividualLinesWithAbbreviation } from '../abbreviationActions';
|
||||
|
||||
const htmlContentsForWrapTests = `
|
||||
const htmlContentsForBlockWrapTests = `
|
||||
<ul class="nav main">
|
||||
<li class="item1">img</li>
|
||||
<li class="item2">$hithere</li>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
const htmlContentsForInlineWrapTests = `
|
||||
<ul class="nav main">
|
||||
<em class="item1">img</em>
|
||||
<em class="item2">$hithere</em>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
const wrapBlockElementExpected = `
|
||||
<ul class="nav main">
|
||||
<div>
|
||||
|
@ -29,15 +36,19 @@ const wrapBlockElementExpected = `
|
|||
|
||||
const wrapInlineElementExpected = `
|
||||
<ul class="nav main">
|
||||
<span><li class="item1">img</li></span>
|
||||
<span><li class="item2">$hithere</li></span>
|
||||
<span><em class="item1">img</em></span>
|
||||
<span><em class="item2">$hithere</em></span>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
const wrapSnippetExpected = `
|
||||
<ul class="nav main">
|
||||
<a href=""><li class="item1">img</li></a>
|
||||
<a href=""><li class="item2">$hithere</li></a>
|
||||
<a href="">
|
||||
<li class="item1">img</li>
|
||||
</a>
|
||||
<a href="">
|
||||
<li class="item2">$hithere</li>
|
||||
</a>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
|
@ -56,10 +67,16 @@ const wrapMultiLineAbbrExpected = `
|
|||
</ul>
|
||||
`;
|
||||
|
||||
// technically a bug, but also a feature (requested behaviour)
|
||||
// https://github.com/microsoft/vscode/issues/78015
|
||||
const wrapInlineElementExpectedFormatFalse = `
|
||||
<ul class="nav main">
|
||||
<h1><li class="item1">img</li></h1>
|
||||
<h1><li class="item2">$hithere</li></h1>
|
||||
<h1>
|
||||
<li class="item1">img</li>
|
||||
</h1>
|
||||
<h1>
|
||||
<li class="item2">$hithere</li>
|
||||
</h1>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
|
@ -73,51 +90,51 @@ suite('Tests for Wrap with Abbreviations', () => {
|
|||
const oldValueForSyntaxProfiles = workspace.getConfiguration('emmet').inspect('syntaxProfile');
|
||||
|
||||
test('Wrap with block element using multi cursor', () => {
|
||||
return testWrapWithAbbreviation(multiCursors, 'div', wrapBlockElementExpected);
|
||||
return testWrapWithAbbreviation(multiCursors, 'div', wrapBlockElementExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with inline element using multi cursor', () => {
|
||||
return testWrapWithAbbreviation(multiCursors, 'span', wrapInlineElementExpected);
|
||||
return testWrapWithAbbreviation(multiCursors, 'span', wrapInlineElementExpected, htmlContentsForInlineWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with snippet using multi cursor', () => {
|
||||
return testWrapWithAbbreviation(multiCursors, 'a', wrapSnippetExpected);
|
||||
return testWrapWithAbbreviation(multiCursors, 'a', wrapSnippetExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with multi line abbreviation using multi cursor', () => {
|
||||
return testWrapWithAbbreviation(multiCursors, 'ul>li', wrapMultiLineAbbrExpected);
|
||||
return testWrapWithAbbreviation(multiCursors, 'ul>li', wrapMultiLineAbbrExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with block element using multi cursor selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'div', wrapBlockElementExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'div', wrapBlockElementExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with inline element using multi cursor selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'span', wrapInlineElementExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'span', wrapInlineElementExpected, htmlContentsForInlineWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with snippet using multi cursor selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'a', wrapSnippetExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'a', wrapSnippetExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with multi line abbreviation using multi cursor selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'ul>li', wrapMultiLineAbbrExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithSelection, 'ul>li', wrapMultiLineAbbrExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with block element using multi cursor full line selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'div', wrapBlockElementExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'div', wrapBlockElementExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with inline element using multi cursor full line selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'span', wrapInlineElementExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'span', wrapInlineElementExpected, htmlContentsForInlineWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with snippet using multi cursor full line selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'a', wrapSnippetExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'a', wrapSnippetExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with multi line abbreviation using multi cursor full line selection', () => {
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'ul>li', wrapMultiLineAbbrExpected);
|
||||
return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'ul>li', wrapMultiLineAbbrExpected, htmlContentsForBlockWrapTests);
|
||||
});
|
||||
|
||||
test('Wrap with abbreviation and comment filter', () => {
|
||||
|
@ -128,15 +145,31 @@ suite('Tests for Wrap with Abbreviations', () => {
|
|||
`;
|
||||
const expectedContents = `
|
||||
<ul class="nav main">
|
||||
<li class="hello">
|
||||
line
|
||||
</li>
|
||||
<li class="hello">line</li>
|
||||
<!-- /.hello -->
|
||||
</ul>
|
||||
`;
|
||||
return testWrapWithAbbreviation([new Selection(2, 0, 2, 0)], 'li.hello|c', expectedContents, contents);
|
||||
});
|
||||
|
||||
test('Wrap with abbreviation link', () => {
|
||||
const contents = `
|
||||
<ul class="nav main">
|
||||
line
|
||||
</ul>
|
||||
`;
|
||||
const expectedContents = `
|
||||
<a href="https://example.com">
|
||||
<div>
|
||||
<ul class="nav main">
|
||||
line
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
`;
|
||||
return testWrapWithAbbreviation([new Selection(1, 1, 1, 1)], 'a[href="https://example.com"]>div', expectedContents, contents);
|
||||
});
|
||||
|
||||
test('Wrap with abbreviation entire node when cursor is on opening tag', () => {
|
||||
const contents = `
|
||||
<div class="nav main">
|
||||
|
@ -192,8 +225,12 @@ suite('Tests for Wrap with Abbreviations', () => {
|
|||
const wrapIndividualLinesExpected = `
|
||||
<ul class="nav main">
|
||||
<ul>
|
||||
<li class="hello1"><li class="item1">This $10 is not a tabstop</li></li>
|
||||
<li class="hello2"><li class="item2">hi.there</li></li>
|
||||
<li class="hello1">
|
||||
<li class="item1">This $10 is not a tabstop</li>
|
||||
</li>
|
||||
<li class="hello2">
|
||||
<li class="item2">hi.there</li>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
`;
|
||||
|
@ -210,8 +247,12 @@ suite('Tests for Wrap with Abbreviations', () => {
|
|||
const wrapIndividualLinesExpected = `
|
||||
<ul class="nav main">
|
||||
<ul>
|
||||
<li class="hello1"><li class="item1">img</li></li>
|
||||
<li class="hello2"><li class="item2">hi.there</li></li>
|
||||
<li class="hello1">
|
||||
<li class="item1">img</li>
|
||||
</li>
|
||||
<li class="hello2">
|
||||
<li class="item2">hi.there</li>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
`;
|
||||
|
@ -228,9 +269,13 @@ suite('Tests for Wrap with Abbreviations', () => {
|
|||
const wrapIndividualLinesExpected = `
|
||||
<ul class="nav main">
|
||||
<ul>
|
||||
<li class="hello"><li class="item1">img</li></li>
|
||||
<li class="hello">
|
||||
<li class="item1">img</li>
|
||||
</li>
|
||||
<!-- /.hello -->
|
||||
<li class="hello"><li class="item2">hi.there</li></li>
|
||||
<li class="hello">
|
||||
<li class="item2">hi.there</li>
|
||||
</li>
|
||||
<!-- /.hello -->
|
||||
</ul>
|
||||
</ul>
|
||||
|
@ -257,9 +302,9 @@ suite('Tests for Wrap with Abbreviations', () => {
|
|||
});
|
||||
|
||||
test('Wrap with abbreviation and format set to false', () => {
|
||||
return workspace.getConfiguration('emmet').update('syntaxProfiles',{ 'html' : { 'format': false } } , ConfigurationTarget.Global).then(() => {
|
||||
return testWrapWithAbbreviation(multiCursors,'h1',wrapInlineElementExpectedFormatFalse).then(() => {
|
||||
return workspace.getConfiguration('emmet').update('syntaxProfiles',oldValueForSyntaxProfiles ? oldValueForSyntaxProfiles.globalValue : undefined, ConfigurationTarget.Global);
|
||||
return workspace.getConfiguration('emmet').update('syntaxProfiles', { 'html' : { 'format': false } }, ConfigurationTarget.Global).then(() => {
|
||||
return testWrapWithAbbreviation(multiCursors, 'h1', wrapInlineElementExpectedFormatFalse, htmlContentsForBlockWrapTests).then(() => {
|
||||
return workspace.getConfiguration('emmet').update('syntaxProfiles', oldValueForSyntaxProfiles ? oldValueForSyntaxProfiles.globalValue : undefined, ConfigurationTarget.Global);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -302,23 +347,27 @@ suite('Tests for Wrap with Abbreviations', () => {
|
|||
</ul>
|
||||
`;
|
||||
|
||||
return testWrapWithAbbreviation([new Selection(2,2,3,33)], '.hello', wrapMultiLineJsxExpected, htmlContentsForWrapTests, 'jsx');
|
||||
return testWrapWithAbbreviation([new Selection(2,2,3,33)], '.hello', wrapMultiLineJsxExpected, htmlContentsForBlockWrapTests, 'jsx');
|
||||
});
|
||||
|
||||
test('Wrap individual line with abbreviation uses className for jsx files', () => {
|
||||
const wrapIndividualLinesJsxExpected = `
|
||||
<ul class="nav main">
|
||||
<div className="hello1"><li class="item1">img</li></div>
|
||||
<div className="hello2"><li class="item2">$hithere</li></div>
|
||||
<div className="hello1">
|
||||
<li class="item1">img</li>
|
||||
</div>
|
||||
<div className="hello2">
|
||||
<li class="item2">$hithere</li>
|
||||
</div>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
return testWrapIndividualLinesWithAbbreviation([new Selection(2,2,3,33)], '.hello$*', wrapIndividualLinesJsxExpected, htmlContentsForWrapTests, 'jsx');
|
||||
return testWrapIndividualLinesWithAbbreviation([new Selection(2,2,3,33)], '.hello$*', wrapIndividualLinesJsxExpected, htmlContentsForBlockWrapTests, 'jsx');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function testWrapWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string = htmlContentsForWrapTests, fileExtension: string = 'html'): Thenable<any> {
|
||||
function testWrapWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string, fileExtension: string = 'html'): Thenable<any> {
|
||||
return withRandomFileEditor(input, fileExtension, (editor, _) => {
|
||||
editor.selections = selections;
|
||||
const promise = wrapWithAbbreviation({ abbreviation });
|
||||
|
@ -334,7 +383,7 @@ function testWrapWithAbbreviation(selections: Selection[], abbreviation: string,
|
|||
});
|
||||
}
|
||||
|
||||
function testWrapIndividualLinesWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string = htmlContentsForWrapTests, fileExtension: string = 'html'): Thenable<any> {
|
||||
function testWrapIndividualLinesWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string, fileExtension: string = 'html'): Thenable<any> {
|
||||
return withRandomFileEditor(input, fileExtension, (editor, _) => {
|
||||
editor.selections = selections;
|
||||
const promise = wrapIndividualLinesWithAbbreviation({ abbreviation });
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@emmetio/abbreviation@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@emmetio/abbreviation/-/abbreviation-2.0.2.tgz#e26d55d78c00cdeb2ef983e902c7ad55ed0b648d"
|
||||
integrity sha512-kpWg6jyR1YEj/yWceruvDj/fe1BhXqA0tGH3Z2ZiPFo8SDMH4JHg6FChqon5x0CCfLf4zVswrQa0gcZ4XtdRBQ==
|
||||
"@emmetio/abbreviation@^2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@emmetio/abbreviation/-/abbreviation-2.2.0.tgz#9f8dedbdb00e3136d6d37c6415375c82c0bb477f"
|
||||
integrity sha512-NPGVUmnr7cLj4i6MKS4c8NjuoIIJROrruJl/8nXsp2MdbDRHvtfq25foySvv/NbfqTQm+P9JzVLDD9JxGIpvkQ==
|
||||
dependencies:
|
||||
"@emmetio/scanner" "^1.0.0"
|
||||
|
||||
|
@ -54,16 +54,15 @@
|
|||
integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI=
|
||||
|
||||
"@types/node@^12.19.9":
|
||||
version "12.19.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679"
|
||||
integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==
|
||||
version "12.19.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.12.tgz#04793c2afa4ce833a9972e4c476432e30f9df47b"
|
||||
integrity sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==
|
||||
|
||||
emmet@^2.1.5:
|
||||
version "2.1.6"
|
||||
resolved "https://registry.yarnpkg.com/emmet/-/emmet-2.1.6.tgz#425e0bcef6bf6e5eb758610f3e8d49f86a6fe877"
|
||||
integrity sha512-kfJMlze+k8jpX5CUx7xPYS83DxRNXuh8rQ98rQKnnf+wfo/KD+BG6pmpnEp5a7a1DWM9xmllKuOPfC7MeRmepQ==
|
||||
"emmet@https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a":
|
||||
version "2.3.0"
|
||||
resolved "https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a"
|
||||
dependencies:
|
||||
"@emmetio/abbreviation" "^2.0.2"
|
||||
"@emmetio/abbreviation" "^2.2.0"
|
||||
"@emmetio/css-abbreviation" "^2.1.2"
|
||||
|
||||
image-size@^0.5.2:
|
||||
|
@ -76,12 +75,12 @@ jsonc-parser@^2.3.0:
|
|||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342"
|
||||
integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==
|
||||
|
||||
vscode-emmet-helper@~2.0.0:
|
||||
version "2.0.9"
|
||||
resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.0.9.tgz#16244c087cba4e379116f268384bb644649db6ad"
|
||||
integrity sha512-S6RjnR9gUicl8LsYnQAMNqqOxolud9gcj+NpPyEnxfxp1YIBuC9oetj6l6N9VMZBWu6tL77wmf+/EJsRx1PDPA==
|
||||
vscode-emmet-helper@2.2.4-2:
|
||||
version "2.2.4-2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.2.4-2.tgz#8019188077a91dbe9a8d8c10c0b79369bb5c24d6"
|
||||
integrity sha512-7UTZXwt9M1xwaV72o2YgSBVoghtDtscTgYTOl1kiPkXN9OKiM4N52hcHFA1LlRtdTvIQd4PEkgaz57F9ZT/4kg==
|
||||
dependencies:
|
||||
emmet "^2.1.5"
|
||||
emmet "https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a"
|
||||
jsonc-parser "^2.3.0"
|
||||
vscode-languageserver-textdocument "^1.0.1"
|
||||
vscode-languageserver-types "^3.15.1"
|
||||
|
@ -94,9 +93,9 @@ vscode-languageserver-textdocument@^1.0.1:
|
|||
integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==
|
||||
|
||||
vscode-languageserver-types@^3.15.1:
|
||||
version "3.15.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de"
|
||||
integrity sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==
|
||||
version "3.16.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247"
|
||||
integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==
|
||||
|
||||
vscode-nls@^5.0.0:
|
||||
version "5.0.0"
|
||||
|
|
Loading…
Reference in a new issue