@czhlin/vite-plugin-vscode
Version:
Use vue/react to develop 'vscode extension webview', supporting esm/cjs
18 lines (16 loc) • 5.96 kB
JavaScript
//#region src/webview/template.html
var template_default = "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n html,\n body {\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n overflow: hidden;\n }\n\n #webview-patch-iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n .outer {\n width: 100%;\n height: 100%;\n overflow: hidden;\n }\n </style>\n\n <script type=\"module\" id=\"webview-patch\">\n const TAG = '[@tomjs:vscode:extension] ';\n\n function onDomReady(callback, doc) {\n const _doc = doc || document;\n if (_doc.readyState === 'interactive' || _doc.readyState === 'complete') {\n callback();\n } else {\n _doc.addEventListener('DOMContentLoaded', callback);\n }\n }\n\n let vsCodeApi;\n\n function getApi() {\n if (vsCodeApi) return vsCodeApi;\n return (vsCodeApi = acquireVsCodeApi());\n }\n\n function sendInitData(iframe) {\n console.log(TAG + 'init data');\n const dataset = {};\n Object.keys(document.body.dataset).forEach((key) => {\n dataset[key] = document.body.dataset[key];\n });\n\n iframe.contentWindow.postMessage(\n {\n type: '[vscode:extension]:init',\n data: {\n state: getApi().getState(),\n style: document.getElementById('_defaultStyles').innerHTML,\n root: {\n cssText: document.documentElement.style.cssText,\n },\n body: {\n dataset: dataset,\n className: document.body.className,\n role: document.body.getAttribute('role'),\n },\n },\n },\n '*',\n );\n }\n\n function observeAttributeChanges(element, attributeName, callback) {\n const observer = new MutationObserver(function (mutationsList) {\n for (let mutation of mutationsList) {\n if (mutation.type === 'attributes' && mutation.attributeName === attributeName) {\n callback(mutation.target.getAttribute(attributeName));\n }\n }\n });\n observer.observe(element, { attributes: true });\n return observer;\n }\n\n // message handler\n let iframeLoaded = false;\n const cacheMessages = [];\n\n function handleMessage(e) {\n const iframe = document.getElementById('webview-patch-iframe');\n if (!iframeLoaded || !iframe) {\n return;\n }\n if (e.origin.startsWith('vscode-webview://')) {\n iframe.contentWindow.postMessage(e.data, '*');\n } else if ('{{serverUrl}}'.startsWith(e.origin)) {\n const { type, data } = e.data;\n console.log(TAG + ' received:', e.data);\n if (type === '[vscode:client]:postMessage') {\n getApi().postMessage(data);\n } else if (type === '[vscode:client]:commands') {\n if (data === 'F1') {\n window.dispatchEvent(\n new KeyboardEvent('keydown', {\n key: 'F1',\n keyCode: 112,\n code: 'F1',\n }),\n );\n }\n }\n }\n }\n\n window.addEventListener('message', function (event) {\n if (event.origin.startsWith('vscode-webview://')) {\n cacheMessages.push(event);\n return;\n }\n handleMessage(event);\n });\n\n let isCacheWorking = false;\n setInterval(() => {\n if (isCacheWorking) {\n return;\n }\n\n isCacheWorking = true;\n if (iframeLoaded) {\n let event = cacheMessages.shift();\n while (event) {\n handleMessage(event);\n event = cacheMessages.shift();\n }\n }\n isCacheWorking = false;\n }, 50);\n\n onDomReady(function () {\n /** @type {HTMLIFrameElement} */\n const iframe = document.getElementById('webview-patch-iframe');\n observeAttributeChanges(document.body, 'class', function (className) {\n sendInitData(iframe);\n });\n\n onDomReady(function () {\n iframeLoaded = true;\n sendInitData(iframe);\n }, iframe.contentDocument);\n\n iframe.addEventListener('load', function (e) {\n iframeLoaded = true;\n\n let interval = setInterval(() => {\n try {\n if (document.getElementById('_defaultStyles')) {\n sendInitData(iframe);\n // addListeners(iframe);\n clearInterval(interval);\n return;\n }\n } catch (e) {\n clearInterval(interval);\n console.error(e);\n }\n }, 10);\n });\n });\n <\/script>\n </head>\n\n <body>\n <div class=\"outer\">\n <iframe\n id=\"webview-patch-iframe\"\n frameborder=\"0\"\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads\"\n allow=\"cross-origin-isolated; autoplay; clipboard-read; clipboard-write\"\n src=\"{{serverUrl}}\"\n ></iframe>\n </div>\n </body>\n</html>\n";
//#endregion
//#region src/webview/webview.ts
/**
*
* @param options serverUrl string or object options
*/
function getWebviewHtml(options) {
const opts = { serverUrl: "" };
Object.assign(opts, options);
return template_default.replace(/\{\{serverUrl\}\}/g, opts.serverUrl);
}
var webview_default = getWebviewHtml;
//#endregion
export { webview_default as default };