Better readability for util.ts
This commit is contained in:
parent
610918d48f
commit
dcc243c992
|
@ -17,7 +17,7 @@ import { fetchEditPoint } from './editPoint';
|
|||
import { fetchSelectItem } from './selectItem';
|
||||
import { evaluateMathExpression } from './evaluateMathExpression';
|
||||
import { incrementDecrement } from './incrementDecrement';
|
||||
import { LANGUAGE_MODES, getMappingForIncludedLanguages, resolveUpdateExtensionsPath } from './util';
|
||||
import { LANGUAGE_MODES, getMappingForIncludedLanguages, updateEmmetExtensionsPath } from './util';
|
||||
import { updateImageSize } from './updateImageSize';
|
||||
import { reflectCssValue } from './reflectCssValue';
|
||||
|
||||
|
@ -129,11 +129,15 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
return reflectCssValue();
|
||||
}));
|
||||
|
||||
resolveUpdateExtensionsPath();
|
||||
updateEmmetExtensionsPath();
|
||||
|
||||
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => {
|
||||
registerCompletionProviders(context);
|
||||
resolveUpdateExtensionsPath();
|
||||
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e) => {
|
||||
if (e.affectsConfiguration('emmet.includeLanguages')) {
|
||||
registerCompletionProviders(context);
|
||||
}
|
||||
if (e.affectsConfiguration('emmet.extensionsPath')) {
|
||||
updateEmmetExtensionsPath();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,19 @@ let _emmetHelper: any;
|
|||
let _currentExtensionsPath: string | undefined = undefined;
|
||||
|
||||
export function getEmmetHelper() {
|
||||
// Lazy load vscode-emmet-helper instead of importing it
|
||||
// directly to reduce the start-up time of the extension
|
||||
if (!_emmetHelper) {
|
||||
_emmetHelper = require('vscode-emmet-helper');
|
||||
}
|
||||
resolveUpdateExtensionsPath();
|
||||
updateEmmetExtensionsPath();
|
||||
return _emmetHelper;
|
||||
}
|
||||
|
||||
export function resolveUpdateExtensionsPath() {
|
||||
/**
|
||||
* Update Emmet Helper to use user snippets from the extensionsPath setting
|
||||
*/
|
||||
export function updateEmmetExtensionsPath() {
|
||||
if (!_emmetHelper) {
|
||||
return;
|
||||
}
|
||||
|
@ -31,7 +36,10 @@ export function resolveUpdateExtensionsPath() {
|
|||
}
|
||||
}
|
||||
|
||||
export const LANGUAGE_MODES: any = {
|
||||
/**
|
||||
* Mapping between languages that support Emmet and completion trigger characters
|
||||
*/
|
||||
export const LANGUAGE_MODES: { [id: string]: string[] } = {
|
||||
'html': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
||||
'jade': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
||||
'slim': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
||||
|
@ -47,19 +55,6 @@ export const LANGUAGE_MODES: any = {
|
|||
'typescriptreact': ['!', '.', '}', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
||||
};
|
||||
|
||||
export const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template', 'text/template', 'text/ng-template'];
|
||||
|
||||
const emmetModes = ['html', 'pug', 'slim', 'haml', 'xml', 'xsl', 'jsx', 'css', 'scss', 'sass', 'less', 'stylus'];
|
||||
|
||||
// Explicitly map languages that have built-in grammar in VS Code to their parent language
|
||||
// to get emmet completion support
|
||||
// For other languages, users will have to use `emmet.includeLanguages` or
|
||||
// language specific extensions can provide emmet completion support
|
||||
export const MAPPED_MODES: Object = {
|
||||
'handlebars': 'html',
|
||||
'php': 'html'
|
||||
};
|
||||
|
||||
export function isStyleSheet(syntax: string): boolean {
|
||||
let stylesheetSyntaxes = ['css', 'scss', 'sass', 'less', 'stylus'];
|
||||
return (stylesheetSyntaxes.indexOf(syntax) > -1);
|
||||
|
@ -78,6 +73,15 @@ export function validate(allowStylesheet: boolean = true): boolean {
|
|||
}
|
||||
|
||||
export function getMappingForIncludedLanguages(): any {
|
||||
// Explicitly map languages that have built-in grammar in VS Code to their parent language
|
||||
// to get emmet completion support
|
||||
// For other languages, users will have to use `emmet.includeLanguages` or
|
||||
// language specific extensions can provide emmet completion support
|
||||
const MAPPED_MODES: Object = {
|
||||
'handlebars': 'html',
|
||||
'php': 'html'
|
||||
};
|
||||
|
||||
const finalMappedModes = Object.create(null);
|
||||
let includeLanguagesConfig = vscode.workspace.getConfiguration('emmet')['includeLanguages'];
|
||||
let includeLanguages = Object.assign({}, MAPPED_MODES, includeLanguagesConfig ? includeLanguagesConfig : {});
|
||||
|
@ -111,6 +115,7 @@ export function getEmmetMode(language: string, excludedLanguages: string[]): str
|
|||
if (language === 'jade') {
|
||||
return 'pug';
|
||||
}
|
||||
const emmetModes = ['html', 'pug', 'slim', 'haml', 'xml', 'xsl', 'jsx', 'css', 'scss', 'sass', 'less', 'stylus'];
|
||||
if (emmetModes.indexOf(language) > -1) {
|
||||
return language;
|
||||
}
|
||||
|
@ -137,6 +142,12 @@ const openBrace = 123;
|
|||
const slash = 47;
|
||||
const star = 42;
|
||||
|
||||
/**
|
||||
* Traverse the given document backward & forward from given position
|
||||
* to find a complete ruleset, then parse just that to return a Stylesheet
|
||||
* @param document vscode.TextDocument
|
||||
* @param position vscode.Position
|
||||
*/
|
||||
export function parsePartialStylesheet(document: vscode.TextDocument, position: vscode.Position): Stylesheet | undefined {
|
||||
const isCSS = document.languageId === 'css';
|
||||
let startPosition = new vscode.Position(0, 0);
|
||||
|
@ -145,6 +156,25 @@ export function parsePartialStylesheet(document: vscode.TextDocument, position:
|
|||
const limitPosition = limitCharacter > 0 ? document.positionAt(limitCharacter) : startPosition;
|
||||
const stream = new DocumentStreamReader(document, position);
|
||||
|
||||
function findOpeningCommentBeforePosition(pos: vscode.Position): vscode.Position | undefined {
|
||||
let text = document.getText(new vscode.Range(0, 0, pos.line, pos.character));
|
||||
let offset = text.lastIndexOf('/*');
|
||||
if (offset === -1) {
|
||||
return;
|
||||
}
|
||||
return document.positionAt(offset);
|
||||
}
|
||||
|
||||
function findClosingCommentAfterPosition(pos: vscode.Position): vscode.Position | undefined {
|
||||
let text = document.getText(new vscode.Range(pos.line, pos.character, document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length));
|
||||
let offset = text.indexOf('*/');
|
||||
if (offset === -1) {
|
||||
return;
|
||||
}
|
||||
offset += 2 + document.offsetAt(pos);
|
||||
return document.positionAt(offset);
|
||||
}
|
||||
|
||||
function consumeLineCommentBackwards() {
|
||||
if (!isCSS && currentLine !== stream.pos.line) {
|
||||
currentLine = stream.pos.line;
|
||||
|
@ -158,7 +188,7 @@ export function parsePartialStylesheet(document: vscode.TextDocument, position:
|
|||
function consumeBlockCommentBackwards() {
|
||||
if (stream.peek() === slash) {
|
||||
if (stream.backUp(1) === star) {
|
||||
stream.pos = findOpeningCommentBeforePosition(document, stream.pos) || startPosition;
|
||||
stream.pos = findOpeningCommentBeforePosition(stream.pos) || startPosition;
|
||||
} else {
|
||||
stream.next();
|
||||
}
|
||||
|
@ -170,7 +200,7 @@ export function parsePartialStylesheet(document: vscode.TextDocument, position:
|
|||
if (stream.eat(slash) && !isCSS) {
|
||||
stream.pos = new vscode.Position(stream.pos.line + 1, 0);
|
||||
} else if (stream.eat(star)) {
|
||||
stream.pos = findClosingCommentAfterPosition(document, stream.pos) || endPosition;
|
||||
stream.pos = findClosingCommentAfterPosition(stream.pos) || endPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,25 +294,6 @@ export function parsePartialStylesheet(document: vscode.TextDocument, position:
|
|||
}
|
||||
}
|
||||
|
||||
function findOpeningCommentBeforePosition(document: vscode.TextDocument, position: vscode.Position): vscode.Position | undefined {
|
||||
let text = document.getText(new vscode.Range(0, 0, position.line, position.character));
|
||||
let offset = text.lastIndexOf('/*');
|
||||
if (offset === -1) {
|
||||
return;
|
||||
}
|
||||
return document.positionAt(offset);
|
||||
}
|
||||
|
||||
function findClosingCommentAfterPosition(document: vscode.TextDocument, position: vscode.Position): vscode.Position | undefined {
|
||||
let text = document.getText(new vscode.Range(position.line, position.character, document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length));
|
||||
let offset = text.indexOf('*/');
|
||||
if (offset === -1) {
|
||||
return;
|
||||
}
|
||||
offset += 2 + document.offsetAt(position);
|
||||
return document.positionAt(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns node corresponding to given position in the given root node
|
||||
*/
|
||||
|
@ -311,11 +322,22 @@ export function getNode(root: Node | undefined, position: vscode.Position, inclu
|
|||
return foundNode;
|
||||
}
|
||||
|
||||
export const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template', 'text/template', 'text/ng-template'];
|
||||
|
||||
/**
|
||||
* Returns HTML node corresponding to given position in the given root node
|
||||
* If position is inside a script tag of type template, then it will be parsed to find the inner HTML node as well
|
||||
*/
|
||||
export function getHtmlNode(document: vscode.TextDocument, root: Node | undefined, position: vscode.Position, includeNodeBoundary: boolean): HtmlNode | undefined {
|
||||
let currentNode = <HtmlNode>getNode(root, position, includeNodeBoundary);
|
||||
if (!currentNode) { return; }
|
||||
|
||||
if (isTemplateScript(currentNode) && currentNode.close &&
|
||||
const isTemplateScript = currentNode.name === 'script' &&
|
||||
(currentNode.attributes &&
|
||||
currentNode.attributes.some(x => x.name.toString() === 'type'
|
||||
&& allowedMimeTypesInScriptTag.indexOf(x.value.toString()) > -1));
|
||||
|
||||
if (isTemplateScript && currentNode.close &&
|
||||
(position.isAfter(currentNode.open.end) && position.isBefore(currentNode.close.start))) {
|
||||
|
||||
let buffer = new DocumentStreamReader(document, currentNode.open.end, new vscode.Range(currentNode.open.end, currentNode.close.start));
|
||||
|
@ -340,6 +362,10 @@ export function getInnerRange(currentNode: HtmlNode): vscode.Range | undefined {
|
|||
return new vscode.Range(currentNode.open.end, currentNode.close.start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the deepest non comment node under given node
|
||||
* @param node
|
||||
*/
|
||||
export function getDeepestNode(node: Node | undefined): Node | undefined {
|
||||
if (!node || !node.children || node.children.length === 0 || !node.children.find(x => x.type !== 'comment')) {
|
||||
return node;
|
||||
|
@ -434,37 +460,32 @@ export function getNodesInBetween(node1: Node, node2: Node): Node[] {
|
|||
return [node1];
|
||||
}
|
||||
|
||||
// Same parent
|
||||
if (sameNodes(node1.parent, node2.parent)) {
|
||||
return getNextSiblingsTillPosition(node1, node2.end);
|
||||
// Not siblings
|
||||
if (!sameNodes(node1.parent, node2.parent)) {
|
||||
// node2 is ancestor of node1
|
||||
if (node2.start.isBefore(node1.start)) {
|
||||
return [node2];
|
||||
}
|
||||
|
||||
// node1 is ancestor of node2
|
||||
if (node2.start.isBefore(node1.end)) {
|
||||
return [node1];
|
||||
}
|
||||
|
||||
// Get the highest ancestor of node1 that should be commented
|
||||
while (node1.parent && node1.parent.end.isBefore(node2.start)) {
|
||||
node1 = node1.parent;
|
||||
}
|
||||
|
||||
// Get the highest ancestor of node2 that should be commented
|
||||
while (node2.parent && node2.parent.start.isAfter(node1.start)) {
|
||||
node2 = node2.parent;
|
||||
}
|
||||
}
|
||||
|
||||
// node2 is ancestor of node1
|
||||
if (node2.start.isBefore(node1.start)) {
|
||||
return [node2];
|
||||
}
|
||||
|
||||
// node1 is ancestor of node2
|
||||
if (node2.start.isBefore(node1.end)) {
|
||||
return [node1];
|
||||
}
|
||||
|
||||
// Get the highest ancestor of node1 that should be commented
|
||||
while (node1.parent && node1.parent.end.isBefore(node2.start)) {
|
||||
node1 = node1.parent;
|
||||
}
|
||||
|
||||
// Get the highest ancestor of node2 that should be commented
|
||||
while (node2.parent && node2.parent.start.isAfter(node1.start)) {
|
||||
node2 = node2.parent;
|
||||
}
|
||||
|
||||
return getNextSiblingsTillPosition(node1, node2.end);
|
||||
}
|
||||
|
||||
function getNextSiblingsTillPosition(node: Node, position: vscode.Position): Node[] {
|
||||
let siblings: Node[] = [];
|
||||
let currentNode = node;
|
||||
const siblings: Node[] = [];
|
||||
let currentNode = node1;
|
||||
const position = node2.end;
|
||||
while (currentNode && position.isAfter(currentNode.start)) {
|
||||
siblings.push(currentNode);
|
||||
currentNode = currentNode.nextSibling;
|
||||
|
@ -589,9 +610,4 @@ export function isStyleAttribute(currentNode: Node | null, position: vscode.Posi
|
|||
return position.isAfterOrEqual(styleAttribute.value.start) && position.isBeforeOrEqual(styleAttribute.value.end);
|
||||
}
|
||||
|
||||
export function isTemplateScript(currentNode: HtmlNode): boolean {
|
||||
return currentNode.name === 'script' &&
|
||||
(currentNode.attributes &&
|
||||
currentNode.attributes.some(x => x.name.toString() === 'type'
|
||||
&& allowedMimeTypesInScriptTag.indexOf(x.value.toString()) > -1));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue