2 flat logo on transparent 256
2018-08-06

Vue.jsでマークダウンに対応したメモ帳アプリを作成する|コピペで動くサンプルコード付き

Memo 20180806

Vue.jsはJavaScriptのフレームワークで、DOMの要素を簡単に操作したり、コンポネート機能で再利用可能なインスタンスを作成し、フロントエンドのデザインを容易に変更できたりします。

今回はVue.jsでマークダウン対応のメモ帳アプリを紹介します。

なおコピペで動くサンプルコード付きです。

サンプルコード

以下の内容をメモ帳などに貼り付け、html形式で保存して展開すると表示されます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Vueで始めるメモ帳アプリ</title>
    <!--CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
    <!--JS -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.4.0/marked.js"></script>
    <script>
        $(function () {
            var app = new Vue({
                el: '#markdown-text',
                data: {
                    input: '# ここに内容を記載してください',
                },
                methods: {
                    updateValue: function (eventObject) {
                        this.input = eventObject.target.value;
                    }
                },
                computed: {
                    convertMarkdownToHtml: function () {
                        return marked(this.input, {sanitize: true});
                    },

                    wordCount: function () {
                        MarkdownText = this.convertMarkdownToHtml.replace(/\r\n|\n|\r|( | )+|<("[^"]*"|'[^']*'|[^'">])*>/g, '');
                        return MarkdownText.length;
                    }
                }
            });
        });
    </script>
    <style>
        .flex {
            display: flex;
        }

        .memo {
            width: 500px;
            height: 800px;
            border: 1px solid;
        }

        .m-20 {
            margin-top: 20px;
        }

    </style>
</head>
<body>
    <div id='markdown-text' class="container">
        <div class="flex row">
            <div class="m-20">
                <textarea class="memo" v-bind:value='input' v-on:input='updateValue'></textarea>
            </div>
            <div>
                <div>マークダウン変換後文字数:{{wordCount}}</div>
                <div class="memo" v-html='convertMarkdownToHtml'></div>
            </div>
        </div>
    </div>
</body>
</html>

なお本コードは以下サイトを参考にしています。

参考サイト

セキュリティ的注意点

・一般公開されるサイトには公開しない

このメモ帳アプリはHTMLの要素をリアリタイムで変更させます。そのため悪意のある人間がVueやJavaScriptの脆弱性を突い て、不正攻撃を行うとアクセスするすべての人間に影響します。

例えば以下コードのsanitizeをtrueからfalseに変更し

 computed: {
                    convertMarkdownToHtml: function () {
                        return marked(this.input, {sanitize: true});
                    },

メモ帳に以下コードを貼り付けてください。

<button type="button" onclick="history.back()">戻る</button>

すると以下のようにメモ帳アプリでJavaScriptの機能を利用できるようになります。

XSS画像

マークダウンの機能はVue.jsの外部ライブラリを利用しており、 テキスト入力の際はsanitize: trueにすることによって JavaScriptを入力しても、動作させないようにしています。

しかし、最新の脆弱性を突き攻撃されると防御しきれませんので 本アプリケーションの様にユーザーが入力された内容をリアルタイムに表示する場合は、絶対に一般公開はせず会員向けサイトやAdmin権限を設定したアカウントのみ利用できるように設定をお願いします。

サンプルコード解説

el methodsの解説

var app = new Vue({
    el: '#markdown-text',
    data: {
        input: '# ここに内容を記載してください',
    },
   methods: {
       updateValue: function (eventObject) {
        this.input = eventObject.target.value;
    }
},

elはhtml要素の

<div id='markdown-text' class="container">

に紐づく要素になります。

htmlの id='markdown-text'で囲まれた部分がVue.jsとして認識されます。

inputはメモ帳で表示される初期値になります。

methodsはhtml要素の v-on:input='updateValue' でインプットされた場合にイベントを発火させ、テキスト入力された内容を 表示させます。

computedの解説

computed: {
    convertMarkdownToHtml: function () {
        return marked(this.input, {sanitize: true});
    },

    wordCount: function () {
        MarkdownText = this.convertMarkdownToHtml.replace(/\r\n|\n|\r|( | )+|<("[^"]*"|'[^']*'|[^'">])*>/g, '');
        return MarkdownText.length;
    }
},

computedは値が変更されたタイミングで処理を実行する 部分です。

convertMarkdownToHtmlで入力された内容を マークダウン化します。

wordCountはマークダウン化した文章の文字数をカウントします。

文字数カウントには、改行とスペースhtmlタグを除去してカウントします。

その他関連記事

Vue.jsとAnimate.cssで手軽にアニメーションを実現する|コピペで動くサンプル付き

jQuery記事一覧

Bootstrapでモーダルウインドウを表示する|コピペで動くサンプル付き

Bootstrapでモーダルウインドウをカスタマイズする|コピペで動くサンプル付き

Bootstrapで画像スライダーを実現する|コピペで動くサンプル付き

htmlの要素をFlexBoxで簡単に横並びにする|サンプル付き

前の記事
次の記事