[Laravel9]Markdownエディタ”EasyMDE”を使ってみた with Tailwind CSS
- 公開日:2022/7/19
この記事は最終更新日から2年以上が経過しています。
Laravel 9 でマークダウンエディタのEadyMDEを使ってみました。
環境
- Laravel 9
- Vite
- Laravel Breeze
- Tailwind CSS
Tailwind CSS Typographyをインストール
マークダウンエディタを導入した場合、フロントやプレビューでは記述内容をHTML形式で取得して表示することになりますが、Tailwind CSSはブラウザの標準スタイルをリセットしてしまうので、tailwind CSS Typographyというプラグインをマークダウンエディタ導入前にインストールしておきます。
$ npm install -D @tailwindcss/typography
tailwind.config.jsに以下を記述し、プラグインを追加します。
const defaultTheme = require('tailwindcss/defaultTheme');
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
],
theme: {
extend: {
fontFamily: {
sans: ['Nunito', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')],
};
そして、run vite
$ npm run dev
マークダウンエディタをインストール
いよいよマークダウンエディタをインストールします。
$ composer require graham-campbell/markdown:^14.0
vendor assets を公開します。
どのprovider または tag のファイルか聞かれるので、とりあえず”全て”と答えました。
$ php artisan vendor:publish
Which provider or tag's files would you like to publish?:
[0 ] Publish files from all providers and tags listed below
[1 ] Provider: GrahamCampbell\Markdown\MarkdownServiceProvider
[2 ] Provider: Illuminate\Foundation\Providers\FoundationServiceProvider
[3 ] Provider: Illuminate\Mail\MailServiceProvider
[4 ] Provider: Illuminate\Notifications\NotificationServiceProvider
[5 ] Provider: Illuminate\Pagination\PaginationServiceProvider
[6 ] Provider: Laravel\Sail\SailServiceProvider
[7 ] Provider: Laravel\Sanctum\SanctumServiceProvider
[8 ] Provider: Laravel\Tinker\TinkerServiceProvider
[9 ] Provider: Spatie\LaravelIgnition\IgnitionServiceProvider
[10] Tag: flare-config
[11] Tag: ignition-config
[12] Tag: laravel-errors
[13] Tag: laravel-mail
[14] Tag: laravel-notifications
[15] Tag: laravel-pagination
[16] Tag: sail
[17] Tag: sail-bin
[18] Tag: sail-docker
[19] Tag: sanctum-config
[20] Tag: sanctum-migrations
> 0
Copied Directory [/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/views] To [/resources/views/errors]
Copied Directory [/vendor/laravel/framework/src/Illuminate/Notifications/resources/views] To [/resources/views/vendor/notifications]
Copied Directory [/vendor/laravel/framework/src/Illuminate/Pagination/resources/views] To [/resources/views/vendor/pagination]
Copied File [/vendor/graham-campbell/markdown/config/markdown.php] To [/config/markdown.php]
Copied Directory [/vendor/laravel/sanctum/database/migrations] To [/database/migrations]
Copied File [/vendor/spatie/laravel-ignition/config/ignition.php] To [/config/ignition.php]
Copied File [/vendor/spatie/laravel-ignition/config/flare.php] To [/config/flare.php]
Copied Directory [/vendor/laravel/framework/src/Illuminate/Mail/resources/views] To [/resources/views/vendor/mail]
Copied Directory [/vendor/laravel/sail/runtimes] To [/docker]
Copied File [/vendor/laravel/sail/bin/sail] To [/sail]
Copied File [/vendor/laravel/tinker/config/tinker.php] To [/config/tinker.php]
Publishing complete.
ControllerとViewsファイルを編集
以下の構成とします。
├ app/
├ Http/
├ Controllers/
└ BlogController.php
├ resources/
├ views/
├ layouts/
└ app.blade.php
├ posts/
├ create.blade.php
├ article.blade.php
レイアウト用のapp.blade.php
head内に@stack(‘style’)、そして、bodyの閉じタグ直前に@stack(‘js’)を追記します。
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">
@stack('styles')
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100">
@include('layouts.navigation')
<!-- Page Heading -->
<header class="bg-white shadow">
<div class="px-4 py-6 mx-auto max-w-7xl sm:px-6 lg:px-8">
{{ $header }}
</div>
</header>
<!-- Page Content -->
<main>
{{ $slot }}
</main>
</div>
@stack('scripts')
</body>
</html>
投稿用のcreate.blade.phpにEasyMDEを追加
<x-app-layout>
@push('styles')
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">
@endpush
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Post Create') }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<form method="POST" action="{{ route('posts.store') }}">
@csrf
// ・・・(省略)・・・
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Description</span>
<textarea id="markdown-editor" class="block w-full mt-1 rounded-md" name="description" rows="3"></textarea>
</label>
@error('description')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
// ・・・(省略)・・・
</form>
</div>
</div>
</div>
</div>
@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
<script>
const easyMDE = new EasyMDE({
showIcons: ['strikethrough', 'code', 'table', 'redo', 'heading', 'undo', 'heading-bigger', 'heading-smaller', 'heading-1', 'heading-2', 'heading-3', 'clean-block', 'horizontal-rule'], element: document.getElementById('markdown-editor')});
</script>
@endpush
</x-app-layout>
これで投稿画面のエディタが変わりました。
id名は任意。エディタに表示するアイコンもお好みに。
表示部分をコントロールするBlogContoller.php
DBにはマークダウン記法のまま保存し、表示のときにマークダウン記法をHTMLにします。
<?php
namespace App\Http\Controllers;
// ・・・(省略)・・・
use GrahamCampbell\Markdown\Facades\Markdown;
class BlogController extends Controller
{
// ・・・(省略)・・・
/*
* 記事を表示
*/
public function show( $slug ) {
$article = Post::where('slug', $slug)->first();
// マークダウンをhtmlに
$article->body = Markdown::convert($article->body)->getContent();
return view('article', ['article' => $article]);
}
}
表示用のarticle.blade.php
<html>
<head>
// ・・・(省略)・・・
@stack('styles')
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
// ・・・(省略)・・・
<div class="prose lg:prose-xl">
{!! $article->body !!}
</div>
// ・・・(省略)・・・
@stack('scripts')
</body>
</html>
最後にbuildしておく
$ npm run build