Example #1
0
function getEmbeddedContentForNode(languageService: LanguageService, document: TextDocument, node: Node): { languageId: string, start: number, end: number } {
	if (node.tag === 'style') {
		let scanner = languageService.createScanner(document.getText().substring(node.start, node.end));
		let token = scanner.scan();
		while (token !== TokenType.EOS) {
			if (token === TokenType.Styles) {
				return { languageId: 'css', start: node.start + scanner.getTokenOffset(), end: node.start + scanner.getTokenEnd() };
			}
			token = scanner.scan();
		}
	} else if (node.tag === 'script') {
		let scanner = languageService.createScanner(document.getText().substring(node.start, node.end));
		let token = scanner.scan();
		let isTypeAttribute = false;
		let languageId = 'javascript';
		while (token !== TokenType.EOS) {
			if (token === TokenType.AttributeName) {
				isTypeAttribute = scanner.getTokenText() === 'type';
			} else if (token === TokenType.AttributeValue) {
				if (isTypeAttribute) {
					if (/["'](text|application)\/(java|ecma)script["']/.test(scanner.getTokenText())) {
						languageId = 'javascript';
					} else {
						languageId = void 0;
					}
				}
				isTypeAttribute = false;
			} else if (token === TokenType.Script) {
				return { languageId, start: node.start + scanner.getTokenOffset(), end: node.start + scanner.getTokenEnd() };
			}
			token = scanner.scan();
		}
	}
	return void 0;
}
Example #2
0
export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageMode {
	let globalSettings: Settings = {};
	let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
	return {
		getId() {
			return 'html';
		},
		configure(options: any) {
			globalSettings = options;
		},
		doComplete(document: TextDocument, position: Position, settings: Settings = globalSettings) {
			let options = settings && settings.html && settings.html.suggest;
			let doAutoComplete = settings && settings.html && settings.html.autoClosingTags;
			if (doAutoComplete) {
				options.hideAutoCompleteProposals = true;
			}
			return htmlLanguageService.doComplete(document, position, htmlDocuments.get(document), options);
		},
		doHover(document: TextDocument, position: Position) {
			return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));
		},
		findDocumentHighlight(document: TextDocument, position: Position) {
			return htmlLanguageService.findDocumentHighlights(document, position, htmlDocuments.get(document));
		},
		findDocumentLinks(document: TextDocument, documentContext: DocumentContext) {
			return htmlLanguageService.findDocumentLinks(document, documentContext);
		},
		findDocumentSymbols(document: TextDocument) {
			return htmlLanguageService.findDocumentSymbols(document, htmlDocuments.get(document));
		},
		format(document: TextDocument, range: Range, formatParams: FormattingOptions, settings: Settings = globalSettings) {
			let formatSettings: HTMLFormatConfiguration = settings && settings.html && settings.html.format;
			if (formatSettings) {
				formatSettings = merge(formatSettings, {});
			} else {
				formatSettings = {};
			}
			if (formatSettings.contentUnformatted) {
				formatSettings.contentUnformatted = formatSettings.contentUnformatted + ',script';
			} else {
				formatSettings.contentUnformatted = 'script';
			}
			formatSettings = merge(formatParams, formatSettings);
			return htmlLanguageService.format(document, range, formatSettings);
		},
		doAutoClose(document: TextDocument, position: Position) {
			let offset = document.offsetAt(position);
			let text = document.getText();
			if (offset > 0 && text.charAt(offset - 1).match(/[>\/]/g)) {
				return htmlLanguageService.doTagComplete(document, position, htmlDocuments.get(document));
			}
		},
		onDocumentRemoved(document: TextDocument) {
			htmlDocuments.onDocumentRemoved(document);
		},
		dispose() {
			htmlDocuments.dispose();
		}
	};
}
Example #3
0
export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageMode {
	let settings: any = {};
	let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
	return {
		getId() {
			return 'html';
		},
		configure(options: any) {
			settings = options && options.html;
		},
		doComplete(document: TextDocument, position: Position) {
			let options = settings && settings.suggest;
			return htmlLanguageService.doComplete(document, position, htmlDocuments.get(document), options);
		},
		doHover(document: TextDocument, position: Position) {
			return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));
		},
		findDocumentHighlight(document: TextDocument, position: Position) {
			return htmlLanguageService.findDocumentHighlights(document, position, htmlDocuments.get(document));
		},
		findDocumentLinks(document: TextDocument, documentContext: DocumentContext) {
			return htmlLanguageService.findDocumentLinks(document, documentContext);
		},
		format(document: TextDocument, range: Range, formatParams: FormattingOptions) {
			let formatSettings = settings && settings.format;
			if (!formatSettings) {
				formatSettings = formatParams;
			} else {
				formatSettings = merge(formatParams, merge(formatSettings, {}));
			}
			return htmlLanguageService.format(document, range, formatSettings);
		},
		onDocumentRemoved(document: TextDocument) {
			htmlDocuments.onDocumentRemoved(document);
		},
		dispose() {
			htmlDocuments.dispose();
		}
	};
};
Example #4
0
	let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
Example #5
0
export function getHTMLMode(htmlLanguageService: HTMLLanguageService, workspace: Workspace): LanguageMode {
	let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
	return {
		getId() {
			return 'html';
		},
		doComplete(document: TextDocument, position: Position, settings = workspace.settings) {
			let options = settings && settings.html && settings.html.suggest;
			let doAutoComplete = settings && settings.html && settings.html.autoClosingTags;
			if (doAutoComplete) {
				options.hideAutoCompleteProposals = true;
			}
			let pathCompletionProposals: CompletionItem[] = [];
			let participants = [getPathCompletionParticipant(document, workspace.folders, pathCompletionProposals)];
			htmlLanguageService.setCompletionParticipants(participants);

			const htmlDocument = htmlDocuments.get(document);
			let completionList = htmlLanguageService.doComplete(document, position, htmlDocument, options);
			completionList.items.push(...pathCompletionProposals);
			return completionList;
		},
		doHover(document: TextDocument, position: Position) {
			return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));
		},
		findDocumentHighlight(document: TextDocument, position: Position) {
			return htmlLanguageService.findDocumentHighlights(document, position, htmlDocuments.get(document));
		},
		findDocumentLinks(document: TextDocument, documentContext: DocumentContext) {
			return htmlLanguageService.findDocumentLinks(document, documentContext);
		},
		findDocumentSymbols(document: TextDocument) {
			return htmlLanguageService.findDocumentSymbols(document, htmlDocuments.get(document));
		},
		format(document: TextDocument, range: Range, formatParams: FormattingOptions, settings = workspace.settings) {
			let formatSettings: HTMLFormatConfiguration = settings && settings.html && settings.html.format;
			if (formatSettings) {
				formatSettings = merge(formatSettings, {});
			} else {
				formatSettings = {};
			}
			if (formatSettings.contentUnformatted) {
				formatSettings.contentUnformatted = formatSettings.contentUnformatted + ',script';
			} else {
				formatSettings.contentUnformatted = 'script';
			}
			formatSettings = merge(formatParams, formatSettings);
			return htmlLanguageService.format(document, range, formatSettings);
		},
		getFoldingRanges(document: TextDocument, range: Range): FoldingRange[] {
			let ranges = htmlLanguageService.getFoldingRanges(document);
			return ranges.filter(r => r.startLine >= range.start.line && r.endLine < range.end.line);
		},
		doAutoClose(document: TextDocument, position: Position) {
			let offset = document.offsetAt(position);
			let text = document.getText();
			if (offset > 0 && text.charAt(offset - 1).match(/[>\/]/g)) {
				return htmlLanguageService.doTagComplete(document, position, htmlDocuments.get(document));
			}
			return null;
		},
		onDocumentRemoved(document: TextDocument) {
			htmlDocuments.onDocumentRemoved(document);
		},
		dispose() {
			htmlDocuments.dispose();
		}
	};
}
Example #6
0
export function getDocumentRegions(languageService: LanguageService, document: TextDocument): HTMLDocumentRegions {
	let regions: EmbeddedRegion[] = [];
	let scanner = languageService.createScanner(document.getText());
	let lastTagName: string = '';
	let lastAttributeName: string | null = null;
	let languageIdFromType: string | undefined = undefined;
	let importedScripts: string[] = [];

	let token = scanner.scan();
	while (token !== TokenType.EOS) {
		switch (token) {
			case TokenType.StartTag:
				lastTagName = scanner.getTokenText();
				lastAttributeName = null;
				languageIdFromType = 'javascript';
				break;
			case TokenType.Styles:
				regions.push({ languageId: 'css', start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
				break;
			case TokenType.Script:
				regions.push({ languageId: languageIdFromType, start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
				break;
			case TokenType.AttributeName:
				lastAttributeName = scanner.getTokenText();
				break;
			case TokenType.AttributeValue:
				if (lastAttributeName === 'src' && lastTagName.toLowerCase() === 'script') {
					let value = scanner.getTokenText();
					if (value[0] === '\'' || value[0] === '"') {
						value = value.substr(1, value.length - 1);
					}
					importedScripts.push(value);
				} else if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') {
					if (/["'](module|(text|application)\/(java|ecma)script)["']/.test(scanner.getTokenText())) {
						languageIdFromType = 'javascript';
					} else {
						languageIdFromType = void 0;
					}
				} else {
					let attributeLanguageId = getAttributeLanguage(lastAttributeName!);
					if (attributeLanguageId) {
						let start = scanner.getTokenOffset();
						let end = scanner.getTokenEnd();
						let firstChar = document.getText()[start];
						if (firstChar === '\'' || firstChar === '"') {
							start++;
							end--;
						}
						regions.push({ languageId: attributeLanguageId, start, end, attributeValue: true });
					}
				}
				lastAttributeName = null;
				break;
		}
		token = scanner.scan();
	}
	return {
		getLanguageRanges: (range: Range) => getLanguageRanges(document, regions, range),
		getEmbeddedDocument: (languageId: string, ignoreAttributeValues: boolean) => getEmbeddedDocument(document, regions, languageId, ignoreAttributeValues),
		getLanguageAtPosition: (position: Position) => getLanguageAtPosition(document, regions, position),
		getLanguagesInDocument: () => getLanguagesInDocument(document, regions),
		getImportedScripts: () => importedScripts
	};
}
export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageMode {
	let globalSettings: Settings = {};
	let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
	let completionParticipants = [];
	return {
		getId() {
			return 'html';
		},
		configure(options: any) {
			globalSettings = options;
		},
		doComplete(document: TextDocument, position: Position, settings: Settings = globalSettings) {
			let options = settings && settings.html && settings.html.suggest;
			let doAutoComplete = settings && settings.html && settings.html.autoClosingTags;
			if (doAutoComplete) {
				options.hideAutoCompleteProposals = true;
			}

			const htmlDocument = htmlDocuments.get(document);
			const offset = document.offsetAt(position);
			const node = htmlDocument.findNodeBefore(offset);
			const scanner = htmlLanguageService.createScanner(document.getText(), node.start);
			let token = scanner.scan();
			while (token !== TokenType.EOS && scanner.getTokenOffset() <= offset) {
				if (token === TokenType.Content && offset <= scanner.getTokenEnd()) {
					completionParticipants.forEach(participant => { if (participant.onHtmlContent) { participant.onHtmlContent(); } });
					break;
				}
				token = scanner.scan();
			}
			return htmlLanguageService.doComplete(document, position, htmlDocument, options);
		},
		setCompletionParticipants(registeredCompletionParticipants: any[]) {
			completionParticipants = registeredCompletionParticipants;
		},
		doHover(document: TextDocument, position: Position) {
			return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));
		},
		findDocumentHighlight(document: TextDocument, position: Position) {
			return htmlLanguageService.findDocumentHighlights(document, position, htmlDocuments.get(document));
		},
		findDocumentLinks(document: TextDocument, documentContext: DocumentContext) {
			return htmlLanguageService.findDocumentLinks(document, documentContext);
		},
		findDocumentSymbols(document: TextDocument) {
			return htmlLanguageService.findDocumentSymbols(document, htmlDocuments.get(document));
		},
		format(document: TextDocument, range: Range, formatParams: FormattingOptions, settings: Settings = globalSettings) {
			let formatSettings: HTMLFormatConfiguration = settings && settings.html && settings.html.format;
			if (formatSettings) {
				formatSettings = merge(formatSettings, {});
			} else {
				formatSettings = {};
			}
			if (formatSettings.contentUnformatted) {
				formatSettings.contentUnformatted = formatSettings.contentUnformatted + ',script';
			} else {
				formatSettings.contentUnformatted = 'script';
			}
			formatSettings = merge(formatParams, formatSettings);
			return htmlLanguageService.format(document, range, formatSettings);
		},
		doAutoClose(document: TextDocument, position: Position) {
			let offset = document.offsetAt(position);
			let text = document.getText();
			if (offset > 0 && text.charAt(offset - 1).match(/[>\/]/g)) {
				return htmlLanguageService.doTagComplete(document, position, htmlDocuments.get(document));
			}
			return null;
		},
		onDocumentRemoved(document: TextDocument) {
			htmlDocuments.onDocumentRemoved(document);
		},
		dispose() {
			htmlDocuments.dispose();
		}
	};
}
Example #8
0
export function getHTMLFoldingRegions(htmlLanguageService: HTMLLanguageService, document: TextDocument, range: Range): FoldingRange[] {
	const scanner = htmlLanguageService.createScanner(document.getText());
	let token = scanner.scan();
	let ranges: FoldingRange[] = [];
	let stack: { startLine: number, tagName: string }[] = [];
	let lastTagName = null;
	let prevStart = -1;

	function addRange(range: FoldingRange) {
		ranges.push(range);
		prevStart = range.startLine;
	}

	while (token !== TokenType.EOS) {
		switch (token) {
			case TokenType.StartTag: {
				let tagName = scanner.getTokenText();
				let startLine = document.positionAt(scanner.getTokenOffset()).line;
				stack.push({ startLine, tagName });
				lastTagName = tagName;
				break;
			}
			case TokenType.EndTag: {
				lastTagName = scanner.getTokenText();
				break;
			}
			case TokenType.StartTagClose:
				if (!lastTagName || !isEmptyElement(lastTagName)) {
					break;
				}
			// fallthrough
			case TokenType.EndTagClose:
			case TokenType.StartTagSelfClose: {
				let i = stack.length - 1;
				while (i >= 0 && stack[i].tagName !== lastTagName) {
					i--;
				}
				if (i >= 0) {
					let stackElement = stack[i];
					stack.length = i;
					let line = document.positionAt(scanner.getTokenOffset()).line;
					let startLine = stackElement.startLine;
					let endLine = line - 1;
					if (endLine > startLine && prevStart !== startLine) {
						addRange({ startLine, endLine });
					}
				}
				break;
			}
			case TokenType.Comment: {
				let startLine = document.positionAt(scanner.getTokenOffset()).line;
				let text = scanner.getTokenText();
				let m = text.match(/^\s*#(region\b)|(endregion\b)/);
				if (m) {
					if (m[1]) { // start pattern match
						stack.push({ startLine, tagName: '' }); // empty tagName marks region
					} else {
						let i = stack.length - 1;
						while (i >= 0 && stack[i].tagName.length) {
							i--;
						}
						if (i >= 0) {
							let stackElement = stack[i];
							stack.length = i;
							let endLine = startLine;
							startLine = stackElement.startLine;
							if (endLine > startLine && prevStart !== startLine) {
								addRange({ startLine, endLine, type: FoldingRangeType.Region });
							}
						}
					}
				} else {
					let endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
					if (startLine < endLine) {
						addRange({ startLine, endLine, type: FoldingRangeType.Comment });
					}
				}
				break;
			}
		}
		token = scanner.scan();
	}
	return ranges;
}