Redmineのtextile記法で、コードハイライトは<pre><code class="java"></code></pre>
のような書き方をするのですが、これを入力するのが面倒になってきたので、Greasemonkeyを使ってテキストエリアで入力補完を行ってみました。
なお、Redmine 3.3 からは、ツールバーにコードハイライト用のボタンが追加されていますので、それを使うことによっても手間は軽減できるかと思います。
実装方法
テキストエリアでの入力補完は、カーソル位置を取るのが面倒なため、他のライブラリを利用します。
いくつかよさそうなものがありましたが、手軽そうなものということで、At.jsを今回は利用しました。
Greasemonkeyの@require
で外部JavaScriptを読み込めるので、cdnjsにあるAt.jsと、At.jsが依存しているCaret.jsというライブラリを読み込むようにしました。At.jsはjQueryに依存していますが、Redmineの各画面でも読み込んでいるので、指定しなくて大丈夫です。
- https://cdnjs.cloudflare.com/ajax/libs/at.js/1.5.2/js/jquery.atwho.min.js
- https://cdnjs.cloudflare.com/ajax/libs/Caret.js/0.3.1/jquery.caret.min.js
At.js用のスタイルは、直接styleタグとしてヘッダに追加しました。
後は対象のテキストエリアを指定して、入力補完の設定をしていくだけです。
At.jsでは、atwho
という関数に対して、必要な情報を指定することよって、補完が行われるようになります。
とてもシンプルなので、迷うことはありませんでした。
$('.atwho-inputor').atwho({ at: "@", data: ["one", "two", "three"], }).atwho({ at: ":", data: ["+1", "-1", "smile"] });
動作イメージ
スクリプト
ということで出来上がったスクリプトは、下記のようになります。
// ==UserScript== // @name Redmine wiki textcomplete // @namespace com.enjoyxstudy.redmine.wiki.textcomplete // @version 1 // @grant none // @require https://cdnjs.cloudflare.com/ajax/libs/at.js/1.5.2/js/jquery.atwho.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/Caret.js/0.3.1/jquery.caret.min.js // ==/UserScript== (function($) { $('textarea.wiki-edit').atwho({ at: '<', data: [ {name: 'java', content: '<pre><code class="java">\n</code></pre>'}, {name: 'sql', content: '<pre><code class="sql">\n</code></pre>'}], insertTpl: '${content}', suffix: '' }).atwho({ at: '{', data: [ {name: 'collapse', content: '{{collapse(詳細を表示...)\n}}'}], insertTpl: '${content}', suffix: '' }).atwho({ at: 'a', data: [ {name: 'attachment', content: 'attachment:'}], insertTpl: '${content}', suffix: '' }).atwho({ at: 'c', data: [ {name: 'commit', content: 'commit:'}], insertTpl: '${content}', suffix: '' }); $('head').append( `<style> .atwho-view { position:absolute; top: 0; left: 0; display: none; margin-top: 18px; background: white; color: black; border: 1px solid #DDD; border-radius: 3px; box-shadow: 0 0 5px rgba(0,0,0,0.1); min-width: 120px; z-index: 11110 !important; } .atwho-view .atwho-header { padding: 5px; margin: 5px; cursor: pointer; border-bottom: solid 1px #eaeff1; color: #6f8092; font-size: 11px; font-weight: bold; } .atwho-view .atwho-header .small { color: #6f8092; float: right; padding-top: 2px; margin-right: -5px; font-size: 12px; font-weight: normal; } .atwho-view .atwho-header:hover { cursor: default; } .atwho-view .cur { background: #3366FF; color: white; } .atwho-view .cur small { color: white; } .atwho-view strong { color: #3366FF; } .atwho-view .cur strong { color: white; font:bold; } .atwho-view ul { /* width: 100px; */ list-style:none; padding:0; margin:auto; max-height: 200px; overflow-y: auto; } .atwho-view ul li { display: block; padding: 5px 10px; border-bottom: 1px solid #DDD; cursor: pointer; /* border-top: 1px solid #C8C8C8; */ } .atwho-view small { font-size: smaller; color: #777; font-weight: normal; } </style>` ); })(jQuery);
おわりに
いろいろ候補を追加して、自分好みのものに変えていこうと思っています。