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?

皆様こんにちは!ばるとーくです!
今回はWordPressの記事投稿を手元のローカル環境とgitを用いて,markdown形式にて行うことを目的としたCLIツールを作ってみたので,それについて解説していこうと思います!

wp-markdown-cli とは

セルフホストの WordPress サイトを Markdown + Git で管理する CLI ツールです。
記事を Markdown ファイルで書き、npm run push で WordPress REST API へ投稿・更新できます。
Githubにて公開・配布しておりますので、ライセンス範囲内でご自由にお使いください。

動作要件

  • Node.js 20 以上
  • WordPress 5.6 以上(Application Password 機能が必要)
  • WordPress REST API が有効(既定で有効)
  • WordPress ユーザーに Application Password の発行権限があること

セットアップ

1. 依存パッケージのインストール

cd wp-markdown-cli
npm install

2. WordPress Application Password の発行

  1. WP 管理画面 → ユーザー → プロフィール
  2. ページ下部の「アプリケーションパスワード」セクション
  3. 名前に wp-markdown-cli などと入力して「新しいアプリケーションパスワードを追加」
  4. 表示された xxxx xxxx xxxx xxxx xxxx xxxx 形式のパスワードを控える(この画面でしか見られません

Application Password は WordPress 5.6 の標準機能です。通常のログインパスワードとは別物で、REST API 専用の認証情報です。万が一漏れても、その Application Password だけ失効させれば被害を限定できます。

3. .env の作成

cp .env.example .env

.env を編集して WP_BASE_URLWP_USERNAMEWP_APP_PASSWORD を設定してください。

コマンド一覧

新規記事の作成

npm run new -- "記事タイトル"

posts/YYYY-MM-DD-NNNN/index.md を自動生成します(-- の後にタイトルを渡すのは npm の仕様です)。

記事の投稿・更新

npm run push -- 2026-04-30-0001        # 1記事
npm run push -- .                       # posts/ 以下の全記事
  • 初回は新規投稿(POST)、2 回目以降は更新(PUT)になります。
  • .meta/post_map.json でローカルディレクトリと WordPress 投稿 ID の対応を管理しています。
  • 画像は内容ハッシュで重複アップロードを防止します。
  • push が成功すると .meta/ と記事ディレクトリの変更が自動コミットされます。

記事の取得(WordPress → ローカル)

npm run pull                    # 全記事
npm run pull -- --id 123        # 特定の記事のみ

注意: pull はブロックエディタ形式のコンテンツを Markdown に変換しようとしますが、変換品質は保証されません。このツールは push を主流 として設計されており、pull はバックアップや初期取り込みを目的としています。pull 後のファイルを push すると内容が変わる場合があります。

frontmatter の書き方

---
title: "記事タイトル"           # 必須
slug: "post-slug"               # URL 末尾。省略可(省略時は WP が自動生成)
post_type: "post"               # post / private_post(カスタム投稿タイプ)
status: "draft"                 # draft / publish / private
categories:
  - "技術/Node.js"              # "親/子" のパス記法(存在しない場合は自動作成)
  - "日記"                      # 親単独でも可
tags: ["WordPress", "Git"]
date: "2026-04-30T12:00:00+09:00"
excerpt: "抜粋文(省略可)"
featured_image: "images/cover.jpg"  # アイキャッチ画像(記事ディレクトリからの相対パス)
---

カテゴリは 親/子/孫 と深く書くことも可能です。存在しない場合は自動作成されます。

画像の扱い

  • 記事ディレクトリ内の images/ に画像を置き、![alt](images/foo.png) と参照します。
  • push 時に WordPress メディアライブラリへ自動アップロードし、URL を WP のものに置換します。
  • 同じ画像を再 push しても、ハッシュが一致すれば再アップロードせずキャッシュを利用します。
  • アイキャッチ画像は frontmatter の featured_image で指定します。

設定(.env)

変数 必須 説明
WP_BASE_URL WordPress サイトの URL(末尾スラッシュなし)
WP_USERNAME WordPress ユーザー名
WP_APP_PASSWORD Application Password(スペース区切りのままでも可)
SHORTCODE_PROTECTION true にすると WordPress ショートコードを Markdown 変換から保護(既定: false
SOFT_BREAKS true にすると段落内の単一改行を <br> に変換(既定: false

SHORTCODE_PROTECTION

[blogcard url="..."][toc] のような WordPress ショートコードを記事中に書いている場合、Markdown→HTML 変換器がこれを誤って加工することがあります。SHORTCODE_PROTECTION=true にすると、変換の前後でショートコードを退避・復元し、原形のまま WordPress に渡します。

Cocoon など、ショートコードを多用するテーマを使っている方は true を推奨します。

補足: ショートコード内の URL が WordPress 側で属性変換されてしまう場合は、子テーマの functions.php で以下を追加すると解消します(サーバー側の設定です):

remove_filter('the_content', 'wptexturize');

SOFT_BREAKS

true にすると、段落内の単一改行が <br> に変換されます(remark-breaks を使用)。エディタの見た目通りに改行を反映したい場合に有効です。

標準 Markdown の仕様(段落内の単一改行は空白として扱われる)に従いたい場合は false(既定)のままにしてください。

設計上の注意点

「全部 HTML ブロック」戦略

本文を Gutenberg の <!-- wp:html --> ブロック 1 つにまとめて投稿します。これにより:

  • ✅ Markdown ⇄ HTML の往復で情報がほぼ失われない
  • ❌ WordPress 管理画面でのブロック単位の編集はできなくなる

管理画面では編集しない前提で運用してください。pull → ローカル編集 → push の一方向が基本です。

.meta/ は git に含めること

.meta/post_map.json.meta/media_map.json は「どのローカルファイルがどの WordPress ID に対応するか」を記録しています。これが消えると更新が新規投稿になってしまうため、必ず git に含めてください(.gitignore で除外していません)。

ディレクトリ構造

wp-markdown-cli/
├── posts/                      # 記事本体
│   └── YYYY-MM-DD-NNNN/
│       ├── index.md
│       └── images/
├── .meta/                      # git 管理対象(WordPress ID 対応表)
│   ├── post_map.json
│   └── media_map.json
├── scripts/                    # CLI スクリプト
│   ├── new.ts
│   ├── push.ts
│   ├── pull.ts
│   └── lib/
├── .env                        # gitignore 対象(認証情報)
└── .env.example                # テンプレート

ライセンス

MITを設定しています。
詳しくは、リポジトリをご覧ください。

宣伝

私個人運営のブログ「ばるとーくの壊れた部屋」にも同じ記事を投稿しております。
ここでは上げないようなこまごました話や、日常の話(主にAtCoderの振り返り)を投稿しております!
もしお時間よろしければ、こちらにも遊びに来てくれると嬉しいです!
私のプロフィール、あるいは、以下のURLよりご覧ください!

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?