|
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