diff --git a/html/session/webview/observer.js b/html/session/webview/observer.js new file mode 100644 index 000000000..1f48a8357 --- /dev/null +++ b/html/session/webview/observer.js @@ -0,0 +1,41 @@ +const MutationObserver = window.MutationObserver || window.WebKitMutationObserver; +const replaceReg = /vscode-webview:\/\//; +const testReg = /vscode-webview:\/\/.*\.[A-Za-z/0-9_-]*?\/.+/; +const watchedTags = [ + "IMG", + "A", + "LINK", + "SCRIPT" +]; +const mutationQueue = []; + +const observer = new MutationObserver(mutations => { + if (!mutationQueue.length) { + requestAnimationFrame(setSrc); + } + mutationQueue.push(mutations); +}); + +observer.observe(document.getElementById("webview-content"), { + subtree: true, + attributes: true, + attributeFilter: ["src", "href", "style", "class"], + characterData: false +}); + +function setSrc() { + for (const mutations of mutationQueue) { + const targ = mutations[0].target; + if (watchedTags.includes(targ.tagName) && testReg.test(targ.src)) { + const newSrc = targ.src.replace(replaceReg, 'https://'); + console.log( + `%c[VSC-R] %cThe file request '${targ.src}' was converted to the URL '${newSrc}'. Reason: the request appears to refer to a URL, not a local file as suggested by the file scheme. %cIf you believe this to be in error, please log an issue on GitHub.`, + "color: orange", + "color: inherit", + "font-style: italic" + ); + targ.src = newSrc; + } + } + mutationQueue.length = 0; +} diff --git a/src/session.ts b/src/session.ts index 85dcab5f1..a702bb90d 100644 --- a/src/session.ts +++ b/src/session.ts @@ -14,7 +14,7 @@ import { FSWatcher } from 'fs-extra'; import { config, readContent } from './util'; import { purgeAddinPickerItems, dispatchRStudioAPICall } from './rstudioapi'; -import { homeExtDir, rWorkspace, globalRHelp, globalHttpgdManager } from './extension'; +import { homeExtDir, rWorkspace, globalRHelp, globalHttpgdManager, extensionContext } from './extension'; import { UUID, rHostService, rGuestService, isLiveShare, isHost, isGuestSession, closeBrowser, guestResDir, shareBrowser, openVirtualDoc, shareWorkspace } from './liveShare'; export let globalenv: any; @@ -273,6 +273,7 @@ export async function showWebView(file: string, title: string, viewer: string | void env.openExternal(Uri.parse(file)); } else { const dir = path.dirname(file); + const webviewDir = extensionContext.asAbsolutePath('html/session/webview/'); const panel = window.createWebviewPanel('webview', title, { preserveFocus: true, @@ -282,14 +283,10 @@ export async function showWebView(file: string, title: string, viewer: string | enableScripts: true, enableFindWidget: true, retainContextWhenHidden: true, - localResourceRoots: [Uri.file(dir)], + localResourceRoots: [Uri.file(dir), Uri.file(webviewDir)], }); - const content = await readContent(file, 'utf8'); - const html = content.toString() - .replace('
', '') - .replace(/<(\w+)\s+(href|src)="(?!\w+:)/g, - `<$1 $2="${String(panel.webview.asWebviewUri(Uri.file(dir)))}/`); - panel.webview.html = html; + + panel.webview.html = await getWebviewHtml(panel.webview, file, title, dir, webviewDir); } console.info('[showWebView] Done'); } @@ -607,6 +604,45 @@ export async function getListHtml(webview: Webview, file: string): Promise