blogをdev.toサポートした

Table of Contents

背景・動機

takeokunn/blog でdev.toの記事を管理できるようにしたのでメモしておく。

試したこと・やったこと

1. 対応理由整理

takeokunn/blog は次の3つのターゲットに対してorg-roamでコンテンツ管理をしている。

以前から英語でもブログを書きたいという欲求があった。 ホスティング先はどこがよいのか検討した所、dev.to がなんだかんだ安牌であることがわかったので対応することにした。

2. NixでBuildできるようにする

flake.nix は以下。

https://github.com/takeokunn/blog/blob/main/devto/flake.nix

{
  packages = {
   build-devto = pkgs.stdenv.mkDerivation {
     name = "build-devto";
     src = ./.;
       nativeBuildInputs = with pkgs; [
         (emacsPkg.pkgs.withPackages (epkgs: (with epkgs.melpaPackages; [ ox-gfm ])))
       ];
       buildPhase = ''
         mkdir -p ./articles
         emacs --batch --load scripts/ox-devto.el --funcall export-org-devto-files
       '';
       installPhase = ''
         mkdir -p $out
         # Article Sync Format: articles/{slug}/article.json + article.md
         for dir in ./articles/*/; do
           if [ -f "$dir/article.json" ]; then
             cp -r "$dir" $out/
           fi
         done
       '';
     };
  };
}

ox-devto.el を適当に作り、 ox-gfm をdev.to用にwrapした。

https://github.com/takeokunn/blog/blob/main/devto/scripts/ox-devto.el

(org-export-define-derived-backend 'devto 'gfm
  :options-alist
  '((:devto-tags "TAGS" nil nil t)
    (:devto-description "DESCRIPTION" nil nil t)
    (:devto-id "DEVTO_ID" nil nil t)
    (:devto-slug "DEVTO_SLUG" nil nil t)))

(defun export-org-devto-files ()
  "Export all Org files in articles directory to Article Sync format."
  (setq org-publish-timestamp-directory org-devto-timestamp-directory)
  (let ((org-publish-project-alist
         `(("devto"
            :recursive t
            :base-directory ,org-devto-articles-directory
            :base-extension "org"
            :publishing-directory ,org-devto-output-directory
            :publishing-function org-devto-publish-to-article-sync))))
    (org-publish-all t)))

3. 実際にorg-modeで記事を書く

DEVTO_IDDEVTO_SLUG は実際にブログ記事を生成してからじゃないと取得できない値なので注意。

管理画面で手動で記事を作成してから入力するフローになるようだ。

:PROPERTIES:
:ID:       51301ebb-2373-0794-838b-44ab40369fc3
:END:
#+TITLE: devto test1 aaaa
#+AUTHOR: takeokunn
#+DESCRIPTION: description
#+TAGS: sandbox
#+DEVTO_ID: 3048601
#+DEVTO_SLUG: devto-test-ol9
* testhogehogeho

testfdsafsafafa

#+begin_src bash
  echo "hello world"
#+end_src

* zzzzzzzzzzz

#+begin_quote
fdasfasfa
#+end_quote

4. GitHub Actionsで同期する

dev.toの記事もGitHubで管理してみた - Zenn を参考にGitHub Actionsを設定した。

同期してるMarkdownがどういう状況か可視化する為に devto ブランチを作成する運用にしてる。

https://github.com/takeokunn/blog/tree/devto

build-devto:
  runs-on: ubuntu-latest
  needs: ci
  defaults:
    run:
      working-directory: ./devto
  steps:
    - uses: actions/checkout@v6
    - name: Setup nix
      uses: ./.github/actions/setup-nix
      with:
        cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
    - name: Build devto (Article Sync format)
      run: nix build .#build-devto
    - name: Prepare articles directory
      run: |
        mkdir -p public/
        rsync -a --chmod=u+w result/ public/
    - name: Sync articles to dev.to
      uses: calvinmclean/article-sync@v1.3.4
      with:
        api_key: ${{ secrets.DEV_TO_TOKEN }}
        article_path: ./devto/public
        type: synchronize
        gh_token: ${{ secrets.GITHUB_TOKEN }}
    - name: Create devto branch
      uses: peaceiris/actions-gh-pages@v4
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./devto/public
        publish_branch: devto
        force_orphan: true

得られた結果・所感

無事テスト記事の投稿ができた。

今後の展開・検討事項

英語記事を大量に書いて英語力を上げたい。