PHPでMarkdownをいい感じにやる

Markdown方言

Markdownの方言は
Markdown
CommonMark
Github flavored Markdown
Markdown Extra
だいたいこの4つから選ぶことになると思います。

CommonMark

  • Markdown系のスタンダード(になるかもしれない)
  • 現在も仕様策定中で2017年内にv1.0.0がリリース予定
  • 公式のPHPの実装がある

Markdown

  • 本来の「Markdown」といった場合はこのMarkdown
  • 機能は少ない
  • 実装はいくつかある

Github flavored Markdown

  • Githubで利用できるMarkdown
  • URLの自動リンクやテーブルが利用可能
  • 行末にスペース2つを入れずに、改行するだけで<br>が生成されるのが特徴
  • PHPでの実装は単独では見つからない

Markdown Extra

  • テーブルに加え定義リスト(まさにこのリストの部分)が利用可能
  • 多機能で実装も多い
  • PHPで実装されている

ライブラリ

今回はcebe/markdownを選びました。

cebe/markdownの特徴はMarkdownGithub flavored MarkdownMarkdown Extraの3つが利用可能ですが、Markdown Extraについては定義リストなど実装されていない文法があるようです。
ただし、拡張が簡単なので、今回はこれを利用します。

実装

まずはcomposerでインストールします。

composer require cebe/markdown

下記のコードで簡単にHTMLに変換することができます。

$markdown_string = '# Hello, Markdown';
$converter = new \cebe\markdown\MarkdownExtra();
echo $converter->parse($markdown_string);
<h1># Hello, Markdown</h1>

ただ、Markdown Extraは改行のみだと<br>が生成されず、行末にスペースを2つ入れる必要があるので、拡張してみましょう。

class MyMarkdown extends \cebe\markdown\MarkdownExtra{
	//同ライブラリのGithub flavored用の実装と同一
	protected function renderText($text){
		if ($this->enableNewlines) {
			$br = $this->html5 ? "<br>\n" : "<br />\n";
			return strtr($text[1], ["  \n" => $br, "\n" => $br]);
		} else {
			return parent::renderText($text);
		}
	}
}

$markdown_string = '# Hello, Markdown';
$converter = new MyMarkdown();
echo $converter->parse($markdown_string);

簡単ですね。これをうまく利用するとWordPressでも実装することができます。
WordPressへの組み込みはまたいずれ…。

Prerender SPA Plugin を使ってSPAサイトのSEO対策をする

株式会社なすびのウェブサイトは、Vue.jsを用いたSPAで作られています(2017年4月現在)。

コーポレートサイトのような情報の提供に重きを置くサイトで、SPAのアーキテクチャを使うことはSEOの面からあまり適した用途であるとは言えません。

それは、GoogleボットこそJSを実行してからパースしてくれるので問題にはならないのですが、FacebookなどのSNSにシェアされた場合は未だにJSの実行までしてくれないからです。

これを解決するためには、サーバーからのレスポンスでHTMLを返す必要性が絶対的にあるのですが、いかんせんSSRを前提に環境の構築を考えると、サーバサイドでNode.jsを噛ませる必要があったりなど、なかなかに敷居が高いのです。

しかしコーポレートサイトのような、ページ数も動的コンテンツも少ない小規模サイトであれば、プリレンダリングという選択肢もあります。

今回はwebpackプラグインでサクッとプリレンダリングする方法の紹介です。

Prerender SPA Plugin
https://github.com/chrisvfritz/prerender-spa-plugin

このプラグインを使って、webpackのbuild過程で静的HTMLを書き出してしまいます。

// webpack.conf.js
var Path = require('path')
var PrerenderSpaPlugin = require('prerender-spa-plugin')

module.exports = {
  // ...
  plugins: [
    new PrerenderSpaPlugin(
      // Absolute path to compiled SPA
      Path.join(__dirname, '../dist'),
      // List of routes to prerender
      [ '/', '/about', '/contact' ]
    )
  ]
}

上記のように保存先とエンドポイントを設定してbuildすると、下記3ファイルが書き出されます。

/index.html
/about/index.html
/contact/index.html

これらのファイルをウェブサーバーに配置すると、当然下記URLでbuildされたHTMLがレスポンスされるのですが、

http://example.com/
http://example.com/about/
http://example.com/contact/

SPAとしてリンクを辿ってaboutページに遷移すると、URLは /about となります。

/about/about/ は違うファイルを指しているため、この状態でリロードすると404になってしまいます。
これを回避するためには、 /about にリクエストが来たら /about/ へリダイレクトする.htaccessを置いてあげれば良いのです

<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png|jpg)
RewriteRule (.*) / [L]
</ifModule>