上次說為了不想在web端登入部落格園,我想著還是繼續使用MarkWord編寫部落格,不過在使用的過程中,如果markdown檔案的目錄中有中文的話,Markdown預覽就不能夠顯示貼上的圖片了,原因是之前.NET Framework的WeBrowser
庫太老了,應該升級一下。
替換WebBrowser的方案很多,在Stackoverflow上有人推薦使用WebView2,我就直接用了,也沒有多想,實際上使用的問題還是不少的,簡單記錄一下。
WebView2
這個東西是微軟推出基於Edge或者說是基於chromium核心的瀏覽器元件,可以提供現代的瀏覽器體驗,用於整合到.NET程式中,實現.NET對web的訪問與呼叫,或者反過來也行。這個東西感覺是CefSharp
的有利競爭者呀,雖然我也沒咋用過CefSharp
。
WebBrowser->WebView2
遷移的第一步是引用的替換,WebBrowser在System.Windows.Forms.WebBrowser名稱空間,如果使用WPF的話,需要使用WindowsFormsHost,這個就體驗不是那麼好了,WPF下,有Microsoft.Web.WebView2.Wpf,可以提供給WPF原生的訪問,贊一個。
訪問DOM
然後就是出現的錯誤了,最難受的是,WebView2不提供對DOM的訪問許可權!,WebBrowser可以直接通過Document來訪問DOM節點,而WebView2只能設定訪問的Uri資訊,然後控制導航與呼叫js。
為了實現動態的控制預覽框的內容,訪問DOM是必須的,如果我動態的渲染一個檔案,然後隨時再構造Uri,再傳遞到WebView2中,那太囉嗦了。由於這個東西可以直接呼叫JS,那麼我們換一個思路:通過WebView2呼叫JS,然後使用Js操作DOM,曲線實現控制DOM的目標。廢話不多說,直接上程式碼。
if (winWebDoc.CoreWebView2 == null)
return;
var script = "document.body.innerHTML = '" + Markdown.ToHtml(MarkValue, pipeline).Trim() + "'";
winWebDoc.ExecuteScriptAsync(script);
之前我也嘗試過document.write的方法,發現有點問題,還是不能正常識別。
WebView2除了直接在傳遞js的函式體以外,還可以呼叫頁面中的頂級JS函式,具體使用方法參見後面的參考文獻或者園子裡面的這篇文章,反正我這麼使用之後中文目錄的問題就解決了,不過右側渲染如果有回車換行的話,就經常會卡死,好像是引擎就崩潰了。
替換預設換行
經過debug,發現WebView2在執行的過程中,需要渲染的html內,標籤之間不能有\r\n之類的東西,如果有就寄了。而使用CommonMark.CommonMarkConverter.Convert方法轉換的markdown檔案都會有這個東西...
這個庫時間也比較久遠了,經過簡單研究,我換成了Markdig這個庫,二者相容,而且Markdig還提供了更多定製的地方,我這裡將所有的換行,替換為空字元。
private MarkdownPipeline pipeline = new MarkdownPipelineBuilder()
.ConfigureNewLine("")
.Build();
這樣,換行就沒啥問題了,但是在初次使用時,會出現WebView2無法正常渲染的問題。
WebView2初始化
WebView2的初始化和其他的庫有點不同,它提供了一個EnsureCoreWebView2Async的方法,對它的操作,請一定等這個方法返回。可以使用await,也可以和我一樣,使用TPL。
winWebDoc.EnsureCoreWebView2Async()
.ContinueWith(t =>
{
Dispatcher.Invoke(() =>
{
winWebDoc.Source = new Uri(System.IO.Path.Combine(Environment.CurrentDirectory, "index.html"));
});
});
注意我這裡使用載入了一個本地的模板HTML檔案,訪問本地檔案的時候,需要使用Uri的方式訪問。
結語
經過了一番折騰,終於是能夠繼續使用MarkWord寫部落格了,雖然我更換了主題之後,滾動不是很利索了,另外渲染程式碼換行好像還有點問題,不過好歹能用了,以後再折騰吧。