diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 5f8c24cd63a..cbf9f30c480 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -849,7 +849,10 @@ "./media/highlight.css" ], "markdown.previewScripts": [ - "./media/index.js" + { + "path": "./media/index.js", + "type": "module" + } ], "customEditors": [ { diff --git a/extensions/markdown-language-features/schemas/package.schema.json b/extensions/markdown-language-features/schemas/package.schema.json index 8dea48f757f..4962543264b 100644 --- a/extensions/markdown-language-features/schemas/package.schema.json +++ b/extensions/markdown-language-features/schemas/package.schema.json @@ -17,8 +17,31 @@ "type": "array", "description": "Contributed scripts that are executed in the Markdown preview", "items": { - "type": "string", - "description": "Extension relative path to a JavaScript file" + "oneOf": [ + { + "type": "string", + "description": "Extension relative path to a JavaScript file" + }, + { + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string", + "description": "Extension relative path to a JavaScript file" + }, + "type": { + "type": "string", + "enum": [ + "module" + ], + "description": "The script type to use when loading the contributed script" + } + } + } + ] } }, "markdown.markdownItPlugins": { diff --git a/extensions/markdown-language-features/src/markdownExtensions.ts b/extensions/markdown-language-features/src/markdownExtensions.ts index 568a0f0b638..0d4b34330c9 100644 --- a/extensions/markdown-language-features/src/markdownExtensions.ts +++ b/extensions/markdown-language-features/src/markdownExtensions.ts @@ -23,8 +23,13 @@ function* resolveExtensionResources(extension: vscode.Extension, resourcePa } } +export interface MarkdownPreviewScript { + readonly resource: vscode.Uri; + readonly type?: 'module'; +} + export interface MarkdownContributions { - readonly previewScripts: readonly vscode.Uri[]; + readonly previewScripts: readonly MarkdownPreviewScript[]; readonly previewStyles: readonly vscode.Uri[]; readonly previewResourceRoots: readonly vscode.Uri[]; readonly markdownItPlugins: ReadonlyMap any>>; @@ -51,8 +56,12 @@ export namespace MarkdownContributions { return a.toString() === b.toString(); } + function previewScriptEqual(a: MarkdownPreviewScript, b: MarkdownPreviewScript): boolean { + return uriEqual(a.resource, b.resource) && a.type === b.type; + } + export function equal(a: MarkdownContributions, b: MarkdownContributions): boolean { - return arrays.equals(a.previewScripts, b.previewScripts, uriEqual) + return arrays.equals(a.previewScripts, b.previewScripts, previewScriptEqual) && arrays.equals(a.previewStyles, b.previewStyles, uriEqual) && arrays.equals(a.previewResourceRoots, b.previewResourceRoots, uriEqual) && arrays.equals(Array.from(a.markdownItPlugins.keys()), Array.from(b.markdownItPlugins.keys())); @@ -96,8 +105,8 @@ export namespace MarkdownContributions { function getContributedScripts( contributes: any, extension: vscode.Extension - ) { - return resolveExtensionResources(extension, contributes['markdown.previewScripts']); + ): Iterable { + return resolvePreviewScripts(extension, contributes['markdown.previewScripts']); } function getContributedStyles( @@ -106,6 +115,48 @@ export namespace MarkdownContributions { ) { return resolveExtensionResources(extension, contributes['markdown.previewStyles']); } + + function* resolvePreviewScripts(extension: vscode.Extension, scripts: unknown): Iterable { + if (!Array.isArray(scripts)) { + return; + } + + for (const script of scripts) { + const contribution = getPreviewScriptContribution(script); + if (!contribution) { + continue; + } + + try { + yield { + resource: resolveExtensionResource(extension, contribution.path), + type: contribution.type, + }; + } catch { + // noop + } + } + } + + function getPreviewScriptContribution(script: unknown): { path: string; type?: MarkdownPreviewScript['type'] } | undefined { + if (typeof script === 'string') { + return { path: script }; + } + + if (!script || typeof script !== 'object') { + return undefined; + } + + const contribution = script as Record; + if (typeof contribution.path !== 'string') { + return undefined; + } + + return { + path: contribution.path, + type: contribution.type === 'module' ? contribution.type : undefined, + }; + } } export interface MarkdownContributionProvider { diff --git a/extensions/markdown-language-features/src/preview/documentRenderer.ts b/extensions/markdown-language-features/src/preview/documentRenderer.ts index 5e5aeb780fa..85407fb81bf 100644 --- a/extensions/markdown-language-features/src/preview/documentRenderer.ts +++ b/extensions/markdown-language-features/src/preview/documentRenderer.ts @@ -244,9 +244,10 @@ export class MdDocumentRenderer { #getScripts(resourceProvider: WebviewResourceProvider, nonce: string): string { const out: string[] = []; - for (const resource of this.#contributionProvider.contributions.previewScripts) { - out.push(``); }