Marpをカスタマイズして爆速スライド開発環境を手に入れよう

## はじめに

みなさん、Marp使ってらっしゃいますか？

いいですよね、Marp。

今回は、**ただVSCodeの拡張機能を入れるだけでも便利なMarpをさらにカスタマイズしてテンプレートリポジトリにして公開してみた話**です。

## まず、成果物

https://github.com/Gityosan/marp-slide-template

是非cloneして使ってみてください。

## そもそもやりたかったこと

これまで簡易的なスライドはMarpで作り、ちょっと凝ったデザインのスライドはFigmaで作っていたが、Figmaでexportするとスライド一枚ずつexportされてしまい、それらを結合して、一枚ずつexportされたpdfを削除して、、、と面倒だった。

#### Marpでまとめて作ってしまおう！

目標はこれまでFigmaで作っていたスライドをMarpで再現すること

↓今回目標とするFigmaで作っていたスライドは以下のようなデザイン↓

![sample_slide1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2769277/434a704e-b59e-1d74-62dc-90b75984bbd1.png)
![sample_slide2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2769277/446fd8ff-6790-b237-b2c0-dd9da0e209d7.png)
![sample_slide3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2769277/110f54b3-496f-a429-95fa-c591976bfba5.png)
![sample_slide4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2769277/99b91577-dd8f-2d25-3077-64331519d775.png)

## 作業手順

1. リポジトリ＆フォルダ作成
2. marp-cli導入とコマンド用意
3. scss postcss prettier stylelint導入
4. カスタムテーマの作成

### リポジトリ＆フォルダ作成

githubでリポジトリ作ったら下ろしてきて、`npm init`打って、フォルダを作る

構成はこんな感じ

```
marp-slide-template
├ .vscode
├ markdown
├ images
├ style
│ ├ css
│ └ scss
├ pdf
├ pptx
└ package.json
```

個人的にpdf形式とpptx形式の時で出力先を分けたかったのでそれぞれフォルダを用意しているがもちろんまとめて`output`フォルダなどとしても良い。

### marp-cli導入とコマンド用意

`@marp-team/marp-cli`を導入してpackage.jsonに各種コマンドを用意します

```bash
npm install -D @marp-team/marp-cli
```

```json
{
  "scripts": {
    "new": "sh -c 'sed -e \"s/: \\(.*\\)#\\(.*\\)/: \\1/\" markdown/template.md > markdown/$([ \"$1\" != \"\" ] && { echo \"$1\";true; } || { uuidgen | cut -c1-2,25-36 | tr \"[:upper:]\" \"[:lower:]\"; }).md' --",
    "pdf": "sh -c 'file=\"$1\" && title=$(sed -n \"s/title: \\(.*\\)/\\1/p\" \"$file\" | sed -n \"s/^.//p\" | sed -n \"s/.$//p\") && marp \"$file\" -o \"pdf/$title.pdf\"' --",
    "pptx": "sh -c 'file=\"$1\" && title=$(sed -n \"s/title: \\(.*\\)/\\1/p\" \"$file\" | sed -n \"s/^.//p\" | sed -n \"s/.$//p\") && marp \"$file\" -o \"pptx/$title.pptx\"' --"
  }
}
```

な、長い、、、、
一つずつ見ていきます。

#### newコマンド

```bash
sh -c 'sed -e "s/: (.*)#(.*)/: \1/" markdown/template.md > markdown/$([ "$1" != "" ] && { echo "$1";true; } || { uuidgen | cut -c1-2,25-36 | tr "[:upper:]" "[:lower:]"; }).md' --
```

<br>

1. sedコマンドでtemplate.mdを複製して新たなmdファイルを作成します
2. `s/: (.*)#(.*)/: \1/`のところでmdファイル最初の設定値の箇所のコメントアウトを取り除きます
3. `markdown/template.md > markdown/${new file name}.md`の箇所で新しいmdファイルに複製します
4. `[ "$1" != "" ] && { echo "$1";true; } || { uuidgen | cut -c1-2,25-36 | tr "[:upper:]" "[:lower:]"; }`の箇所は擬似的な三項演算子を用いています。<br>引数にファイル名が与えられればそれを採用し、与えられなければ12桁の英数字から成る文字列を採用します

#### pdf / pptxコマンド

```bash
sh -c 'file="$1" && title=$(sed -n "s/title: (.*)/\1/p" "$file" | sed -n "s/^.//p" | sed -n "s/.$//p") && marp "$file" -o "pdf/$title.pdf"' --
```

```bash
sh -c 'file="$1" && title=$(sed -n "s/title: (.*)/\1/p\" "$file" | sed -n "s/^.//p" | sed -n "s/.$//p") && marp "$file" -o "pptx/$title.pptx"' --
```

<br>
この二つのコマンドはやっていることは殆ど同じです

1. `file="$1" && title=$(sed -n "s/title: (.*)/\1/p\" "$file" | sed -n "s/^.//p" | sed -n "s/.$//p")`の箇所で対象となるmdファイルのパスと出力するファイルの名前を変数に格納します
2. `sed -n "s/title: (.*)/\1/p\" "$file" | sed -n "s/^.//p" | sed -n "s/.$//p"`の箇所でmdファイルの設定値のtitleの箇所を抜き出し、前後に付いている`'`または`"`を取り除きます(もっといい処理の仕方があるはずですが、一旦出来たので出来たのでこれで良しとしています)
3. marpコマンドで出力します（[オプション一覧はこちら](https://github.com/marp-team/marp-cli#options)）

<br>

### scss/postcss/prettier/stylelintの導入

scssをcssに変換して、postcssにautoprefixerとcssnanoを入れて最適化しています
stylelintとprettierも入れて`.vscode/settings.json`で保存時に自動整形するようにしています。
いつか、vscode以外のIDEを使っていても自動整形できるようにhuskyとlint-stagedも導入したいですね...

### カスタムテーマの作成

基本的にレイアウトなどのカスタマイズはbase.scssにまとめ、base.scssを継承した各種カラーテーマで色を選択できるようにしました。現在目次用index-sectionクラス、色反転のinvertクラス、フッターを参考文献等を表示するためのthesis-footerクラスを用意しています。

また、いつも色選びで悩むため予めカラーのセットを複数用意しました。(現在6種類)
今後も良いカラーセットを見つけたら追加していきます！

## 完成品

当初やりたかったことの大半はできました

https://www.slideshare.net/ssuser1ca6b8/creating-a-more-efficient-development-repository-with-marp-slide-development-librarypdf

## 今回やってみて良かったこと

#### 1. shellの理解がちょっとできた

- 特に今回使った`sed`コマンドや擬似的な三項演算子の汎用性の高さを身にしみて感じたのでこれからも多用していきたい。

#### 2. scssとpostcssの理解ができた

- いつもvueやnuxtを使っている中で勝手に設定しておいてくれるため改めて環境構築する機会は意外と無かった。

#### 3. 気楽にスライドが作れるようになった

- これが一番大きい。スライドを作る際に悩むことが一気に減った。

## 最後に

この記事をご覧のみなさんも是非素敵なMarpライフを！

## 2023/10/06 追記

上記解説していたコマンドですが、バグが見つかったり、追加で実現したいことがあったり、安定性を増したいということになり、ちゃんとshファイルを作ってそこに切り分けることにしました。

### new コマンド

- 引数の数が一つでない場合にログを出して終了するようにしました。
- 以前はsedコマンドでファイル内全体を対象にコメントアウトの削除をしていましたが、本文中の#マーク以下の部分（見出し等）を間違って削除してしまわないように対象範囲をyamlフロントマター内に限定するように変更しました。

https://github.com/Gityosan/marp-slide-template/blob/main/bin/new.sh

### pdf / pptx コマンド

- 引数の数が一つでない場合にログを出して終了するようにしました。
- yamlフロントマター内のtitleを抜き出す際の正規表現をより汎用性のある形に変更しました。
- 以前はyamlフロントマター内のtitleに設定されている値をファイル名として採用していました。ただ、titleの値が空文字列の時に変になってしまっていたので、空文字列のときはmarkdownファイルのファイル名を代わりに採用するように変更しました。

https://github.com/Gityosan/marp-slide-template/blob/main/bin/pdf.sh

https://github.com/Gityosan/marp-slide-template/blob/main/bin/pptx.sh

合わせて呼び出し方法も変更しています。

```json
// package.json
{
  "scripts": {
    "new": "sh ./bin/new.sh",
    "pdf": "sh ./bin/pdf.sh",
    "pptx": "sh ./bin/pptx.sh"
  }
}
```