ソースコード共有サービス emoscode (エモすこ)

![emoscode201911203-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59265/74471e3f-2fe5-03d9-a3a5-3a5dd9166733.gif)
先日 [emoscode(エモすこ)](https://emoscode.net/) というWebサービスをリリースしました。
[github](https://github.com/) の [gist](https://gist.github.com/discover) や [pastebin](https://pastebin.com/archive) のようにソースコードを投稿するサイトはすでにたくさんありますが、このサービスの特徴はソースコードの任意の場所にコメントをつけることができます。もう少し詳しく説明すると、テキスト選択をした場所を指す矢印のついたコメントを投稿することができます。

なんのこっちゃようわからん、という方は[サンプルページ](https://emoscode.net/displayCode/6fd3ab58-eb3a-498d-9e33-8de4ab0b100e)をご覧下さい。(コメントも自由に付けてみて下さい)

投稿されたソースコードにエモい箇所を見つけたら、そこにコメントをつけて「すこ」を伝えましょう。「エモ」いコードに「すこ」を伝えるサービス、それが「エモすこ」です。(ドヤァァァ)

# なぜ作ろうと思ったか
[gist](https://gist.github.com/discover) や [pastebin](https://pastebin.com/archive) にもコメントを投稿することはできますが、ソースコードの後にコメントが追加されていきます。
また、Qiitaで[記事](https://qiita.com/tomotaco/items/9e917de89a68430b006c)を書くときによくソースコードを掲載しますが、ソースコードの「ここ」と特定の場所を指してコメントを付けたいと思うことが何度もありました。もちろんコメント文を使って書くことはできますが、ソースコード自体に手を入れずに見やすい形…ということで矢印で指すような漠然としたイメージがありました。
その後、W3c の [Canvas](https://www.w3.org/TR/2dcontext2/) のデフォルト値が透明ということを知ったことから実現への目途が立ち、なんやかやあって作ろうと思い立った…という次第です。

# 何をやっているか
HTML の構造は以下の通りです。 

```display.html
<pre>
    <code class="python hljs" id="code">
        <span class="hljs-keyword"></span>
        <mark id="marker-cd36d740-c450-44bf-ba7f-2909d8b8a91d">
            <span class="hljs-keyword">import</span>
             argparse
        </mark>
        <svg xmlns="http://www.w3.org/2000/svg" class="arrow-area" style="width: 502px; height: 1641px; display: block;">
            <polygon id="arrow-4d365e78-b5a3-47a2-904c-eecf81dd7876" stroke="#CEE4FF" stroke-width="2" fill="#509FFF" points="564.9786364864356 216.1576339629191 118.7073207756119 41.93108801717698 116.88895726204744 46.58872198009608 101.8951484375 30 124.16241131630532 27.958186128419687 122.34404780274086 32.61582009133878 568.6153635135645 206.8423660370809"></polygon>
        </svg>
        <div class="arrow-caption non-editable" id="caption-4d365e78-b5a3-47a2-904c-eecf81dd7876" style="left: 275px; top: 119.5px;">
            <div class="caption-content">
                <div class="caption-icon">
                    <img src="https://emoscode.s3-ap-northeast-1.amazonaws.com/user/profile-image-01b778d1-74c2-5212-9371-114249b70c55.png" alt="ともたこ">
                    <div class="caption-author-name" data-toggle="tooltip" data-original-title="" title="ともたこ">ともたこ</div>
                </div>
                <div class="caption-text">コメント</div>
            </div>
        </div>
    </code>
</pre>
```
`<pre><code>` ～ `</code></pre>` のタグ内にソースコードを流し込み、[highlight.js](https://highlightjs.org/) で色付けを行います。コメントをつけたい箇所を `<mark>` タグで囲み、ソースコードと同じ階層に `position: absolute;` のスタイルで矢印表示用の `<svg>` タグとコメント用の `<div>` を並べておきます。`<svg>` のサイズは `<code>` タグと同期するように [jQuery](https://jquery.com/) で書いておきます。これでソースコード上に図形とコメントを自由に配置することができるようになりました。`<mark>` タグとコメント用の `<div>` タグの位置・サイズは [jQuery](https://jquery.com/) で取得できますので、それぞれの中心座標を結ぶ線分から矢印の各頂点の座標を計算し、`<svg>` 内の `<polygon>` タグで矢印を表示します。(細かい事を書くと `<mark>` タグの矩形領域でクリッピングもしています)

# 使用しているフロントエンド技術
当初 Javascript と [jQuery](https://jquery.com/) で開発を進めていましたが、規模が大きくなる前に ES Modules を導入したかったので、ビルドツールの [Webpack4](https://webpack.js.org/) を導入、ついでに [Typescript](https://www.typescriptlang.org/) に移行しました。型安全のある暮らし最高ですね!
CSSフレームワークには [Bootstrap4](https://getbootstrap.com/) 、ソースコードの色付けに前出の [highlight.js](https://highlightjs.org/) 、DOM 操作と ajax に [jQuery](https://jquery.com/) を使用しています。
[jQuery](https://jquery.com/) を使っている旨を人に話すと、ほぼ決まって「[Vue.js](https://jp.vuejs.org/index.html) 使わないんですか?」という提案を頂いてしまうのですが、先日ようやく1 つだけインクリメンタルサーチ付き select を実現する [vue-select](https://vue-select.org/) を組込むことができました。[Vue.js](https://jp.vuejs.org/index.html) を使うにはフロントエンド全体を SPA にしないといけない…という思い込みがあったのですが、コンポーネント単位で [vue-select](https://vue-select.org/) に置き換えしていく…というやりかたでも(正しい使い方かどうかはさておき)全く支障ありませんでした。コンポーネント1つだけでもかなり使いやすいので、今後は設定UIなどからちょっとずつこちらに移行していきたい…と考えています。

# 使用しているバックエンド技術
バックエンドの実装には [Python](https://www.python.org/) を使用しました。ORマッパーに [SQLAlchemy](https://www.sqlalchemy.org/) 、Web フレームワークに [Bottle](https://bottlepy.org/docs/dev/) 、テンプレートエンジンに [Jinja2](https://www.palletsprojects.com/p/jinja/) を使っています。
メジャーな [django](https://www.djangoproject.com/) や [Flask](https://palletsprojects.com/p/flask/) ではなく [Bottle](https://bottlepy.org/docs/dev/) を採用したのは以前の業務で使っていた…という歴史的な経緯によるものですが、せめて [Flask](https://palletsprojects.com/p/flask/)にしておけば [Python Social Auth](https://github.com/python-social-auth) が使うことができて SNS 認証で楽ができたのに…と思います。[Bottle](https://bottlepy.org/docs/dev/) では自前で書く羽目になってえらい時間がかかりました。
また、[Bottle](https://bottlepy.org/docs/dev/) 単体ではセッションを扱うことができないため、セッション(とDBキャッシュ)に [bottle-beaker](https://pypi.org/project/bottle-beaker/) を使いました。

# 使用しているサーバー・外部サービス
Webホスティングに [Heroku](https://jp.heroku.com/) Hobby (USD 7ドル/月)、データベースに Heroku PostgreSQL hobby-basic (USD 9ドル/月)、DBキャッシュとセッション情報の保持に Heroku Redis (無料)を使っています。
ストレージとして [Amazon S3](https://aws.amazon.com/jp/s3/) (今のところ USD 0.00ドル/月) を使用していますが、これはSNSアイコン画像とコードのOGP 画像の保管用です。また、DNS・コンテンツキャッシュに Cloudflare (無料) を使用しています。
何もしなくても毎月USD 16ドルが溶けていくだけを見続けるのはちょっとしんどいので、ユーザー数増加の目途が立たなければ DB サーバを無料プランの hobby-dev (1万件制限あり)にスペックダウンを考えています。

# 今後の展望について
実は、リリースしてからずっと投稿したコードを削除することができなかったため、投稿への心理的な障壁が高いままだったと思われます。昨日(12/3)の更新でようやく削除はできるようになりましたが、編集機能も早急に追加してさらに気軽に投稿してもらえるように改善して行きます。
また、コードレビューのような用途にも使えるかも…と想定しているのですが、公開範囲が完全オープンなままだとやりづらいのかも知れません。グループのような概念を導入、限られたメンバー間だけで閲覧可能、のようなクローズドな場を用意する必要があるのかな…とぼんやり考えています。
あと、明日(12/5)に [クソアプリ2アドベントカレンダー](https://qiita.com/advent-calendar/2019/kuso-app2) 担当日に合わせて、せわしない新機能を公開予定です。(が果たして間に合うのかどうか…?)