0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Django学習記録⑩Pythonコードブロックごとの実行結果保存とエラー表示を実装

0
Posted at

はじめに

今回は、MarkdownにPyhtonコード実行機能を改善しました。SmarMemoでは、Markdownの中にPyhtonコードを記述し、ブラウザ上で実行できるようにしています。

error-result_1.png

今回取り組んだのは、主に以下の内容です。

  • コードブロックごとの実行結果を管理
  • Pythonの実行結果をMarkdownへ保存する
  • PythonのエラーもMarkdownへ保存する
  • エラー結果をプレビュー上で分かりやすく表示する

単純に実行するというところから、実行した結果もメモとして残せるところまで改善しました。

コードブロックごとの実行結果を管理する

最初に取り込んだのは、複数のPythonコードブロックを実行したときの実行結果の管理です。
たとえば、Markdownの中に複数のPythonコードがある場合

print("HelloWorld~")
for i in range(1,10):
    print(i)

それぞれのコードに対応した実行結果を保存する必要があります。
そこで、実行されたPythonコードからMarkdown上のコードブロックを作成し、indexOf()を使って現在のMarkdown内の位置を検索するようにしました。

const currentContent = editor.getValue();

const codeBlock = 
"```python\n" +
code.trim() + 
"\n```";

const position = currentContent.indexOf(codeBlock);

コードブロックが見つからない場合は処理を終了します。

if (position === -1){
   return;
}

これによって、実行されたコードブロックを基準に、その直後の実行結果を管理できるようにしました。

PythonのエラーもMarkdownへ保存する

次に、Python実行時のエラーについて改善しました。

PyodideでPythonを実行してエラーが発生した場合、エラー内容を取得して表示します。

}catch (err){
    outputDiv.classList.remove('text-light');
    outputDiv.classList.add('text-danger');

    outputDiv.textContent =
    `❌ ${err.name || 'Error'}: ${err.message}\n`;
}

例えば、

❌ ZeroDivisionError: division by zero

のように表示されます。

しかし、画面に表示するだけではページを更新したときに消えてしまいます。

そこで、エラーの場合も updateOutputBlock() を呼び出して、Markdownへ保存するようにしました。

updateOutputBlock(
    editor,
    block.textContent,
    outputDiv.textContent,
    true
);

textとerrorを区別

実行結果とエラーを区別するため、Markdownのコードフェンスを分けることにしました。

const fenceLabel = isError ? 'error' : 'text';

const outputBlock =
"\n\n```" + fenceLabel + "\n" +
output.trim() +
"\n```\n";

正常な実行結果の場合は、

Hello

エラーの場合は、

❌ ZeroDivisionError: division by zero

として保存されます。

Markdownそのものには文字色を指定していません。

text と error という種類だけをMarkdownに保存し、表示方法はCSS側で管理するという考え方にしました。

CSSでエラーを赤く表示する

Markdownでは標準的に文字色を変更する機能はありません。

そこで、marked.js が生成するコードブロックのクラスを利用しました。

error はHTMLに変換されると、

<code class="language-error">

のようになります。

そこでCSSに、

#preview pre code.language-error {
    color: #ff6b6b;
    background-color: #2b1414;
    display: block;
    padding: 0.5rem;
    border-radius: 4px;
    white-space: pre-wrap;
}

を追加しました。

これによって、通常の実行結果は通常のコードブロックとして表示し、エラーだけを赤文字で表示できるようになりました。

実装してみて

今回の改善によって、SmartMemoのPython実行機能が少しずつ「実行するだけ」の機能から、「実行した内容を記録する」機能へ変わってきました。

現在は、

Markdown

Pythonコードを実行

実行結果を取得

コードブロックを特定

既存の結果を置き換え

Markdownへ保存

プレビューに反映

という流れになっています。また、エラーの場合は、

Pythonエラー

errorブロックとして保存

language-error

CSSで赤く表示

という流れにしています。

Markdown、JavaScript、Pyodide、CSSを組み合わせることで、単純なメモアプリとは少し違った使い方ができるようになってきました。

今後について

次回はUI改善に取り組む予定です。
現在エディタとプレビューのサイズが小さく固定されているため、幅を変更して見やすく作りたいと考えています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?