Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

クソアプリ Advent Calendar 2018 の3日目です。

概要

Twitterでツイートしようと思った時にふと「Markdownで書きたい」と思ったことはないでしょうか? ここに訪れている方であれば誰もがあるはずです。僕も時々そう思っていたので今回TwitterでMarkdownを使えるようにしてみました。

とりあえず完成したもの

例えば下記のようなツイートを行うと…

Twitterでmarkdownを入力している画面

こんな感じで表示されます。

ツイートのmarkdownがきちんと変換されている画像

リンクや画像も、コードまでも思いのままです。さあ、皆さん思う存分Twitter上でMarkdownライフをエンジョイしてください!

…と、すみません、技術解説や使い方の説明が抜けていました。

技術解説

何はともあれツイート文に書かれているMarkdownを変換する必要がありますので、変換用ライブラリと、コードハイライトのライブラリを導入します。あとCSSも一緒に入れておきます。

yarn add marked highlight.js github-markdown-css

markedを初期化します。コード部分はhighlight.jsを使うように設定します。

const marked = require("marked");
import * as hljs from "highlight.js";
require("highlight.js/styles/atom-one-dark.css");
const renderer = new marked.Renderer();
renderer.code = (code, language) => {
  return (
    "<pre" +
    '><code class="hljs">' +
    hljs.highlightAuto(code).value +
    "</code></pre>"
  );
};
marked.setOptions({
  renderer: renderer
});

各ツイートはjs-tweet-text-containerというクラスの要素に含まれているため、これでループしていきます。

  document.querySelectorAll(".js-tweet-text-container").forEach(element => {
    let body = element.innerHTML;
    if (body.match(/<!--marked-->/)) {
      return;
    }
    const pStartRegex = /<p[^>]+>/;
    const pStart = body.match(pStartRegex);
    body = body.replace(pStartRegex, "");
    body = body.replace(/<\/p>/, "");

    body = stripUrlTags(body);
    body = stripDollarHashLinks(body);

    body = body.trim();
    const markdown = marked(body).replace(/<p> +/, pStart[0]);
    const divStart = pStart[0]
      .replace(/<p/, "<div")
      .replace(/class="/, 'class="markdown-body ');
    element.innerHTML = `<!--marked-->${divStart}${markdown}</div>`;
  }

各要素を監視して実行してるため、同じ要素で何度も実行してしまわないように<!--marked-->というコメントを入れてそれがあれば無視するようにしています。

あとpとかdivとかをあれこれしていますが、ツイート本文はpタグで囲まれているため、Markdownを変換後は色々なタグがそのpタグの子要素になってしまい正常ではなくなるため、divに変更してあります。ついでにCSSが反映されるようにmarkdown-bodyクラスを追加しています。

URLの自動リンクを削除

ツイートにURLを書くと自動的にリンクされてしまいます。そのためMarkdownのリンク最初からリンクされている状態になってしまうため正常に変換できません。そのため予め自動的に付与されたリンクを削除しておきます。

function stripUrlTags(body) {
  const regex = /\[([^\]]*)\]\((<a.+?twitter-timeline-link.+?>.+?<\/a>)[]*\)/;
  let match = body.match(regex);
  while (match) {
    const url = match[2]
      .replace(/<[^>]+>/g, "")
      .replace(/[]/g, "")
      .replace(/&nbsp;/g, "")
      .trim();
    console.log(url);
    const replaced = `[${match[1]}](${url})`;
    body = body.replace(match[0], replaced);
    match = body.match(regex);
  }
  return body;
}

ハッシュタグの自動リンクを削除

ハッシュタグと、あと$で始まるキャッシュタグも自動リンクされてしまいます。PHPの変数を含めたコードを書きたい場合などに支障が出るためこちらも予め削除しておきます。

function stripDollarHashLinks(body) {
  const lines = body.split(/\n/);
  const regex = /<a.+?twitter-(c|h)ashtag.+?>.+?<\/a>/g;
  let isCode = false;
  lines.forEach((line, i) => {
    if (line.substr(0, 3) == "```") {
      isCode = !isCode;
      return;
    }
    if (!isCode) {
      return;
    }

    const matches = line.match(regex);
    if (!matches) {
      return;
    }
    matches.forEach(match => {
      const replaced = match.replace(/<[^>]+>/g, "");
      body = body.replace(match, replaced);
    });
    lines[i] = line;
  });
  return body;
}

使い方

さて、次に使い方ですが、下記のChrome拡張をインストールするだけです。これでMarkdownライフがエンジョイできます。

Twitter Markdown

注意点

Chrome拡張なので当然インストールしているブラウザでしか変換されません。他の人が見るとこんな感じになっています…。

ツイートのmarkdownが変換されずそのまま表示されている様子

ということで全員がこのChrome拡張のインストールをお願いします!!! (あとMarkdown変換に対応したスマホ用のTwitterクライアントの開発もどなたかお願いします)

関連リンク

dala00
Qiitaのようだけどポエムでも何でも書けるサービスを運営しています。 https://crieit.net 個人開発もしてるWebエンジニアです。業務依頼、同業種の方からのコンタクトなどお気軽に。業務経験有:PHP, MySQL, Laravel, Vue.js, Go, RoR 趣味サービス:Flutter, React, Next.js, Nuxt.js, Phoenix等色々
https://crieit.net/users/dala00
admin-guild
「Webサービスの運営に必要なあらゆる知見」を共有できる場として作られた、運営者のためのコミュニティです。
https://admin-guild.slack.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした