Quarto + TypstでCVを自動で作る

Quarto + TypstでCV作成を自動化した
CSVファイルからQuartoとGitHub Actionsを用いて, CVを自動で生成するワークフローを作りました.

これを実現するためにQuartoのTypstテンプレートとしてquarto-awesomecv-typstとRによるサポートパッケージtypstcvも開発しました. 同様のプロジェクトとしてRmarkdown + TinyTexを用いるmitchelloharawild/vitaeがありますが, Quarto + Typstを用いることで, より高速なCV作成が可能になります.
私自身のCVとして実際に運用しているので, コードは以下のレポジトリを参照してください.
なぜTypstを使うのか
Typstは
とはいえTypstはまだ開発途上であり, ジャーナルに投稿する際は
CVの作成
インストール
typstcvは現在R-universe (かGitHub) のみで提供されているので以下のコマンドでインストールします.
install.packages("typstcv", repos = "https://kazuyanagimoto.r-universe.dev")
Quartoテンプレートから始めるのがもっとも簡単です.
quarto use template kazuyanagimoto/quarto-awesomecv-typst
このコマンドを新しいディレクトリ上に, typstのテンプレートとQuartoのテンプレートが作成されます. デフォルトではエントリーが以下のようになっています.
```{=typst}
#resume-entry(
  title: "On the Electrodynamics of Moving Bodies",
  location: " Annalen der Physik",
  date: "September 1905"
)
```
これを後述するtypst::resume_entry()関数を用いて置き換えていきます.
YAMLの設定

基本情報
author:
  firstname: Albert
  lastname: Einstein
  address: "Rämistrasse 101, CH-8092 Zürich, Switzerland, Zürich"
  position: "Research Physicist ・ Professor"
  contacts:
    - icon: fa envelope
      text: ae@example.com
      url: "mailto:ae@example.com"
    - icon: PATH_TO_ICON/icon.svg
      text: example.com
      url: https://example.com
アイコンはFont Awesomeのフリーのアイコンをfaを前につけることで指定することができます.[1] また, Font Awesomeが対応していないアイコンであっても, SVGファイルを指定することで利用することができます. Google scholarなどは, Academiconsなどからダウンロードできますし, 他にもBootstrap IconsやSimple Iconsなどがあります (Zennのロゴもありますね!)
フォント & カラー
style:
   color-accent: "516db0"
   font-header: "Roboto"
   font-text: "Source Sans Pro"
format:
  awesomecv-typst:
    font-paths: ["PATH_TO_FONT"]
アクセントカラーとフォントを指定することができます. システムにインストールされているフォントを用いることができますが, GitHub Actionsなどでフォントファイルをレポジトリに含める場合は, パスを指定することで利用することができます.
コンテンツの設定
 typstcv::resume_entry()
resume_entry()関数を用いて, データフレームからコンテンツを生成することができます.
educ
#>               title            location        date          description
#> 1  Ph.D. in Physics Zürich, Switzerland        1905 University of Zürich
#> 2 Master of Science Zürich, Switzerland 1896 - 1900                  ETH
```{r}
#| output: asis
educ |>
  resume_entry(
    title = "title",
    location = "location",
    date = "date",
    description = "description"
)
```

QuartoのRコードチャンクでは, output: asisを必ず指定してください. これは, resume_entry()が生成したTypstコードを認識させるために必要です (以下の説明では省略します.) なお, データフレームの列名がtitleやlocationのように引数名と一致している場合は, 引数を省略することができます.
また, details引数を用いて, 箇条書きのエントリーを作ることができます. 以下の例では, awardデータフレームのdetail1とdetail2の列を箇条書きにして出力しています.
award
#>                    title          location date         description
#> 1 Nobel Prize in Physics Stockholm, Sweden 1921 For his services to
#>               detail1                                          detail2
#> 1 Theoretical Physics Discovery of the law of the photoelectric effect
resume_entry(award, details = c("detail1", "detail2"))

箇条書きの項目が多い場合は, 以下のようにgrep()を用いるのが簡便でしょう.
resume_entry(award, details = grep("^detail", names(award)))
 typstcv:date_formatter()
date_formatter()関数を用いて, 日付順にソートし指定の形式で出力することができます.
work
#>                 title            location      start        end
#> 1 Technical Assistant   Bern, Switzerland 1902-01-01 1908-01-01
#> 2    Junior Professor   Bern, Switzerland 1908-01-01 1909-01-01
#> 3 Associate Professor Zürich, Switzerland 1909-01-01 1911-01-01
#>             description
#> 1 Federal Patent Office
#> 2    University of Bern
#> 3  University of Zürich
work |>
  format_date(
    start = "start",
    end = "end",
    date_format = "%Y",
    sep = "->",
    sort_by = "start"
  ) |>
  resume_entry()

GitHub Actions & GitHub Pages
Quartoドキュメントであるため, GitHub Actionsを用いて簡単にビルドし, GitHub Pagesで公開することができます.
データの用意
ローカルでコンパイルするのであれば, Google Spreadsheetなどからデータを取得するなどの方法がありますが[2], GitHub Actionsを用いる場合は, CSVファイルを用いるのが簡便でしょう. 更新の際も, CSVファイルに新しい行を追加するだけでよいです.
degree,start,end,institution,location
M.Sc.,2016-04-01,2019-03-31,University of Zurich,Zurich
Ph.D.,2019-04-01,2022-03-31,University of Zurich,Zurich
```{r}
#| output: asis
educ <- read.csv("data/education.csv",
                 colClasses = c("character", "Date", "Date",
                                "character", "character"))
educ |>
  format_date(end = "end", sort_by = "start") |>
  resume_entry(title = "degree",
               description = "institution")
```
GitHub Actionsの設定
on:
  workflow_dispatch:
  push:
    branches: main
name: Quarto Publish
jobs:
  build-deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Check out repository
        uses: actions/checkout@v4
      
      - name: Set up Quarto
        uses: quarto-dev/quarto-actions/setup@v2
      - uses: r-lib/actions/setup-r@v2
      - uses: r-lib/actions/setup-renv@v2
      - name: Render and Publish
        uses: quarto-dev/quarto-actions/publish@v2
        with:
          target: gh-pages
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ビルドするためには, 少なくともrmarkdownとtypstcvのパッケージがインストールされている必要があります. 私はrenvを用いてパッケージを管理しているため, r-lib/actions/setup-renv@v2を実行しています.
なおrenvを用いたパッケージ管理に関しては以前の記事で解説をしています.
GitHub Pagesの設定
_quarto.yml
GitHub Pagesで必要なファイルだけをdocsディレクトリに出力するために, _quarto.ymlを以下のように設定します.
project:
  type: default
  output-dir: docs
リダイレクトの設定
上記の設定だけでも, https://username.github.io/repo/cv.pdf でアクセスすることができますが, https://username.github.io/repo/index.html からリダイレクトすることで, https://username.github.io/repo/ でアクセスすることができるようになります. GitHub PagesのJekyllプラグインを用いて設定します.
---
redirect_to: "cv.pdf"
---
plugins:
  - jekyll-redirect-from
なお私の場合は, GitHub Pagesで自分のウェブサイトをホストし, カスタムドメインを設定しているため, アドレスが https://kazuyanagimoto.com/cv/ になっています.
おわりに
以上で私がQuarto + Typstを用いてCVをCSVファイルからGitHub Actions上でビルドする方法を解説しました. CSVからCVを自動作成することで, データの更新が容易になりますし, バージョン管理もしやすくなります.
このquarto-awesomecv-typstは, Byungjin Park氏のAwesome-CVのPaul Tsouchlo氏によるTypst実装をさらに改変したものです. 至らない点があるかと思いますので, GitHub Issuesからお知らせいただけると幸いです. Pull Requestも歓迎です.
- 
duskmoon314/typst-fontawesomeを用いて実装しているのですが, いくつかのアイコンは正しく表示できないようです. その場合は, SVGファイルを指定することで対応することができます. ↩︎
 - 
googlesheets4を用いるなど.datadrivencvなどもあります ↩︎ 
Discussion