PowerPoint(pptx)をtextlintする

## はじめに

これは、「[富士通クラウドテクノロジーズ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/fjct)」の16日目の記事です。
昨日は @yoshitsugumi さんの[病児保育施設の需要と供給の実態を可視化しようとして失敗した話](https://www.yoshitsugumi.com/entry/2019/12/15/201621)でした。

データ分析する際はデータソースが重要なのはいわずもがなですが、よいデータを集めるのが困難だったりしますね。

さて、私の担当として、「第二回[技術書同人誌博覧会](https://gishohaku.dev/)の話を書くかも」 と宣言はしていました。実際、先日サークル参加をしてきまして、大変楽しめたこともあって感想や今後の技術書同人誌イベントのあり方について思うところを書こうとも思ったのですが、それは別の機会にして今回は「PowerPoint(pptx)をtextlintする」という全く関係ないテーマについて書きたいと思います。

## モチベーション

さて、みなさんは仕事でPowerPoint(pptx)を扱う機会はあるでしょうか。私はあります。

私の普段の業務では、通常の社内文書であれば基本的にテキストベースで Gitlab ないしは Slack でほぼ済みます（ほぼ）。テキストベースであれば修正が簡単ですし、変更履歴や差分管理もやりやすく、場合によってはスクリプトで加工することも容易です。今回の本題である `textlint` もテキストベースのフォーマットに対応しています。また、図が必要なケースもPlantUML等を使えば業務で必要な範囲では概ねカバーできます。逆に言うと、社内文書をテキストベースで書かない理由があまりありません。ちなみに、好きな軽量マークアップ言語は [AsciiDoc](http://asciidoc.org/) です。

が、それでもやはりPowerPointを使う機会はしばしばあります。たとえば顧客に提示するための資料であったり、限られた時間で情報を共有しなければいけなかったり、短い時間でポンチ絵を仕立て上げたかったり。特に顧客に提示する場での説明は、何らかのスライドは必要とされるでしょう。もちろん、PowerPoint以外にもスライドを作成するソフトウェアは多く存在し、テキストからpptxを生成するものも実用的なものが複数存在します。しかし、 `短時間で見栄えのいい資料を作ることができ` かつ `他の人とも資料が共有しやすい` ソフトウェアとしては、やはりPowerPointが採用されることは多いのではないでしょうか。

顧客向けのスライドで、誤字があったり、日本語の誤りがあったり、用語のブレがあったりすると非常に恥ずかしいですね。そのために、何度も資料を読み返したり、他の人にレビューしてもらったりとすることもあると思います。が、目視でのレビューは非常に時間がかかり、かつ精度も低いです。

そこで、文書校正ツールとして非常に優れている textlint を使うことが考えられます。textlintが使えれば、文章の問題点を一瞬で見つけたり修正することができます。公開されている汎用的なルールが使い回せるだけではなく、社内の用語に合わせた独自のルールを組むこともできます。私もテキストベースの重要な社内文書であれば、CIでtextlintをかけるようにします。

しかしながら、 現在、素のpptxファイルに対して textlint をかけることはできません。このままでは、目視地獄から我々は抜け出すことはできません。つらいですね。

## 対応方針

さて、pptxファイル内の文章に textlint をかけるために実施できるアプローチは大きく分けて2つ考えられます。

- (1) pptxをMarkdownなどのテキストに変換後、textlintにかける
- (2) textlintをpptx対応させるプラグインを作る

(2) のほうがより精度の高い校正が実現できると思われますが、少々ハードルが高そうです。そこで、今回はいったん簡単そうな (1) の方法で試してみます。

## 実際にやってみる

では、方針が決まったところで実際にやってみます。今回の資材は [slidex-textlint-example](https://github.com/heriet/slidex-textlint-example) にまとめているので、必要に応じて参照ください。

### テスト対象のPowerPoint

検証用に下記のスライドを含む pptx ファイルを用意しました。

![hatoba_dummy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77961/776e197b-7890-49d8-7570-769a74814392.png)

みなさんは上記スライドにおいて、どういった誤りがあるか1秒以内にすべてわかるでしょうか？もしわかるなら、今後は人間textlintとして生きていくことをオススメします。人間textlintになれない人は、これから提示する方法を試す価値があるでしょう。

なお、この資料は今回の検証用に1から作成した文章であり、実際に業務で使われているものとは異なります。

### PowerPointをMarkdown化する

まず、このpptxファイルを何らかの方法でMarkdownに変換します。pptxといえど中身は復元可能なテキストが詰められているので、テキストを抽出したり分析ができるソフトウェアは多数存在します。ただ、変換精度がいまいちなものも多くあります。今回は、私が調査した中では最も都合が良さそうな [datalorax/slidex](https://github.com/datalorax/slidex) で変換を行います。この slidex は Rで作られているようです（！）

まず、下記の Dockerfileを用意しました。Rと必要なモジュールをインストールするだけのイメージになります。

```slidex.dockerfile
FROM rocker/r-apt:bionic

RUN apt-get update && \
    apt-get install -y -qq \
    	r-cran-devtools

RUN R -e 'library(devtools); install_github("datalorax/slidex")' && \
    R -e 'install.packages(c("xaringan", "knitr", "kableExtra", "tibble"))'

WORKDIR /work
CMD ["R"]
```

あとは下記のMakefileを作りました。

```slidex.mk
PPTX_NAME=hatoba_dummy
PPTX_FILE=${PPTX_NAME}.pptx

SLIDEX_IMAGE_NAME=slidex
SLIDEX_PPTX_AUTHOR=heriet
TEXTLINT_IMAGE_NAME=textlint

build:
	docker build -t ${SLIDEX_IMAGE_NAME} -f slidex.dockerfile .

convert:
	rm -rf ${PPTX_NAME}
	docker run --rm \
		-v ${PWD}:/work \
		${SLIDEX_IMAGE_NAME} \
			R -e 'library(slidex); convert_pptx(path = "${PPTX_FILE}", author = "${SLIDEX_PPTX_AUTHOR}")'

lint:
	docker run -it --rm \
		-v ${PWD}:/work \
		${TEXTLINT_IMAGE_NAME} \
			${PPTX_NAME}/*

```

基本的に、dockerコマンドを叩くだけですね。slidex は 実行時に pptxのファイル名と同名のディレクトリを作成します。2回目以降の実行時に前回のディレクトリがあると出力できないので、 削除するようにしています。

上記を使って変換してみます。

```shell
$ make -f slidex.dockerfile build
$ make -f slidex.dockerfile convert
```

実行後、下記のような Markdownが出力されました。

```md:hatoba_dummy/hatoba_dummy.Rmd
---
title: ' ニフクラ Hatoba（β）ご紹介資料 '
subtitle: '富士通クラウドテクノロジーズ'
author: heriet
date: 2019-12-15
output:
  xaringan::moon_reader:
  lib_dir: libs
  nature:
    highlightStyle: github
    highlightLines: true
    countIncrementalSlides: false
---
#  ニフクラ hatoba（β）とは 

+ ニフクラが提供する Kuberentes  as a Serivice
+ Web 画面 から簡単に構築・運用が可能になると思います
+ β 提供中で、審査 が 通れば無償で使用することができます

現在は、 β なため限られた機能しか使えませんが、正式版に向けて、鋭意開発中です。

---
#  Kubernetesとは 

+ あああ
+ いいい

```

たしかにスライドの内容がMarkdownになっています。slidexが出力するMarkdownはただのMarkdownではなく remark.js 用の Markdownになっていることもわかります。今回は とにかく textlint にかけられれば良いので、 remark.js 用かどうかはあまり重要ではありません。

変換後の文章を読むと、なぜか元の文章にはないスペースが入っていたりするのですが、いったん大きな問題にはなるほどではなさそうです。

### Markdown に textlint をかける

pptxをMarkdownにすることはできたので、あとは一般のご家庭のお手元にある textlint をいつも通りにかけてもらうだけです。詳細は割愛しますが、気になる方は[slidex-textlint-example](https://github.com/heriet/slidex-textlint-example)を参照ください。

```shell
$ make -f slidex.mk lint
docker run -it --rm \
                -v /Users/sera/work/snippet/pptxlint:/work \
                textlint \
                        hatoba_dummy/hatoba_dummy.md

/work/hatoba_dummy/hatoba_dummy.md
  14:9   ✓ error  hatoba => Hatoba                                                                                                                                            prh
  16:13  ✓ error  Kuberentes => Kubernetes                                                                                                                                    prh
  17:27  error    弱い表現: "思います" が使われています。                                                                                                                     ja-technical-writing/ja-no-weak-phrase
  18:23  ✓ error  "することができます"は冗長な表現です。"することが"を省き簡潔な表現にすると文章が明瞭になります。参考: http://qiita.com/takahi-i/items/a93dc2ff42af6b93f6e0  ja-technical-writing/ja-no-redundant-expression
  20:33  error    一つの文で"、"を3つ以上使用しています                                                                                                                       ja-technical-writing/max-ten
```

textlintの結果から、今回は5つの文章誤りが検出されたことがわかります。 この方法を使えば CLIから簡単にpptxに対してtextlintをかけられますし、手動ではなくCIで実行することも難しくはないでしょう。


## まとめ

今回は `(1) pptxをMarkdownなどのテキストに変換後、textlintにかける` 手法である `slidex + textlint` によって、 pptxへのtextlintを実現することができました。しかし、いくつか課題もあります。

- 行番号などがMarkdownに従うので、pptx上どの位置にあるのかわかりにくい
- 一度 Markdownへの変換を挟むので、情報が落ちる（Markdownの表現力は乏しいので）
- なぜかpptxにはない空白が入ることがある（pptxが悪いのかslidexの仕様なのかは不明）
- 今回の方法だとファイル名の指定が面倒

これらの課題を解決するには、 ` (2) textlintをpptx対応させるプラグインを作る` のアプローチを実施するのが良さそうです。実際ちょっとプラグインを書き始めているのですが、もう少し時間がかかりそうなので、今回はここまでとします。

### 次のアドベントカレンダー

明日は @sasachi1231 さんの「TBD」ということで、なにか書いてくれるようです。普段は mBaaSの企画担当をされている方で、私と同じくゲーム好きな同士なので、どんな内容が飛び出てくるか楽しみです。