python でカレントディレクトリ配下のmdファイルを検索してmarkdown表示する

python でカレントディレクトリ配下のmdファイルを検索してmarkdown表示する

2024/01/20 00:00:00
Program
Python

前提 #

  • 環境は windows10 pro
  • git-bash 環境にpyenv-winは設定済みの状態であること
  • python バージョンは3.11.6
  • 完成ソースは以下に登録
    https://github.com/oya3/pymdreader

アプリ作業エリア生成 #

git-bash で以下を実行

$ pyenv install 3.11.6
$ mkdir pymdreader
$ cd pyreader
$ pyenv local 3.11.6
$ python -m venv venv
$ source venv/Scripts/activate
# 必要なパッケージを追加
$ pip install flask markdown2 glob2
...
[notice] A new release of pip is available: 23.2.1 -> 23.3.2
[notice] To update, run: python.exe -m pip install --upgrade pip
$ python.exe -m pip install --upgrade pip

# exe 化用パッケージも追加
$ pip install pyinstaller

# パッケージリスト保持
$ pip freeze > requirements.txt

# エディタで静的解析が必要な場合(poetry使わないと開発用パッケージが混ざるので注意)
$ pip install jedi flake8 importmagic autopep8 yapf black

アプリ作成 #

$ emacs pymdreader.py

from flask import Flask, render_template_string, request, send_from_directory
import markdown2
import glob
import os
import re

app = Flask(__name__, static_url_path='', static_folder=os.path.abspath('.'))

@app.route('/')
def home():
    files = glob.glob("**/*.md", recursive=True)
    files = [f.replace('\\', '/') for f in files if 'venv' not in f]
    return render_template_string("""
<!DOCTYPE html>
<html>
<head>
    <title>Markdown Preview</title>
    <style>
        #container {
            display: flex;
        }
        #file-list {
            width: 30%;
            overflow: auto;
            height: 100vh;
            border-right: 1px solid #ccc;
            padding: 10px;
        }
        #file-content {
            width: 70%;
            padding: 10px;
            overflow: auto;
            height: 100vh;
        }
        .file-item {
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div id="container">
        <div id="file-list">
            {% for file in files %}
                <div class="file-item" onclick="loadFile('{{ file }}')">{{ file }}</div>
            {% endfor %}
        </div>
        <div id="file-content"></div>
    </div>
    <script>
        function loadFile(filePath) {
            fetch('/file?path=' + filePath)
                .then(response => response.text())
                .then(data => {
                    document.getElementById('file-content').innerHTML = data;
                });
        }
    </script>
</body>
</html>
    """, files=files)

@app.route('/file')
def file_content():
    path = request.args.get('path')
    with open(path, 'r', encoding='utf-8') as f:
        markdown = f.read()
    html = markdown2.markdown(markdown, extras=["tables"])
    directory = os.path.dirname(path)
    html = re.sub(r'src="([^"]*)"', lambda match: 'src="' + os.path.join(directory, match.group(1)) + '"', html)
    return html

@app.route('/<path:path>')
def static_file(path):
    return send_from_directory('.', path)

if __name__ == '__main__':
    app.run(port=3000)

exe 化 #

以下を git-bash で実行すると、dist ディレクトリに pymdreader.exe が生成される

$ pyinstaller pymdreader.py --onefile

実行 #

  1. dist にある pymdreader.exe をコピー
    mdファイルが保存されたディレクトリ階層の一番上にコピー
  2. コピーした pymdreader.exe を実行
    実行するとコマンドプロンプト画面が表示され http://127.0.0.1:3000 で待ち受けているメッセージが表示される
  3. ブラウザで http://127.0.0.1:3000 にアクセス
    左ペインにmdファイル一覧が表示され、それをクリックするとmorkdownプレビューが中央ペインに表示される