public static IHtmlContent GetHtmlInjection(Uri[] probingUris, string seed) { var apiCacheBuster = $"{Process.GetCurrentProcess().Id}.{seed}"; var template = $@" <div> <div id='dotnet-interactive-this-cell-$CACHE_BUSTER$' style='display: none'> The below script needs to be able to find the current output cell; this is an easy method to get it. </div> <script type='text/javascript'> async function probeAddresses(probingAddresses) {{ function timeout(ms, promise) {{ return new Promise(function (resolve, reject) {{ setTimeout(function () {{ reject(new Error('timeout')) }}, ms) promise.then(resolve, reject) }}) }} if (Array.isArray(probingAddresses)) {{ for (let i = 0; i < probingAddresses.length; i++) {{ let rootUrl = probingAddresses[i]; if (!rootUrl.endsWith('/')) {{ rootUrl = `${{rootUrl}}/`; }} try {{ let response = await timeout(1000, fetch(`${{rootUrl}}discovery`, {{ method: 'POST', cache: 'no-cache', mode: 'cors', timeout: 1000, headers: {{ 'Content-Type': 'text/plain' }}, body: probingAddresses[i] }})); if (response.status == 200) {{ return rootUrl; }} }} catch (e) {{ }} }} }} }} function loadDotnetInteractiveApi() {{ probeAddresses($ADDRESSES$) .then((root) => {{ // use probing to find host url and api resources // load interactive helpers and language services let dotnetInteractiveRequire = require.config({{ context: '$CACHE_BUSTER$', paths: {{ 'dotnet-interactive': `${{root}}resources` }} }}) || require; window.dotnetInteractiveRequire = dotnetInteractiveRequire; window.configureRequireFromExtension = function(extensionName, extensionCacheBuster) {{ let paths = {{}}; paths[extensionName] = `${{root}}extensions/${{extensionName}}/resources/`; let internalRequire = require.config({{ context: extensionCacheBuster, paths: paths, urlArgs: `cacheBuster=${{extensionCacheBuster}}` }}) || require; return internalRequire }}; dotnetInteractiveRequire([ 'dotnet-interactive/dotnet-interactive' ], function (dotnet) {{ dotnet.init(window); }}, function (error) {{ console.log(error); }} ); }}) .catch(error => {{console.log(error);}}); }} {JavascriptUtilities.GetCodeForEnsureRequireJs(onRequirejsLoadedCallBackName: "loadDotnetInteractiveApi")} </script> </div>"; var jsProbingUris = $"[{ string.Join(", ", probingUris.Select(a => $"\"{a.AbsoluteUri}\"")) }]"; var html = template .Replace("$ADDRESSES$", jsProbingUris) .Replace("$CACHE_BUSTER$", apiCacheBuster); return(new HtmlString(html)); }
private string GenerateBootstrapperCode(Uri externalUri, string frontendType, string hash) { string template = $@" // ensure `require` is available globally (function (global) {{ if (!global) {{ global = window; }} let bootstrapper_$FRONTENDTYPE$_$HASH$ = function () {{ let loadDotnetInteractiveApi = function () {{ // use probing to find host url and api resources // load interactive helpers and language services let dotnetInteractiveRequire = require.config({{ context: '$HASH$', paths: {{ 'dotnet-interactive': '$EXTERNALURI$resources' }}, urlArgs: 'cacheBuster=$HASH$' }}) || require; global.dotnetInteractiveRequire = dotnetInteractiveRequire; global.configureRequireFromExtension = function (extensionName, extensionCacheBuster) {{ let paths = {{}}; paths[extensionName] = `$EXTERNALURI$extensions/${{extensionName}}/resources/`; let internalRequire = require.config({{ context: extensionCacheBuster, paths: paths, urlArgs: `cacheBuster=${{extensionCacheBuster}}` }}) || require; return internalRequire }}; dotnetInteractiveRequire([ 'dotnet-interactive/dotnet-interactive' ], function (dotnet) {{ dotnet.init(global); console.log('dotnet-interactive js api initialised'); }}, function (error) {{ console.log(error); }} ); console.log('execution of boostrapper function bootstrapper_$FRONTENDTYPE$_$HASH$ completed'); }} {JavascriptUtilities.GetCodeForEnsureRequireJs(new Uri("https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"), "loadDotnetInteractiveApi")} }}; console.log('installed boostrapper function bootstrapper_$FRONTENDTYPE$_$HASH$'); bootstrapper_$FRONTENDTYPE$_$HASH$(); }})(window); "; return(template .Replace("$HASH$", hash) .Replace("$EXTERNALURI$", externalUri.AbsoluteUri) .Replace("$FRONTENDTYPE$", frontendType)); }