Ikeda's Blog

JavaScriptで、MarkdownをHTMLに変換する

やること

テキストエリアに入力したMarkdown形式の文字列を、HTMLに変換する。

使用するライブラリ

markedjs

使い方

1. ライブラリを読み込む

CDNにJSファイルを置いてくださっているので、利用させて頂く。

<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>

2. 変換

変換自体は、marked.parse()でできてしまう。
後は、必要に応じたオプションを設定するくらい。

const before = '# 変換前';
const after = marked.parse(before);
console.log(after); // <h1>変換前</h1>

使用例

▼ Markdown入力欄<br />
<textarea id="demo_markdown_before"></textarea><br />
<input type="button" id="demo_markdown_parse" value="Markdown変換" /><br />
▼ 変換後<br />
<textarea id="demo_markdown_after"></textarea>
                    
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
    $(document)
        .on('click', '#demo_markdown_parse', function(){
            // オプション:文中の改行をbrタグに変換する
            marked.setOptions({breaks : true});

            // テキストエリアに入力されたMarkdown形式の内容をHTMLに変換
            const after = marked.parse($('#demo_markdown_before').val());

            // 変換したHTMLを、変換後テキストエリアに出力
            $('#demo_markdown_after').val(after);
        })
    ;
</script>

WEB上のソースコードに、シンタックスハイライトを導入(highlight.js)

目的

読みやすさ向上のため、記事内に書くプログラムコード等に、シンタックスハイライトをつけたい。

導入するライブラリ

highlight.jsを導入します。

ダウンロード

TOPページのGet version XX.XX.XXをクリックします。

移動先のページで、

  • CDNを利用する
  • ダウンロードする
  • npmからインストールする

についての説明があります。
今回は、ダウンロードで利用しますので、「Custom package」のところまでスクロールします。

ここで、必要な言語を含めた分でダウンロードできます。
必要最小限に絞ることで、容量を減らすことにも繋がります。
(追加する時は、選択を増やして改めてダウンロードすれば良いので)

チェックできたら、ダウンロードボタンを押して、zipファイルを取得。
解凍後、任意の場所に設置します。

例:Laravelを利用して作った当ブログの場合

+ public
  + js
    + highlight
      + styles
        + atom-one-dark-reasonable.min.css
      + highlight.min.js

テーマの選択

スタイルを選択します。
デモページがあるので、確認して使用するテーマを決めます。

HTML側の対応

HTML側で、jsとテーマCSSを読み込みます。
以下は、このブログにて実装した際の記述です。

    {{-- コードハイライト --}}
    <link rel="stylesheet" href="{{ asset('/js/highlight/styles/atom-one-dark-reasonable.min.css') }}">
    <script type="text/javascript" src="{{ asset('/js/highlight/highlight.min.js') }}" charset="UTF-8"></script>
    <script>hljs.highlightAll();</script>

Laravelでブログサイトを作る 19. 管理画面・記事編集の時に、画像をアップロードできるように(TinyMCE)

はじめに

前回にて実装したTinyMCEの機能を利用して、記事の編集中に画像をアップロードする仕組みを用意します。

サーバー側での対応

Laravelのディレクトリ構造から考えまして、画像は、storageディレクトリ(storage/app/public)に保存するべきと考えました。
しかし、このディレクトリを参照することはできません。
そこで、以下のコマンドを実行しておきます。

$ php artisan storage:link

これで、public/storageにシンボリックリンクが作成されますので、storage/***.jpgのようにして画像を表示できます。

$ ls -l public/
(省略) storage -> /home/vagrant/blog/storage/app/public

TinyMCEでアップロードできるようにする

resources/views/admin/articleEdit.blade.php
前回実装したTinyMCSの記述を修正します。

<script src="{{ asset('/js/tinymce/tinymce.min.js') }}"></script>
<script>
    tinymce.init({
        selector:'textarea',
        language: "ja", // 日本語対応(https://qiita.com/nissuk/items/e31bdfa858d6c5c018c2)

        // ▼画像アップロード対応(https://www.tiny.cloud/docs/configure/file-image-upload/)
        plugins: 'image code',
        toolbar: 'undo redo | link image | code',
        image_title: true, // イメージダイアログのタイトルフィールドを有効にする
        automatic_uploads: true, // ブロブやデータのURIで表現された画像の自動アップロードを可能にする
        images_upload_url: '{{ route('admin_article_image_upload') }}?_token={{ csrf_token() }}',
        file_picker_types: 'image',
        relative_urls : false,  // 画像やリンクのパスが相対パスに変換されるのを防ぐ
        convert_urls: false,

        /* カスタムイメージピッカー */
        file_picker_callback: function (cb, value, meta) {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.setAttribute('accept', 'image/*');

            input.onchange = function () {
                var file = this.files[0];

                var reader = new FileReader();
                reader.onload = function () {
                    var id = 'blobid' + (new Date()).getTime();
                    var blobCache =  tinymce.activeEditor.editorUpload.blobCache;
                    var base64 = reader.result.split(',')[1];
                    var blobInfo = blobCache.create(id, file, base64);
                    blobCache.add(blobInfo);
                    cb(blobInfo.blobUri(), { title: file.name });
                };
                reader.readAsDataURL(file);
            };

            input.click();
        },
        content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
    });
</script>

アップロードされた画像を保存する

ルーティング

routes/web.php
アップロードするルーティングを追加します。

Route::group(['prefix' => 'admin', 'middleware' => 'auth', 'namespace' => 'App\\Http\\Controllers\\'], function() {
    // ...省略...

    Route::post('articleImageUpload', 'ArticleController@image')->name('admin_article_image_upload'); // 画像アップロード

    // ...省略...
});

Controller

app/Http/Controllers/ArticleController.php

アップロードされた画像を保存し、パスを返却します。

/**
 * 画像アップロード
 *
 * @param Request $request
 * @return false|string
 */
public function image(Request $request) {
    // ファイルの保存(戻り値はファイル名)
    $imgpath = request()->file('file')->store('', 'public');

    // 画像パスを返却
    return json_encode(['location' => '/storage/' . $imgpath]);
}

参考文献

https://www.tiny.cloud/docs/configure/file-image-upload/
https://qiita.com/kawa_matsu/items/50306befb7a5f879e38e
https://readouble.com/laravel/7.x/ja/structure.html

Laravelでブログサイトを作る 18. 管理画面・記事編集の際に入力補助を(TinyMCE)

はじめに

記事を編集する際に、HTMLの入力補助を行えるようにします。
様々なライブラリが存在しますが、TinyMCEを使用します。
画像のアップロード機能を組み込むことができるので(次回解説予定)、という理由で

選定しました。

導入方法

  1. JSファイルをダウンロードし、public/jsに配置する
    • CDNを使うと、日本語化で手こずる懸念と、バージョンアップに引きずられて問題が発生する可能性があるため、ファイルをダウンロードします。
  2. テンプレートファイルに、JSの読み込みと初期化構文を記述する

1. JSファイルのダウンロード

ダウンロードは、コチラから可能です。
ページ中程にある「Download TinyMCE Community」から本体を、「Download Language Pack」から日本語パックをダウンロードし、解凍します。

本体は、public/jsに配置します。
その後、langディレクトリに日本語パックのja.jsを移動します。
最終的には、以下のような形です。

public/
└ js/
  └ tinymce/
    ├ lang
    |  └ ja.js ←日本語パックから移動
    └ その他、jquery.tinymce.min.js など

テンプレート

resources/views/admin/articleEdit.blade.php
JSファイルの読み込みと、初期化についての記述を追加するだけで、便利なTinyMCEが使えるようになります。
日本語化せずにCDNを使う場合は、前述のダウンロード云々もスキップできるので、非常に簡単です。


@section('adminMain')
    {{-- 省略 --}}

    <h3>記事本文</h3>
    <textarea name="body">{{ $articleData->body ?? '' }}</textarea>

    {{-- 省略 --}}
    
    <script src="{{ asset('/js/tinymce/tinymce.min.js') }}"></script>
    <script>
        tinymce.init({
            selector:'textarea',
            language: "ja"
        });
    </script>
@endsection

参考文献

TinyMCEを設置する
https://qiita.com/nissuk/items/e31bdfa858d6c5c018c2