Vueでマークダウンとシンタックスハイライトの実装

imatomix
2017年12月3日 13:52

ゴール

  • マークダウン記入をするとすぐにプレビューされる
  • マークダウンから変換されてできた内はシンタックスハイライトされてる
  • これらをvue上で行う

使用した js

  • マークダウン入力をhtmlに変換する

  • <code></code>内をシンタックスハイライトする

  • 上記処理の発生を間引くためのdebounce処理に。

スクリプト

debounce

  • 書いたらすぐプレビューと言っても、文字打つ度にプレビュー処理+ハイライト処理するのも非効率なので、入力中に処理は行わず、入力後一定時間入力がなかったら処理を走らせる。
  • そのために v-model は使わず @input で debounce のメソッドを走らせた。
  • debounce には lodash を使った。でもこのくらいならsetTimeoutで自分でやってもいい。
methods: { update: lodash.debounce(function (e) { this.body = e.target.value }, 500), }

marked.setOptions

  • ここに ハイライト処理を入れることができる
  • ただ入れるだけじゃなく、すこしおもてなしが必要
created: function(){ marked.setOptions({ breaks: true, langPrefix: 'language-', highlight: function (code, lang) { if ( lang && lang.match(":")) { // : 付きの lang から言語名だけ切り出す lang = lang.substring(0,lang.indexOf(":")); } if(lang in Prism.languages){ // 対応言語(自分で指定できる)内にlangの言語があれば return Prism.highlight(code, Prism.languages[lang]); }else{ // なにもない場合はそのままのcode return code } } })

全体

<template> <form> <textarea placeholder="# 本文" rows=24 @input="update"></textarea> <div v-html="compiledMarkdown"></div> </section> </form> </template> <script> import marked from 'marked' import Prism from 'prismjs' import lodash from 'lodash' export default{ data: function(){ return{ title: '', body: '', } }, computed: { compiledMarkdown: function () { return marked(this.body, { sanitize: true }) } }, created: function(){ marked.setOptions({ breaks: true, langPrefix: 'language-', highlight: function (code, lang) { if ( lang && lang.match(":")) { lang = lang.substring(0,lang.indexOf(":")); } if(lang in Prism.languages){ return Prism.highlight(code, Prism.languages[lang]); }else{ return code } } }) }, methods: { update: lodash.debounce(function (e) { this.body = e.target.value }, 500), } } </script>