如何將c#線上編輯器嵌入自己專案

tokengo發表於2023-05-08

如何將c#線上編輯器嵌入自己專案

首先我們需要介紹一下這個線上編輯器,當前的線上編輯器支援c#的程式碼編譯執行,並且無需後臺服務,基於WebAssembly實現的在瀏覽器端去執行我們的c#程式碼,基於Roslyn提供的Api封裝一套簡單的編譯,並且封裝了js的支援,讓嵌入的方式更簡單。

使用現有專案嵌入線上編輯器

最簡單的嵌入方式是使用別人已經部署好的介面去嵌入到自己的專案當中,這樣的好處就是程式碼量極少,但是強依賴於他人的專案,下面我將提供一個簡單的案例在react中嵌入已經存在的編輯器,我將使用自己的部落格專案,在部落格專案中嵌入線上編輯器。

啟動專案

yarn start

我在我的專案中新增了編輯器的單獨頁面,下面是完整的程式碼,

import React, { Component } from 'react'
import './index.css';

export default class Ide extends Component {

    render() {
        return (
            <iframe style={{height:"100%",width:'100%'}} src='https://webassembly.tokengo.top:8843/'></iframe>
        )
    }
}

看到上面的實現方式,是透過iframe直接嵌入的,當然這是因為我提供的網站並沒有做跨域限制,所以可以直接嵌入,也可以供大家一快使用。

效果如圖所示。

然後右鍵編輯區域,會出現執行按鈕,點選執行

將在下面的輸出中顯示輸出資訊

這樣就非常簡單的將線上編輯器嵌入到自己部落格中

嵌入獨有的編輯器

當然,也有人覺得嵌入他人的部落格會受制於他人,如果別人的站點掛了就無法使用,所以想知道是否可以自己搭建

這裡提供倆個方案,一個使用現成的docker映象,直接部署一個使用,另一個就是使用sdk功能自己實現介面編輯,只需要使用sdk提供的編譯功能

docker部署

這是提供的基本的映象registry.cn-shenzhen.aliyuncs.com/gotrays/web-actuator:latest,由阿里雲的免費映象倉庫提供。
可以使用一下命令拉起執行一個簡單的倉庫

docker run -p 8888:80 --name web-actuator registry.cn-shenzhen.aliyuncs.com/gotrays/web-actuator:latest

使用SDK功能

專案將簡單的介紹在JavaScript中使用動態編輯c#的SDK

實現我們需要拉去SDK的程式碼

git clone https://github.com/239573049/WebActuator.git

然後使用vs開啟WebActuator.sln解決方案,

選中WebActuator.WebAssembly專案進行釋出

釋出以後開啟發布的資料夾,開啟_framework 資料夾,然後刪除資料夾下面的*.gz檔案,因為預設使用的br壓縮,所以不需要使用*.gz

下面是釋出的根目錄,我們需要複製除了index.html的檔案到我們自己的專案當中

嵌入專案截圖

開啟我們的index.html


  <script src="_framework/blazor.webassembly.js" autostart="false"></script>
  <script type="module">
    import { BrotliDecode } from './decode.min.js';
    import * as exportManage from './exportManage.js';
    window.exportManage = exportManage;
    Blazor.start({
      loadBootResource: function (type, name, defaultUri, integrity) {
          if (type !== 'dotnetjs') {
          return (async function () {
            const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
            if (!response.ok) {
              throw new Error(response.statusText);
            }
            const originalResponseBuffer = await response.arrayBuffer();
            const originalResponseArray = new Int8Array(originalResponseBuffer);
            const decompressedResponseArray = BrotliDecode(originalResponseArray);
            const contentType = type === 
              'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
            return new Response(decompressedResponseArray, 
              { headers: { 'content-type': contentType } });
          })();
        }
      }
    });
  </script>

將以上程式碼新增的我們專案的index.html

然後在我們需要實現的介面進行編譯初始化

let assemblys=["https://assembly.tokengo.top:8843/System.dll",
      "https://assembly.tokengo.top:8843/System.Buffers.dll",
      "https://assembly.tokengo.top:8843/System.Collections.dll",
      "https://assembly.tokengo.top:8843/System.Core.dll",
      "https://assembly.tokengo.top:8843/System.Linq.Expressions.dll",
      "https://assembly.tokengo.top:8843/System.Linq.Parallel.dll",
      "https://assembly.tokengo.top:8843/mscorlib.dll",
      "https://assembly.tokengo.top:8843/System.Linq.dll",
      "https://assembly.tokengo.top:8843/System.Console.dll",
      "https://assembly.tokengo.top:8843/System.Runtime.dll",
      "https://assembly.tokengo.top:8843/System.Net.Http.dll",
      "https://assembly.tokengo.top:8843/System.Private.CoreLib.dll",
      "https://assembly.tokengo.top:8843/System.Console.dll"]
   await window.exportManage.SetReferences(assemblys);

使用 await window.exportManage.SetReferences(assemblys);提供預設需要編譯的程式集

await window.exportManage.SetReferences(assemblys);的程式碼是在exportManage.js中提供的api

這是用於初始化編譯所需要的程式集,基本預設就這些,當然也可以新增其他的程式集,

監聽Console輸出


window.OnWriteLine = (message: string) => {
            console.log(message);
    }

window.OnDiagnostic = (json: string) => {
		console.log(json);
    }

上面是SDK提供的控制檯攔截器,

OnWriteLine是控制檯的輸出

OnDiagnostic是早編譯的錯誤和日誌

建立了倆個監聽器然後就可以呼叫編輯方法了,呼叫

await window.exportManage.RunSubmission(`Console.WriteLine("hello world");`, false);

執行編譯,然後我們就可以在瀏覽器控制檯中看到編譯輸出了

如果你想要重複寫那麼多程式碼可以修改WebActuator.Web專案當中的ClientApp的程式碼

專案提供了基於monaco實現的簡單的編輯器。

APIs列表:

// 獲取當前引用
window.exportManage.Using()

// 新增預設引用
window.exportManage.SetUsing(using)
 
 // 刪除指定引用
window.exportManage.RemoveUsing(using)

// 清空全域性引用
window.exportManage.ClearUsing()

// 獲取當前編譯的語言版本
window.exportManage.LanguageVersion()

// 修改編譯的語言版本
window.exportManage.SetLanguageVersion(languageVersion)

// 獲取當前依賴的程式集URL
window.exportManage.References()

// 新增編譯依賴的程式集
window.exportManage.SetReferences(references)

// 只編譯程式碼
window.exportManage.TryCompile(source, concurrentBuild)

// 執行編譯程式碼
window.exportManage.RunSubmission(code, concurrentBuild)

以上只是當前版本的APIs,後續還會最佳化並且更新,打造一個好用方便的線上編譯c#程式碼的編輯器。

結尾

來自token的分享

倉庫地址:https://github.com/239573049/WebActuator 歡迎PR和star

技術交流群:737776595

相關文章