CSSを使ってMarkdownを行末のスペースなしで改行
Gatsbyの3への更新の余波シリーズの第1弾。 Markdownの改行を末尾の2つの半角スペースなしに改行してくれるプラグインがGatsby3で動作しなくなりました。 テキスト中の改行は、素直に改行として処理して欲しいので対策することにしました。
結果
html 文中の改行の有効化は white-space: pre-wrap で簡単に実現できました。 Markdownの記事本文が .main_text クラスが当たった div に入っていると仮定して、このような感じです。
.main_text > p {
white-space: pre-wrap;
}
.main_text > p * {
white-space: normal;
}
当ブログで使用している emotion のオブジェクト表記だとこうなります。
const main_text = css({
'> p': {
whiteSpace: 'pre-wrap',
'*': {
whiteSpace: 'normal',
},
},
})
Markdown は文章を段落ごとに p タグの中に入れるので、それのみに適応する形になります。 p は子セレクタではなく子孫セレクタでも問題なかったのですが、安全のために適応範囲を最小にしました。
重要なのは、pre-wrap を子孫要素へ適応させないことです。
対策までの過程
このブログは MarkDown で記述していますが、MarkDown の標準仕様では改行は行末に半角スペース2つをつけないと判定してくれません。 この仕様は、文章を書く上でとても面倒なので、何かしら対策する必要があります。
Gatsby2の時は gatsby-remark-line-breaks というプラグインで対応していました。
インストールして gatsby-config に記述するだけで、Contentful から所得した Markdown 内の改行を処理してくれていましたが、これがGatsby3では動かなくなりました。 このプラグインを gatsby-config.ts で読み込むとビルドが失敗します。
CSSのwhite-spaceを使う
この問題、プラグインなしでもCSS だけで対応できました。
「white-space」というのは、空白文字についてだけの設定だけに聞こえる名前ですが、改行の処理も内包しているというのがちょっと分かりづらいですね。 6種類の設定がありますが、使いそうなのはデフォルトの normal と pre-wrap の2つだけかなと思いました。 normal だと通常の html と同じように改行は無視され、pre-wrapなら brタグなしで改行できる。とりあえずこれだけ覚えていれば問題ないでしょう。
pre-wrap を記事に当てるだけで Markdown 内の改行を改行として処理してくれます。
white-space: pre-wrapの落とし穴
まずは当ブログをサンプルに、white-space: pre-wrap の適応前の状態です。
段落内での改行が全て消えてしまっています。
次が、記事全体に white-space: pre-wrap を適応した状態です。
改行は処理されていますが、画像のアスペクト比が狂っています。 全体に pre-wrap が適応されていると、Gatsbyのプラグインが生成する画像に不具合が出るようです。
なので、子孫要素への pre-wrap の適応を打ち消す必要があったんですね。
これで想定通りの表示になりました。