🚀 Python + HTML で作る Markdown エディタ & サーバー(保存失敗のデバッグ対応)
このコードは Python + HTML を使って Markdown を編集・プレビューし、.md
として保存できるエディタ を実装するものです。
✅ 保存ボタンを押したらファイル名を入力し、.md
として保存
✅ Markdown をリアルタイムでプレビュー表示
✅ Python サーバー経由で .md
ファイルの保存・管理が可能
✅ 保存失敗時のエラーを詳細表示
📂 プロジェクト構成
📁 プロジェクトフォルダ
├── markdown_server.py # Python サーバー (Markdown ファイルの保存 & 読み込み)
├── markdown_editor.html # HTML + JavaScript (Markdown エディタ & プレビュー)
├── saved_notes/ # `.md` ファイルの保存先
└── saved_images/ # 画像ファイルの保存先
📝 markdown_server.py
(Python サーバー)
import http.server
import socketserver
import json
import os
PORT = 8000
SAVE_DIR = "saved_notes"
# 保存フォルダを作成(なければ)
if not os.path.exists(SAVE_DIR):
try:
os.makedirs(SAVE_DIR)
print(f"📁 フォルダ '{SAVE_DIR}' を作成しました。")
except Exception as e:
print(f"❌ フォルダ作成失敗: {e}")
class MarkdownServer(http.server.SimpleHTTPRequestHandler):
def do_POST(self):
if self.path == "/save":
try:
content_length = int(self.headers.get("Content-Length", 0))
if content_length == 0:
raise ValueError("受信データが空です")
post_data = self.rfile.read(content_length).decode("utf-8")
print(f"📥 受信データの長さ: {content_length}")
print(f"📥 受信データの中身: {post_data}")
try:
data = json.loads(post_data)
except json.JSONDecodeError as json_error:
print(f"❌ JSON パースエラー: {json_error}")
self.send_response(400)
self.end_headers()
self.wfile.write(f"❌ JSON パースエラー: {json_error}".encode("utf-8"))
return
# ファイル名のバリデーション
filename = data.get("filename", "").strip()
content = data.get("content", "")
if not filename:
raise ValueError("❌ ファイル名が空です")
filename = os.path.basename(filename) # ディレクトリ名を除外
if not filename.endswith(".md"):
filename += ".md"
filepath = os.path.join(SAVE_DIR, filename)
print(f"📂 保存先: {filepath}")
# 書き込み時のエラーハンドリング
try:
with open(filepath, "w", encoding="utf-8") as f:
f.write(content)
self.send_response(200)
self.end_headers()
self.wfile.write(f"✅ {filename} に保存しました!".encode("utf-8"))
print(f"✅ {filename} に保存成功!")
except OSError as write_error:
print(f"❌ 書き込みエラー: {write_error}")
self.send_response(500)
self.end_headers()
self.wfile.write(f"❌ 書き込みエラー: {write_error}".encode("utf-8"))
except ValueError as value_error:
print(f"❌ 値エラー: {value_error}")
self.send_response(400)
self.end_headers()
self.wfile.write(f"❌ 値エラー: {value_error}".encode("utf-8"))
except Exception as e:
print(f"❌ その他のエラー: {e}")
self.send_response(500)
self.end_headers()
self.wfile.write(f"❌ その他のエラー: {e}".encode("utf-8"))
# サーバー起動
try:
with socketserver.TCPServer(("", PORT), MarkdownServer) as httpd:
print(f"✅ サーバーが起動しました: http://localhost:{PORT}")
except Exception as e:
print(f"❌ サーバー起動エラー: {e}")
---
## **📝 `markdown_editor.html`(Markdown エディタ)**
```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Markdown Editor</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
body { font-family: Arial, sans-serif; display: flex; height: 100vh; margin: 0; }
#editor-container, #preview-container {
width: 50%;
padding: 10px;
overflow: auto;
box-sizing: border-box;
}
#editor-container {
border-right: 1px solid #ccc;
}
#editor {
width: 100%;
height: 90%;
font-size: 16px;
padding: 10px;
box-sizing: border-box;
resize: none;
}
</style>
<script>
function updatePreview() {
let mdText = document.getElementById("editor").value;
document.getElementById("preview").innerHTML = marked.parse(mdText);
}
function saveMarkdown() {
let mdText = document.getElementById("editor").value;
let filename = prompt("保存するファイル名を入力(.mdを省略可)", "markdown_note");
if (!filename) {
alert("ファイル名が入力されていません。");
return;
}
if (!filename.endsWith(".md")) {
filename += ".md";
}
fetch("http://localhost:8000/save", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ filename: filename, content: mdText })
})
.then(response => response.text())
.then((message) => {
if (message.includes("❌")) {
alert("保存に失敗しました: " + message);
} else {
alert(`"${filename}" に保存しました!`);
}
})
.catch(error => alert("保存に失敗しました!\nエラー詳細: " + error));
}
</script>
</head>
<body>
<div id="editor-container">
<button onclick="saveMarkdown()">📝 保存</button>
<textarea id="editor" oninput="updatePreview()"># Markdown Editor
## ✅ チェックボックス
- [ ] 未完了のタスク
- [x] 完了したタスク
## 🔹 引用
> これは引用のサンプルです。
## 📌 コードブロック
\`\`\`python
print("Hello, Python!")
\`\`\`
</textarea>
</div>
<div id="preview-container">
<div id="preview"></div>
</div>
</body>
</html>
📌 使い方
-
Pythonサーバーを起動
python markdown_server.py
→
Serving at http://localhost:8000
と表示されたらOK! -
ブラウザで
markdown_editor.html
を開く- Markdown をエディタに入力
- 「📝 保存」ボタンを押し、ファイル名を入力
saved_notes/
に.md
が正しく保存されるか確認- エラーが出る場合はターミナルに詳細エラーが表示される