|
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information.
|
4 | 4 | *--------------------------------------------------------------------------------------------*/
|
5 | 5 |
|
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'; |
8 | 9 | import { CancellationToken } from '../../../../base/common/cancellation.js';
|
9 | 10 | import * as marked from '../../../../base/common/marked/marked.js';
|
10 | 11 | import { Schemas } from '../../../../base/common/network.js';
|
@@ -156,48 +157,57 @@ pre code {
|
156 | 157 | }
|
157 | 158 | `;
|
158 | 159 |
|
159 |
| -const allowedProtocols = [ |
| 160 | +const defaultAllowedProtocols = Object.freeze([ |
160 | 161 | Schemas.http,
|
161 | 162 | Schemas.https,
|
162 | 163 | Schemas.command,
|
163 |
| -]; |
| 164 | +]); |
164 | 165 |
|
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 { |
167 | 167 | return sanitizeHtml(documentContent, {
|
168 | 168 | allowedLinkProtocols: {
|
169 |
| - override: allowAllProtocols ? '*' : allowedProtocols, |
| 169 | + override: sanitizerConfig?.allowedProtocols?.override ?? defaultAllowedProtocols, |
170 | 170 | },
|
171 | 171 | allowedTags: {
|
172 |
| - override: [ |
173 |
| - ...basicMarkupHtmlTags, |
174 |
| - 'input', |
175 |
| - 'select', |
176 |
| - 'checkbox', |
177 |
| - 'checklist', |
178 |
| - ], |
| 172 | + override: allowedMarkdownHtmlTags, |
| 173 | + augment: sanitizerConfig?.allowedTags?.augment |
179 | 174 | },
|
180 | 175 | allowedAttributes: {
|
181 | 176 | override: [
|
182 | 177 | ...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', |
186 | 183 | ],
|
| 184 | + augment: sanitizerConfig?.allowedAttributes?.augment ?? [], |
187 | 185 | }
|
188 | 186 | });
|
189 | 187 | }
|
190 | 188 |
|
| 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 | + |
191 | 201 | 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[]; |
195 | 204 | }
|
196 | 205 |
|
197 | 206 | /**
|
198 |
| - * Renders a string of markdown as a document. |
| 207 | + * Renders a string of markdown for use in an external document context. |
199 | 208 | *
|
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. |
201 | 211 | */
|
202 | 212 | export async function renderMarkdownDocument(
|
203 | 213 | text: string,
|
@@ -227,11 +237,11 @@ export async function renderMarkdownDocument(
|
227 | 237 | ...(options?.markedExtensions ?? []),
|
228 | 238 | );
|
229 | 239 |
|
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') { |
234 | 242 | return raw;
|
| 243 | + } else { |
| 244 | + return sanitize(raw, options?.sanitizerConfig) as any as string; |
235 | 245 | }
|
236 | 246 | }
|
237 | 247 |
|
|
0 commit comments