Markdownに書いたコードを直接実行するアプリの技術的要素

# 1. この記事について

この記事は、私が開発したExecNoteというアプリケーションの技術的要素を説明したものです。

ExecNoteは、Markdownに記述したコードを、ワンクリックで実行できるアプリケーションです。現在は、NodeJS、Python、Powershellのコード実行に対応しています。

[https://execnote.app/](https://execnote.app/)

[![execnote-helloworld.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695786/9dd5c388-7133-f4f9-7edf-b0a4fa550b2d.png)](https://execnote.app/)


現在はWindowsのみですが、今後、Mac OSX、Linux、AWS Lambda等でコード実行できるSaaSアプリ化へ対応予定です。


# 2. 作者について

私は、SIerのSEとして５年、その後、自動車部品製造業社内SEとして６年ほどシステムエンジニアとして働いています。実務では主にERPや製造業務システムの要件定義・設計開発・保守を担当しています。VB6とCOBOLで開発されたERPのメンテナンスもしています。

ブログは主に技術的な内容を書いています。

- Blog: [https://usefuledge.com/](https://usefuledge.com/)

Twitterでは、ExecNoteの宣伝や、感じたことを徒然と書いています。

- Twitter: [https://twitter.com/Harus0313](https://twitter.com/Harus0313)


# 3. ExecNoteの機能概要

ExecNoteは、2020年8月22日時点で、主に以下の機能を実装しています。

1. Markdownドキュメントのツリー表示
2. Markdown編集機能
3. プレビュー機能
5. オートセーブ機能
4. コード実行機能
6. コード実行時の作業ディレクトリ変更機能

画像のコピペに対応していなかったり、今一つ機能としては足りていないところもありますが、必要最低限の機能を実装しています。

機能概要は、以下のYouTube動画にまとめています。

[https://youtu.be/b_WYr35MUSc](https://youtu.be/b_WYr35MUSc)

[![execnote-youtube.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695786/921c9783-df50-a964-5db6-6041e5ed187f.png)](https://youtu.be/b_WYr35MUSc)

# 4. 使用したプログラム言語とフレームワーク

このアプリケーションは、ローカルPC上に .NET Core Blazor サーバーを起動して、ブラウザで表示しています。よって、バックグラウンドは、Blazor Server と C#, フロント側は、HTML, JavaScript, CSSを使用しています。

Markdownを編集するエディタは、Visual Studio Codeと同じく、Monaco Editor を採用しました。補完機能が充実していますし、個人的に好きなので。

[https://microsoft.github.io/monaco-editor/](https://microsoft.github.io/monaco-editor/)

MarkdownをHTMLに変換するエンジンは、marked.js を採用しました。シンプルでものすごく使いやすいです。

[https://github.com/markedjs/marked](https://github.com/markedjs/marked)

Markdownドキュメントや設定情報は、内部にポータブルNoSQLデータベースを作成して保存しています。ポータブルNoSQLデータベースは、LiteDBを採用しました。
LiteDBは、.NET Framework で書かれています。動作も高速で、ファイルサイズも32KB程度とかなり軽量です。

[https://www.litedb.org/](https://www.litedb.org/)

# 5. コマンドと言語の取得方法

ExecNoteは、Markdownに記述されたコードと言語を判断して、実行することが最重要機能要件です。

コード記入のMarkdown文法では、以下のようにプログラム言語を記述できます。

![execnote-code.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695786/183cb46b-022a-0297-1863-accd84bea543.png)

これをmarked.jsでHTMLに変換すると、&lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;...&lt;/code&gt;&lt;/pre&gt;のように、classに言語名が付与されます。

![execnote-code-html.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695786/64e844d4-fd46-841e-4851-cc5d3d5d483c.png)

これをもとにプログラム言語を判定します。そのため、Markdownの記述が誤っていると、誤ったインタプリタで実行されてしまいます。

コードは、&lt;code&gt;...&lt;/code&gt;の中に書かれた内容をinnerTextで取得します。

これらの情報をBlazorServer側に渡して、コードを実行します。


# 6. フロントエンド(JavaScript)からBlazor Serverの関数を呼び出す方法

フロントエンド(JavaScript)からBlazor Server関数を呼び出すには、`DotNet.invokeMethodAsync`を使用します。

以下のコードは、ExecNoteプロジェクトの`JSInvokableExecCode`というBlazorServer側の関数を呼び出します。引数は、`codeInfoJson`です。

```
DotNet.invokeMethodAsync('ExecNote', 'JSInvokableExecCode', codeInfoJson)
```

`JSInvokableExecCode`から返り値がある場合、`.then`を用いて取得します。

```
    DotNet.invokeMethodAsync('ExecNote', 'JSInvokableExecCode', codeInfoJson)
    .then(data => {

    })
```

詳しくは以下を参照ください。

[https://usefuledge.com/js-call-blazor-function.html](https://usefuledge.com/js-call-blazor-function.html)


# 7. Monaco Editor の使い方

まず、[https://microsoft.github.io/monaco-editor/](https://microsoft.github.io/monaco-editor/)を参照し、npm installなどを使用してダウンロードします。

`_Host.cshtml`に`loader.js`を記述します。

```
    <script src="~/monaco-editor/min/vs/loader.js"></script>
```

razorコンポーネント等に、Monaco Editor を表示するDIVタグを記述します。

```
<div id="EditorContainer"></div>
```


以下のような、初期化用のJavaScript関数を定義します。オプションは、PlaygroundもしくはAPI DOCSをみると分かるかもしれません。

[https://microsoft.github.io/monaco-editor/playground.html](https://microsoft.github.io/monaco-editor/playground.html)

[https://microsoft.github.io/monaco-editor/api/index.html](https://microsoft.github.io/monaco-editor/api/index.html)　

Monaco Editor の OnChangeなイベントは`window.editor.onDidChangeModelContent`で実行できます。

```
function initializeMonaco()
{
    require(['vs/editor/editor.main'], function () {
        window.editor = monaco.editor.create(document.getElementById('EditorContainer'), {
    
            value: GetReadMe(),
            language: 'html',
            theme: "vs-dark"
        });
    
        window.editor.onDidChangeModelContent(() => {
            PreviewMarkdown();
            AutoSaveDB();
        });
    

}
```

# 8. 終わりに

機能を実装するにはいろいろな手法があると思いますが、１つの例として読んで頂ければと思います。

また、ExecNoteは、定常的に実行するコードをMarkdownと一緒に管理することで、作業効率が見込まれるアプリケーションです。

よければダウンロードをお願いします！

[https://execnote.app/](https://execnote.app/)
[![execnote-youtube.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695786/921c9783-df50-a964-5db6-6041e5ed187f.png)](https://execnote.app/)