in src/services/htmlCompletion.ts [372:460]
documentation: localize('entity.propose', `Character entity representing '${entities[entity]}'`),
textEdit: TextEdit.replace(range, label),
insertTextFormat: InsertTextFormat.PlainText
});
}
}
}
return result;
}
function suggestDoctype(replaceStart: number, replaceEnd: number) {
const range = getReplaceRange(replaceStart, replaceEnd);
result.items.push({
label: '!DOCTYPE',
kind: CompletionItemKind.Property,
documentation: 'A preamble for an HTML document.',
textEdit: TextEdit.replace(range, '!DOCTYPE html>'),
insertTextFormat: InsertTextFormat.PlainText
});
}
let token = scanner.scan();
while (token !== TokenType.EOS && scanner.getTokenOffset() <= offset) {
switch (token) {
case TokenType.StartTagOpen:
if (scanner.getTokenEnd() === offset) {
const endPos = scanNextForEndPos(TokenType.StartTag);
if (position.line === 0) {
suggestDoctype(offset, endPos);
}
return collectTagSuggestions(offset, endPos);
}
break;
case TokenType.StartTag:
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) {
return collectOpenTagSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd());
}
currentTag = scanner.getTokenText();
break;
case TokenType.AttributeName:
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) {
return collectAttributeNameSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd());
}
currentAttributeName = scanner.getTokenText();
break;
case TokenType.DelimiterAssign:
if (scanner.getTokenEnd() === offset) {
const endPos = scanNextForEndPos(TokenType.AttributeValue);
return collectAttributeValueSuggestions(offset, endPos);
}
break;
case TokenType.AttributeValue:
if (scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd()) {
return collectAttributeValueSuggestions(scanner.getTokenOffset(), scanner.getTokenEnd());
}
break;
case TokenType.Whitespace:
if (offset <= scanner.getTokenEnd()) {
switch (scanner.getScannerState()) {
case ScannerState.AfterOpeningStartTag:
const startPos = scanner.getTokenOffset();
const endTagPos = scanNextForEndPos(TokenType.StartTag);
return collectTagSuggestions(startPos, endTagPos);
case ScannerState.WithinTag:
case ScannerState.AfterAttributeName:
return collectAttributeNameSuggestions(scanner.getTokenEnd());
case ScannerState.BeforeAttributeValue:
return collectAttributeValueSuggestions(scanner.getTokenEnd());
case ScannerState.AfterOpeningEndTag:
return collectCloseTagSuggestions(scanner.getTokenOffset() - 1, false);
case ScannerState.WithinContent:
return collectInsideContent();
}
}
break;
case TokenType.EndTagOpen:
if (offset <= scanner.getTokenEnd()) {
const afterOpenBracket = scanner.getTokenOffset() + 1;
const endOffset = scanNextForEndPos(TokenType.EndTag);
return collectCloseTagSuggestions(afterOpenBracket, false, endOffset);
}
break;
case TokenType.EndTag:
if (offset <= scanner.getTokenEnd()) {
let start = scanner.getTokenOffset() - 1;
while (start >= 0) {
const ch = text.charAt(start);
if (ch === '/') {