ASP.NET CoreでMarkdownを活用してみる

GitHubやQiitaなど、さまざまなサービスで使われている形式になってきたMarkdown。この便利(?)なものをASP.NETでも使ってみようというのがこの記事の趣旨です。

CommonMark.NET

Markdownを処理するライブラリを探してみると、その一つとしてCommonMark.NETが見つかります。この説明によると、Full .NETライブラリにも関わらずネイティブライブラリのラッパーと同じくらい速く、さらにPCLや.NET Coreの上でも動くそうです。これはMarkdownで書くときには使わない手はないですよね。

ちなみにCommonMarkとは、Markdownに数ある方言を解決するために、その仕様化を目指したプロジェクトです。というわけで、正確にはMarkdownを使っている…というわけではないですが、大抵は問題なく使えるでしょう。

使い方

基本の使い方は簡単で、using CommonMark;と書いた状態で、CommonMarkConverter.Convertメソッドを使って変換します。他にもParseメソッドやProcessStageメソッドなどもありますが、自分のMarkdown拡張を作ったりしない分には使わないと思います。出力されるHTMLの形式を切り替えたいときは、CommonMarkSettings.Default.Clone()をして自分で設定していくことになります。

            var setting = CommonMarkSettings.Default;
            var md = @"
# Hello!
This is CommonMark.NET test. 
Simple library.
1. foo
2. bar
";

          // settingはオプション引数
          Console.WriteLine(CommonMarkConverter.Convert(md, setting));
<h1>Hello!</h1>
<p>This is CommonMark.NET test.<br />
Simple library.</p>
<ol>
<li>foo</li>
<li>bar</li>
</ol?

ファイル(ストリーム)から読んで別ファイルに出力するというオーバーロードも存在します。

using (var input = File.OpenRead("Hoge.md"))
using (var reader = new StreamReader(input))
using (var output = File.OpenWrite("Piyo.html"))
using (var writer = new StreamWriter(output))
{
    CommonMarkConverter.Convert(reader, writer, setting);
}

ASP.NET Coreと絡めたサンプル

ライブラリの紹介が終わったところで、いよいよASP.NET Coreで使ってみます。全体のソースコードはこちらから

まずはASP.NET Coreプロジェクトを作成し、project.jsonに依存関係を書き加えます。Microsoft.AspNetCore.StaticFilesCommonMark.NETを追加しました。

テンプレートとして、下のような簡単なものを用意しました。style.cssは別途用意しています。

		const string ContentTemplate = @"
<!DOCTYPE html>
<html>
<head>
<title>{0}</title>
<link href=""/style.css"" rel=""stylesheet"" />
</head>
<body>
{1}
</body>
</html>
";

処理コードの中では、用意しているCommonMarkと同じ名前のリクエストがあれば、それをHTMLに変換して表示しています。CommonMarkの実際の処理はCommonMarkConverter.Convertメソッドだけです。

		public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
		{
			var contnetDir = env.ContentRootFileProvider.GetDirectoryContents(@"content");
			if (!contnetDir.Exists)
			{
				throw new Exception("\"content\" directory does not exist.");
			}

			app.UseStaticFiles();

			loggerFactory.AddConsole();

			if (env.IsDevelopment())
			{
				app.UseDeveloperExceptionPage();
			}

			app.Run(async (context) =>
			{
				var pathElements = context.Request.Path.Value.Split('/');
				if (pathElements.Length != 2)
				{
					return;
				}

				var requestName = pathElements[1];
				if (string.IsNullOrEmpty(requestName))
				{
					requestName = "index";
				}

				var file = contnetDir.SingleOrDefault(x => x.Name == requestName + ".md");
				if (file != null)
				{
					using (var stream = file.CreateReadStream())
					using (var reader = new StreamReader(stream))
					{
						var pageContent = await reader.ReadToEndAsync();
						var htmlPart = CommonMarkConverter.Convert(pageContent);
						await context.Response.WriteAsync(string.Format(
							ContentTemplate, requestName, htmlPart));
					}
				}
			});
		}

このプロジェクトを実行すると、次のようなページが表示されます。元のCommonMarkファイル

例1

例1

例2

例2

まとめ

Markdownを処理するためのライブラリであるCommonMark.NETを紹介し、それをASP.NETで利用してみました。

データベースやブラウザエディタを含めてプロジェクトを作れば、MarkdownのCMSっぽいのを構築できるかもしれません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です