"""記事の作業フォルダ(iCloud)から、記事1本をサイトに入れる。 使い方: python3 tools/add_article.py <作業フォルダ> <シリーズ名> [--no-split] やること: - LOG{N}_article.md → src/content/records/LOG{N}.md(先頭の項目に series を足す) - LOG{N}_thumbnail.html → public/thumbs/LOG{N}.html(考察記事は使わない。記事の頭の question・key から tools/deep_dive_thumb.py で書き出す) - 本文の【図解】の HTML → public/embeds/(図解の高さを親ページに知らせる仕組みを足す) - 本文の【画像】の画像 → あるかを確かめるだけ。画像は GitHub に入れず、Mac で tools/upload_media.py を使って R2 に入れる - 長いコード・ログ・データ → tools/split_files.py で public/files/LOG{N}/ に分け、押したときだけ読み込む形にする (2026-10-23 から全記事。--no-split を付けると分けずに全文を記事に入れる。元の載せ方に戻すときに使う) このあと、Claude のクラウドの作業環境で tools/render_og.py LOG{N} を動かし、 サムネイルを SNS・検索結果用の画像(public/og/LOG{N}.jpg)に書き出す(Mac には Playwright がないため) """ import re, shutil, sys from pathlib import Path args = [a for a in sys.argv[1:] if not a.startswith("--")] work, day, series = Path(args[0]), args[1], args[2] no_split = "--no-split" in sys.argv site = Path(__file__).resolve().parent.parent md_src = work / f"LOG{day}_article.md" text = md_src.read_text(encoding="utf-8") # 先頭の項目(---で囲まれた部分)に series を入れる fm_end = text.index("\n---", 3) fm, body = text[:fm_end], text[fm_end:] if re.search(r"^series:", fm, flags=re.M): fm = re.sub(r"^series:.*$", f'series: "{series}"', fm, flags=re.M) else: fm += f'\nseries: "{series}"' out = site / "src/content/records" / f"LOG{day}.md" out.parent.mkdir(parents=True, exist_ok=True) out.write_text(fm + body, encoding="utf-8") reporter = re.search(r'HEIGHT_REPORTER = """(.*?)"""', (site / "tools/import_all.py").read_text(encoding="utf-8"), re.S).group(1) thumb = work / f"LOG{day}_thumbnail.html" deep_dive = series == "考察記事" if deep_dive: # 考察記事のサムネイルは、問いを文字で組んだ形(2026-10-26 から)。記事の頭の項目の question と key から書き出す # question: 問い(縦書きで改行したい所に「/」、1行9字まで)/ key: 強く見せる一語(問いの1行の中にある語) q = re.search(r'^question:\s*"?(.*?)"?\s*$', fm, flags=re.M) k = re.search(r'^key:\s*"?(.*?)"?\s*$', fm, flags=re.M) if not (q and k): raise SystemExit("考察記事は、記事の頭の項目に question(問い)と key(強く見せる一語)を書いてください(tools/deep_dive_thumb.py)") import subprocess subprocess.run([sys.executable, str(site / "tools/deep_dive_thumb.py"), "--add", day, q.group(1), k.group(1)], check=True) elif thumb.exists(): (site / "public/thumbs").mkdir(parents=True, exist_ok=True) shutil.copy2(thumb, site / "public/thumbs" / f"LOG{day}.html") for name in re.findall(r"^【図解】\s*(\S+\.html)\s*$", body, flags=re.M): doc = (work / name).read_text(encoding="utf-8") doc = doc.replace("", reporter + "", 1) if "" in doc else doc + reporter (site / "public/embeds" / name).write_text(doc, encoding="utf-8") missing = [] for name in re.findall(r"^【画像】\s*(\S+)(?:\s+.*)?$", body, flags=re.M): # 「【画像】ファイル名 説明」の説明は alt になる src = work / f"LOG{day}_images" / name if not src.exists(): missing.append(name) # 長いコード・ログ・データを外に出す(2026-10-23 から、これから入れる記事はすべて) files_dir = site / "public/files" / f"LOG{day}" if no_split: if files_dir.exists(): shutil.rmtree(files_dir) else: import subprocess subprocess.run([sys.executable, str(site / "tools/split_files.py"), day], check=True) print(f"次に: python3 tools/render_og.py LOG{day}(SNS・検索結果用の画像を書き出す)") print(f"LOG{day}: 記事 {out.name}, シリーズ {series}" + (f", 見つからない画像 {missing}" if missing else "")) if missing: sys.exit(1)