Skip to content

Commit b829292

Browse files
authored
Merge pull request microsoft#259633 from mjbvz/zestful-fowl
Clean up markdownDocumentRenderer api
2 parents c3f866e + a20495b commit b829292

File tree

6 files changed

+64
-31
lines changed

6 files changed

+64
-31
lines changed

src/vs/base/browser/markdownRenderer.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,6 @@ export const allowedMarkdownHtmlAttributes = [
446446
'autoplay',
447447
'alt',
448448
'checked',
449-
'class',
450449
'colspan',
451450
'controls',
452451
'disabled',

src/vs/workbench/contrib/extensions/browser/extensionEditor.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,9 @@ export class ExtensionEditor extends EditorPane {
750750
return '';
751751
}
752752

753-
const content = await renderMarkdownDocument(contents, this.extensionService, this.languageService, { shouldSanitize: extension.type !== ExtensionType.System }, token);
753+
const content = await renderMarkdownDocument(contents, this.extensionService, this.languageService, {
754+
sanitizerConfig: extension.type === ExtensionType.System ? 'skipSanitization' : {}
755+
}, token);
754756
if (token?.isCancellationRequested) {
755757
return '';
756758
}

src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { basicMarkupHtmlTags, sanitizeHtml } from '../../../../base/browser/domSanitize.js';
7-
import { allowedMarkdownHtmlAttributes } from '../../../../base/browser/markdownRenderer.js';
6+
import { sanitizeHtml } from '../../../../base/browser/domSanitize.js';
7+
import { allowedMarkdownHtmlAttributes, allowedMarkdownHtmlTags } from '../../../../base/browser/markdownRenderer.js';
8+
import { raceCancellationError } from '../../../../base/common/async.js';
89
import { CancellationToken } from '../../../../base/common/cancellation.js';
910
import * as marked from '../../../../base/common/marked/marked.js';
1011
import { Schemas } from '../../../../base/common/network.js';
@@ -156,48 +157,57 @@ pre code {
156157
}
157158
`;
158159

159-
const allowedProtocols = [
160+
const defaultAllowedProtocols = Object.freeze([
160161
Schemas.http,
161162
Schemas.https,
162163
Schemas.command,
163-
];
164+
]);
164165

165-
function sanitize(documentContent: string, allowAllProtocols = false): TrustedHTML {
166-
// TODO: Move most of these options to the callers
166+
function sanitize(documentContent: string, sanitizerConfig: MarkdownDocumentSanitizerConfig | undefined): TrustedHTML {
167167
return sanitizeHtml(documentContent, {
168168
allowedLinkProtocols: {
169-
override: allowAllProtocols ? '*' : allowedProtocols,
169+
override: sanitizerConfig?.allowedProtocols?.override ?? defaultAllowedProtocols,
170170
},
171171
allowedTags: {
172-
override: [
173-
...basicMarkupHtmlTags,
174-
'input',
175-
'select',
176-
'checkbox',
177-
'checklist',
178-
],
172+
override: allowedMarkdownHtmlTags,
173+
augment: sanitizerConfig?.allowedTags?.augment
179174
},
180175
allowedAttributes: {
181176
override: [
182177
...allowedMarkdownHtmlAttributes,
183-
'data-command', 'name', 'id', 'role', 'tabindex',
184-
'x-dispatch',
185-
'required', 'checked', 'placeholder', 'when-checked', 'checked-on',
178+
'name',
179+
'id',
180+
'role',
181+
'tabindex',
182+
'placeholder',
186183
],
184+
augment: sanitizerConfig?.allowedAttributes?.augment ?? [],
187185
}
188186
});
189187
}
190188

189+
interface MarkdownDocumentSanitizerConfig {
190+
readonly allowedProtocols?: {
191+
readonly override: readonly string[] | '*';
192+
};
193+
readonly allowedTags?: {
194+
readonly augment: readonly string[];
195+
};
196+
readonly allowedAttributes?: {
197+
readonly augment: readonly string[];
198+
};
199+
}
200+
191201
interface IRenderMarkdownDocumentOptions {
192-
readonly shouldSanitize?: boolean;
193-
readonly allowUnknownProtocols?: boolean;
194-
readonly markedExtensions?: marked.MarkedExtension[];
202+
readonly sanitizerConfig?: 'skipSanitization' | MarkdownDocumentSanitizerConfig;
203+
readonly markedExtensions?: readonly marked.MarkedExtension[];
195204
}
196205

197206
/**
198-
* Renders a string of markdown as a document.
207+
* Renders a string of markdown for use in an external document context.
199208
*
200-
* Uses VS Code's syntax highlighting code blocks.
209+
* Uses VS Code's syntax highlighting code blocks. Also does not attach all the hooks and customization that normal
210+
* markdown renderer.
201211
*/
202212
export async function renderMarkdownDocument(
203213
text: string,
@@ -227,11 +237,11 @@ export async function renderMarkdownDocument(
227237
...(options?.markedExtensions ?? []),
228238
);
229239

230-
const raw = await m.parse(text, { async: true });
231-
if (options?.shouldSanitize ?? true) {
232-
return sanitize(raw, options?.allowUnknownProtocols ?? false) as any as string;
233-
} else {
240+
const raw = await raceCancellationError(m.parse(text, { async: true }), token ?? CancellationToken.None);
241+
if (options?.sanitizerConfig === 'skipSanitization') {
234242
return raw;
243+
} else {
244+
return sanitize(raw, options?.sanitizerConfig) as any as string;
235245
}
236246
}
237247

src/vs/workbench/contrib/mcp/browser/mcpServerEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ export class McpServerEditor extends EditorPane {
529529
return '';
530530
}
531531

532-
const content = await renderMarkdownDocument(contents, this.extensionService, this.languageService, { shouldSanitize: true }, token);
532+
const content = await renderMarkdownDocument(contents, this.extensionService, this.languageService, {}, token);
533533
if (token?.isCancellationRequested) {
534534
return '';
535535
}

src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ export class ReleaseNotesManager {
264264
const nonce = generateUuid();
265265

266266
const content = await renderMarkdownDocument(fileContent.text, this._extensionService, this._languageService, {
267-
shouldSanitize: false,
267+
sanitizerConfig: 'skipSanitization',
268268
markedExtensions: [{
269269
renderer: {
270270
html: this._simpleSettingRenderer.getHtmlRenderer(),

src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,29 @@ export class GettingStartedDetailsRenderer {
236236
private async readAndCacheStepMarkdown(path: URI, base: URI): Promise<string> {
237237
if (!this.mdCache.has(path)) {
238238
const contents = await this.readContentsOfPath(path);
239-
const markdownContents = await renderMarkdownDocument(transformUris(contents, base), this.extensionService, this.languageService, { allowUnknownProtocols: true });
239+
const markdownContents = await renderMarkdownDocument(transformUris(contents, base), this.extensionService, this.languageService, {
240+
sanitizerConfig: {
241+
allowedProtocols: {
242+
override: '*'
243+
},
244+
allowedTags: {
245+
augment: [
246+
'select',
247+
'checkbox',
248+
'checklist',
249+
]
250+
},
251+
allowedAttributes: {
252+
augment: [
253+
'x-dispatch',
254+
'data-command',
255+
'when-checked',
256+
'checked-on',
257+
'checked',
258+
]
259+
},
260+
}
261+
});
240262
this.mdCache.set(path, markdownContents);
241263
}
242264
return assertReturnsDefined(this.mdCache.get(path));

0 commit comments

Comments
 (0)