src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts/renderMarkdownHovers
export function renderMarkdownHovers(
	context: IEditorHoverRenderContext,
	hoverParts: MarkdownHover[],
	editor: ICodeEditor,
	languageService: ILanguageService,
	openerService: IOpenerService,
): IDisposable {

	// Sort hover parts to keep them stable since they might come in async, out-of-order
	hoverParts.sort((a, b) => a.ordinal - b.ordinal);

	const disposables = new DisposableStore();
	for (const hoverPart of hoverParts) {
		for (const contents of hoverPart.contents) {
			if (isEmptyMarkdownString(contents)) {
				continue;
			}
			const markdownHoverElement = $('div.hover-row.markdown-hover');
			const hoverContentsElement = dom.append(markdownHoverElement, $('div.hover-contents'));
			const renderer = disposables.add(new MarkdownRenderer({ editor }, languageService, openerService));
			disposables.add(renderer.onDidRenderAsync(() => {
				hoverContentsElement.className = 'hover-contents code-hover-contents';
				context.onContentsChanged();
			}));
			const renderedContents = disposables.add(renderer.render(contents));
			hoverContentsElement.appendChild(renderedContents.element);
			context.fragment.appendChild(markdownHoverElement);
		}
	}
	return disposables;
}