markdown-pdf でログ等の装飾をなくす

Markdown で書いたドキュメントを PDF に変換する際には markdown-pdf を利用しています。

通常プログラムのコード等ではシンタックスハイライトで見やすくなるはずの装飾が、ログではかえって逆効果の場合があります。そうした場合に装飾を削るための Tips をメモしておきます。

経緯

markdown-pdf はコードの装飾に highlight.js を利用しているようですが、これがかえって逆効果のことも。

例えば、以下のようなログがあったとします。

[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00493: SIGUSR1 received.  Doing graceful restart
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [lbmethod_heartbeat:notice] [pid 27078:tid 000000000000000] AH02282: No slotmem from mod_heartmonitor
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00489: Apache/X.X.XX (centos) OpenSSL/Y.Y.YY configured -- resuming normal operations
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [core:notice] [pid 27078:tid 000000000000000] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'

これを以下のような Markdown として記述して markdown-pdf にかけます。

```
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00493: SIGUSR1 received.  Doing graceful restart
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [lbmethod_heartbeat:notice] [pid 27078:tid 000000000000000] AH02282: No slotmem from mod_heartmonitor
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00489: Apache/X.X.XX (centos) OpenSSL/Y.Y.YY configured -- resuming normal operations
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [core:notice] [pid 27078:tid 000000000000000] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
```

すると……

言語指定しない場合の pre code の表示
言語指定しない場合の pre code の表示

文字色が変わったり、数字は緑色になっていたりします。このくらいのログならば良いのですが、もっと長いものや、別のフォーマットのログだと次の bash 指定した際のログのように意図しない場所で文字サイズが変わってしまったりするので、非常に見づらくなってしまうケースもありました。

```bash
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00493: SIGUSR1 received.  Doing graceful restart
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [lbmethod_heartbeat:notice] [pid 27078:tid 000000000000000] AH02282: No slotmem from mod_heartmonitor
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00489: Apache/X.X.XX (centos) OpenSSL/Y.Y.YY configured -- resuming normal operations
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [core:notice] [pid 27078:tid 000000000000000] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
```
言語を bash に指定した場合の pre code の表示
言語を bash に指定した場合の pre code の表示

対処

今回は自前 css と独自言語設定でこれらの装飾を外しました。

```plain
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00493: SIGUSR1 received.  Doing graceful restart
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [lbmethod_heartbeat:notice] [pid 27078:tid 000000000000000] AH02282: No slotmem from mod_heartmonitor
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [mpm_event:notice] [pid 27078:tid 000000000000000] AH00489: Apache/X.X.XX (centos) OpenSSL/Y.Y.YY configured -- resuming normal operations
[DDD mmm dd hh:ii:ss.mmmmmm yyyy] [core:notice] [pid 27078:tid 000000000000000] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
```

言語指定に独自の plain を指定。

pre {
    padding: .5rem;
}
pre code {
    margin: 0;
    padding: 0;
    white-space: pre;
    border: none;
    background: transparent;
}
pre[class*="language-plain"],
code[class*="language-plain"],
pre[class*="language-plain"] > *,
code[class*="language-plain"] > * {
    color: #000 !important;
    font-size: 0.8rem !important;
    font-weight: normal !important;
    font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
}

ついでに Scss 版も。

pre {
    padding: .5rem;
    code {
        margin: 0;
        padding: 0;
        white-space: pre;
        border: none;
        background: transparent;
    }
}
pre[class*="language-plain"],
code[class*="language-plain"] {
    &, & > * {
        color: #000 !important;
        font: {
            size: 0.8rem !important;
            weight: normal !important;
            family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
        }
    }
}

この css (仮に ./src/md/css/style.css とします)を以下のように markdown-pdf に処理させます。

const markdownpdf = require('markdown-pdf');

markdownpdf(
    {
        cssPath: './src/md/css/style.css',
        remarkable: {
            html: true,
            breaks: true
        }
    }
)
.from('./src/md/hoge.md')
.to('./dist/hoge.pdf');

これで以下のような表示が得られました。

言語を plain (独自指定) に指定した場合の pre code の表示
言語を plain (独自指定) に指定した場合の pre code の表示

とりあえず読めるようにはなったかな、と。

参考

余談

今回の対処をする際に久々に npm で markdown-pdf を確認したのですが、いくつかの依存パッケージが out of date になってしまっていますね……これはそもそも他の方法を考えなければならない気がします。というか未だに PhantomJS を使っているっぽい……?

検索したところ、 md-to-pdf が引っかかりました。アクティブそうなのでこちらに乗り換えるのも検討ですかね。

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。