92
54

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

明治大学Advent Calendar 2018

Day 9

Twitterでmarkdownをツイートするガチなchrome拡張作った

Last updated at Posted at 2018-12-08

追記情報

お前の二番煎じじゃね?

はい、そうですけど?

そうですけど、ガチなChrome拡張作ったから、とりあえず見て!!!!!

tmd-3.gif

ということで、明治大学advent calendarやっていきます。

Abstract

Twitterという素晴らしいSNSにマークダウンを画像として投稿できるようにする、ガチなChrome拡張を作った。

Introduction

皆さん、Twitterは使ってる????

僕は身体の一部って思っているレベルで使ってる。いや、もはや息を吸うレベルで使ってる。信じるか信じないはあなた次第。

Twitterは最高なんですけど、以下のような仕方がない問題があるよね。(多分、エンジニアとか理系な人たちが特に思っているんだろうな。)

  • 数式が書けない
  • コードが書けない
  • 280文字ぐらい制限

上記のような問題に対して、Twitterユーザーは以下のようなことをするよね。

  • 数式はtex記法か画像
  • コードはplainか画像

これ、正直どうにかしたい。

Related works

どうやら、解決策が幾つかあるそう。

1. TwitterでMarkdownを使えるようにした

Chrome拡張で、Twitterでmarkdownをレンダリングするやりかた。
Pros

  • markdownが使える
  • sytax highlightされる

Cons

  • Chrome拡張をインストールしているデバイスでのみmarkdownがレンダリングされる
  • Twitterのeditorでmarkdownを書く必要がある
  • 数式が使えない

2. Mathtodon

あの、一時期、流行ってた分散型Twitterであるマストドン。マストドンに数式をレンダリングする機能を追加したインスタンス。(使ったことないからよくわからん。)

Pros

  • 数式が書ける

Cons

  • Twitterじゃない

3. ritwee

WYSWYGエディターでrichなツイートできるサービス。画像化してツイートするやり方。

Pros

  • 画像としてツイートされるので、デバイス依存無し
  • syntax highlight
  • WYSWYG

Cons

  • Ritweeのサイトに行かないとダメで、めんどい
  • 数式が使えない
  • WYSWYGが好きじゃない(個人的な好みだけど、皆、markdown好きでしょ?)

My method

色々な解決策があるとはいえ、consの部分が痛いので、only prosな解決策を考えた。

Overview

Chrome拡張でmarkdownを画像にし、Twitter APIで画像をツイートする。

スクリーンショット 2018-12-09 6.38.29.png

Chrome拡張

どのウェブサイトを見ていても、クローム拡張のポップアップならアクセシビリティが良い。Twitterを拡張するにはもってこい。

md to html

markdown-itなり、markedなりのmd parserを使い、mdをhtmlにする。今回はmarkdown-itにした。

import markdownIt from "markdown-it";

const mdParser = markdownIt({
  html: true,
  xhtmlOut: true,
  breaks: true,
  langPrefix: "language-",
  linkify: true,
});

sytax highlight

syntax highlightする。今回はhighlihghtjsを使う。

import hljs from "highlightjs";
const mdParser = markdownIt({
  //...
  highlight: function(str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(lang, str).value;
      } catch (__) {}
    }

    return ""; // use external default escaping
  }
})

Checkbox

markdown-itのcheckbox記法をパースしてくれるをpluginがある。

import markdownCheckbox from "markdown-it-checkbox";
mdParser.use(markdownCheckbox);

Math formula

有名どころだとMathjaxがあるが、重いので使いたくない。今回は高速で有名なkatexを使う。面倒なので、markdown-itにkatex pluginを使う。

import markdownKatex from "markdown-it-katex";
mdParser.use(markdownKatex)

html to image

画像に変換することが大事。これでデバイス依存無しにマークダウンをレンダリングできるようになる。

今回は、html2canvasというOSSを使い、domをcanvasにし、canvasからpngにする。ここで注意が必要なのは、html to canvasではなく、dom to canvasであること。しかも、domもinnerHtmlとかはダメだったりして、工夫が必要。

まずは、htmlからdomを作る。

const parser = new DOMParser()
const wrapper = parser.parseFromString(html, "text/html");

wrapper.body以下のdomをブラウザでレンダリングさせる。

const nodes = wrapper.body.childNodes;
const markdownBody = document.createElement("div");
nodes.forEach(node => {
    markdownBody.append(node);
  });
document.body.appendChild(markdownBody);

すると、canvasに変換することができるようになる。

html2canvas(markdownBody)
  .then(canvas => {
    //...
  });

そして、画像にする。

html2canvas(markdownBody)
  .then(canvas => {
    canvas.toBlob(blob => {
      //...
    });
  });

ここで、注意なのが、canvasで別オリジンの画像をレンダリングできないこと。なので、Access-Control-Allow-Originヘッダーを付与するためのproxy層が必要になる。

どうやら、html2canvasがCORS用のexpress middlewareを提供してくれているのでそれを使う。

server.js
const express = require("express");
const app = express();
const proxy = require("html2canvas-proxy");
app.use("/corsProxy", proxy());

そして、html2canvasのオプションを設定する。

html2canvas(markdownBody, {
    proxy: `${config.apiUrl}/corsProxy`,
    useCORS: true
  })

これで、mdを完璧にレンダリングできるようになる。

download (2).png

Twitter api

nodejsのtwitterモジュールを使う。まずは画像をアップロードしてから、ツイートする。

server.js
const twitterClient = new Twitter({
    consumer_key: config.consumerKey,
    consumer_secret: config.consumerSecret,
    access_token_key: user.access_token,
    access_token_secret: user.access_token_secret
  });

  twitterClient.post("media/upload", { media: image }, (err, media) => {
    if (err) return

    const status = {
      status: "something",
      media_ids: media.media_id_string // Pass the media id string
    };

    twitterClient.post("statuses/update", status, function(err, tweet) {
      if (!err) console.log('done')
    });
  });

あとは、reactなりvueなりを使ってホゲホゲして最高の拡張を作って、終わり。

My work

Chrome拡張を作った。名前は TwitterMD。Github

スクリーンショット 2018-12-09 7.34.51.png

現在、chrome web storeに申請中。リジェクトされたった👿

We may remove your item if it has an unclear description field, or missing icons or screenshots, and appears to be suspicious

description書くの忘れてた。。。。

とりあえず、Chrome拡張はGithubに置いておきます。申請通ったら追記します。

数日で開発してソースコードが汚いのと、API KEYを直書きしてしまっているので、ソースコードは載せてません。いつか、綺麗にして公開します。create-react-app使わなければよかった。。。

追記: 12/10 - Published Chrome Extension

  • chrome web storeにrejectされまくっていて辛い👿
  • 機能追加
    • markdownのcssをカスタマイズ可能に
    • ツイート時の本文を設定可能に
    • Front Matter
スクリーンショット 2018-12-10 21.01.17.png スクリーンショット 2018-12-10 21.49.46.png

追記: 12/14

  • chrome web extension ようやく公開できました。

chrome web store

おわりに

僕/私も機能追加したい!なんて方が居たら連絡ください!

連絡はここ(twitter)までお願いします。

92
54
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
92
54

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?