【Laravel】簡単にマークダウン (Markdown) を使用する

Laravel Markdown等で検索した際に、パッケージを追加してマークダウンを表示している記事を見かけるが

Laravel のデフォルトでメール機能(Mailable)があり、それはマークダウンを使用できる
マークダウンをHTMLに変換できる機能を持っている（はず）
それを使えばいいのではと思ったので、やってみた


#やりかた

`Illuminate\Mail\Markdown`に`static function parse`というのがあるのでそれをつかってやる

```php:Controller

use Illuminate\Mail\Markdown;

class HogeController extends Controller
{
    public function index()
    {
        $text = <<< EOM
    # 見出し h1
    ## 見出し h2
    ### 見出し h3
    #### 見出し h4
    ##### 見出し h5
    ###### 見出し h6
    **太字**
    - リスト
    - リスト
        - リスト
    - [ ] チェックボックス
    - [x] チェックボックス
    - [ ]

    | Left align       |       Right align |    Center align    |
    |:-----------------|------------------:|:------------------:|
    | This             |              This |        This        |
    | column           |            column |       column       |
    | will             |              will |        will        |
    | be               |                be |         be         |
    | left             |             right |       center       |
    | aligned          |           aligned |      aligned       |
    EOM;



        // 変換
        dd(Markdown::parse($text));
    }
}
```

結果
![000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174757/efe13bf3-c3e7-7c04-79bf-7dc3028f92ef.jpeg)

##入力された内容から変換

普通に取得したデータをparseしてあげる

```php
public function index()
{
    $post = Post::find(1);
    // 入力をhtmlspecialcharsのヘルパe()でサニタイズしておく
    $markdown = Markdown::parse(e($post->content));
    // return $markdown;
    // return view('blade',compact('markdown'));
}

// bladeで表示する場合
{{ $markdown }}
```

モデルにアクセサとして定義しておくのも良い

##HTMLは使いたいけどXSSは考慮したい

Laravel 5.5と6.xで確認したが
5.5だと内部的にParsedownを使用していたが
6.xだとcommonmarkに変更されている

```php:Laravel5.5
    /**
     * Parse the given Markdown text into HTML.
     *
     * @param  string  $text
     * @return \Illuminate\Support\HtmlString
     */
    public static function parse($text)
    {
        $parsedown = new Parsedown;

        return new HtmlString($parsedown->text($text));
    }
```

```php:Laravel6.x
    /**
     * Parse the given Markdown text into HTML.
     *
     * @param  string  $text
     * @return \Illuminate\Support\HtmlString
     */
    public static function parse($text)
    {
        $environment = Environment::createCommonMarkEnvironment();

        $environment->addExtension(new TableExtension);

        $converter = new CommonMarkConverter([
            'allow_unsafe_links' => false,
        ], $environment);

        return new HtmlString($converter->convertToHtml($text));
    }
```

commonmarkは[ドキュメントによると](https://commonmark.thephpleague.com/1.4/extensions/disallowed-raw-html/)下記のタグだけ無効化してくれる

```
<title>
<textarea>
<style>
<xmp>
<iframe>
<noembed>
<noframes>
<script>
<plaintext>
```

なので、

適当にフォルダを作成し、Markdownクラスのparseだけパクってくれば良い

```php:Markdown

namespace App\Services;

use Illuminate\Support\HtmlString;
use League\CommonMark\CommonMarkConverter;
use League\CommonMark\Environment;
use League\CommonMark\Extension\Table\TableExtension;
// 追加
use League\CommonMark\Extension\DisallowedRawHTML\DisallowedRawHTMLExtension;

class Markdown
{
    public static function parse($text)
    {
        $environment = Environment::createCommonMarkEnvironment();

        $environment->addExtension(new TableExtension);
        // 追加
        $environment->addExtension(new DisallowedRawHTMLExtension());

        $converter = new CommonMarkConverter([
            'allow_unsafe_links' => false,
        ], $environment);

        return new HtmlString($converter->convertToHtml($text));
    }
}
```

`'allow_unsafe_links' => false`
次のプロトコルのいずれかを使用するリンクを解析およびレンダリングしないようにするものですのでfalseのまま。

 - javascript:
 - vbscript:
 - file:
 - data:（data:imagepng、gif、jpeg、またはwebp形式を除く）
 
## GitHub風のマークダウンを使いたい

ひとつ上で作ったparse処理に
`League\CommonMark\Extension\GithubFlavoredMarkdownExtension;`をuseして

```
$environment->addExtension(new GithubFlavoredMarkdownExtension());
```
をついかする。