vscode-html-languageservice
Advanced tools
Comparing version 2.0.16 to 2.0.17-next.1
@@ -22,6 +22,6 @@ import { TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, DocumentHighlight, FormattingOptions, MarkedString, DocumentLink } from 'vscode-languageserver-types'; | ||
export interface Node { | ||
tag: string; | ||
tag: string | undefined; | ||
start: number; | ||
end: number; | ||
endTagStart: number; | ||
endTagStart: number | undefined; | ||
children: Node[]; | ||
@@ -31,3 +31,3 @@ parent?: Node; | ||
[name: string]: string | null; | ||
}; | ||
} | undefined; | ||
} | ||
@@ -89,2 +89,11 @@ export declare enum TokenType { | ||
} | ||
export interface ICompletionParticipant { | ||
onHtmlAttributeValue?: (context: { | ||
tag: string; | ||
attribute: string; | ||
value: string; | ||
range: Range; | ||
}) => void; | ||
onHtmlContent?: () => void; | ||
} | ||
export interface LanguageService { | ||
@@ -95,2 +104,3 @@ createScanner(input: string, initialOffset?: number): Scanner; | ||
doComplete(document: TextDocument, position: Position, htmlDocument: HTMLDocument, options?: CompletionConfiguration): CompletionList; | ||
setCompletionParticipants(registeredCompletionParticipants: ICompletionParticipant[]): void; | ||
doHover(document: TextDocument, position: Position, htmlDocument: HTMLDocument): Hover | null; | ||
@@ -97,0 +107,0 @@ format(document: TextDocument, range: Range | undefined, options: HTMLFormatConfiguration): TextEdit[]; |
@@ -77,6 +77,8 @@ (function (factory) { | ||
function getLanguageService() { | ||
var htmlCompletion = new htmlCompletion_1.HTMLCompletion(); | ||
return { | ||
createScanner: htmlScanner_1.createScanner, | ||
parseHTMLDocument: function (document) { return htmlParser_1.parse(document.getText()); }, | ||
doComplete: htmlCompletion_1.doComplete, | ||
doComplete: htmlCompletion.doComplete.bind(htmlCompletion), | ||
setCompletionParticipants: htmlCompletion.setCompletionParticipants.bind(htmlCompletion), | ||
doHover: htmlHover_1.doHover, | ||
@@ -87,3 +89,3 @@ format: htmlFormatter_1.format, | ||
findDocumentSymbols: htmlSymbolsProvider_1.findDocumentSymbols, | ||
doTagComplete: htmlCompletion_1.doTagComplete | ||
doTagComplete: htmlCompletion.doTagComplete.bind(htmlCompletion), | ||
}; | ||
@@ -90,0 +92,0 @@ } |
@@ -25,2 +25,3 @@ (function (factory) { | ||
this.parent = parent; | ||
this.closed = false; | ||
} | ||
@@ -94,3 +95,3 @@ Object.defineProperty(Node.prototype, "attributeNames", { | ||
curr.end = scanner.getTokenEnd(); // might be later set to end tag position | ||
if (htmlTags_1.isEmptyElement(curr.tag) && curr.parent) { | ||
if (curr.tag && htmlTags_1.isEmptyElement(curr.tag) && curr.parent) { | ||
curr.closed = true; | ||
@@ -97,0 +98,0 @@ curr = curr.parent; |
@@ -24,382 +24,404 @@ (function (factory) { | ||
var localize = nls.loadMessageBundle(); | ||
function doComplete(document, position, htmlDocument, settings) { | ||
var result = { | ||
isIncomplete: false, | ||
items: [] | ||
var HTMLCompletion = /** @class */ (function () { | ||
function HTMLCompletion() { | ||
this.completionParticipants = []; | ||
} | ||
HTMLCompletion.prototype.setCompletionParticipants = function (registeredCompletionParticipants) { | ||
this.completionParticipants = registeredCompletionParticipants || []; | ||
}; | ||
var tagProviders = tagProviders_1.allTagProviders.filter(function (p) { return p.isApplicable(document.languageId) && (!settings || settings[p.getId()] !== false); }); | ||
var text = document.getText(); | ||
var offset = document.offsetAt(position); | ||
var node = htmlDocument.findNodeBefore(offset); | ||
if (!node) { | ||
return result; | ||
} | ||
var scanner = htmlScanner_1.createScanner(text, node.start); | ||
var currentTag = ''; | ||
var currentAttributeName; | ||
function getReplaceRange(replaceStart, replaceEnd) { | ||
if (replaceEnd === void 0) { replaceEnd = offset; } | ||
if (replaceStart > offset) { | ||
replaceStart = offset; | ||
HTMLCompletion.prototype.doComplete = function (document, position, htmlDocument, settings) { | ||
var result = { | ||
isIncomplete: false, | ||
items: [] | ||
}; | ||
var completionParticipants = this.completionParticipants; | ||
var tagProviders = tagProviders_1.allTagProviders.filter(function (p) { return p.isApplicable(document.languageId) && (!settings || settings[p.getId()] !== false); }); | ||
var text = document.getText(); | ||
var offset = document.offsetAt(position); | ||
var node = htmlDocument.findNodeBefore(offset); | ||
if (!node) { | ||
return result; | ||
} | ||
return { start: document.positionAt(replaceStart), end: document.positionAt(replaceEnd) }; | ||
} | ||
function collectOpenTagSuggestions(afterOpenBracket, tagNameEnd) { | ||
var range = getReplaceRange(afterOpenBracket, tagNameEnd); | ||
tagProviders.forEach(function (provider) { | ||
provider.collectTags(function (tag, label) { | ||
result.items.push({ | ||
label: tag, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Property, | ||
documentation: label, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, tag), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
var scanner = htmlScanner_1.createScanner(text, node.start); | ||
var currentTag = ''; | ||
var currentAttributeName; | ||
function getReplaceRange(replaceStart, replaceEnd) { | ||
if (replaceEnd === void 0) { replaceEnd = offset; } | ||
if (replaceStart > offset) { | ||
replaceStart = offset; | ||
} | ||
return { start: document.positionAt(replaceStart), end: document.positionAt(replaceEnd) }; | ||
} | ||
function collectOpenTagSuggestions(afterOpenBracket, tagNameEnd) { | ||
var range = getReplaceRange(afterOpenBracket, tagNameEnd); | ||
tagProviders.forEach(function (provider) { | ||
provider.collectTags(function (tag, label) { | ||
result.items.push({ | ||
label: tag, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Property, | ||
documentation: label, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, tag), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
}); | ||
}); | ||
}); | ||
}); | ||
return result; | ||
} | ||
function getLineIndent(offset) { | ||
var start = offset; | ||
while (start > 0) { | ||
var ch = text.charAt(start - 1); | ||
if ("\n\r".indexOf(ch) >= 0) { | ||
return text.substring(start, offset); | ||
return result; | ||
} | ||
function getLineIndent(offset) { | ||
var start = offset; | ||
while (start > 0) { | ||
var ch = text.charAt(start - 1); | ||
if ("\n\r".indexOf(ch) >= 0) { | ||
return text.substring(start, offset); | ||
} | ||
if (!isWhiteSpace(ch)) { | ||
return null; | ||
} | ||
start--; | ||
} | ||
if (!isWhiteSpace(ch)) { | ||
return null; | ||
return text.substring(0, offset); | ||
} | ||
function collectCloseTagSuggestions(afterOpenBracket, inOpenTag, tagNameEnd) { | ||
if (tagNameEnd === void 0) { tagNameEnd = offset; } | ||
var range = getReplaceRange(afterOpenBracket, tagNameEnd); | ||
var closeTag = isFollowedBy(text, tagNameEnd, htmlScanner_1.ScannerState.WithinEndTag, htmlScanner_1.TokenType.EndTagClose) ? '' : '>'; | ||
var curr = node; | ||
if (inOpenTag) { | ||
curr = curr.parent; // don't suggest the own tag, it's not yet open | ||
} | ||
start--; | ||
} | ||
return text.substring(0, offset); | ||
} | ||
function collectCloseTagSuggestions(afterOpenBracket, inOpenTag, tagNameEnd) { | ||
if (tagNameEnd === void 0) { tagNameEnd = offset; } | ||
var range = getReplaceRange(afterOpenBracket, tagNameEnd); | ||
var closeTag = isFollowedBy(text, tagNameEnd, htmlScanner_1.ScannerState.WithinEndTag, htmlScanner_1.TokenType.EndTagClose) ? '' : '>'; | ||
var curr = node; | ||
if (inOpenTag) { | ||
curr = curr.parent; // don't suggest the own tag, it's not yet open | ||
} | ||
while (curr) { | ||
var tag = curr.tag; | ||
if (tag && (!curr.closed || curr.endTagStart > offset)) { | ||
var item = { | ||
label: '/' + tag, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Property, | ||
filterText: '/' + tag + closeTag, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, '/' + tag + closeTag), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
}; | ||
var startIndent = getLineIndent(curr.start); | ||
var endIndent = getLineIndent(afterOpenBracket - 1); | ||
if (startIndent !== null && endIndent !== null && startIndent !== endIndent) { | ||
var insertText = startIndent + '</' + tag + closeTag; | ||
item.textEdit = vscode_languageserver_types_1.TextEdit.replace(getReplaceRange(afterOpenBracket - 1 - endIndent.length), insertText); | ||
item.filterText = endIndent + '</' + tag + closeTag; | ||
while (curr) { | ||
var tag = curr.tag; | ||
if (tag && (!curr.closed || curr.endTagStart && (curr.endTagStart > offset))) { | ||
var item = { | ||
label: '/' + tag, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Property, | ||
filterText: '/' + tag + closeTag, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, '/' + tag + closeTag), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
}; | ||
var startIndent = getLineIndent(curr.start); | ||
var endIndent = getLineIndent(afterOpenBracket - 1); | ||
if (startIndent !== null && endIndent !== null && startIndent !== endIndent) { | ||
var insertText = startIndent + '</' + tag + closeTag; | ||
item.textEdit = vscode_languageserver_types_1.TextEdit.replace(getReplaceRange(afterOpenBracket - 1 - endIndent.length), insertText); | ||
item.filterText = endIndent + '</' + tag + closeTag; | ||
} | ||
result.items.push(item); | ||
return result; | ||
} | ||
result.items.push(item); | ||
curr = curr.parent; | ||
} | ||
if (inOpenTag) { | ||
return result; | ||
} | ||
curr = curr.parent; | ||
} | ||
if (inOpenTag) { | ||
tagProviders.forEach(function (provider) { | ||
provider.collectTags(function (tag, label) { | ||
result.items.push({ | ||
label: '/' + tag, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Property, | ||
documentation: label, | ||
filterText: '/' + tag + closeTag, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, '/' + tag + closeTag), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
}); | ||
}); | ||
}); | ||
return result; | ||
} | ||
tagProviders.forEach(function (provider) { | ||
provider.collectTags(function (tag, label) { | ||
function collectAutoCloseTagSuggestion(tagCloseEnd, tag) { | ||
if (settings && settings.hideAutoCompleteProposals) { | ||
return result; | ||
} | ||
if (!htmlTags_1.isEmptyElement(tag)) { | ||
var pos = document.positionAt(tagCloseEnd); | ||
result.items.push({ | ||
label: '/' + tag, | ||
label: '</' + tag + '>', | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Property, | ||
documentation: label, | ||
filterText: '/' + tag + closeTag, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, '/' + tag + closeTag), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
filterText: '</' + tag + '>', | ||
textEdit: vscode_languageserver_types_1.TextEdit.insert(pos, '$0</' + tag + '>'), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.Snippet | ||
}); | ||
}); | ||
}); | ||
return result; | ||
} | ||
function collectAutoCloseTagSuggestion(tagCloseEnd, tag) { | ||
if (settings && settings.hideAutoCompleteProposals) { | ||
} | ||
return result; | ||
} | ||
if (!htmlTags_1.isEmptyElement(tag)) { | ||
var pos = document.positionAt(tagCloseEnd); | ||
result.items.push({ | ||
label: '</' + tag + '>', | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Property, | ||
filterText: '</' + tag + '>', | ||
textEdit: vscode_languageserver_types_1.TextEdit.insert(pos, '$0</' + tag + '>'), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.Snippet | ||
}); | ||
function collectTagSuggestions(tagStart, tagEnd) { | ||
collectOpenTagSuggestions(tagStart, tagEnd); | ||
collectCloseTagSuggestions(tagStart, true, tagEnd); | ||
return result; | ||
} | ||
return result; | ||
} | ||
function collectTagSuggestions(tagStart, tagEnd) { | ||
collectOpenTagSuggestions(tagStart, tagEnd); | ||
collectCloseTagSuggestions(tagStart, true, tagEnd); | ||
return result; | ||
} | ||
function collectAttributeNameSuggestions(nameStart, nameEnd) { | ||
if (nameEnd === void 0) { nameEnd = offset; } | ||
var replaceEnd = offset; | ||
while (replaceEnd < nameEnd && text[replaceEnd] !== '<') { | ||
replaceEnd++; | ||
} | ||
var range = getReplaceRange(nameStart, replaceEnd); | ||
var value = isFollowedBy(text, nameEnd, htmlScanner_1.ScannerState.AfterAttributeName, htmlScanner_1.TokenType.DelimiterAssign) ? '' : '="$1"'; | ||
var tag = currentTag.toLowerCase(); | ||
tagProviders.forEach(function (provider) { | ||
provider.collectAttributes(tag, function (attribute, type) { | ||
var codeSnippet = attribute; | ||
var command; | ||
if (type !== 'v' && value.length) { | ||
codeSnippet = codeSnippet + value; | ||
if (type) { | ||
command = { | ||
title: 'Suggest', | ||
command: 'editor.action.triggerSuggest' | ||
}; | ||
function collectAttributeNameSuggestions(nameStart, nameEnd) { | ||
if (nameEnd === void 0) { nameEnd = offset; } | ||
var replaceEnd = offset; | ||
while (replaceEnd < nameEnd && text[replaceEnd] !== '<') { | ||
replaceEnd++; | ||
} | ||
var range = getReplaceRange(nameStart, replaceEnd); | ||
var value = isFollowedBy(text, nameEnd, htmlScanner_1.ScannerState.AfterAttributeName, htmlScanner_1.TokenType.DelimiterAssign) ? '' : '="$1"'; | ||
var tag = currentTag.toLowerCase(); | ||
tagProviders.forEach(function (provider) { | ||
provider.collectAttributes(tag, function (attribute, type) { | ||
var codeSnippet = attribute; | ||
var command; | ||
if (type !== 'v' && value.length) { | ||
codeSnippet = codeSnippet + value; | ||
if (type) { | ||
command = { | ||
title: 'Suggest', | ||
command: 'editor.action.triggerSuggest' | ||
}; | ||
} | ||
} | ||
} | ||
result.items.push({ | ||
label: attribute, | ||
kind: type === 'handler' ? vscode_languageserver_types_1.CompletionItemKind.Function : vscode_languageserver_types_1.CompletionItemKind.Value, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, codeSnippet), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.Snippet, | ||
command: command | ||
result.items.push({ | ||
label: attribute, | ||
kind: type === 'handler' ? vscode_languageserver_types_1.CompletionItemKind.Function : vscode_languageserver_types_1.CompletionItemKind.Value, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, codeSnippet), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.Snippet, | ||
command: command | ||
}); | ||
}); | ||
}); | ||
}); | ||
collectDataAttributesSuggestions(range); | ||
return result; | ||
} | ||
function collectDataAttributesSuggestions(range) { | ||
var dataAttr = 'data-'; | ||
var dataAttributes = {}; | ||
dataAttributes[dataAttr] = dataAttr + "$1=\"$2\""; | ||
function addNodeDataAttributes(node) { | ||
node.attributeNames.forEach(function (attr) { | ||
if (strings_1.startsWith(attr, dataAttr) && !dataAttributes[attr]) { | ||
dataAttributes[attr] = attr + '="$1"'; | ||
} | ||
}); | ||
node.children.forEach(function (child) { return addNodeDataAttributes(child); }); | ||
collectDataAttributesSuggestions(range); | ||
return result; | ||
} | ||
if (htmlDocument) { | ||
htmlDocument.roots.forEach(function (root) { return addNodeDataAttributes(root); }); | ||
} | ||
Object.keys(dataAttributes).forEach(function (attr) { return result.items.push({ | ||
label: attr, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Value, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, dataAttributes[attr]), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.Snippet | ||
}); }); | ||
} | ||
function collectAttributeValueSuggestions(valueStart, valueEnd) { | ||
if (valueEnd === void 0) { valueEnd = offset; } | ||
var range; | ||
var addQuotes; | ||
if (offset > valueStart && offset <= valueEnd && text[valueStart] === '"') { | ||
// inside attribute | ||
if (valueEnd > offset && text[valueEnd - 1] === '"') { | ||
valueEnd--; | ||
function collectDataAttributesSuggestions(range) { | ||
var dataAttr = 'data-'; | ||
var dataAttributes = {}; | ||
dataAttributes[dataAttr] = dataAttr + "$1=\"$2\""; | ||
function addNodeDataAttributes(node) { | ||
node.attributeNames.forEach(function (attr) { | ||
if (strings_1.startsWith(attr, dataAttr) && !dataAttributes[attr]) { | ||
dataAttributes[attr] = attr + '="$1"'; | ||
} | ||
}); | ||
node.children.forEach(function (child) { return addNodeDataAttributes(child); }); | ||
} | ||
var wsBefore = getWordStart(text, offset, valueStart + 1); | ||
var wsAfter = getWordEnd(text, offset, valueEnd); | ||
range = getReplaceRange(wsBefore, wsAfter); | ||
addQuotes = false; | ||
if (htmlDocument) { | ||
htmlDocument.roots.forEach(function (root) { return addNodeDataAttributes(root); }); | ||
} | ||
Object.keys(dataAttributes).forEach(function (attr) { return result.items.push({ | ||
label: attr, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Value, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, dataAttributes[attr]), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.Snippet | ||
}); }); | ||
} | ||
else { | ||
range = getReplaceRange(valueStart, valueEnd); | ||
addQuotes = true; | ||
} | ||
var tag = currentTag.toLowerCase(); | ||
var attribute = currentAttributeName.toLowerCase(); | ||
tagProviders.forEach(function (provider) { | ||
provider.collectValues(tag, attribute, function (value) { | ||
var insertText = addQuotes ? '"' + value + '"' : value; | ||
result.items.push({ | ||
label: value, | ||
filterText: insertText, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Unit, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, insertText), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
}); | ||
}); | ||
}); | ||
collectCharacterEntityProposals(); | ||
return result; | ||
} | ||
function scanNextForEndPos(nextToken) { | ||
if (offset === scanner.getTokenEnd()) { | ||
token = scanner.scan(); | ||
if (token === nextToken && scanner.getTokenOffset() === offset) { | ||
return scanner.getTokenEnd(); | ||
function collectAttributeValueSuggestions(valueStart, valueEnd) { | ||
if (valueEnd === void 0) { valueEnd = offset; } | ||
var range; | ||
var addQuotes; | ||
if (offset > valueStart && offset <= valueEnd && text[valueStart] === '"') { | ||
// inside attribute | ||
if (valueEnd > offset && text[valueEnd - 1] === '"') { | ||
valueEnd--; | ||
} | ||
var wsBefore = getWordStart(text, offset, valueStart + 1); | ||
var wsAfter = getWordEnd(text, offset, valueEnd); | ||
range = getReplaceRange(wsBefore, wsAfter); | ||
addQuotes = false; | ||
} | ||
} | ||
return offset; | ||
} | ||
function collectInsideContent() { | ||
return collectCharacterEntityProposals(); | ||
} | ||
function collectCharacterEntityProposals() { | ||
// character entities | ||
var k = offset - 1; | ||
var characterStart = position.character; | ||
while (k >= 0 && strings_1.isLetterOrDigit(text, k)) { | ||
k--; | ||
characterStart--; | ||
} | ||
if (k >= 0 && text[k] === '&') { | ||
var range = vscode_languageserver_types_1.Range.create(vscode_languageserver_types_1.Position.create(position.line, characterStart - 1), position); | ||
for (var entity in htmlEntities_1.entities) { | ||
if (strings_1.endsWith(entity, ';')) { | ||
var label = '&' + entity; | ||
else { | ||
range = getReplaceRange(valueStart, valueEnd); | ||
addQuotes = true; | ||
} | ||
var tag = currentTag.toLowerCase(); | ||
var attribute = currentAttributeName.toLowerCase(); | ||
var value = extractAttributeValue(scanner.getTokenText()); | ||
for (var _i = 0, completionParticipants_1 = completionParticipants; _i < completionParticipants_1.length; _i++) { | ||
var participant = completionParticipants_1[_i]; | ||
if (participant.onHtmlAttributeValue) { | ||
participant.onHtmlAttributeValue({ tag: tag, attribute: attribute, value: value, range: range }); | ||
} | ||
} | ||
tagProviders.forEach(function (provider) { | ||
provider.collectValues(tag, attribute, function (value) { | ||
var insertText = addQuotes ? '"' + value + '"' : value; | ||
result.items.push({ | ||
label: label, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Keyword, | ||
documentation: localize('entity.propose', "Character entity representing '" + htmlEntities_1.entities[entity] + "'"), | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, label), | ||
label: value, | ||
filterText: insertText, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Unit, | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, insertText), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
}); | ||
}); | ||
}); | ||
collectCharacterEntityProposals(); | ||
return result; | ||
} | ||
function scanNextForEndPos(nextToken) { | ||
if (offset === scanner.getTokenEnd()) { | ||
token = scanner.scan(); | ||
if (token === nextToken && scanner.getTokenOffset() === offset) { | ||
return scanner.getTokenEnd(); | ||
} | ||
} | ||
return offset; | ||
} | ||
return result; | ||
} | ||
var token = scanner.scan(); | ||
while (token !== htmlScanner_1.TokenType.EOS && scanner.getTokenOffset() <= offset) { | ||
switch (token) { | ||
case htmlScanner_1.TokenType.StartTagOpen: | ||
if (scanner.getTokenEnd() === offset) { | ||
var endPos = scanNextForEndPos(htmlScanner_1.TokenType.StartTag); | ||
return collectTagSuggestions(offset, endPos); | ||
function collectInsideContent() { | ||
for (var _i = 0, completionParticipants_2 = completionParticipants; _i < completionParticipants_2.length; _i++) { | ||
var participant = completionParticipants_2[_i]; | ||
if (participant.onHtmlContent) { | ||
participant.onHtmlContent(); | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.StartTag: | ||
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) { | ||
return collectOpenTagSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd()); | ||
} | ||
return collectCharacterEntityProposals(); | ||
} | ||
function collectCharacterEntityProposals() { | ||
// character entities | ||
var k = offset - 1; | ||
var characterStart = position.character; | ||
while (k >= 0 && strings_1.isLetterOrDigit(text, k)) { | ||
k--; | ||
characterStart--; | ||
} | ||
if (k >= 0 && text[k] === '&') { | ||
var range = vscode_languageserver_types_1.Range.create(vscode_languageserver_types_1.Position.create(position.line, characterStart - 1), position); | ||
for (var entity in htmlEntities_1.entities) { | ||
if (strings_1.endsWith(entity, ';')) { | ||
var label = '&' + entity; | ||
result.items.push({ | ||
label: label, | ||
kind: vscode_languageserver_types_1.CompletionItemKind.Keyword, | ||
documentation: localize('entity.propose', "Character entity representing '" + htmlEntities_1.entities[entity] + "'"), | ||
textEdit: vscode_languageserver_types_1.TextEdit.replace(range, label), | ||
insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText | ||
}); | ||
} | ||
} | ||
currentTag = scanner.getTokenText(); | ||
break; | ||
case htmlScanner_1.TokenType.AttributeName: | ||
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) { | ||
return collectAttributeNameSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd()); | ||
} | ||
currentAttributeName = scanner.getTokenText(); | ||
break; | ||
case htmlScanner_1.TokenType.DelimiterAssign: | ||
if (scanner.getTokenEnd() === offset) { | ||
return collectAttributeValueSuggestions(scanner.getTokenEnd()); | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.AttributeValue: | ||
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) { | ||
return collectAttributeValueSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd()); | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.Whitespace: | ||
if (offset <= scanner.getTokenEnd()) { | ||
switch (scanner.getScannerState()) { | ||
case htmlScanner_1.ScannerState.AfterOpeningStartTag: | ||
var startPos = scanner.getTokenOffset(); | ||
var endTagPos = scanNextForEndPos(htmlScanner_1.TokenType.StartTag); | ||
return collectTagSuggestions(startPos, endTagPos); | ||
case htmlScanner_1.ScannerState.WithinTag: | ||
case htmlScanner_1.ScannerState.AfterAttributeName: | ||
return collectAttributeNameSuggestions(scanner.getTokenEnd()); | ||
case htmlScanner_1.ScannerState.BeforeAttributeValue: | ||
return collectAttributeValueSuggestions(scanner.getTokenEnd()); | ||
case htmlScanner_1.ScannerState.AfterOpeningEndTag: | ||
return collectCloseTagSuggestions(scanner.getTokenOffset() - 1, false); | ||
case htmlScanner_1.ScannerState.WithinContent: | ||
return collectInsideContent(); | ||
} | ||
return result; | ||
} | ||
var token = scanner.scan(); | ||
while (token !== htmlScanner_1.TokenType.EOS && scanner.getTokenOffset() <= offset) { | ||
switch (token) { | ||
case htmlScanner_1.TokenType.StartTagOpen: | ||
if (scanner.getTokenEnd() === offset) { | ||
var endPos = scanNextForEndPos(htmlScanner_1.TokenType.StartTag); | ||
return collectTagSuggestions(offset, endPos); | ||
} | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.EndTagOpen: | ||
if (offset <= scanner.getTokenEnd()) { | ||
var afterOpenBracket = scanner.getTokenOffset() + 1; | ||
var endOffset = scanNextForEndPos(htmlScanner_1.TokenType.EndTag); | ||
return collectCloseTagSuggestions(afterOpenBracket, false, endOffset); | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.EndTag: | ||
if (offset <= scanner.getTokenEnd()) { | ||
var start = scanner.getTokenOffset() - 1; | ||
while (start >= 0) { | ||
var ch = text.charAt(start); | ||
if (ch === '/') { | ||
return collectCloseTagSuggestions(start, false, scanner.getTokenEnd()); | ||
break; | ||
case htmlScanner_1.TokenType.StartTag: | ||
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) { | ||
return collectOpenTagSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd()); | ||
} | ||
currentTag = scanner.getTokenText(); | ||
break; | ||
case htmlScanner_1.TokenType.AttributeName: | ||
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) { | ||
return collectAttributeNameSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd()); | ||
} | ||
currentAttributeName = scanner.getTokenText(); | ||
break; | ||
case htmlScanner_1.TokenType.DelimiterAssign: | ||
if (scanner.getTokenEnd() === offset) { | ||
return collectAttributeValueSuggestions(scanner.getTokenEnd()); | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.AttributeValue: | ||
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) { | ||
return collectAttributeValueSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd()); | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.Whitespace: | ||
if (offset <= scanner.getTokenEnd()) { | ||
switch (scanner.getScannerState()) { | ||
case htmlScanner_1.ScannerState.AfterOpeningStartTag: | ||
var startPos = scanner.getTokenOffset(); | ||
var endTagPos = scanNextForEndPos(htmlScanner_1.TokenType.StartTag); | ||
return collectTagSuggestions(startPos, endTagPos); | ||
case htmlScanner_1.ScannerState.WithinTag: | ||
case htmlScanner_1.ScannerState.AfterAttributeName: | ||
return collectAttributeNameSuggestions(scanner.getTokenEnd()); | ||
case htmlScanner_1.ScannerState.BeforeAttributeValue: | ||
return collectAttributeValueSuggestions(scanner.getTokenEnd()); | ||
case htmlScanner_1.ScannerState.AfterOpeningEndTag: | ||
return collectCloseTagSuggestions(scanner.getTokenOffset() - 1, false); | ||
case htmlScanner_1.ScannerState.WithinContent: | ||
return collectInsideContent(); | ||
} | ||
else if (!isWhiteSpace(ch)) { | ||
break; | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.EndTagOpen: | ||
if (offset <= scanner.getTokenEnd()) { | ||
var afterOpenBracket = scanner.getTokenOffset() + 1; | ||
var endOffset = scanNextForEndPos(htmlScanner_1.TokenType.EndTag); | ||
return collectCloseTagSuggestions(afterOpenBracket, false, endOffset); | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.EndTag: | ||
if (offset <= scanner.getTokenEnd()) { | ||
var start = scanner.getTokenOffset() - 1; | ||
while (start >= 0) { | ||
var ch = text.charAt(start); | ||
if (ch === '/') { | ||
return collectCloseTagSuggestions(start, false, scanner.getTokenEnd()); | ||
} | ||
else if (!isWhiteSpace(ch)) { | ||
break; | ||
} | ||
start--; | ||
} | ||
start--; | ||
} | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.StartTagClose: | ||
if (offset <= scanner.getTokenEnd()) { | ||
if (currentTag) { | ||
return collectAutoCloseTagSuggestion(scanner.getTokenEnd(), currentTag); | ||
break; | ||
case htmlScanner_1.TokenType.StartTagClose: | ||
if (offset <= scanner.getTokenEnd()) { | ||
if (currentTag) { | ||
return collectAutoCloseTagSuggestion(scanner.getTokenEnd(), currentTag); | ||
} | ||
} | ||
} | ||
break; | ||
case htmlScanner_1.TokenType.Content: | ||
if (offset <= scanner.getTokenEnd()) { | ||
return collectInsideContent(); | ||
} | ||
break; | ||
default: | ||
if (offset <= scanner.getTokenEnd()) { | ||
return result; | ||
} | ||
break; | ||
break; | ||
case htmlScanner_1.TokenType.Content: | ||
if (offset <= scanner.getTokenEnd()) { | ||
return collectInsideContent(); | ||
} | ||
break; | ||
default: | ||
if (offset <= scanner.getTokenEnd()) { | ||
return result; | ||
} | ||
break; | ||
} | ||
token = scanner.scan(); | ||
} | ||
token = scanner.scan(); | ||
} | ||
return result; | ||
} | ||
exports.doComplete = doComplete; | ||
function doTagComplete(document, position, htmlDocument) { | ||
var offset = document.offsetAt(position); | ||
if (offset <= 0) { | ||
return null; | ||
} | ||
var char = document.getText().charAt(offset - 1); | ||
if (char === '>') { | ||
var node = htmlDocument.findNodeBefore(offset); | ||
if (node && node.tag && !htmlTags_1.isEmptyElement(node.tag) && node.start < offset && (!node.endTagStart || node.endTagStart > offset)) { | ||
var scanner = htmlScanner_1.createScanner(document.getText(), node.start); | ||
var token = scanner.scan(); | ||
while (token !== htmlScanner_1.TokenType.EOS && scanner.getTokenEnd() <= offset) { | ||
if (token === htmlScanner_1.TokenType.StartTagClose && scanner.getTokenEnd() === offset) { | ||
return "$0</" + node.tag + ">"; | ||
return result; | ||
}; | ||
HTMLCompletion.prototype.doTagComplete = function (document, position, htmlDocument) { | ||
var offset = document.offsetAt(position); | ||
if (offset <= 0) { | ||
return null; | ||
} | ||
var char = document.getText().charAt(offset - 1); | ||
if (char === '>') { | ||
var node = htmlDocument.findNodeBefore(offset); | ||
if (node && node.tag && !htmlTags_1.isEmptyElement(node.tag) && node.start < offset && (!node.endTagStart || node.endTagStart > offset)) { | ||
var scanner = htmlScanner_1.createScanner(document.getText(), node.start); | ||
var token = scanner.scan(); | ||
while (token !== htmlScanner_1.TokenType.EOS && scanner.getTokenEnd() <= offset) { | ||
if (token === htmlScanner_1.TokenType.StartTagClose && scanner.getTokenEnd() === offset) { | ||
return "$0</" + node.tag + ">"; | ||
} | ||
token = scanner.scan(); | ||
} | ||
token = scanner.scan(); | ||
} | ||
} | ||
} | ||
else if (char === '/') { | ||
var node = htmlDocument.findNodeBefore(offset); | ||
while (node && node.closed) { | ||
node = node.parent; | ||
} | ||
if (node && node.tag) { | ||
var scanner = htmlScanner_1.createScanner(document.getText(), node.start); | ||
var token = scanner.scan(); | ||
while (token !== htmlScanner_1.TokenType.EOS && scanner.getTokenEnd() <= offset) { | ||
if (token === htmlScanner_1.TokenType.EndTagOpen && scanner.getTokenEnd() === offset) { | ||
return node.tag + ">"; | ||
else if (char === '/') { | ||
var node = htmlDocument.findNodeBefore(offset); | ||
while (node && node.closed) { | ||
node = node.parent; | ||
} | ||
if (node && node.tag) { | ||
var scanner = htmlScanner_1.createScanner(document.getText(), node.start); | ||
var token = scanner.scan(); | ||
while (token !== htmlScanner_1.TokenType.EOS && scanner.getTokenEnd() <= offset) { | ||
if (token === htmlScanner_1.TokenType.EndTagOpen && scanner.getTokenEnd() === offset) { | ||
return node.tag + ">"; | ||
} | ||
token = scanner.scan(); | ||
} | ||
token = scanner.scan(); | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
exports.doTagComplete = doTagComplete; | ||
return null; | ||
}; | ||
return HTMLCompletion; | ||
}()); | ||
exports.HTMLCompletion = HTMLCompletion; | ||
function isWhiteSpace(s) { | ||
@@ -431,3 +453,7 @@ return /^\s*$/.test(s); | ||
} | ||
function extractAttributeValue(input) { | ||
// Todo: decoding | ||
return input.replace(/^['"]/, '').replace(/['"]$/, ''); | ||
} | ||
}); | ||
//# sourceMappingURL=htmlCompletion.js.map |
@@ -51,5 +51,5 @@ (function (factory) { | ||
} | ||
return name; | ||
return name || '?'; | ||
} | ||
}); | ||
//# sourceMappingURL=htmlSymbolsProvider.js.map |
{ | ||
"name": "vscode-html-languageservice", | ||
"version": "2.0.16", | ||
"version": "2.0.17-next.1", | ||
"description": "Language service for HTML", | ||
@@ -21,4 +21,4 @@ "main": "./lib/htmlLanguageService.js", | ||
"mocha": "^4.0.1", | ||
"tslint": "^5.8.0", | ||
"typescript": "^2.6.1" | ||
"tslint": "^5.9.1", | ||
"typescript": "^2.7.2" | ||
}, | ||
@@ -25,0 +25,0 @@ "dependencies": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
347727
6976
2