mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
Merge pull request #75741 from microsoft/dev/mjbvz/webviewResourceRoot
Add vscode.env.webviewResourceRoot API
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -4,7 +4,8 @@
|
||||
"description": "%description%",
|
||||
"version": "1.0.0",
|
||||
"icon": "icon.png",
|
||||
"publisher": "vscode",
|
||||
"publisher": "vscode",
|
||||
"enableProposedApi": true,
|
||||
"license": "MIT",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"engines": {
|
||||
|
||||
@@ -19,7 +19,7 @@ const settings = getSettings();
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
// Set VS Code state
|
||||
let state = getData('data-state');
|
||||
let state = getData<{ line: number }>('data-state');
|
||||
vscode.setState(state);
|
||||
|
||||
const messaging = createPosterForVsCode(vscode);
|
||||
@@ -131,8 +131,8 @@ document.addEventListener('click', event => {
|
||||
if (node.getAttribute('href').startsWith('#')) {
|
||||
break;
|
||||
}
|
||||
if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:')) {
|
||||
const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').split('#');
|
||||
if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:') || node.href.startsWith(settings.webviewResourceRoot)) {
|
||||
const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)).split('#');
|
||||
messaging.postMessage('clickLink', { path, fragment });
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -157,4 +157,8 @@ if (settings.scrollEditorWithPreview) {
|
||||
}
|
||||
}
|
||||
}, 50));
|
||||
}
|
||||
|
||||
function escapeRegExp(text: string) {
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
}
|
||||
@@ -4,18 +4,19 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export interface PreviewSettings {
|
||||
source: string;
|
||||
line: number;
|
||||
lineCount: number;
|
||||
scrollPreviewWithEditor?: boolean;
|
||||
scrollEditorWithPreview: boolean;
|
||||
disableSecurityWarnings: boolean;
|
||||
doubleClickToSwitchToEditor: boolean;
|
||||
readonly source: string;
|
||||
readonly line: number;
|
||||
readonly lineCount: number;
|
||||
readonly scrollPreviewWithEditor?: boolean;
|
||||
readonly scrollEditorWithPreview: boolean;
|
||||
readonly disableSecurityWarnings: boolean;
|
||||
readonly doubleClickToSwitchToEditor: boolean;
|
||||
readonly webviewResourceRoot: string;
|
||||
}
|
||||
|
||||
let cachedSettings: PreviewSettings | undefined = undefined;
|
||||
|
||||
export function getData(key: string): PreviewSettings {
|
||||
export function getData<T = {}>(key: string): T {
|
||||
const element = document.getElementById('vscode-markdown-preview-data');
|
||||
if (element) {
|
||||
const data = element.getAttribute(key);
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Logger } from '../logger';
|
||||
import { ContentSecurityPolicyArbiter, MarkdownPreviewSecurityLevel } from '../security';
|
||||
import { MarkdownPreviewConfigurationManager, MarkdownPreviewConfiguration } from './previewConfig';
|
||||
import { MarkdownContributionProvider } from '../markdownExtensions';
|
||||
import { toResoruceUri } from '../util/resources';
|
||||
|
||||
/**
|
||||
* Strings used inside the markdown preview.
|
||||
@@ -63,7 +64,8 @@ export class MarkdownContentProvider {
|
||||
scrollPreviewWithEditor: config.scrollPreviewWithEditor,
|
||||
scrollEditorWithPreview: config.scrollEditorWithPreview,
|
||||
doubleClickToSwitchToEditor: config.doubleClickToSwitchToEditor,
|
||||
disableSecurityWarnings: this.cspArbiter.shouldDisableSecurityWarnings()
|
||||
disableSecurityWarnings: this.cspArbiter.shouldDisableSecurityWarnings(),
|
||||
webviewResourceRoot: vscode.env.webviewResourceRoot,
|
||||
};
|
||||
|
||||
this.logger.log('provideTextDocumentContent', initialData);
|
||||
@@ -84,7 +86,7 @@ export class MarkdownContentProvider {
|
||||
data-state="${escapeAttribute(JSON.stringify(state || {}))}">
|
||||
<script src="${this.extensionResourcePath('pre.js')}" nonce="${nonce}"></script>
|
||||
${this.getStyles(sourceUri, nonce, config, state)}
|
||||
<base href="${markdownDocument.uri.with({ scheme: 'vscode-resource' }).toString(true)}">
|
||||
<base href="${toResoruceUri(markdownDocument.uri)}">
|
||||
</head>
|
||||
<body class="vscode-body ${config.scrollBeyondLastLine ? 'scrollBeyondLastLine' : ''} ${config.wordWrap ? 'wordWrap' : ''} ${config.markEditorSelection ? 'showEditorSelection' : ''}">
|
||||
${body}
|
||||
@@ -108,8 +110,7 @@ export class MarkdownContentProvider {
|
||||
}
|
||||
|
||||
private extensionResourcePath(mediaFile: string): string {
|
||||
return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile)))
|
||||
.with({ scheme: 'vscode-resource' })
|
||||
return toResoruceUri(vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile))))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@@ -124,23 +125,17 @@ export class MarkdownContentProvider {
|
||||
|
||||
// Assume it must be a local file
|
||||
if (path.isAbsolute(href)) {
|
||||
return vscode.Uri.file(href)
|
||||
.with({ scheme: 'vscode-resource' })
|
||||
.toString();
|
||||
return toResoruceUri(vscode.Uri.file(href)).toString();
|
||||
}
|
||||
|
||||
// Use a workspace relative path if there is a workspace
|
||||
const root = vscode.workspace.getWorkspaceFolder(resource);
|
||||
if (root) {
|
||||
return vscode.Uri.file(path.join(root.uri.fsPath, href))
|
||||
.with({ scheme: 'vscode-resource' })
|
||||
.toString();
|
||||
return toResoruceUri(vscode.Uri.file(path.join(root.uri.fsPath, href))).toString();
|
||||
}
|
||||
|
||||
// Otherwise look relative to the markdown file
|
||||
return vscode.Uri.file(path.join(path.dirname(resource.fsPath), href))
|
||||
.with({ scheme: 'vscode-resource' })
|
||||
.toString();
|
||||
return toResoruceUri(vscode.Uri.file(path.join(path.dirname(resource.fsPath), href))).toString();
|
||||
}
|
||||
|
||||
private computeCustomStyleSheetIncludes(resource: vscode.Uri, config: MarkdownPreviewConfiguration): string {
|
||||
@@ -197,17 +192,17 @@ export class MarkdownContentProvider {
|
||||
private getCspForResource(resource: vscode.Uri, nonce: string): string {
|
||||
switch (this.cspArbiter.getSecurityLevelForResource(resource)) {
|
||||
case MarkdownPreviewSecurityLevel.AllowInsecureContent:
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' vscode-resource: http: https: data:; media-src 'self' vscode-resource: http: https: data:; script-src 'nonce-${nonce}'; style-src 'self' vscode-resource: 'unsafe-inline' http: https: data:; font-src 'self' vscode-resource: http: https: data:;">`;
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${vscode.env.webviewResourceRoot} http: https: data:; media-src 'self' ${vscode.env.webviewResourceRoot} http: https: data:; script-src 'nonce-${nonce}'; style-src 'self' ${vscode.env.webviewResourceRoot} 'unsafe-inline' http: https: data:; font-src 'self' ${vscode.env.webviewResourceRoot} http: https: data:;">`;
|
||||
|
||||
case MarkdownPreviewSecurityLevel.AllowInsecureLocalContent:
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' vscode-resource: https: data: http://localhost:* http://127.0.0.1:*; media-src 'self' vscode-resource: https: data: http://localhost:* http://127.0.0.1:*; script-src 'nonce-${nonce}'; style-src 'self' vscode-resource: 'unsafe-inline' https: data: http://localhost:* http://127.0.0.1:*; font-src 'self' vscode-resource: https: data: http://localhost:* http://127.0.0.1:*;">`;
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${vscode.env.webviewResourceRoot} https: data: http://localhost:* http://127.0.0.1:*; media-src 'self' ${vscode.env.webviewResourceRoot} https: data: http://localhost:* http://127.0.0.1:*; script-src 'nonce-${nonce}'; style-src 'self' ${vscode.env.webviewResourceRoot} 'unsafe-inline' https: data: http://localhost:* http://127.0.0.1:*; font-src 'self' ${vscode.env.webviewResourceRoot} https: data: http://localhost:* http://127.0.0.1:*;">`;
|
||||
|
||||
case MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent:
|
||||
return '';
|
||||
|
||||
case MarkdownPreviewSecurityLevel.Strict:
|
||||
default:
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' vscode-resource: https: data:; media-src 'self' vscode-resource: https: data:; script-src 'nonce-${nonce}'; style-src 'self' vscode-resource: 'unsafe-inline' https: data:; font-src 'self' vscode-resource: https: data:;">`;
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${vscode.env.webviewResourceRoot} https: data:; media-src 'self' ${vscode.env.webviewResourceRoot} https: data:; script-src 'nonce-${nonce}'; style-src 'self' ${vscode.env.webviewResourceRoot} 'unsafe-inline' https: data:; font-src 'self' ${vscode.env.webviewResourceRoot} https: data:;">`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { Disposable } from './util/dispose';
|
||||
import * as arrays from './util/arrays';
|
||||
import { toResoruceUri } from './util/resources';
|
||||
|
||||
const resolveExtensionResource = (extension: vscode.Extension<any>, resourcePath: string): vscode.Uri => {
|
||||
return vscode.Uri.file(path.join(extension.extensionPath, resourcePath))
|
||||
.with({ scheme: 'vscode-resource' });
|
||||
return toResoruceUri(vscode.Uri.file(path.join(extension.extensionPath, resourcePath)));
|
||||
};
|
||||
|
||||
const resolveExtensionResources = (extension: vscode.Extension<any>, resourcePaths: unknown): vscode.Uri[] => {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
const rootUri = vscode.Uri.parse(vscode.env.webviewResourceRoot);
|
||||
|
||||
export function toResoruceUri(uri: vscode.Uri): vscode.Uri {
|
||||
return rootUri.with({
|
||||
path: rootUri.path + uri.path,
|
||||
query: uri.query,
|
||||
fragment: uri.fragment,
|
||||
});
|
||||
}
|
||||
@@ -251,7 +251,7 @@ suite('Webview tests', () => {
|
||||
});
|
||||
</script>`);
|
||||
|
||||
const workspaceRootUri = vscode.Uri.file(vscode.workspace.rootPath!).with({ scheme: 'vscode-resource' });
|
||||
const workspaceRootUri = vscode.env.webviewResourceRoot + vscode.Uri.file(vscode.workspace.rootPath!).path;
|
||||
|
||||
{
|
||||
const imagePath = workspaceRootUri.toString() + '/image.png';
|
||||
|
||||
Reference in New Issue
Block a user