mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-08 01:28:26 -05:00
Merge from vscode merge-base (#22780)
* Revert "Revert "Merge from vscode merge-base (#22769)" (#22779)"
This reverts commit 47a1745180.
* Fix notebook download task
* Remove done call from extensions-ci
This commit is contained in:
@@ -9,11 +9,9 @@ import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { createElement, FormattedTextRenderOptions } from 'vs/base/browser/formattedTextRenderer';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { raceCancellation } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IMarkdownString, parseHrefAndDimensions, removeMarkdownEscapes } from 'vs/base/common/htmlContent';
|
||||
import { IMarkdownString, escapeDoubleQuotes, parseHrefAndDimensions, removeMarkdownEscapes } from 'vs/base/common/htmlContent';
|
||||
import { markdownEscapeEscapedIcons } from 'vs/base/common/iconLabels';
|
||||
import { defaultGenerator } from 'vs/base/common/idGenerator';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
@@ -44,8 +42,6 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
const disposables = new DisposableStore();
|
||||
let isDisposed = false;
|
||||
|
||||
const cts = disposables.add(new CancellationTokenSource());
|
||||
|
||||
const element = createElement(options);
|
||||
|
||||
const _uriMassage = function (part: string): string {
|
||||
@@ -96,11 +92,6 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
return uri.toString();
|
||||
};
|
||||
|
||||
// signal to code-block render that the
|
||||
// element has been created
|
||||
let signalInnerHTML: () => void;
|
||||
const withInnerHTML = new Promise<void>(c => signalInnerHTML = c);
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
renderer.image = (href: string, title: string, text: string) => {
|
||||
@@ -108,13 +99,13 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
let attributes: string[] = [];
|
||||
if (href) {
|
||||
({ href, dimensions } = parseHrefAndDimensions(href));
|
||||
attributes.push(`src="${href}"`);
|
||||
attributes.push(`src="${escapeDoubleQuotes(href)}"`);
|
||||
}
|
||||
if (text) {
|
||||
attributes.push(`alt="${text}"`);
|
||||
attributes.push(`alt="${escapeDoubleQuotes(text)}"`);
|
||||
}
|
||||
if (title) {
|
||||
attributes.push(`title="${title}"`);
|
||||
attributes.push(`title="${escapeDoubleQuotes(title)}"`);
|
||||
}
|
||||
if (dimensions.length) {
|
||||
attributes = attributes.concat(dimensions);
|
||||
@@ -130,53 +121,30 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
if (href === text) { // raw link case
|
||||
text = removeMarkdownEscapes(text);
|
||||
}
|
||||
href = _href(href, false);
|
||||
if (markdown.baseUri) {
|
||||
href = resolveWithBaseUri(URI.from(markdown.baseUri), href);
|
||||
}
|
||||
title = typeof title === 'string' ? removeMarkdownEscapes(title) : '';
|
||||
href = removeMarkdownEscapes(href);
|
||||
if (
|
||||
!href
|
||||
|| /^data:|javascript:/i.test(href)
|
||||
|| (/^command:/i.test(href) && !markdown.isTrusted)
|
||||
|| /^command:(\/\/\/)?_workbench\.downloadResource/i.test(href)
|
||||
) {
|
||||
// drop the link
|
||||
return text;
|
||||
|
||||
} else {
|
||||
// HTML Encode href
|
||||
href = href.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
return `<a data-href="${href}" title="${title || href}">${text}</a>`;
|
||||
}
|
||||
title = typeof title === 'string' ? escapeDoubleQuotes(removeMarkdownEscapes(title)) : '';
|
||||
href = removeMarkdownEscapes(href);
|
||||
|
||||
// HTML Encode href
|
||||
href = href.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
return `<a href="${href}" title="${title || href}">${text}</a>`;
|
||||
};
|
||||
renderer.paragraph = (text): string => {
|
||||
return `<p>${text}</p>`;
|
||||
};
|
||||
|
||||
// Will collect [id, renderedElement] tuples
|
||||
const codeBlocks: Promise<[string, HTMLElement]>[] = [];
|
||||
|
||||
if (options.codeBlockRenderer) {
|
||||
renderer.code = (code, lang) => {
|
||||
const value = options.codeBlockRenderer!(lang ?? '', code);
|
||||
// when code-block rendering is async we return sync
|
||||
// but update the node with the real result later.
|
||||
const id = defaultGenerator.nextId();
|
||||
raceCancellation(Promise.all([value, withInnerHTML]), cts.token).then(values => {
|
||||
if (!isDisposed && values) {
|
||||
const span = element.querySelector<HTMLDivElement>(`div[data-code="${id}"]`);
|
||||
if (span) {
|
||||
DOM.reset(span, values[0]);
|
||||
}
|
||||
options.asyncRenderCallback?.();
|
||||
}
|
||||
}).catch(() => {
|
||||
// ignore
|
||||
});
|
||||
|
||||
const value = options.codeBlockRenderer!(lang ?? '', code);
|
||||
codeBlocks.push(value.then(element => [id, element]));
|
||||
return `<div class="code" data-code="${id}">${escape(code)}</div>`;
|
||||
};
|
||||
}
|
||||
@@ -268,10 +236,45 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
}
|
||||
});
|
||||
|
||||
markdownHtmlDoc.body.querySelectorAll('a')
|
||||
.forEach(a => {
|
||||
const href = a.getAttribute('href'); // Get the raw 'href' attribute value as text, not the resolved 'href'
|
||||
a.setAttribute('href', ''); // Clear out href. We use the `data-href` for handling clicks instead
|
||||
if (
|
||||
!href
|
||||
|| /^data:|javascript:/i.test(href)
|
||||
|| (/^command:/i.test(href) && !markdown.isTrusted)
|
||||
|| /^command:(\/\/\/)?_workbench\.downloadResource/i.test(href)
|
||||
) {
|
||||
// drop the link
|
||||
a.replaceWith(...a.childNodes);
|
||||
} else {
|
||||
let resolvedHref = _href(href, false);
|
||||
if (markdown.baseUri) {
|
||||
resolvedHref = resolveWithBaseUri(URI.from(markdown.baseUri), href);
|
||||
}
|
||||
a.dataset.href = resolvedHref;
|
||||
}
|
||||
});
|
||||
|
||||
element.innerHTML = sanitizeRenderedMarkdown(markdown, markdownHtmlDoc.body.innerHTML) as unknown as string;
|
||||
|
||||
// signal that async code blocks can be now be inserted
|
||||
signalInnerHTML!();
|
||||
if (codeBlocks.length > 0) {
|
||||
Promise.all(codeBlocks).then((tuples) => {
|
||||
if (isDisposed) {
|
||||
return;
|
||||
}
|
||||
const renderedElements = new Map(tuples);
|
||||
const placeholderElements = element.querySelectorAll<HTMLDivElement>(`div[data-code]`);
|
||||
for (const placeholderElement of placeholderElements) {
|
||||
const renderedElement = renderedElements.get(placeholderElement.dataset['code'] ?? '');
|
||||
if (renderedElement) {
|
||||
DOM.reset(placeholderElement, renderedElement);
|
||||
}
|
||||
}
|
||||
options.asyncRenderCallback?.();
|
||||
});
|
||||
}
|
||||
|
||||
// signal size changes for image tags
|
||||
if (options.asyncRenderCallback) {
|
||||
@@ -287,7 +290,6 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
element,
|
||||
dispose: () => {
|
||||
isDisposed = true;
|
||||
cts.cancel();
|
||||
disposables.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user