在 ASP.NET Core 網站直接顯示 Markdown 文件
5 | 3,409 |
前幾天介紹過在 Visual Studio 寫 Markdown 文件的好用擴充套件 - Markdown Editor,我有個大膽的想法:既然在 VS 寫 Markdown 這麼方便,我何不在 ASP.NET Core 網站開個專屬資料夾直接寫線上使用手冊,像這樣:
像上面這樣,Markdown 文件、圖檔、下載 PDF 都放在同一個資料夾,還可以區分子資料夾。
文件可加入連結串接其他 Markdown 文件(例如本案中的 other、SubFolder/ 對映 other.md 及 SubFolder/index.md)或下載檔案(demo.pdf):
這樣的架構彈性夠,寫作上應該蠻順手的。至於要放到網站上使用,除了靠 Hugo 之類的軟體批次轉換,若能讓 ASP.NET Core 直接將 .md 轉成 HTML,其餘圖檔、PDF、子資料夾結構都能 100% 沿用,感覺上更直覺簡單了。
首先我們需要一個 Markdown 轉 HTML 的程式庫,Markdown Editor 用的是 MarkDig,從 NuGet 安裝 MarkDig 程式庫,寫個 HelpController 呼叫 Markdown.ToHtml(File.ReadAllText(md_path));
,我們便能產生 Markdown Editor 預覽一致的 HTML 內容。
但 HelpController 只負責處理 .md,HelpDoc 資料夾的 png、pdf 靜態檔案可交給 ASP.NET Core 底層處理,讓 URL /help/folder/name.png 對映到 /HelpDoc/folder/name.png 即可,之前研究過用 UseStaticFiles() 自訂靜態檔案來源,現在便派上用場了。
有了構想,簡單拼裝一下。Program.cs 加入 UseStaticFiles() 及 MapControllerRoute():
//... 省略
app.UseHttpsRedirection();
// 將 /HelpDoc 目錄檔案對映到 /help URL
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(app.Environment.ContentRootPath, "HelpDoc")),
RequestPath = "/help"
});
// 將 /help/** 非靜檔案路徑對映到 HelpController,{*path} 可涵蓋包含多層 / 的網址
app.MapControllerRoute(
name: "Help",
pattern: "help/{*path}",
defaults: new { controller = "Help", action = "Index" }
);
app.UseStaticFiles();
//... 省略
HelpController.cs 內做簡單的路徑對映轉換,這種依使用者指定路徑讀檔的程式,一定要嚴防路徑參數被插入特殊字元偷檔案,我採用的檢核方式是用 Regex.IsMatch(path, "^[A-Za-z/]*$")
限定路徑只能包含英文字母及 / 符號,其餘一律視為不合法。
using Microsoft.AspNetCore.Mvc;
using System.Text.RegularExpressions;
namespace MarkdownDistrictAspNetCore.Controllers
{
public class HelpController : Controller
{
string MarkdownPath;
public HelpController(IHostEnvironment env)
{
MarkdownPath = Path.Combine(env.ContentRootPath, "HelpDoc");
}
public IActionResult Index(string path)
{
// Path validation
path = path ?? string.Empty;
if (!Regex.IsMatch(path, "^[A-Za-z/]*$"))
return Content($"Ivalid Path - {path}");
var mdPath = Path.Combine(MarkdownPath, path.Replace("/", "\\"));
if (!System.IO.File.Exists(mdPath + ".md"))
{
mdPath = mdPath.TrimEnd('/') + "/index";
if (!System.IO.File.Exists(mdPath + ".md"))
return NotFound();
else
{
if (!string.IsNullOrEmpty(path))
path = path.TrimEnd('/') + "/";
return Redirect($"~/Help/{path}index");
}
}
ViewBag.HtmlContent = Markdig.Markdown.ToHtml(System.IO.File.ReadAllText(mdPath + ".md"));
return View();
}
}
}
就醬,插電、開機,輕鬆秒殺~
相同的檔案結構,.md 直接變成網頁,很酷吧?
範例程式已上傳 Github,需要者請自取。
Tips of showing Markdown documents in ASP.NET Core web sites.
Comments
# by Toolman
黑大好 如果想用 markdown 產說明文件,或許可以用一些 document generator ? 像是 Vuepress 只要用這些靜態產生器產出靜態檔,就可以直接掛載到 IIS 上當成說明文件了 另外想請問一下黑大,您的部落格網站是架在什麼機器上呢? 部落格中的圖檔等等靜態檔,是否有存在什麼額外的 static file server 呢?
# by Jeffrey
to Toolman,這個解決方案我打算用在簡單的線上輔助說明,若是完整手冊,我偏好用 Hugo 來做。Vuepress 挺吃前端技能的,完全沒摸過 npm、yarn 的生手看到會怕,Hugo 相對簡單一些。 我的 Blog 是以 Miniblog.Core 為基礎修改的,在 Linux Docker 容器執行,圖檔就放在 wwwroot 下,沒用特殊儲存做法,但有沿用 Miniblog.Core 內建的圖片延遲載入機制。
# by Toolman
了解,感謝回答 不好意思想再請問,您的 Linux Docker 是架在自己的機器上嗎? 還是是放在第3方的機器上呢?
# by Jeffrey
to Toolman,放雲端,但 ASP.NET Core 跑 Docker 蠻省資源的,試過放在迷你主機 ( https://blog.darkthread.net/blog/minipc-as-centos-server/ ) 跑也沒什麼問題
# by Toolman
挺有趣的XD 感謝黑大的分享